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 the method definitions to translate 59 * SCSI Log Sense command based of the SATv2 spec. 60 */ 61 62 #if !defined(DISABLE_SATI_LOG_SENSE) 63 64 #include <dev/isci/scil/sati_log_sense.h> 65 #include <dev/isci/scil/sati_callbacks.h> 66 #include <dev/isci/scil/sati_util.h> 67 68 //****************************************************************************** 69 //* P R I V A T E M E T H O D S 70 //****************************************************************************** 71 72 /** 73 * @brief This method constructs the SATI supported log page. This is a log 74 * containing the page codes of all the SATI supported log pages. 75 * 76 * @return n/a 77 * 78 */ 79 static 80 void sati_supported_log_page_construct( 81 SATI_TRANSLATOR_SEQUENCE_T * sequence, 82 void * scsi_io 83 ) 84 { 85 U32 next_byte; 86 //set SPF = 0 and PAGE_CODE = 0 87 sati_set_data_byte(sequence, scsi_io, 0, 0x00); 88 89 //set SUBPAGE_CODE = 0 90 sati_set_data_byte(sequence, scsi_io, 1, 0x00); 91 92 //set the Page Length to (n-3) or 2 because only two log pages are supported 93 sati_set_data_byte(sequence, scsi_io, 2, 0x00); 94 sati_set_data_byte(sequence, scsi_io, 3, 0x02); 95 96 //specify the next byte to be set 97 next_byte = 4; 98 99 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT) 100 { 101 sati_set_data_byte( 102 sequence, 103 scsi_io, 104 next_byte, 105 SCSI_LOG_PAGE_INFORMATION_EXCEPTION 106 ); 107 next_byte = 5; 108 } 109 110 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT) 111 { 112 sati_set_data_byte( 113 sequence, 114 scsi_io, 115 next_byte, 116 SCSI_LOG_PAGE_SELF_TEST 117 ); 118 } 119 } 120 121 /** 122 * @brief This method sets bytes 4-19 of the self-test log parameter to zero. 123 * 124 * @return n/a 125 * 126 */ 127 static 128 void sati_set_parameters_to_zero( 129 SATI_TRANSLATOR_SEQUENCE_T * sequence, 130 void * scsi_io 131 ) 132 { 133 sati_set_data_byte(sequence, scsi_io, 8, 0x00); //log_parameter byte 4 134 sati_set_data_byte(sequence, scsi_io, 9, 0x00); //log_parameter byte 5 135 sati_set_data_byte(sequence, scsi_io, 10, 0x00); //log_parameter byte 6 136 sati_set_data_byte(sequence, scsi_io, 11, 0x00); //log_parameter byte 7 137 sati_set_data_byte(sequence, scsi_io, 12, 0x00); //log_parameter byte 8 138 sati_set_data_byte(sequence, scsi_io, 13, 0x00); //log_parameter byte 9 139 sati_set_data_byte(sequence, scsi_io, 14, 0x00); //log_parameter byte 10 140 sati_set_data_byte(sequence, scsi_io, 15, 0x00); //log_parameter byte 11 141 sati_set_data_byte(sequence, scsi_io, 16, 0x00); //log_parameter byte 12 142 sati_set_data_byte(sequence, scsi_io, 17, 0x00); //log_parameter byte 13 143 sati_set_data_byte(sequence, scsi_io, 18, 0x00); //log_parameter byte 14 144 sati_set_data_byte(sequence, scsi_io, 19, 0x00); //log_parameter byte 15 145 sati_set_data_byte(sequence, scsi_io, 20, 0x00); //log_parameter byte 16 146 sati_set_data_byte(sequence, scsi_io, 21, 0x00); //log_parameter byte 17 147 sati_set_data_byte(sequence, scsi_io, 22, 0x00); //log_parameter byte 18 148 sati_set_data_byte(sequence, scsi_io, 23, 0x00); //log_parameter byte 19 149 } 150 151 /** 152 * @brief This method translates the ATA Extended SMART self-test log into 153 * SCSI Sense Key, Additional Sense Code, and Additional Sense code 154 * qualifiers based on the self test status byte in the appropriate 155 * descriptor entry. 156 * 157 * @return n/a 158 * 159 */ 160 static 161 void sati_translate_sense_values( 162 SATI_TRANSLATOR_SEQUENCE_T * sequence, 163 void * scsi_io, 164 U8 self_test_status_byte 165 ) 166 { 167 //byte 17 168 sati_set_data_byte( 169 sequence, 170 scsi_io, 171 21, 172 SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT 173 ); 174 175 switch(self_test_status_byte) 176 { 177 case 1: 178 //byte 16 179 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND); 180 181 //byte 18 182 sati_set_data_byte(sequence, scsi_io, 22, 0x81); 183 break; 184 185 case 2: 186 //byte 16 187 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND); 188 189 //byte 18 190 sati_set_data_byte(sequence, scsi_io, 22, 0x82); 191 break; 192 193 case 3: 194 //byte 16 195 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND); 196 197 //byte 18 198 sati_set_data_byte(sequence, scsi_io, 22, 0x83); 199 break; 200 201 case 4: 202 //byte 16 203 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR); 204 205 //byte 18 206 sati_set_data_byte(sequence, scsi_io, 22, 0x84); 207 break; 208 209 case 5: 210 //byte 16 211 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR); 212 213 //byte 18 214 sati_set_data_byte(sequence, scsi_io, 22, 0x85); 215 break; 216 217 case 6: 218 //byte 16 219 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR); 220 221 //byte 18 222 sati_set_data_byte(sequence, scsi_io, 22, 0x86); 223 break; 224 225 case 7: 226 //byte 16 227 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_MEDIUM_ERROR); 228 229 //byte 18 230 sati_set_data_byte(sequence, scsi_io, 22, 0x87); 231 break; 232 233 case 8: 234 //byte 16 235 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR); 236 237 //byte 18 238 sati_set_data_byte(sequence, scsi_io, 22, 0x88); 239 break; 240 241 default: 242 //byte 16 243 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_NO_SENSE); 244 //byte 17 245 sati_set_data_byte(sequence, scsi_io, 21, SCSI_ASC_NO_ADDITIONAL_SENSE); 246 //byte 18 247 sati_set_data_byte(sequence, scsi_io, 22, 0x00); 248 break; 249 } 250 251 } 252 253 /** 254 * @brief This method retrieves the correct self-test results by checking the 255 * descriptor index in the extended SMART self-test log. The index is 256 * used to determine the appropriate descriptor entry. 257 * 258 * @return n/a 259 * 260 */ 261 static 262 void sati_get_self_test_results( 263 SATI_TRANSLATOR_SEQUENCE_T * sequence, 264 void * scsi_io, 265 ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log 266 ) 267 { 268 U16 descriptor_index = *((U16 *)(&ata_log->self_test_descriptor_index[0])); 269 270 /* 271 * SATv2 wants data from descriptor N where N is equal to 272 * (descriptor_index - parameter_code) + 1. Since parameter 273 * code is always 0x0001 just checking descriptor_index. 274 */ 275 276 if(descriptor_index <= 0) 277 { 278 sati_set_parameters_to_zero(sequence, scsi_io); 279 } 280 else 281 { 282 sati_set_data_byte( 283 sequence, 284 scsi_io, 285 8, 286 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte 287 ); 288 289 //Sef-test number unspecified per satv2 290 sati_set_data_byte(sequence, scsi_io, 9, 0x00); 291 sati_set_data_byte( 292 sequence, 293 scsi_io, 294 10, 295 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_high 296 ); 297 298 sati_set_data_byte( 299 sequence, 300 scsi_io, 301 11, 302 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_low 303 ); 304 305 //set to zero because it's a 48bit address 306 sati_set_data_byte(sequence, scsi_io, 12, 0x00); 307 sati_set_data_byte(sequence, scsi_io, 13, 0x00); 308 309 sati_set_data_byte( 310 sequence, 311 scsi_io, 312 14, 313 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high_ext 314 ); 315 316 sati_set_data_byte( 317 sequence, 318 scsi_io, 319 15, 320 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid_ext 321 ); 322 323 sati_set_data_byte( 324 sequence, 325 scsi_io, 326 16, 327 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low_ext 328 ); 329 330 sati_set_data_byte( 331 sequence, 332 scsi_io, 333 17, 334 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high 335 ); 336 337 sati_set_data_byte( 338 sequence, 339 scsi_io, 340 18, 341 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid 342 ); 343 344 sati_set_data_byte( 345 sequence, 346 scsi_io, 347 19, 348 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low 349 ); 350 351 sati_translate_sense_values( 352 sequence, 353 scsi_io, 354 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte 355 ); 356 } 357 } 358 359 /** 360 * @brief This method will construct the first eight bytes of the SCSI self test 361 * log page for both cases when SATI sends a ATA read log ext and a smart 362 * read log command. 363 * 364 * @return n/a 365 * 366 */ 367 static 368 void sati_self_test_log_header_construct( 369 SATI_TRANSLATOR_SEQUENCE_T * sequence, 370 void * scsi_io 371 ) 372 { 373 //PAGE CODE for Self-Test Log Page 374 sati_set_data_byte(sequence, scsi_io, 0, 0x10); 375 sati_set_data_byte(sequence, scsi_io, 1, 0x00); 376 377 //PAGE LENGTH is 0x14 instead of 0x190, not returning 20/0x190 log perameters 378 sati_set_data_byte(sequence, scsi_io, 2, 0x00); 379 sati_set_data_byte(sequence, scsi_io, 3, 0x14); 380 381 /* 382 * Log PARAMETER 0x0001 383 * Only sending one log parameter per self-test request. 384 */ 385 sati_set_data_byte(sequence, scsi_io, 4, 0x00); //log_parameter byte 0 386 sati_set_data_byte(sequence, scsi_io, 5, 0x01); //log_parameter byte 1 387 388 //Set to 0x03 per SATv2 spec 389 sati_set_data_byte(sequence, scsi_io, 6, 0x03); //log_parameter byte 2 390 391 //Parameter Length set to 0x10 per SATv2 spec 392 sati_set_data_byte(sequence, scsi_io, 7, 0x10); //log_parameter byte 3 393 } 394 395 /** 396 * @brief This method will construct the SCSI self test log page from 397 * the Extended SMART self-test log response recieved from the 398 * ATA device. The response is from a ATA_Read_Log_EXT command 399 * issued by SATI. 400 * 401 * @return n/a 402 * 403 */ 404 static 405 void sati_extended_self_test_log_page_construct( 406 SATI_TRANSLATOR_SEQUENCE_T * sequence, 407 void * scsi_io, 408 void * ata_data 409 ) 410 { 411 ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log = 412 (ATA_EXTENDED_SMART_SELF_TEST_LOG_T*) ata_data; 413 414 sati_self_test_log_header_construct(sequence, scsi_io); 415 416 //bytes 4-19 417 if( (ata_log->self_test_descriptor_index[0] == 0) && 418 (ata_log->self_test_descriptor_index[1] == 0)) 419 { 420 sati_set_parameters_to_zero(sequence, scsi_io); 421 } 422 else 423 { 424 sati_get_self_test_results(sequence, scsi_io, ata_log); 425 } 426 } 427 428 /** 429 * @brief This method will construct the SCSI self test log page from 430 * the SMART self-test log response recieved from the ATA device. 431 * The response is from a ATA_SMART_Read_Log command issued by SATI. 432 * 433 * @return n/a 434 * 435 */ 436 static 437 void sati_self_test_log_page_construct( 438 SATI_TRANSLATOR_SEQUENCE_T * sequence, 439 void * scsi_io, 440 void * ata_data 441 ) 442 { 443 ATA_SMART_SELF_TEST_LOG_T * ata_log = 444 (ATA_SMART_SELF_TEST_LOG_T*) ata_data; 445 446 sati_self_test_log_header_construct(sequence, scsi_io); 447 448 //first descriptor entry(index == 0) is always used because scsi_parameter_code == 1 449 sati_set_data_byte( 450 sequence, 451 scsi_io, 452 8, 453 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte 454 ); 455 456 //Sef-test number unspecified per satv2 457 sati_set_data_byte(sequence, scsi_io, 9, 0x00); 458 459 sati_set_data_byte( 460 sequence, 461 scsi_io, 462 10, 463 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_high 464 ); 465 466 sati_set_data_byte( 467 sequence, 468 scsi_io, 469 11, 470 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_low 471 ); 472 473 //set to zero because it's a 28bit address 474 sati_set_data_byte(sequence, scsi_io, 12, 0x00); 475 sati_set_data_byte(sequence, scsi_io, 13, 0x00); 476 sati_set_data_byte(sequence, scsi_io, 14, 0x00); 477 sati_set_data_byte(sequence, scsi_io, 15, 0x00); 478 479 sati_set_data_byte( 480 sequence, 481 scsi_io, 482 16, 483 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low_ext 484 ); 485 486 sati_set_data_byte( 487 sequence, 488 scsi_io, 489 17, 490 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_high 491 ); 492 493 sati_set_data_byte( 494 sequence, 495 scsi_io, 496 18, 497 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_mid 498 ); 499 500 sati_set_data_byte( 501 sequence, 502 scsi_io, 503 19, 504 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low 505 ); 506 507 sati_translate_sense_values( 508 sequence, 509 scsi_io, 510 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte 511 ); 512 } 513 514 /** 515 * @brief This method will construct the SCSI information exception log page from 516 * the ATA SMART response recieved from the ATA device. The response is 517 * from a ATA SMART return status command issued by SATI. 518 * 519 * @return n/a 520 * 521 */ 522 static 523 void sati_information_exception_log_page_contruct( 524 SATI_TRANSLATOR_SEQUENCE_T * sequence, 525 void * scsi_io, 526 void * ata_io 527 ) 528 { 529 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 530 U32 mid_register = sati_get_ata_lba_mid(register_fis); 531 U32 high_register = sati_get_ata_lba_high(register_fis); 532 533 //Information Exception Page code 534 sati_set_data_byte( 535 sequence, 536 scsi_io, 537 0, 538 SCSI_LOG_PAGE_INFORMATION_EXCEPTION 539 ); 540 541 //Sub-page code 542 sati_set_data_byte(sequence, scsi_io, 1, 0x00); 543 544 //Page length of log parameters 545 sati_set_data_byte(sequence, scsi_io, 2, 0x00); 546 sati_set_data_byte(sequence, scsi_io, 3, 0x08); 547 548 //parameter code 549 sati_set_data_byte(sequence, scsi_io, 4, 0x00); 550 sati_set_data_byte(sequence, scsi_io, 5, 0x00); 551 552 //Format and Linking 553 sati_set_data_byte(sequence, scsi_io, 6, 0x03); 554 //Parameter Length 555 sati_set_data_byte(sequence, scsi_io, 7, 0x04); 556 557 if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED 558 && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED) 559 { 560 sati_set_data_byte( 561 sequence, 562 scsi_io, 563 8, 564 SCSI_ASC_HARDWARE_IMPENDING_FAILURE 565 ); 566 567 sati_set_data_byte( 568 sequence, 569 scsi_io, 570 9, 571 SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE 572 ); 573 } 574 else 575 { 576 sati_set_data_byte(sequence, scsi_io, 8, SCSI_ASC_NO_ADDITIONAL_SENSE); 577 sati_set_data_byte(sequence, scsi_io, 9, SCSI_ASCQ_NO_ADDITIONAL_SENSE); 578 } 579 //setting most recent temperature reading to 0xFF(not supported) for now. 580 sati_set_data_byte(sequence, scsi_io, 10, 0xFF); 581 } 582 583 //****************************************************************************** 584 //* P U B L I C M E T H O D S 585 //****************************************************************************** 586 587 /** 588 * @brief This method will translate the SCSI Log Sense command into ATA commands 589 * specified by SATv2. ATA commands Read Log EXT and SMART Read Log will 590 * be issued by this translation. 591 * 592 * @return SATI_STATUS Indicates if the command translation succeeded. 593 * 594 */ 595 SATI_STATUS sati_log_sense_translate_command( 596 SATI_TRANSLATOR_SEQUENCE_T * sequence, 597 void * scsi_io, 598 void * ata_io 599 ) 600 { 601 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 602 SATI_STATUS status = SATI_FAILURE; 603 604 if(SATI_LOG_SENSE_GET_PC_FIELD(cdb) == 1 && 605 (sati_get_cdb_byte(cdb, 3) == 0)) 606 { 607 sequence->allocation_length = (sati_get_cdb_byte(cdb, 7) << 8) | 608 (sati_get_cdb_byte(cdb, 8)); 609 610 switch(SATI_LOG_SENSE_GET_PAGE_CODE(cdb)) 611 { 612 //Return Supported Log Pages log page 613 case SCSI_LOG_PAGE_SUPPORTED_PAGES : 614 sati_supported_log_page_construct(sequence, scsi_io); 615 sequence->type = SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE; 616 status = SATI_COMPLETE; 617 break; 618 619 //Return Self-Test Results log page 620 case SCSI_LOG_PAGE_SELF_TEST : 621 622 if((sequence->device->capabilities & 623 SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT) == 0) 624 { 625 sati_scsi_sense_data_construct( 626 sequence, 627 scsi_io, 628 SCSI_STATUS_CHECK_CONDITION, 629 SCSI_SENSE_ILLEGAL_REQUEST, 630 SCSI_ASC_INVALID_FIELD_IN_CDB, 631 SCSI_ASCQ_INVALID_FIELD_IN_CDB 632 ); 633 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 634 } 635 else 636 { 637 //check if 48-bit Address feature set is supported 638 if((sequence->device->capabilities & 639 SATI_DEVICE_CAP_48BIT_ENABLE)) 640 { 641 //ATA Read Log Ext with log address set to 0x07 642 sati_ata_read_log_ext_construct( 643 ata_io, 644 sequence, 645 ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST, 646 sizeof(ATA_EXTENDED_SMART_SELF_TEST_LOG_T) 647 ); 648 sequence->type = 649 SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE; 650 status = SATI_SUCCESS; 651 } 652 else 653 { 654 //ATA Smart Read Log with log address set to 0x06 655 sati_ata_smart_read_log_construct( 656 ata_io, 657 sequence, 658 ATA_LOG_PAGE_SMART_SELF_TEST, 659 sizeof(ATA_SMART_SELF_TEST_LOG_T) 660 ); 661 sequence->type = SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE; 662 status = SATI_SUCCESS; 663 } 664 } 665 break; 666 667 //Return Informational Exceptions log page 668 case SCSI_LOG_PAGE_INFORMATION_EXCEPTION : 669 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT) 670 { 671 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE) 672 { 673 sati_ata_smart_return_status_construct( 674 ata_io, 675 sequence, 676 ATA_SMART_SUB_CMD_RETURN_STATUS 677 ); 678 sequence->type = 679 SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE; 680 status = SATI_SUCCESS; 681 } 682 else 683 { 684 sati_scsi_sense_data_construct( 685 sequence, 686 scsi_io, 687 SCSI_STATUS_CHECK_CONDITION, 688 SCSI_SENSE_ABORTED_COMMAND, 689 SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED, 690 SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED 691 ); 692 693 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 694 } 695 } 696 else 697 { 698 sati_scsi_sense_data_construct( 699 sequence, 700 scsi_io, 701 SCSI_STATUS_CHECK_CONDITION, 702 SCSI_SENSE_ILLEGAL_REQUEST, 703 SCSI_ASC_INVALID_FIELD_IN_CDB, 704 SCSI_ASCQ_INVALID_FIELD_IN_CDB 705 ); 706 707 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 708 } 709 break; 710 default : 711 //UNSPECIFIED SATv2r9 712 sati_scsi_sense_data_construct( 713 sequence, 714 scsi_io, 715 SCSI_STATUS_CHECK_CONDITION, 716 SCSI_SENSE_ILLEGAL_REQUEST, 717 SCSI_ASC_NO_ADDITIONAL_SENSE , 718 SCSI_ASCQ_NO_ADDITIONAL_SENSE 719 ); 720 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 721 break; 722 } 723 } 724 return status; 725 } 726 727 /** 728 * @brief This method will translate the response to the SATI Log Sense 729 * translation. ATA command responses will be translated into the 730 * correct SCSI log pages to be returned by SATI. 731 * 732 * @return SATI_STATUS Indicates if the response translation succeeded. 733 * 734 */ 735 SATI_STATUS sati_log_sense_translate_response( 736 SATI_TRANSLATOR_SEQUENCE_T * sequence, 737 void * scsi_io, 738 void * ata_io 739 ) 740 { 741 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 742 SATI_STATUS status = SATI_FAILURE; 743 744 if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT) 745 { 746 sati_scsi_sense_data_construct( 747 sequence, 748 scsi_io, 749 SCSI_STATUS_CHECK_CONDITION, 750 SCSI_SENSE_ABORTED_COMMAND, 751 SCSI_ASC_NO_ADDITIONAL_SENSE , 752 SCSI_ASCQ_NO_ADDITIONAL_SENSE 753 ); 754 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 755 } 756 else 757 { 758 759 void * ata_data = sati_cb_get_ata_data_address(ata_io); 760 761 if(ata_data == NULL) 762 { 763 return SATI_FAILURE; 764 } 765 766 switch(sequence->type) 767 { 768 case SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE: 769 sati_extended_self_test_log_page_construct( 770 sequence, scsi_io, ata_data 771 ); 772 773 status = SATI_COMPLETE; 774 break; 775 776 case SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE: 777 sati_self_test_log_page_construct(sequence, scsi_io, ata_data); 778 status = SATI_COMPLETE; 779 break; 780 781 case SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE: 782 //This function needs a d->h register fis, not ata data 783 sati_information_exception_log_page_contruct( 784 sequence, scsi_io, ata_io 785 ); 786 787 status = SATI_COMPLETE; 788 break; 789 790 default: 791 sati_scsi_sense_data_construct( 792 sequence, 793 scsi_io, 794 SCSI_STATUS_CHECK_CONDITION, 795 SCSI_SENSE_ABORTED_COMMAND, 796 SCSI_ASC_NO_ADDITIONAL_SENSE , 797 SCSI_ASCQ_NO_ADDITIONAL_SENSE 798 ); 799 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 800 break; 801 } 802 } 803 return status; 804 } 805 806 #endif // !defined(DISABLE_SATI_LOG_SENSE) 807 808