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 */
79static
80void 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 */
127static
128void 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 */
160static
161void 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 */
261static
262void 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*/
367static
368void 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 recieved 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 */
404static
405void 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 recieved 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*/
436static
437void 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 recieved 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*/
522static
523void 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 */
595SATI_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 */
735SATI_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