#include <sys/cdefs.h>
#include <dev/isci/scil/sati.h>
#include <dev/isci/scil/sati_callbacks.h>
#include <dev/isci/scil/sati_util.h>
#include <dev/isci/scil/sati_report_luns.h>
#include <dev/isci/scil/sati_inquiry.h>
#include <dev/isci/scil/sati_mode_sense_6.h>
#include <dev/isci/scil/sati_mode_sense_10.h>
#include <dev/isci/scil/sati_mode_select.h>
#include <dev/isci/scil/sati_test_unit_ready.h>
#include <dev/isci/scil/sati_read_capacity.h>
#include <dev/isci/scil/sati_read.h>
#include <dev/isci/scil/sati_write.h>
#include <dev/isci/scil/sati_verify.h>
#include <dev/isci/scil/sati_synchronize_cache.h>
#include <dev/isci/scil/sati_lun_reset.h>
#include <dev/isci/scil/sati_start_stop_unit.h>
#include <dev/isci/scil/sati_request_sense.h>
#include <dev/isci/scil/sati_write_long.h>
#include <dev/isci/scil/sati_reassign_blocks.h>
#include <dev/isci/scil/sati_log_sense.h>
#include <dev/isci/scil/sati_abort_task_set.h>
#include <dev/isci/scil/sati_unmap.h>
#include <dev/isci/scil/sati_passthrough.h>
#include <dev/isci/scil/sati_write_and_verify.h>
#include <dev/isci/scil/sati_read_buffer.h>
#include <dev/isci/scil/sati_write_buffer.h>
#include <dev/isci/scil/intel_ata.h>
#include <dev/isci/scil/intel_scsi.h>
#include <dev/isci/scil/intel_sat.h>
void sati_translate_error(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * scsi_io,
U8 error
)
{
if (error & ATA_ERROR_REG_NO_MEDIA_BIT)
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_NOT_READY,
SCSI_ASC_MEDIUM_NOT_PRESENT,
SCSI_ASCQ_MEDIUM_NOT_PRESENT
);
}
else if (error & ATA_ERROR_REG_MEDIA_CHANGE_BIT)
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_UNIT_ATTENTION,
SCSI_ASC_NOT_READY_TO_READY_CHANGE,
SCSI_ASCQ_NOT_READY_TO_READY_CHANGE
);
}
else if (error & ATA_ERROR_REG_MEDIA_CHANGE_REQUEST_BIT)
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_UNIT_ATTENTION,
SCSI_ASC_MEDIUM_REMOVAL_REQUEST,
SCSI_ASCQ_MEDIUM_REMOVAL_REQUEST
);
}
else if (error & ATA_ERROR_REG_ID_NOT_FOUND_BIT)
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_ILLEGAL_REQUEST,
SCSI_ASC_LBA_OUT_OF_RANGE,
SCSI_ASCQ_LBA_OUT_OF_RANGE
);
}
else if (error & ATA_ERROR_REG_UNCORRECTABLE_BIT)
{
sequence->state = SATI_SEQUENCE_STATE_READ_ERROR;
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_MEDIUM_ERROR,
SCSI_ASC_UNRECOVERED_READ_ERROR,
SCSI_ASCQ_UNRECOVERED_READ_ERROR
);
}
else if ( (sequence->data_direction == SATI_DATA_DIRECTION_OUT)
&& (error & ATA_ERROR_REG_WRITE_PROTECTED_BIT) )
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_DATA_PROTECT,
SCSI_ASC_WRITE_PROTECTED,
SCSI_ASCQ_WRITE_PROTECTED
);
}
else if (error & ATA_ERROR_REG_ICRC_BIT)
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_ABORTED_COMMAND,
SCSI_ASC_IU_CRC_ERROR_DETECTED,
SCSI_ASCQ_IU_CRC_ERROR_DETECTED
);
}
else
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_ABORTED_COMMAND,
SCSI_ASC_NO_ADDITIONAL_SENSE,
SCSI_ASCQ_NO_ADDITIONAL_SENSE
);
}
}
static
void sati_translate_data(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * ata_input_data,
void * scsi_io
)
{
sati_device_update_capabilities(
sequence->device, (ATA_IDENTIFY_DEVICE_DATA_T*) ata_input_data
);
switch (sequence->type)
{
#if !defined(DISABLE_SATI_INQUIRY)
case SATI_SEQUENCE_INQUIRY_STANDARD:
sati_inquiry_standard_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER:
sati_inquiry_serial_number_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_INQUIRY_DEVICE_ID:
sati_inquiry_device_id_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE:
sati_inquiry_block_device_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_INQUIRY_ATA_INFORMATION:
sati_inquiry_ata_information_translate_data(
sequence, ata_input_data, scsi_io
);
break;
#endif
#if !defined(DISABLE_SATI_READ_CAPACITY)
case SATI_SEQUENCE_READ_CAPACITY_10:
sati_read_capacity_10_translate_data(sequence, ata_input_data, scsi_io);
break;
case SATI_SEQUENCE_READ_CAPACITY_16:
sati_read_capacity_16_translate_data(sequence, ata_input_data, scsi_io);
break;
#endif
#if !defined(DISABLE_SATI_MODE_SENSE)
case SATI_SEQUENCE_MODE_SENSE_6_CACHING:
sati_mode_sense_6_caching_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL:
sati_mode_sense_6_informational_excp_control_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR:
sati_mode_sense_6_read_write_error_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT:
sati_mode_sense_6_disconnect_reconnect_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_6_CONTROL:
sati_mode_sense_6_control_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES:
sati_mode_sense_6_all_pages_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION:
sati_mode_sense_6_power_condition_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION:
sati_mode_sense_10_power_condition_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_10_CACHING:
sati_mode_sense_10_caching_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL:
sati_mode_sense_10_informational_excp_control_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR:
sati_mode_sense_10_read_write_error_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT:
sati_mode_sense_10_disconnect_reconnect_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_10_CONTROL:
sati_mode_sense_10_control_translate_data(
sequence, ata_input_data, scsi_io
);
break;
case SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES:
sati_mode_sense_10_all_pages_translate_data(
sequence, ata_input_data, scsi_io
);
break;
#endif
default:
break;
}
}
SATI_STATUS sati_translate_command(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
SATI_DEVICE_T * sati_device,
void * scsi_io,
void * ata_io
)
{
SATI_STATUS status = SATI_FAILURE;
U8 * cdb = sati_cb_get_cdb_address(scsi_io);
sequence->is_sense_response_set = FALSE;
sequence->is_translate_response_required = FALSE;
sequence->device = sati_device;
if (sati_cb_get_lun(scsi_io) != 0)
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_ILLEGAL_REQUEST,
SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
0
);
return SATI_FAILURE_CHECK_RESPONSE_DATA;
}
if ( (sati_get_cdb_byte(cdb, sati_cb_get_cdb_length(scsi_io) - 1)
& SCSI_CONTROL_BYTE_NACA_BIT_ENABLE))
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_ILLEGAL_REQUEST,
SCSI_ASC_INVALID_FIELD_IN_CDB,
SCSI_ASCQ_INVALID_FIELD_IN_CDB
);
return SATI_FAILURE_CHECK_RESPONSE_DATA;
}
if (sati_device->state == SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED)
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_HARDWARE_ERROR,
SCSI_ASC_INTERNAL_TARGET_FAILURE,
SCSI_ASCQ_INTERNAL_TARGET_FAILURE
);
return SATI_FAILURE_CHECK_RESPONSE_DATA;
}
if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
{
sequence->command_specific_data.scratch = 0;
sequence->number_data_bytes_set = 0;
}
#ifdef SATI_TRANSPORT_SUPPORTS_SATA
{
U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
sati_set_sata_command_flag(register_fis);
sati_set_sata_fis_type(register_fis, SATA_FIS_TYPE_REGH2D);
}
#endif
switch (sati_get_cdb_byte(cdb, 0))
{
#if !defined(DISABLE_SATI_REPORT_LUNS)
case SCSI_REPORT_LUNS:
status = sati_report_luns_translate_command(
sequence, scsi_io, ata_io
);
break;
#endif
#if !defined(DISABLE_SATI_INQUIRY)
case SCSI_INQUIRY:
status = sati_inquiry_translate_command(
sequence, scsi_io, ata_io
);
break;
#endif
#if !defined(DISABLE_SATI_MODE_SENSE)
case SCSI_MODE_SENSE_6:
status = sati_mode_sense_6_translate_command(
sequence, scsi_io, ata_io
);
break;
case SCSI_MODE_SENSE_10:
status = sati_mode_sense_10_translate_command(
sequence, scsi_io, ata_io
);
break;
#endif
#if !defined(DISABLE_SATI_MODE_SELECT)
case SCSI_MODE_SELECT_6:
status = sati_mode_select_6_translate_command(
sequence, scsi_io, ata_io
);
break;
case SCSI_MODE_SELECT_10:
status = sati_mode_select_10_translate_command(
sequence, scsi_io, ata_io
);
break;
#endif
#if !defined(DISABLE_SATI_TEST_UNIT_READY)
case SCSI_TEST_UNIT_READY:
status = sati_test_unit_ready_translate_command(
sequence, scsi_io, ata_io
);
break;
#endif
#if !defined(DISABLE_SATI_READ_CAPACITY)
case SCSI_READ_CAPACITY_10:
status = sati_read_capacity_10_translate_command(
sequence, scsi_io, ata_io
);
break;
case SCSI_SERVICE_ACTION_IN_16:
if ( (sati_get_cdb_byte(cdb, 1) & SCSI_SERVICE_ACTION_MASK)
== SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16)
status = sati_read_capacity_16_translate_command(
sequence, scsi_io, ata_io
);
else
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
break;
#endif
#if !defined(DISABLE_SATI_REQUEST_SENSE)
case SCSI_REQUEST_SENSE:
status = sati_request_sense_translate_command(
sequence, scsi_io, ata_io
);
break;
#endif
case SCSI_READ_6:
status = sati_read_6_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_READ_10:
status = sati_read_10_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_READ_12:
status = sati_read_12_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_READ_16:
status = sati_read_16_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_WRITE_6:
status = sati_write_6_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_WRITE_10:
status = sati_write_10_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_WRITE_12:
status = sati_write_12_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_WRITE_16:
status = sati_write_16_translate_command(sequence, scsi_io, ata_io);
break;
#if !defined(DISABLE_SATI_VERIFY)
case SCSI_VERIFY_10:
status = sati_verify_10_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_VERIFY_12:
status = sati_verify_12_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_VERIFY_16:
status = sati_verify_16_translate_command(sequence, scsi_io, ata_io);
break;
#endif
#if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \
&& !defined(DISABLE_SATI_VERIFY) \
&& !defined(DISABLE_SATI_WRITE)
case SCSI_WRITE_AND_VERIFY_10:
status = sati_write_and_verify_10_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_WRITE_AND_VERIFY_12:
status = sati_write_and_verify_12_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_WRITE_AND_VERIFY_16:
status = sati_write_and_verify_16_translate_command(sequence, scsi_io, ata_io);
break;
#endif
#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
case SCSI_REASSIGN_BLOCKS:
status = sati_reassign_blocks_translate_command(sequence, scsi_io, ata_io);
break;
#endif
#if !defined(DISABLE_SATI_SYNCHRONIZE_CACHE)
case SCSI_SYNCHRONIZE_CACHE_10:
case SCSI_SYNCHRONIZE_CACHE_16:
status = sati_synchronize_cache_translate_command(sequence, scsi_io, ata_io);
break;
#endif
#if !defined(DISABLE_SATI_START_STOP_UNIT)
case SCSI_START_STOP_UNIT:
status = sati_start_stop_unit_translate_command(
sequence, scsi_io, ata_io
);
break;
#endif
#if !defined(DISABLE_SATI_WRITE_LONG)
case SCSI_WRITE_LONG_10:
case SCSI_WRITE_LONG_16:
status = sati_write_long_translate_command(sequence, scsi_io, ata_io);
break;
#endif
#if !defined(DISABLE_SATI_LOG_SENSE)
case SCSI_LOG_SENSE:
status = sati_log_sense_translate_command(sequence, scsi_io, ata_io);
break;
#endif
case SCSI_PERSISTENT_RESERVE_IN:
case SCSI_PERSISTENT_RESERVE_OUT:
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_ILLEGAL_REQUEST,
SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE
);
return SATI_FAILURE_CHECK_RESPONSE_DATA;
break;
#if !defined(DISABLE_SATI_UNMAP)
case SCSI_UNMAP:
status = sati_unmap_translate_command(sequence, scsi_io, ata_io);
break;
#endif
#if !defined(DISABLE_SATI_ATA_PASSTHROUGH)
case SCSI_ATA_PASSTHRU_12:
status = sati_passthrough_12_translate_command(sequence, scsi_io, ata_io);
break;
case SCSI_ATA_PASSTHRU_16:
status = sati_passthrough_16_translate_command(sequence, scsi_io, ata_io);
break;
#endif
#if !defined(DISABLE_SATI_READ_BUFFER)
case SCSI_READ_BUFFER:
status = sati_read_buffer_translate_command(sequence, scsi_io, ata_io);
break;
#endif
#if !defined(DISABLE_SATI_WRITE_BUFFER)
case SCSI_WRITE_BUFFER:
status = sati_write_buffer_translate_command(sequence, scsi_io, ata_io);
break;
#endif
default:
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
break;
}
if( (status == SATI_FAILURE_CHECK_RESPONSE_DATA) &&
!(sequence->is_sense_response_set) )
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_ILLEGAL_REQUEST,
SCSI_ASC_INVALID_FIELD_IN_CDB,
SCSI_ASCQ_INVALID_FIELD_IN_CDB
);
}
return status;
}
#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
SATI_STATUS sati_translate_task_management(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
SATI_DEVICE_T * sati_device,
void * scsi_task,
void * ata_io
)
{
SATI_STATUS status=SATI_FAILURE;
U8 task_function = sati_cb_get_task_function(scsi_task);
sequence->device = sati_device;
switch (task_function)
{
case SCSI_TASK_REQUEST_ABORT_TASK:
case SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET:
status = sati_lun_reset_translate_command(sequence, scsi_task, ata_io);
break;
case SCSI_TASK_REQUEST_ABORT_TASK_SET:
#if !defined(DISABLE_SATI_ABORT_TASK_SET)
status = sati_abort_task_set_translate_command(sequence, scsi_task, ata_io);
#else
status = SATI_FAILURE;
#endif
break;
default:
status = SATI_FAILURE;
break;
}
return status;
}
#endif
#if !defined(DISABLE_SATI_INQUIRY) \
|| !defined(DISABLE_SATI_READY_CAPACITY) \
|| !defined(DISABLE_SATI_MODE_SENSE) \
|| !defined(DISABLE_SATI_MODE_SELECT) \
|| !defined(DISABLE_SATI_REASSIGN_BLOCKS) \
|| !defined(DISABLE_SATI_START_STOP_UNIT) \
|| !defined(DISABLE_SATI_REQUEST_SENSE) \
|| !defined(DISABLE_SATI_WRITE_LONG) \
|| !defined(DISABLE_SATI_LOG_SENSE) \
|| !defined(DISABLE_SATI_UNMAP)
static
SATI_STATUS sati_check_data_io(
SATI_TRANSLATOR_SEQUENCE_T * sequence
)
{
if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
{
return SATI_SEQUENCE_INCOMPLETE;
}
else if(sequence->number_data_bytes_set < sequence->allocation_length)
{
return SATI_COMPLETE_IO_DONE_EARLY;
}
else
{
return SATI_COMPLETE;
}
}
#endif
SATI_STATUS sati_translate_command_response(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * scsi_io,
void * ata_io
)
{
SATI_STATUS status = SATI_COMPLETE;
U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
U8 ata_status;
ata_status = (U8) sati_get_ata_status(register_fis);
if (ata_status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
{
sati_scsi_sense_data_construct(
sequence,
scsi_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_HARDWARE_ERROR,
SCSI_ASC_INTERNAL_TARGET_FAILURE,
SCSI_ASCQ_INTERNAL_TARGET_FAILURE
);
sequence->device->state = SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED;
sati_sequence_terminate(sequence,
scsi_io,
ata_io);
return SATI_FAILURE_CHECK_RESPONSE_DATA;
}
switch (sequence->type)
{
#if !defined(DISABLE_SATI_TEST_UNIT_READY)
case SATI_SEQUENCE_TEST_UNIT_READY:
status = sati_test_unit_ready_translate_response(
sequence, scsi_io, ata_io
);
break;
#endif
#if !defined(DISABLE_SATI_INQUIRY) \
|| !defined(DISABLE_SATI_READY_CAPACITY) \
|| !defined(DISABLE_SATI_MODE_SENSE)
case SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG:
if (ata_status & ATA_STATUS_REG_ERROR_BIT)
{
U8 error = (U8) sati_get_ata_error(register_fis);
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
sati_translate_error(sequence, scsi_io, error);
}
else
{
sati_inquiry_ata_information_finish_translation(
sequence,
scsi_io,
ata_io
);
status = sati_check_data_io(sequence);
}
break;
case SATI_SEQUENCE_INQUIRY_STANDARD:
case SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES:
case SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER:
case SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE:
case SATI_SEQUENCE_INQUIRY_ATA_INFORMATION:
case SATI_SEQUENCE_INQUIRY_DEVICE_ID:
case SATI_SEQUENCE_READ_CAPACITY_10:
case SATI_SEQUENCE_READ_CAPACITY_16:
case SATI_SEQUENCE_MODE_SENSE_6_CACHING:
case SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL:
case SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR:
case SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT:
case SATI_SEQUENCE_MODE_SENSE_6_CONTROL:
case SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION:
case SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES:
case SATI_SEQUENCE_MODE_SENSE_10_CACHING:
case SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL:
case SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR:
case SATI_SEQUENCE_MODE_SENSE_10_CONTROL:
case SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION:
case SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT:
case SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES:
if (ata_status & ATA_STATUS_REG_ERROR_BIT)
{
U8 error = (U8) sati_get_ata_error(register_fis);
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
sati_translate_error(sequence, scsi_io, error);
}
else
{
void * ata_data = sati_cb_get_ata_data_address(ata_io);
if(ata_data == NULL)
{
status = SATI_FAILURE;
}
else
{
sati_translate_data(sequence, ata_data, scsi_io);
status = sati_check_data_io(sequence);
}
}
break;
#endif
#if !defined(DISABLE_SATI_MODE_SELECT)
case SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING:
status = sati_mode_select_translate_response(
sequence, scsi_io, ata_io
);
if(status == SATI_COMPLETE)
{
status = sati_check_data_io(sequence);
}
break;
case SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION:
case SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL:
if (ata_status & ATA_STATUS_REG_ERROR_BIT)
{
U8 error = (U8) sati_get_ata_error(register_fis);
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
sati_translate_error(sequence, scsi_io, error);
}
else
{
status = sati_check_data_io(sequence);
}
break;
#endif
#if !defined(DISABLE_SATI_WRITE_AND_VERIFY)
case SATI_SEQUENCE_WRITE_AND_VERIFY:
if (ata_status & ATA_STATUS_REG_ERROR_BIT)
{
U8 error = (U8) sati_get_ata_error(register_fis);
sati_translate_error(sequence, scsi_io, error);
return SATI_FAILURE_CHECK_RESPONSE_DATA;
}
else
{
status = sati_write_and_verify_translate_response(
sequence,
scsi_io,
ata_io
);
}
break;
#endif
case SATI_SEQUENCE_READ_6:
case SATI_SEQUENCE_READ_10:
case SATI_SEQUENCE_READ_12:
case SATI_SEQUENCE_READ_16:
case SATI_SEQUENCE_WRITE_6:
case SATI_SEQUENCE_WRITE_10:
case SATI_SEQUENCE_WRITE_12:
case SATI_SEQUENCE_WRITE_16:
case SATI_SEQUENCE_VERIFY_10:
case SATI_SEQUENCE_VERIFY_12:
case SATI_SEQUENCE_VERIFY_16:
case SATI_SEQUENCE_SYNCHRONIZE_CACHE:
if (ata_status & ATA_STATUS_REG_ERROR_BIT)
{
U8 error = (U8) sati_get_ata_error(register_fis);
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
sati_translate_error(sequence, scsi_io, error);
if(sequence->state == SATI_SEQUENCE_STATE_READ_ERROR )
{
sati_scsi_read_error_sense_construct(
sequence,
scsi_io,
ata_io,
SCSI_STATUS_CHECK_CONDITION,
SCSI_SENSE_MEDIUM_ERROR,
SCSI_ASC_UNRECOVERED_READ_ERROR,
SCSI_ASCQ_UNRECOVERED_READ_ERROR
);
sequence->state = SATI_SEQUENCE_STATE_FINAL;
}
}
else
{
if (sequence->command_specific_data.scratch)
{
status = SATI_SEQUENCE_INCOMPLETE;
}
}
break;
#if !defined(DISABLE_SATI_READ_BUFFER)
case SATI_SEQUENCE_READ_BUFFER:
status = sati_read_buffer_translate_response(
sequence, scsi_io, ata_io
);
if(status == SATI_COMPLETE)
{
status = sati_check_data_io(sequence);
}
break;
#endif
#if !defined(DISABLE_SATI_WRITE_BUFFER)
case SATI_SEQUENCE_WRITE_BUFFER:
case SATI_SEQUENCE_WRITE_BUFFER_MICROCODE:
status = sati_write_buffer_translate_response(
sequence, scsi_io, ata_io
);
break;
#endif
#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
case SATI_SEQUENCE_REASSIGN_BLOCKS:
status = sati_reassign_blocks_translate_response(
sequence, scsi_io, ata_io
);
if(status == SATI_COMPLETE)
{
status = sati_check_data_io(sequence);
}
break;
#endif
#if !defined(DISABLE_SATI_START_STOP_UNIT)
case SATI_SEQUENCE_START_STOP_UNIT:
status = sati_start_stop_unit_translate_response(
sequence, scsi_io, ata_io
);
if(status == SATI_COMPLETE)
{
status = sati_check_data_io(sequence);
}
break;
#endif
#if !defined(DISABLE_SATI_REQUEST_SENSE)
case SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS:
case SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE:
status = sati_request_sense_translate_response(
sequence, scsi_io, ata_io
);
if(status == SATI_COMPLETE)
{
status = sati_check_data_io(sequence);
}
break;
#endif
#if !defined(DISABLE_SATI_WRITE_LONG)
case SATI_SEQUENCE_WRITE_LONG:
status = sati_write_long_translate_response(
sequence, scsi_io, ata_io
);
if(status == SATI_COMPLETE)
{
status = sati_check_data_io(sequence);
}
break;
#endif
#if !defined(DISABLE_SATI_LOG_SENSE)
case SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE:
case SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE:
case SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE:
case SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE:
status = sati_log_sense_translate_response(
sequence, scsi_io, ata_io
);
if(status == SATI_COMPLETE)
{
status = sati_check_data_io(sequence);
}
break;
#endif
#if !defined(DISABLE_SATI_UNMAP)
case SATI_SEQUENCE_UNMAP:
status = sati_unmap_translate_response(
sequence, scsi_io, ata_io
);
break;
#endif
#if !defined(DISABLE_SATI_ATA_PASSTHROUGH)
case SATI_SEQUENCE_ATA_PASSTHROUGH_12:
case SATI_SEQUENCE_ATA_PASSTHROUGH_16:
status = sati_passthrough_translate_response(
sequence, scsi_io, ata_io
);
break;
#endif
default:
status = SATI_FAILURE_INVALID_SEQUENCE_TYPE;
break;
}
return status;
}
#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
SATI_STATUS sati_translate_task_response(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * scsi_io,
void * ata_io
)
{
SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
U8 ata_status;
ata_status = (U8) sati_get_ata_status(register_fis);
if (ata_status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
{
sati_scsi_response_data_construct(
sequence,
scsi_io,
SCSI_TASK_MGMT_FUNC_FAILED
);
return SATI_FAILURE_CHECK_RESPONSE_DATA;
}
switch (sequence->type)
{
case SATI_SEQUENCE_LUN_RESET:
if (ata_status & ATA_STATUS_REG_ERROR_BIT)
{
sati_scsi_response_data_construct(
sequence, scsi_io, SCSI_TASK_MGMT_FUNC_FAILED);
}
else
{
sati_scsi_response_data_construct(
sequence, scsi_io, SCSI_TASK_MGMT_FUNC_COMPLETE);
}
status = SATI_COMPLETE;
break;
#if !defined(DISABLE_SATI_ABORT_TASK_SET)
case SATI_SEQUENCE_ABORT_TASK_SET:
if (ata_status & ATA_STATUS_REG_ERROR_BIT)
{
sati_scsi_response_data_construct(
sequence, scsi_io, SCSI_TASK_MGMT_FUNC_FAILED);
}
else
{
void * ata_data = sati_cb_get_ata_data_address(ata_io);
if(ata_data == NULL)
{
status = SATI_FAILURE;
}
else
{
status = sati_abort_task_set_translate_data(
sequence,
ata_data,
scsi_io
);
}
}
break;
#endif
default:
status = SATI_FAILURE_INVALID_SEQUENCE_TYPE;
break;
}
return status;
}
#endif
#if !defined(ENABLE_MINIMUM_MEMORY_MODE)
U32 sati_get_sat_compliance_version(
void
)
{
return 2;
}
U32 sati_get_sat_compliance_version_revision(
void
)
{
return 7;
}
#endif
U16 sati_get_number_data_bytes_set(
SATI_TRANSLATOR_SEQUENCE_T * sequence
)
{
return sequence->number_data_bytes_set;
}
void sati_sequence_construct(
SATI_TRANSLATOR_SEQUENCE_T * sequence
)
{
sequence->state = SATI_SEQUENCE_STATE_INITIAL;
}
void sati_sequence_terminate(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * scsi_io,
void * ata_io
)
{
switch (sequence->type)
{
case SATI_SEQUENCE_UNMAP:
sati_unmap_terminate(sequence,scsi_io,ata_io);
break;
}
}