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: releng/10.3/sys/dev/isci/scil/sati_util.c 240514 2012-09-14 20:05:38Z jimharris $");
55230557Sjimharris
56230557Sjimharris/**
57230557Sjimharris * @file
58230557Sjimharris * @brief This file contains all of the method implementations that
59230557Sjimharris *        provide generic support for SATI.  Some methods can be utilized
60230557Sjimharris *        by a user to construct ATA/ATAPI commands, copy ATA device
61230557Sjimharris *        structure data, fill in sense data, etc.
62230557Sjimharris */
63230557Sjimharris
64230557Sjimharris#include <dev/isci/scil/sati_util.h>
65230557Sjimharris#include <dev/isci/scil/sati_callbacks.h>
66230557Sjimharris#include <dev/isci/scil/intel_scsi.h>
67230557Sjimharris#include <dev/isci/scil/intel_ata.h>
68230557Sjimharris#include <dev/isci/scil/intel_sat.h>
69230557Sjimharris#include <dev/isci/scil/intel_sas.h>
70230557Sjimharris
71230557Sjimharris/**
72230557Sjimharris * @brief This method will set the data direction, protocol, and transfer
73230557Sjimharris *        kength for an ATA non-data command.
74230557Sjimharris *
75230557Sjimharris * @pre It is expected that the user will use this method for setting these
76230557Sjimharris *      values in a non-data ATA command constuct.
77230557Sjimharris *
78230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
79230557Sjimharris *             for which to build the IDENTIFY DEVICE command.
80230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
81230557Sjimharris *             for which the command is being constructed.
82230557Sjimharris *
83230557Sjimharris * @return none.
84230557Sjimharris */
85230557Sjimharrisvoid sati_ata_non_data_command(
86230557Sjimharris   void                        * ata_io,
87230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T  * sequence
88230557Sjimharris)
89230557Sjimharris{
90230557Sjimharris   sequence->data_direction      = SATI_DATA_DIRECTION_NONE;
91230557Sjimharris   sequence->protocol            = SAT_PROTOCOL_NON_DATA;
92230557Sjimharris   sequence->ata_transfer_length = 0;
93230557Sjimharris}
94230557Sjimharris
95230557Sjimharris/**
96230557Sjimharris * @brief This method will construct the ATA identify device command.
97230557Sjimharris *
98230557Sjimharris * @pre It is expected that the user has properly set the current contents
99230557Sjimharris *      of the register FIS to 0.
100230557Sjimharris *
101230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
102230557Sjimharris *             for which to build the IDENTIFY DEVICE command.
103230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
104230557Sjimharris *             for which the command is being constructed.
105230557Sjimharris *
106230557Sjimharris * @return none.
107230557Sjimharris */
108230557Sjimharrisvoid sati_ata_identify_device_construct(
109230557Sjimharris   void                       * ata_io,
110230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
111230557Sjimharris)
112230557Sjimharris{
113230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
114230557Sjimharris
115230557Sjimharris   sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE);
116230557Sjimharris   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
117230557Sjimharris   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
118230557Sjimharris   sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T);
119230557Sjimharris}
120230557Sjimharris
121230557Sjimharris/**
122230557Sjimharris* @brief This method will construct the ATA Execute Device Diagnostic command.
123230557Sjimharris*
124230557Sjimharris* @param[out] ata_io This parameter specifies the ATA IO request structure
125230557Sjimharris*             for which to build the IDENTIFY DEVICE command.
126230557Sjimharris* @param[in]  sequence This parameter specifies the translator sequence
127230557Sjimharris*             for which the command is being constructed.
128230557Sjimharris*
129230557Sjimharris* @return none.
130230557Sjimharris*/
131230557Sjimharrisvoid sati_ata_execute_device_diagnostic_construct(
132230557Sjimharris   void                       * ata_io,
133230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
134230557Sjimharris)
135230557Sjimharris{
136230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
137230557Sjimharris
138230557Sjimharris   sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG);
139230557Sjimharris
140230557Sjimharris   sequence->data_direction = SATI_DATA_DIRECTION_IN;
141230557Sjimharris   sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC;
142230557Sjimharris   sequence->ata_transfer_length = 16;
143230557Sjimharris}
144230557Sjimharris
145230557Sjimharris/**
146230557Sjimharris * @brief This method will set data bytes in the user data area.  If the
147230557Sjimharris *        caller requests it, the data written will be forced to ascii
148230557Sjimharris *        printable characters if it isn't already a printable character.
149230557Sjimharris *        A printable character is considered to be >= 0x20 and <= 0x70.
150230557Sjimharris *
151230557Sjimharris * @param[in]  sequence This parameter specifies the translation sequence
152230557Sjimharris *             for which to copy and swap the data.
153230557Sjimharris * @param[out] destination_scsi_io This parameter specifies the SCSI IO
154230557Sjimharris *             request containing the destination buffer into which to copy.
155230557Sjimharris * @param[in]  destination_offset This parameter specifies the offset into
156230557Sjimharris *             the data buffer where the information will be copied to.
157230557Sjimharris * @param[in]  source_value This parameter specifies the value retrieved
158230557Sjimharris *             from the source buffer that is to be copied into the user
159230557Sjimharris *             buffer area.
160230557Sjimharris * @param[in]  use_printable_chars This parameter indicates if the copy should
161230557Sjimharris *             ensure that the value copied is considered an ASCII printable
162230557Sjimharris *             character (e.g. A, B, " ", etc.).  These characters reside
163230557Sjimharris *             in the 0x20 - 0x7E ASCII range.
164230557Sjimharris *
165230557Sjimharris * @return none
166230557Sjimharris */
167230557Sjimharrisstatic
168230557Sjimharrisvoid sati_set_ascii_data_byte(
169230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
170230557Sjimharris   void                       * destination_scsi_io,
171230557Sjimharris   U32                          destination_offset,
172230557Sjimharris   U8                           source_value,
173230557Sjimharris   BOOL                         use_printable_chars
174230557Sjimharris)
175230557Sjimharris{
176230557Sjimharris   // if the user requests that the copied data be ascii printable, then
177230557Sjimharris   // default to " " (i.e. 0x20) for all non-ascii printable characters.
178230557Sjimharris   if((use_printable_chars == TRUE)
179230557Sjimharris     && ((source_value < 0x20) || (source_value > 0x7E)))
180230557Sjimharris   {
181230557Sjimharris      source_value = 0x20;
182230557Sjimharris   }
183230557Sjimharris
184230557Sjimharris   sati_set_data_byte(
185230557Sjimharris      sequence, destination_scsi_io, destination_offset, source_value
186230557Sjimharris   );
187230557Sjimharris}
188230557Sjimharris
189230557Sjimharris/**
190230557Sjimharris * @brief This method performs a copy operation using an offset into the
191230557Sjimharris *        source buffer, an offset into the destination buffer, and a length.
192230557Sjimharris *        It will perform the byte swap from the 16-bit identify field
193230557Sjimharris *        into the network byte order SCSI location.
194230557Sjimharris *
195230557Sjimharris * @param[in]  sequence This parameter specifies the translation sequence
196230557Sjimharris *             for which to copy and swap the data.
197230557Sjimharris * @param[out] destination_scsi_io This parameter specifies the SCSI IO
198230557Sjimharris *             request containing the destination buffer into which to copy.
199230557Sjimharris * @param[in]  destination_offset This parameter specifies the offset into
200230557Sjimharris *             the data buffer where the information will be copied to.
201230557Sjimharris * @param[in]  source_buffer This parameter specifies the source buffer from
202230557Sjimharris *             which the data will be copied.
203230557Sjimharris * @param[in]  source_offset This parameter specifies the offset into the
204230557Sjimharris *             source buffer where the copy shall begin.
205230557Sjimharris * @param[in]  length This parameter specifies the number of bytes to copy
206230557Sjimharris *             during this operation.
207230557Sjimharris * @param[in]  use_printable_chars This parameter indicates if the copy should
208230557Sjimharris *             ensure that the value copied is considered an ASCII printable
209230557Sjimharris *             character (e.g. A, B, " ", etc.).  These characters reside
210230557Sjimharris *             in the 0x20 - 0x7E ASCII range.
211230557Sjimharris *
212230557Sjimharris * @return none
213230557Sjimharris */
214230557Sjimharrisvoid sati_ata_identify_device_copy_data(
215230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
216230557Sjimharris   void                       * destination_scsi_io,
217230557Sjimharris   U32                          destination_offset,
218230557Sjimharris   U8                         * source_buffer,
219230557Sjimharris   U32                          source_offset,
220230557Sjimharris   U32                          length,
221230557Sjimharris   BOOL                         use_printable_chars
222230557Sjimharris)
223230557Sjimharris{
224230557Sjimharris   source_buffer += source_offset;
225230557Sjimharris   while (length > 0)
226230557Sjimharris   {
227230557Sjimharris      sati_set_ascii_data_byte(
228230557Sjimharris         sequence,
229230557Sjimharris         destination_scsi_io,
230230557Sjimharris         destination_offset,
231230557Sjimharris         *(source_buffer+1),
232230557Sjimharris         use_printable_chars
233230557Sjimharris      );
234230557Sjimharris
235230557Sjimharris      sati_set_ascii_data_byte(
236230557Sjimharris         sequence,
237230557Sjimharris         destination_scsi_io,
238230557Sjimharris         destination_offset+1,
239230557Sjimharris         *source_buffer,
240230557Sjimharris         use_printable_chars
241230557Sjimharris      );
242230557Sjimharris
243230557Sjimharris      destination_offset += 2;
244230557Sjimharris      source_buffer      += 2;
245230557Sjimharris      length             -= 2;
246230557Sjimharris   }
247230557Sjimharris}
248230557Sjimharris
249230557Sjimharris/**
250230557Sjimharris * @brief This method performs a copy operation using a source buffer,
251230557Sjimharris *        an offset into the destination buffer, and a length.
252230557Sjimharris *
253230557Sjimharris * @param[in]  sequence This parameter specifies the translation sequence
254230557Sjimharris *             for which to copy and swap the data.
255230557Sjimharris * @param[out] destination_scsi_io This parameter specifies the SCSI IO
256230557Sjimharris *             request containing the destination buffer into which to copy.
257230557Sjimharris * @param[in]  destination_offset This parameter specifies the offset into
258230557Sjimharris *             the data buffer where the information will be copied to.
259230557Sjimharris * @param[in]  source_buffer This parameter specifies the source buffer from
260230557Sjimharris *             which the data will be copied.
261230557Sjimharris * @param[in]  length This parameter specifies the number of bytes to copy
262230557Sjimharris *             during this operation.
263230557Sjimharris *
264230557Sjimharris * @return none
265230557Sjimharris */
266230557Sjimharrisvoid sati_copy_data(
267230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
268230557Sjimharris   void                       * destination_scsi_io,
269230557Sjimharris   U32                          destination_offset,
270230557Sjimharris   U8                         * source_buffer,
271230557Sjimharris   U32                          length
272230557Sjimharris)
273230557Sjimharris{
274230557Sjimharris   while (length > 0)
275230557Sjimharris   {
276230557Sjimharris      sati_set_data_byte(
277230557Sjimharris         sequence, destination_scsi_io, destination_offset, *source_buffer
278230557Sjimharris      );
279230557Sjimharris
280230557Sjimharris      destination_offset++;
281230557Sjimharris      source_buffer++;
282230557Sjimharris      length--;
283230557Sjimharris   }
284230557Sjimharris}
285230557Sjimharris
286230557Sjimharris/**
287230557Sjimharris * @brief This method extracts the Logical Block Address high and low 32-bit
288230557Sjimharris *        values and the sector count 32-bit value from the ATA identify
289230557Sjimharris *        device data.
290230557Sjimharris *
291230557Sjimharris * @param[in]  identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA
292230557Sjimharris *             from which to extract the sector information.
293230557Sjimharris * @param[out] lba_high This parameter specifies the upper 32 bits for the
294230557Sjimharris *             number of logical block addresses for the device. The upper
295230557Sjimharris *             16-bits should always be 0, since 48-bits of LBA is the most
296230557Sjimharris *             supported by an ATA device.
297230557Sjimharris * @param[out] lba_low This parameter specifies the lower 32 bits for the
298230557Sjimharris *             number of logical block addresses for the device.
299230557Sjimharris * @param[out] sector_size This parameter specifies the 32-bits of sector
300230557Sjimharris *             size.  If the ATA device doesn't support reporting it's
301230557Sjimharris *             sector size, then 512 bytes is utilized as the default value.
302230557Sjimharris *
303230557Sjimharris * @return none
304230557Sjimharris */
305230557Sjimharrisvoid sati_ata_identify_device_get_sector_info(
306230557Sjimharris   ATA_IDENTIFY_DEVICE_DATA_T * identify,
307230557Sjimharris   U32                        * lba_high,
308230557Sjimharris   U32                        * lba_low,
309230557Sjimharris   U32                        * sector_size
310230557Sjimharris)
311230557Sjimharris{
312230557Sjimharris   // Calculate the values to be returned
313230557Sjimharris   // Calculation will be different if the SATA device supports
314230557Sjimharris   // 48-bit addressing.  Bit 10 of Word 86 of ATA Identify
315230557Sjimharris   if (identify->command_set_enabled1
316230557Sjimharris       & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE)
317230557Sjimharris   {
318230557Sjimharris      // This drive supports 48-bit addressing
319230557Sjimharris
320230557Sjimharris      *lba_high  = identify->max_48bit_lba[7] << 24;
321230557Sjimharris      *lba_high |= identify->max_48bit_lba[6] << 16;
322230557Sjimharris      *lba_high |= identify->max_48bit_lba[5] << 8;
323230557Sjimharris      *lba_high |= identify->max_48bit_lba[4];
324230557Sjimharris
325230557Sjimharris      *lba_low  = identify->max_48bit_lba[3] << 24;
326230557Sjimharris      *lba_low |= identify->max_48bit_lba[2] << 16;
327230557Sjimharris      *lba_low |= identify->max_48bit_lba[1] << 8;
328230557Sjimharris      *lba_low |= identify->max_48bit_lba[0];
329230557Sjimharris   }
330230557Sjimharris   else
331230557Sjimharris   {
332230557Sjimharris      // This device doesn't support 48-bit addressing
333230557Sjimharris      // Pull out the largest LBA from words 60 and 61.
334230557Sjimharris      *lba_high  = 0;
335230557Sjimharris      *lba_low   = identify->total_num_sectors[3] << 24;
336230557Sjimharris      *lba_low  |= identify->total_num_sectors[2] << 16;
337230557Sjimharris      *lba_low  |= identify->total_num_sectors[1] << 8;
338230557Sjimharris      *lba_low  |= identify->total_num_sectors[0];
339230557Sjimharris   }
340230557Sjimharris
341230557Sjimharris   // If the ATA device reports its sector size (bit 12 of Word 106),
342230557Sjimharris   // then use that instead.
343230557Sjimharris   if (identify->physical_logical_sector_info
344230557Sjimharris       & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE)
345230557Sjimharris   {
346230557Sjimharris      *sector_size  = identify->words_per_logical_sector[3] << 24;
347230557Sjimharris      *sector_size |= identify->words_per_logical_sector[2] << 16;
348230557Sjimharris      *sector_size |= identify->words_per_logical_sector[1] << 8;
349230557Sjimharris      *sector_size |= identify->words_per_logical_sector[0];
350230557Sjimharris   }
351230557Sjimharris   else
352230557Sjimharris   {
353230557Sjimharris      // Default the sector size to 512 bytes
354230557Sjimharris      *sector_size = 512;
355230557Sjimharris   }
356230557Sjimharris}
357230557Sjimharris
358230557Sjimharris/**
359230557Sjimharris * @brief This method will construct the ATA check power mode command.
360230557Sjimharris *
361230557Sjimharris * @pre It is expected that the user has properly set the current contents
362230557Sjimharris *      of the register FIS to 0.
363230557Sjimharris *
364230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
365230557Sjimharris *             for which to build the CHECK POWER MODE command.
366230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
367230557Sjimharris *             for which the command is being constructed.
368230557Sjimharris *
369230557Sjimharris * @return none.
370230557Sjimharris */
371230557Sjimharrisvoid sati_ata_check_power_mode_construct(
372230557Sjimharris   void                       * ata_io,
373230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
374230557Sjimharris)
375230557Sjimharris{
376230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
377230557Sjimharris
378230557Sjimharris   sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE);
379230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
380230557Sjimharris}
381230557Sjimharris
382230557Sjimharris/**
383230557Sjimharris * @brief This method is utilized to set a specific byte in the sense
384230557Sjimharris *        data area.  It will ensure that the supplied byte offset
385230557Sjimharris *        isn't larger then the length of the requested sense data.
386230557Sjimharris *
387230557Sjimharris * @param[in] scsi_io This parameter specifies the user SCSI IO request
388230557Sjimharris *            for which to set the sense data byte.
389230557Sjimharris * @param[in] byte_offset This parameter specifies the byte offset into
390230557Sjimharris *            the sense data buffer where the data should be written.
391230557Sjimharris * @param[in] value This parameter specifies the 8-bit value to be written
392230557Sjimharris *            into the sense data area.
393230557Sjimharris *
394230557Sjimharris * @return none
395230557Sjimharris */
396230557Sjimharrisvoid sati_set_sense_data_byte(
397230557Sjimharris   U8  * sense_data,
398230557Sjimharris   U32   max_sense_data_len,
399230557Sjimharris   U32   byte_offset,
400230557Sjimharris   U8    value
401230557Sjimharris)
402230557Sjimharris{
403230557Sjimharris   // Ensure that we don't attempt to write past the end of the sense
404230557Sjimharris   // data buffer.
405230557Sjimharris   if (byte_offset < max_sense_data_len)
406230557Sjimharris      sense_data[byte_offset] = value;
407230557Sjimharris}
408230557Sjimharris
409230557Sjimharris/**
410230557Sjimharris * @brief This method will construct the common response IU in the user
411230557Sjimharris *           request's response IU location.
412230557Sjimharris *
413230557Sjimharris * @param[out] rsp_iu This parameter specifies the user request's
414230557Sjimharris *                response IU to be constructed.
415230557Sjimharris * @param[in]  scsi_status This parameter specifies the SCSI status
416230557Sjimharris *                value for the user's IO request.
417230557Sjimharris * @param[in]  sense_data_length This parameter specifies the sense data
418230557Sjimharris *                length for response IU.
419230557Sjimharris * @param[in]  data_present The parameter specifies the specific
420230557Sjimharris *                data present value for response IU.
421230557Sjimharris *
422230557Sjimharris * @return none
423230557Sjimharris */
424230557Sjimharrisvoid sati_scsi_common_response_iu_construct(
425230557Sjimharris   SCI_SSP_RESPONSE_IU_T * rsp_iu,
426230557Sjimharris   U8                      scsi_status,
427230557Sjimharris   U8                      sense_data_length,
428230557Sjimharris   U8                      data_present
429230557Sjimharris)
430230557Sjimharris{
431230557Sjimharris   rsp_iu->sense_data_length[3] = sense_data_length;
432230557Sjimharris   rsp_iu->sense_data_length[2] = 0;
433230557Sjimharris   rsp_iu->sense_data_length[1] = 0;
434230557Sjimharris   rsp_iu->sense_data_length[0] = 0;
435230557Sjimharris   rsp_iu->status               = scsi_status;
436230557Sjimharris   rsp_iu->data_present         = data_present;
437230557Sjimharris}
438230557Sjimharris
439230557Sjimharris/**
440230557Sjimharris * @brief This method will construct the buffer for sense data
441230557Sjimharris *        sense data buffer location.  Additionally, it will set the user's
442230557Sjimharris *        SCSI status.
443230557Sjimharris *
444230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request
445230557Sjimharris *                for which to construct the buffer for sense data.
446230557Sjimharris * @param[in]     scsi_status This parameter specifies the SCSI status
447230557Sjimharris *                value for the user's IO request.
448230557Sjimharris * @param[out]    sense_data This paramater
449230557Sjimharris *
450230557Sjimharris * @return none
451230557Sjimharris */
452230557Sjimharrisstatic
453230557Sjimharrisvoid sati_scsi_get_sense_data_buffer(
454230557Sjimharris    SATI_TRANSLATOR_SEQUENCE_T      * sequence,
455230557Sjimharris    void                            * scsi_io,
456230557Sjimharris    U8                                scsi_status,
457230557Sjimharris    U8                             ** sense_data,
458230557Sjimharris    U32                             * sense_len)
459230557Sjimharris{
460230557Sjimharris#ifdef SATI_TRANSPORT_SUPPORTS_SAS
461230557Sjimharris   SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
462230557Sjimharris                                    sati_cb_get_response_iu_address(scsi_io);
463230557Sjimharris
464230557Sjimharris   sati_scsi_common_response_iu_construct(
465230557Sjimharris      rsp_iu,
466230557Sjimharris      scsi_status,
467230557Sjimharris      sati_scsi_get_sense_data_length(sequence, scsi_io),
468230557Sjimharris      SCSI_RESPONSE_DATA_PRES_SENSE_DATA
469230557Sjimharris   );
470230557Sjimharris
471230557Sjimharris   *sense_data                   = (U8*) rsp_iu->data;
472230557Sjimharris   *sense_len                    = SSP_RESPONSE_IU_MAX_DATA * 4;  // dwords to bytes
473230557Sjimharris#else
474230557Sjimharris   *sense_data = sati_cb_get_sense_data_address(scsi_io);
475230557Sjimharris   *sense_len  = sati_cb_get_sense_data_length(scsi_io);
476230557Sjimharris   sati_cb_set_scsi_status(scsi_io, scsi_status);
477230557Sjimharris#endif // SATI_TRANSPORT_SUPPORTS_SAS
478230557Sjimharris}
479230557Sjimharris
480230557Sjimharris/**
481230557Sjimharris * @brief This method extract response code based on on device settings.
482230557Sjimharris *
483230557Sjimharris * @return response code
484230557Sjimharris */
485230557Sjimharrisstatic
486230557SjimharrisU8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence)
487230557Sjimharris{
488230557Sjimharris    if (sequence->device->descriptor_sense_enable)
489230557Sjimharris    {
490230557Sjimharris       return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE;
491230557Sjimharris    }
492230557Sjimharris    else
493230557Sjimharris    {
494230557Sjimharris       return SCSI_FIXED_CURRENT_RESPONSE_CODE;
495230557Sjimharris    }
496230557Sjimharris}
497230557Sjimharris
498230557Sjimharris/**
499230557Sjimharris * @brief This method will return length of descriptor sense data for executed command.
500230557Sjimharris *
501230557Sjimharris * @return sense data length
502230557Sjimharris */
503230557Sjimharrisstatic
504230557SjimharrisU8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence,
505230557Sjimharris        void * scsi_io)
506230557Sjimharris{
507230557Sjimharris    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
508230557Sjimharris    //Initial value is descriptor header length
509230557Sjimharris    U8 length = 8;
510230557Sjimharris
511230557Sjimharris    switch (sati_get_cdb_byte(cdb, 0))
512230557Sjimharris    {
513230557Sjimharris#if !defined(DISABLE_SATI_WRITE_LONG)
514230557Sjimharris    case SCSI_WRITE_LONG_10:
515230557Sjimharris    case SCSI_WRITE_LONG_16:
516230557Sjimharris        length += SCSI_BLOCK_DESCRIPTOR_LENGTH +
517230557Sjimharris            SCSI_INFORMATION_DESCRIPTOR_LENGTH;
518230557Sjimharris        break;
519230557Sjimharris#endif // !defined(DISABLE_SATI_WRITE_LONG)
520230557Sjimharris#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
521230557Sjimharris    case SCSI_REASSIGN_BLOCKS:
522230557Sjimharris        length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH +
523230557Sjimharris            SCSI_INFORMATION_DESCRIPTOR_LENGTH;
524230557Sjimharris        break;
525230557Sjimharris#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
526230557Sjimharris    case SCSI_READ_6:
527230557Sjimharris    case SCSI_READ_10:
528230557Sjimharris    case SCSI_READ_12:
529230557Sjimharris    case SCSI_READ_16:
530230557Sjimharris    case SCSI_WRITE_6:
531230557Sjimharris    case SCSI_WRITE_10:
532230557Sjimharris    case SCSI_WRITE_12:
533230557Sjimharris    case SCSI_WRITE_16:
534230557Sjimharris#if !defined(DISABLE_SATI_VERIFY)
535230557Sjimharris    case SCSI_VERIFY_10:
536230557Sjimharris    case SCSI_VERIFY_12:
537230557Sjimharris    case SCSI_VERIFY_16:
538230557Sjimharris#endif // !defined(DISABLE_SATI_VERIFY)
539230557Sjimharris#if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
540230557Sjimharris    && !defined(DISABLE_SATI_VERIFY)            \
541230557Sjimharris    && !defined(DISABLE_SATI_WRITE)
542230557Sjimharris
543230557Sjimharris    case SCSI_WRITE_AND_VERIFY_10:
544230557Sjimharris    case SCSI_WRITE_AND_VERIFY_12:
545230557Sjimharris    case SCSI_WRITE_AND_VERIFY_16:
546230557Sjimharris#endif //    !defined(DISABLE_SATI_WRITE_AND_VERIFY)
547230557Sjimharris       // && !defined(DISABLE_SATI_VERIFY)
548230557Sjimharris       // && !defined(DISABLE_SATI_WRITE)
549230557Sjimharris        length += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
550230557Sjimharris        break;
551230557Sjimharris    }
552230557Sjimharris
553230557Sjimharris    return length;
554230557Sjimharris}
555230557Sjimharris
556230557Sjimharris/**
557230557Sjimharris * @brief This method will return length of sense data.
558230557Sjimharris *
559230557Sjimharris * @return sense data length
560230557Sjimharris */
561230557SjimharrisU8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io)
562230557Sjimharris{
563230557Sjimharris    U8 response_code;
564230557Sjimharris
565230557Sjimharris    response_code = sati_scsi_get_sense_data_response_code(sequence);
566230557Sjimharris
567230557Sjimharris    switch (response_code)
568230557Sjimharris    {
569230557Sjimharris    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
570230557Sjimharris    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
571230557Sjimharris        return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
572230557Sjimharris    break;
573230557Sjimharris    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
574230557Sjimharris    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
575230557Sjimharris        return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io);
576230557Sjimharris    break;
577230557Sjimharris    }
578230557Sjimharris
579230557Sjimharris    return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
580230557Sjimharris}
581230557Sjimharris
582230557Sjimharris/**
583230557Sjimharris * @brief This method will construct the sense data buffer in the user's
584230557Sjimharris *        sense data buffer location.  Additionally, it will set the user's
585230557Sjimharris *        SCSI status.
586230557Sjimharris *
587230557Sjimharris * @param[in]     sequence This parameter specifies the translation sequence
588230557Sjimharris *                for which to construct the sense data.
589230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request
590230557Sjimharris *                for which to construct the sense data.
591230557Sjimharris * @param[in]     scsi_status This parameter specifies the SCSI status
592230557Sjimharris *                value for the user's IO request.
593230557Sjimharris * @param[in]     sense_key This parameter specifies the sense key to
594230557Sjimharris *                be set for the user's IO request.
595230557Sjimharris * @param[in]     additional_sense_code This parameter specifies the
596230557Sjimharris *                additional sense code (ASC) key to be set for the user's
597230557Sjimharris *                IO request.
598230557Sjimharris * @param[in]     additional_sense_code_qualifier This parameter specifies
599230557Sjimharris *                the additional sense code qualifier (ASCQ) key to be set
600230557Sjimharris *                for the user's IO request.
601230557Sjimharris *
602230557Sjimharris * @return none
603230557Sjimharris */
604230557Sjimharrisvoid sati_scsi_sense_data_construct(
605230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
606230557Sjimharris   void                       * scsi_io,
607230557Sjimharris   U8                           scsi_status,
608230557Sjimharris   U8                           sense_key,
609230557Sjimharris   U8                           additional_sense_code,
610230557Sjimharris   U8                           additional_sense_code_qualifier
611230557Sjimharris)
612230557Sjimharris{
613230557Sjimharris    U8 response_code;
614230557Sjimharris
615230557Sjimharris    response_code = sati_scsi_get_sense_data_response_code(sequence);
616230557Sjimharris
617230557Sjimharris    switch (response_code)
618230557Sjimharris    {
619230557Sjimharris    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
620230557Sjimharris    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
621230557Sjimharris    sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
622230557Sjimharris                sense_key, additional_sense_code, additional_sense_code_qualifier);
623230557Sjimharris    break;
624230557Sjimharris    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
625230557Sjimharris    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
626230557Sjimharris        sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
627230557Sjimharris                sense_key, additional_sense_code, additional_sense_code_qualifier);
628230557Sjimharris        break;
629230557Sjimharris    }
630230557Sjimharris
631230557Sjimharris    sequence->is_sense_response_set = TRUE;
632230557Sjimharris}
633230557Sjimharris
634230557Sjimharris/**
635230557Sjimharris * @brief This method will construct the block descriptor in the user's descriptor
636230557Sjimharris *            sense data buffer location.
637230557Sjimharris *
638230557Sjimharris * @param[in]     sense_data This parameter specifies the user SCSI IO request
639230557Sjimharris *                for which to set the sense data byte.
640230557Sjimharris * @param[in]     sense_len This parameter specifies length of the sense data
641230557Sjimharris *                to be returned by SATI.
642230557Sjimharris * @param[out]    descriptor_len This parameter returns the length of constructed
643230557Sjimharris *                descriptor.
644230557Sjimharris *
645230557Sjimharris * @return none
646230557Sjimharris */
647230557Sjimharrisstatic
648230557Sjimharrisvoid sati_scsi_block_descriptor_construct(
649230557Sjimharris        U8 * sense_data,
650230557Sjimharris        U32 sense_len)
651230557Sjimharris{
652230557Sjimharris    U8 ili = 1;
653230557Sjimharris
654230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_BLOCK_DESCRIPTOR_TYPE);
655230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH);
656230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 2,  0);
657230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 3,  (ili << 5));
658230557Sjimharris}
659230557Sjimharris
660230557Sjimharris/**
661230557Sjimharris * @brief This method will construct the command-specific descriptor for
662230557Sjimharris *           the descriptor sense data buffer in the user's sense data buffer
663230557Sjimharris *           location.
664230557Sjimharris *
665230557Sjimharris * @param[in]     sense_data This parameter specifies the user SCSI IO request
666230557Sjimharris *                for which to set the sense data byte.
667230557Sjimharris * @param[in]     sense_len This parameter specifies length of the sense data
668230557Sjimharris *                to be returned by SATI.
669230557Sjimharris * @param[out]    descriptor_len This parameter returns the length of constructed
670230557Sjimharris *                descriptor.
671230557Sjimharris * @param[in]     information_buff This parameter specifies the address for which
672230557Sjimharris *                to set the command-specific information buffer.
673230557Sjimharris *
674230557Sjimharris * @return none
675230557Sjimharris */
676230557Sjimharrisstatic
677230557Sjimharrisvoid sati_scsi_command_specific_descriptor_construct(
678230557Sjimharris    U8       * sense_data,
679230557Sjimharris    U32        sense_len,
680230557Sjimharris    U8       * information_buff)
681230557Sjimharris{
682230557Sjimharris    U8 i;
683230557Sjimharris
684230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE);
685230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH);
686230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 2,  0);
687230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
688230557Sjimharris
689230557Sjimharris    // fill information buffer
690230557Sjimharris    // SBC 5.20.1 REASSIGN BLOCKS command overview
691230557Sjimharris    // If information about the first LBA not reassigned is not available
692230557Sjimharris    // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh
693230557Sjimharris    for (i=0; i<8; i++)
694230557Sjimharris        sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]);
695230557Sjimharris}
696230557Sjimharris
697230557Sjimharris/**
698230557Sjimharris * @brief This method will construct the information descriptor for
699230557Sjimharris *           the descriptor sense data buffer in the user's sense data buffer
700230557Sjimharris *           location.
701230557Sjimharris *
702230557Sjimharris * @param[in]     sense_data This parameter specifies the user SCSI IO request
703230557Sjimharris *                for which to set the sense data byte.
704230557Sjimharris * @param[in]     sense_len This parameter specifies length of the sense data
705230557Sjimharris *                to be returned by SATI.
706230557Sjimharris * @param[out]    descriptor_len This parameter returns the length of constructed
707230557Sjimharris *                descriptor.
708230557Sjimharris * @param[in]     information_buff This parameter specifies the address for which
709230557Sjimharris *                to set the information buffer.
710230557Sjimharris *
711230557Sjimharris * @return none
712230557Sjimharris */
713230557Sjimharrisstatic
714230557Sjimharrisvoid sati_scsi_information_descriptor_construct(
715230557Sjimharris    U8      * sense_data,
716230557Sjimharris    U32       sense_len,
717230557Sjimharris    U8      * information_buff)
718230557Sjimharris{
719230557Sjimharris    U8 i;
720230557Sjimharris    U8 valid = 1;
721230557Sjimharris
722230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_INFORMATION_DESCRIPTOR_TYPE);
723230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH);
724230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 2,  (valid << 7));
725230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
726230557Sjimharris
727230557Sjimharris    // fill information buffer
728230557Sjimharris    for (i=0; i<8; i++)
729230557Sjimharris        sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]);
730230557Sjimharris}
731230557Sjimharris
732230557Sjimharris/**
733230557Sjimharris * @brief This method will construct the descriptors in the user's descriptor
734230557Sjimharris *           sense data buffer location.
735230557Sjimharris *
736230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request
737230557Sjimharris *                for which to construct the sense data.
738230557Sjimharris * @param[in]     sense_data This parameter specifies the user SCSI IO request
739230557Sjimharris *                for which to set the sense data byte.
740230557Sjimharris * @param[in]     sense_len This parameter specifies length of the sense data
741230557Sjimharris *                to be returned by SATI.
742230557Sjimharris * @param[out]    descriptor_len This parameter returns the length of constructed
743230557Sjimharris *                descriptor.
744230557Sjimharris * @param[in]     information_buff This parameter specifies the address for which
745230557Sjimharris *                to set the information buffer.
746230557Sjimharris *
747230557Sjimharris * @return none
748230557Sjimharris */
749230557Sjimharrisstatic
750230557Sjimharrisvoid sati_scsi_common_descriptors_construct(
751230557Sjimharris    void    * scsi_io,
752230557Sjimharris    U8      * sense_data,
753230557Sjimharris    U32       sense_len,
754230557Sjimharris    U8      * information_buff)
755230557Sjimharris{
756230557Sjimharris    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
757230557Sjimharris    U8 offset = 0;
758230557Sjimharris
759230557Sjimharris    switch (sati_get_cdb_byte(cdb, 0))
760230557Sjimharris    {
761230557Sjimharris#if !defined(DISABLE_SATI_WRITE_LONG)
762230557Sjimharris    case SCSI_WRITE_LONG_10:
763230557Sjimharris    case SCSI_WRITE_LONG_16:
764230557Sjimharris        sati_scsi_block_descriptor_construct(
765230557Sjimharris                sense_data + offset,
766230557Sjimharris                sense_len - offset);
767230557Sjimharris
768230557Sjimharris        offset += SCSI_BLOCK_DESCRIPTOR_LENGTH;
769230557Sjimharris        sati_scsi_information_descriptor_construct(
770230557Sjimharris                  sense_data + offset,
771230557Sjimharris                  sense_len - offset,
772230557Sjimharris                  information_buff);
773230557Sjimharris
774230557Sjimharris        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
775230557Sjimharris        break;
776230557Sjimharris#endif // !defined(DISABLE_SATI_WRITE_LONG)
777230557Sjimharris#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
778230557Sjimharris    case SCSI_REASSIGN_BLOCKS:
779230557Sjimharris        sati_scsi_command_specific_descriptor_construct(
780230557Sjimharris          sense_data + offset,
781230557Sjimharris          sense_len - offset,
782230557Sjimharris          NULL);
783230557Sjimharris
784230557Sjimharris        offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH;
785230557Sjimharris        sati_scsi_information_descriptor_construct(
786230557Sjimharris                  sense_data + offset,
787230557Sjimharris                  sense_len - offset,
788230557Sjimharris                  information_buff);
789230557Sjimharris
790230557Sjimharris        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
791230557Sjimharris        break;
792230557Sjimharris#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
793230557Sjimharris    case SCSI_READ_6:
794230557Sjimharris    case SCSI_READ_10:
795230557Sjimharris    case SCSI_READ_12:
796230557Sjimharris    case SCSI_READ_16:
797230557Sjimharris    case SCSI_WRITE_6:
798230557Sjimharris    case SCSI_WRITE_10:
799230557Sjimharris    case SCSI_WRITE_12:
800230557Sjimharris    case SCSI_WRITE_16:
801230557Sjimharris#if !defined(DISABLE_SATI_VERIFY)
802230557Sjimharris    case SCSI_VERIFY_10:
803230557Sjimharris    case SCSI_VERIFY_12:
804230557Sjimharris    case SCSI_VERIFY_16:
805230557Sjimharris#endif // !defined(DISABLE_SATI_VERIFY)
806230557Sjimharris#if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
807230557Sjimharris    && !defined(DISABLE_SATI_VERIFY)            \
808230557Sjimharris    && !defined(DISABLE_SATI_WRITE)
809230557Sjimharris
810230557Sjimharris    case SCSI_WRITE_AND_VERIFY_10:
811230557Sjimharris    case SCSI_WRITE_AND_VERIFY_12:
812230557Sjimharris    case SCSI_WRITE_AND_VERIFY_16:
813230557Sjimharris#endif //    !defined(DISABLE_SATI_WRITE_AND_VERIFY)
814230557Sjimharris       // && !defined(DISABLE_SATI_VERIFY)
815230557Sjimharris       // && !defined(DISABLE_SATI_WRITE)
816230557Sjimharris        sati_scsi_information_descriptor_construct(
817230557Sjimharris                  sense_data + offset,
818230557Sjimharris                  sense_len - offset,
819230557Sjimharris                  information_buff);
820230557Sjimharris
821230557Sjimharris        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
822230557Sjimharris        break;
823230557Sjimharris    }
824230557Sjimharris}
825230557Sjimharris
826230557Sjimharris/**
827230557Sjimharris * @brief This method will construct the descriptor sense data buffer in
828230557Sjimharris *           the user's sense data buffer location.  Additionally, it will set
829230557Sjimharris *           the user's SCSI status.
830230557Sjimharris *
831230557Sjimharris * @param[in]     sequence This parameter specifies the translation sequence
832230557Sjimharris *                for which to construct the sense data.
833230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request
834230557Sjimharris *                for which to construct the sense data.
835230557Sjimharris * @param[in]     scsi_status This parameter specifies the SCSI status
836230557Sjimharris *                value for the user's IO request.
837230557Sjimharris * @param[in]     sense_key This parameter specifies the sense key to
838230557Sjimharris *                be set for the user's IO request.
839230557Sjimharris * @param[in]     additional_sense_code This parameter specifies the
840230557Sjimharris *                additional sense code (ASC) key to be set for the user's
841230557Sjimharris *                IO request.
842230557Sjimharris * @param[in]     additional_sense_code_qualifier This parameter specifies
843230557Sjimharris *                the additional sense code qualifier (ASCQ) key to be set
844230557Sjimharris *                for the user's IO request.
845230557Sjimharris *
846230557Sjimharris * @return none
847230557Sjimharris */
848230557Sjimharrisvoid sati_scsi_descriptor_sense_data_construct(
849230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
850230557Sjimharris   void                       * scsi_io,
851230557Sjimharris   U8                           scsi_status,
852230557Sjimharris   U8                           response_code,
853230557Sjimharris   U8                           sense_key,
854230557Sjimharris   U8                           additional_sense_code,
855230557Sjimharris   U8                           additional_sense_code_qualifier
856230557Sjimharris)
857230557Sjimharris{
858230557Sjimharris   U8 * sense_data;
859230557Sjimharris   U32    sense_len;
860230557Sjimharris
861230557Sjimharris   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
862230557Sjimharris
863230557Sjimharris   sati_set_sense_data_byte(
864230557Sjimharris      sense_data,
865230557Sjimharris      sense_len,
866230557Sjimharris      0,
867230557Sjimharris      response_code
868230557Sjimharris   );
869230557Sjimharris
870230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 1,  sense_key);
871230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 2,  additional_sense_code);
872230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 3,  additional_sense_code_qualifier);
873230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
874230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
875230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
876230557Sjimharris
877230557Sjimharris   sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL);
878230557Sjimharris
879230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 7,  sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
880230557Sjimharris}
881230557Sjimharris
882230557Sjimharris/**
883230557Sjimharris * @brief This method will construct the fixed format sense data buffer
884230557Sjimharris *           in the user's sense data buffer location.  Additionally, it will
885230557Sjimharris *          set the user's SCSI status.
886230557Sjimharris *
887230557Sjimharris * @param[in]     sequence This parameter specifies the translation sequence
888230557Sjimharris *                for which to construct the sense data.
889230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request
890230557Sjimharris *                for which to construct the sense data.
891230557Sjimharris * @param[in]     scsi_status This parameter specifies the SCSI status
892230557Sjimharris *                value for the user's IO request.
893230557Sjimharris * @param[in]     sense_key This parameter specifies the sense key to
894230557Sjimharris *                be set for the user's IO request.
895230557Sjimharris * @param[in]     additional_sense_code This parameter specifies the
896230557Sjimharris *                additional sense code (ASC) key to be set for the user's
897230557Sjimharris *                IO request.
898230557Sjimharris * @param[in]     additional_sense_code_qualifier This parameter specifies
899230557Sjimharris *                the additional sense code qualifier (ASCQ) key to be set
900230557Sjimharris *                for the user's IO request.
901230557Sjimharris *
902230557Sjimharris * @return none
903230557Sjimharris */
904230557Sjimharrisvoid sati_scsi_fixed_sense_data_construct(
905230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
906230557Sjimharris   void                       * scsi_io,
907230557Sjimharris   U8                           scsi_status,
908230557Sjimharris   U8                           response_code,
909230557Sjimharris   U8                           sense_key,
910230557Sjimharris   U8                           additional_sense_code,
911230557Sjimharris   U8                           additional_sense_code_qualifier
912230557Sjimharris)
913230557Sjimharris{
914230557Sjimharris    U8 * sense_data;
915230557Sjimharris    U32  sense_len;
916230557Sjimharris
917230557Sjimharris    sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
918230557Sjimharris
919230557Sjimharris    // Write out the sense data format per SPC-4.
920230557Sjimharris    // We utilize the fixed format sense data format.
921230557Sjimharris
922230557Sjimharris    sati_set_sense_data_byte(
923230557Sjimharris      sense_data,
924230557Sjimharris      sense_len,
925230557Sjimharris      0,
926230557Sjimharris      response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT
927230557Sjimharris    );
928230557Sjimharris
929230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 1,  0);
930230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 2,  sense_key);
931230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
932230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
933230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
934230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
935230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 7,  0);
936230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 8,  0);
937230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 9,  0);
938230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
939230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
940230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
941230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
942230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
943230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 15, 0);
944230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
945230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
946230557Sjimharris}
947230557Sjimharris
948230557Sjimharris/**
949230557Sjimharris* @brief This method will construct common sense data that will be identical in
950230557Sjimharris*        both read error sense construct functions.
951230557Sjimharris*        sati_scsi_read_ncq_error_sense_construct,
952230557Sjimharris*        sati_scsi_read_error_sense_construct
953230557Sjimharris*
954230557Sjimharris * @param[in]    sense_data This parameter specifies the user SCSI IO request
955230557Sjimharris *               for which to set the sense data byte.
956230557Sjimharris* @param[in]     sense_len This parameter specifies length of the sense data
957230557Sjimharris*                to be returned by SATI.
958230557Sjimharris* @param[in]     sense_key This parameter specifies the sense key to
959230557Sjimharris*                be set for the user's IO request.
960230557Sjimharris* @param[in]     additional_sense_code This parameter specifies the
961230557Sjimharris*                additional sense code (ASC) key to be set for the user's
962230557Sjimharris*                IO request.
963230557Sjimharris* @param[in]     additional_sense_code_qualifier This parameter specifies
964230557Sjimharris*                the additional sense code qualifier (ASCQ) key to be set
965230557Sjimharris*                for the user's IO request.
966230557Sjimharris*
967230557Sjimharris* @return none
968230557Sjimharris*/
969230557Sjimharrisstatic
970230557Sjimharrisvoid sati_scsi_common_fixed_sense_construct(
971230557Sjimharris   U8                         * sense_data,
972230557Sjimharris   U32                          sense_len,
973230557Sjimharris   U8                           sense_key,
974230557Sjimharris   U8                           additional_sense_code,
975230557Sjimharris   U8                           additional_sense_code_qualifier
976230557Sjimharris)
977230557Sjimharris{
978230557Sjimharris
979230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 1,  0);
980230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 2,  sense_key);
981230557Sjimharris
982230557Sjimharris   //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions
983230557Sjimharris
984230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 7,  0);
985230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 8,  0);
986230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 9,  0);
987230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
988230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
989230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
990230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
991230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
992230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 15, 0x80);
993230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
994230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
995230557Sjimharris}
996230557Sjimharris
997230557Sjimharris/**
998230557Sjimharris * @brief This method will construct the descriptor sense data buffer in
999230557Sjimharris *           the user's sense data buffer location.  Additionally, it will set
1000230557Sjimharris *           the user's SCSI status.
1001230557Sjimharris *
1002230557Sjimharris * @param[in]     sequence This parameter specifies the translation sequence
1003230557Sjimharris *                for which to construct the sense data.
1004230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request
1005230557Sjimharris *                for which to construct the sense data.
1006230557Sjimharris * @param[in]     scsi_status This parameter specifies the SCSI status
1007230557Sjimharris *                value for the user's IO request.
1008230557Sjimharris * @param[in]     sense_key This parameter specifies the sense key to
1009230557Sjimharris *                be set for the user's IO request.
1010230557Sjimharris * @param[in]     additional_sense_code This parameter specifies the
1011230557Sjimharris *                additional sense code (ASC) key to be set for the user's
1012230557Sjimharris *                IO request.
1013230557Sjimharris * @param[in]     additional_sense_code_qualifier This parameter specifies
1014230557Sjimharris *                the additional sense code qualifier (ASCQ) key to be set
1015230557Sjimharris *                for the user's IO request.
1016230557Sjimharris *
1017230557Sjimharris * @return none
1018230557Sjimharris */
1019230557Sjimharrisstatic
1020230557Sjimharrisvoid sati_scsi_common_descriptor_sense_construct(
1021230557Sjimharris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1022230557Sjimharris    void                       * scsi_io,
1023230557Sjimharris    U8                         * sense_data,
1024230557Sjimharris    U32                          sense_len,
1025230557Sjimharris    U8                           sense_key,
1026230557Sjimharris    U8                           additional_sense_code,
1027230557Sjimharris    U8                           additional_sense_code_qualifier,
1028230557Sjimharris    U8                         * information_buff
1029230557Sjimharris)
1030230557Sjimharris{
1031230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 1,  sense_key);
1032230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 2,  additional_sense_code);
1033230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 3,  additional_sense_code_qualifier);
1034230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
1035230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
1036230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
1037230557Sjimharris
1038230557Sjimharris    sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff);
1039230557Sjimharris
1040230557Sjimharris    sati_set_sense_data_byte(sense_data, sense_len, 7,  sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
1041230557Sjimharris}
1042230557Sjimharris
1043230557Sjimharris/**
1044230557Sjimharris* @brief This method will construct the sense data buffer in the user's
1045230557Sjimharris*        descriptor sense data buffer location.  Additionally, it will set
1046230557Sjimharris*        the user's SCSI status. This is only used for NCQ uncorrectable
1047230557Sjimharris*        read errors
1048230557Sjimharris*
1049230557Sjimharris* @param[in]     sequence This parameter specifies the translation sequence
1050230557Sjimharris*                for which to construct the sense data.
1051230557Sjimharris* @param[in,out] scsi_io This parameter specifies the user's IO request
1052230557Sjimharris*                for which to construct the sense data.
1053230557Sjimharris* @param[in]     ata_input_data This parameter specifies the user's ATA IO
1054230557Sjimharris*                response from a Read Log Ext command.
1055230557Sjimharris* @param[in]     scsi_status This parameter specifies the SCSI status
1056230557Sjimharris*                value for the user's IO request.
1057230557Sjimharris* @param[in]     sense_key This parameter specifies the sense key to
1058230557Sjimharris*                be set for the user's IO request.
1059230557Sjimharris* @param[in]     additional_sense_code This parameter specifies the
1060230557Sjimharris*                additional sense code (ASC) key to be set for the user's
1061230557Sjimharris*                IO request.
1062230557Sjimharris* @param[in]     additional_sense_code_qualifier This parameter specifies
1063230557Sjimharris*                the additional sense code qualifier (ASCQ) key to be set
1064230557Sjimharris*                for the user's IO request.
1065230557Sjimharris*
1066230557Sjimharris* @return none
1067230557Sjimharris*/
1068230557Sjimharrisstatic
1069230557Sjimharrisvoid sati_scsi_read_ncq_error_descriptor_sense_construct(
1070230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1071230557Sjimharris   void                       * scsi_io,
1072230557Sjimharris   void                       * ata_input_data,
1073230557Sjimharris   U8                           scsi_status,
1074230557Sjimharris   U8                           response_code,
1075230557Sjimharris   U8                           sense_key,
1076230557Sjimharris   U8                           additional_sense_code,
1077230557Sjimharris   U8                           additional_sense_code_qualifier
1078230557Sjimharris)
1079230557Sjimharris{
1080230557Sjimharris   U8 * sense_data;
1081230557Sjimharris   U32  sense_len;
1082230557Sjimharris
1083230557Sjimharris   U8 information_buff[8] = {0};
1084230557Sjimharris
1085230557Sjimharris   ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
1086230557Sjimharris
1087230557Sjimharris   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1088230557Sjimharris
1089230557Sjimharris   sati_set_sense_data_byte(
1090230557Sjimharris      sense_data,
1091230557Sjimharris      sense_len,
1092230557Sjimharris      0,
1093230557Sjimharris      response_code
1094230557Sjimharris   );
1095230557Sjimharris
1096230557Sjimharris   information_buff[2] = ncq_log->lba_47_40;
1097230557Sjimharris   information_buff[3] = ncq_log->lba_39_32;
1098230557Sjimharris   information_buff[4] = ncq_log->lba_31_24;
1099230557Sjimharris   information_buff[5] = ncq_log->lba_23_16;
1100230557Sjimharris   information_buff[6] = ncq_log->lba_15_8;
1101230557Sjimharris   information_buff[7] = ncq_log->lba_7_0;
1102230557Sjimharris
1103230557Sjimharris   sati_scsi_common_descriptor_sense_construct(
1104230557Sjimharris           sequence,
1105230557Sjimharris           scsi_io,
1106230557Sjimharris           sense_data,
1107230557Sjimharris           sense_len,
1108230557Sjimharris           sense_key,
1109230557Sjimharris           additional_sense_code,
1110230557Sjimharris           additional_sense_code_qualifier,
1111230557Sjimharris           information_buff
1112230557Sjimharris   );
1113230557Sjimharris}
1114230557Sjimharris
1115230557Sjimharris/**
1116230557Sjimharris* @brief This method will construct the sense data buffer in the user's
1117230557Sjimharris*        sense data buffer location.  Additionally, it will set the user's
1118230557Sjimharris*        SCSI status. This is only used for NCQ uncorrectable read errors
1119230557Sjimharris*
1120230557Sjimharris* @param[in]     sequence This parameter specifies the translation sequence
1121230557Sjimharris*                for which to construct the sense data.
1122230557Sjimharris* @param[in,out] scsi_io This parameter specifies the user's IO request
1123230557Sjimharris*                for which to construct the sense data.
1124230557Sjimharris* @param[in]     ata_input_data This parameter specifies the user's ATA IO
1125230557Sjimharris*                response from a Read Log Ext command.
1126230557Sjimharris* @param[in]     scsi_status This parameter specifies the SCSI status
1127230557Sjimharris*                value for the user's IO request.
1128230557Sjimharris* @param[in]     sense_key This parameter specifies the sense key to
1129230557Sjimharris*                be set for the user's IO request.
1130230557Sjimharris* @param[in]     additional_sense_code This parameter specifies the
1131230557Sjimharris*                additional sense code (ASC) key to be set for the user's
1132230557Sjimharris*                IO request.
1133230557Sjimharris* @param[in]     additional_sense_code_qualifier This parameter specifies
1134230557Sjimharris*                the additional sense code qualifier (ASCQ) key to be set
1135230557Sjimharris*                for the user's IO request.
1136230557Sjimharris*
1137230557Sjimharris* @return none
1138230557Sjimharris*/
1139230557Sjimharrisstatic
1140230557Sjimharrisvoid sati_scsi_read_ncq_error_fixed_sense_construct(
1141230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1142230557Sjimharris   void                       * scsi_io,
1143230557Sjimharris   void                       * ata_input_data,
1144230557Sjimharris   U8                           scsi_status,
1145230557Sjimharris   U8                           response_code,
1146230557Sjimharris   U8                           sense_key,
1147230557Sjimharris   U8                           additional_sense_code,
1148230557Sjimharris   U8                           additional_sense_code_qualifier
1149230557Sjimharris)
1150230557Sjimharris{
1151230557Sjimharris   U8 * sense_data;
1152230557Sjimharris   U32  sense_len;
1153230557Sjimharris   U8   valid = TRUE;
1154230557Sjimharris
1155230557Sjimharris   ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
1156230557Sjimharris
1157230557Sjimharris   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1158230557Sjimharris
1159230557Sjimharris   if(ncq_log->lba_39_32 > 0)
1160230557Sjimharris   {
1161230557Sjimharris      valid = FALSE;
1162230557Sjimharris   }
1163230557Sjimharris
1164230557Sjimharris   sati_set_sense_data_byte(
1165230557Sjimharris      sense_data,
1166230557Sjimharris      sense_len,
1167230557Sjimharris      0,
1168230557Sjimharris      (valid << 7) | response_code
1169230557Sjimharris   );
1170230557Sjimharris
1171230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 3,  ncq_log->lba_31_24);
1172230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 4,  ncq_log->lba_23_16);
1173230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 5,  ncq_log->lba_15_8);
1174230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 6,  ncq_log->lba_7_0);
1175230557Sjimharris
1176230557Sjimharris   sati_scsi_common_fixed_sense_construct(
1177230557Sjimharris      sense_data,
1178230557Sjimharris      sense_len,
1179230557Sjimharris      sense_key,
1180230557Sjimharris      additional_sense_code,
1181230557Sjimharris      additional_sense_code_qualifier
1182230557Sjimharris   );
1183230557Sjimharris}
1184230557Sjimharris
1185230557Sjimharrisvoid sati_scsi_read_ncq_error_sense_construct(
1186230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1187230557Sjimharris   void                       * scsi_io,
1188230557Sjimharris   void                       * ata_input_data,
1189230557Sjimharris   U8                           scsi_status,
1190230557Sjimharris   U8                           sense_key,
1191230557Sjimharris   U8                           additional_sense_code,
1192230557Sjimharris   U8                           additional_sense_code_qualifier
1193230557Sjimharris)
1194230557Sjimharris{
1195230557Sjimharris    U8 response_code;
1196230557Sjimharris
1197230557Sjimharris    response_code = sati_scsi_get_sense_data_response_code(sequence);
1198230557Sjimharris
1199230557Sjimharris    switch (response_code)
1200230557Sjimharris    {
1201230557Sjimharris    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
1202230557Sjimharris    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
1203230557Sjimharris        sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1204230557Sjimharris                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1205230557Sjimharris    break;
1206230557Sjimharris    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
1207230557Sjimharris    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
1208230557Sjimharris        sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1209230557Sjimharris                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1210230557Sjimharris        break;
1211230557Sjimharris    }
1212230557Sjimharris
1213230557Sjimharris    sequence->is_sense_response_set = TRUE;
1214230557Sjimharris}
1215230557Sjimharris
1216230557Sjimharris/**
1217230557Sjimharris* @brief This method will construct the sense data buffer in the user's
1218230557Sjimharris*        sense data buffer location.  Additionally, it will set the user's
1219230557Sjimharris*        SCSI status. This is used for uncorrectable read errors.
1220230557Sjimharris*
1221230557Sjimharris* @param[in]     sequence This parameter specifies the translation sequence
1222230557Sjimharris*                for which to construct the sense data.
1223230557Sjimharris* @param[in,out] scsi_io This parameter specifies the user's IO request
1224230557Sjimharris*                for which to construct the sense data.
1225230557Sjimharris* @param[in]     ata_io This parameter is a pointer to the ATA IO data used
1226230557Sjimharris*                to get the ATA register fis.
1227230557Sjimharris* @param[in]     scsi_status This parameter specifies the SCSI status
1228230557Sjimharris*                value for the user's IO request.
1229230557Sjimharris* @param[in]     sense_key This parameter specifies the sense key to
1230230557Sjimharris*                be set for the user's IO request.
1231230557Sjimharris* @param[in]     additional_sense_code This parameter specifies the
1232230557Sjimharris*                additional sense code (ASC) key to be set for the user's
1233230557Sjimharris*                IO request.
1234230557Sjimharris* @param[in]     additional_sense_code_qualifier This parameter specifies
1235230557Sjimharris*                the additional sense code qualifier (ASCQ) key to be set
1236230557Sjimharris*                for the user's IO request.
1237230557Sjimharris*
1238230557Sjimharris* @return none
1239230557Sjimharris*/
1240230557Sjimharrisstatic
1241230557Sjimharrisvoid sati_scsi_read_error_descriptor_sense_construct(
1242230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1243230557Sjimharris   void                       * scsi_io,
1244230557Sjimharris   void                       * ata_io,
1245230557Sjimharris   U8                           scsi_status,
1246230557Sjimharris   U8                           response_code,
1247230557Sjimharris   U8                           sense_key,
1248230557Sjimharris   U8                           additional_sense_code,
1249230557Sjimharris   U8                           additional_sense_code_qualifier
1250230557Sjimharris)
1251230557Sjimharris{
1252230557Sjimharris   U8 * sense_data;
1253230557Sjimharris   U32  sense_len;
1254230557Sjimharris   U8 information_buff[8] = {0};
1255230557Sjimharris
1256230557Sjimharris   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
1257230557Sjimharris
1258230557Sjimharris   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1259230557Sjimharris
1260230557Sjimharris   information_buff[2] = sati_get_ata_lba_high_ext(register_fis);
1261230557Sjimharris   information_buff[3] = sati_get_ata_lba_mid_ext(register_fis);
1262230557Sjimharris   information_buff[4] = sati_get_ata_lba_low_ext(register_fis);
1263230557Sjimharris   information_buff[5] = sati_get_ata_lba_high(register_fis);
1264230557Sjimharris   information_buff[6] = sati_get_ata_lba_mid(register_fis);
1265230557Sjimharris   information_buff[7] = sati_get_ata_lba_low(register_fis);
1266230557Sjimharris
1267230557Sjimharris   sati_set_sense_data_byte(
1268230557Sjimharris      sense_data,
1269230557Sjimharris      sense_len,
1270230557Sjimharris      0,
1271230557Sjimharris      SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE
1272230557Sjimharris   );
1273230557Sjimharris
1274230557Sjimharris   sati_scsi_common_descriptor_sense_construct(
1275230557Sjimharris      sequence,
1276230557Sjimharris      scsi_io,
1277230557Sjimharris      sense_data,
1278230557Sjimharris      sense_len,
1279230557Sjimharris      sense_key,
1280230557Sjimharris      additional_sense_code,
1281230557Sjimharris      additional_sense_code_qualifier,
1282230557Sjimharris      information_buff
1283230557Sjimharris   );
1284230557Sjimharris}
1285230557Sjimharris
1286230557Sjimharris/**
1287230557Sjimharris* @brief This method will construct the sense data buffer in the user's
1288230557Sjimharris*        sense data buffer location.  Additionally, it will set the user's
1289230557Sjimharris*        SCSI status. This is used for uncorrectable read errors.
1290230557Sjimharris*
1291230557Sjimharris* @param[in]     sequence This parameter specifies the translation sequence
1292230557Sjimharris*                for which to construct the sense data.
1293230557Sjimharris* @param[in,out] scsi_io This parameter specifies the user's IO request
1294230557Sjimharris*                for which to construct the sense data.
1295230557Sjimharris* @param[in]     ata_io This parameter is a pointer to the ATA IO data used
1296230557Sjimharris*                to get the ATA register fis.
1297230557Sjimharris* @param[in]     scsi_status This parameter specifies the SCSI status
1298230557Sjimharris*                value for the user's IO request.
1299230557Sjimharris* @param[in]     sense_key This parameter specifies the sense key to
1300230557Sjimharris*                be set for the user's IO request.
1301230557Sjimharris* @param[in]     additional_sense_code This parameter specifies the
1302230557Sjimharris*                additional sense code (ASC) key to be set for the user's
1303230557Sjimharris*                IO request.
1304230557Sjimharris* @param[in]     additional_sense_code_qualifier This parameter specifies
1305230557Sjimharris*                the additional sense code qualifier (ASCQ) key to be set
1306230557Sjimharris*                for the user's IO request.
1307230557Sjimharris*
1308230557Sjimharris* @return none
1309230557Sjimharris*/
1310230557Sjimharrisstatic
1311230557Sjimharrisvoid sati_scsi_read_error_fixed_sense_construct(
1312230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1313230557Sjimharris   void                       * scsi_io,
1314230557Sjimharris   void                       * ata_io,
1315230557Sjimharris   U8                           scsi_status,
1316230557Sjimharris   U8                           response_code,
1317230557Sjimharris   U8                           sense_key,
1318230557Sjimharris   U8                           additional_sense_code,
1319230557Sjimharris   U8                           additional_sense_code_qualifier
1320230557Sjimharris)
1321230557Sjimharris{
1322230557Sjimharris   U8 * sense_data;
1323230557Sjimharris   U32  sense_len;
1324230557Sjimharris   U8   valid = TRUE;
1325230557Sjimharris
1326230557Sjimharris   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
1327230557Sjimharris
1328230557Sjimharris   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1329230557Sjimharris
1330230557Sjimharris   if(sati_get_ata_lba_mid_ext(register_fis) > 0)
1331230557Sjimharris   {
1332230557Sjimharris      valid = FALSE;
1333230557Sjimharris   }
1334230557Sjimharris
1335230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 3,  sati_get_ata_lba_low_ext(register_fis));
1336230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 4,  sati_get_ata_lba_high(register_fis));
1337230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 5,  sati_get_ata_lba_mid(register_fis));
1338230557Sjimharris   sati_set_sense_data_byte(sense_data, sense_len, 6,  sati_get_ata_lba_low(register_fis));
1339230557Sjimharris
1340230557Sjimharris
1341230557Sjimharris   sati_set_sense_data_byte(
1342230557Sjimharris      sense_data,
1343230557Sjimharris      sense_len,
1344230557Sjimharris      0,
1345230557Sjimharris      (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE
1346230557Sjimharris   );
1347230557Sjimharris
1348230557Sjimharris   sati_scsi_common_fixed_sense_construct(
1349230557Sjimharris      sense_data,
1350230557Sjimharris      sense_len,
1351230557Sjimharris      sense_key,
1352230557Sjimharris      additional_sense_code,
1353230557Sjimharris      additional_sense_code_qualifier
1354230557Sjimharris   );
1355230557Sjimharris}
1356230557Sjimharris
1357230557Sjimharrisvoid sati_scsi_read_error_sense_construct(
1358230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1359230557Sjimharris   void                       * scsi_io,
1360230557Sjimharris   void                       * ata_input_data,
1361230557Sjimharris   U8                           scsi_status,
1362230557Sjimharris   U8                           sense_key,
1363230557Sjimharris   U8                           additional_sense_code,
1364230557Sjimharris   U8                           additional_sense_code_qualifier
1365230557Sjimharris)
1366230557Sjimharris{
1367230557Sjimharris    U8 response_code;
1368230557Sjimharris
1369230557Sjimharris    response_code = sati_scsi_get_sense_data_response_code(sequence);
1370230557Sjimharris
1371230557Sjimharris    switch (response_code)
1372230557Sjimharris    {
1373230557Sjimharris    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
1374230557Sjimharris    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
1375230557Sjimharris        sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1376230557Sjimharris                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1377230557Sjimharris    break;
1378230557Sjimharris    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
1379230557Sjimharris    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
1380230557Sjimharris        sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1381230557Sjimharris                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1382230557Sjimharris        break;
1383230557Sjimharris    }
1384230557Sjimharris
1385230557Sjimharris    sequence->is_sense_response_set = TRUE;
1386230557Sjimharris}
1387230557Sjimharris
1388230557Sjimharris/*
1389230557Sjimharris * @brief This method builds the scsi response data for a sata task management
1390230557Sjimharris *        request.
1391230557Sjimharris *
1392230557Sjimharris * @param[in]     sequence This parameter specifies the translation sequence
1393230557Sjimharris *                for which to construct the sense data.
1394230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request
1395230557Sjimharris *                for which to construct the sense data.
1396230557Sjimharris * @param[in]     response_data The response status for the task management
1397230557Sjimharris *                request.
1398230557Sjimharris */
1399230557Sjimharrisvoid sati_scsi_response_data_construct(
1400230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1401230557Sjimharris   void                       * scsi_io,
1402230557Sjimharris   U8                           response_data
1403230557Sjimharris)
1404230557Sjimharris{
1405230557Sjimharris#ifdef SATI_TRANSPORT_SUPPORTS_SAS
1406230557Sjimharris   SCI_SSP_RESPONSE_IU_T * rsp_iu  = (SCI_SSP_RESPONSE_IU_T*)
1407230557Sjimharris                                        sati_cb_get_response_iu_address(scsi_io);
1408230557Sjimharris   rsp_iu->data_present            = 0x01;
1409230557Sjimharris   rsp_iu->response_data_length[3] = sizeof(U32);
1410230557Sjimharris   rsp_iu->status                  = 0;
1411230557Sjimharris   ((U8 *)rsp_iu->data)[3]         = response_data;
1412230557Sjimharris#else
1413230557Sjimharris#endif // SATI_TRANSPORT_SUPPORTS_SAS
1414230557Sjimharris}
1415230557Sjimharris
1416230557Sjimharris/**
1417230557Sjimharris * @brief This method checks to make sure that the translation isn't
1418230557Sjimharris *        exceeding the allocation length specified in the CDB prior
1419230557Sjimharris *        to retrieving the payload data byte from the user's buffer.
1420230557Sjimharris *
1421230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request
1422230557Sjimharris *                for which to set the user payload data byte.
1423230557Sjimharris * @param[in]     byte_offset This parameter specifies the offset into
1424230557Sjimharris *                the user's payload buffer at which to write the supplied
1425230557Sjimharris *                value.
1426230557Sjimharris * @param[in]     value This parameter specifies the memory location into
1427230557Sjimharris *                which to read the value from the user's payload buffer.
1428230557Sjimharris *
1429230557Sjimharris * @return none
1430230557Sjimharris */
1431230557Sjimharrisvoid sati_get_data_byte(
1432230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1433230557Sjimharris   void                       * scsi_io,
1434230557Sjimharris   U32                          byte_offset,
1435230557Sjimharris   U8                         * value
1436230557Sjimharris)
1437230557Sjimharris{
1438230557Sjimharris   if (byte_offset < sequence->allocation_length)
1439230557Sjimharris      sati_cb_get_data_byte(scsi_io, byte_offset, value);
1440230557Sjimharris}
1441230557Sjimharris
1442230557Sjimharris/**
1443230557Sjimharris * @brief This method checks to make sure that the translation isn't
1444230557Sjimharris *        exceeding the allocation length specified in the CDB while
1445230557Sjimharris *        translating payload data into the user's buffer.
1446230557Sjimharris *
1447230557Sjimharris * @param[in]     sequence This parameter specifies the translation sequence
1448230557Sjimharris *                for which to set the user payload data byte.
1449230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request
1450230557Sjimharris *                for which to set the user payload data byte.
1451230557Sjimharris * @param[in]     byte_offset This parameter specifies the offset into
1452230557Sjimharris *                the user's payload buffer at which to write the supplied
1453230557Sjimharris *                value.
1454230557Sjimharris * @param[in]     value This parameter specifies the new value to be
1455230557Sjimharris *                written out into the user's payload buffer.
1456230557Sjimharris *
1457230557Sjimharris * @return none
1458230557Sjimharris */
1459230557Sjimharrisvoid sati_set_data_byte(
1460230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1461230557Sjimharris   void                       * scsi_io,
1462230557Sjimharris   U32                          byte_offset,
1463230557Sjimharris   U8                           value
1464230557Sjimharris)
1465230557Sjimharris{
1466230557Sjimharris   if (byte_offset < sequence->allocation_length)
1467230557Sjimharris   {
1468230557Sjimharris      sequence->number_data_bytes_set++;
1469230557Sjimharris      sati_cb_set_data_byte(scsi_io, byte_offset, value);
1470230557Sjimharris   }
1471230557Sjimharris}
1472230557Sjimharris
1473230557Sjimharris/**
1474230557Sjimharris * @brief This method checks to make sure that the translation isn't
1475230557Sjimharris *        exceeding the allocation length specified in the CDB while
1476230557Sjimharris *        translating payload data into the user's buffer.
1477230557Sjimharris *
1478230557Sjimharris * @param[in]     sequence This parameter specifies the translation sequence
1479230557Sjimharris *                for which to set the user payload data dword.
1480230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request
1481230557Sjimharris *                for which to set the user payload data dword.
1482230557Sjimharris * @param[in]     byte_offset This parameter specifies the offset into
1483230557Sjimharris *                the user's payload buffer at which to write the supplied
1484230557Sjimharris *                value.
1485230557Sjimharris * @param[in]     value This parameter specifies the new value to be
1486230557Sjimharris *                written out into the user's payload buffer.
1487230557Sjimharris *
1488230557Sjimharris * @return none
1489230557Sjimharris */
1490230557Sjimharrisvoid sati_set_data_dword(
1491230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1492230557Sjimharris   void                       * scsi_io,
1493230557Sjimharris   U32                          byte_offset,
1494230557Sjimharris   U32                          value
1495230557Sjimharris)
1496230557Sjimharris{
1497230557Sjimharris   /// @todo Check to ensure that the bytes appear correctly (SAS Address).
1498230557Sjimharris
1499230557Sjimharris   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF);
1500230557Sjimharris       byte_offset++;
1501230557Sjimharris   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF);
1502230557Sjimharris       byte_offset++;
1503230557Sjimharris   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF);
1504230557Sjimharris       byte_offset++;
1505230557Sjimharris   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF);
1506230557Sjimharris}
1507230557Sjimharris
1508230557Sjimharris/**
1509230557Sjimharris * @brief This method will construct the ATA flush cache command.
1510230557Sjimharris *
1511230557Sjimharris * @pre It is expected that the user has properly set the current contents
1512230557Sjimharris *      of the register FIS to 0.
1513230557Sjimharris *
1514230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
1515230557Sjimharris *             for which to build the FLUSH CACHE command.
1516230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
1517230557Sjimharris *             for which the command is being constructed.
1518230557Sjimharris *
1519230557Sjimharris * @return none.
1520230557Sjimharris */
1521230557Sjimharrisvoid sati_ata_flush_cache_construct(
1522230557Sjimharris   void                       * ata_io,
1523230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
1524230557Sjimharris)
1525230557Sjimharris{
1526230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1527230557Sjimharris
1528230557Sjimharris   sati_set_ata_command(register_fis, ATA_FLUSH_CACHE);
1529230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1530230557Sjimharris}
1531230557Sjimharris
1532230557Sjimharris/**
1533230557Sjimharris * @brief This method will construct the ATA standby immediate command.
1534230557Sjimharris *
1535230557Sjimharris * @pre It is expected that the user has properly set the current contents
1536230557Sjimharris *      of the register FIS to 0.
1537230557Sjimharris *
1538230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
1539230557Sjimharris *             for which to build the STANDBY IMMEDIATE command.
1540230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
1541230557Sjimharris *             for which the command is being constructed.
1542230557Sjimharris *
1543230557Sjimharris * @param[in]  count This parameter specifies the time period programmed
1544230557Sjimharris *             into the Standby Timer. See ATA8 spec for more details
1545230557Sjimharris * @return none.
1546230557Sjimharris */
1547230557Sjimharrisvoid sati_ata_standby_construct(
1548230557Sjimharris   void                       * ata_io,
1549230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1550230557Sjimharris   U16                          count
1551230557Sjimharris)
1552230557Sjimharris{
1553230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1554230557Sjimharris
1555230557Sjimharris   sati_set_ata_command(register_fis, ATA_STANDBY);
1556230557Sjimharris   sati_set_ata_sector_count(register_fis, count);
1557230557Sjimharris
1558230557Sjimharris   sequence->device->ata_standby_timer = (U8) count;
1559230557Sjimharris
1560230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1561230557Sjimharris}
1562230557Sjimharris
1563230557Sjimharris/**
1564230557Sjimharris * @brief This method will construct the ATA standby immediate command.
1565230557Sjimharris *
1566230557Sjimharris * @pre It is expected that the user has properly set the current contents
1567230557Sjimharris *      of the register FIS to 0.
1568230557Sjimharris *
1569230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
1570230557Sjimharris *             for which to build the STANDBY IMMEDIATE command.
1571230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
1572230557Sjimharris *             for which the command is being constructed.
1573230557Sjimharris *
1574230557Sjimharris * @return none.
1575230557Sjimharris */
1576230557Sjimharrisvoid sati_ata_standby_immediate_construct(
1577230557Sjimharris   void                       * ata_io,
1578230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
1579230557Sjimharris)
1580230557Sjimharris{
1581230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1582230557Sjimharris
1583230557Sjimharris   sati_set_ata_command(register_fis, ATA_STANDBY_IMMED);
1584230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1585230557Sjimharris}
1586230557Sjimharris
1587230557Sjimharris/**
1588230557Sjimharris * @brief This method will construct the ATA idle immediate command.
1589230557Sjimharris *
1590230557Sjimharris * @pre It is expected that the user has properly set the current contents
1591230557Sjimharris *      of the register FIS to 0.
1592230557Sjimharris *
1593230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
1594230557Sjimharris *             for which to build the IDLE IMMEDIATE command.
1595230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
1596230557Sjimharris *             for which the command is being constructed.
1597230557Sjimharris *
1598230557Sjimharris * @return none.
1599230557Sjimharris */
1600230557Sjimharrisvoid sati_ata_idle_immediate_construct(
1601230557Sjimharris   void                       * ata_io,
1602230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
1603230557Sjimharris)
1604230557Sjimharris{
1605230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1606230557Sjimharris
1607230557Sjimharris   sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
1608230557Sjimharris   sati_set_ata_features(register_fis, 0x00);
1609230557Sjimharris   sati_set_ata_sector_count(register_fis, 0x00);
1610230557Sjimharris   sati_set_ata_lba_high(register_fis, 0x00);
1611230557Sjimharris   sati_set_ata_lba_mid(register_fis, 0x00);
1612230557Sjimharris   sati_set_ata_lba_low(register_fis, 0x00);
1613230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1614230557Sjimharris}
1615230557Sjimharris
1616230557Sjimharris/**
1617230557Sjimharris * @brief This method will construct the ATA idle immediate command
1618230557Sjimharris          for Unload Features.
1619230557Sjimharris *
1620230557Sjimharris * @pre It is expected that the user has properly set the current contents
1621230557Sjimharris *      of the register FIS to 0.
1622230557Sjimharris *
1623230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
1624230557Sjimharris *             for which to build the IDLE IMMEDIATE command.
1625230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
1626230557Sjimharris *             for which the command is being constructed.
1627230557Sjimharris *
1628230557Sjimharris * @return none.
1629230557Sjimharris */
1630230557Sjimharrisvoid sati_ata_idle_immediate_unload_construct(
1631230557Sjimharris   void                       * ata_io,
1632230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
1633230557Sjimharris)
1634230557Sjimharris{
1635230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1636230557Sjimharris
1637230557Sjimharris   sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
1638230557Sjimharris   sati_set_ata_features(register_fis, 0x44);
1639230557Sjimharris   sati_set_ata_sector_count(register_fis, 0x00);
1640230557Sjimharris   sati_set_ata_lba_high(register_fis, 0x55);
1641230557Sjimharris   sati_set_ata_lba_mid(register_fis, 0x4E);
1642230557Sjimharris   sati_set_ata_lba_low(register_fis, 0x4C);
1643230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1644230557Sjimharris}
1645230557Sjimharris
1646230557Sjimharris/**
1647230557Sjimharris * @brief This method will construct the ATA IDLE command.\
1648230557Sjimharris *
1649230557Sjimharris * @pre It is expected that the user has properly set the current contents
1650230557Sjimharris *      of the register FIS to 0.
1651230557Sjimharris *
1652230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
1653230557Sjimharris *             for which to build the ATA IDLE command.
1654230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
1655230557Sjimharris *             for which the command is being constructed.
1656230557Sjimharris *
1657230557Sjimharris * @return none.
1658230557Sjimharris */
1659230557Sjimharrisvoid sati_ata_idle_construct(
1660230557Sjimharris   void                       * ata_io,
1661230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
1662230557Sjimharris)
1663230557Sjimharris{
1664230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1665230557Sjimharris
1666230557Sjimharris   sati_set_ata_command(register_fis, ATA_IDLE);
1667230557Sjimharris   sati_set_ata_features(register_fis, 0x00);
1668230557Sjimharris   sati_set_ata_sector_count(register_fis, 0x00);
1669230557Sjimharris
1670230557Sjimharris   sequence->device->ata_standby_timer = 0x00;
1671230557Sjimharris
1672230557Sjimharris   sati_set_ata_lba_high(register_fis, 0x00);
1673230557Sjimharris   sati_set_ata_lba_mid(register_fis, 0x00);
1674230557Sjimharris   sati_set_ata_lba_low(register_fis, 0x00);
1675230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1676230557Sjimharris}
1677230557Sjimharris
1678230557Sjimharris/**
1679230557Sjimharris * @brief This method will construct the ATA MEDIA EJECT command.
1680230557Sjimharris *
1681230557Sjimharris * @pre It is expected that the user has properly set the current contents
1682230557Sjimharris *      of the register FIS to 0.
1683230557Sjimharris *
1684230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
1685230557Sjimharris *             for which to build the MEDIA EJCT command.
1686230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
1687230557Sjimharris *             for which the command is being constructed.
1688230557Sjimharris *
1689230557Sjimharris * @return none.
1690230557Sjimharris */
1691230557Sjimharrisvoid sati_ata_media_eject_construct(
1692230557Sjimharris   void                       * ata_io,
1693230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
1694230557Sjimharris)
1695230557Sjimharris{
1696230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1697230557Sjimharris
1698230557Sjimharris   sati_set_ata_command(register_fis, ATA_MEDIA_EJECT);
1699230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1700230557Sjimharris}
1701230557Sjimharris
1702230557Sjimharris
1703230557Sjimharris/**
1704230557Sjimharris * @brief This method will construct the ATA read verify sector(s) command.
1705230557Sjimharris *
1706230557Sjimharris * @pre It is expected that the user has properly set the current contents
1707230557Sjimharris *      of the register FIS to 0.
1708230557Sjimharris *
1709230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure
1710230557Sjimharris *             for which to build the ATA READ VERIFY SECTOR(S) command.
1711230557Sjimharris * @param[in]  sequence This parameter specifies the translator sequence
1712230557Sjimharris *             for which the command is being constructed.
1713230557Sjimharris *
1714230557Sjimharris * @return none.
1715230557Sjimharris */
1716230557Sjimharrisvoid sati_ata_read_verify_sectors_construct(
1717230557Sjimharris   void                       * ata_io,
1718230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
1719230557Sjimharris)
1720230557Sjimharris{
1721230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1722230557Sjimharris
1723230557Sjimharris   sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
1724230557Sjimharris
1725230557Sjimharris   //According to SAT-2 (v7) 9.11.3
1726230557Sjimharris   sati_set_ata_sector_count(register_fis, 1);
1727230557Sjimharris
1728230557Sjimharris   //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the
1729230557Sjimharris   //maximum LBA supported by the ATA device in its current configuration.
1730230557Sjimharris   //From the unit test, it seems we have to set LBA to a non-zero value.
1731230557Sjimharris   sati_set_ata_lba_low(register_fis, 1);
1732230557Sjimharris
1733230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1734230557Sjimharris}
1735230557Sjimharris
1736230557Sjimharris/**
1737230557Sjimharris * @brief This method will construct a ATA SMART Return Status command so the
1738230557Sjimharris *        status of the ATA device can be returned. The status of the SMART
1739230557Sjimharris *        threshold will be returned by this command.
1740230557Sjimharris *
1741230557Sjimharris * @return N/A
1742230557Sjimharris *
1743230557Sjimharris */
1744230557Sjimharrisvoid sati_ata_smart_return_status_construct(
1745230557Sjimharris   void                       * ata_io,
1746230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1747230557Sjimharris   U8                           feature_value
1748230557Sjimharris)
1749230557Sjimharris{
1750230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1751230557Sjimharris
1752230557Sjimharris   sati_set_ata_command(register_fis, ATA_SMART);
1753230557Sjimharris
1754230557Sjimharris   sati_set_ata_features(register_fis, feature_value);
1755230557Sjimharris
1756230557Sjimharris   sati_set_ata_lba_high(register_fis, 0xC2);
1757230557Sjimharris   sati_set_ata_lba_mid(register_fis, 0x4F);
1758230557Sjimharris
1759230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1760230557Sjimharris}
1761230557Sjimharris
1762230557Sjimharris/**
1763230557Sjimharris * @brief This method will construct a ATA SMART Return Status command so the
1764230557Sjimharris *        status of the ATA device can be returned. The status of the SMART
1765230557Sjimharris *        threshold will be returned by this command.
1766230557Sjimharris *
1767230557Sjimharris * @return N/A
1768230557Sjimharris *
1769230557Sjimharris */
1770230557Sjimharrisvoid sati_ata_smart_read_log_construct(
1771230557Sjimharris   void                       * ata_io,
1772230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1773230557Sjimharris   U8                           log_address,
1774230557Sjimharris   U32                          transfer_length
1775230557Sjimharris)
1776230557Sjimharris{
1777230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1778230557Sjimharris
1779230557Sjimharris   sati_set_ata_command(register_fis, ATA_SMART);
1780230557Sjimharris   sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG);
1781230557Sjimharris
1782230557Sjimharris   sati_set_ata_lba_high(register_fis, 0xC2);
1783230557Sjimharris   sati_set_ata_lba_mid(register_fis, 0x4F);
1784230557Sjimharris   sati_set_ata_lba_low(register_fis, log_address);
1785230557Sjimharris
1786230557Sjimharris   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1787230557Sjimharris   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1788230557Sjimharris   sequence->ata_transfer_length = transfer_length;
1789230557Sjimharris}
1790230557Sjimharris
1791230557Sjimharris/**
1792230557Sjimharris * @brief This method will construct a Write Uncorrectable ATA command that
1793230557Sjimharris *        will write one sector with a psuedo or flagged error. The type of
1794230557Sjimharris *        error is specified by the feature value.
1795230557Sjimharris *
1796230557Sjimharris * @return N/A
1797230557Sjimharris *
1798230557Sjimharris */
1799230557Sjimharrisvoid sati_ata_write_uncorrectable_construct(
1800230557Sjimharris   void                       * ata_io,
1801230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1802230557Sjimharris   U8                           feature_value
1803230557Sjimharris)
1804230557Sjimharris{
1805230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1806230557Sjimharris
1807230557Sjimharris   sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE);
1808230557Sjimharris   sati_set_ata_features(register_fis, feature_value);
1809230557Sjimharris   sati_set_ata_sector_count(register_fis, 0x0001);
1810230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1811230557Sjimharris}
1812230557Sjimharris
1813230557Sjimharris/**
1814230557Sjimharris * @brief This method will construct a Mode Select ATA SET FEATURES command
1815230557Sjimharris *        For example, Enable/Disable Write Cache, Enable/Disable Read Ahead
1816230557Sjimharris *
1817230557Sjimharris * @return N/A
1818230557Sjimharris *
1819230557Sjimharris */
1820230557Sjimharrisvoid sati_ata_set_features_construct(
1821230557Sjimharris   void                       * ata_io,
1822230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1823230557Sjimharris   U8                           feature
1824230557Sjimharris)
1825230557Sjimharris{
1826230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1827230557Sjimharris
1828230557Sjimharris   sati_set_ata_command(register_fis, ATA_SET_FEATURES);
1829230557Sjimharris   sati_set_ata_features(register_fis, feature);
1830230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
1831230557Sjimharris}
1832230557Sjimharris
1833230557Sjimharris
1834230557Sjimharris
1835230557Sjimharris/**
1836230557Sjimharris * @brief This method will construct a Read Log ext ATA command that
1837230557Sjimharris *        will request a log page based on the log_address.
1838230557Sjimharris *
1839230557Sjimharris * @param[in]  log_address This parameter specifies the log page
1840230557Sjimharris *             to be returned from Read Log Ext.
1841230557Sjimharris *
1842230557Sjimharris * @param[in]  transfer_length This parameter specifies the size of the
1843230557Sjimharris *             log page response returned by Read Log Ext.
1844230557Sjimharris *
1845230557Sjimharris * @return N/A
1846230557Sjimharris *
1847230557Sjimharris */
1848230557Sjimharrisvoid sati_ata_read_log_ext_construct(
1849230557Sjimharris   void                          * ata_io,
1850230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T    * sequence,
1851230557Sjimharris   U8                              log_address,
1852230557Sjimharris   U32                             transfer_length
1853230557Sjimharris)
1854230557Sjimharris{
1855230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1856230557Sjimharris
1857230557Sjimharris   sati_set_ata_command(register_fis, ATA_READ_LOG_EXT);
1858230557Sjimharris
1859230557Sjimharris   sati_set_ata_lba_low(register_fis, log_address);
1860230557Sjimharris   sati_set_ata_lba_mid(register_fis, 0x00);
1861230557Sjimharris   sati_set_ata_lba_mid_exp(register_fis, 0x00);
1862230557Sjimharris
1863230557Sjimharris   sati_set_ata_sector_count(register_fis, 0x01);
1864230557Sjimharris
1865230557Sjimharris   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1866230557Sjimharris   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1867230557Sjimharris   sequence->ata_transfer_length = transfer_length;
1868230557Sjimharris
1869230557Sjimharris}
1870230557Sjimharris
1871230557Sjimharris/**
1872230557Sjimharris* @brief This method will check if the ATA device is in the stopped power
1873230557Sjimharris*        state. This is used for all medium access commands for SAT
1874230557Sjimharris*        compliance. See SAT2r07 section 9.11.1
1875230557Sjimharris*
1876230557Sjimharris* @param[in] sequence - SATI sequence data with the device state.
1877230557Sjimharris*
1878230557Sjimharris* @return TRUE If device is stopped
1879230557Sjimharris*
1880230557Sjimharris*/
1881230557SjimharrisBOOL sati_device_state_stopped(
1882230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1883230557Sjimharris   void                       * scsi_io
1884230557Sjimharris)
1885230557Sjimharris{
1886230557Sjimharris   if(sequence->device->state == SATI_DEVICE_STATE_STOPPED)
1887230557Sjimharris   {
1888230557Sjimharris      sati_scsi_sense_data_construct(
1889230557Sjimharris         sequence,
1890230557Sjimharris         scsi_io,
1891230557Sjimharris         SCSI_STATUS_CHECK_CONDITION,
1892230557Sjimharris         SCSI_SENSE_NOT_READY ,
1893230557Sjimharris         SCSI_ASC_INITIALIZING_COMMAND_REQUIRED,
1894230557Sjimharris         SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED
1895230557Sjimharris      );
1896230557Sjimharris      return TRUE;
1897230557Sjimharris   }
1898230557Sjimharris   return FALSE;
1899230557Sjimharris}
1900230557Sjimharris
1901230557Sjimharris/**
1902230557Sjimharris* @brief This method will construct a ATA Read Buffer command that
1903230557Sjimharris*        will request PIO in data containing the target device's buffer.
1904230557Sjimharris*
1905230557Sjimharris* @param[out] ata_io This parameter specifies the ATA IO request structure
1906230557Sjimharris*             for which to build the ATA READ VERIFY SECTOR(S) command.
1907230557Sjimharris* @param[in]  sequence This parameter specifies the translator sequence
1908230557Sjimharris*             for which the command is being constructed.
1909230557Sjimharris* @return N/A
1910230557Sjimharris*
1911230557Sjimharris*/
1912230557Sjimharrisvoid sati_ata_read_buffer_construct(
1913230557Sjimharris   void                       * ata_io,
1914230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
1915230557Sjimharris)
1916230557Sjimharris{
1917230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1918230557Sjimharris
1919230557Sjimharris   sati_set_ata_command(register_fis, ATA_READ_BUFFER);
1920230557Sjimharris   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1921230557Sjimharris   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1922230557Sjimharris   sequence->ata_transfer_length = 512;
1923230557Sjimharris}
1924230557Sjimharris
1925230557Sjimharris
1926230557Sjimharris/**
1927230557Sjimharris* @brief This method will construct a ATA Write Buffer command that
1928230557Sjimharris*        will send PIO out data to the target device's buffer.
1929230557Sjimharris*
1930230557Sjimharris* @param[out] ata_io This parameter specifies the ATA IO request structure
1931230557Sjimharris*             for which to build the ATA READ VERIFY SECTOR(S) command.
1932230557Sjimharris* @param[in]  sequence This parameter specifies the translator sequence
1933230557Sjimharris*             for which the command is being constructed.
1934230557Sjimharris* @return N/A
1935230557Sjimharris*
1936230557Sjimharris*/
1937230557Sjimharrisvoid sati_ata_write_buffer_construct(
1938230557Sjimharris   void                       * ata_io,
1939230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence
1940230557Sjimharris)
1941230557Sjimharris{
1942230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1943230557Sjimharris
1944230557Sjimharris   sati_set_ata_command(register_fis, ATA_WRITE_BUFFER);
1945230557Sjimharris
1946230557Sjimharris   sequence->data_direction      = SATI_DATA_DIRECTION_OUT;
1947230557Sjimharris   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_OUT;
1948230557Sjimharris   sequence->ata_transfer_length = 512;
1949230557Sjimharris}
1950230557Sjimharris
1951230557Sjimharris
1952230557Sjimharris/**
1953230557Sjimharris* @brief This method will construct a ATA Download Microcode command that
1954230557Sjimharris*        will send PIO out data containing new firmware for the target drive.
1955230557Sjimharris*
1956230557Sjimharris* @param[out] ata_io This parameter specifies the ATA IO request structure
1957230557Sjimharris*             for which to build the ATA READ VERIFY SECTOR(S) command.
1958230557Sjimharris* @param[in]  sequence This parameter specifies the translator sequence
1959230557Sjimharris*             for which the command is being constructed.
1960230557Sjimharris* @param[in]  mode This parameter specifies the download microcode sub-command
1961230557Sjimharris*             code.
1962230557Sjimharris* @param[in]  allocation_length This parameter specifies the number of bytes
1963230557Sjimharris*             being sent to the target device.
1964230557Sjimharris* @param[in]  buffer_offset This parameter specifies the buffer offset for the
1965230557Sjimharris*             data sent to the target device.
1966230557Sjimharris*
1967230557Sjimharris* @return N/A
1968230557Sjimharris*
1969230557Sjimharris*/
1970230557Sjimharrisvoid sati_ata_download_microcode_construct(
1971230557Sjimharris   void                       * ata_io,
1972230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1973230557Sjimharris   U8                           mode,
1974230557Sjimharris   U32                          allocation_length,
1975230557Sjimharris   U32                          buffer_offset
1976230557Sjimharris)
1977230557Sjimharris{
1978230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1979240514Sjimharris   U32 allocation_blocks = allocation_length >> 9;
1980240514Sjimharris   U32 buffer_blkoffset = buffer_offset >> 9;
1981230557Sjimharris
1982230557Sjimharris   sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE);
1983230557Sjimharris   sati_set_ata_features(register_fis, mode);
1984230557Sjimharris
1985230557Sjimharris   if(mode == ATA_MICROCODE_DOWNLOAD_SAVE)
1986230557Sjimharris   {
1987230557Sjimharris      sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9));
1988230557Sjimharris      sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17));
1989230557Sjimharris   }
1990230557Sjimharris   else //mode == 0x03
1991230557Sjimharris   {
1992240514Sjimharris      sati_set_ata_sector_count(register_fis, (U8) (allocation_blocks & 0xff));
1993240514Sjimharris      sati_set_ata_lba_low(register_fis, (U8) ((allocation_blocks >> 8) & 0xff));
1994240514Sjimharris      sati_set_ata_lba_mid(register_fis, (U8) (buffer_blkoffset & 0xff));
1995240514Sjimharris      sati_set_ata_lba_high(register_fis, (U8) ((buffer_blkoffset >> 8) & 0xff));
1996230557Sjimharris   }
1997230557Sjimharris
1998230557Sjimharris   if((allocation_length == 0) && (buffer_offset == 0))
1999230557Sjimharris   {
2000230557Sjimharris      sati_ata_non_data_command(ata_io, sequence);
2001230557Sjimharris   }
2002230557Sjimharris   else
2003230557Sjimharris   {
2004230557Sjimharris      sequence->data_direction      = SATI_DATA_DIRECTION_OUT;
2005230557Sjimharris      sequence->protocol            = SAT_PROTOCOL_PIO_DATA_OUT;
2006230557Sjimharris      sequence->ata_transfer_length = allocation_length;
2007230557Sjimharris   }
2008230557Sjimharris}
2009