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 */
81static
82void 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 */
129static
130void 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 */
162static
163void 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 */
263static
264void 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*/
369static
370void 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 */
406static
407void 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*/
438static
439void 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*/
524static
525void 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 */
597SATI_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 */
737SATI_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