/** * @brief This method will translate the lun reset SCSI task request into an * ATA SOFT RESET command. For more information on the parameters * passed to this method, please reference sati_translate_command(). * * @return Indicate if the command translation succeeded. * @retval SCI_SUCCESS This is returned if the command translation was * successful. * * @note It is up to the user of the sata translator to set the command bit * and clear the control softreset bit and send the second register fis. */ SATI_STATUS sati_lun_reset_translate_command( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_io ) { U8* register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_NOP); sati_set_ata_control(register_fis, ATA_CONTROL_REG_SOFT_RESET_BIT); //set all other fields to zero. sati_clear_sata_command_flag(register_fis); sati_set_ata_features(register_fis, 0); sati_set_ata_features_exp(register_fis, 0); sati_set_ata_sector_count(register_fis, 0); sati_set_ata_sector_count_exp(register_fis, 0); sati_set_ata_lba_low(register_fis, 0); sati_set_ata_lba_mid(register_fis, 0); sati_set_ata_lba_high(register_fis, 0); sati_set_ata_lba_low_exp(register_fis, 0); sati_set_ata_lba_mid_exp(register_fis, 0); sati_set_ata_lba_high_exp(register_fis, 0); sati_set_ata_device_head(register_fis, 0); sequence->type = SATI_SEQUENCE_LUN_RESET; sequence->data_direction = SATI_DATA_DIRECTION_NONE; sequence->protocol = SAT_PROTOCOL_SOFT_RESET; sequence->ata_transfer_length = 0; return SATI_SUCCESS; }
/** * @brief This method performs the SCSI SYNCHRONIZE_CACHE 10 and 16 command translation * functionality common to all SYNCHRONIZE_CACHE command sizes. * This includes: * - setting the command register * - setting the device head register * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object. * For more information on the parameters passed to this method, * please reference sati_translate_command(). * * @return Indicate if the method was successfully completed. * @retval SATI_SUCCESS This is returned in all other cases. */ SATI_STATUS sati_synchronize_cache_translate_command( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_io ) { U8 * cdb = sati_cb_get_cdb_address(scsi_io); U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sequence->type = SATI_SEQUENCE_SYNCHRONIZE_CACHE; sequence->protocol = SAT_PROTOCOL_NON_DATA; sequence->data_direction = SATI_DATA_DIRECTION_NONE; if (sati_get_cdb_byte(cdb, 1) & SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED) { //currently we ignore immed bit. ; } // Ensure the device supports the 48 bit feature set. if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE) sati_set_ata_command(register_fis, ATA_FLUSH_CACHE_EXT); else sati_set_ata_command(register_fis, ATA_FLUSH_CACHE); return SATI_SUCCESS; }
/** * @brief This method performs the SCSI Unmap command translation * functionality. * This includes: * - setting the command register * - setting the device head register * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object. * For more information on the parameters passed to this method, * please reference sati_translate_command(). * * @return Indicate if the method was successfully completed. * @retval SATI_SUCCESS This is returned in all other cases. */ SATI_STATUS sati_unmap_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_io, U32 sector_count ) { U8 * h2d_register_fis = sati_cb_get_h2d_register_fis_address(ata_io); U8 * d2h_register_fis = sati_cb_get_d2h_register_fis_address(ata_io); sati_set_ata_command(h2d_register_fis, ATA_DATA_SET_MANAGEMENT); sati_set_ata_features(h2d_register_fis, 0x01); sati_set_ata_sector_count(h2d_register_fis, (U8)sector_count); sati_set_ata_device_head(h2d_register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE); // Set the completion status since the core will not do that for // the udma fast path. sati_set_ata_status(d2h_register_fis, 0x00); // Set up the direction and protocol for SCIC sequence->data_direction = SATI_DATA_DIRECTION_OUT; sequence->protocol = SAT_PROTOCOL_UDMA_DATA_OUT; // The UNMAP translation will always require a callback // on every response so it can free memory if an error // occurs. sequence->is_translate_response_required = TRUE; ASSERT(sector_count < 0x100); return SATI_SUCCESS; }
/** * @brief This method performs the SCSI VERIFY command translation * functionality common to all VERIFY command sizes. * This includes: * - setting the command register * - setting the device head register * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object. * For more information on the parameters passed to this method, * please reference sati_translate_command(). * * @return Indicate if the method was successfully completed. * @retval SATI_SUCCESS This is returned in all other cases. */ static SATI_STATUS sati_verify_translate_command( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_io ) { U8 * cdb = sati_cb_get_cdb_address(scsi_io); U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); /** * The translator doesn't support performing the byte check operation. * As a result, error the request if the BYTCHK bit is set. */ if ((sati_get_cdb_byte(cdb, 1) & SCSI_VERIFY_BYTCHK_ENABLED)) { 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; } sequence->protocol = SAT_PROTOCOL_NON_DATA; sequence->data_direction = SATI_DATA_DIRECTION_NONE; sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE); // Ensure the device supports the 48 bit feature set. if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE) sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT); else sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS); return SATI_SUCCESS; }
/** * @brief This method will translate the abort task set SCSI task request into an * ATA READ LOG EXT command. For more information on the parameters * passed to this method, please reference sati_translate_command(). * * @return Indicate if the command translation succeeded. * @retval SCI_SUCCESS This is returned if the command translation was * successful. */ SATI_STATUS sati_abort_task_set_translate_command( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_io ) { U8 * register_fis; //ATA Read Log Ext with log address set to 0x10 sati_ata_read_log_ext_construct( ata_io, sequence, ATA_LOG_PAGE_NCQ_ERROR, sizeof(ATA_NCQ_COMMAND_ERROR_LOG_T) ); register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_sata_command_flag(register_fis); sequence->type = SATI_SEQUENCE_ABORT_TASK_SET; sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE; return SATI_SUCCESS; }
/** * @brief This method will translate the SCSI Passthrough command * into the corresponding ATA command. * * @return Indicate if the command translation succeeded. * @retval SATI_SUCCESS This is returned if the command translation was * successful. * @retval SATI_FAILURE This is returned if the command translation was * unsuccessful */ SATI_STATUS sati_passthrough_16_translate_command( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_io ) { SATI_STATUS status; U8 * cdb; U8 * register_fis; status = SATI_FAILURE; sequence->type = SATI_SEQUENCE_ATA_PASSTHROUGH_16; sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA; cdb = sati_cb_get_cdb_address(scsi_io); sequence->protocol = PASSTHROUGH_CDB_PROTOCOL(cdb); register_fis = sati_cb_get_h2d_register_fis_address(ata_io); /* * CAM will send passthrough commands with protocol set to multiword * DMA even though no multiword DMA mode is selected on the device. * This is because some controllers (LSI) will only accept * ATA_PASSTHROUGH commands with DMA mode - not UDMA_IN/OUT. * * Since isci does not support multiword DMA, fix this up here. */ if (sequence->protocol == PASSTHROUGH_DMA) { if (PASSTHROUGH_CDB_T_DIR(cdb) == 0x1) { sequence->protocol = PASSTHROUGH_UDMA_DATA_IN; } else { sequence->protocol = PASSTHROUGH_UDMA_DATA_OUT; } } if (sati_passthrough_check_direction(sequence, cdb) != SATI_COMPLETE || sati_passthrough_multiple_count_error(cdb) ) { // Fail due to mismatch 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 (PASSTHROUGH_CDB_EXTEND(cdb) == 1) { sati_set_ata_features_exp(register_fis, sati_get_cdb_byte(cdb, 3)); sati_set_ata_sector_count_exp(register_fis, sati_get_cdb_byte(cdb, 5)); sati_set_ata_lba_low_exp(register_fis, sati_get_cdb_byte(cdb, 7)); sati_set_ata_lba_mid_exp(register_fis, sati_get_cdb_byte(cdb, 9)); sati_set_ata_lba_high_exp(register_fis, sati_get_cdb_byte(cdb, 11)); } if (PASSTHROUGH_CDB_CK_COND(cdb) || PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_RETURN_RESPONSE) { sequence->is_translate_response_required = TRUE; } sati_set_ata_features(register_fis, sati_get_cdb_byte(cdb, 4)); sati_set_ata_sector_count(register_fis, sati_get_cdb_byte(cdb, 6)); sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 8)); sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 10)); sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 12)); sati_set_ata_device_head(register_fis, sati_get_cdb_byte(cdb, 13)); sati_set_ata_command(register_fis, sati_get_cdb_byte(cdb, 14)); sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE; return SATI_SUCCESS; }
SATI_STATUS sati_atapi_translate_command( SATI_TRANSLATOR_SEQUENCE_T * sequence, SATI_DEVICE_T * sati_device, void * scsi_io, void * atapi_io ) { SATI_STATUS status; U8 * cdb = sati_cb_get_cdb_address(scsi_io); SATA_FIS_REG_H2D_T * register_fis = (SATA_FIS_REG_H2D_T *)sati_cb_get_h2d_register_fis_address(atapi_io); U8 io_direction = SATI_DATA_DIRECTION_IN; //No sense response has been set for the translation sequence yet sequence->is_sense_response_set = FALSE; // Default to no translation response required sequence->is_translate_response_required = FALSE; sequence->number_data_bytes_set = 0; sequence->device = sati_device; sequence->command_specific_data.scratch = 0; sati_cb_get_data_direction(scsi_io, &io_direction); //set sat protocol. if (io_direction == SATI_DATA_DIRECTION_NONE) sequence->protocol = SAT_PROTOCOL_PACKET_NON_DATA; else if (io_direction == SATI_DATA_DIRECTION_IN) sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_IN; else if (io_direction == SATI_DATA_DIRECTION_OUT) sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_OUT; // We don't send Report Luns command out. if (sati_get_cdb_byte(cdb, 0) == SCSI_REPORT_LUNS) { status = sati_report_luns_translate_command( sequence, scsi_io, atapi_io ); } else 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 ); status = SATI_FAILURE_CHECK_RESPONSE_DATA; } else { if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE) { //Request Sense command is required. U8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH] = {0x3, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; //set the sequence->protocol to DATA_IN anyway; sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_IN; //set the cdb for Request Sense using command_specific_data field. memcpy(sequence->command_specific_data.sati_atapi_data.request_sense_cdb, request_sense_cdb, SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH ); } //build Packet Fis for any other command translation. register_fis->command = ATA_PACKET; register_fis->features |= ATA_PACKET_FEATURE_DMA; register_fis->fis_type = SATA_FIS_TYPE_REGH2D; register_fis->command_flag = 1; status = SATI_SUCCESS; } return status; }