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