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