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 * @brief This file contains all of the method implementations that 59 * provide generic support for SATI. Some methods can be utilized 60 * by a user to construct ATA/ATAPI commands, copy ATA device 61 * structure data, fill in sense data, etc. 62 */ 63 64 #include <dev/isci/scil/sati_util.h> 65 #include <dev/isci/scil/sati_callbacks.h> 66 #include <dev/isci/scil/intel_scsi.h> 67 #include <dev/isci/scil/intel_ata.h> 68 #include <dev/isci/scil/intel_sat.h> 69 #include <dev/isci/scil/intel_sas.h> 70 71 /** 72 * @brief This method will set the data direction, protocol, and transfer 73 * kength for an ATA non-data command. 74 * 75 * @pre It is expected that the user will use this method for setting these 76 * values in a non-data ATA command constuct. 77 * 78 * @param[out] ata_io This parameter specifies the ATA IO request structure 79 * for which to build the IDENTIFY DEVICE command. 80 * @param[in] sequence This parameter specifies the translator sequence 81 * for which the command is being constructed. 82 * 83 * @return none. 84 */ 85 void sati_ata_non_data_command( 86 void * ata_io, 87 SATI_TRANSLATOR_SEQUENCE_T * sequence 88 ) 89 { 90 sequence->data_direction = SATI_DATA_DIRECTION_NONE; 91 sequence->protocol = SAT_PROTOCOL_NON_DATA; 92 sequence->ata_transfer_length = 0; 93 } 94 95 /** 96 * @brief This method will construct the ATA identify device command. 97 * 98 * @pre It is expected that the user has properly set the current contents 99 * of the register FIS to 0. 100 * 101 * @param[out] ata_io This parameter specifies the ATA IO request structure 102 * for which to build the IDENTIFY DEVICE command. 103 * @param[in] sequence This parameter specifies the translator sequence 104 * for which the command is being constructed. 105 * 106 * @return none. 107 */ 108 void sati_ata_identify_device_construct( 109 void * ata_io, 110 SATI_TRANSLATOR_SEQUENCE_T * sequence 111 ) 112 { 113 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 114 115 sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE); 116 sequence->data_direction = SATI_DATA_DIRECTION_IN; 117 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 118 sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T); 119 } 120 121 /** 122 * @brief This method will construct the ATA Execute Device Diagnostic command. 123 * 124 * @param[out] ata_io This parameter specifies the ATA IO request structure 125 * for which to build the IDENTIFY DEVICE command. 126 * @param[in] sequence This parameter specifies the translator sequence 127 * for which the command is being constructed. 128 * 129 * @return none. 130 */ 131 void sati_ata_execute_device_diagnostic_construct( 132 void * ata_io, 133 SATI_TRANSLATOR_SEQUENCE_T * sequence 134 ) 135 { 136 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 137 138 sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG); 139 140 sequence->data_direction = SATI_DATA_DIRECTION_IN; 141 sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC; 142 sequence->ata_transfer_length = 16; 143 } 144 145 /** 146 * @brief This method will set data bytes in the user data area. If the 147 * caller requests it, the data written will be forced to ascii 148 * printable characters if it isn't already a printable character. 149 * A printable character is considered to be >= 0x20 and <= 0x70. 150 * 151 * @param[in] sequence This parameter specifies the translation sequence 152 * for which to copy and swap the data. 153 * @param[out] destination_scsi_io This parameter specifies the SCSI IO 154 * request containing the destination buffer into which to copy. 155 * @param[in] destination_offset This parameter specifies the offset into 156 * the data buffer where the information will be copied to. 157 * @param[in] source_value This parameter specifies the value retrieved 158 * from the source buffer that is to be copied into the user 159 * buffer area. 160 * @param[in] use_printable_chars This parameter indicates if the copy should 161 * ensure that the value copied is considered an ASCII printable 162 * character (e.g. A, B, " ", etc.). These characters reside 163 * in the 0x20 - 0x7E ASCII range. 164 * 165 * @return none 166 */ 167 static 168 void sati_set_ascii_data_byte( 169 SATI_TRANSLATOR_SEQUENCE_T * sequence, 170 void * destination_scsi_io, 171 U32 destination_offset, 172 U8 source_value, 173 BOOL use_printable_chars 174 ) 175 { 176 // if the user requests that the copied data be ascii printable, then 177 // default to " " (i.e. 0x20) for all non-ascii printable characters. 178 if((use_printable_chars == TRUE) 179 && ((source_value < 0x20) || (source_value > 0x7E))) 180 { 181 source_value = 0x20; 182 } 183 184 sati_set_data_byte( 185 sequence, destination_scsi_io, destination_offset, source_value 186 ); 187 } 188 189 /** 190 * @brief This method performs a copy operation using an offset into the 191 * source buffer, an offset into the destination buffer, and a length. 192 * It will perform the byte swap from the 16-bit identify field 193 * into the network byte order SCSI location. 194 * 195 * @param[in] sequence This parameter specifies the translation sequence 196 * for which to copy and swap the data. 197 * @param[out] destination_scsi_io This parameter specifies the SCSI IO 198 * request containing the destination buffer into which to copy. 199 * @param[in] destination_offset This parameter specifies the offset into 200 * the data buffer where the information will be copied to. 201 * @param[in] source_buffer This parameter specifies the source buffer from 202 * which the data will be copied. 203 * @param[in] source_offset This parameter specifies the offset into the 204 * source buffer where the copy shall begin. 205 * @param[in] length This parameter specifies the number of bytes to copy 206 * during this operation. 207 * @param[in] use_printable_chars This parameter indicates if the copy should 208 * ensure that the value copied is considered an ASCII printable 209 * character (e.g. A, B, " ", etc.). These characters reside 210 * in the 0x20 - 0x7E ASCII range. 211 * 212 * @return none 213 */ 214 void sati_ata_identify_device_copy_data( 215 SATI_TRANSLATOR_SEQUENCE_T * sequence, 216 void * destination_scsi_io, 217 U32 destination_offset, 218 U8 * source_buffer, 219 U32 source_offset, 220 U32 length, 221 BOOL use_printable_chars 222 ) 223 { 224 source_buffer += source_offset; 225 while (length > 0) 226 { 227 sati_set_ascii_data_byte( 228 sequence, 229 destination_scsi_io, 230 destination_offset, 231 *(source_buffer+1), 232 use_printable_chars 233 ); 234 235 sati_set_ascii_data_byte( 236 sequence, 237 destination_scsi_io, 238 destination_offset+1, 239 *source_buffer, 240 use_printable_chars 241 ); 242 243 destination_offset += 2; 244 source_buffer += 2; 245 length -= 2; 246 } 247 } 248 249 /** 250 * @brief This method performs a copy operation using a source buffer, 251 * an offset into the destination buffer, and a length. 252 * 253 * @param[in] sequence This parameter specifies the translation sequence 254 * for which to copy and swap the data. 255 * @param[out] destination_scsi_io This parameter specifies the SCSI IO 256 * request containing the destination buffer into which to copy. 257 * @param[in] destination_offset This parameter specifies the offset into 258 * the data buffer where the information will be copied to. 259 * @param[in] source_buffer This parameter specifies the source buffer from 260 * which the data will be copied. 261 * @param[in] length This parameter specifies the number of bytes to copy 262 * during this operation. 263 * 264 * @return none 265 */ 266 void sati_copy_data( 267 SATI_TRANSLATOR_SEQUENCE_T * sequence, 268 void * destination_scsi_io, 269 U32 destination_offset, 270 U8 * source_buffer, 271 U32 length 272 ) 273 { 274 while (length > 0) 275 { 276 sati_set_data_byte( 277 sequence, destination_scsi_io, destination_offset, *source_buffer 278 ); 279 280 destination_offset++; 281 source_buffer++; 282 length--; 283 } 284 } 285 286 /** 287 * @brief This method extracts the Logical Block Address high and low 32-bit 288 * values and the sector count 32-bit value from the ATA identify 289 * device data. 290 * 291 * @param[in] identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA 292 * from which to extract the sector information. 293 * @param[out] lba_high This parameter specifies the upper 32 bits for the 294 * number of logical block addresses for the device. The upper 295 * 16-bits should always be 0, since 48-bits of LBA is the most 296 * supported by an ATA device. 297 * @param[out] lba_low This parameter specifies the lower 32 bits for the 298 * number of logical block addresses for the device. 299 * @param[out] sector_size This parameter specifies the 32-bits of sector 300 * size. If the ATA device doesn't support reporting it's 301 * sector size, then 512 bytes is utilized as the default value. 302 * 303 * @return none 304 */ 305 void sati_ata_identify_device_get_sector_info( 306 ATA_IDENTIFY_DEVICE_DATA_T * identify, 307 U32 * lba_high, 308 U32 * lba_low, 309 U32 * sector_size 310 ) 311 { 312 // Calculate the values to be returned 313 // Calculation will be different if the SATA device supports 314 // 48-bit addressing. Bit 10 of Word 86 of ATA Identify 315 if (identify->command_set_enabled1 316 & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE) 317 { 318 // This drive supports 48-bit addressing 319 320 *lba_high = identify->max_48bit_lba[7] << 24; 321 *lba_high |= identify->max_48bit_lba[6] << 16; 322 *lba_high |= identify->max_48bit_lba[5] << 8; 323 *lba_high |= identify->max_48bit_lba[4]; 324 325 *lba_low = identify->max_48bit_lba[3] << 24; 326 *lba_low |= identify->max_48bit_lba[2] << 16; 327 *lba_low |= identify->max_48bit_lba[1] << 8; 328 *lba_low |= identify->max_48bit_lba[0]; 329 } 330 else 331 { 332 // This device doesn't support 48-bit addressing 333 // Pull out the largest LBA from words 60 and 61. 334 *lba_high = 0; 335 *lba_low = identify->total_num_sectors[3] << 24; 336 *lba_low |= identify->total_num_sectors[2] << 16; 337 *lba_low |= identify->total_num_sectors[1] << 8; 338 *lba_low |= identify->total_num_sectors[0]; 339 } 340 341 // If the ATA device reports its sector size (bit 12 of Word 106), 342 // then use that instead. 343 if (identify->physical_logical_sector_info 344 & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE) 345 { 346 *sector_size = identify->words_per_logical_sector[3] << 24; 347 *sector_size |= identify->words_per_logical_sector[2] << 16; 348 *sector_size |= identify->words_per_logical_sector[1] << 8; 349 *sector_size |= identify->words_per_logical_sector[0]; 350 } 351 else 352 { 353 // Default the sector size to 512 bytes 354 *sector_size = 512; 355 } 356 } 357 358 /** 359 * @brief This method will construct the ATA check power mode command. 360 * 361 * @pre It is expected that the user has properly set the current contents 362 * of the register FIS to 0. 363 * 364 * @param[out] ata_io This parameter specifies the ATA IO request structure 365 * for which to build the CHECK POWER MODE command. 366 * @param[in] sequence This parameter specifies the translator sequence 367 * for which the command is being constructed. 368 * 369 * @return none. 370 */ 371 void sati_ata_check_power_mode_construct( 372 void * ata_io, 373 SATI_TRANSLATOR_SEQUENCE_T * sequence 374 ) 375 { 376 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 377 378 sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE); 379 sati_ata_non_data_command(ata_io, sequence); 380 } 381 382 /** 383 * @brief This method is utilized to set a specific byte in the sense 384 * data area. It will ensure that the supplied byte offset 385 * isn't larger then the length of the requested sense data. 386 * 387 * @param[in] scsi_io This parameter specifies the user SCSI IO request 388 * for which to set the sense data byte. 389 * @param[in] byte_offset This parameter specifies the byte offset into 390 * the sense data buffer where the data should be written. 391 * @param[in] value This parameter specifies the 8-bit value to be written 392 * into the sense data area. 393 * 394 * @return none 395 */ 396 void sati_set_sense_data_byte( 397 U8 * sense_data, 398 U32 max_sense_data_len, 399 U32 byte_offset, 400 U8 value 401 ) 402 { 403 // Ensure that we don't attempt to write past the end of the sense 404 // data buffer. 405 if (byte_offset < max_sense_data_len) 406 sense_data[byte_offset] = value; 407 } 408 409 /** 410 * @brief This method will construct the common response IU in the user 411 * request's response IU location. 412 * 413 * @param[out] rsp_iu This parameter specifies the user request's 414 * response IU to be constructed. 415 * @param[in] scsi_status This parameter specifies the SCSI status 416 * value for the user's IO request. 417 * @param[in] sense_data_length This parameter specifies the sense data 418 * length for response IU. 419 * @param[in] data_present The parameter specifies the specific 420 * data present value for response IU. 421 * 422 * @return none 423 */ 424 void sati_scsi_common_response_iu_construct( 425 SCI_SSP_RESPONSE_IU_T * rsp_iu, 426 U8 scsi_status, 427 U8 sense_data_length, 428 U8 data_present 429 ) 430 { 431 rsp_iu->sense_data_length[3] = sense_data_length; 432 rsp_iu->sense_data_length[2] = 0; 433 rsp_iu->sense_data_length[1] = 0; 434 rsp_iu->sense_data_length[0] = 0; 435 rsp_iu->status = scsi_status; 436 rsp_iu->data_present = data_present; 437 } 438 439 /** 440 * @brief This method will construct the buffer for sense data 441 * sense data buffer location. Additionally, it will set the user's 442 * SCSI status. 443 * 444 * @param[in,out] scsi_io This parameter specifies the user's IO request 445 * for which to construct the buffer for sense data. 446 * @param[in] scsi_status This parameter specifies the SCSI status 447 * value for the user's IO request. 448 * @param[out] sense_data This paramater 449 * 450 * @return none 451 */ 452 static 453 void sati_scsi_get_sense_data_buffer( 454 SATI_TRANSLATOR_SEQUENCE_T * sequence, 455 void * scsi_io, 456 U8 scsi_status, 457 U8 ** sense_data, 458 U32 * sense_len) 459 { 460 #ifdef SATI_TRANSPORT_SUPPORTS_SAS 461 SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*) 462 sati_cb_get_response_iu_address(scsi_io); 463 464 sati_scsi_common_response_iu_construct( 465 rsp_iu, 466 scsi_status, 467 sati_scsi_get_sense_data_length(sequence, scsi_io), 468 SCSI_RESPONSE_DATA_PRES_SENSE_DATA 469 ); 470 471 *sense_data = (U8*) rsp_iu->data; 472 *sense_len = SSP_RESPONSE_IU_MAX_DATA * 4; // dwords to bytes 473 #else 474 *sense_data = sati_cb_get_sense_data_address(scsi_io); 475 *sense_len = sati_cb_get_sense_data_length(scsi_io); 476 sati_cb_set_scsi_status(scsi_io, scsi_status); 477 #endif // SATI_TRANSPORT_SUPPORTS_SAS 478 } 479 480 /** 481 * @brief This method extract response code based on on device settings. 482 * 483 * @return response code 484 */ 485 static 486 U8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence) 487 { 488 if (sequence->device->descriptor_sense_enable) 489 { 490 return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE; 491 } 492 else 493 { 494 return SCSI_FIXED_CURRENT_RESPONSE_CODE; 495 } 496 } 497 498 /** 499 * @brief This method will return length of descriptor sense data for executed command. 500 * 501 * @return sense data length 502 */ 503 static 504 U8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, 505 void * scsi_io) 506 { 507 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 508 //Initial value is descriptor header length 509 U8 length = 8; 510 511 switch (sati_get_cdb_byte(cdb, 0)) 512 { 513 #if !defined(DISABLE_SATI_WRITE_LONG) 514 case SCSI_WRITE_LONG_10: 515 case SCSI_WRITE_LONG_16: 516 length += SCSI_BLOCK_DESCRIPTOR_LENGTH + 517 SCSI_INFORMATION_DESCRIPTOR_LENGTH; 518 break; 519 #endif // !defined(DISABLE_SATI_WRITE_LONG) 520 #if !defined(DISABLE_SATI_REASSIGN_BLOCKS) 521 case SCSI_REASSIGN_BLOCKS: 522 length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH + 523 SCSI_INFORMATION_DESCRIPTOR_LENGTH; 524 break; 525 #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS) 526 case SCSI_READ_6: 527 case SCSI_READ_10: 528 case SCSI_READ_12: 529 case SCSI_READ_16: 530 case SCSI_WRITE_6: 531 case SCSI_WRITE_10: 532 case SCSI_WRITE_12: 533 case SCSI_WRITE_16: 534 #if !defined(DISABLE_SATI_VERIFY) 535 case SCSI_VERIFY_10: 536 case SCSI_VERIFY_12: 537 case SCSI_VERIFY_16: 538 #endif // !defined(DISABLE_SATI_VERIFY) 539 #if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \ 540 && !defined(DISABLE_SATI_VERIFY) \ 541 && !defined(DISABLE_SATI_WRITE) 542 543 case SCSI_WRITE_AND_VERIFY_10: 544 case SCSI_WRITE_AND_VERIFY_12: 545 case SCSI_WRITE_AND_VERIFY_16: 546 #endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY) 547 // && !defined(DISABLE_SATI_VERIFY) 548 // && !defined(DISABLE_SATI_WRITE) 549 length += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 550 break; 551 } 552 553 return length; 554 } 555 556 /** 557 * @brief This method will return length of sense data. 558 * 559 * @return sense data length 560 */ 561 U8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io) 562 { 563 U8 response_code; 564 565 response_code = sati_scsi_get_sense_data_response_code(sequence); 566 567 switch (response_code) 568 { 569 case SCSI_FIXED_CURRENT_RESPONSE_CODE: 570 case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 571 return SCSI_FIXED_SENSE_DATA_BASE_LENGTH; 572 break; 573 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 574 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 575 return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io); 576 break; 577 } 578 579 return SCSI_FIXED_SENSE_DATA_BASE_LENGTH; 580 } 581 582 /** 583 * @brief This method will construct the sense data buffer in the user's 584 * sense data buffer location. Additionally, it will set the user's 585 * SCSI status. 586 * 587 * @param[in] sequence This parameter specifies the translation sequence 588 * for which to construct the sense data. 589 * @param[in,out] scsi_io This parameter specifies the user's IO request 590 * for which to construct the sense data. 591 * @param[in] scsi_status This parameter specifies the SCSI status 592 * value for the user's IO request. 593 * @param[in] sense_key This parameter specifies the sense key to 594 * be set for the user's IO request. 595 * @param[in] additional_sense_code This parameter specifies the 596 * additional sense code (ASC) key to be set for the user's 597 * IO request. 598 * @param[in] additional_sense_code_qualifier This parameter specifies 599 * the additional sense code qualifier (ASCQ) key to be set 600 * for the user's IO request. 601 * 602 * @return none 603 */ 604 void sati_scsi_sense_data_construct( 605 SATI_TRANSLATOR_SEQUENCE_T * sequence, 606 void * scsi_io, 607 U8 scsi_status, 608 U8 sense_key, 609 U8 additional_sense_code, 610 U8 additional_sense_code_qualifier 611 ) 612 { 613 U8 response_code; 614 615 response_code = sati_scsi_get_sense_data_response_code(sequence); 616 617 switch (response_code) 618 { 619 case SCSI_FIXED_CURRENT_RESPONSE_CODE: 620 case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 621 sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code, 622 sense_key, additional_sense_code, additional_sense_code_qualifier); 623 break; 624 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 625 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 626 sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code, 627 sense_key, additional_sense_code, additional_sense_code_qualifier); 628 break; 629 } 630 631 sequence->is_sense_response_set = TRUE; 632 } 633 634 /** 635 * @brief This method will construct the block descriptor in the user's descriptor 636 * sense data buffer location. 637 * 638 * @param[in] sense_data This parameter specifies the user SCSI IO request 639 * for which to set the sense data byte. 640 * @param[in] sense_len This parameter specifies length of the sense data 641 * to be returned by SATI. 642 * @param[out] descriptor_len This parameter returns the length of constructed 643 * descriptor. 644 * 645 * @return none 646 */ 647 static 648 void sati_scsi_block_descriptor_construct( 649 U8 * sense_data, 650 U32 sense_len) 651 { 652 U8 ili = 1; 653 654 sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_BLOCK_DESCRIPTOR_TYPE); 655 sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH); 656 sati_set_sense_data_byte(sense_data, sense_len, 2, 0); 657 sati_set_sense_data_byte(sense_data, sense_len, 3, (ili << 5)); 658 } 659 660 /** 661 * @brief This method will construct the command-specific descriptor for 662 * the descriptor sense data buffer in the user's sense data buffer 663 * location. 664 * 665 * @param[in] sense_data This parameter specifies the user SCSI IO request 666 * for which to set the sense data byte. 667 * @param[in] sense_len This parameter specifies length of the sense data 668 * to be returned by SATI. 669 * @param[out] descriptor_len This parameter returns the length of constructed 670 * descriptor. 671 * @param[in] information_buff This parameter specifies the address for which 672 * to set the command-specific information buffer. 673 * 674 * @return none 675 */ 676 static 677 void sati_scsi_command_specific_descriptor_construct( 678 U8 * sense_data, 679 U32 sense_len, 680 U8 * information_buff) 681 { 682 U8 i; 683 684 sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE); 685 sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH); 686 sati_set_sense_data_byte(sense_data, sense_len, 2, 0); 687 sati_set_sense_data_byte(sense_data, sense_len, 3, 0); 688 689 // fill information buffer 690 // SBC 5.20.1 REASSIGN BLOCKS command overview 691 // If information about the first LBA not reassigned is not available 692 // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh 693 for (i=0; i<8; i++) 694 sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]); 695 } 696 697 /** 698 * @brief This method will construct the information descriptor for 699 * the descriptor sense data buffer in the user's sense data buffer 700 * location. 701 * 702 * @param[in] sense_data This parameter specifies the user SCSI IO request 703 * for which to set the sense data byte. 704 * @param[in] sense_len This parameter specifies length of the sense data 705 * to be returned by SATI. 706 * @param[out] descriptor_len This parameter returns the length of constructed 707 * descriptor. 708 * @param[in] information_buff This parameter specifies the address for which 709 * to set the information buffer. 710 * 711 * @return none 712 */ 713 static 714 void sati_scsi_information_descriptor_construct( 715 U8 * sense_data, 716 U32 sense_len, 717 U8 * information_buff) 718 { 719 U8 i; 720 U8 valid = 1; 721 722 sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_INFORMATION_DESCRIPTOR_TYPE); 723 sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH); 724 sati_set_sense_data_byte(sense_data, sense_len, 2, (valid << 7)); 725 sati_set_sense_data_byte(sense_data, sense_len, 3, 0); 726 727 // fill information buffer 728 for (i=0; i<8; i++) 729 sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]); 730 } 731 732 /** 733 * @brief This method will construct the descriptors in the user's descriptor 734 * sense data buffer location. 735 * 736 * @param[in,out] scsi_io This parameter specifies the user's IO request 737 * for which to construct the sense data. 738 * @param[in] sense_data This parameter specifies the user SCSI IO request 739 * for which to set the sense data byte. 740 * @param[in] sense_len This parameter specifies length of the sense data 741 * to be returned by SATI. 742 * @param[out] descriptor_len This parameter returns the length of constructed 743 * descriptor. 744 * @param[in] information_buff This parameter specifies the address for which 745 * to set the information buffer. 746 * 747 * @return none 748 */ 749 static 750 void sati_scsi_common_descriptors_construct( 751 void * scsi_io, 752 U8 * sense_data, 753 U32 sense_len, 754 U8 * information_buff) 755 { 756 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 757 U8 offset = 0; 758 759 switch (sati_get_cdb_byte(cdb, 0)) 760 { 761 #if !defined(DISABLE_SATI_WRITE_LONG) 762 case SCSI_WRITE_LONG_10: 763 case SCSI_WRITE_LONG_16: 764 sati_scsi_block_descriptor_construct( 765 sense_data + offset, 766 sense_len - offset); 767 768 offset += SCSI_BLOCK_DESCRIPTOR_LENGTH; 769 sati_scsi_information_descriptor_construct( 770 sense_data + offset, 771 sense_len - offset, 772 information_buff); 773 774 offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 775 break; 776 #endif // !defined(DISABLE_SATI_WRITE_LONG) 777 #if !defined(DISABLE_SATI_REASSIGN_BLOCKS) 778 case SCSI_REASSIGN_BLOCKS: 779 sati_scsi_command_specific_descriptor_construct( 780 sense_data + offset, 781 sense_len - offset, 782 NULL); 783 784 offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH; 785 sati_scsi_information_descriptor_construct( 786 sense_data + offset, 787 sense_len - offset, 788 information_buff); 789 790 offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 791 break; 792 #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS) 793 case SCSI_READ_6: 794 case SCSI_READ_10: 795 case SCSI_READ_12: 796 case SCSI_READ_16: 797 case SCSI_WRITE_6: 798 case SCSI_WRITE_10: 799 case SCSI_WRITE_12: 800 case SCSI_WRITE_16: 801 #if !defined(DISABLE_SATI_VERIFY) 802 case SCSI_VERIFY_10: 803 case SCSI_VERIFY_12: 804 case SCSI_VERIFY_16: 805 #endif // !defined(DISABLE_SATI_VERIFY) 806 #if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \ 807 && !defined(DISABLE_SATI_VERIFY) \ 808 && !defined(DISABLE_SATI_WRITE) 809 810 case SCSI_WRITE_AND_VERIFY_10: 811 case SCSI_WRITE_AND_VERIFY_12: 812 case SCSI_WRITE_AND_VERIFY_16: 813 #endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY) 814 // && !defined(DISABLE_SATI_VERIFY) 815 // && !defined(DISABLE_SATI_WRITE) 816 sati_scsi_information_descriptor_construct( 817 sense_data + offset, 818 sense_len - offset, 819 information_buff); 820 821 offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 822 break; 823 } 824 } 825 826 /** 827 * @brief This method will construct the descriptor sense data buffer in 828 * the user's sense data buffer location. Additionally, it will set 829 * the user's SCSI status. 830 * 831 * @param[in] sequence This parameter specifies the translation sequence 832 * for which to construct the sense data. 833 * @param[in,out] scsi_io This parameter specifies the user's IO request 834 * for which to construct the sense data. 835 * @param[in] scsi_status This parameter specifies the SCSI status 836 * value for the user's IO request. 837 * @param[in] sense_key This parameter specifies the sense key to 838 * be set for the user's IO request. 839 * @param[in] additional_sense_code This parameter specifies the 840 * additional sense code (ASC) key to be set for the user's 841 * IO request. 842 * @param[in] additional_sense_code_qualifier This parameter specifies 843 * the additional sense code qualifier (ASCQ) key to be set 844 * for the user's IO request. 845 * 846 * @return none 847 */ 848 void sati_scsi_descriptor_sense_data_construct( 849 SATI_TRANSLATOR_SEQUENCE_T * sequence, 850 void * scsi_io, 851 U8 scsi_status, 852 U8 response_code, 853 U8 sense_key, 854 U8 additional_sense_code, 855 U8 additional_sense_code_qualifier 856 ) 857 { 858 U8 * sense_data; 859 U32 sense_len; 860 861 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 862 863 sati_set_sense_data_byte( 864 sense_data, 865 sense_len, 866 0, 867 response_code 868 ); 869 870 sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key); 871 sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code); 872 sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier); 873 sati_set_sense_data_byte(sense_data, sense_len, 4, 0); 874 sati_set_sense_data_byte(sense_data, sense_len, 5, 0); 875 sati_set_sense_data_byte(sense_data, sense_len, 6, 0); 876 877 sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL); 878 879 sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8); 880 } 881 882 /** 883 * @brief This method will construct the fixed format sense data buffer 884 * in the user's sense data buffer location. Additionally, it will 885 * set the user's SCSI status. 886 * 887 * @param[in] sequence This parameter specifies the translation sequence 888 * for which to construct the sense data. 889 * @param[in,out] scsi_io This parameter specifies the user's IO request 890 * for which to construct the sense data. 891 * @param[in] scsi_status This parameter specifies the SCSI status 892 * value for the user's IO request. 893 * @param[in] sense_key This parameter specifies the sense key to 894 * be set for the user's IO request. 895 * @param[in] additional_sense_code This parameter specifies the 896 * additional sense code (ASC) key to be set for the user's 897 * IO request. 898 * @param[in] additional_sense_code_qualifier This parameter specifies 899 * the additional sense code qualifier (ASCQ) key to be set 900 * for the user's IO request. 901 * 902 * @return none 903 */ 904 void sati_scsi_fixed_sense_data_construct( 905 SATI_TRANSLATOR_SEQUENCE_T * sequence, 906 void * scsi_io, 907 U8 scsi_status, 908 U8 response_code, 909 U8 sense_key, 910 U8 additional_sense_code, 911 U8 additional_sense_code_qualifier 912 ) 913 { 914 U8 * sense_data; 915 U32 sense_len; 916 917 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 918 919 // Write out the sense data format per SPC-4. 920 // We utilize the fixed format sense data format. 921 922 sati_set_sense_data_byte( 923 sense_data, 924 sense_len, 925 0, 926 response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT 927 ); 928 929 sati_set_sense_data_byte(sense_data, sense_len, 1, 0); 930 sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key); 931 sati_set_sense_data_byte(sense_data, sense_len, 3, 0); 932 sati_set_sense_data_byte(sense_data, sense_len, 4, 0); 933 sati_set_sense_data_byte(sense_data, sense_len, 5, 0); 934 sati_set_sense_data_byte(sense_data, sense_len, 6, 0); 935 sati_set_sense_data_byte(sense_data, sense_len, 7, 0); 936 sati_set_sense_data_byte(sense_data, sense_len, 8, 0); 937 sati_set_sense_data_byte(sense_data, sense_len, 9, 0); 938 sati_set_sense_data_byte(sense_data, sense_len, 10, 0); 939 sati_set_sense_data_byte(sense_data, sense_len, 11, 0); 940 sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code); 941 sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier); 942 sati_set_sense_data_byte(sense_data, sense_len, 14, 0); 943 sati_set_sense_data_byte(sense_data, sense_len, 15, 0); 944 sati_set_sense_data_byte(sense_data, sense_len, 16, 0); 945 sati_set_sense_data_byte(sense_data, sense_len, 17, 0); 946 } 947 948 /** 949 * @brief This method will construct common sense data that will be identical in 950 * both read error sense construct functions. 951 * sati_scsi_read_ncq_error_sense_construct, 952 * sati_scsi_read_error_sense_construct 953 * 954 * @param[in] sense_data This parameter specifies the user SCSI IO request 955 * for which to set the sense data byte. 956 * @param[in] sense_len This parameter specifies length of the sense data 957 * to be returned by SATI. 958 * @param[in] sense_key This parameter specifies the sense key to 959 * be set for the user's IO request. 960 * @param[in] additional_sense_code This parameter specifies the 961 * additional sense code (ASC) key to be set for the user's 962 * IO request. 963 * @param[in] additional_sense_code_qualifier This parameter specifies 964 * the additional sense code qualifier (ASCQ) key to be set 965 * for the user's IO request. 966 * 967 * @return none 968 */ 969 static 970 void sati_scsi_common_fixed_sense_construct( 971 U8 * sense_data, 972 U32 sense_len, 973 U8 sense_key, 974 U8 additional_sense_code, 975 U8 additional_sense_code_qualifier 976 ) 977 { 978 979 sati_set_sense_data_byte(sense_data, sense_len, 1, 0); 980 sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key); 981 982 //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions 983 984 sati_set_sense_data_byte(sense_data, sense_len, 7, 0); 985 sati_set_sense_data_byte(sense_data, sense_len, 8, 0); 986 sati_set_sense_data_byte(sense_data, sense_len, 9, 0); 987 sati_set_sense_data_byte(sense_data, sense_len, 10, 0); 988 sati_set_sense_data_byte(sense_data, sense_len, 11, 0); 989 sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code); 990 sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier); 991 sati_set_sense_data_byte(sense_data, sense_len, 14, 0); 992 sati_set_sense_data_byte(sense_data, sense_len, 15, 0x80); 993 sati_set_sense_data_byte(sense_data, sense_len, 16, 0); 994 sati_set_sense_data_byte(sense_data, sense_len, 17, 0); 995 } 996 997 /** 998 * @brief This method will construct the descriptor sense data buffer in 999 * the user's sense data buffer location. Additionally, it will set 1000 * the user's SCSI status. 1001 * 1002 * @param[in] sequence This parameter specifies the translation sequence 1003 * for which to construct the sense data. 1004 * @param[in,out] scsi_io This parameter specifies the user's IO request 1005 * for which to construct the sense data. 1006 * @param[in] scsi_status This parameter specifies the SCSI status 1007 * value for the user's IO request. 1008 * @param[in] sense_key This parameter specifies the sense key to 1009 * be set for the user's IO request. 1010 * @param[in] additional_sense_code This parameter specifies the 1011 * additional sense code (ASC) key to be set for the user's 1012 * IO request. 1013 * @param[in] additional_sense_code_qualifier This parameter specifies 1014 * the additional sense code qualifier (ASCQ) key to be set 1015 * for the user's IO request. 1016 * 1017 * @return none 1018 */ 1019 static 1020 void sati_scsi_common_descriptor_sense_construct( 1021 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1022 void * scsi_io, 1023 U8 * sense_data, 1024 U32 sense_len, 1025 U8 sense_key, 1026 U8 additional_sense_code, 1027 U8 additional_sense_code_qualifier, 1028 U8 * information_buff 1029 ) 1030 { 1031 sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key); 1032 sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code); 1033 sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier); 1034 sati_set_sense_data_byte(sense_data, sense_len, 4, 0); 1035 sati_set_sense_data_byte(sense_data, sense_len, 5, 0); 1036 sati_set_sense_data_byte(sense_data, sense_len, 6, 0); 1037 1038 sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff); 1039 1040 sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8); 1041 } 1042 1043 /** 1044 * @brief This method will construct the sense data buffer in the user's 1045 * descriptor sense data buffer location. Additionally, it will set 1046 * the user's SCSI status. This is only used for NCQ uncorrectable 1047 * read errors 1048 * 1049 * @param[in] sequence This parameter specifies the translation sequence 1050 * for which to construct the sense data. 1051 * @param[in,out] scsi_io This parameter specifies the user's IO request 1052 * for which to construct the sense data. 1053 * @param[in] ata_input_data This parameter specifies the user's ATA IO 1054 * response from a Read Log Ext command. 1055 * @param[in] scsi_status This parameter specifies the SCSI status 1056 * value for the user's IO request. 1057 * @param[in] sense_key This parameter specifies the sense key to 1058 * be set for the user's IO request. 1059 * @param[in] additional_sense_code This parameter specifies the 1060 * additional sense code (ASC) key to be set for the user's 1061 * IO request. 1062 * @param[in] additional_sense_code_qualifier This parameter specifies 1063 * the additional sense code qualifier (ASCQ) key to be set 1064 * for the user's IO request. 1065 * 1066 * @return none 1067 */ 1068 static 1069 void sati_scsi_read_ncq_error_descriptor_sense_construct( 1070 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1071 void * scsi_io, 1072 void * ata_input_data, 1073 U8 scsi_status, 1074 U8 response_code, 1075 U8 sense_key, 1076 U8 additional_sense_code, 1077 U8 additional_sense_code_qualifier 1078 ) 1079 { 1080 U8 * sense_data; 1081 U32 sense_len; 1082 1083 U8 information_buff[8] = {0}; 1084 1085 ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data; 1086 1087 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1088 1089 sati_set_sense_data_byte( 1090 sense_data, 1091 sense_len, 1092 0, 1093 response_code 1094 ); 1095 1096 information_buff[2] = ncq_log->lba_47_40; 1097 information_buff[3] = ncq_log->lba_39_32; 1098 information_buff[4] = ncq_log->lba_31_24; 1099 information_buff[5] = ncq_log->lba_23_16; 1100 information_buff[6] = ncq_log->lba_15_8; 1101 information_buff[7] = ncq_log->lba_7_0; 1102 1103 sati_scsi_common_descriptor_sense_construct( 1104 sequence, 1105 scsi_io, 1106 sense_data, 1107 sense_len, 1108 sense_key, 1109 additional_sense_code, 1110 additional_sense_code_qualifier, 1111 information_buff 1112 ); 1113 } 1114 1115 /** 1116 * @brief This method will construct the sense data buffer in the user's 1117 * sense data buffer location. Additionally, it will set the user's 1118 * SCSI status. This is only used for NCQ uncorrectable read errors 1119 * 1120 * @param[in] sequence This parameter specifies the translation sequence 1121 * for which to construct the sense data. 1122 * @param[in,out] scsi_io This parameter specifies the user's IO request 1123 * for which to construct the sense data. 1124 * @param[in] ata_input_data This parameter specifies the user's ATA IO 1125 * response from a Read Log Ext command. 1126 * @param[in] scsi_status This parameter specifies the SCSI status 1127 * value for the user's IO request. 1128 * @param[in] sense_key This parameter specifies the sense key to 1129 * be set for the user's IO request. 1130 * @param[in] additional_sense_code This parameter specifies the 1131 * additional sense code (ASC) key to be set for the user's 1132 * IO request. 1133 * @param[in] additional_sense_code_qualifier This parameter specifies 1134 * the additional sense code qualifier (ASCQ) key to be set 1135 * for the user's IO request. 1136 * 1137 * @return none 1138 */ 1139 static 1140 void sati_scsi_read_ncq_error_fixed_sense_construct( 1141 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1142 void * scsi_io, 1143 void * ata_input_data, 1144 U8 scsi_status, 1145 U8 response_code, 1146 U8 sense_key, 1147 U8 additional_sense_code, 1148 U8 additional_sense_code_qualifier 1149 ) 1150 { 1151 U8 * sense_data; 1152 U32 sense_len; 1153 U8 valid = TRUE; 1154 1155 ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data; 1156 1157 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1158 1159 if(ncq_log->lba_39_32 > 0) 1160 { 1161 valid = FALSE; 1162 } 1163 1164 sati_set_sense_data_byte( 1165 sense_data, 1166 sense_len, 1167 0, 1168 (valid << 7) | response_code 1169 ); 1170 1171 sati_set_sense_data_byte(sense_data, sense_len, 3, ncq_log->lba_31_24); 1172 sati_set_sense_data_byte(sense_data, sense_len, 4, ncq_log->lba_23_16); 1173 sati_set_sense_data_byte(sense_data, sense_len, 5, ncq_log->lba_15_8); 1174 sati_set_sense_data_byte(sense_data, sense_len, 6, ncq_log->lba_7_0); 1175 1176 sati_scsi_common_fixed_sense_construct( 1177 sense_data, 1178 sense_len, 1179 sense_key, 1180 additional_sense_code, 1181 additional_sense_code_qualifier 1182 ); 1183 } 1184 1185 void sati_scsi_read_ncq_error_sense_construct( 1186 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1187 void * scsi_io, 1188 void * ata_input_data, 1189 U8 scsi_status, 1190 U8 sense_key, 1191 U8 additional_sense_code, 1192 U8 additional_sense_code_qualifier 1193 ) 1194 { 1195 U8 response_code; 1196 1197 response_code = sati_scsi_get_sense_data_response_code(sequence); 1198 1199 switch (response_code) 1200 { 1201 case SCSI_FIXED_CURRENT_RESPONSE_CODE: 1202 case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 1203 sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1204 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1205 break; 1206 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 1207 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 1208 sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1209 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1210 break; 1211 } 1212 1213 sequence->is_sense_response_set = TRUE; 1214 } 1215 1216 /** 1217 * @brief This method will construct the sense data buffer in the user's 1218 * sense data buffer location. Additionally, it will set the user's 1219 * SCSI status. This is used for uncorrectable read errors. 1220 * 1221 * @param[in] sequence This parameter specifies the translation sequence 1222 * for which to construct the sense data. 1223 * @param[in,out] scsi_io This parameter specifies the user's IO request 1224 * for which to construct the sense data. 1225 * @param[in] ata_io This parameter is a pointer to the ATA IO data used 1226 * to get the ATA register fis. 1227 * @param[in] scsi_status This parameter specifies the SCSI status 1228 * value for the user's IO request. 1229 * @param[in] sense_key This parameter specifies the sense key to 1230 * be set for the user's IO request. 1231 * @param[in] additional_sense_code This parameter specifies the 1232 * additional sense code (ASC) key to be set for the user's 1233 * IO request. 1234 * @param[in] additional_sense_code_qualifier This parameter specifies 1235 * the additional sense code qualifier (ASCQ) key to be set 1236 * for the user's IO request. 1237 * 1238 * @return none 1239 */ 1240 static 1241 void sati_scsi_read_error_descriptor_sense_construct( 1242 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1243 void * scsi_io, 1244 void * ata_io, 1245 U8 scsi_status, 1246 U8 response_code, 1247 U8 sense_key, 1248 U8 additional_sense_code, 1249 U8 additional_sense_code_qualifier 1250 ) 1251 { 1252 U8 * sense_data; 1253 U32 sense_len; 1254 U8 information_buff[8] = {0}; 1255 1256 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 1257 1258 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1259 1260 information_buff[2] = sati_get_ata_lba_high_ext(register_fis); 1261 information_buff[3] = sati_get_ata_lba_mid_ext(register_fis); 1262 information_buff[4] = sati_get_ata_lba_low_ext(register_fis); 1263 information_buff[5] = sati_get_ata_lba_high(register_fis); 1264 information_buff[6] = sati_get_ata_lba_mid(register_fis); 1265 information_buff[7] = sati_get_ata_lba_low(register_fis); 1266 1267 sati_set_sense_data_byte( 1268 sense_data, 1269 sense_len, 1270 0, 1271 SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE 1272 ); 1273 1274 sati_scsi_common_descriptor_sense_construct( 1275 sequence, 1276 scsi_io, 1277 sense_data, 1278 sense_len, 1279 sense_key, 1280 additional_sense_code, 1281 additional_sense_code_qualifier, 1282 information_buff 1283 ); 1284 } 1285 1286 /** 1287 * @brief This method will construct the sense data buffer in the user's 1288 * sense data buffer location. Additionally, it will set the user's 1289 * SCSI status. This is used for uncorrectable read errors. 1290 * 1291 * @param[in] sequence This parameter specifies the translation sequence 1292 * for which to construct the sense data. 1293 * @param[in,out] scsi_io This parameter specifies the user's IO request 1294 * for which to construct the sense data. 1295 * @param[in] ata_io This parameter is a pointer to the ATA IO data used 1296 * to get the ATA register fis. 1297 * @param[in] scsi_status This parameter specifies the SCSI status 1298 * value for the user's IO request. 1299 * @param[in] sense_key This parameter specifies the sense key to 1300 * be set for the user's IO request. 1301 * @param[in] additional_sense_code This parameter specifies the 1302 * additional sense code (ASC) key to be set for the user's 1303 * IO request. 1304 * @param[in] additional_sense_code_qualifier This parameter specifies 1305 * the additional sense code qualifier (ASCQ) key to be set 1306 * for the user's IO request. 1307 * 1308 * @return none 1309 */ 1310 static 1311 void sati_scsi_read_error_fixed_sense_construct( 1312 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1313 void * scsi_io, 1314 void * ata_io, 1315 U8 scsi_status, 1316 U8 response_code, 1317 U8 sense_key, 1318 U8 additional_sense_code, 1319 U8 additional_sense_code_qualifier 1320 ) 1321 { 1322 U8 * sense_data; 1323 U32 sense_len; 1324 U8 valid = TRUE; 1325 1326 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 1327 1328 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1329 1330 if(sati_get_ata_lba_mid_ext(register_fis) > 0) 1331 { 1332 valid = FALSE; 1333 } 1334 1335 sati_set_sense_data_byte(sense_data, sense_len, 3, sati_get_ata_lba_low_ext(register_fis)); 1336 sati_set_sense_data_byte(sense_data, sense_len, 4, sati_get_ata_lba_high(register_fis)); 1337 sati_set_sense_data_byte(sense_data, sense_len, 5, sati_get_ata_lba_mid(register_fis)); 1338 sati_set_sense_data_byte(sense_data, sense_len, 6, sati_get_ata_lba_low(register_fis)); 1339 1340 1341 sati_set_sense_data_byte( 1342 sense_data, 1343 sense_len, 1344 0, 1345 (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE 1346 ); 1347 1348 sati_scsi_common_fixed_sense_construct( 1349 sense_data, 1350 sense_len, 1351 sense_key, 1352 additional_sense_code, 1353 additional_sense_code_qualifier 1354 ); 1355 } 1356 1357 void sati_scsi_read_error_sense_construct( 1358 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1359 void * scsi_io, 1360 void * ata_input_data, 1361 U8 scsi_status, 1362 U8 sense_key, 1363 U8 additional_sense_code, 1364 U8 additional_sense_code_qualifier 1365 ) 1366 { 1367 U8 response_code; 1368 1369 response_code = sati_scsi_get_sense_data_response_code(sequence); 1370 1371 switch (response_code) 1372 { 1373 case SCSI_FIXED_CURRENT_RESPONSE_CODE: 1374 case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 1375 sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1376 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1377 break; 1378 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 1379 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 1380 sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1381 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1382 break; 1383 } 1384 1385 sequence->is_sense_response_set = TRUE; 1386 } 1387 1388 /* 1389 * @brief This method builds the scsi response data for a sata task management 1390 * request. 1391 * 1392 * @param[in] sequence This parameter specifies the translation sequence 1393 * for which to construct the sense data. 1394 * @param[in,out] scsi_io This parameter specifies the user's IO request 1395 * for which to construct the sense data. 1396 * @param[in] response_data The response status for the task management 1397 * request. 1398 */ 1399 void sati_scsi_response_data_construct( 1400 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1401 void * scsi_io, 1402 U8 response_data 1403 ) 1404 { 1405 #ifdef SATI_TRANSPORT_SUPPORTS_SAS 1406 SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*) 1407 sati_cb_get_response_iu_address(scsi_io); 1408 rsp_iu->data_present = 0x01; 1409 rsp_iu->response_data_length[3] = sizeof(U32); 1410 rsp_iu->status = 0; 1411 ((U8 *)rsp_iu->data)[3] = response_data; 1412 #else 1413 #endif // SATI_TRANSPORT_SUPPORTS_SAS 1414 } 1415 1416 /** 1417 * @brief This method checks to make sure that the translation isn't 1418 * exceeding the allocation length specified in the CDB prior 1419 * to retrieving the payload data byte from the user's buffer. 1420 * 1421 * @param[in,out] scsi_io This parameter specifies the user's IO request 1422 * for which to set the user payload data byte. 1423 * @param[in] byte_offset This parameter specifies the offset into 1424 * the user's payload buffer at which to write the supplied 1425 * value. 1426 * @param[in] value This parameter specifies the memory location into 1427 * which to read the value from the user's payload buffer. 1428 * 1429 * @return none 1430 */ 1431 void sati_get_data_byte( 1432 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1433 void * scsi_io, 1434 U32 byte_offset, 1435 U8 * value 1436 ) 1437 { 1438 if (byte_offset < sequence->allocation_length) 1439 sati_cb_get_data_byte(scsi_io, byte_offset, value); 1440 } 1441 1442 /** 1443 * @brief This method checks to make sure that the translation isn't 1444 * exceeding the allocation length specified in the CDB while 1445 * translating payload data into the user's buffer. 1446 * 1447 * @param[in] sequence This parameter specifies the translation sequence 1448 * for which to set the user payload data byte. 1449 * @param[in,out] scsi_io This parameter specifies the user's IO request 1450 * for which to set the user payload data byte. 1451 * @param[in] byte_offset This parameter specifies the offset into 1452 * the user's payload buffer at which to write the supplied 1453 * value. 1454 * @param[in] value This parameter specifies the new value to be 1455 * written out into the user's payload buffer. 1456 * 1457 * @return none 1458 */ 1459 void sati_set_data_byte( 1460 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1461 void * scsi_io, 1462 U32 byte_offset, 1463 U8 value 1464 ) 1465 { 1466 if (byte_offset < sequence->allocation_length) 1467 { 1468 sequence->number_data_bytes_set++; 1469 sati_cb_set_data_byte(scsi_io, byte_offset, value); 1470 } 1471 } 1472 1473 /** 1474 * @brief This method checks to make sure that the translation isn't 1475 * exceeding the allocation length specified in the CDB while 1476 * translating payload data into the user's buffer. 1477 * 1478 * @param[in] sequence This parameter specifies the translation sequence 1479 * for which to set the user payload data dword. 1480 * @param[in,out] scsi_io This parameter specifies the user's IO request 1481 * for which to set the user payload data dword. 1482 * @param[in] byte_offset This parameter specifies the offset into 1483 * the user's payload buffer at which to write the supplied 1484 * value. 1485 * @param[in] value This parameter specifies the new value to be 1486 * written out into the user's payload buffer. 1487 * 1488 * @return none 1489 */ 1490 void sati_set_data_dword( 1491 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1492 void * scsi_io, 1493 U32 byte_offset, 1494 U32 value 1495 ) 1496 { 1497 /// @todo Check to ensure that the bytes appear correctly (SAS Address). 1498 1499 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF); 1500 byte_offset++; 1501 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF); 1502 byte_offset++; 1503 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF); 1504 byte_offset++; 1505 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF); 1506 } 1507 1508 /** 1509 * @brief This method will construct the ATA flush cache command. 1510 * 1511 * @pre It is expected that the user has properly set the current contents 1512 * of the register FIS to 0. 1513 * 1514 * @param[out] ata_io This parameter specifies the ATA IO request structure 1515 * for which to build the FLUSH CACHE command. 1516 * @param[in] sequence This parameter specifies the translator sequence 1517 * for which the command is being constructed. 1518 * 1519 * @return none. 1520 */ 1521 void sati_ata_flush_cache_construct( 1522 void * ata_io, 1523 SATI_TRANSLATOR_SEQUENCE_T * sequence 1524 ) 1525 { 1526 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1527 1528 sati_set_ata_command(register_fis, ATA_FLUSH_CACHE); 1529 sati_ata_non_data_command(ata_io, sequence); 1530 } 1531 1532 /** 1533 * @brief This method will construct the ATA standby immediate command. 1534 * 1535 * @pre It is expected that the user has properly set the current contents 1536 * of the register FIS to 0. 1537 * 1538 * @param[out] ata_io This parameter specifies the ATA IO request structure 1539 * for which to build the STANDBY IMMEDIATE command. 1540 * @param[in] sequence This parameter specifies the translator sequence 1541 * for which the command is being constructed. 1542 * 1543 * @param[in] count This parameter specifies the time period programmed 1544 * into the Standby Timer. See ATA8 spec for more details 1545 * @return none. 1546 */ 1547 void sati_ata_standby_construct( 1548 void * ata_io, 1549 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1550 U16 count 1551 ) 1552 { 1553 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1554 1555 sati_set_ata_command(register_fis, ATA_STANDBY); 1556 sati_set_ata_sector_count(register_fis, count); 1557 1558 sequence->device->ata_standby_timer = (U8) count; 1559 1560 sati_ata_non_data_command(ata_io, sequence); 1561 } 1562 1563 /** 1564 * @brief This method will construct the ATA standby immediate command. 1565 * 1566 * @pre It is expected that the user has properly set the current contents 1567 * of the register FIS to 0. 1568 * 1569 * @param[out] ata_io This parameter specifies the ATA IO request structure 1570 * for which to build the STANDBY IMMEDIATE command. 1571 * @param[in] sequence This parameter specifies the translator sequence 1572 * for which the command is being constructed. 1573 * 1574 * @return none. 1575 */ 1576 void sati_ata_standby_immediate_construct( 1577 void * ata_io, 1578 SATI_TRANSLATOR_SEQUENCE_T * sequence 1579 ) 1580 { 1581 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1582 1583 sati_set_ata_command(register_fis, ATA_STANDBY_IMMED); 1584 sati_ata_non_data_command(ata_io, sequence); 1585 } 1586 1587 /** 1588 * @brief This method will construct the ATA idle immediate command. 1589 * 1590 * @pre It is expected that the user has properly set the current contents 1591 * of the register FIS to 0. 1592 * 1593 * @param[out] ata_io This parameter specifies the ATA IO request structure 1594 * for which to build the IDLE IMMEDIATE command. 1595 * @param[in] sequence This parameter specifies the translator sequence 1596 * for which the command is being constructed. 1597 * 1598 * @return none. 1599 */ 1600 void sati_ata_idle_immediate_construct( 1601 void * ata_io, 1602 SATI_TRANSLATOR_SEQUENCE_T * sequence 1603 ) 1604 { 1605 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1606 1607 sati_set_ata_command(register_fis, ATA_IDLE_IMMED); 1608 sati_set_ata_features(register_fis, 0x00); 1609 sati_set_ata_sector_count(register_fis, 0x00); 1610 sati_set_ata_lba_high(register_fis, 0x00); 1611 sati_set_ata_lba_mid(register_fis, 0x00); 1612 sati_set_ata_lba_low(register_fis, 0x00); 1613 sati_ata_non_data_command(ata_io, sequence); 1614 } 1615 1616 /** 1617 * @brief This method will construct the ATA idle immediate command 1618 for Unload Features. 1619 * 1620 * @pre It is expected that the user has properly set the current contents 1621 * of the register FIS to 0. 1622 * 1623 * @param[out] ata_io This parameter specifies the ATA IO request structure 1624 * for which to build the IDLE IMMEDIATE command. 1625 * @param[in] sequence This parameter specifies the translator sequence 1626 * for which the command is being constructed. 1627 * 1628 * @return none. 1629 */ 1630 void sati_ata_idle_immediate_unload_construct( 1631 void * ata_io, 1632 SATI_TRANSLATOR_SEQUENCE_T * sequence 1633 ) 1634 { 1635 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1636 1637 sati_set_ata_command(register_fis, ATA_IDLE_IMMED); 1638 sati_set_ata_features(register_fis, 0x44); 1639 sati_set_ata_sector_count(register_fis, 0x00); 1640 sati_set_ata_lba_high(register_fis, 0x55); 1641 sati_set_ata_lba_mid(register_fis, 0x4E); 1642 sati_set_ata_lba_low(register_fis, 0x4C); 1643 sati_ata_non_data_command(ata_io, sequence); 1644 } 1645 1646 /** 1647 * @brief This method will construct the ATA IDLE command.\ 1648 * 1649 * @pre It is expected that the user has properly set the current contents 1650 * of the register FIS to 0. 1651 * 1652 * @param[out] ata_io This parameter specifies the ATA IO request structure 1653 * for which to build the ATA IDLE command. 1654 * @param[in] sequence This parameter specifies the translator sequence 1655 * for which the command is being constructed. 1656 * 1657 * @return none. 1658 */ 1659 void sati_ata_idle_construct( 1660 void * ata_io, 1661 SATI_TRANSLATOR_SEQUENCE_T * sequence 1662 ) 1663 { 1664 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1665 1666 sati_set_ata_command(register_fis, ATA_IDLE); 1667 sati_set_ata_features(register_fis, 0x00); 1668 sati_set_ata_sector_count(register_fis, 0x00); 1669 1670 sequence->device->ata_standby_timer = 0x00; 1671 1672 sati_set_ata_lba_high(register_fis, 0x00); 1673 sati_set_ata_lba_mid(register_fis, 0x00); 1674 sati_set_ata_lba_low(register_fis, 0x00); 1675 sati_ata_non_data_command(ata_io, sequence); 1676 } 1677 1678 /** 1679 * @brief This method will construct the ATA MEDIA EJECT command. 1680 * 1681 * @pre It is expected that the user has properly set the current contents 1682 * of the register FIS to 0. 1683 * 1684 * @param[out] ata_io This parameter specifies the ATA IO request structure 1685 * for which to build the MEDIA EJCT command. 1686 * @param[in] sequence This parameter specifies the translator sequence 1687 * for which the command is being constructed. 1688 * 1689 * @return none. 1690 */ 1691 void sati_ata_media_eject_construct( 1692 void * ata_io, 1693 SATI_TRANSLATOR_SEQUENCE_T * sequence 1694 ) 1695 { 1696 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1697 1698 sati_set_ata_command(register_fis, ATA_MEDIA_EJECT); 1699 sati_ata_non_data_command(ata_io, sequence); 1700 } 1701 1702 1703 /** 1704 * @brief This method will construct the ATA read verify sector(s) command. 1705 * 1706 * @pre It is expected that the user has properly set the current contents 1707 * of the register FIS to 0. 1708 * 1709 * @param[out] ata_io This parameter specifies the ATA IO request structure 1710 * for which to build the ATA READ VERIFY SECTOR(S) command. 1711 * @param[in] sequence This parameter specifies the translator sequence 1712 * for which the command is being constructed. 1713 * 1714 * @return none. 1715 */ 1716 void sati_ata_read_verify_sectors_construct( 1717 void * ata_io, 1718 SATI_TRANSLATOR_SEQUENCE_T * sequence 1719 ) 1720 { 1721 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1722 1723 sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS); 1724 1725 //According to SAT-2 (v7) 9.11.3 1726 sati_set_ata_sector_count(register_fis, 1); 1727 1728 //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the 1729 //maximum LBA supported by the ATA device in its current configuration. 1730 //From the unit test, it seems we have to set LBA to a non-zero value. 1731 sati_set_ata_lba_low(register_fis, 1); 1732 1733 sati_ata_non_data_command(ata_io, sequence); 1734 } 1735 1736 /** 1737 * @brief This method will construct a ATA SMART Return Status command so the 1738 * status of the ATA device can be returned. The status of the SMART 1739 * threshold will be returned by this command. 1740 * 1741 * @return N/A 1742 * 1743 */ 1744 void sati_ata_smart_return_status_construct( 1745 void * ata_io, 1746 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1747 U8 feature_value 1748 ) 1749 { 1750 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1751 1752 sati_set_ata_command(register_fis, ATA_SMART); 1753 1754 sati_set_ata_features(register_fis, feature_value); 1755 1756 sati_set_ata_lba_high(register_fis, 0xC2); 1757 sati_set_ata_lba_mid(register_fis, 0x4F); 1758 1759 sati_ata_non_data_command(ata_io, sequence); 1760 } 1761 1762 /** 1763 * @brief This method will construct a ATA SMART Return Status command so the 1764 * status of the ATA device can be returned. The status of the SMART 1765 * threshold will be returned by this command. 1766 * 1767 * @return N/A 1768 * 1769 */ 1770 void sati_ata_smart_read_log_construct( 1771 void * ata_io, 1772 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1773 U8 log_address, 1774 U32 transfer_length 1775 ) 1776 { 1777 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1778 1779 sati_set_ata_command(register_fis, ATA_SMART); 1780 sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG); 1781 1782 sati_set_ata_lba_high(register_fis, 0xC2); 1783 sati_set_ata_lba_mid(register_fis, 0x4F); 1784 sati_set_ata_lba_low(register_fis, log_address); 1785 1786 sequence->data_direction = SATI_DATA_DIRECTION_IN; 1787 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 1788 sequence->ata_transfer_length = transfer_length; 1789 } 1790 1791 /** 1792 * @brief This method will construct a Write Uncorrectable ATA command that 1793 * will write one sector with a pseudo or flagged error. The type of 1794 * error is specified by the feature value. 1795 * 1796 * @return N/A 1797 * 1798 */ 1799 void sati_ata_write_uncorrectable_construct( 1800 void * ata_io, 1801 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1802 U8 feature_value 1803 ) 1804 { 1805 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1806 1807 sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE); 1808 sati_set_ata_features(register_fis, feature_value); 1809 sati_set_ata_sector_count(register_fis, 0x0001); 1810 sati_ata_non_data_command(ata_io, sequence); 1811 } 1812 1813 /** 1814 * @brief This method will construct a Mode Select ATA SET FEATURES command 1815 * For example, Enable/Disable Write Cache, Enable/Disable Read Ahead 1816 * 1817 * @return N/A 1818 * 1819 */ 1820 void sati_ata_set_features_construct( 1821 void * ata_io, 1822 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1823 U8 feature 1824 ) 1825 { 1826 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1827 1828 sati_set_ata_command(register_fis, ATA_SET_FEATURES); 1829 sati_set_ata_features(register_fis, feature); 1830 sati_ata_non_data_command(ata_io, sequence); 1831 } 1832 1833 1834 1835 /** 1836 * @brief This method will construct a Read Log ext ATA command that 1837 * will request a log page based on the log_address. 1838 * 1839 * @param[in] log_address This parameter specifies the log page 1840 * to be returned from Read Log Ext. 1841 * 1842 * @param[in] transfer_length This parameter specifies the size of the 1843 * log page response returned by Read Log Ext. 1844 * 1845 * @return N/A 1846 * 1847 */ 1848 void sati_ata_read_log_ext_construct( 1849 void * ata_io, 1850 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1851 U8 log_address, 1852 U32 transfer_length 1853 ) 1854 { 1855 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1856 1857 sati_set_ata_command(register_fis, ATA_READ_LOG_EXT); 1858 1859 sati_set_ata_lba_low(register_fis, log_address); 1860 sati_set_ata_lba_mid(register_fis, 0x00); 1861 sati_set_ata_lba_mid_exp(register_fis, 0x00); 1862 1863 sati_set_ata_sector_count(register_fis, 0x01); 1864 1865 sequence->data_direction = SATI_DATA_DIRECTION_IN; 1866 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 1867 sequence->ata_transfer_length = transfer_length; 1868 1869 } 1870 1871 /** 1872 * @brief This method will check if the ATA device is in the stopped power 1873 * state. This is used for all medium access commands for SAT 1874 * compliance. See SAT2r07 section 9.11.1 1875 * 1876 * @param[in] sequence - SATI sequence data with the device state. 1877 * 1878 * @return TRUE If device is stopped 1879 * 1880 */ 1881 BOOL sati_device_state_stopped( 1882 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1883 void * scsi_io 1884 ) 1885 { 1886 if(sequence->device->state == SATI_DEVICE_STATE_STOPPED) 1887 { 1888 sati_scsi_sense_data_construct( 1889 sequence, 1890 scsi_io, 1891 SCSI_STATUS_CHECK_CONDITION, 1892 SCSI_SENSE_NOT_READY , 1893 SCSI_ASC_INITIALIZING_COMMAND_REQUIRED, 1894 SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 1895 ); 1896 return TRUE; 1897 } 1898 return FALSE; 1899 } 1900 1901 /** 1902 * @brief This method will construct a ATA Read Buffer command that 1903 * will request PIO in data containing the target device's buffer. 1904 * 1905 * @param[out] ata_io This parameter specifies the ATA IO request structure 1906 * for which to build the ATA READ VERIFY SECTOR(S) command. 1907 * @param[in] sequence This parameter specifies the translator sequence 1908 * for which the command is being constructed. 1909 * @return N/A 1910 * 1911 */ 1912 void sati_ata_read_buffer_construct( 1913 void * ata_io, 1914 SATI_TRANSLATOR_SEQUENCE_T * sequence 1915 ) 1916 { 1917 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1918 1919 sati_set_ata_command(register_fis, ATA_READ_BUFFER); 1920 sequence->data_direction = SATI_DATA_DIRECTION_IN; 1921 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 1922 sequence->ata_transfer_length = 512; 1923 } 1924 1925 1926 /** 1927 * @brief This method will construct a ATA Write Buffer command that 1928 * will send PIO out data to the target device's buffer. 1929 * 1930 * @param[out] ata_io This parameter specifies the ATA IO request structure 1931 * for which to build the ATA READ VERIFY SECTOR(S) command. 1932 * @param[in] sequence This parameter specifies the translator sequence 1933 * for which the command is being constructed. 1934 * @return N/A 1935 * 1936 */ 1937 void sati_ata_write_buffer_construct( 1938 void * ata_io, 1939 SATI_TRANSLATOR_SEQUENCE_T * sequence 1940 ) 1941 { 1942 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1943 1944 sati_set_ata_command(register_fis, ATA_WRITE_BUFFER); 1945 1946 sequence->data_direction = SATI_DATA_DIRECTION_OUT; 1947 sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT; 1948 sequence->ata_transfer_length = 512; 1949 } 1950 1951 1952 /** 1953 * @brief This method will construct a ATA Download Microcode command that 1954 * will send PIO out data containing new firmware for the target drive. 1955 * 1956 * @param[out] ata_io This parameter specifies the ATA IO request structure 1957 * for which to build the ATA READ VERIFY SECTOR(S) command. 1958 * @param[in] sequence This parameter specifies the translator sequence 1959 * for which the command is being constructed. 1960 * @param[in] mode This parameter specifies the download microcode sub-command 1961 * code. 1962 * @param[in] allocation_length This parameter specifies the number of bytes 1963 * being sent to the target device. 1964 * @param[in] buffer_offset This parameter specifies the buffer offset for the 1965 * data sent to the target device. 1966 * 1967 * @return N/A 1968 * 1969 */ 1970 void sati_ata_download_microcode_construct( 1971 void * ata_io, 1972 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1973 U8 mode, 1974 U32 allocation_length, 1975 U32 buffer_offset 1976 ) 1977 { 1978 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1979 U32 allocation_blocks = allocation_length >> 9; 1980 U32 buffer_blkoffset = buffer_offset >> 9; 1981 1982 sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE); 1983 sati_set_ata_features(register_fis, mode); 1984 1985 if(mode == ATA_MICROCODE_DOWNLOAD_SAVE) 1986 { 1987 sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9)); 1988 sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17)); 1989 } 1990 else //mode == 0x03 1991 { 1992 sati_set_ata_sector_count(register_fis, (U8) (allocation_blocks & 0xff)); 1993 sati_set_ata_lba_low(register_fis, (U8) ((allocation_blocks >> 8) & 0xff)); 1994 sati_set_ata_lba_mid(register_fis, (U8) (buffer_blkoffset & 0xff)); 1995 sati_set_ata_lba_high(register_fis, (U8) ((buffer_blkoffset >> 8) & 0xff)); 1996 } 1997 1998 if((allocation_length == 0) && (buffer_offset == 0)) 1999 { 2000 sati_ata_non_data_command(ata_io, sequence); 2001 } 2002 else 2003 { 2004 sequence->data_direction = SATI_DATA_DIRECTION_OUT; 2005 sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT; 2006 sequence->ata_transfer_length = allocation_length; 2007 } 2008 } 2009