/** * @brief This method finishes the construction of the SCSI data associated with a request for the ATA information vital product data (VPD) page. The ATA device signature is written into the data response from the task fle registers after issuing a Execute Device Diagnostic command. * * @param[in] sequence This parameter specifies the translator sequence * object to be utilized during data translation. * @param[out] scsi_io This parameter specifies the user IO request for * which to construct the ATA information page. * @param[in] ata_io This parameter specifies the ATA payload * buffer location and size to be translated. * * @return none */ void sati_inquiry_ata_information_finish_translation( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_io ) { U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); U32 offset; //SATA transport sati_set_data_byte(sequence, scsi_io, 36, 0x34); sati_set_data_byte(sequence, scsi_io, 37, 0x00); sati_set_data_byte(sequence, scsi_io, 38, (U8) sati_get_ata_status(register_fis)); sati_set_data_byte(sequence, scsi_io, 39, (U8) sati_get_ata_error(register_fis)); sati_set_data_byte(sequence, scsi_io, 40, sati_get_ata_lba_low(register_fis)); sati_set_data_byte(sequence, scsi_io, 41, sati_get_ata_lba_mid(register_fis)); sati_set_data_byte(sequence, scsi_io, 42, sati_get_ata_lba_high(register_fis)); sati_set_data_byte(sequence, scsi_io, 43, sati_get_ata_device(register_fis)); sati_set_data_byte(sequence, scsi_io, 44, sati_get_ata_lba_low_ext(register_fis)); sati_set_data_byte(sequence, scsi_io, 45, sati_get_ata_lba_mid_ext(register_fis)); sati_set_data_byte(sequence, scsi_io, 46, sati_get_ata_lba_high_ext(register_fis)); sati_set_data_byte(sequence, scsi_io, 47, 0x00); sati_set_data_byte(sequence, scsi_io, 48, sati_get_ata_sector_count(register_fis)); sati_set_data_byte(sequence, scsi_io, 49, sati_get_ata_sector_count_exp(register_fis)); for(offset = 50; offset < 56; offset++) { sati_set_data_byte(sequence, scsi_io, offset, 0x00); } sequence->state = SATI_SEQUENCE_STATE_FINAL; }
/** * @brief This method will construct the sense data buffer in the user's * sense data buffer location. Additionally, it will set the user's * SCSI status. * * @param[in] sequence This parameter specifies the translation sequence * for which to construct the sense data. * @param[in] register_fis This parameter specifies the fis from which * to get the data. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[in] sense_key This parameter specifies the sense key to * be set for the user's IO request. * @param[in] additional_sense_code This parameter specifies the * additional sense code (ASC) key to be set for the user's * IO request. * @param[in] additional_sense_code_qualifier This parameter specifies * the additional sense code qualifier (ASCQ) key to be set * for the user's IO request. * * @return none */ static void sati_passthrough_construct_sense( SATI_TRANSLATOR_SEQUENCE_T * sequence, U8 * register_fis, void * scsi_io, U8 scsi_status, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { U8 * sense_data; U32 sense_len; U8 * cdb; unsigned char sector_count_upper; unsigned char lba_upper; #ifdef SATI_TRANSPORT_SUPPORTS_SAS SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*) sati_cb_get_response_iu_address(scsi_io); sati_scsi_common_response_iu_construct( rsp_iu, scsi_status, SCSI_FIXED_SENSE_DATA_BASE_LENGTH, SCSI_RESPONSE_DATA_PRES_SENSE_DATA ); sense_data = (U8*) rsp_iu->data; sense_len = SSP_RESPONSE_IU_MAX_DATA * 4; // dwords to bytes #else sense_data = sati_cb_get_sense_data_address(scsi_io); sense_len = sati_cb_get_sense_data_length(scsi_io); #endif // SATI_TRANSPORT_SUPPORTS_SAS sati_scsi_sense_data_construct( sequence, scsi_io, scsi_status, sense_key, additional_sense_code, additional_sense_code_qualifier ); cdb = sati_cb_get_cdb_address(scsi_io); if (sati_get_ata_sector_count_ext(register_fis) != 0) { sector_count_upper = 1; } else { sector_count_upper = 0; } if (sati_get_ata_lba_high_ext(register_fis) != 0 || sati_get_ata_lba_mid_ext(register_fis) != 0 || sati_get_ata_lba_low_ext(register_fis) != 0) { lba_upper = 1; } else { lba_upper = 0; } // Information section sati_set_sense_data_byte(sense_data, sense_len, 3, (U8)sati_get_ata_error(register_fis)); sati_set_sense_data_byte(sense_data, sense_len, 4, (U8)sati_get_ata_status(register_fis)); sati_set_sense_data_byte(sense_data, sense_len, 5, sati_get_ata_device(register_fis)); sati_set_sense_data_byte(sense_data, sense_len, 6, sati_get_ata_sector_count(register_fis)); // Command specific section sati_set_sense_data_byte(sense_data, sense_len, 8, (PASSTHROUGH_CDB_EXTEND(cdb) << 7) | (sector_count_upper << 6) | (lba_upper << 5)); sati_set_sense_data_byte(sense_data, sense_len, 9, sati_get_ata_lba_high(register_fis)); sati_set_sense_data_byte(sense_data, sense_len, 10, sati_get_ata_lba_mid(register_fis)); sati_set_sense_data_byte(sense_data, sense_len, 11, sati_get_ata_lba_low(register_fis)); sequence->is_sense_response_set = TRUE; }
/** * @brief This method will translate the response to the SATI Request Sense * translation. ATA_Check_Power_Mode and ATA_SMART_Return_Status will * be translated into a SCSI sense data response. * * @return SATI_STATUS Indicates if the response translation succeeded. * */ SATI_STATUS sati_request_sense_translate_response( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_io ) { U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); U32 mid_register; U32 high_register; U32 sector_count; SATI_STATUS status = SATI_FAILURE; if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT) { 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 ); status = SATI_FAILURE_CHECK_RESPONSE_DATA; } else { switch(sequence->type) { case SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS: mid_register = sati_get_ata_lba_mid(register_fis); high_register = sati_get_ata_lba_high(register_fis); if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED) { sati_request_sense_data_response_construct( sequence, scsi_io, SCSI_SENSE_NO_SENSE, SCSI_ASC_HARDWARE_IMPENDING_FAILURE, SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE ); status = SATI_COMPLETE; } else { sati_request_sense_data_response_construct( sequence, scsi_io, SCSI_SENSE_NO_SENSE, SCSI_ASC_NO_ADDITIONAL_SENSE, SCSI_ASCQ_NO_ADDITIONAL_SENSE ); status = SATI_COMPLETE; } break; case SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE: sector_count = sati_get_ata_sector_count(register_fis); switch(sector_count) { case ATA_STANDBY_POWER_MODE: sati_request_sense_data_response_construct( sequence, scsi_io, SCSI_SENSE_NO_SENSE, SCSI_ASC_POWER_STATE_CHANGE, SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY ); status = SATI_COMPLETE; break; case ATA_IDLE_POWER_MODE: sati_request_sense_data_response_construct( sequence, scsi_io, SCSI_SENSE_NO_SENSE, SCSI_ASC_POWER_STATE_CHANGE, SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE ); status = SATI_COMPLETE; break; case ATA_ACTIVE_POWER_MODE: sati_request_sense_data_response_construct( sequence, scsi_io, SCSI_SENSE_NO_SENSE, SCSI_ASC_NO_ADDITIONAL_SENSE, SCSI_ASCQ_NO_ADDITIONAL_SENSE ); status = SATI_COMPLETE; break; default: break; } break; default: sati_request_sense_data_response_construct( sequence, scsi_io, SCSI_SENSE_NO_SENSE, SCSI_ASC_NO_ADDITIONAL_SENSE, SCSI_ASCQ_NO_ADDITIONAL_SENSE ); status = SATI_COMPLETE; } } return status; }