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.
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
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.
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.
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.
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
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
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.
53 #include <sys/cdefs.h>
54 __FBSDID("$FreeBSD$");
58 * @brief This file contains the method definitions to translate
59 * SCSI Log Sense command based of the SATv2 spec.
62 #if !defined(DISABLE_SATI_LOG_SENSE)
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>
68 //******************************************************************************
69 //* P R I V A T E M E T H O D S
70 //******************************************************************************
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.
80 void sati_supported_log_page_construct(
81 SATI_TRANSLATOR_SEQUENCE_T * sequence,
86 //set SPF = 0 and PAGE_CODE = 0
87 sati_set_data_byte(sequence, scsi_io, 0, 0x00);
89 //set SUBPAGE_CODE = 0
90 sati_set_data_byte(sequence, scsi_io, 1, 0x00);
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);
96 //specify the next byte to be set
99 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
105 SCSI_LOG_PAGE_INFORMATION_EXCEPTION
110 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT)
116 SCSI_LOG_PAGE_SELF_TEST
122 * @brief This method sets bytes 4-19 of the self-test log parameter to zero.
128 void sati_set_parameters_to_zero(
129 SATI_TRANSLATOR_SEQUENCE_T * sequence,
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
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
161 void sati_translate_sense_values(
162 SATI_TRANSLATOR_SEQUENCE_T * sequence,
164 U8 self_test_status_byte
172 SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT
175 switch(self_test_status_byte)
179 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
182 sati_set_data_byte(sequence, scsi_io, 22, 0x81);
187 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
190 sati_set_data_byte(sequence, scsi_io, 22, 0x82);
195 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
198 sati_set_data_byte(sequence, scsi_io, 22, 0x83);
203 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
206 sati_set_data_byte(sequence, scsi_io, 22, 0x84);
211 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
214 sati_set_data_byte(sequence, scsi_io, 22, 0x85);
219 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
222 sati_set_data_byte(sequence, scsi_io, 22, 0x86);
227 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_MEDIUM_ERROR);
230 sati_set_data_byte(sequence, scsi_io, 22, 0x87);
235 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
238 sati_set_data_byte(sequence, scsi_io, 22, 0x88);
243 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_NO_SENSE);
245 sati_set_data_byte(sequence, scsi_io, 21, SCSI_ASC_NO_ADDITIONAL_SENSE);
247 sati_set_data_byte(sequence, scsi_io, 22, 0x00);
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.
262 void sati_get_self_test_results(
263 SATI_TRANSLATOR_SEQUENCE_T * sequence,
265 ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log
268 U16 descriptor_index = *((U16 *)(&ata_log->self_test_descriptor_index[0]));
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.
276 if(descriptor_index <= 0)
278 sati_set_parameters_to_zero(sequence, scsi_io);
286 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
289 //Sef-test number unspecified per satv2
290 sati_set_data_byte(sequence, scsi_io, 9, 0x00);
295 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_high
302 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_low
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);
313 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high_ext
320 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid_ext
327 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low_ext
334 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high
341 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid
348 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low
351 sati_translate_sense_values(
354 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
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
368 void sati_self_test_log_header_construct(
369 SATI_TRANSLATOR_SEQUENCE_T * sequence,
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);
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);
382 * Log PARAMETER 0x0001
383 * Only sending one log parameter per self-test request.
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
388 //Set to 0x03 per SATv2 spec
389 sati_set_data_byte(sequence, scsi_io, 6, 0x03); //log_parameter byte 2
391 //Parameter Length set to 0x10 per SATv2 spec
392 sati_set_data_byte(sequence, scsi_io, 7, 0x10); //log_parameter byte 3
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
405 void sati_extended_self_test_log_page_construct(
406 SATI_TRANSLATOR_SEQUENCE_T * sequence,
411 ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log =
412 (ATA_EXTENDED_SMART_SELF_TEST_LOG_T*) ata_data;
414 sati_self_test_log_header_construct(sequence, scsi_io);
417 if( (ata_log->self_test_descriptor_index[0] == 0) &&
418 (ata_log->self_test_descriptor_index[1] == 0))
420 sati_set_parameters_to_zero(sequence, scsi_io);
424 sati_get_self_test_results(sequence, scsi_io, ata_log);
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.
437 void sati_self_test_log_page_construct(
438 SATI_TRANSLATOR_SEQUENCE_T * sequence,
443 ATA_SMART_SELF_TEST_LOG_T * ata_log =
444 (ATA_SMART_SELF_TEST_LOG_T*) ata_data;
446 sati_self_test_log_header_construct(sequence, scsi_io);
448 //first descriptor entry(index == 0) is always used because scsi_parameter_code == 1
453 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
456 //Sef-test number unspecified per satv2
457 sati_set_data_byte(sequence, scsi_io, 9, 0x00);
463 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_high
470 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_low
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);
483 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low_ext
490 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_high
497 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_mid
504 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low
507 sati_translate_sense_values(
510 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
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.
523 void sati_information_exception_log_page_contruct(
524 SATI_TRANSLATOR_SEQUENCE_T * sequence,
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);
533 //Information Exception Page code
538 SCSI_LOG_PAGE_INFORMATION_EXCEPTION
542 sati_set_data_byte(sequence, scsi_io, 1, 0x00);
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);
549 sati_set_data_byte(sequence, scsi_io, 4, 0x00);
550 sati_set_data_byte(sequence, scsi_io, 5, 0x00);
553 sati_set_data_byte(sequence, scsi_io, 6, 0x03);
555 sati_set_data_byte(sequence, scsi_io, 7, 0x04);
557 if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED
558 && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED)
564 SCSI_ASC_HARDWARE_IMPENDING_FAILURE
571 SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE
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);
579 //setting most recent temperature reading to 0xFF(not supported) for now.
580 sati_set_data_byte(sequence, scsi_io, 10, 0xFF);
583 //******************************************************************************
584 //* P U B L I C M E T H O D S
585 //******************************************************************************
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.
592 * @return SATI_STATUS Indicates if the command translation succeeded.
595 SATI_STATUS sati_log_sense_translate_command(
596 SATI_TRANSLATOR_SEQUENCE_T * sequence,
601 U8 * cdb = sati_cb_get_cdb_address(scsi_io);
602 SATI_STATUS status = SATI_FAILURE;
604 if(SATI_LOG_SENSE_GET_PC_FIELD(cdb) == 1 &&
605 (sati_get_cdb_byte(cdb, 3) == 0))
607 sequence->allocation_length = (sati_get_cdb_byte(cdb, 7) << 8) |
608 (sati_get_cdb_byte(cdb, 8));
610 switch(SATI_LOG_SENSE_GET_PAGE_CODE(cdb))
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;
619 //Return Self-Test Results log page
620 case SCSI_LOG_PAGE_SELF_TEST :
622 if((sequence->device->capabilities &
623 SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT) == 0)
625 sati_scsi_sense_data_construct(
628 SCSI_STATUS_CHECK_CONDITION,
629 SCSI_SENSE_ILLEGAL_REQUEST,
630 SCSI_ASC_INVALID_FIELD_IN_CDB,
631 SCSI_ASCQ_INVALID_FIELD_IN_CDB
633 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
637 //check if 48-bit Address feature set is supported
638 if((sequence->device->capabilities &
639 SATI_DEVICE_CAP_48BIT_ENABLE))
641 //ATA Read Log Ext with log address set to 0x07
642 sati_ata_read_log_ext_construct(
645 ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST,
646 sizeof(ATA_EXTENDED_SMART_SELF_TEST_LOG_T)
649 SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE;
650 status = SATI_SUCCESS;
654 //ATA Smart Read Log with log address set to 0x06
655 sati_ata_smart_read_log_construct(
658 ATA_LOG_PAGE_SMART_SELF_TEST,
659 sizeof(ATA_SMART_SELF_TEST_LOG_T)
661 sequence->type = SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE;
662 status = SATI_SUCCESS;
667 //Return Informational Exceptions log page
668 case SCSI_LOG_PAGE_INFORMATION_EXCEPTION :
669 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
671 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE)
673 sati_ata_smart_return_status_construct(
676 ATA_SMART_SUB_CMD_RETURN_STATUS
679 SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE;
680 status = SATI_SUCCESS;
684 sati_scsi_sense_data_construct(
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
693 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
698 sati_scsi_sense_data_construct(
701 SCSI_STATUS_CHECK_CONDITION,
702 SCSI_SENSE_ILLEGAL_REQUEST,
703 SCSI_ASC_INVALID_FIELD_IN_CDB,
704 SCSI_ASCQ_INVALID_FIELD_IN_CDB
707 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
711 //UNSPECIFIED SATv2r9
712 sati_scsi_sense_data_construct(
715 SCSI_STATUS_CHECK_CONDITION,
716 SCSI_SENSE_ILLEGAL_REQUEST,
717 SCSI_ASC_NO_ADDITIONAL_SENSE ,
718 SCSI_ASCQ_NO_ADDITIONAL_SENSE
720 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
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.
732 * @return SATI_STATUS Indicates if the response translation succeeded.
735 SATI_STATUS sati_log_sense_translate_response(
736 SATI_TRANSLATOR_SEQUENCE_T * sequence,
741 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
742 SATI_STATUS status = SATI_FAILURE;
744 if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
746 sati_scsi_sense_data_construct(
749 SCSI_STATUS_CHECK_CONDITION,
750 SCSI_SENSE_ABORTED_COMMAND,
751 SCSI_ASC_NO_ADDITIONAL_SENSE ,
752 SCSI_ASCQ_NO_ADDITIONAL_SENSE
754 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
759 void * ata_data = sati_cb_get_ata_data_address(ata_io);
766 switch(sequence->type)
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
773 status = SATI_COMPLETE;
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;
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
787 status = SATI_COMPLETE;
791 sati_scsi_sense_data_construct(
794 SCSI_STATUS_CHECK_CONDITION,
795 SCSI_SENSE_ABORTED_COMMAND,
796 SCSI_ASC_NO_ADDITIONAL_SENSE ,
797 SCSI_ASCQ_NO_ADDITIONAL_SENSE
799 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
806 #endif // !defined(DISABLE_SATI_LOG_SENSE)