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