1 /*- 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of version 2 of the GNU General Public License as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21 * The full GNU General Public License is included in this distribution 22 * in the file called LICENSE.GPL. 23 * 24 * BSD LICENSE 25 * 26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * * Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * * Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 */ 52 53 #include <sys/cdefs.h> 54 __FBSDID("$FreeBSD$"); 55 56 /** 57 * @file 58 * 59 * @brief This file contains the method implementations required to 60 * translate the SCSI inquiry command. 61 * The following (VPD) pages are currently supported: 62 * - Standard 63 * - Supported Pages 64 * - Unit Serial Number 65 * - Device Identification 66 */ 67 68 #if !defined(DISABLE_SATI_INQUIRY) 69 70 #include <dev/isci/scil/sati_inquiry.h> 71 #include <dev/isci/scil/sati_callbacks.h> 72 #include <dev/isci/scil/sati_util.h> 73 #include <dev/isci/scil/intel_ata.h> 74 #include <dev/isci/scil/intel_scsi.h> 75 76 //****************************************************************************** 77 //* P R I V A T E M E T H O D S 78 //****************************************************************************** 79 /** 80 * @brief This method builds the SCSI data associated with the SATI product 81 * revision that is commonly used on the Standard inquiry response and 82 * the ATA information page. 83 * 84 * @param[in] sequence This parameter specifies the translator sequence 85 * object to be utilized during data translation. 86 * @param[in] ata_input_data This parameter specifies ata data received from 87 * the remote device. 88 * @param[out] scsi_io This parameter specifies the user IO request for 89 * which to construct the standard inquiry data. 90 * 91 * @return none 92 */ 93 static 94 void sati_inquiry_construct_product_revision( 95 SATI_TRANSLATOR_SEQUENCE_T * sequence, 96 void * ata_input_data, 97 void * scsi_io 98 ) 99 { 100 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 101 ata_input_data; 102 103 // Fill in the product revision level field. 104 // Per SAT, copy portions of the firmware revision that is not filled 105 // with spaces. Some devices left-align their firmware rev ID, while 106 // others right-align. 107 if ( (identify->firmware_revision[4] == 0x20) 108 && (identify->firmware_revision[5] == 0x20) 109 && (identify->firmware_revision[6] == 0x20) 110 && (identify->firmware_revision[7] == 0x20) ) 111 { 112 sati_ata_identify_device_copy_data( 113 sequence, 114 scsi_io, 115 32, 116 ata_input_data, 117 ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision), 118 4, 119 TRUE 120 ); 121 } 122 else 123 { 124 // Since the last 4 bytes of the firmware revision are not spaces, 125 // utilize these bytes as the firmware revision in the inquiry data. 126 sati_ata_identify_device_copy_data( 127 sequence, 128 scsi_io, 129 32, 130 ata_input_data, 131 ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision)+4, 132 4, 133 TRUE 134 ); 135 } 136 } 137 138 139 //****************************************************************************** 140 //* P U B L I C M E T H O D S 141 //****************************************************************************** 142 143 /** 144 * @brief This method builds the SCSI data associated with a SCSI standard 145 * inquiry request. 146 * 147 * @param[in] sequence This parameter specifies the translator sequence 148 * object to be utilized during data translation. 149 * @param[in] ata_input_data This parameter specifies ata data received from 150 * the remote device. 151 * @param[out] scsi_io This parameter specifies the user IO request for 152 * which to construct the standard inquiry data. 153 * 154 * @return none 155 */ 156 void sati_inquiry_standard_translate_data( 157 SATI_TRANSLATOR_SEQUENCE_T * sequence, 158 void * ata_input_data, 159 void * scsi_io 160 ) 161 { 162 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 163 ata_input_data; 164 U32 index; 165 166 // Device type is disk, attached to this lun. 167 sati_set_data_byte(sequence, scsi_io, 0, 0x00); 168 169 // If the device indicates it's a removable media device, then set the 170 // RMB bit 171 if (identify->general_config_bits & ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE) 172 sati_set_data_byte(sequence, scsi_io, 1, 0x80); 173 else 174 sati_set_data_byte(sequence, scsi_io, 1, 0x00); 175 176 sati_set_data_byte(sequence, scsi_io, 2, 0x05); // Indicate SPC-3 support 177 sati_set_data_byte(sequence, scsi_io, 3, 0x02); // Response Format SPC-3 178 179 sati_set_data_byte(sequence, scsi_io, 4, 62); // 62 Additional Data Bytes. 180 // n-4 per the spec, we end at 181 // byte 66, so 66-4. 182 sati_set_data_byte(sequence, scsi_io, 5, 0x00); 183 sati_set_data_byte(sequence, scsi_io, 6, 0x00); 184 sati_set_data_byte(sequence, scsi_io, 7, 0x02); // Enable Cmd Queueing 185 186 // The Vender identification field is set to "ATA " 187 sati_set_data_byte(sequence, scsi_io, 8, 0x41); 188 sati_set_data_byte(sequence, scsi_io, 9, 0x54); 189 sati_set_data_byte(sequence, scsi_io, 10, 0x41); 190 sati_set_data_byte(sequence, scsi_io, 11, 0x20); 191 sati_set_data_byte(sequence, scsi_io, 12, 0x20); 192 sati_set_data_byte(sequence, scsi_io, 13, 0x20); 193 sati_set_data_byte(sequence, scsi_io, 14, 0x20); 194 sati_set_data_byte(sequence, scsi_io, 15, 0x20); 195 196 // Fill in the product ID field. 197 sati_ata_identify_device_copy_data( 198 sequence, 199 scsi_io, 200 16, 201 ata_input_data, 202 ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number), 203 16, 204 TRUE 205 ); 206 207 sati_inquiry_construct_product_revision( 208 sequence, 209 ata_input_data, 210 scsi_io 211 ); 212 213 // Set the remaining fields up to the version descriptors to 0. 214 for (index = 36; index < 58; index++) 215 sati_set_data_byte(sequence, scsi_io, index, 0); 216 217 // Add version descriptors for the various protocols in play. 218 219 // SAM-4 220 sati_set_data_byte(sequence, scsi_io, 58, 0); 221 sati_set_data_byte(sequence, scsi_io, 59, 0x80); 222 223 // SAS-2 224 sati_set_data_byte(sequence, scsi_io, 60, 0x0C); 225 sati_set_data_byte(sequence, scsi_io, 61, 0x20); 226 227 // SPC-4 228 sati_set_data_byte(sequence, scsi_io, 62, 0x04); 229 sati_set_data_byte(sequence, scsi_io, 63, 0x60); 230 231 // SBC-3 232 sati_set_data_byte(sequence, scsi_io, 64, 0x04); 233 sati_set_data_byte(sequence, scsi_io, 65, 0xC0); 234 235 // ATA/ATAPI-8 ACS 236 sati_set_data_byte(sequence, scsi_io, 66, 0x16); 237 sati_set_data_byte(sequence, scsi_io, 67, 0x23); 238 } 239 240 /** 241 * @brief This method builds the SCSI data associated with an SCSI inquiry 242 * for the supported VPD pages page. 243 * 244 * @param[in] sequence This parameter specifies the translator sequence 245 * object to be utilized during data translation. 246 * @param[out] scsi_io This parameter specifies the user IO request for 247 * which to construct the supported VPD page information. 248 * 249 * @return none 250 */ 251 static 252 void sati_inquiry_supported_pages_translate_data( 253 SATI_TRANSLATOR_SEQUENCE_T * sequence, 254 void * scsi_io 255 ) 256 { 257 // Formulate the SCSI output data for the caller. 258 sati_set_data_byte(sequence, scsi_io, 0, 0); // Qualifier and Device Type 259 sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE); 260 sati_set_data_byte(sequence, scsi_io, 2, 0); // Reserved. 261 sati_set_data_byte(sequence, scsi_io, 3, 4); // # VPD pages supported 262 sati_set_data_byte(sequence, scsi_io, 4, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE); 263 sati_set_data_byte(sequence, scsi_io, 5, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE); 264 sati_set_data_byte(sequence, scsi_io, 6, SCSI_INQUIRY_DEVICE_ID_PAGE); 265 sati_set_data_byte(sequence, scsi_io, 7, SCSI_INQUIRY_ATA_INFORMATION_PAGE); 266 sati_set_data_byte(sequence, scsi_io, 8, SCSI_INQUIRY_BLOCK_DEVICE_PAGE); 267 sati_set_data_byte(sequence, scsi_io, 9, 0); // End of the list 268 } 269 270 /** 271 * @brief This method builds the SCSI data associated with a request for 272 * the unit serial number vital product data (VPD) page. 273 * 274 * @param[in] sequence This parameter specifies the translator sequence 275 * object to be utilized during data translation. 276 * @param[in] ata_input_data This parameter specifies ata data received from 277 * the remote device. 278 * @param[out] scsi_io This parameter specifies the user IO request for 279 * which to construct the unit serial number data. 280 * 281 * @return none 282 */ 283 void sati_inquiry_serial_number_translate_data( 284 SATI_TRANSLATOR_SEQUENCE_T * sequence, 285 void * ata_input_data, 286 void * scsi_io 287 ) 288 { 289 // Peripheral qualifier (0x0, currently connected) 290 // Peripheral device type (0x0 direct-access block device) 291 sati_set_data_byte(sequence, scsi_io, 0, 0x00); 292 293 sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE); 294 sati_set_data_byte(sequence, scsi_io, 2, 0x00); // Reserved 295 sati_set_data_byte(sequence, scsi_io, 3, ATA_IDENTIFY_SERIAL_NUMBER_LEN); 296 297 sati_ata_identify_device_copy_data( 298 sequence, 299 scsi_io, 300 4, 301 ata_input_data, 302 ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number), 303 ATA_IDENTIFY_SERIAL_NUMBER_LEN, 304 TRUE 305 ); 306 } 307 308 /** 309 * @brief This method builds the SCSI data associated with a request for 310 * the Block Device Characteristics vital product data (VPD) page. 311 * 312 * @param[in] sequence This parameter specifies the translator sequence 313 * object to be utilized during data translation. 314 * @param[in] ata_input_data This parameter specifies ata data received from 315 * the remote device. 316 * @param[out] scsi_io This parameter specifies the user IO request for 317 * which to construct the unit serial number data. 318 * 319 * @return none 320 */ 321 void sati_inquiry_block_device_translate_data( 322 SATI_TRANSLATOR_SEQUENCE_T * sequence, 323 void * ata_input_data, 324 void * scsi_io 325 ) 326 { 327 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 328 ata_input_data; 329 330 U32 offset; 331 332 // Peripheral qualifier (0x0, currently connected) 333 // Peripheral device type (0x0 direct-access block device) 334 sati_set_data_byte(sequence, scsi_io, 0, 0x00); 335 336 sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_BLOCK_DEVICE_PAGE); 337 338 //PAGE LENGTH 0x003C 339 sati_set_data_byte(sequence, scsi_io, 2, 0x00); 340 sati_set_data_byte(sequence, scsi_io, 3, SCSI_INQUIRY_BLOCK_DEVICE_LENGTH); 341 342 sati_ata_identify_device_copy_data( 343 sequence, 344 scsi_io, 345 4, 346 ata_input_data, 347 ATA_IDENTIFY_DEVICE_GET_OFFSET(nominal_media_rotation_rate), 348 2, 349 FALSE 350 ); 351 352 sati_set_data_byte(sequence, scsi_io, 6, 0x00); 353 354 sati_set_data_byte( 355 sequence, 356 scsi_io, 357 7, 358 (identify->device_nominal_form_factor & 0x0F) // only need bits 0-3 359 ); 360 361 //bytes 8-63 are reserved 362 for(offset = 8; offset < 64; offset++) 363 { 364 sati_set_data_byte(sequence, scsi_io, offset, 0x00); 365 } 366 } 367 368 /** 369 * @brief This method builds the SCSI data associated with a request for 370 * the device identification vital product data (VPD) page. 371 * 372 * @param[in] sequence This parameter specifies the translator sequence 373 * object to be utilized during data translation. 374 * @param[in] ata_input_data This parameter specifies ata data received from 375 * the remote device. 376 * @param[out] scsi_io This parameter specifies the user IO request for 377 * which to construct the device ID page. 378 * 379 * @return none 380 */ 381 void sati_inquiry_device_id_translate_data( 382 SATI_TRANSLATOR_SEQUENCE_T * sequence, 383 void * ata_input_data, 384 void * scsi_io 385 ) 386 { 387 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 388 ata_input_data; 389 U16 byte_offset = 4; 390 U16 page_length; 391 392 // Peripheral qualifier (0x0, currently connected) 393 // Peripheral device type (0x0 direct-access block device) 394 sati_set_data_byte(sequence, scsi_io, 0, 0x00); 395 396 sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_DEVICE_ID_PAGE); 397 398 /** 399 * If World Wide Names are supported by this target, then build an 400 * identification descriptor using the WWN. 401 */ 402 403 if (identify->command_set_supported_extention 404 & ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE) 405 { 406 407 sati_set_data_byte(sequence, 408 scsi_io, 4, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET 409 ); 410 411 412 sati_set_data_byte(sequence, 413 scsi_io, 5, SCSI_LUN_ASSOCIATION | SCSI_NAA_IDENTIFIER_TYPE 414 ); 415 416 sati_set_data_byte(sequence, scsi_io, 6, 0); 417 sati_set_data_byte(sequence, scsi_io, 7, 0x08); // WWN are 8 bytes long 418 419 // Copy data from the identify device world wide name field into the 420 // buffer. 421 sati_ata_identify_device_copy_data( 422 sequence, 423 scsi_io, 424 8, 425 ata_input_data, 426 ATA_IDENTIFY_DEVICE_GET_OFFSET(world_wide_name), 427 ATA_IDENTIFY_WWN_LEN, 428 FALSE 429 ); 430 431 byte_offset = 16; 432 } 433 434 /** 435 * Build a identification descriptor using the model number & serial number. 436 */ 437 438 sati_set_data_byte(sequence, 439 scsi_io, byte_offset, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_ASCII_CODE_SET 440 ); 441 byte_offset++; 442 sati_set_data_byte(sequence, 443 scsi_io, byte_offset, SCSI_LUN_ASSOCIATION | SCSI_T10_IDENTIFIER_TYPE 444 ); 445 byte_offset++; 446 sati_set_data_byte(sequence, scsi_io, byte_offset, 0); 447 byte_offset++; 448 449 // Identifier length (8 bytes for "ATA " + 40 bytes from ATA IDENTIFY 450 // model number field + 20 bytes from ATA IDENTIFY serial number field. 451 sati_set_data_byte( 452 sequence, 453 scsi_io, 454 byte_offset, 455 8 + (ATA_IDENTIFY_SERIAL_NUMBER_LEN) + (ATA_IDENTIFY_MODEL_NUMBER_LEN) 456 ); 457 byte_offset++; 458 459 // Per SAT, write "ATA ". 460 sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41); 461 byte_offset++; 462 sati_set_data_byte(sequence, scsi_io, byte_offset, 0x54); 463 byte_offset++; 464 sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41); 465 byte_offset++; 466 sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); 467 byte_offset++; 468 sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); 469 byte_offset++; 470 sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); 471 byte_offset++; 472 sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); 473 byte_offset++; 474 sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20); 475 byte_offset++; 476 477 // Copy data from the identify device model number field into the 478 // buffer and update the byte_offset. 479 sati_ata_identify_device_copy_data( 480 sequence, 481 scsi_io, 482 byte_offset, 483 ata_input_data, 484 ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number), 485 ATA_IDENTIFY_MODEL_NUMBER_LEN, 486 TRUE 487 ); 488 489 byte_offset += ATA_IDENTIFY_MODEL_NUMBER_LEN; 490 491 // Copy data from the identify device serial number field into the 492 // buffer and update the byte_offset. 493 sati_ata_identify_device_copy_data( 494 sequence, 495 scsi_io, 496 byte_offset, 497 ata_input_data, 498 ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number), 499 ATA_IDENTIFY_SERIAL_NUMBER_LEN, 500 TRUE 501 ); 502 503 byte_offset += ATA_IDENTIFY_SERIAL_NUMBER_LEN; 504 505 /** 506 * If the target is contained in a SAS Domain, then build a target port 507 * ID descriptor using the SAS address. 508 */ 509 510 #if defined(SATI_TRANSPORT_SUPPORTS_SAS) \ 511 && defined(DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT) 512 { 513 SCI_SAS_ADDRESS_T sas_address; 514 515 sati_set_data_byte( 516 sequence, 517 scsi_io, 518 byte_offset, 519 SCSI_SAS_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET 520 ); 521 byte_offset++; 522 523 sati_set_data_byte( 524 sequence, 525 scsi_io, 526 byte_offset, 527 SCSI_PIV_ENABLE | SCSI_TARGET_PORT_ASSOCIATION | 528 SCSI_NAA_IDENTIFIER_TYPE 529 ); 530 531 byte_offset++; 532 sati_set_data_byte(sequence, scsi_io, byte_offset, 0); 533 byte_offset++; 534 sati_set_data_byte(sequence, scsi_io, byte_offset, 8); // SAS Addr=8 bytes 535 byte_offset++; 536 537 sati_cb_device_get_sas_address(scsi_io, &sas_address); 538 539 // Store the SAS address in the target port descriptor. 540 sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.high); 541 byte_offset += 4; 542 sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.low); 543 byte_offset += 4; 544 } 545 #endif // SATI_TRANSPORT_SUPPORTS_SAS && DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT 546 547 /** 548 * Set the Page length field. The page length is n-3, where n is the 549 * last offset in the page (considered page length - 4). 550 */ 551 552 page_length = byte_offset - 4; 553 sati_set_data_byte(sequence, scsi_io, 2, (U8)((page_length & 0xFF00) >> 8)); 554 sati_set_data_byte(sequence, scsi_io, 3, (U8)(page_length & 0x00FF)); 555 } 556 557 /** 558 * @brief This method builds the SCSI data associated with a request for 559 * the ATA information vital product data (VPD) page. 560 * 561 * @param[in] sequence This parameter specifies the translator sequence 562 * object to be utilized during data translation. 563 * @param[in] ata_input_data This parameter specifies ata data received from 564 * a identify device command processed by the remote device. 565 * @param[out] scsi_io This parameter specifies the user IO request for 566 * which to construct the ATA information page. 567 * 568 * @return none 569 */ 570 SATI_STATUS sati_inquiry_ata_information_translate_data( 571 SATI_TRANSLATOR_SEQUENCE_T * sequence, 572 void * ata_input_data, 573 void * scsi_io 574 ) 575 { 576 sati_set_data_byte(sequence, scsi_io, 0, 0x00); 577 sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_ATA_INFORMATION_PAGE); 578 sati_set_data_byte(sequence, scsi_io, 2, 0x02); 579 sati_set_data_byte(sequence, scsi_io, 3, 0x38); 580 581 //Reserved SAT2r07 582 sati_set_data_byte(sequence, scsi_io, 4, 0x00); 583 sati_set_data_byte(sequence, scsi_io, 5, 0x00); 584 sati_set_data_byte(sequence, scsi_io, 6, 0x00); 585 sati_set_data_byte(sequence, scsi_io, 7, 0x00); 586 587 // The Vender identification field is set to "ATA " 588 sati_set_data_byte(sequence, scsi_io, 8, 0x41); 589 sati_set_data_byte(sequence, scsi_io, 9, 0x54); 590 sati_set_data_byte(sequence, scsi_io, 10, 0x41); 591 sati_set_data_byte(sequence, scsi_io, 11, 0x20); 592 sati_set_data_byte(sequence, scsi_io, 12, 0x20); 593 sati_set_data_byte(sequence, scsi_io, 13, 0x20); 594 sati_set_data_byte(sequence, scsi_io, 14, 0x20); 595 sati_set_data_byte(sequence, scsi_io, 15, 0x20); 596 597 //SAT Product identification 598 sati_ata_identify_device_copy_data( 599 sequence, 600 scsi_io, 601 16, 602 ata_input_data, 603 ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number), 604 16, 605 TRUE 606 ); 607 608 //SAT Product Revision level bytes 32-35 609 sati_inquiry_construct_product_revision( 610 sequence, 611 ata_input_data, 612 scsi_io 613 ); 614 615 //skipping ATA device signature for now 616 617 //Command code 618 sati_set_data_byte(sequence, scsi_io, 56, 0xEC); 619 620 //Reserved SAT2r07 621 sati_set_data_byte(sequence, scsi_io, 57, 0x00); 622 sati_set_data_byte(sequence, scsi_io, 58, 0x00); 623 sati_set_data_byte(sequence, scsi_io, 59, 0x00); 624 625 //copy all ATA identify device data 626 sati_ata_identify_device_copy_data( 627 sequence, 628 scsi_io, 629 60, 630 ata_input_data, 631 0, 632 sizeof(ATA_IDENTIFY_DEVICE_DATA_T), 633 FALSE 634 ); 635 636 //Need to send ATA Execute Device Diagnostic command still 637 sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 638 639 return SATI_SEQUENCE_INCOMPLETE; 640 } 641 642 /** 643 * @brief This method will translate the inquiry SCSI command into 644 * an ATA IDENTIFY DEVICE command. It will handle several different 645 * VPD pages and the standard inquiry page. 646 * For more information on the parameters passed to this method, 647 * please reference sati_translate_command(). 648 * 649 * @return Indicate if the command translation succeeded. 650 * @retval SCI_SUCCESS This is returned if the command translation was 651 * successful. 652 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 653 * the page isn't supported, or the page code 654 * field is not zero when the EVPD bit is 0. 655 */ 656 SATI_STATUS sati_inquiry_translate_command( 657 SATI_TRANSLATOR_SEQUENCE_T * sequence, 658 void * scsi_io, 659 void * ata_io 660 ) 661 { 662 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 663 664 /** 665 * SPC dictates: 666 * - that the page code field must be 0, if VPD enable is 0. 667 */ 668 if ( ((sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) == 0) 669 && (sati_get_cdb_byte(cdb, 2) != 0) ) 670 { 671 sati_scsi_sense_data_construct( 672 sequence, 673 scsi_io, 674 SCSI_STATUS_CHECK_CONDITION, 675 SCSI_SENSE_ILLEGAL_REQUEST, 676 SCSI_ASC_INVALID_FIELD_IN_CDB, 677 SCSI_ASCQ_INVALID_FIELD_IN_CDB 678 ); 679 return SATI_FAILURE_CHECK_RESPONSE_DATA; 680 } 681 682 // Set the data length based on the allocation length field in the CDB. 683 sequence->allocation_length = (sati_get_cdb_byte(cdb, 3) << 8) | 684 (sati_get_cdb_byte(cdb, 4)); 685 686 // Check to see if there was a request for the vital product data or just 687 // the standard inquiry. 688 if (sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) 689 { 690 // Parse the page code to determine which translator to invoke. 691 switch (sati_get_cdb_byte(cdb, 2)) 692 { 693 case SCSI_INQUIRY_SUPPORTED_PAGES_PAGE: 694 sequence->type = SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES; 695 sati_inquiry_supported_pages_translate_data(sequence, scsi_io); 696 return SATI_COMPLETE; 697 break; 698 699 case SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE: 700 sequence->type = SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER; 701 break; 702 703 case SCSI_INQUIRY_DEVICE_ID_PAGE: 704 sequence->type = SATI_SEQUENCE_INQUIRY_DEVICE_ID; 705 break; 706 707 case SCSI_INQUIRY_ATA_INFORMATION_PAGE: 708 709 if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE) 710 { 711 sati_ata_execute_device_diagnostic_construct( 712 ata_io, 713 sequence 714 ); 715 sequence->type = SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG; 716 } 717 else 718 { 719 sequence->type = SATI_SEQUENCE_INQUIRY_ATA_INFORMATION; 720 } 721 break; 722 723 case SCSI_INQUIRY_BLOCK_DEVICE_PAGE: 724 sequence->type = SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE; 725 break; 726 727 default: 728 sati_scsi_sense_data_construct( 729 sequence, 730 scsi_io, 731 SCSI_STATUS_CHECK_CONDITION, 732 SCSI_SENSE_ILLEGAL_REQUEST, 733 SCSI_ASC_INVALID_FIELD_IN_CDB, 734 SCSI_ASCQ_INVALID_FIELD_IN_CDB 735 ); 736 return SATI_FAILURE_CHECK_RESPONSE_DATA; 737 break; 738 } 739 } 740 else 741 { 742 sequence->type = SATI_SEQUENCE_INQUIRY_STANDARD; 743 } 744 745 sati_ata_identify_device_construct(ata_io, sequence); 746 747 return SATI_SUCCESS; 748 } 749 750 /** 751 * @brief This method finishes the construction of the SCSI data associated 752 with a request for the ATA information vital product data (VPD) page. 753 The ATA device signature is written into the data response from the 754 task fle registers after issuing a Execute Device Diagnostic command. 755 * 756 * @param[in] sequence This parameter specifies the translator sequence 757 * object to be utilized during data translation. 758 * @param[out] scsi_io This parameter specifies the user IO request for 759 * which to construct the ATA information page. 760 * @param[in] ata_io This parameter specifies the ATA payload 761 * buffer location and size to be translated. 762 * 763 * @return none 764 */ 765 void sati_inquiry_ata_information_finish_translation( 766 SATI_TRANSLATOR_SEQUENCE_T * sequence, 767 void * scsi_io, 768 void * ata_io 769 ) 770 { 771 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 772 U32 offset; 773 774 //SATA transport 775 sati_set_data_byte(sequence, scsi_io, 36, 0x34); 776 sati_set_data_byte(sequence, scsi_io, 37, 0x00); 777 sati_set_data_byte(sequence, scsi_io, 38, (U8) sati_get_ata_status(register_fis)); 778 sati_set_data_byte(sequence, scsi_io, 39, (U8) sati_get_ata_error(register_fis)); 779 sati_set_data_byte(sequence, scsi_io, 40, sati_get_ata_lba_low(register_fis)); 780 sati_set_data_byte(sequence, scsi_io, 41, sati_get_ata_lba_mid(register_fis)); 781 sati_set_data_byte(sequence, scsi_io, 42, sati_get_ata_lba_high(register_fis)); 782 sati_set_data_byte(sequence, scsi_io, 43, sati_get_ata_device(register_fis)); 783 sati_set_data_byte(sequence, scsi_io, 44, sati_get_ata_lba_low_ext(register_fis)); 784 sati_set_data_byte(sequence, scsi_io, 45, sati_get_ata_lba_mid_ext(register_fis)); 785 sati_set_data_byte(sequence, scsi_io, 46, sati_get_ata_lba_high_ext(register_fis)); 786 sati_set_data_byte(sequence, scsi_io, 47, 0x00); 787 sati_set_data_byte(sequence, scsi_io, 48, sati_get_ata_sector_count(register_fis)); 788 sati_set_data_byte(sequence, scsi_io, 49, sati_get_ata_sector_count_exp(register_fis)); 789 790 for(offset = 50; offset < 56; offset++) 791 { 792 sati_set_data_byte(sequence, scsi_io, offset, 0x00); 793 } 794 795 sequence->state = SATI_SEQUENCE_STATE_FINAL; 796 } 797 798 #endif // !defined(DISABLE_SATI_INQUIRY) 799 800