diff options
author | Jim Harris <jimharris@FreeBSD.org> | 2012-01-31 19:38:18 +0000 |
---|---|---|
committer | Jim Harris <jimharris@FreeBSD.org> | 2012-01-31 19:38:18 +0000 |
commit | f11c7f63056671247335df83a3fe80b94c6616ac (patch) | |
tree | cb4ab69703685955650ec588ba9e9a9f80756563 /sys/dev/isci/scil/sati_log_sense.c | |
parent | db25e24c2f75db6edfb0d0b59f051ae30f62f5cd (diff) |
Add isci(4) driver for amd64 and i386 targets.
The isci driver is for the integrated SAS controller in the Intel C600
(Patsburg) chipset. Source files in sys/dev/isci directory are
FreeBSD-specific, and sys/dev/isci/scil subdirectory contains
an OS-agnostic library (SCIL) published by Intel to control the SAS
controller. This library is used primarily as-is in this driver, with
some post-processing to better integrate into the kernel build
environment.
isci.4 and a README in the sys/dev/isci directory contain a few
additional details.
This driver is only built for amd64 and i386 targets.
Sponsored by: Intel
Reviewed by: scottl
Approved by: scottl
Notes
Notes:
svn path=/head/; revision=230843
Diffstat (limited to 'sys/dev/isci/scil/sati_log_sense.c')
-rw-r--r-- | sys/dev/isci/scil/sati_log_sense.c | 807 |
1 files changed, 807 insertions, 0 deletions
diff --git a/sys/dev/isci/scil/sati_log_sense.c b/sys/dev/isci/scil/sati_log_sense.c new file mode 100644 index 000000000000..44bc4e91afab --- /dev/null +++ b/sys/dev/isci/scil/sati_log_sense.c @@ -0,0 +1,807 @@ +/*- + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/** +* @file +* @brief This file contains the method definitions to translate +* SCSI Log Sense command based of the SATv2 spec. +*/ + +#if !defined(DISABLE_SATI_LOG_SENSE) + +#include <dev/isci/scil/sati_log_sense.h> +#include <dev/isci/scil/sati_callbacks.h> +#include <dev/isci/scil/sati_util.h> + +//****************************************************************************** +//* P R I V A T E M E T H O D S +//****************************************************************************** + +/** + * @brief This method constructs the SATI supported log page. This is a log + * containing the page codes of all the SATI supported log pages. + * + * @return n/a + * + */ +static +void sati_supported_log_page_construct( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * scsi_io +) +{ + U32 next_byte; + //set SPF = 0 and PAGE_CODE = 0 + sati_set_data_byte(sequence, scsi_io, 0, 0x00); + + //set SUBPAGE_CODE = 0 + sati_set_data_byte(sequence, scsi_io, 1, 0x00); + + //set the Page Length to (n-3) or 2 because only two log pages are supported + sati_set_data_byte(sequence, scsi_io, 2, 0x00); + sati_set_data_byte(sequence, scsi_io, 3, 0x02); + + //specify the next byte to be set + next_byte = 4; + + if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT) + { + sati_set_data_byte( + sequence, + scsi_io, + next_byte, + SCSI_LOG_PAGE_INFORMATION_EXCEPTION + ); + next_byte = 5; + } + + if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT) + { + sati_set_data_byte( + sequence, + scsi_io, + next_byte, + SCSI_LOG_PAGE_SELF_TEST + ); + } +} + +/** + * @brief This method sets bytes 4-19 of the self-test log parameter to zero. + * + * @return n/a + * + */ +static +void sati_set_parameters_to_zero( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * scsi_io +) +{ + sati_set_data_byte(sequence, scsi_io, 8, 0x00); //log_parameter byte 4 + sati_set_data_byte(sequence, scsi_io, 9, 0x00); //log_parameter byte 5 + sati_set_data_byte(sequence, scsi_io, 10, 0x00); //log_parameter byte 6 + sati_set_data_byte(sequence, scsi_io, 11, 0x00); //log_parameter byte 7 + sati_set_data_byte(sequence, scsi_io, 12, 0x00); //log_parameter byte 8 + sati_set_data_byte(sequence, scsi_io, 13, 0x00); //log_parameter byte 9 + sati_set_data_byte(sequence, scsi_io, 14, 0x00); //log_parameter byte 10 + sati_set_data_byte(sequence, scsi_io, 15, 0x00); //log_parameter byte 11 + sati_set_data_byte(sequence, scsi_io, 16, 0x00); //log_parameter byte 12 + sati_set_data_byte(sequence, scsi_io, 17, 0x00); //log_parameter byte 13 + sati_set_data_byte(sequence, scsi_io, 18, 0x00); //log_parameter byte 14 + sati_set_data_byte(sequence, scsi_io, 19, 0x00); //log_parameter byte 15 + sati_set_data_byte(sequence, scsi_io, 20, 0x00); //log_parameter byte 16 + sati_set_data_byte(sequence, scsi_io, 21, 0x00); //log_parameter byte 17 + sati_set_data_byte(sequence, scsi_io, 22, 0x00); //log_parameter byte 18 + sati_set_data_byte(sequence, scsi_io, 23, 0x00); //log_parameter byte 19 +} + +/** + * @brief This method translates the ATA Extended SMART self-test log into + * SCSI Sense Key, Additional Sense Code, and Additional Sense code + * qualifiers based on the self test status byte in the appropriate + * descriptor entry. + * + * @return n/a + * + */ +static +void sati_translate_sense_values( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * scsi_io, + U8 self_test_status_byte +) +{ + //byte 17 + sati_set_data_byte( + sequence, + scsi_io, + 21, + SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT + ); + + switch(self_test_status_byte) + { + case 1: + //byte 16 + sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND); + + //byte 18 + sati_set_data_byte(sequence, scsi_io, 22, 0x81); + break; + + case 2: + //byte 16 + sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND); + + //byte 18 + sati_set_data_byte(sequence, scsi_io, 22, 0x82); + break; + + case 3: + //byte 16 + sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND); + + //byte 18 + sati_set_data_byte(sequence, scsi_io, 22, 0x83); + break; + + case 4: + //byte 16 + sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR); + + //byte 18 + sati_set_data_byte(sequence, scsi_io, 22, 0x84); + break; + + case 5: + //byte 16 + sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR); + + //byte 18 + sati_set_data_byte(sequence, scsi_io, 22, 0x85); + break; + + case 6: + //byte 16 + sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR); + + //byte 18 + sati_set_data_byte(sequence, scsi_io, 22, 0x86); + break; + + case 7: + //byte 16 + sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_MEDIUM_ERROR); + + //byte 18 + sati_set_data_byte(sequence, scsi_io, 22, 0x87); + break; + + case 8: + //byte 16 + sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR); + + //byte 18 + sati_set_data_byte(sequence, scsi_io, 22, 0x88); + break; + + default: + //byte 16 + sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_NO_SENSE); + //byte 17 + sati_set_data_byte(sequence, scsi_io, 21, SCSI_ASC_NO_ADDITIONAL_SENSE); + //byte 18 + sati_set_data_byte(sequence, scsi_io, 22, 0x00); + break; + } + +} + +/** + * @brief This method retrieves the correct self-test results by checking the + * descriptor index in the extended SMART self-test log. The index is + * used to determine the appropriate descriptor entry. + * + * @return n/a + * + */ +static +void sati_get_self_test_results( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * scsi_io, + ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log +) +{ + U16 descriptor_index = *((U16 *)(&ata_log->self_test_descriptor_index[0])); + + /* + * SATv2 wants data from descriptor N where N is equal to + * (descriptor_index - parameter_code) + 1. Since parameter + * code is always 0x0001 just checking descriptor_index. + */ + + if(descriptor_index <= 0) + { + sati_set_parameters_to_zero(sequence, scsi_io); + } + else + { + sati_set_data_byte( + sequence, + scsi_io, + 8, + ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte + ); + + //Sef-test number unspecified per satv2 + sati_set_data_byte(sequence, scsi_io, 9, 0x00); + sati_set_data_byte( + sequence, + scsi_io, + 10, + ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_high + ); + + sati_set_data_byte( + sequence, + scsi_io, + 11, + ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_low + ); + + //set to zero because it's a 48bit address + sati_set_data_byte(sequence, scsi_io, 12, 0x00); + sati_set_data_byte(sequence, scsi_io, 13, 0x00); + + sati_set_data_byte( + sequence, + scsi_io, + 14, + ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high_ext + ); + + sati_set_data_byte( + sequence, + scsi_io, + 15, + ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid_ext + ); + + sati_set_data_byte( + sequence, + scsi_io, + 16, + ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low_ext + ); + + sati_set_data_byte( + sequence, + scsi_io, + 17, + ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high + ); + + sati_set_data_byte( + sequence, + scsi_io, + 18, + ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid + ); + + sati_set_data_byte( + sequence, + scsi_io, + 19, + ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low + ); + + sati_translate_sense_values( + sequence, + scsi_io, + ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte + ); + } +} + +/** +* @brief This method will construct the first eight bytes of the SCSI self test +* log page for both cases when SATI sends a ATA read log ext and a smart +* read log command. +* +* @return n/a +* +*/ +static +void sati_self_test_log_header_construct( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * scsi_io +) +{ + //PAGE CODE for Self-Test Log Page + sati_set_data_byte(sequence, scsi_io, 0, 0x10); + sati_set_data_byte(sequence, scsi_io, 1, 0x00); + + //PAGE LENGTH is 0x14 instead of 0x190, not returning 20/0x190 log perameters + sati_set_data_byte(sequence, scsi_io, 2, 0x00); + sati_set_data_byte(sequence, scsi_io, 3, 0x14); + + /* + * Log PARAMETER 0x0001 + * Only sending one log parameter per self-test request. + */ + sati_set_data_byte(sequence, scsi_io, 4, 0x00); //log_parameter byte 0 + sati_set_data_byte(sequence, scsi_io, 5, 0x01); //log_parameter byte 1 + + //Set to 0x03 per SATv2 spec + sati_set_data_byte(sequence, scsi_io, 6, 0x03); //log_parameter byte 2 + + //Parameter Length set to 0x10 per SATv2 spec + sati_set_data_byte(sequence, scsi_io, 7, 0x10); //log_parameter byte 3 +} + +/** + * @brief This method will construct the SCSI self test log page from + * the Extended SMART self-test log response recieved from the + * ATA device. The response is from a ATA_Read_Log_EXT command + * issued by SATI. + * + * @return n/a + * + */ +static +void sati_extended_self_test_log_page_construct( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * scsi_io, + void * ata_data +) +{ + ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log = + (ATA_EXTENDED_SMART_SELF_TEST_LOG_T*) ata_data; + + sati_self_test_log_header_construct(sequence, scsi_io); + + //bytes 4-19 + if( (ata_log->self_test_descriptor_index[0] == 0) && + (ata_log->self_test_descriptor_index[1] == 0)) + { + sati_set_parameters_to_zero(sequence, scsi_io); + } + else + { + sati_get_self_test_results(sequence, scsi_io, ata_log); + } +} + +/** +* @brief This method will construct the SCSI self test log page from +* the SMART self-test log response recieved from the ATA device. +* The response is from a ATA_SMART_Read_Log command issued by SATI. +* +* @return n/a +* +*/ +static +void sati_self_test_log_page_construct( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * scsi_io, + void * ata_data +) +{ + ATA_SMART_SELF_TEST_LOG_T * ata_log = + (ATA_SMART_SELF_TEST_LOG_T*) ata_data; + + sati_self_test_log_header_construct(sequence, scsi_io); + + //first descriptor entry(index == 0) is always used because scsi_parameter_code == 1 + sati_set_data_byte( + sequence, + scsi_io, + 8, + ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte + ); + + //Sef-test number unspecified per satv2 + sati_set_data_byte(sequence, scsi_io, 9, 0x00); + + sati_set_data_byte( + sequence, + scsi_io, + 10, + ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_high + ); + + sati_set_data_byte( + sequence, + scsi_io, + 11, + ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_low + ); + + //set to zero because it's a 28bit address + sati_set_data_byte(sequence, scsi_io, 12, 0x00); + sati_set_data_byte(sequence, scsi_io, 13, 0x00); + sati_set_data_byte(sequence, scsi_io, 14, 0x00); + sati_set_data_byte(sequence, scsi_io, 15, 0x00); + + sati_set_data_byte( + sequence, + scsi_io, + 16, + ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low_ext + ); + + sati_set_data_byte( + sequence, + scsi_io, + 17, + ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_high + ); + + sati_set_data_byte( + sequence, + scsi_io, + 18, + ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_mid + ); + + sati_set_data_byte( + sequence, + scsi_io, + 19, + ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low + ); + + sati_translate_sense_values( + sequence, + scsi_io, + ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte + ); +} + +/** +* @brief This method will construct the SCSI information exception log page from +* the ATA SMART response recieved from the ATA device. The response is +* from a ATA SMART return status command issued by SATI. +* +* @return n/a +* +*/ +static +void sati_information_exception_log_page_contruct( + 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 = sati_get_ata_lba_mid(register_fis); + U32 high_register = sati_get_ata_lba_high(register_fis); + + //Information Exception Page code + sati_set_data_byte( + sequence, + scsi_io, + 0, + SCSI_LOG_PAGE_INFORMATION_EXCEPTION + ); + + //Sub-page code + sati_set_data_byte(sequence, scsi_io, 1, 0x00); + + //Page length of log parameters + sati_set_data_byte(sequence, scsi_io, 2, 0x00); + sati_set_data_byte(sequence, scsi_io, 3, 0x08); + + //parameter code + sati_set_data_byte(sequence, scsi_io, 4, 0x00); + sati_set_data_byte(sequence, scsi_io, 5, 0x00); + + //Format and Linking + sati_set_data_byte(sequence, scsi_io, 6, 0x03); + //Parameter Length + sati_set_data_byte(sequence, scsi_io, 7, 0x04); + + if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED + && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED) + { + sati_set_data_byte( + sequence, + scsi_io, + 8, + SCSI_ASC_HARDWARE_IMPENDING_FAILURE + ); + + sati_set_data_byte( + sequence, + scsi_io, + 9, + SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE + ); + } + else + { + sati_set_data_byte(sequence, scsi_io, 8, SCSI_ASC_NO_ADDITIONAL_SENSE); + sati_set_data_byte(sequence, scsi_io, 9, SCSI_ASCQ_NO_ADDITIONAL_SENSE); + } + //setting most recent temperature reading to 0xFF(not supported) for now. + sati_set_data_byte(sequence, scsi_io, 10, 0xFF); +} + +//****************************************************************************** +//* P U B L I C M E T H O D S +//****************************************************************************** + +/** + * @brief This method will translate the SCSI Log Sense command into ATA commands + * specified by SATv2. ATA commands Read Log EXT and SMART Read Log will + * be issued by this translation. + * + * @return SATI_STATUS Indicates if the command translation succeeded. + * + */ +SATI_STATUS sati_log_sense_translate_command( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * scsi_io, + void * ata_io +) +{ + U8 * cdb = sati_cb_get_cdb_address(scsi_io); + SATI_STATUS status = SATI_FAILURE; + + if(SATI_LOG_SENSE_GET_PC_FIELD(cdb) == 1 && + (sati_get_cdb_byte(cdb, 3) == 0)) + { + sequence->allocation_length = (sati_get_cdb_byte(cdb, 7) << 8) | + (sati_get_cdb_byte(cdb, 8)); + + switch(SATI_LOG_SENSE_GET_PAGE_CODE(cdb)) + { + //Return Supported Log Pages log page + case SCSI_LOG_PAGE_SUPPORTED_PAGES : + sati_supported_log_page_construct(sequence, scsi_io); + sequence->type = SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE; + status = SATI_COMPLETE; + break; + + //Return Self-Test Results log page + case SCSI_LOG_PAGE_SELF_TEST : + + if((sequence->device->capabilities & + SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT) == 0) + { + 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 + ); + status = SATI_FAILURE_CHECK_RESPONSE_DATA; + } + else + { + //check if 48-bit Address feature set is supported + if((sequence->device->capabilities & + SATI_DEVICE_CAP_48BIT_ENABLE)) + { + //ATA Read Log Ext with log address set to 0x07 + sati_ata_read_log_ext_construct( + ata_io, + sequence, + ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST, + sizeof(ATA_EXTENDED_SMART_SELF_TEST_LOG_T) + ); + sequence->type = + SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE; + status = SATI_SUCCESS; + } + else + { + //ATA Smart Read Log with log address set to 0x06 + sati_ata_smart_read_log_construct( + ata_io, + sequence, + ATA_LOG_PAGE_SMART_SELF_TEST, + sizeof(ATA_SMART_SELF_TEST_LOG_T) + ); + sequence->type = SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE; + status = SATI_SUCCESS; + } + } + break; + + //Return Informational Exceptions log page + case SCSI_LOG_PAGE_INFORMATION_EXCEPTION : + if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT) + { + if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE) + { + sati_ata_smart_return_status_construct( + ata_io, + sequence, + ATA_SMART_SUB_CMD_RETURN_STATUS + ); + sequence->type = + SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE; + status = SATI_SUCCESS; + } + else + { + sati_scsi_sense_data_construct( + sequence, + scsi_io, + SCSI_STATUS_CHECK_CONDITION, + SCSI_SENSE_ABORTED_COMMAND, + SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED, + SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED + ); + + status = SATI_FAILURE_CHECK_RESPONSE_DATA; + } + } + else + { + 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 + ); + + status = SATI_FAILURE_CHECK_RESPONSE_DATA; + } + break; + default : + //UNSPECIFIED SATv2r9 + sati_scsi_sense_data_construct( + sequence, + scsi_io, + SCSI_STATUS_CHECK_CONDITION, + SCSI_SENSE_ILLEGAL_REQUEST, + SCSI_ASC_NO_ADDITIONAL_SENSE , + SCSI_ASCQ_NO_ADDITIONAL_SENSE + ); + status = SATI_FAILURE_CHECK_RESPONSE_DATA; + break; + } + } + return status; +} + +/** + * @brief This method will translate the response to the SATI Log Sense + * translation. ATA command responses will be translated into the + * correct SCSI log pages to be returned by SATI. + * + * @return SATI_STATUS Indicates if the response translation succeeded. + * + */ +SATI_STATUS sati_log_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); + 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 + { + + void * ata_data = sati_cb_get_ata_data_address(ata_io); + + if(ata_data == NULL) + { + return SATI_FAILURE; + } + + switch(sequence->type) + { + case SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE: + sati_extended_self_test_log_page_construct( + sequence, scsi_io, ata_data + ); + + status = SATI_COMPLETE; + break; + + case SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE: + sati_self_test_log_page_construct(sequence, scsi_io, ata_data); + status = SATI_COMPLETE; + break; + + case SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE: + //This function needs a d->h register fis, not ata data + sati_information_exception_log_page_contruct( + sequence, scsi_io, ata_io + ); + + status = SATI_COMPLETE; + break; + + default: + 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; + break; + } + } + return status; +} + +#endif // !defined(DISABLE_SATI_LOG_SENSE) + |