1230557Sjimharris/*-
2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license.  When using or
3230557Sjimharris * redistributing this file, you may do so under either license.
4230557Sjimharris *
5230557Sjimharris * GPL LICENSE SUMMARY
6230557Sjimharris *
7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8230557Sjimharris *
9230557Sjimharris * This program is free software; you can redistribute it and/or modify
10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as
11230557Sjimharris * published by the Free Software Foundation.
12230557Sjimharris *
13230557Sjimharris * This program is distributed in the hope that it will be useful, but
14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of
15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16230557Sjimharris * General Public License for more details.
17230557Sjimharris *
18230557Sjimharris * You should have received a copy of the GNU General Public License
19230557Sjimharris * along with this program; if not, write to the Free Software
20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21230557Sjimharris * The full GNU General Public License is included in this distribution
22230557Sjimharris * in the file called LICENSE.GPL.
23230557Sjimharris *
24230557Sjimharris * BSD LICENSE
25230557Sjimharris *
26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27230557Sjimharris * All rights reserved.
28230557Sjimharris *
29230557Sjimharris * Redistribution and use in source and binary forms, with or without
30230557Sjimharris * modification, are permitted provided that the following conditions
31230557Sjimharris * are met:
32230557Sjimharris *
33230557Sjimharris *   * Redistributions of source code must retain the above copyright
34230557Sjimharris *     notice, this list of conditions and the following disclaimer.
35230557Sjimharris *   * Redistributions in binary form must reproduce the above copyright
36230557Sjimharris *     notice, this list of conditions and the following disclaimer in
37230557Sjimharris *     the documentation and/or other materials provided with the
38230557Sjimharris *     distribution.
39230557Sjimharris *
40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51230557Sjimharris */
52230557Sjimharris
53230557Sjimharris#include <sys/cdefs.h>
54230557Sjimharris__FBSDID("$FreeBSD$");
55230557Sjimharris
56230557Sjimharris/**
57230557Sjimharris* @file
58230557Sjimharris* @brief This file contains the method definitions to translate
59230557Sjimharris*        SCSI Log Sense command based of the SATv2 spec.
60230557Sjimharris*/
61230557Sjimharris
62230557Sjimharris#if !defined(DISABLE_SATI_LOG_SENSE)
63230557Sjimharris
64230557Sjimharris#include <dev/isci/scil/sati_log_sense.h>
65230557Sjimharris#include <dev/isci/scil/sati_callbacks.h>
66230557Sjimharris#include <dev/isci/scil/sati_util.h>
67230557Sjimharris
68230557Sjimharris//******************************************************************************
69230557Sjimharris//* P R I V A T E   M E T H O D S
70230557Sjimharris//******************************************************************************
71230557Sjimharris
72230557Sjimharris/**
73230557Sjimharris * @brief This method constructs the SATI supported log page. This is a log
74230557Sjimharris *        containing the page codes of all the SATI supported log pages.
75230557Sjimharris *
76230557Sjimharris * @return n/a
77230557Sjimharris *
78230557Sjimharris */
79230557Sjimharrisstatic
80230557Sjimharrisvoid sati_supported_log_page_construct(
81230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T  * sequence,
82230557Sjimharris   void                        * scsi_io
83230557Sjimharris)
84230557Sjimharris{
85230557Sjimharris   U32 next_byte;
86230557Sjimharris   //set SPF = 0 and PAGE_CODE = 0
87230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
88230557Sjimharris
89230557Sjimharris   //set SUBPAGE_CODE = 0
90230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 1, 0x00);
91230557Sjimharris
92230557Sjimharris   //set the Page Length to (n-3) or 2 because only two log pages are supported
93230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 2, 0x00);
94230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 3, 0x02);
95230557Sjimharris
96230557Sjimharris   //specify the next byte to be set
97230557Sjimharris   next_byte = 4;
98230557Sjimharris
99230557Sjimharris   if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
100230557Sjimharris   {
101230557Sjimharris      sati_set_data_byte(
102230557Sjimharris         sequence,
103230557Sjimharris         scsi_io,
104230557Sjimharris         next_byte,
105230557Sjimharris         SCSI_LOG_PAGE_INFORMATION_EXCEPTION
106230557Sjimharris      );
107230557Sjimharris      next_byte = 5;
108230557Sjimharris   }
109230557Sjimharris
110230557Sjimharris   if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT)
111230557Sjimharris   {
112230557Sjimharris      sati_set_data_byte(
113230557Sjimharris         sequence,
114230557Sjimharris         scsi_io,
115230557Sjimharris         next_byte,
116230557Sjimharris         SCSI_LOG_PAGE_SELF_TEST
117230557Sjimharris      );
118230557Sjimharris   }
119230557Sjimharris}
120230557Sjimharris
121230557Sjimharris/**
122230557Sjimharris * @brief This method sets bytes 4-19 of the self-test log parameter to zero.
123230557Sjimharris *
124230557Sjimharris * @return n/a
125230557Sjimharris *
126230557Sjimharris */
127230557Sjimharrisstatic
128230557Sjimharrisvoid sati_set_parameters_to_zero(
129230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
130230557Sjimharris   void                       * scsi_io
131230557Sjimharris)
132230557Sjimharris{
133230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 8, 0x00);   //log_parameter byte 4
134230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 9, 0x00);   //log_parameter byte 5
135230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 10, 0x00);  //log_parameter byte 6
136230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 11, 0x00);  //log_parameter byte 7
137230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 12, 0x00);  //log_parameter byte 8
138230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 13, 0x00);  //log_parameter byte 9
139230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 14, 0x00);  //log_parameter byte 10
140230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 15, 0x00);  //log_parameter byte 11
141230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 16, 0x00);  //log_parameter byte 12
142230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 17, 0x00);  //log_parameter byte 13
143230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 18, 0x00);  //log_parameter byte 14
144230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 19, 0x00);  //log_parameter byte 15
145230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 20, 0x00);  //log_parameter byte 16
146230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 21, 0x00);  //log_parameter byte 17
147230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 22, 0x00);  //log_parameter byte 18
148230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 23, 0x00);  //log_parameter byte 19
149230557Sjimharris}
150230557Sjimharris
151230557Sjimharris/**
152230557Sjimharris * @brief This method translates the ATA Extended SMART self-test log into
153230557Sjimharris *        SCSI Sense Key, Additional Sense Code, and Additional Sense code
154230557Sjimharris *        qualifiers based on the self test status byte in the appropriate
155230557Sjimharris *        descriptor entry.
156230557Sjimharris *
157230557Sjimharris * @return n/a
158230557Sjimharris *
159230557Sjimharris */
160230557Sjimharrisstatic
161230557Sjimharrisvoid sati_translate_sense_values(
162230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
163230557Sjimharris   void                       * scsi_io,
164230557Sjimharris   U8                           self_test_status_byte
165230557Sjimharris)
166230557Sjimharris{
167230557Sjimharris   //byte 17
168230557Sjimharris   sati_set_data_byte(
169230557Sjimharris      sequence,
170230557Sjimharris      scsi_io,
171230557Sjimharris      21,
172230557Sjimharris      SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT
173230557Sjimharris   );
174230557Sjimharris
175230557Sjimharris   switch(self_test_status_byte)
176230557Sjimharris   {
177230557Sjimharris      case 1:
178230557Sjimharris         //byte 16
179230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
180230557Sjimharris
181230557Sjimharris         //byte 18
182230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 22, 0x81);
183230557Sjimharris         break;
184230557Sjimharris
185230557Sjimharris      case 2:
186230557Sjimharris         //byte 16
187230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
188230557Sjimharris
189230557Sjimharris         //byte 18
190230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 22, 0x82);
191230557Sjimharris         break;
192230557Sjimharris
193230557Sjimharris      case 3:
194230557Sjimharris         //byte 16
195230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
196230557Sjimharris
197230557Sjimharris         //byte 18
198230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 22, 0x83);
199230557Sjimharris         break;
200230557Sjimharris
201230557Sjimharris      case 4:
202230557Sjimharris         //byte 16
203230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
204230557Sjimharris
205230557Sjimharris         //byte 18
206230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 22, 0x84);
207230557Sjimharris         break;
208230557Sjimharris
209230557Sjimharris      case 5:
210230557Sjimharris         //byte 16
211230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
212230557Sjimharris
213230557Sjimharris         //byte 18
214230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 22, 0x85);
215230557Sjimharris         break;
216230557Sjimharris
217230557Sjimharris      case 6:
218230557Sjimharris         //byte 16
219230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
220230557Sjimharris
221230557Sjimharris         //byte 18
222230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 22, 0x86);
223230557Sjimharris         break;
224230557Sjimharris
225230557Sjimharris      case 7:
226230557Sjimharris         //byte 16
227230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_MEDIUM_ERROR);
228230557Sjimharris
229230557Sjimharris         //byte 18
230230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 22, 0x87);
231230557Sjimharris         break;
232230557Sjimharris
233230557Sjimharris      case 8:
234230557Sjimharris         //byte 16
235230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
236230557Sjimharris
237230557Sjimharris         //byte 18
238230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 22, 0x88);
239230557Sjimharris         break;
240230557Sjimharris
241230557Sjimharris      default:
242230557Sjimharris         //byte 16
243230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_NO_SENSE);
244230557Sjimharris         //byte 17
245230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 21, SCSI_ASC_NO_ADDITIONAL_SENSE);
246230557Sjimharris         //byte 18
247230557Sjimharris         sati_set_data_byte(sequence, scsi_io, 22, 0x00);
248230557Sjimharris         break;
249230557Sjimharris   }
250230557Sjimharris
251230557Sjimharris}
252230557Sjimharris
253230557Sjimharris/**
254230557Sjimharris * @brief This method retrieves the correct self-test results by checking the
255230557Sjimharris *        descriptor index in the extended SMART self-test log. The index is
256230557Sjimharris *        used to determine the appropriate descriptor entry.
257230557Sjimharris *
258230557Sjimharris * @return n/a
259230557Sjimharris *
260230557Sjimharris */
261230557Sjimharrisstatic
262230557Sjimharrisvoid sati_get_self_test_results(
263230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T          * sequence,
264230557Sjimharris   void                                * scsi_io,
265230557Sjimharris   ATA_EXTENDED_SMART_SELF_TEST_LOG_T  * ata_log
266230557Sjimharris)
267230557Sjimharris{
268230557Sjimharris   U16 descriptor_index = *((U16 *)(&ata_log->self_test_descriptor_index[0]));
269230557Sjimharris
270230557Sjimharris   /*
271230557Sjimharris    * SATv2 wants data from descriptor N where N is equal to
272230557Sjimharris    * (descriptor_index - parameter_code) + 1. Since parameter
273230557Sjimharris    * code is always 0x0001 just checking descriptor_index.
274230557Sjimharris    */
275230557Sjimharris
276230557Sjimharris   if(descriptor_index <= 0)
277230557Sjimharris   {
278230557Sjimharris      sati_set_parameters_to_zero(sequence, scsi_io);
279230557Sjimharris   }
280230557Sjimharris   else
281230557Sjimharris   {
282230557Sjimharris      sati_set_data_byte(
283230557Sjimharris       sequence,
284230557Sjimharris       scsi_io,
285230557Sjimharris       8,
286230557Sjimharris       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
287230557Sjimharris      );
288230557Sjimharris
289230557Sjimharris      //Sef-test number unspecified per satv2
290230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 9, 0x00);
291230557Sjimharris      sati_set_data_byte(
292230557Sjimharris       sequence,
293230557Sjimharris       scsi_io,
294230557Sjimharris       10,
295230557Sjimharris       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_high
296230557Sjimharris      );
297230557Sjimharris
298230557Sjimharris      sati_set_data_byte(
299230557Sjimharris       sequence,
300230557Sjimharris       scsi_io,
301230557Sjimharris       11,
302230557Sjimharris       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_low
303230557Sjimharris      );
304230557Sjimharris
305230557Sjimharris      //set to zero because it's a 48bit address
306230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 12, 0x00);
307230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 13, 0x00);
308230557Sjimharris
309230557Sjimharris      sati_set_data_byte(
310230557Sjimharris       sequence,
311230557Sjimharris       scsi_io,
312230557Sjimharris       14,
313230557Sjimharris       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high_ext
314230557Sjimharris      );
315230557Sjimharris
316230557Sjimharris      sati_set_data_byte(
317230557Sjimharris       sequence,
318230557Sjimharris       scsi_io,
319230557Sjimharris       15,
320230557Sjimharris       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid_ext
321230557Sjimharris      );
322230557Sjimharris
323230557Sjimharris      sati_set_data_byte(
324230557Sjimharris       sequence,
325230557Sjimharris       scsi_io,
326230557Sjimharris       16,
327230557Sjimharris       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low_ext
328230557Sjimharris      );
329230557Sjimharris
330230557Sjimharris      sati_set_data_byte(
331230557Sjimharris       sequence,
332230557Sjimharris       scsi_io,
333230557Sjimharris       17,
334230557Sjimharris       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high
335230557Sjimharris      );
336230557Sjimharris
337230557Sjimharris      sati_set_data_byte(
338230557Sjimharris       sequence,
339230557Sjimharris       scsi_io,
340230557Sjimharris       18,
341230557Sjimharris       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid
342230557Sjimharris      );
343230557Sjimharris
344230557Sjimharris      sati_set_data_byte(
345230557Sjimharris       sequence,
346230557Sjimharris       scsi_io,
347230557Sjimharris       19,
348230557Sjimharris       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low
349230557Sjimharris      );
350230557Sjimharris
351230557Sjimharris      sati_translate_sense_values(
352230557Sjimharris       sequence,
353230557Sjimharris       scsi_io,
354230557Sjimharris       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
355230557Sjimharris      );
356230557Sjimharris   }
357230557Sjimharris}
358230557Sjimharris
359230557Sjimharris/**
360230557Sjimharris* @brief This method will construct the first eight bytes of the SCSI self test
361230557Sjimharris*        log page for both cases when SATI sends a ATA read log ext and a smart
362230557Sjimharris*        read log command.
363230557Sjimharris*
364230557Sjimharris* @return n/a
365230557Sjimharris*
366230557Sjimharris*/
367230557Sjimharrisstatic
368230557Sjimharrisvoid sati_self_test_log_header_construct(
369230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T  * sequence,
370230557Sjimharris   void                        * scsi_io
371230557Sjimharris)
372230557Sjimharris{
373230557Sjimharris   //PAGE CODE for Self-Test Log Page
374230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 0, 0x10);
375230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 1, 0x00);
376230557Sjimharris
377230557Sjimharris   //PAGE LENGTH is 0x14 instead of 0x190, not returning 20/0x190 log perameters
378230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 2, 0x00);
379230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 3, 0x14);
380230557Sjimharris
381230557Sjimharris   /*
382230557Sjimharris    * Log PARAMETER 0x0001
383230557Sjimharris    * Only sending one log parameter per self-test request.
384230557Sjimharris    */
385230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 4, 0x00);       //log_parameter byte 0
386230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 5, 0x01);       //log_parameter byte 1
387230557Sjimharris
388230557Sjimharris   //Set to 0x03 per SATv2 spec
389230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 6, 0x03);       //log_parameter byte 2
390230557Sjimharris
391230557Sjimharris   //Parameter Length set to 0x10 per SATv2 spec
392230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 7, 0x10);       //log_parameter byte 3
393230557Sjimharris}
394230557Sjimharris
395230557Sjimharris/**
396230557Sjimharris * @brief This method will construct the SCSI self test log page from
397230557Sjimharris *        the Extended SMART self-test log response recieved from the
398230557Sjimharris *        ATA device. The response is from a ATA_Read_Log_EXT command
399230557Sjimharris *        issued by SATI.
400230557Sjimharris *
401230557Sjimharris * @return n/a
402230557Sjimharris *
403230557Sjimharris */
404230557Sjimharrisstatic
405230557Sjimharrisvoid sati_extended_self_test_log_page_construct(
406230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T  * sequence,
407230557Sjimharris   void                        * scsi_io,
408230557Sjimharris   void                        * ata_data
409230557Sjimharris)
410230557Sjimharris{
411230557Sjimharris   ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log =
412230557Sjimharris                  (ATA_EXTENDED_SMART_SELF_TEST_LOG_T*) ata_data;
413230557Sjimharris
414230557Sjimharris   sati_self_test_log_header_construct(sequence, scsi_io);
415230557Sjimharris
416230557Sjimharris   //bytes 4-19
417230557Sjimharris   if( (ata_log->self_test_descriptor_index[0] == 0) &&
418230557Sjimharris       (ata_log->self_test_descriptor_index[1] == 0))
419230557Sjimharris   {
420230557Sjimharris      sati_set_parameters_to_zero(sequence, scsi_io);
421230557Sjimharris   }
422230557Sjimharris   else
423230557Sjimharris   {
424230557Sjimharris      sati_get_self_test_results(sequence, scsi_io, ata_log);
425230557Sjimharris   }
426230557Sjimharris}
427230557Sjimharris
428230557Sjimharris/**
429230557Sjimharris* @brief This method will construct the SCSI self test log page from
430230557Sjimharris*        the SMART self-test log response recieved from the ATA device.
431230557Sjimharris*        The response is from a ATA_SMART_Read_Log command issued by SATI.
432230557Sjimharris*
433230557Sjimharris* @return n/a
434230557Sjimharris*
435230557Sjimharris*/
436230557Sjimharrisstatic
437230557Sjimharrisvoid sati_self_test_log_page_construct(
438230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T  * sequence,
439230557Sjimharris   void                        * scsi_io,
440230557Sjimharris   void                        * ata_data
441230557Sjimharris)
442230557Sjimharris{
443230557Sjimharris   ATA_SMART_SELF_TEST_LOG_T * ata_log =
444230557Sjimharris                        (ATA_SMART_SELF_TEST_LOG_T*) ata_data;
445230557Sjimharris
446230557Sjimharris   sati_self_test_log_header_construct(sequence, scsi_io);
447230557Sjimharris
448230557Sjimharris   //first descriptor entry(index == 0) is always used because scsi_parameter_code == 1
449230557Sjimharris   sati_set_data_byte(
450230557Sjimharris      sequence,
451230557Sjimharris      scsi_io,
452230557Sjimharris      8,
453230557Sjimharris      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
454230557Sjimharris   );
455230557Sjimharris
456230557Sjimharris   //Sef-test number unspecified per satv2
457230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 9, 0x00);
458230557Sjimharris
459230557Sjimharris   sati_set_data_byte(
460230557Sjimharris      sequence,
461230557Sjimharris      scsi_io,
462230557Sjimharris      10,
463230557Sjimharris      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_high
464230557Sjimharris   );
465230557Sjimharris
466230557Sjimharris   sati_set_data_byte(
467230557Sjimharris      sequence,
468230557Sjimharris      scsi_io,
469230557Sjimharris      11,
470230557Sjimharris      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_low
471230557Sjimharris   );
472230557Sjimharris
473230557Sjimharris   //set to zero because it's a 28bit address
474230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 12, 0x00);
475230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 13, 0x00);
476230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 14, 0x00);
477230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 15, 0x00);
478230557Sjimharris
479230557Sjimharris   sati_set_data_byte(
480230557Sjimharris      sequence,
481230557Sjimharris      scsi_io,
482230557Sjimharris      16,
483230557Sjimharris      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low_ext
484230557Sjimharris   );
485230557Sjimharris
486230557Sjimharris   sati_set_data_byte(
487230557Sjimharris      sequence,
488230557Sjimharris      scsi_io,
489230557Sjimharris      17,
490230557Sjimharris      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_high
491230557Sjimharris   );
492230557Sjimharris
493230557Sjimharris   sati_set_data_byte(
494230557Sjimharris      sequence,
495230557Sjimharris      scsi_io,
496230557Sjimharris      18,
497230557Sjimharris      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_mid
498230557Sjimharris   );
499230557Sjimharris
500230557Sjimharris   sati_set_data_byte(
501230557Sjimharris      sequence,
502230557Sjimharris      scsi_io,
503230557Sjimharris      19,
504230557Sjimharris      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low
505230557Sjimharris   );
506230557Sjimharris
507230557Sjimharris   sati_translate_sense_values(
508230557Sjimharris      sequence,
509230557Sjimharris      scsi_io,
510230557Sjimharris      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
511230557Sjimharris   );
512230557Sjimharris}
513230557Sjimharris
514230557Sjimharris/**
515230557Sjimharris* @brief This method will construct the SCSI information exception log page from
516230557Sjimharris*        the ATA SMART response recieved from the ATA device. The response is
517230557Sjimharris*         from a ATA SMART return status command issued by SATI.
518230557Sjimharris*
519230557Sjimharris* @return n/a
520230557Sjimharris*
521230557Sjimharris*/
522230557Sjimharrisstatic
523230557Sjimharrisvoid sati_information_exception_log_page_contruct(
524230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T  * sequence,
525230557Sjimharris   void                        * scsi_io,
526230557Sjimharris   void                        * ata_io
527230557Sjimharris)
528230557Sjimharris{
529230557Sjimharris   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
530230557Sjimharris   U32 mid_register = sati_get_ata_lba_mid(register_fis);
531230557Sjimharris   U32 high_register = sati_get_ata_lba_high(register_fis);
532230557Sjimharris
533230557Sjimharris   //Information Exception Page code
534230557Sjimharris   sati_set_data_byte(
535230557Sjimharris      sequence,
536230557Sjimharris      scsi_io,
537230557Sjimharris      0,
538230557Sjimharris      SCSI_LOG_PAGE_INFORMATION_EXCEPTION
539230557Sjimharris   );
540230557Sjimharris
541230557Sjimharris   //Sub-page code
542230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 1, 0x00);
543230557Sjimharris
544230557Sjimharris   //Page length of log parameters
545230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 2, 0x00);
546230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 3, 0x08);
547230557Sjimharris
548230557Sjimharris   //parameter code
549230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 4, 0x00);
550230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 5, 0x00);
551230557Sjimharris
552230557Sjimharris   //Format and Linking
553230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 6, 0x03);
554230557Sjimharris   //Parameter Length
555230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 7, 0x04);
556230557Sjimharris
557230557Sjimharris   if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED
558230557Sjimharris      && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED)
559230557Sjimharris   {
560230557Sjimharris      sati_set_data_byte(
561230557Sjimharris         sequence,
562230557Sjimharris         scsi_io,
563230557Sjimharris         8,
564230557Sjimharris         SCSI_ASC_HARDWARE_IMPENDING_FAILURE
565230557Sjimharris      );
566230557Sjimharris
567230557Sjimharris      sati_set_data_byte(
568230557Sjimharris         sequence,
569230557Sjimharris         scsi_io,
570230557Sjimharris         9,
571230557Sjimharris         SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE
572230557Sjimharris      );
573230557Sjimharris   }
574230557Sjimharris   else
575230557Sjimharris   {
576230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 8, SCSI_ASC_NO_ADDITIONAL_SENSE);
577230557Sjimharris      sati_set_data_byte(sequence, scsi_io, 9, SCSI_ASCQ_NO_ADDITIONAL_SENSE);
578230557Sjimharris   }
579230557Sjimharris   //setting most recent temperature reading to 0xFF(not supported) for now.
580230557Sjimharris   sati_set_data_byte(sequence, scsi_io, 10, 0xFF);
581230557Sjimharris}
582230557Sjimharris
583230557Sjimharris//******************************************************************************
584230557Sjimharris//* P U B L I C   M E T H O D S
585230557Sjimharris//******************************************************************************
586230557Sjimharris
587230557Sjimharris/**
588230557Sjimharris * @brief This method will translate the SCSI Log Sense command into ATA commands
589230557Sjimharris *        specified by SATv2. ATA commands Read Log EXT and SMART Read Log will
590230557Sjimharris *        be issued by this translation.
591230557Sjimharris *
592230557Sjimharris * @return SATI_STATUS Indicates if the command translation succeeded.
593230557Sjimharris *
594230557Sjimharris */
595230557SjimharrisSATI_STATUS sati_log_sense_translate_command(
596230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
597230557Sjimharris   void                       * scsi_io,
598230557Sjimharris   void                       * ata_io
599230557Sjimharris)
600230557Sjimharris{
601230557Sjimharris   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
602230557Sjimharris   SATI_STATUS status = SATI_FAILURE;
603230557Sjimharris
604230557Sjimharris   if(SATI_LOG_SENSE_GET_PC_FIELD(cdb) == 1 &&
605230557Sjimharris      (sati_get_cdb_byte(cdb, 3) == 0))
606230557Sjimharris   {
607230557Sjimharris      sequence->allocation_length = (sati_get_cdb_byte(cdb, 7) << 8) |
608230557Sjimharris                                    (sati_get_cdb_byte(cdb, 8));
609230557Sjimharris
610230557Sjimharris      switch(SATI_LOG_SENSE_GET_PAGE_CODE(cdb))
611230557Sjimharris      {
612230557Sjimharris         //Return Supported Log Pages log page
613230557Sjimharris         case SCSI_LOG_PAGE_SUPPORTED_PAGES :
614230557Sjimharris            sati_supported_log_page_construct(sequence, scsi_io);
615230557Sjimharris            sequence->type = SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE;
616230557Sjimharris            status = SATI_COMPLETE;
617230557Sjimharris            break;
618230557Sjimharris
619230557Sjimharris         //Return Self-Test Results log page
620230557Sjimharris         case SCSI_LOG_PAGE_SELF_TEST :
621230557Sjimharris
622230557Sjimharris            if((sequence->device->capabilities &
623230557Sjimharris               SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT) == 0)
624230557Sjimharris            {
625230557Sjimharris               sati_scsi_sense_data_construct(
626230557Sjimharris                  sequence,
627230557Sjimharris                  scsi_io,
628230557Sjimharris                  SCSI_STATUS_CHECK_CONDITION,
629230557Sjimharris                  SCSI_SENSE_ILLEGAL_REQUEST,
630230557Sjimharris                  SCSI_ASC_INVALID_FIELD_IN_CDB,
631230557Sjimharris                  SCSI_ASCQ_INVALID_FIELD_IN_CDB
632230557Sjimharris               );
633230557Sjimharris               status = SATI_FAILURE_CHECK_RESPONSE_DATA;
634230557Sjimharris            }
635230557Sjimharris            else
636230557Sjimharris            {
637230557Sjimharris               //check if 48-bit Address feature set is supported
638230557Sjimharris               if((sequence->device->capabilities &
639230557Sjimharris                  SATI_DEVICE_CAP_48BIT_ENABLE))
640230557Sjimharris               {
641230557Sjimharris                  //ATA Read Log Ext with log address set to 0x07
642230557Sjimharris                  sati_ata_read_log_ext_construct(
643230557Sjimharris                                     ata_io,
644230557Sjimharris                                     sequence,
645230557Sjimharris                                     ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST,
646230557Sjimharris                                     sizeof(ATA_EXTENDED_SMART_SELF_TEST_LOG_T)
647230557Sjimharris                  );
648230557Sjimharris                  sequence->type =
649230557Sjimharris                            SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE;
650230557Sjimharris                  status = SATI_SUCCESS;
651230557Sjimharris               }
652230557Sjimharris               else
653230557Sjimharris               {
654230557Sjimharris                  //ATA Smart Read Log with log address set to 0x06
655230557Sjimharris                  sati_ata_smart_read_log_construct(
656230557Sjimharris                                       ata_io,
657230557Sjimharris                                       sequence,
658230557Sjimharris                                       ATA_LOG_PAGE_SMART_SELF_TEST,
659230557Sjimharris                                       sizeof(ATA_SMART_SELF_TEST_LOG_T)
660230557Sjimharris                  );
661230557Sjimharris                  sequence->type = SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE;
662230557Sjimharris                  status = SATI_SUCCESS;
663230557Sjimharris               }
664230557Sjimharris            }
665230557Sjimharris            break;
666230557Sjimharris
667230557Sjimharris         //Return Informational Exceptions log page
668230557Sjimharris         case SCSI_LOG_PAGE_INFORMATION_EXCEPTION :
669230557Sjimharris            if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
670230557Sjimharris            {
671230557Sjimharris               if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE)
672230557Sjimharris               {
673230557Sjimharris                  sati_ata_smart_return_status_construct(
674230557Sjimharris                                       ata_io,
675230557Sjimharris                                       sequence,
676230557Sjimharris                                       ATA_SMART_SUB_CMD_RETURN_STATUS
677230557Sjimharris                  );
678230557Sjimharris                  sequence->type =
679230557Sjimharris                                SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE;
680230557Sjimharris                  status = SATI_SUCCESS;
681230557Sjimharris               }
682230557Sjimharris               else
683230557Sjimharris               {
684230557Sjimharris                  sati_scsi_sense_data_construct(
685230557Sjimharris                     sequence,
686230557Sjimharris                     scsi_io,
687230557Sjimharris                     SCSI_STATUS_CHECK_CONDITION,
688230557Sjimharris                     SCSI_SENSE_ABORTED_COMMAND,
689230557Sjimharris                     SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED,
690230557Sjimharris                     SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED
691230557Sjimharris                  );
692230557Sjimharris
693230557Sjimharris                  status = SATI_FAILURE_CHECK_RESPONSE_DATA;
694230557Sjimharris               }
695230557Sjimharris            }
696230557Sjimharris            else
697230557Sjimharris            {
698230557Sjimharris               sati_scsi_sense_data_construct(
699230557Sjimharris                  sequence,
700230557Sjimharris                  scsi_io,
701230557Sjimharris                  SCSI_STATUS_CHECK_CONDITION,
702230557Sjimharris                  SCSI_SENSE_ILLEGAL_REQUEST,
703230557Sjimharris                  SCSI_ASC_INVALID_FIELD_IN_CDB,
704230557Sjimharris                  SCSI_ASCQ_INVALID_FIELD_IN_CDB
705230557Sjimharris               );
706230557Sjimharris
707230557Sjimharris               status = SATI_FAILURE_CHECK_RESPONSE_DATA;
708230557Sjimharris            }
709230557Sjimharris            break;
710230557Sjimharris         default :
711230557Sjimharris            //UNSPECIFIED SATv2r9
712230557Sjimharris            sati_scsi_sense_data_construct(
713230557Sjimharris               sequence,
714230557Sjimharris               scsi_io,
715230557Sjimharris               SCSI_STATUS_CHECK_CONDITION,
716230557Sjimharris               SCSI_SENSE_ILLEGAL_REQUEST,
717230557Sjimharris               SCSI_ASC_NO_ADDITIONAL_SENSE ,
718230557Sjimharris               SCSI_ASCQ_NO_ADDITIONAL_SENSE
719230557Sjimharris            );
720230557Sjimharris            status = SATI_FAILURE_CHECK_RESPONSE_DATA;
721230557Sjimharris            break;
722230557Sjimharris      }
723230557Sjimharris   }
724230557Sjimharris   return status;
725230557Sjimharris}
726230557Sjimharris
727230557Sjimharris/**
728230557Sjimharris * @brief This method will translate the response to the SATI Log Sense
729230557Sjimharris *        translation. ATA command responses will be translated into the
730230557Sjimharris *        correct SCSI log pages to be returned by SATI.
731230557Sjimharris *
732230557Sjimharris * @return SATI_STATUS Indicates if the response translation succeeded.
733230557Sjimharris *
734230557Sjimharris */
735230557SjimharrisSATI_STATUS sati_log_sense_translate_response(
736230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
737230557Sjimharris   void                       * scsi_io,
738230557Sjimharris   void                       * ata_io
739230557Sjimharris)
740230557Sjimharris{
741230557Sjimharris   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
742230557Sjimharris   SATI_STATUS status = SATI_FAILURE;
743230557Sjimharris
744230557Sjimharris   if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
745230557Sjimharris   {
746230557Sjimharris      sati_scsi_sense_data_construct(
747230557Sjimharris         sequence,
748230557Sjimharris         scsi_io,
749230557Sjimharris         SCSI_STATUS_CHECK_CONDITION,
750230557Sjimharris         SCSI_SENSE_ABORTED_COMMAND,
751230557Sjimharris         SCSI_ASC_NO_ADDITIONAL_SENSE ,
752230557Sjimharris         SCSI_ASCQ_NO_ADDITIONAL_SENSE
753230557Sjimharris      );
754230557Sjimharris      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
755230557Sjimharris   }
756230557Sjimharris   else
757230557Sjimharris   {
758230557Sjimharris
759230557Sjimharris      void * ata_data = sati_cb_get_ata_data_address(ata_io);
760230557Sjimharris
761230557Sjimharris      if(ata_data == NULL)
762230557Sjimharris      {
763230557Sjimharris         return SATI_FAILURE;
764230557Sjimharris      }
765230557Sjimharris
766230557Sjimharris      switch(sequence->type)
767230557Sjimharris      {
768230557Sjimharris         case SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE:
769230557Sjimharris            sati_extended_self_test_log_page_construct(
770230557Sjimharris                                 sequence, scsi_io, ata_data
771230557Sjimharris            );
772230557Sjimharris
773230557Sjimharris            status = SATI_COMPLETE;
774230557Sjimharris            break;
775230557Sjimharris
776230557Sjimharris         case SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE:
777230557Sjimharris            sati_self_test_log_page_construct(sequence, scsi_io, ata_data);
778230557Sjimharris            status = SATI_COMPLETE;
779230557Sjimharris            break;
780230557Sjimharris
781230557Sjimharris         case SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE:
782230557Sjimharris            //This function needs a d->h register fis, not ata data
783230557Sjimharris            sati_information_exception_log_page_contruct(
784230557Sjimharris                                 sequence, scsi_io, ata_io
785230557Sjimharris            );
786230557Sjimharris
787230557Sjimharris            status = SATI_COMPLETE;
788230557Sjimharris            break;
789230557Sjimharris
790230557Sjimharris         default:
791230557Sjimharris            sati_scsi_sense_data_construct(
792230557Sjimharris               sequence,
793230557Sjimharris               scsi_io,
794230557Sjimharris               SCSI_STATUS_CHECK_CONDITION,
795230557Sjimharris               SCSI_SENSE_ABORTED_COMMAND,
796230557Sjimharris               SCSI_ASC_NO_ADDITIONAL_SENSE ,
797230557Sjimharris               SCSI_ASCQ_NO_ADDITIONAL_SENSE
798230557Sjimharris            );
799230557Sjimharris            status = SATI_FAILURE_CHECK_RESPONSE_DATA;
800230557Sjimharris            break;
801230557Sjimharris      }
802230557Sjimharris   }
803230557Sjimharris   return status;
804230557Sjimharris}
805230557Sjimharris
806230557Sjimharris#endif // !defined(DISABLE_SATI_LOG_SENSE)
807230557Sjimharris
808