1230557Sjimharris/*- 2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license. When using or 3230557Sjimharris * redistributing this file, you may do so under either license. 4230557Sjimharris * 5230557Sjimharris * GPL LICENSE SUMMARY 6230557Sjimharris * 7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8230557Sjimharris * 9230557Sjimharris * This program is free software; you can redistribute it and/or modify 10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as 11230557Sjimharris * published by the Free Software Foundation. 12230557Sjimharris * 13230557Sjimharris * This program is distributed in the hope that it will be useful, but 14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of 15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16230557Sjimharris * General Public License for more details. 17230557Sjimharris * 18230557Sjimharris * You should have received a copy of the GNU General Public License 19230557Sjimharris * along with this program; if not, write to the Free Software 20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21230557Sjimharris * The full GNU General Public License is included in this distribution 22230557Sjimharris * in the file called LICENSE.GPL. 23230557Sjimharris * 24230557Sjimharris * BSD LICENSE 25230557Sjimharris * 26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27230557Sjimharris * All rights reserved. 28230557Sjimharris * 29230557Sjimharris * Redistribution and use in source and binary forms, with or without 30230557Sjimharris * modification, are permitted provided that the following conditions 31230557Sjimharris * are met: 32230557Sjimharris * 33230557Sjimharris * * Redistributions of source code must retain the above copyright 34230557Sjimharris * notice, this list of conditions and the following disclaimer. 35230557Sjimharris * * Redistributions in binary form must reproduce the above copyright 36230557Sjimharris * notice, this list of conditions and the following disclaimer in 37230557Sjimharris * the documentation and/or other materials provided with the 38230557Sjimharris * distribution. 39230557Sjimharris * 40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51230557Sjimharris */ 52230557Sjimharris 53230557Sjimharris#include <sys/cdefs.h> 54230557Sjimharris__FBSDID("$FreeBSD$"); 55230557Sjimharris 56230557Sjimharris/** 57230557Sjimharris * @file 58230557Sjimharris * 59230557Sjimharris * @brief This file contains the method implementations required to 60230557Sjimharris * translate the SCSI inquiry command. 61230557Sjimharris * The following (VPD) pages are currently supported: 62230557Sjimharris * - Standard 63230557Sjimharris * - Supported Pages 64230557Sjimharris * - Unit Serial Number 65230557Sjimharris * - Device Identification 66230557Sjimharris */ 67230557Sjimharris 68230557Sjimharris#if !defined(DISABLE_SATI_INQUIRY) 69230557Sjimharris 70230557Sjimharris#include <dev/isci/scil/sati_inquiry.h> 71230557Sjimharris#include <dev/isci/scil/sati_callbacks.h> 72230557Sjimharris#include <dev/isci/scil/sati_util.h> 73230557Sjimharris#include <dev/isci/scil/intel_ata.h> 74230557Sjimharris#include <dev/isci/scil/intel_scsi.h> 75230557Sjimharris 76230557Sjimharris//****************************************************************************** 77230557Sjimharris//* P R I V A T E M E T H O D S 78230557Sjimharris//****************************************************************************** 79230557Sjimharris/** 80230557Sjimharris* @brief This method builds the SCSI data associated with the SATI product 81230557Sjimharris* revision that is commonly used on the Standard inquiry response and 82230557Sjimharris* the ATA information page. 83230557Sjimharris* 84230557Sjimharris* @param[in] sequence This parameter specifies the translator sequence 85230557Sjimharris* object to be utilized during data translation. 86230557Sjimharris* @param[in] ata_input_data This parameter specifies ata data received from 87230557Sjimharris* the remote device. 88230557Sjimharris* @param[out] scsi_io This parameter specifies the user IO request for 89230557Sjimharris* which to construct the standard inquiry data. 90230557Sjimharris* 91230557Sjimharris* @return none 92230557Sjimharris*/ 93230557Sjimharrisstatic 94230557Sjimharrisvoid sati_inquiry_construct_product_revision( 95230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 96230557Sjimharris void * ata_input_data, 97230557Sjimharris void * scsi_io 98230557Sjimharris) 99230557Sjimharris{ 100230557Sjimharris ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 101230557Sjimharris ata_input_data; 102230557Sjimharris 103230557Sjimharris // Fill in the product revision level field. 104230557Sjimharris // Per SAT, copy portions of the firmware revision that is not filled 105230557Sjimharris // with spaces. Some devices left-align their firmware rev ID, while 106230557Sjimharris // others right-align. 107230557Sjimharris if ( (identify->firmware_revision[4] == 0x20) 108230557Sjimharris && (identify->firmware_revision[5] == 0x20) 109230557Sjimharris && (identify->firmware_revision[6] == 0x20) 110230557Sjimharris && (identify->firmware_revision[7] == 0x20) ) 111230557Sjimharris { 112230557Sjimharris sati_ata_identify_device_copy_data( 113230557Sjimharris sequence, 114230557Sjimharris scsi_io, 115230557Sjimharris 32, 116230557Sjimharris ata_input_data, 117230557Sjimharris ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision), 118230557Sjimharris 4, 119230557Sjimharris TRUE 120230557Sjimharris ); 121230557Sjimharris } 122230557Sjimharris else 123230557Sjimharris { 124230557Sjimharris // Since the last 4 bytes of the firmware revision are not spaces, 125230557Sjimharris // utilize these bytes as the firmware revision in the inquiry data. 126230557Sjimharris sati_ata_identify_device_copy_data( 127230557Sjimharris sequence, 128230557Sjimharris scsi_io, 129230557Sjimharris 32, 130230557Sjimharris ata_input_data, 131230557Sjimharris ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision)+4, 132230557Sjimharris 4, 133230557Sjimharris TRUE 134230557Sjimharris ); 135230557Sjimharris } 136230557Sjimharris} 137230557Sjimharris 138230557Sjimharris 139230557Sjimharris//****************************************************************************** 140230557Sjimharris//* P U B L I C M E T H O D S 141230557Sjimharris//****************************************************************************** 142230557Sjimharris 143230557Sjimharris/** 144230557Sjimharris * @brief This method builds the SCSI data associated with a SCSI standard 145230557Sjimharris * inquiry request. 146230557Sjimharris * 147230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 148230557Sjimharris * object to be utilized during data translation. 149230557Sjimharris * @param[in] ata_input_data This parameter specifies ata data received from 150230557Sjimharris * the remote device. 151230557Sjimharris * @param[out] scsi_io This parameter specifies the user IO request for 152230557Sjimharris * which to construct the standard inquiry data. 153230557Sjimharris * 154230557Sjimharris * @return none 155230557Sjimharris */ 156230557Sjimharrisvoid sati_inquiry_standard_translate_data( 157230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 158230557Sjimharris void * ata_input_data, 159230557Sjimharris void * scsi_io 160230557Sjimharris) 161230557Sjimharris{ 162230557Sjimharris ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 163230557Sjimharris ata_input_data; 164230557Sjimharris U32 index; 165230557Sjimharris 166230557Sjimharris // Device type is disk, attached to this lun. 167230557Sjimharris sati_set_data_byte(sequence, scsi_io, 0, 0x00); 168230557Sjimharris 169230557Sjimharris // If the device indicates it's a removable media device, then set the 170230557Sjimharris // RMB bit 171230557Sjimharris if (identify->general_config_bits & ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE) 172230557Sjimharris sati_set_data_byte(sequence, scsi_io, 1, 0x80); 173230557Sjimharris else 174230557Sjimharris sati_set_data_byte(sequence, scsi_io, 1, 0x00); 175230557Sjimharris 176230557Sjimharris sati_set_data_byte(sequence, scsi_io, 2, 0x05); // Indicate SPC-3 support 177230557Sjimharris sati_set_data_byte(sequence, scsi_io, 3, 0x02); // Response Format SPC-3 178230557Sjimharris 179230557Sjimharris sati_set_data_byte(sequence, scsi_io, 4, 62); // 62 Additional Data Bytes. 180230557Sjimharris // n-4 per the spec, we end at 181230557Sjimharris // byte 66, so 66-4. 182230557Sjimharris sati_set_data_byte(sequence, scsi_io, 5, 0x00); 183230557Sjimharris sati_set_data_byte(sequence, scsi_io, 6, 0x00); 184230557Sjimharris sati_set_data_byte(sequence, scsi_io, 7, 0x02); // Enable Cmd Queueing 185230557Sjimharris 186230557Sjimharris // The Vender identification field is set to "ATA " 187230557Sjimharris sati_set_data_byte(sequence, scsi_io, 8, 0x41); 188230557Sjimharris sati_set_data_byte(sequence, scsi_io, 9, 0x54); 189230557Sjimharris sati_set_data_byte(sequence, scsi_io, 10, 0x41); 190230557Sjimharris sati_set_data_byte(sequence, scsi_io, 11, 0x20); 191230557Sjimharris sati_set_data_byte(sequence, scsi_io, 12, 0x20); 192230557Sjimharris sati_set_data_byte(sequence, scsi_io, 13, 0x20); 193230557Sjimharris sati_set_data_byte(sequence, scsi_io, 14, 0x20); 194230557Sjimharris sati_set_data_byte(sequence, scsi_io, 15, 0x20); 195230557Sjimharris 196230557Sjimharris // Fill in the product ID field. 197230557Sjimharris sati_ata_identify_device_copy_data( 198230557Sjimharris sequence, 199230557Sjimharris scsi_io, 200230557Sjimharris 16, 201230557Sjimharris ata_input_data, 202230557Sjimharris ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number), 203230557Sjimharris 16, 204230557Sjimharris TRUE 205230557Sjimharris ); 206230557Sjimharris 207230557Sjimharris sati_inquiry_construct_product_revision( 208230557Sjimharris sequence, 209230557Sjimharris ata_input_data, 210230557Sjimharris scsi_io 211230557Sjimharris ); 212230557Sjimharris 213230557Sjimharris // Set the remaining fields up to the version descriptors to 0. 214230557Sjimharris for (index = 36; index < 58; index++) 215230557Sjimharris sati_set_data_byte(sequence, scsi_io, index, 0); 216230557Sjimharris 217230557Sjimharris // Add version descriptors for the various protocols in play. 218230557Sjimharris 219230557Sjimharris // SAM-4 220230557Sjimharris sati_set_data_byte(sequence, scsi_io, 58, 0); 221230557Sjimharris sati_set_data_byte(sequence, scsi_io, 59, 0x80); 222230557Sjimharris 223230557Sjimharris // SAS-2 224230557Sjimharris sati_set_data_byte(sequence, scsi_io, 60, 0x0C); 225230557Sjimharris sati_set_data_byte(sequence, scsi_io, 61, 0x20); 226230557Sjimharris 227230557Sjimharris // SPC-4 228230557Sjimharris sati_set_data_byte(sequence, scsi_io, 62, 0x04); 229230557Sjimharris sati_set_data_byte(sequence, scsi_io, 63, 0x60); 230230557Sjimharris 231230557Sjimharris // SBC-3 232230557Sjimharris sati_set_data_byte(sequence, scsi_io, 64, 0x04); 233230557Sjimharris sati_set_data_byte(sequence, scsi_io, 65, 0xC0); 234230557Sjimharris 235230557Sjimharris // ATA/ATAPI-8 ACS 236230557Sjimharris sati_set_data_byte(sequence, scsi_io, 66, 0x16); 237230557Sjimharris sati_set_data_byte(sequence, scsi_io, 67, 0x23); 238230557Sjimharris} 239230557Sjimharris 240230557Sjimharris/** 241230557Sjimharris * @brief This method builds the SCSI data associated with an SCSI inquiry 242230557Sjimharris * for the supported VPD pages page. 243230557Sjimharris * 244230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 245230557Sjimharris * object to be utilized during data translation. 246230557Sjimharris * @param[out] scsi_io This parameter specifies the user IO request for 247230557Sjimharris * which to construct the supported VPD page information. 248230557Sjimharris * 249230557Sjimharris * @return none 250230557Sjimharris */ 251230557Sjimharrisstatic 252230557Sjimharrisvoid sati_inquiry_supported_pages_translate_data( 253230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 254230557Sjimharris void * scsi_io 255230557Sjimharris) 256230557Sjimharris{ 257230557Sjimharris // Formulate the SCSI output data for the caller. 258230557Sjimharris sati_set_data_byte(sequence, scsi_io, 0, 0); // Qualifier and Device Type 259230557Sjimharris sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE); 260230557Sjimharris sati_set_data_byte(sequence, scsi_io, 2, 0); // Reserved. 261230557Sjimharris sati_set_data_byte(sequence, scsi_io, 3, 4); // # VPD pages supported 262230557Sjimharris sati_set_data_byte(sequence, scsi_io, 4, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE); 263230557Sjimharris sati_set_data_byte(sequence, scsi_io, 5, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE); 264230557Sjimharris sati_set_data_byte(sequence, scsi_io, 6, SCSI_INQUIRY_DEVICE_ID_PAGE); 265230557Sjimharris sati_set_data_byte(sequence, scsi_io, 7, SCSI_INQUIRY_ATA_INFORMATION_PAGE); 266230557Sjimharris sati_set_data_byte(sequence, scsi_io, 8, SCSI_INQUIRY_BLOCK_DEVICE_PAGE); 267230557Sjimharris sati_set_data_byte(sequence, scsi_io, 9, 0); // End of the list 268230557Sjimharris} 269230557Sjimharris 270230557Sjimharris/** 271230557Sjimharris * @brief This method builds the SCSI data associated with a request for 272230557Sjimharris * the unit serial number vital product data (VPD) page. 273230557Sjimharris * 274230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 275230557Sjimharris * object to be utilized during data translation. 276230557Sjimharris * @param[in] ata_input_data This parameter specifies ata data received from 277230557Sjimharris * the remote device. 278230557Sjimharris * @param[out] scsi_io This parameter specifies the user IO request for 279230557Sjimharris * which to construct the unit serial number data. 280230557Sjimharris * 281230557Sjimharris * @return none 282230557Sjimharris */ 283230557Sjimharrisvoid sati_inquiry_serial_number_translate_data( 284230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 285230557Sjimharris void * ata_input_data, 286230557Sjimharris void * scsi_io 287230557Sjimharris) 288230557Sjimharris{ 289230557Sjimharris // Peripheral qualifier (0x0, currently connected) 290230557Sjimharris // Peripheral device type (0x0 direct-access block device) 291230557Sjimharris sati_set_data_byte(sequence, scsi_io, 0, 0x00); 292230557Sjimharris 293230557Sjimharris sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE); 294230557Sjimharris sati_set_data_byte(sequence, scsi_io, 2, 0x00); // Reserved 295230557Sjimharris sati_set_data_byte(sequence, scsi_io, 3, ATA_IDENTIFY_SERIAL_NUMBER_LEN); 296230557Sjimharris 297230557Sjimharris sati_ata_identify_device_copy_data( 298230557Sjimharris sequence, 299230557Sjimharris scsi_io, 300230557Sjimharris 4, 301230557Sjimharris ata_input_data, 302230557Sjimharris ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number), 303230557Sjimharris ATA_IDENTIFY_SERIAL_NUMBER_LEN, 304230557Sjimharris TRUE 305230557Sjimharris ); 306230557Sjimharris} 307230557Sjimharris 308230557Sjimharris/** 309230557Sjimharris* @brief This method builds the SCSI data associated with a request for 310230557Sjimharris* the Block Device Characteristics vital product data (VPD) page. 311230557Sjimharris* 312230557Sjimharris* @param[in] sequence This parameter specifies the translator sequence 313230557Sjimharris* object to be utilized during data translation. 314230557Sjimharris* @param[in] ata_input_data This parameter specifies ata data received from 315230557Sjimharris* the remote device. 316230557Sjimharris* @param[out] scsi_io This parameter specifies the user IO request for 317230557Sjimharris* which to construct the unit serial number data. 318230557Sjimharris* 319230557Sjimharris* @return none 320230557Sjimharris*/ 321230557Sjimharrisvoid sati_inquiry_block_device_translate_data( 322230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 323230557Sjimharris void * ata_input_data, 324230557Sjimharris void * scsi_io 325230557Sjimharris) 326230557Sjimharris{ 327230557Sjimharris ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 328230557Sjimharris ata_input_data; 329230557Sjimharris 330230557Sjimharris U32 offset; 331230557Sjimharris 332230557Sjimharris // Peripheral qualifier (0x0, currently connected) 333230557Sjimharris // Peripheral device type (0x0 direct-access block device) 334230557Sjimharris sati_set_data_byte(sequence, scsi_io, 0, 0x00); 335230557Sjimharris 336230557Sjimharris sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_BLOCK_DEVICE_PAGE); 337230557Sjimharris 338230557Sjimharris //PAGE LENGTH 0x003C 339230557Sjimharris sati_set_data_byte(sequence, scsi_io, 2, 0x00); 340230557Sjimharris sati_set_data_byte(sequence, scsi_io, 3, SCSI_INQUIRY_BLOCK_DEVICE_LENGTH); 341230557Sjimharris 342230557Sjimharris sati_ata_identify_device_copy_data( 343230557Sjimharris sequence, 344230557Sjimharris scsi_io, 345230557Sjimharris 4, 346230557Sjimharris ata_input_data, 347230557Sjimharris ATA_IDENTIFY_DEVICE_GET_OFFSET(nominal_media_rotation_rate), 348230557Sjimharris 2, 349230557Sjimharris FALSE 350230557Sjimharris ); 351230557Sjimharris 352230557Sjimharris sati_set_data_byte(sequence, scsi_io, 6, 0x00); 353230557Sjimharris 354230557Sjimharris sati_set_data_byte( 355230557Sjimharris sequence, 356230557Sjimharris scsi_io, 357230557Sjimharris 7, 358230557Sjimharris (identify->device_nominal_form_factor & 0x0F) // only need bits 0-3 359230557Sjimharris ); 360230557Sjimharris 361230557Sjimharris //bytes 8-63 are reserved 362235043Sjimharris for(offset = 8; offset < 64; offset++) 363230557Sjimharris { 364230557Sjimharris sati_set_data_byte(sequence, scsi_io, offset, 0x00); 365230557Sjimharris } 366230557Sjimharris} 367230557Sjimharris 368230557Sjimharris/** 369230557Sjimharris * @brief This method builds the SCSI data associated with a request for 370230557Sjimharris * the device identification vital product data (VPD) page. 371230557Sjimharris * 372230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 373230557Sjimharris * object to be utilized during data translation. 374230557Sjimharris * @param[in] ata_input_data This parameter specifies ata data received from 375230557Sjimharris * the remote device. 376230557Sjimharris * @param[out] scsi_io This parameter specifies the user IO request for 377230557Sjimharris * which to construct the device ID page. 378230557Sjimharris * 379230557Sjimharris * @return none 380230557Sjimharris */ 381230557Sjimharrisvoid sati_inquiry_device_id_translate_data( 382230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 383230557Sjimharris void * ata_input_data, 384230557Sjimharris void * scsi_io 385230557Sjimharris) 386230557Sjimharris{ 387230557Sjimharris ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 388230557Sjimharris ata_input_data; 389230557Sjimharris U16 byte_offset = 4; 390230557Sjimharris U16 page_length; 391230557Sjimharris 392230557Sjimharris // Peripheral qualifier (0x0, currently connected) 393230557Sjimharris // Peripheral device type (0x0 direct-access block device) 394230557Sjimharris sati_set_data_byte(sequence, scsi_io, 0, 0x00); 395230557Sjimharris 396230557Sjimharris sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_DEVICE_ID_PAGE); 397230557Sjimharris 398230557Sjimharris /** 399230557Sjimharris * If World Wide Names are supported by this target, then build an 400230557Sjimharris * identification descriptor using the WWN. 401230557Sjimharris */ 402230557Sjimharris 403230557Sjimharris if (identify->command_set_supported_extention 404230557Sjimharris & ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE) 405230557Sjimharris { 406230557Sjimharris 407230557Sjimharris sati_set_data_byte(sequence, 408230557Sjimharris scsi_io, 4, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET 409230557Sjimharris ); 410230557Sjimharris 411230557Sjimharris 412230557Sjimharris sati_set_data_byte(sequence, 413230557Sjimharris scsi_io, 5, SCSI_LUN_ASSOCIATION | SCSI_NAA_IDENTIFIER_TYPE 414230557Sjimharris ); 415230557Sjimharris 416230557Sjimharris sati_set_data_byte(sequence, scsi_io, 6, 0); 417230557Sjimharris sati_set_data_byte(sequence, scsi_io, 7, 0x08); // WWN are 8 bytes long 418230557Sjimharris 419230557Sjimharris // Copy data from the identify device world wide name field into the 420230557Sjimharris // buffer. 421230557Sjimharris sati_ata_identify_device_copy_data( 422230557Sjimharris sequence, 423230557Sjimharris scsi_io, 424230557Sjimharris 8, 425230557Sjimharris ata_input_data, 426230557Sjimharris ATA_IDENTIFY_DEVICE_GET_OFFSET(world_wide_name), 427230557Sjimharris ATA_IDENTIFY_WWN_LEN, 428230557Sjimharris FALSE 429230557Sjimharris ); 430230557Sjimharris 431230557Sjimharris byte_offset = 16; 432230557Sjimharris } 433230557Sjimharris 434230557Sjimharris /** 435230557Sjimharris * Build a identification descriptor using the model number & serial number. 436230557Sjimharris */ 437230557Sjimharris 438230557Sjimharris sati_set_data_byte(sequence, 439230557Sjimharris scsi_io, byte_offset, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_ASCII_CODE_SET 440230557Sjimharris ); 441230557Sjimharris byte_offset++; 442230557Sjimharris sati_set_data_byte(sequence, 443230557Sjimharris scsi_io, byte_offset, SCSI_LUN_ASSOCIATION | SCSI_T10_IDENTIFIER_TYPE 444230557Sjimharris ); 445230557Sjimharris byte_offset++; 446230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 0); 447230557Sjimharris byte_offset++; 448230557Sjimharris 449230557Sjimharris // Identifier length (8 bytes for "ATA " + 40 bytes from ATA IDENTIFY 450230557Sjimharris // model number field + 20 bytes from ATA IDENTIFY serial number field. 451230557Sjimharris sati_set_data_byte( 452230557Sjimharris sequence, 453230557Sjimharris scsi_io, 454230557Sjimharris byte_offset, 455230557Sjimharris 8 + (ATA_IDENTIFY_SERIAL_NUMBER_LEN) + (ATA_IDENTIFY_MODEL_NUMBER_LEN) 456230557Sjimharris ); 457230557Sjimharris byte_offset++; 458230557Sjimharris 459230557Sjimharris // Per SAT, write "ATA ". 460230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41); 461230557Sjimharris byte_offset++; 462230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 0x54); 463230557Sjimharris byte_offset++; 464230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41); 465230557Sjimharris byte_offset++; 466230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); 467230557Sjimharris byte_offset++; 468230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); 469230557Sjimharris byte_offset++; 470230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); 471230557Sjimharris byte_offset++; 472230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); 473230557Sjimharris byte_offset++; 474230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); 475230557Sjimharris byte_offset++; 476230557Sjimharris 477230557Sjimharris // Copy data from the identify device model number field into the 478230557Sjimharris // buffer and update the byte_offset. 479230557Sjimharris sati_ata_identify_device_copy_data( 480230557Sjimharris sequence, 481230557Sjimharris scsi_io, 482230557Sjimharris byte_offset, 483230557Sjimharris ata_input_data, 484230557Sjimharris ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number), 485230557Sjimharris ATA_IDENTIFY_MODEL_NUMBER_LEN, 486230557Sjimharris TRUE 487230557Sjimharris ); 488230557Sjimharris 489230557Sjimharris byte_offset += ATA_IDENTIFY_MODEL_NUMBER_LEN; 490230557Sjimharris 491230557Sjimharris // Copy data from the identify device serial number field into the 492230557Sjimharris // buffer and update the byte_offset. 493230557Sjimharris sati_ata_identify_device_copy_data( 494230557Sjimharris sequence, 495230557Sjimharris scsi_io, 496230557Sjimharris byte_offset, 497230557Sjimharris ata_input_data, 498230557Sjimharris ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number), 499230557Sjimharris ATA_IDENTIFY_SERIAL_NUMBER_LEN, 500230557Sjimharris TRUE 501230557Sjimharris ); 502230557Sjimharris 503230557Sjimharris byte_offset += ATA_IDENTIFY_SERIAL_NUMBER_LEN; 504230557Sjimharris 505230557Sjimharris /** 506230557Sjimharris * If the target is contained in a SAS Domain, then build a target port 507230557Sjimharris * ID descriptor using the SAS address. 508230557Sjimharris */ 509230557Sjimharris 510230557Sjimharris#if defined(SATI_TRANSPORT_SUPPORTS_SAS) \ 511230557Sjimharris && defined(DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT) 512230557Sjimharris { 513230557Sjimharris SCI_SAS_ADDRESS_T sas_address; 514230557Sjimharris 515230557Sjimharris sati_set_data_byte( 516230557Sjimharris sequence, 517230557Sjimharris scsi_io, 518230557Sjimharris byte_offset, 519230557Sjimharris SCSI_SAS_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET 520230557Sjimharris ); 521230557Sjimharris byte_offset++; 522230557Sjimharris 523230557Sjimharris sati_set_data_byte( 524230557Sjimharris sequence, 525230557Sjimharris scsi_io, 526230557Sjimharris byte_offset, 527230557Sjimharris SCSI_PIV_ENABLE | SCSI_TARGET_PORT_ASSOCIATION | 528230557Sjimharris SCSI_NAA_IDENTIFIER_TYPE 529230557Sjimharris ); 530230557Sjimharris 531230557Sjimharris byte_offset++; 532230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 0); 533230557Sjimharris byte_offset++; 534230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, 8); // SAS Addr=8 bytes 535230557Sjimharris byte_offset++; 536230557Sjimharris 537230557Sjimharris sati_cb_device_get_sas_address(scsi_io, &sas_address); 538230557Sjimharris 539230557Sjimharris // Store the SAS address in the target port descriptor. 540230557Sjimharris sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.high); 541230557Sjimharris byte_offset += 4; 542230557Sjimharris sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.low); 543230557Sjimharris byte_offset += 4; 544230557Sjimharris } 545230557Sjimharris#endif // SATI_TRANSPORT_SUPPORTS_SAS && DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT 546230557Sjimharris 547230557Sjimharris /** 548230557Sjimharris * Set the Page length field. The page length is n-3, where n is the 549230557Sjimharris * last offset in the page (considered page length - 4). 550230557Sjimharris */ 551230557Sjimharris 552230557Sjimharris page_length = byte_offset - 4; 553230557Sjimharris sati_set_data_byte(sequence, scsi_io, 2, (U8)((page_length & 0xFF00) >> 8)); 554230557Sjimharris sati_set_data_byte(sequence, scsi_io, 3, (U8)(page_length & 0x00FF)); 555230557Sjimharris} 556230557Sjimharris 557230557Sjimharris/** 558230557Sjimharris* @brief This method builds the SCSI data associated with a request for 559230557Sjimharris* the ATA information vital product data (VPD) page. 560230557Sjimharris* 561230557Sjimharris* @param[in] sequence This parameter specifies the translator sequence 562230557Sjimharris* object to be utilized during data translation. 563230557Sjimharris* @param[in] ata_input_data This parameter specifies ata data received from 564230557Sjimharris* a identify device command processed by the remote device. 565230557Sjimharris* @param[out] scsi_io This parameter specifies the user IO request for 566230557Sjimharris* which to construct the ATA information page. 567230557Sjimharris* 568230557Sjimharris* @return none 569230557Sjimharris*/ 570230557SjimharrisSATI_STATUS sati_inquiry_ata_information_translate_data( 571230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 572230557Sjimharris void * ata_input_data, 573230557Sjimharris void * scsi_io 574230557Sjimharris) 575230557Sjimharris{ 576230557Sjimharris sati_set_data_byte(sequence, scsi_io, 0, 0x00); 577230557Sjimharris sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_ATA_INFORMATION_PAGE); 578230557Sjimharris sati_set_data_byte(sequence, scsi_io, 2, 0x02); 579230557Sjimharris sati_set_data_byte(sequence, scsi_io, 3, 0x38); 580230557Sjimharris 581230557Sjimharris //Reserved SAT2r07 582230557Sjimharris sati_set_data_byte(sequence, scsi_io, 4, 0x00); 583230557Sjimharris sati_set_data_byte(sequence, scsi_io, 5, 0x00); 584230557Sjimharris sati_set_data_byte(sequence, scsi_io, 6, 0x00); 585230557Sjimharris sati_set_data_byte(sequence, scsi_io, 7, 0x00); 586230557Sjimharris 587230557Sjimharris // The Vender identification field is set to "ATA " 588230557Sjimharris sati_set_data_byte(sequence, scsi_io, 8, 0x41); 589230557Sjimharris sati_set_data_byte(sequence, scsi_io, 9, 0x54); 590230557Sjimharris sati_set_data_byte(sequence, scsi_io, 10, 0x41); 591230557Sjimharris sati_set_data_byte(sequence, scsi_io, 11, 0x20); 592230557Sjimharris sati_set_data_byte(sequence, scsi_io, 12, 0x20); 593230557Sjimharris sati_set_data_byte(sequence, scsi_io, 13, 0x20); 594230557Sjimharris sati_set_data_byte(sequence, scsi_io, 14, 0x20); 595230557Sjimharris sati_set_data_byte(sequence, scsi_io, 15, 0x20); 596230557Sjimharris 597230557Sjimharris //SAT Product identification 598230557Sjimharris sati_ata_identify_device_copy_data( 599230557Sjimharris sequence, 600230557Sjimharris scsi_io, 601230557Sjimharris 16, 602230557Sjimharris ata_input_data, 603230557Sjimharris ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number), 604230557Sjimharris 16, 605230557Sjimharris TRUE 606230557Sjimharris ); 607230557Sjimharris 608230557Sjimharris //SAT Product Revision level bytes 32-35 609230557Sjimharris sati_inquiry_construct_product_revision( 610230557Sjimharris sequence, 611230557Sjimharris ata_input_data, 612230557Sjimharris scsi_io 613230557Sjimharris ); 614230557Sjimharris 615230557Sjimharris //skipping ATA device signature for now 616230557Sjimharris 617230557Sjimharris //Command code 618230557Sjimharris sati_set_data_byte(sequence, scsi_io, 56, 0xEC); 619230557Sjimharris 620230557Sjimharris //Reserved SAT2r07 621230557Sjimharris sati_set_data_byte(sequence, scsi_io, 57, 0x00); 622230557Sjimharris sati_set_data_byte(sequence, scsi_io, 58, 0x00); 623230557Sjimharris sati_set_data_byte(sequence, scsi_io, 59, 0x00); 624230557Sjimharris 625230557Sjimharris //copy all ATA identify device data 626230557Sjimharris sati_ata_identify_device_copy_data( 627230557Sjimharris sequence, 628230557Sjimharris scsi_io, 629230557Sjimharris 60, 630230557Sjimharris ata_input_data, 631230557Sjimharris 0, 632230557Sjimharris sizeof(ATA_IDENTIFY_DEVICE_DATA_T), 633230557Sjimharris FALSE 634230557Sjimharris ); 635230557Sjimharris 636230557Sjimharris //Need to send ATA Execute Device Diagnostic command still 637230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 638230557Sjimharris 639230557Sjimharris return SATI_SEQUENCE_INCOMPLETE; 640230557Sjimharris} 641230557Sjimharris 642230557Sjimharris/** 643230557Sjimharris * @brief This method will translate the inquiry SCSI command into 644230557Sjimharris * an ATA IDENTIFY DEVICE command. It will handle several different 645230557Sjimharris * VPD pages and the standard inquiry page. 646230557Sjimharris * For more information on the parameters passed to this method, 647230557Sjimharris * please reference sati_translate_command(). 648230557Sjimharris * 649230557Sjimharris * @return Indicate if the command translation succeeded. 650230557Sjimharris * @retval SCI_SUCCESS This is returned if the command translation was 651230557Sjimharris * successful. 652230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 653230557Sjimharris * the page isn't supported, or the page code 654230557Sjimharris * field is not zero when the EVPD bit is 0. 655230557Sjimharris */ 656230557SjimharrisSATI_STATUS sati_inquiry_translate_command( 657230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 658230557Sjimharris void * scsi_io, 659230557Sjimharris void * ata_io 660230557Sjimharris) 661230557Sjimharris{ 662230557Sjimharris U8 * cdb = sati_cb_get_cdb_address(scsi_io); 663230557Sjimharris 664230557Sjimharris /** 665230557Sjimharris * SPC dictates: 666230557Sjimharris * - that the page code field must be 0, if VPD enable is 0. 667230557Sjimharris */ 668230557Sjimharris if ( ((sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) == 0) 669230557Sjimharris && (sati_get_cdb_byte(cdb, 2) != 0) ) 670230557Sjimharris { 671230557Sjimharris sati_scsi_sense_data_construct( 672230557Sjimharris sequence, 673230557Sjimharris scsi_io, 674230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 675230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 676230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_CDB, 677230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_CDB 678230557Sjimharris ); 679230557Sjimharris return SATI_FAILURE_CHECK_RESPONSE_DATA; 680230557Sjimharris } 681230557Sjimharris 682230557Sjimharris // Set the data length based on the allocation length field in the CDB. 683230557Sjimharris sequence->allocation_length = (sati_get_cdb_byte(cdb, 3) << 8) | 684230557Sjimharris (sati_get_cdb_byte(cdb, 4)); 685230557Sjimharris 686230557Sjimharris // Check to see if there was a request for the vital product data or just 687230557Sjimharris // the standard inquiry. 688230557Sjimharris if (sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) 689230557Sjimharris { 690230557Sjimharris // Parse the page code to determine which translator to invoke. 691230557Sjimharris switch (sati_get_cdb_byte(cdb, 2)) 692230557Sjimharris { 693230557Sjimharris case SCSI_INQUIRY_SUPPORTED_PAGES_PAGE: 694230557Sjimharris sequence->type = SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES; 695230557Sjimharris sati_inquiry_supported_pages_translate_data(sequence, scsi_io); 696230557Sjimharris return SATI_COMPLETE; 697230557Sjimharris break; 698230557Sjimharris 699230557Sjimharris case SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE: 700230557Sjimharris sequence->type = SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER; 701230557Sjimharris break; 702230557Sjimharris 703230557Sjimharris case SCSI_INQUIRY_DEVICE_ID_PAGE: 704230557Sjimharris sequence->type = SATI_SEQUENCE_INQUIRY_DEVICE_ID; 705230557Sjimharris break; 706230557Sjimharris 707230557Sjimharris case SCSI_INQUIRY_ATA_INFORMATION_PAGE: 708230557Sjimharris 709230557Sjimharris if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE) 710230557Sjimharris { 711230557Sjimharris sati_ata_execute_device_diagnostic_construct( 712230557Sjimharris ata_io, 713230557Sjimharris sequence 714230557Sjimharris ); 715230557Sjimharris sequence->type = SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG; 716230557Sjimharris } 717230557Sjimharris else 718230557Sjimharris { 719230557Sjimharris sequence->type = SATI_SEQUENCE_INQUIRY_ATA_INFORMATION; 720230557Sjimharris } 721230557Sjimharris break; 722230557Sjimharris 723230557Sjimharris case SCSI_INQUIRY_BLOCK_DEVICE_PAGE: 724230557Sjimharris sequence->type = SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE; 725230557Sjimharris break; 726230557Sjimharris 727230557Sjimharris default: 728230557Sjimharris sati_scsi_sense_data_construct( 729230557Sjimharris sequence, 730230557Sjimharris scsi_io, 731230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 732230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 733230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_CDB, 734230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_CDB 735230557Sjimharris ); 736230557Sjimharris return SATI_FAILURE_CHECK_RESPONSE_DATA; 737230557Sjimharris break; 738230557Sjimharris } 739230557Sjimharris } 740230557Sjimharris else 741230557Sjimharris { 742230557Sjimharris sequence->type = SATI_SEQUENCE_INQUIRY_STANDARD; 743230557Sjimharris } 744230557Sjimharris 745230557Sjimharris sati_ata_identify_device_construct(ata_io, sequence); 746230557Sjimharris 747230557Sjimharris return SATI_SUCCESS; 748230557Sjimharris} 749230557Sjimharris 750230557Sjimharris/** 751230557Sjimharris* @brief This method finishes the construction of the SCSI data associated 752230557Sjimharris with a request for the ATA information vital product data (VPD) page. 753230557Sjimharris The ATA device signature is written into the data response from the 754230557Sjimharris task fle registers after issuing a Execute Device Diagnostic command. 755230557Sjimharris* 756230557Sjimharris* @param[in] sequence This parameter specifies the translator sequence 757230557Sjimharris* object to be utilized during data translation. 758230557Sjimharris* @param[out] scsi_io This parameter specifies the user IO request for 759230557Sjimharris* which to construct the ATA information page. 760230557Sjimharris* @param[in] ata_io This parameter specifies the ATA payload 761230557Sjimharris* buffer location and size to be translated. 762230557Sjimharris* 763230557Sjimharris* @return none 764230557Sjimharris*/ 765230557Sjimharrisvoid sati_inquiry_ata_information_finish_translation( 766230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 767230557Sjimharris void * scsi_io, 768230557Sjimharris void * ata_io 769230557Sjimharris) 770230557Sjimharris{ 771230557Sjimharris U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 772230557Sjimharris U32 offset; 773230557Sjimharris 774230557Sjimharris //SATA transport 775230557Sjimharris sati_set_data_byte(sequence, scsi_io, 36, 0x34); 776230557Sjimharris sati_set_data_byte(sequence, scsi_io, 37, 0x00); 777230557Sjimharris sati_set_data_byte(sequence, scsi_io, 38, (U8) sati_get_ata_status(register_fis)); 778230557Sjimharris sati_set_data_byte(sequence, scsi_io, 39, (U8) sati_get_ata_error(register_fis)); 779230557Sjimharris sati_set_data_byte(sequence, scsi_io, 40, sati_get_ata_lba_low(register_fis)); 780230557Sjimharris sati_set_data_byte(sequence, scsi_io, 41, sati_get_ata_lba_mid(register_fis)); 781230557Sjimharris sati_set_data_byte(sequence, scsi_io, 42, sati_get_ata_lba_high(register_fis)); 782230557Sjimharris sati_set_data_byte(sequence, scsi_io, 43, sati_get_ata_device(register_fis)); 783230557Sjimharris sati_set_data_byte(sequence, scsi_io, 44, sati_get_ata_lba_low_ext(register_fis)); 784230557Sjimharris sati_set_data_byte(sequence, scsi_io, 45, sati_get_ata_lba_mid_ext(register_fis)); 785230557Sjimharris sati_set_data_byte(sequence, scsi_io, 46, sati_get_ata_lba_high_ext(register_fis)); 786230557Sjimharris sati_set_data_byte(sequence, scsi_io, 47, 0x00); 787230557Sjimharris sati_set_data_byte(sequence, scsi_io, 48, sati_get_ata_sector_count(register_fis)); 788230557Sjimharris sati_set_data_byte(sequence, scsi_io, 49, sati_get_ata_sector_count_exp(register_fis)); 789230557Sjimharris 790230557Sjimharris for(offset = 50; offset < 56; offset++) 791230557Sjimharris { 792230557Sjimharris sati_set_data_byte(sequence, scsi_io, offset, 0x00); 793230557Sjimharris } 794230557Sjimharris 795230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 796230557Sjimharris} 797230557Sjimharris 798230557Sjimharris#endif // !defined(DISABLE_SATI_INQUIRY) 799230557Sjimharris 800