diff options
Diffstat (limited to 'sys/dev/isci/scil/sati_inquiry.c')
-rw-r--r-- | sys/dev/isci/scil/sati_inquiry.c | 799 |
1 files changed, 799 insertions, 0 deletions
diff --git a/sys/dev/isci/scil/sati_inquiry.c b/sys/dev/isci/scil/sati_inquiry.c new file mode 100644 index 0000000..8da6325 --- /dev/null +++ b/sys/dev/isci/scil/sati_inquiry.c @@ -0,0 +1,799 @@ +/*- + * 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 implementations required to + * translate the SCSI inquiry command. + * The following (VPD) pages are currently supported: + * - Standard + * - Supported Pages + * - Unit Serial Number + * - Device Identification + */ + +#if !defined(DISABLE_SATI_INQUIRY) + +#include <dev/isci/scil/sati_inquiry.h> +#include <dev/isci/scil/sati_callbacks.h> +#include <dev/isci/scil/sati_util.h> +#include <dev/isci/scil/intel_ata.h> +#include <dev/isci/scil/intel_scsi.h> + +//****************************************************************************** +//* P R I V A T E M E T H O D S +//****************************************************************************** +/** +* @brief This method builds the SCSI data associated with the SATI product +* revision that is commonly used on the Standard inquiry response and +* the ATA information page. +* +* @param[in] sequence This parameter specifies the translator sequence +* object to be utilized during data translation. +* @param[in] ata_input_data This parameter specifies ata data received from +* the remote device. +* @param[out] scsi_io This parameter specifies the user IO request for +* which to construct the standard inquiry data. +* +* @return none +*/ +static +void sati_inquiry_construct_product_revision( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * ata_input_data, + void * scsi_io +) +{ + ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) + ata_input_data; + + // Fill in the product revision level field. + // Per SAT, copy portions of the firmware revision that is not filled + // with spaces. Some devices left-align their firmware rev ID, while + // others right-align. + if ( (identify->firmware_revision[4] == 0x20) + && (identify->firmware_revision[5] == 0x20) + && (identify->firmware_revision[6] == 0x20) + && (identify->firmware_revision[7] == 0x20) ) + { + sati_ata_identify_device_copy_data( + sequence, + scsi_io, + 32, + ata_input_data, + ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision), + 4, + TRUE + ); + } + else + { + // Since the last 4 bytes of the firmware revision are not spaces, + // utilize these bytes as the firmware revision in the inquiry data. + sati_ata_identify_device_copy_data( + sequence, + scsi_io, + 32, + ata_input_data, + ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision)+4, + 4, + TRUE + ); + } +} + + +//****************************************************************************** +//* P U B L I C M E T H O D S +//****************************************************************************** + +/** + * @brief This method builds the SCSI data associated with a SCSI standard + * inquiry request. + * + * @param[in] sequence This parameter specifies the translator sequence + * object to be utilized during data translation. + * @param[in] ata_input_data This parameter specifies ata data received from + * the remote device. + * @param[out] scsi_io This parameter specifies the user IO request for + * which to construct the standard inquiry data. + * + * @return none + */ +void sati_inquiry_standard_translate_data( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * ata_input_data, + void * scsi_io +) +{ + ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) + ata_input_data; + U32 index; + + // Device type is disk, attached to this lun. + sati_set_data_byte(sequence, scsi_io, 0, 0x00); + + // If the device indicates it's a removable media device, then set the + // RMB bit + if (identify->general_config_bits & ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE) + sati_set_data_byte(sequence, scsi_io, 1, 0x80); + else + sati_set_data_byte(sequence, scsi_io, 1, 0x00); + + sati_set_data_byte(sequence, scsi_io, 2, 0x05); // Indicate SPC-3 support + sati_set_data_byte(sequence, scsi_io, 3, 0x02); // Response Format SPC-3 + + sati_set_data_byte(sequence, scsi_io, 4, 62); // 62 Additional Data Bytes. + // n-4 per the spec, we end at + // byte 66, so 66-4. + sati_set_data_byte(sequence, scsi_io, 5, 0x00); + sati_set_data_byte(sequence, scsi_io, 6, 0x00); + sati_set_data_byte(sequence, scsi_io, 7, 0x02); // Enable Cmd Queueing + + // The Vender identification field is set to "ATA " + sati_set_data_byte(sequence, scsi_io, 8, 0x41); + sati_set_data_byte(sequence, scsi_io, 9, 0x54); + sati_set_data_byte(sequence, scsi_io, 10, 0x41); + sati_set_data_byte(sequence, scsi_io, 11, 0x20); + sati_set_data_byte(sequence, scsi_io, 12, 0x20); + sati_set_data_byte(sequence, scsi_io, 13, 0x20); + sati_set_data_byte(sequence, scsi_io, 14, 0x20); + sati_set_data_byte(sequence, scsi_io, 15, 0x20); + + // Fill in the product ID field. + sati_ata_identify_device_copy_data( + sequence, + scsi_io, + 16, + ata_input_data, + ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number), + 16, + TRUE + ); + + sati_inquiry_construct_product_revision( + sequence, + ata_input_data, + scsi_io + ); + + // Set the remaining fields up to the version descriptors to 0. + for (index = 36; index < 58; index++) + sati_set_data_byte(sequence, scsi_io, index, 0); + + // Add version descriptors for the various protocols in play. + + // SAM-4 + sati_set_data_byte(sequence, scsi_io, 58, 0); + sati_set_data_byte(sequence, scsi_io, 59, 0x80); + + // SAS-2 + sati_set_data_byte(sequence, scsi_io, 60, 0x0C); + sati_set_data_byte(sequence, scsi_io, 61, 0x20); + + // SPC-4 + sati_set_data_byte(sequence, scsi_io, 62, 0x04); + sati_set_data_byte(sequence, scsi_io, 63, 0x60); + + // SBC-3 + sati_set_data_byte(sequence, scsi_io, 64, 0x04); + sati_set_data_byte(sequence, scsi_io, 65, 0xC0); + + // ATA/ATAPI-8 ACS + sati_set_data_byte(sequence, scsi_io, 66, 0x16); + sati_set_data_byte(sequence, scsi_io, 67, 0x23); +} + +/** + * @brief This method builds the SCSI data associated with an SCSI inquiry + * for the supported VPD pages page. + * + * @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 supported VPD page information. + * + * @return none + */ +static +void sati_inquiry_supported_pages_translate_data( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * scsi_io +) +{ + // Formulate the SCSI output data for the caller. + sati_set_data_byte(sequence, scsi_io, 0, 0); // Qualifier and Device Type + sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE); + sati_set_data_byte(sequence, scsi_io, 2, 0); // Reserved. + sati_set_data_byte(sequence, scsi_io, 3, 4); // # VPD pages supported + sati_set_data_byte(sequence, scsi_io, 4, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE); + sati_set_data_byte(sequence, scsi_io, 5, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE); + sati_set_data_byte(sequence, scsi_io, 6, SCSI_INQUIRY_DEVICE_ID_PAGE); + sati_set_data_byte(sequence, scsi_io, 7, SCSI_INQUIRY_ATA_INFORMATION_PAGE); + sati_set_data_byte(sequence, scsi_io, 8, SCSI_INQUIRY_BLOCK_DEVICE_PAGE); + sati_set_data_byte(sequence, scsi_io, 9, 0); // End of the list +} + +/** + * @brief This method builds the SCSI data associated with a request for + * the unit serial number vital product data (VPD) page. + * + * @param[in] sequence This parameter specifies the translator sequence + * object to be utilized during data translation. + * @param[in] ata_input_data This parameter specifies ata data received from + * the remote device. + * @param[out] scsi_io This parameter specifies the user IO request for + * which to construct the unit serial number data. + * + * @return none + */ +void sati_inquiry_serial_number_translate_data( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * ata_input_data, + void * scsi_io +) +{ + // Peripheral qualifier (0x0, currently connected) + // Peripheral device type (0x0 direct-access block device) + sati_set_data_byte(sequence, scsi_io, 0, 0x00); + + sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE); + sati_set_data_byte(sequence, scsi_io, 2, 0x00); // Reserved + sati_set_data_byte(sequence, scsi_io, 3, ATA_IDENTIFY_SERIAL_NUMBER_LEN); + + sati_ata_identify_device_copy_data( + sequence, + scsi_io, + 4, + ata_input_data, + ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number), + ATA_IDENTIFY_SERIAL_NUMBER_LEN, + TRUE + ); +} + +/** +* @brief This method builds the SCSI data associated with a request for +* the Block Device Characteristics vital product data (VPD) page. +* +* @param[in] sequence This parameter specifies the translator sequence +* object to be utilized during data translation. +* @param[in] ata_input_data This parameter specifies ata data received from +* the remote device. +* @param[out] scsi_io This parameter specifies the user IO request for +* which to construct the unit serial number data. +* +* @return none +*/ +void sati_inquiry_block_device_translate_data( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * ata_input_data, + void * scsi_io +) +{ + ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) + ata_input_data; + + U32 offset; + + // Peripheral qualifier (0x0, currently connected) + // Peripheral device type (0x0 direct-access block device) + sati_set_data_byte(sequence, scsi_io, 0, 0x00); + + sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_BLOCK_DEVICE_PAGE); + + //PAGE LENGTH 0x003C + sati_set_data_byte(sequence, scsi_io, 2, 0x00); + sati_set_data_byte(sequence, scsi_io, 3, SCSI_INQUIRY_BLOCK_DEVICE_LENGTH); + + sati_ata_identify_device_copy_data( + sequence, + scsi_io, + 4, + ata_input_data, + ATA_IDENTIFY_DEVICE_GET_OFFSET(nominal_media_rotation_rate), + 2, + FALSE + ); + + sati_set_data_byte(sequence, scsi_io, 6, 0x00); + + sati_set_data_byte( + sequence, + scsi_io, + 7, + (identify->device_nominal_form_factor & 0x0F) // only need bits 0-3 + ); + + //bytes 8-63 are reserved + for(offset = 8; offset < 63; offset++) + { + sati_set_data_byte(sequence, scsi_io, offset, 0x00); + } +} + +/** + * @brief This method builds the SCSI data associated with a request for + * the device identification vital product data (VPD) page. + * + * @param[in] sequence This parameter specifies the translator sequence + * object to be utilized during data translation. + * @param[in] ata_input_data This parameter specifies ata data received from + * the remote device. + * @param[out] scsi_io This parameter specifies the user IO request for + * which to construct the device ID page. + * + * @return none + */ +void sati_inquiry_device_id_translate_data( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * ata_input_data, + void * scsi_io +) +{ + ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) + ata_input_data; + U16 byte_offset = 4; + U16 page_length; + + // Peripheral qualifier (0x0, currently connected) + // Peripheral device type (0x0 direct-access block device) + sati_set_data_byte(sequence, scsi_io, 0, 0x00); + + sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_DEVICE_ID_PAGE); + + /** + * If World Wide Names are supported by this target, then build an + * identification descriptor using the WWN. + */ + + if (identify->command_set_supported_extention + & ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE) + { + + sati_set_data_byte(sequence, + scsi_io, 4, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET + ); + + + sati_set_data_byte(sequence, + scsi_io, 5, SCSI_LUN_ASSOCIATION | SCSI_NAA_IDENTIFIER_TYPE + ); + + sati_set_data_byte(sequence, scsi_io, 6, 0); + sati_set_data_byte(sequence, scsi_io, 7, 0x08); // WWN are 8 bytes long + + // Copy data from the identify device world wide name field into the + // buffer. + sati_ata_identify_device_copy_data( + sequence, + scsi_io, + 8, + ata_input_data, + ATA_IDENTIFY_DEVICE_GET_OFFSET(world_wide_name), + ATA_IDENTIFY_WWN_LEN, + FALSE + ); + + byte_offset = 16; + } + + /** + * Build a identification descriptor using the model number & serial number. + */ + + sati_set_data_byte(sequence, + scsi_io, byte_offset, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_ASCII_CODE_SET + ); + byte_offset++; + sati_set_data_byte(sequence, + scsi_io, byte_offset, SCSI_LUN_ASSOCIATION | SCSI_T10_IDENTIFIER_TYPE + ); + byte_offset++; + sati_set_data_byte(sequence, scsi_io, byte_offset, 0); + byte_offset++; + + // Identifier length (8 bytes for "ATA " + 40 bytes from ATA IDENTIFY + // model number field + 20 bytes from ATA IDENTIFY serial number field. + sati_set_data_byte( + sequence, + scsi_io, + byte_offset, + 8 + (ATA_IDENTIFY_SERIAL_NUMBER_LEN) + (ATA_IDENTIFY_MODEL_NUMBER_LEN) + ); + byte_offset++; + + // Per SAT, write "ATA ". + sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41); + byte_offset++; + sati_set_data_byte(sequence, scsi_io, byte_offset, 0x54); + byte_offset++; + sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41); + byte_offset++; + sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); + byte_offset++; + sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); + byte_offset++; + sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); + byte_offset++; + sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); + byte_offset++; + sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); + byte_offset++; + + // Copy data from the identify device model number field into the + // buffer and update the byte_offset. + sati_ata_identify_device_copy_data( + sequence, + scsi_io, + byte_offset, + ata_input_data, + ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number), + ATA_IDENTIFY_MODEL_NUMBER_LEN, + TRUE + ); + + byte_offset += ATA_IDENTIFY_MODEL_NUMBER_LEN; + + // Copy data from the identify device serial number field into the + // buffer and update the byte_offset. + sati_ata_identify_device_copy_data( + sequence, + scsi_io, + byte_offset, + ata_input_data, + ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number), + ATA_IDENTIFY_SERIAL_NUMBER_LEN, + TRUE + ); + + byte_offset += ATA_IDENTIFY_SERIAL_NUMBER_LEN; + + /** + * If the target is contained in a SAS Domain, then build a target port + * ID descriptor using the SAS address. + */ + +#if defined(SATI_TRANSPORT_SUPPORTS_SAS) \ + && defined(DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT) + { + SCI_SAS_ADDRESS_T sas_address; + + sati_set_data_byte( + sequence, + scsi_io, + byte_offset, + SCSI_SAS_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET + ); + byte_offset++; + + sati_set_data_byte( + sequence, + scsi_io, + byte_offset, + SCSI_PIV_ENABLE | SCSI_TARGET_PORT_ASSOCIATION | + SCSI_NAA_IDENTIFIER_TYPE + ); + + byte_offset++; + sati_set_data_byte(sequence, scsi_io, byte_offset, 0); + byte_offset++; + sati_set_data_byte(sequence, scsi_io, byte_offset, 8); // SAS Addr=8 bytes + byte_offset++; + + sati_cb_device_get_sas_address(scsi_io, &sas_address); + + // Store the SAS address in the target port descriptor. + sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.high); + byte_offset += 4; + sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.low); + byte_offset += 4; + } +#endif // SATI_TRANSPORT_SUPPORTS_SAS && DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT + + /** + * Set the Page length field. The page length is n-3, where n is the + * last offset in the page (considered page length - 4). + */ + + page_length = byte_offset - 4; + sati_set_data_byte(sequence, scsi_io, 2, (U8)((page_length & 0xFF00) >> 8)); + sati_set_data_byte(sequence, scsi_io, 3, (U8)(page_length & 0x00FF)); +} + +/** +* @brief This method builds the SCSI data associated with a request for +* the ATA information vital product data (VPD) page. +* +* @param[in] sequence This parameter specifies the translator sequence +* object to be utilized during data translation. +* @param[in] ata_input_data This parameter specifies ata data received from +* a identify device command processed by the remote device. +* @param[out] scsi_io This parameter specifies the user IO request for +* which to construct the ATA information page. +* +* @return none +*/ +SATI_STATUS sati_inquiry_ata_information_translate_data( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * ata_input_data, + void * scsi_io +) +{ + sati_set_data_byte(sequence, scsi_io, 0, 0x00); + sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_ATA_INFORMATION_PAGE); + sati_set_data_byte(sequence, scsi_io, 2, 0x02); + sati_set_data_byte(sequence, scsi_io, 3, 0x38); + + //Reserved SAT2r07 + sati_set_data_byte(sequence, scsi_io, 4, 0x00); + sati_set_data_byte(sequence, scsi_io, 5, 0x00); + sati_set_data_byte(sequence, scsi_io, 6, 0x00); + sati_set_data_byte(sequence, scsi_io, 7, 0x00); + + // The Vender identification field is set to "ATA " + sati_set_data_byte(sequence, scsi_io, 8, 0x41); + sati_set_data_byte(sequence, scsi_io, 9, 0x54); + sati_set_data_byte(sequence, scsi_io, 10, 0x41); + sati_set_data_byte(sequence, scsi_io, 11, 0x20); + sati_set_data_byte(sequence, scsi_io, 12, 0x20); + sati_set_data_byte(sequence, scsi_io, 13, 0x20); + sati_set_data_byte(sequence, scsi_io, 14, 0x20); + sati_set_data_byte(sequence, scsi_io, 15, 0x20); + + //SAT Product identification + sati_ata_identify_device_copy_data( + sequence, + scsi_io, + 16, + ata_input_data, + ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number), + 16, + TRUE + ); + + //SAT Product Revision level bytes 32-35 + sati_inquiry_construct_product_revision( + sequence, + ata_input_data, + scsi_io + ); + + //skipping ATA device signature for now + + //Command code + sati_set_data_byte(sequence, scsi_io, 56, 0xEC); + + //Reserved SAT2r07 + sati_set_data_byte(sequence, scsi_io, 57, 0x00); + sati_set_data_byte(sequence, scsi_io, 58, 0x00); + sati_set_data_byte(sequence, scsi_io, 59, 0x00); + + //copy all ATA identify device data + sati_ata_identify_device_copy_data( + sequence, + scsi_io, + 60, + ata_input_data, + 0, + sizeof(ATA_IDENTIFY_DEVICE_DATA_T), + FALSE + ); + + //Need to send ATA Execute Device Diagnostic command still + sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; + + return SATI_SEQUENCE_INCOMPLETE; +} + +/** + * @brief This method will translate the inquiry SCSI command into + * an ATA IDENTIFY DEVICE command. It will handle several different + * VPD pages and the standard inquiry page. + * 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. + * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if + * the page isn't supported, or the page code + * field is not zero when the EVPD bit is 0. + */ +SATI_STATUS sati_inquiry_translate_command( + SATI_TRANSLATOR_SEQUENCE_T * sequence, + void * scsi_io, + void * ata_io +) +{ + U8 * cdb = sati_cb_get_cdb_address(scsi_io); + + /** + * SPC dictates: + * - that the page code field must be 0, if VPD enable is 0. + */ + if ( ((sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) == 0) + && (sati_get_cdb_byte(cdb, 2) != 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 + ); + return SATI_FAILURE_CHECK_RESPONSE_DATA; + } + + // Set the data length based on the allocation length field in the CDB. + sequence->allocation_length = (sati_get_cdb_byte(cdb, 3) << 8) | + (sati_get_cdb_byte(cdb, 4)); + + // Check to see if there was a request for the vital product data or just + // the standard inquiry. + if (sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) + { + // Parse the page code to determine which translator to invoke. + switch (sati_get_cdb_byte(cdb, 2)) + { + case SCSI_INQUIRY_SUPPORTED_PAGES_PAGE: + sequence->type = SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES; + sati_inquiry_supported_pages_translate_data(sequence, scsi_io); + return SATI_COMPLETE; + break; + + case SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE: + sequence->type = SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER; + break; + + case SCSI_INQUIRY_DEVICE_ID_PAGE: + sequence->type = SATI_SEQUENCE_INQUIRY_DEVICE_ID; + break; + + case SCSI_INQUIRY_ATA_INFORMATION_PAGE: + + if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE) + { + sati_ata_execute_device_diagnostic_construct( + ata_io, + sequence + ); + sequence->type = SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG; + } + else + { + sequence->type = SATI_SEQUENCE_INQUIRY_ATA_INFORMATION; + } + break; + + case SCSI_INQUIRY_BLOCK_DEVICE_PAGE: + sequence->type = SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE; + break; + + default: + 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; + break; + } + } + else + { + sequence->type = SATI_SEQUENCE_INQUIRY_STANDARD; + } + + sati_ata_identify_device_construct(ata_io, sequence); + + return SATI_SUCCESS; +} + +/** +* @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; +} + +#endif // !defined(DISABLE_SATI_INQUIRY) + |