xref: /freebsd/sys/dev/isci/scil/sati_log_sense.c (revision e796cc77c586c2955b2f3940dbf4991b31e8d289)
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