sati_util.c revision 302380
1275970Scy/*-
2275970Scy * This file is provided under a dual BSD/GPLv2 license.  When using or
3275970Scy * redistributing this file, you may do so under either license.
4275970Scy *
5275970Scy * GPL LICENSE SUMMARY
6275970Scy *
7275970Scy * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8275970Scy *
9275970Scy * This program is free software; you can redistribute it and/or modify
10275970Scy * it under the terms of version 2 of the GNU General Public License as
11285612Sdelphij * published by the Free Software Foundation.
12275970Scy *
13275970Scy * This program is distributed in the hope that it will be useful, but
14275970Scy * WITHOUT ANY WARRANTY; without even the implied warranty of
15275970Scy * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16275970Scy * General Public License for more details.
17275970Scy *
18275970Scy * You should have received a copy of the GNU General Public License
19275970Scy * along with this program; if not, write to the Free Software
20275970Scy * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21275970Scy * The full GNU General Public License is included in this distribution
22275970Scy * in the file called LICENSE.GPL.
23275970Scy *
24275970Scy * BSD LICENSE
25275970Scy *
26275970Scy * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27275970Scy * All rights reserved.
28275970Scy *
29275970Scy * Redistribution and use in source and binary forms, with or without
30275970Scy * modification, are permitted provided that the following conditions
31275970Scy * are met:
32275970Scy *
33275970Scy *   * Redistributions of source code must retain the above copyright
34275970Scy *     notice, this list of conditions and the following disclaimer.
35275970Scy *   * Redistributions in binary form must reproduce the above copyright
36275970Scy *     notice, this list of conditions and the following disclaimer in
37275970Scy *     the documentation and/or other materials provided with the
38275970Scy *     distribution.
39275970Scy *
40275970Scy * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41275970Scy * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42275970Scy * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43275970Scy * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44275970Scy * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45275970Scy * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46275970Scy * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50275970Scy * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51275970Scy */
52275970Scy
53275970Scy#include <sys/cdefs.h>
54275970Scy__FBSDID("$FreeBSD: head/sys/dev/isci/scil/sati_util.c 302380 2016-07-06 20:48:42Z jimharris $");
55275970Scy
56275970Scy/**
57275970Scy * @file
58275970Scy * @brief This file contains all of the method implementations that
59275970Scy *        provide generic support for SATI.  Some methods can be utilized
60275970Scy *        by a user to construct ATA/ATAPI commands, copy ATA device
61275970Scy *        structure data, fill in sense data, etc.
62275970Scy */
63275970Scy
64275970Scy#include <dev/isci/scil/sati_util.h>
65275970Scy#include <dev/isci/scil/sati_callbacks.h>
66275970Scy#include <dev/isci/scil/intel_scsi.h>
67275970Scy#include <dev/isci/scil/intel_ata.h>
68275970Scy#include <dev/isci/scil/intel_sat.h>
69275970Scy#include <dev/isci/scil/intel_sas.h>
70275970Scy
71275970Scy/**
72275970Scy * @brief This method will set the data direction, protocol, and transfer
73275970Scy *        kength for an ATA non-data command.
74275970Scy *
75275970Scy * @pre It is expected that the user will use this method for setting these
76275970Scy *      values in a non-data ATA command constuct.
77275970Scy *
78275970Scy * @param[out] ata_io This parameter specifies the ATA IO request structure
79275970Scy *             for which to build the IDENTIFY DEVICE command.
80275970Scy * @param[in]  sequence This parameter specifies the translator sequence
81275970Scy *             for which the command is being constructed.
82275970Scy *
83275970Scy * @return none.
84275970Scy */
85275970Scyvoid sati_ata_non_data_command(
86275970Scy   void                        * ata_io,
87275970Scy   SATI_TRANSLATOR_SEQUENCE_T  * sequence
88275970Scy)
89275970Scy{
90275970Scy   sequence->data_direction      = SATI_DATA_DIRECTION_NONE;
91275970Scy   sequence->protocol            = SAT_PROTOCOL_NON_DATA;
92275970Scy   sequence->ata_transfer_length = 0;
93275970Scy}
94275970Scy
95275970Scy/**
96275970Scy * @brief This method will construct the ATA identify device command.
97275970Scy *
98275970Scy * @pre It is expected that the user has properly set the current contents
99275970Scy *      of the register FIS to 0.
100275970Scy *
101275970Scy * @param[out] ata_io This parameter specifies the ATA IO request structure
102275970Scy *             for which to build the IDENTIFY DEVICE command.
103275970Scy * @param[in]  sequence This parameter specifies the translator sequence
104275970Scy *             for which the command is being constructed.
105275970Scy *
106275970Scy * @return none.
107275970Scy */
108275970Scyvoid sati_ata_identify_device_construct(
109275970Scy   void                       * ata_io,
110275970Scy   SATI_TRANSLATOR_SEQUENCE_T * sequence
111275970Scy)
112275970Scy{
113275970Scy   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
114275970Scy
115275970Scy   sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE);
116285612Sdelphij   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
117285612Sdelphij   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
118285612Sdelphij   sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T);
119285612Sdelphij}
120285612Sdelphij
121285612Sdelphij/**
122285612Sdelphij* @brief This method will construct the ATA Execute Device Diagnostic command.
123285612Sdelphij*
124285612Sdelphij* @param[out] ata_io This parameter specifies the ATA IO request structure
125285612Sdelphij*             for which to build the IDENTIFY DEVICE command.
126285612Sdelphij* @param[in]  sequence This parameter specifies the translator sequence
127285612Sdelphij*             for which the command is being constructed.
128285612Sdelphij*
129285612Sdelphij* @return none.
130285612Sdelphij*/
131285612Sdelphijvoid sati_ata_execute_device_diagnostic_construct(
132285612Sdelphij   void                       * ata_io,
133275970Scy   SATI_TRANSLATOR_SEQUENCE_T * sequence
134275970Scy)
135275970Scy{
136275970Scy   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
137275970Scy
138275970Scy   sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG);
139275970Scy
140275970Scy   sequence->data_direction = SATI_DATA_DIRECTION_IN;
141275970Scy   sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC;
142275970Scy   sequence->ata_transfer_length = 16;
143275970Scy}
144275970Scy
145285612Sdelphij/**
146285612Sdelphij * @brief This method will set data bytes in the user data area.  If the
147275970Scy *        caller requests it, the data written will be forced to ascii
148275970Scy *        printable characters if it isn't already a printable character.
149275970Scy *        A printable character is considered to be >= 0x20 and <= 0x70.
150275970Scy *
151275970Scy * @param[in]  sequence This parameter specifies the translation sequence
152275970Scy *             for which to copy and swap the data.
153275970Scy * @param[out] destination_scsi_io This parameter specifies the SCSI IO
154275970Scy *             request containing the destination buffer into which to copy.
155275970Scy * @param[in]  destination_offset This parameter specifies the offset into
156275970Scy *             the data buffer where the information will be copied to.
157275970Scy * @param[in]  source_value This parameter specifies the value retrieved
158275970Scy *             from the source buffer that is to be copied into the user
159285612Sdelphij *             buffer area.
160275970Scy * @param[in]  use_printable_chars This parameter indicates if the copy should
161275970Scy *             ensure that the value copied is considered an ASCII printable
162275970Scy *             character (e.g. A, B, " ", etc.).  These characters reside
163275970Scy *             in the 0x20 - 0x7E ASCII range.
164275970Scy *
165275970Scy * @return none
166275970Scy */
167275970Scystatic
168275970Scyvoid sati_set_ascii_data_byte(
169275970Scy   SATI_TRANSLATOR_SEQUENCE_T * sequence,
170275970Scy   void                       * destination_scsi_io,
171275970Scy   U32                          destination_offset,
172275970Scy   U8                           source_value,
173275970Scy   BOOL                         use_printable_chars
174275970Scy)
175275970Scy{
176275970Scy   // if the user requests that the copied data be ascii printable, then
177275970Scy   // default to " " (i.e. 0x20) for all non-ascii printable characters.
178275970Scy   if((use_printable_chars == TRUE)
179275970Scy     && ((source_value < 0x20) || (source_value > 0x7E)))
180275970Scy   {
181275970Scy      source_value = 0x20;
182275970Scy   }
183275970Scy
184275970Scy   sati_set_data_byte(
185275970Scy      sequence, destination_scsi_io, destination_offset, source_value
186275970Scy   );
187275970Scy}
188275970Scy
189275970Scy/**
190275970Scy * @brief This method performs a copy operation using an offset into the
191275970Scy *        source buffer, an offset into the destination buffer, and a length.
192275970Scy *        It will perform the byte swap from the 16-bit identify field
193275970Scy *        into the network byte order SCSI location.
194275970Scy *
195275970Scy * @param[in]  sequence This parameter specifies the translation sequence
196275970Scy *             for which to copy and swap the data.
197275970Scy * @param[out] destination_scsi_io This parameter specifies the SCSI IO
198275970Scy *             request containing the destination buffer into which to copy.
199275970Scy * @param[in]  destination_offset This parameter specifies the offset into
200275970Scy *             the data buffer where the information will be copied to.
201275970Scy * @param[in]  source_buffer This parameter specifies the source buffer from
202275970Scy *             which the data will be copied.
203275970Scy * @param[in]  source_offset This parameter specifies the offset into the
204275970Scy *             source buffer where the copy shall begin.
205275970Scy * @param[in]  length This parameter specifies the number of bytes to copy
206275970Scy *             during this operation.
207275970Scy * @param[in]  use_printable_chars This parameter indicates if the copy should
208275970Scy *             ensure that the value copied is considered an ASCII printable
209275970Scy *             character (e.g. A, B, " ", etc.).  These characters reside
210275970Scy *             in the 0x20 - 0x7E ASCII range.
211275970Scy *
212275970Scy * @return none
213275970Scy */
214275970Scyvoid sati_ata_identify_device_copy_data(
215275970Scy   SATI_TRANSLATOR_SEQUENCE_T * sequence,
216275970Scy   void                       * destination_scsi_io,
217275970Scy   U32                          destination_offset,
218275970Scy   U8                         * source_buffer,
219275970Scy   U32                          source_offset,
220275970Scy   U32                          length,
221275970Scy   BOOL                         use_printable_chars
222275970Scy)
223275970Scy{
224275970Scy   source_buffer += source_offset;
225275970Scy   while (length > 0)
226275970Scy   {
227275970Scy      sati_set_ascii_data_byte(
228275970Scy         sequence,
229285612Sdelphij         destination_scsi_io,
230285612Sdelphij         destination_offset,
231275970Scy         *(source_buffer+1),
232275970Scy         use_printable_chars
233275970Scy      );
234275970Scy
235275970Scy      sati_set_ascii_data_byte(
236275970Scy         sequence,
237275970Scy         destination_scsi_io,
238275970Scy         destination_offset+1,
239275970Scy         *source_buffer,
240275970Scy         use_printable_chars
241275970Scy      );
242275970Scy
243275970Scy      destination_offset += 2;
244275970Scy      source_buffer      += 2;
245275970Scy      length             -= 2;
246275970Scy   }
247275970Scy}
248275970Scy
249275970Scy/**
250275970Scy * @brief This method performs a copy operation using a source buffer,
251275970Scy *        an offset into the destination buffer, and a length.
252275970Scy *
253275970Scy * @param[in]  sequence This parameter specifies the translation sequence
254275970Scy *             for which to copy and swap the data.
255275970Scy * @param[out] destination_scsi_io This parameter specifies the SCSI IO
256275970Scy *             request containing the destination buffer into which to copy.
257275970Scy * @param[in]  destination_offset This parameter specifies the offset into
258275970Scy *             the data buffer where the information will be copied to.
259275970Scy * @param[in]  source_buffer This parameter specifies the source buffer from
260275970Scy *             which the data will be copied.
261275970Scy * @param[in]  length This parameter specifies the number of bytes to copy
262275970Scy *             during this operation.
263275970Scy *
264275970Scy * @return none
265275970Scy */
266275970Scyvoid sati_copy_data(
267275970Scy   SATI_TRANSLATOR_SEQUENCE_T * sequence,
268275970Scy   void                       * destination_scsi_io,
269275970Scy   U32                          destination_offset,
270275970Scy   U8                         * source_buffer,
271275970Scy   U32                          length
272275970Scy)
273275970Scy{
274275970Scy   while (length > 0)
275275970Scy   {
276275970Scy      sati_set_data_byte(
277275970Scy         sequence, destination_scsi_io, destination_offset, *source_buffer
278275970Scy      );
279275970Scy
280275970Scy      destination_offset++;
281275970Scy      source_buffer++;
282275970Scy      length--;
283275970Scy   }
284275970Scy}
285275970Scy
286275970Scy/**
287275970Scy * @brief This method extracts the Logical Block Address high and low 32-bit
288275970Scy *        values and the sector count 32-bit value from the ATA identify
289275970Scy *        device data.
290275970Scy *
291275970Scy * @param[in]  identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA
292275970Scy *             from which to extract the sector information.
293275970Scy * @param[out] lba_high This parameter specifies the upper 32 bits for the
294275970Scy *             number of logical block addresses for the device. The upper
295275970Scy *             16-bits should always be 0, since 48-bits of LBA is the most
296275970Scy *             supported by an ATA device.
297275970Scy * @param[out] lba_low This parameter specifies the lower 32 bits for the
298275970Scy *             number of logical block addresses for the device.
299275970Scy * @param[out] sector_size This parameter specifies the 32-bits of sector
300275970Scy *             size.  If the ATA device doesn't support reporting it's
301275970Scy *             sector size, then 512 bytes is utilized as the default value.
302275970Scy *
303275970Scy * @return none
304275970Scy */
305275970Scyvoid sati_ata_identify_device_get_sector_info(
306275970Scy   ATA_IDENTIFY_DEVICE_DATA_T * identify,
307275970Scy   U32                        * lba_high,
308275970Scy   U32                        * lba_low,
309275970Scy   U32                        * sector_size
310275970Scy)
311275970Scy{
312275970Scy   // Calculate the values to be returned
313275970Scy   // Calculation will be different if the SATA device supports
314275970Scy   // 48-bit addressing.  Bit 10 of Word 86 of ATA Identify
315275970Scy   if (identify->command_set_enabled1
316275970Scy       & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE)
317275970Scy   {
318275970Scy      // This drive supports 48-bit addressing
319275970Scy
320275970Scy      *lba_high  = identify->max_48bit_lba[7] << 24;
321275970Scy      *lba_high |= identify->max_48bit_lba[6] << 16;
322275970Scy      *lba_high |= identify->max_48bit_lba[5] << 8;
323275970Scy      *lba_high |= identify->max_48bit_lba[4];
324275970Scy
325275970Scy      *lba_low  = identify->max_48bit_lba[3] << 24;
326275970Scy      *lba_low |= identify->max_48bit_lba[2] << 16;
327275970Scy      *lba_low |= identify->max_48bit_lba[1] << 8;
328275970Scy      *lba_low |= identify->max_48bit_lba[0];
329275970Scy   }
330275970Scy   else
331275970Scy   {
332275970Scy      // This device doesn't support 48-bit addressing
333275970Scy      // Pull out the largest LBA from words 60 and 61.
334275970Scy      *lba_high  = 0;
335275970Scy      *lba_low   = identify->total_num_sectors[3] << 24;
336275970Scy      *lba_low  |= identify->total_num_sectors[2] << 16;
337275970Scy      *lba_low  |= identify->total_num_sectors[1] << 8;
338275970Scy      *lba_low  |= identify->total_num_sectors[0];
339275970Scy   }
340275970Scy
341275970Scy   // If the ATA device reports its sector size (bit 12 of Word 106),
342275970Scy   // then use that instead.
343275970Scy   if (identify->physical_logical_sector_info
344275970Scy       & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE)
345275970Scy   {
346275970Scy      *sector_size  = identify->words_per_logical_sector[3] << 24;
347275970Scy      *sector_size |= identify->words_per_logical_sector[2] << 16;
348275970Scy      *sector_size |= identify->words_per_logical_sector[1] << 8;
349275970Scy      *sector_size |= identify->words_per_logical_sector[0];
350275970Scy   }
351275970Scy   else
352275970Scy   {
353275970Scy      // Default the sector size to 512 bytes
354275970Scy      *sector_size = 512;
355275970Scy   }
356275970Scy}
357275970Scy
358275970Scy/**
359275970Scy * @brief This method will construct the ATA check power mode command.
360275970Scy *
361275970Scy * @pre It is expected that the user has properly set the current contents
362275970Scy *      of the register FIS to 0.
363275970Scy *
364275970Scy * @param[out] ata_io This parameter specifies the ATA IO request structure
365275970Scy *             for which to build the CHECK POWER MODE command.
366275970Scy * @param[in]  sequence This parameter specifies the translator sequence
367275970Scy *             for which the command is being constructed.
368275970Scy *
369275970Scy * @return none.
370275970Scy */
371275970Scyvoid sati_ata_check_power_mode_construct(
372275970Scy   void                       * ata_io,
373275970Scy   SATI_TRANSLATOR_SEQUENCE_T * sequence
374275970Scy)
375275970Scy{
376275970Scy   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
377275970Scy
378275970Scy   sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE);
379275970Scy   sati_ata_non_data_command(ata_io, sequence);
380275970Scy}
381275970Scy
382275970Scy/**
383275970Scy * @brief This method is utilized to set a specific byte in the sense
384275970Scy *        data area.  It will ensure that the supplied byte offset
385275970Scy *        isn't larger then the length of the requested sense data.
386275970Scy *
387275970Scy * @param[in] scsi_io This parameter specifies the user SCSI IO request
388275970Scy *            for which to set the sense data byte.
389275970Scy * @param[in] byte_offset This parameter specifies the byte offset into
390275970Scy *            the sense data buffer where the data should be written.
391275970Scy * @param[in] value This parameter specifies the 8-bit value to be written
392275970Scy *            into the sense data area.
393275970Scy *
394275970Scy * @return none
395275970Scy */
396275970Scyvoid sati_set_sense_data_byte(
397275970Scy   U8  * sense_data,
398275970Scy   U32   max_sense_data_len,
399275970Scy   U32   byte_offset,
400275970Scy   U8    value
401275970Scy)
402275970Scy{
403275970Scy   // Ensure that we don't attempt to write past the end of the sense
404285612Sdelphij   // data buffer.
405275970Scy   if (byte_offset < max_sense_data_len)
406275970Scy      sense_data[byte_offset] = value;
407275970Scy}
408275970Scy
409275970Scy/**
410275970Scy * @brief This method will construct the common response IU in the user
411275970Scy *           request's response IU location.
412275970Scy *
413275970Scy * @param[out] rsp_iu This parameter specifies the user request's
414275970Scy *                response IU to be constructed.
415275970Scy * @param[in]  scsi_status This parameter specifies the SCSI status
416275970Scy *                value for the user's IO request.
417275970Scy * @param[in]  sense_data_length This parameter specifies the sense data
418275970Scy *                length for response IU.
419275970Scy * @param[in]  data_present The parameter specifies the specific
420275970Scy *                data present value for response IU.
421275970Scy *
422275970Scy * @return none
423275970Scy */
424275970Scyvoid sati_scsi_common_response_iu_construct(
425275970Scy   SCI_SSP_RESPONSE_IU_T * rsp_iu,
426275970Scy   U8                      scsi_status,
427275970Scy   U8                      sense_data_length,
428275970Scy   U8                      data_present
429275970Scy)
430275970Scy{
431275970Scy   rsp_iu->sense_data_length[3] = sense_data_length;
432275970Scy   rsp_iu->sense_data_length[2] = 0;
433275970Scy   rsp_iu->sense_data_length[1] = 0;
434275970Scy   rsp_iu->sense_data_length[0] = 0;
435275970Scy   rsp_iu->status               = scsi_status;
436275970Scy   rsp_iu->data_present         = data_present;
437275970Scy}
438275970Scy
439275970Scy/**
440275970Scy * @brief This method will construct the buffer for sense data
441275970Scy *        sense data buffer location.  Additionally, it will set the user's
442275970Scy *        SCSI status.
443275970Scy *
444275970Scy * @param[in,out] scsi_io This parameter specifies the user's IO request
445275970Scy *                for which to construct the buffer for sense data.
446275970Scy * @param[in]     scsi_status This parameter specifies the SCSI status
447275970Scy *                value for the user's IO request.
448275970Scy * @param[out]    sense_data This paramater
449275970Scy *
450275970Scy * @return none
451275970Scy */
452275970Scystatic
453275970Scyvoid sati_scsi_get_sense_data_buffer(
454275970Scy    SATI_TRANSLATOR_SEQUENCE_T      * sequence,
455275970Scy    void                            * scsi_io,
456275970Scy    U8                                scsi_status,
457275970Scy    U8                             ** sense_data,
458275970Scy    U32                             * sense_len)
459275970Scy{
460275970Scy#ifdef SATI_TRANSPORT_SUPPORTS_SAS
461275970Scy   SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
462275970Scy                                    sati_cb_get_response_iu_address(scsi_io);
463275970Scy
464275970Scy   sati_scsi_common_response_iu_construct(
465275970Scy      rsp_iu,
466275970Scy      scsi_status,
467275970Scy      sati_scsi_get_sense_data_length(sequence, scsi_io),
468275970Scy      SCSI_RESPONSE_DATA_PRES_SENSE_DATA
469275970Scy   );
470275970Scy
471275970Scy   *sense_data                   = (U8*) rsp_iu->data;
472275970Scy   *sense_len                    = SSP_RESPONSE_IU_MAX_DATA * 4;  // dwords to bytes
473275970Scy#else
474275970Scy   *sense_data = sati_cb_get_sense_data_address(scsi_io);
475275970Scy   *sense_len  = sati_cb_get_sense_data_length(scsi_io);
476275970Scy   sati_cb_set_scsi_status(scsi_io, scsi_status);
477275970Scy#endif // SATI_TRANSPORT_SUPPORTS_SAS
478275970Scy}
479275970Scy
480275970Scy/**
481275970Scy * @brief This method extract response code based on on device settings.
482275970Scy *
483275970Scy * @return response code
484275970Scy */
485275970Scystatic
486275970ScyU8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence)
487275970Scy{
488275970Scy    if (sequence->device->descriptor_sense_enable)
489275970Scy    {
490275970Scy       return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE;
491275970Scy    }
492275970Scy    else
493275970Scy    {
494275970Scy       return SCSI_FIXED_CURRENT_RESPONSE_CODE;
495275970Scy    }
496275970Scy}
497275970Scy
498275970Scy/**
499275970Scy * @brief This method will return length of descriptor sense data for executed command.
500275970Scy *
501275970Scy * @return sense data length
502275970Scy */
503275970Scystatic
504275970ScyU8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence,
505275970Scy        void * scsi_io)
506275970Scy{
507275970Scy    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
508275970Scy    //Initial value is descriptor header length
509275970Scy    U8 length = 8;
510275970Scy
511275970Scy    switch (sati_get_cdb_byte(cdb, 0))
512275970Scy    {
513275970Scy#if !defined(DISABLE_SATI_WRITE_LONG)
514275970Scy    case SCSI_WRITE_LONG_10:
515275970Scy    case SCSI_WRITE_LONG_16:
516275970Scy        length += SCSI_BLOCK_DESCRIPTOR_LENGTH +
517275970Scy            SCSI_INFORMATION_DESCRIPTOR_LENGTH;
518275970Scy        break;
519275970Scy#endif // !defined(DISABLE_SATI_WRITE_LONG)
520275970Scy#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
521275970Scy    case SCSI_REASSIGN_BLOCKS:
522275970Scy        length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH +
523275970Scy            SCSI_INFORMATION_DESCRIPTOR_LENGTH;
524275970Scy        break;
525275970Scy#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
526275970Scy    case SCSI_READ_6:
527275970Scy    case SCSI_READ_10:
528275970Scy    case SCSI_READ_12:
529275970Scy    case SCSI_READ_16:
530275970Scy    case SCSI_WRITE_6:
531275970Scy    case SCSI_WRITE_10:
532275970Scy    case SCSI_WRITE_12:
533275970Scy    case SCSI_WRITE_16:
534275970Scy#if !defined(DISABLE_SATI_VERIFY)
535275970Scy    case SCSI_VERIFY_10:
536275970Scy    case SCSI_VERIFY_12:
537275970Scy    case SCSI_VERIFY_16:
538275970Scy#endif // !defined(DISABLE_SATI_VERIFY)
539275970Scy#if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
540275970Scy    && !defined(DISABLE_SATI_VERIFY)            \
541275970Scy    && !defined(DISABLE_SATI_WRITE)
542275970Scy
543275970Scy    case SCSI_WRITE_AND_VERIFY_10:
544275970Scy    case SCSI_WRITE_AND_VERIFY_12:
545275970Scy    case SCSI_WRITE_AND_VERIFY_16:
546#endif //    !defined(DISABLE_SATI_WRITE_AND_VERIFY)
547       // && !defined(DISABLE_SATI_VERIFY)
548       // && !defined(DISABLE_SATI_WRITE)
549        length += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
550        break;
551    }
552
553    return length;
554}
555
556/**
557 * @brief This method will return length of sense data.
558 *
559 * @return sense data length
560 */
561U8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io)
562{
563    U8 response_code;
564
565    response_code = sati_scsi_get_sense_data_response_code(sequence);
566
567    switch (response_code)
568    {
569    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
570    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
571        return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
572    break;
573    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
574    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
575        return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io);
576    break;
577    }
578
579    return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
580}
581
582/**
583 * @brief This method will construct the sense data buffer in the user's
584 *        sense data buffer location.  Additionally, it will set the user's
585 *        SCSI status.
586 *
587 * @param[in]     sequence This parameter specifies the translation sequence
588 *                for which to construct the sense data.
589 * @param[in,out] scsi_io This parameter specifies the user's IO request
590 *                for which to construct the sense data.
591 * @param[in]     scsi_status This parameter specifies the SCSI status
592 *                value for the user's IO request.
593 * @param[in]     sense_key This parameter specifies the sense key to
594 *                be set for the user's IO request.
595 * @param[in]     additional_sense_code This parameter specifies the
596 *                additional sense code (ASC) key to be set for the user's
597 *                IO request.
598 * @param[in]     additional_sense_code_qualifier This parameter specifies
599 *                the additional sense code qualifier (ASCQ) key to be set
600 *                for the user's IO request.
601 *
602 * @return none
603 */
604void sati_scsi_sense_data_construct(
605   SATI_TRANSLATOR_SEQUENCE_T * sequence,
606   void                       * scsi_io,
607   U8                           scsi_status,
608   U8                           sense_key,
609   U8                           additional_sense_code,
610   U8                           additional_sense_code_qualifier
611)
612{
613    U8 response_code;
614
615    response_code = sati_scsi_get_sense_data_response_code(sequence);
616
617    switch (response_code)
618    {
619    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
620    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
621    sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
622                sense_key, additional_sense_code, additional_sense_code_qualifier);
623    break;
624    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
625    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
626        sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
627                sense_key, additional_sense_code, additional_sense_code_qualifier);
628        break;
629    }
630
631    sequence->is_sense_response_set = TRUE;
632}
633
634/**
635 * @brief This method will construct the block descriptor in the user's descriptor
636 *            sense data buffer location.
637 *
638 * @param[in]     sense_data This parameter specifies the user SCSI IO request
639 *                for which to set the sense data byte.
640 * @param[in]     sense_len This parameter specifies length of the sense data
641 *                to be returned by SATI.
642 * @param[out]    descriptor_len This parameter returns the length of constructed
643 *                descriptor.
644 *
645 * @return none
646 */
647static
648void sati_scsi_block_descriptor_construct(
649        U8 * sense_data,
650        U32 sense_len)
651{
652    U8 ili = 1;
653
654    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_BLOCK_DESCRIPTOR_TYPE);
655    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH);
656    sati_set_sense_data_byte(sense_data, sense_len, 2,  0);
657    sati_set_sense_data_byte(sense_data, sense_len, 3,  (ili << 5));
658}
659
660/**
661 * @brief This method will construct the command-specific descriptor for
662 *           the descriptor sense data buffer in the user's sense data buffer
663 *           location.
664 *
665 * @param[in]     sense_data This parameter specifies the user SCSI IO request
666 *                for which to set the sense data byte.
667 * @param[in]     sense_len This parameter specifies length of the sense data
668 *                to be returned by SATI.
669 * @param[out]    descriptor_len This parameter returns the length of constructed
670 *                descriptor.
671 * @param[in]     information_buff This parameter specifies the address for which
672 *                to set the command-specific information buffer.
673 *
674 * @return none
675 */
676static
677void sati_scsi_command_specific_descriptor_construct(
678    U8       * sense_data,
679    U32        sense_len,
680    U8       * information_buff)
681{
682    U8 i;
683
684    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE);
685    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH);
686    sati_set_sense_data_byte(sense_data, sense_len, 2,  0);
687    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
688
689    // fill information buffer
690    // SBC 5.20.1 REASSIGN BLOCKS command overview
691    // If information about the first LBA not reassigned is not available
692    // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh
693    for (i=0; i<8; i++)
694        sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]);
695}
696
697/**
698 * @brief This method will construct the information descriptor for
699 *           the descriptor sense data buffer in the user's sense data buffer
700 *           location.
701 *
702 * @param[in]     sense_data This parameter specifies the user SCSI IO request
703 *                for which to set the sense data byte.
704 * @param[in]     sense_len This parameter specifies length of the sense data
705 *                to be returned by SATI.
706 * @param[out]    descriptor_len This parameter returns the length of constructed
707 *                descriptor.
708 * @param[in]     information_buff This parameter specifies the address for which
709 *                to set the information buffer.
710 *
711 * @return none
712 */
713static
714void sati_scsi_information_descriptor_construct(
715    U8      * sense_data,
716    U32       sense_len,
717    U8      * information_buff)
718{
719    U8 i;
720    U8 valid = 1;
721
722    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_INFORMATION_DESCRIPTOR_TYPE);
723    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH);
724    sati_set_sense_data_byte(sense_data, sense_len, 2,  (valid << 7));
725    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
726
727    // fill information buffer
728    for (i=0; i<8; i++)
729        sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]);
730}
731
732/**
733 * @brief This method will construct the descriptors in the user's descriptor
734 *           sense data buffer location.
735 *
736 * @param[in,out] scsi_io This parameter specifies the user's IO request
737 *                for which to construct the sense data.
738 * @param[in]     sense_data This parameter specifies the user SCSI IO request
739 *                for which to set the sense data byte.
740 * @param[in]     sense_len This parameter specifies length of the sense data
741 *                to be returned by SATI.
742 * @param[out]    descriptor_len This parameter returns the length of constructed
743 *                descriptor.
744 * @param[in]     information_buff This parameter specifies the address for which
745 *                to set the information buffer.
746 *
747 * @return none
748 */
749static
750void sati_scsi_common_descriptors_construct(
751    void    * scsi_io,
752    U8      * sense_data,
753    U32       sense_len,
754    U8      * information_buff)
755{
756    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
757    U8 offset = 0;
758
759    switch (sati_get_cdb_byte(cdb, 0))
760    {
761#if !defined(DISABLE_SATI_WRITE_LONG)
762    case SCSI_WRITE_LONG_10:
763    case SCSI_WRITE_LONG_16:
764        sati_scsi_block_descriptor_construct(
765                sense_data + offset,
766                sense_len - offset);
767
768        offset += SCSI_BLOCK_DESCRIPTOR_LENGTH;
769        sati_scsi_information_descriptor_construct(
770                  sense_data + offset,
771                  sense_len - offset,
772                  information_buff);
773
774        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
775        break;
776#endif // !defined(DISABLE_SATI_WRITE_LONG)
777#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
778    case SCSI_REASSIGN_BLOCKS:
779        sati_scsi_command_specific_descriptor_construct(
780          sense_data + offset,
781          sense_len - offset,
782          NULL);
783
784        offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH;
785        sati_scsi_information_descriptor_construct(
786                  sense_data + offset,
787                  sense_len - offset,
788                  information_buff);
789
790        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
791        break;
792#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
793    case SCSI_READ_6:
794    case SCSI_READ_10:
795    case SCSI_READ_12:
796    case SCSI_READ_16:
797    case SCSI_WRITE_6:
798    case SCSI_WRITE_10:
799    case SCSI_WRITE_12:
800    case SCSI_WRITE_16:
801#if !defined(DISABLE_SATI_VERIFY)
802    case SCSI_VERIFY_10:
803    case SCSI_VERIFY_12:
804    case SCSI_VERIFY_16:
805#endif // !defined(DISABLE_SATI_VERIFY)
806#if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
807    && !defined(DISABLE_SATI_VERIFY)            \
808    && !defined(DISABLE_SATI_WRITE)
809
810    case SCSI_WRITE_AND_VERIFY_10:
811    case SCSI_WRITE_AND_VERIFY_12:
812    case SCSI_WRITE_AND_VERIFY_16:
813#endif //    !defined(DISABLE_SATI_WRITE_AND_VERIFY)
814       // && !defined(DISABLE_SATI_VERIFY)
815       // && !defined(DISABLE_SATI_WRITE)
816        sati_scsi_information_descriptor_construct(
817                  sense_data + offset,
818                  sense_len - offset,
819                  information_buff);
820
821        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
822        break;
823    }
824}
825
826/**
827 * @brief This method will construct the descriptor sense data buffer in
828 *           the user's sense data buffer location.  Additionally, it will set
829 *           the user's SCSI status.
830 *
831 * @param[in]     sequence This parameter specifies the translation sequence
832 *                for which to construct the sense data.
833 * @param[in,out] scsi_io This parameter specifies the user's IO request
834 *                for which to construct the sense data.
835 * @param[in]     scsi_status This parameter specifies the SCSI status
836 *                value for the user's IO request.
837 * @param[in]     sense_key This parameter specifies the sense key to
838 *                be set for the user's IO request.
839 * @param[in]     additional_sense_code This parameter specifies the
840 *                additional sense code (ASC) key to be set for the user's
841 *                IO request.
842 * @param[in]     additional_sense_code_qualifier This parameter specifies
843 *                the additional sense code qualifier (ASCQ) key to be set
844 *                for the user's IO request.
845 *
846 * @return none
847 */
848void sati_scsi_descriptor_sense_data_construct(
849   SATI_TRANSLATOR_SEQUENCE_T * sequence,
850   void                       * scsi_io,
851   U8                           scsi_status,
852   U8                           response_code,
853   U8                           sense_key,
854   U8                           additional_sense_code,
855   U8                           additional_sense_code_qualifier
856)
857{
858   U8 * sense_data;
859   U32    sense_len;
860
861   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
862
863   sati_set_sense_data_byte(
864      sense_data,
865      sense_len,
866      0,
867      response_code
868   );
869
870   sati_set_sense_data_byte(sense_data, sense_len, 1,  sense_key);
871   sati_set_sense_data_byte(sense_data, sense_len, 2,  additional_sense_code);
872   sati_set_sense_data_byte(sense_data, sense_len, 3,  additional_sense_code_qualifier);
873   sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
874   sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
875   sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
876
877   sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL);
878
879   sati_set_sense_data_byte(sense_data, sense_len, 7,  sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
880}
881
882/**
883 * @brief This method will construct the fixed format sense data buffer
884 *           in the user's sense data buffer location.  Additionally, it will
885 *          set the user's SCSI status.
886 *
887 * @param[in]     sequence This parameter specifies the translation sequence
888 *                for which to construct the sense data.
889 * @param[in,out] scsi_io This parameter specifies the user's IO request
890 *                for which to construct the sense data.
891 * @param[in]     scsi_status This parameter specifies the SCSI status
892 *                value for the user's IO request.
893 * @param[in]     sense_key This parameter specifies the sense key to
894 *                be set for the user's IO request.
895 * @param[in]     additional_sense_code This parameter specifies the
896 *                additional sense code (ASC) key to be set for the user's
897 *                IO request.
898 * @param[in]     additional_sense_code_qualifier This parameter specifies
899 *                the additional sense code qualifier (ASCQ) key to be set
900 *                for the user's IO request.
901 *
902 * @return none
903 */
904void sati_scsi_fixed_sense_data_construct(
905   SATI_TRANSLATOR_SEQUENCE_T * sequence,
906   void                       * scsi_io,
907   U8                           scsi_status,
908   U8                           response_code,
909   U8                           sense_key,
910   U8                           additional_sense_code,
911   U8                           additional_sense_code_qualifier
912)
913{
914    U8 * sense_data;
915    U32  sense_len;
916
917    sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
918
919    // Write out the sense data format per SPC-4.
920    // We utilize the fixed format sense data format.
921
922    sati_set_sense_data_byte(
923      sense_data,
924      sense_len,
925      0,
926      response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT
927    );
928
929    sati_set_sense_data_byte(sense_data, sense_len, 1,  0);
930    sati_set_sense_data_byte(sense_data, sense_len, 2,  sense_key);
931    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
932    sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
933    sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
934    sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
935    sati_set_sense_data_byte(sense_data, sense_len, 7,  (sense_len < 18 ? sense_len - 1 : 17) - 7);
936    sati_set_sense_data_byte(sense_data, sense_len, 8,  0);
937    sati_set_sense_data_byte(sense_data, sense_len, 9,  0);
938    sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
939    sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
940    sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
941    sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
942    sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
943    sati_set_sense_data_byte(sense_data, sense_len, 15, 0);
944    sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
945    sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
946}
947
948/**
949* @brief This method will construct common sense data that will be identical in
950*        both read error sense construct functions.
951*        sati_scsi_read_ncq_error_sense_construct,
952*        sati_scsi_read_error_sense_construct
953*
954 * @param[in]    sense_data This parameter specifies the user SCSI IO request
955 *               for which to set the sense data byte.
956* @param[in]     sense_len This parameter specifies length of the sense data
957*                to be returned by SATI.
958* @param[in]     sense_key This parameter specifies the sense key to
959*                be set for the user's IO request.
960* @param[in]     additional_sense_code This parameter specifies the
961*                additional sense code (ASC) key to be set for the user's
962*                IO request.
963* @param[in]     additional_sense_code_qualifier This parameter specifies
964*                the additional sense code qualifier (ASCQ) key to be set
965*                for the user's IO request.
966*
967* @return none
968*/
969static
970void sati_scsi_common_fixed_sense_construct(
971   U8                         * sense_data,
972   U32                          sense_len,
973   U8                           sense_key,
974   U8                           additional_sense_code,
975   U8                           additional_sense_code_qualifier
976)
977{
978
979   sati_set_sense_data_byte(sense_data, sense_len, 1,  0);
980   sati_set_sense_data_byte(sense_data, sense_len, 2,  sense_key);
981
982   //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions
983
984   sati_set_sense_data_byte(sense_data, sense_len, 7,  (sense_len < 18 ? sense_len - 1 : 17) - 7);
985   sati_set_sense_data_byte(sense_data, sense_len, 8,  0);
986   sati_set_sense_data_byte(sense_data, sense_len, 9,  0);
987   sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
988   sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
989   sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
990   sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
991   sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
992   sati_set_sense_data_byte(sense_data, sense_len, 15, 0x80);
993   sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
994   sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
995}
996
997/**
998 * @brief This method will construct the descriptor sense data buffer in
999 *           the user's sense data buffer location.  Additionally, it will set
1000 *           the user's SCSI status.
1001 *
1002 * @param[in]     sequence This parameter specifies the translation sequence
1003 *                for which to construct the sense data.
1004 * @param[in,out] scsi_io This parameter specifies the user's IO request
1005 *                for which to construct the sense data.
1006 * @param[in]     scsi_status This parameter specifies the SCSI status
1007 *                value for the user's IO request.
1008 * @param[in]     sense_key This parameter specifies the sense key to
1009 *                be set for the user's IO request.
1010 * @param[in]     additional_sense_code This parameter specifies the
1011 *                additional sense code (ASC) key to be set for the user's
1012 *                IO request.
1013 * @param[in]     additional_sense_code_qualifier This parameter specifies
1014 *                the additional sense code qualifier (ASCQ) key to be set
1015 *                for the user's IO request.
1016 *
1017 * @return none
1018 */
1019static
1020void sati_scsi_common_descriptor_sense_construct(
1021    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1022    void                       * scsi_io,
1023    U8                         * sense_data,
1024    U32                          sense_len,
1025    U8                           sense_key,
1026    U8                           additional_sense_code,
1027    U8                           additional_sense_code_qualifier,
1028    U8                         * information_buff
1029)
1030{
1031    sati_set_sense_data_byte(sense_data, sense_len, 1,  sense_key);
1032    sati_set_sense_data_byte(sense_data, sense_len, 2,  additional_sense_code);
1033    sati_set_sense_data_byte(sense_data, sense_len, 3,  additional_sense_code_qualifier);
1034    sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
1035    sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
1036    sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
1037
1038    sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff);
1039
1040    sati_set_sense_data_byte(sense_data, sense_len, 7,  sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
1041}
1042
1043/**
1044* @brief This method will construct the sense data buffer in the user's
1045*        descriptor sense data buffer location.  Additionally, it will set
1046*        the user's SCSI status. This is only used for NCQ uncorrectable
1047*        read errors
1048*
1049* @param[in]     sequence This parameter specifies the translation sequence
1050*                for which to construct the sense data.
1051* @param[in,out] scsi_io This parameter specifies the user's IO request
1052*                for which to construct the sense data.
1053* @param[in]     ata_input_data This parameter specifies the user's ATA IO
1054*                response from a Read Log Ext command.
1055* @param[in]     scsi_status This parameter specifies the SCSI status
1056*                value for the user's IO request.
1057* @param[in]     sense_key This parameter specifies the sense key to
1058*                be set for the user's IO request.
1059* @param[in]     additional_sense_code This parameter specifies the
1060*                additional sense code (ASC) key to be set for the user's
1061*                IO request.
1062* @param[in]     additional_sense_code_qualifier This parameter specifies
1063*                the additional sense code qualifier (ASCQ) key to be set
1064*                for the user's IO request.
1065*
1066* @return none
1067*/
1068static
1069void sati_scsi_read_ncq_error_descriptor_sense_construct(
1070   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1071   void                       * scsi_io,
1072   void                       * ata_input_data,
1073   U8                           scsi_status,
1074   U8                           response_code,
1075   U8                           sense_key,
1076   U8                           additional_sense_code,
1077   U8                           additional_sense_code_qualifier
1078)
1079{
1080   U8 * sense_data;
1081   U32  sense_len;
1082
1083   U8 information_buff[8] = {0};
1084
1085   ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
1086
1087   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1088
1089   sati_set_sense_data_byte(
1090      sense_data,
1091      sense_len,
1092      0,
1093      response_code
1094   );
1095
1096   information_buff[2] = ncq_log->lba_47_40;
1097   information_buff[3] = ncq_log->lba_39_32;
1098   information_buff[4] = ncq_log->lba_31_24;
1099   information_buff[5] = ncq_log->lba_23_16;
1100   information_buff[6] = ncq_log->lba_15_8;
1101   information_buff[7] = ncq_log->lba_7_0;
1102
1103   sati_scsi_common_descriptor_sense_construct(
1104           sequence,
1105           scsi_io,
1106           sense_data,
1107           sense_len,
1108           sense_key,
1109           additional_sense_code,
1110           additional_sense_code_qualifier,
1111           information_buff
1112   );
1113}
1114
1115/**
1116* @brief This method will construct the sense data buffer in the user's
1117*        sense data buffer location.  Additionally, it will set the user's
1118*        SCSI status. This is only used for NCQ uncorrectable read errors
1119*
1120* @param[in]     sequence This parameter specifies the translation sequence
1121*                for which to construct the sense data.
1122* @param[in,out] scsi_io This parameter specifies the user's IO request
1123*                for which to construct the sense data.
1124* @param[in]     ata_input_data This parameter specifies the user's ATA IO
1125*                response from a Read Log Ext command.
1126* @param[in]     scsi_status This parameter specifies the SCSI status
1127*                value for the user's IO request.
1128* @param[in]     sense_key This parameter specifies the sense key to
1129*                be set for the user's IO request.
1130* @param[in]     additional_sense_code This parameter specifies the
1131*                additional sense code (ASC) key to be set for the user's
1132*                IO request.
1133* @param[in]     additional_sense_code_qualifier This parameter specifies
1134*                the additional sense code qualifier (ASCQ) key to be set
1135*                for the user's IO request.
1136*
1137* @return none
1138*/
1139static
1140void sati_scsi_read_ncq_error_fixed_sense_construct(
1141   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1142   void                       * scsi_io,
1143   void                       * ata_input_data,
1144   U8                           scsi_status,
1145   U8                           response_code,
1146   U8                           sense_key,
1147   U8                           additional_sense_code,
1148   U8                           additional_sense_code_qualifier
1149)
1150{
1151   U8 * sense_data;
1152   U32  sense_len;
1153   U8   valid = TRUE;
1154
1155   ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
1156
1157   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1158
1159   if(ncq_log->lba_39_32 > 0)
1160   {
1161      valid = FALSE;
1162   }
1163
1164   sati_set_sense_data_byte(
1165      sense_data,
1166      sense_len,
1167      0,
1168      (valid << 7) | response_code
1169   );
1170
1171   sati_set_sense_data_byte(sense_data, sense_len, 3,  ncq_log->lba_31_24);
1172   sati_set_sense_data_byte(sense_data, sense_len, 4,  ncq_log->lba_23_16);
1173   sati_set_sense_data_byte(sense_data, sense_len, 5,  ncq_log->lba_15_8);
1174   sati_set_sense_data_byte(sense_data, sense_len, 6,  ncq_log->lba_7_0);
1175
1176   sati_scsi_common_fixed_sense_construct(
1177      sense_data,
1178      sense_len,
1179      sense_key,
1180      additional_sense_code,
1181      additional_sense_code_qualifier
1182   );
1183}
1184
1185void sati_scsi_read_ncq_error_sense_construct(
1186   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1187   void                       * scsi_io,
1188   void                       * ata_input_data,
1189   U8                           scsi_status,
1190   U8                           sense_key,
1191   U8                           additional_sense_code,
1192   U8                           additional_sense_code_qualifier
1193)
1194{
1195    U8 response_code;
1196
1197    response_code = sati_scsi_get_sense_data_response_code(sequence);
1198
1199    switch (response_code)
1200    {
1201    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
1202    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
1203        sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1204                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1205    break;
1206    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
1207    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
1208        sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1209                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1210        break;
1211    }
1212
1213    sequence->is_sense_response_set = TRUE;
1214}
1215
1216/**
1217* @brief This method will construct the sense data buffer in the user's
1218*        sense data buffer location.  Additionally, it will set the user's
1219*        SCSI status. This is used for uncorrectable read errors.
1220*
1221* @param[in]     sequence This parameter specifies the translation sequence
1222*                for which to construct the sense data.
1223* @param[in,out] scsi_io This parameter specifies the user's IO request
1224*                for which to construct the sense data.
1225* @param[in]     ata_io This parameter is a pointer to the ATA IO data used
1226*                to get the ATA register fis.
1227* @param[in]     scsi_status This parameter specifies the SCSI status
1228*                value for the user's IO request.
1229* @param[in]     sense_key This parameter specifies the sense key to
1230*                be set for the user's IO request.
1231* @param[in]     additional_sense_code This parameter specifies the
1232*                additional sense code (ASC) key to be set for the user's
1233*                IO request.
1234* @param[in]     additional_sense_code_qualifier This parameter specifies
1235*                the additional sense code qualifier (ASCQ) key to be set
1236*                for the user's IO request.
1237*
1238* @return none
1239*/
1240static
1241void sati_scsi_read_error_descriptor_sense_construct(
1242   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1243   void                       * scsi_io,
1244   void                       * ata_io,
1245   U8                           scsi_status,
1246   U8                           response_code,
1247   U8                           sense_key,
1248   U8                           additional_sense_code,
1249   U8                           additional_sense_code_qualifier
1250)
1251{
1252   U8 * sense_data;
1253   U32  sense_len;
1254   U8 information_buff[8] = {0};
1255
1256   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
1257
1258   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1259
1260   information_buff[2] = sati_get_ata_lba_high_ext(register_fis);
1261   information_buff[3] = sati_get_ata_lba_mid_ext(register_fis);
1262   information_buff[4] = sati_get_ata_lba_low_ext(register_fis);
1263   information_buff[5] = sati_get_ata_lba_high(register_fis);
1264   information_buff[6] = sati_get_ata_lba_mid(register_fis);
1265   information_buff[7] = sati_get_ata_lba_low(register_fis);
1266
1267   sati_set_sense_data_byte(
1268      sense_data,
1269      sense_len,
1270      0,
1271      SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE
1272   );
1273
1274   sati_scsi_common_descriptor_sense_construct(
1275      sequence,
1276      scsi_io,
1277      sense_data,
1278      sense_len,
1279      sense_key,
1280      additional_sense_code,
1281      additional_sense_code_qualifier,
1282      information_buff
1283   );
1284}
1285
1286/**
1287* @brief This method will construct the sense data buffer in the user's
1288*        sense data buffer location.  Additionally, it will set the user's
1289*        SCSI status. This is used for uncorrectable read errors.
1290*
1291* @param[in]     sequence This parameter specifies the translation sequence
1292*                for which to construct the sense data.
1293* @param[in,out] scsi_io This parameter specifies the user's IO request
1294*                for which to construct the sense data.
1295* @param[in]     ata_io This parameter is a pointer to the ATA IO data used
1296*                to get the ATA register fis.
1297* @param[in]     scsi_status This parameter specifies the SCSI status
1298*                value for the user's IO request.
1299* @param[in]     sense_key This parameter specifies the sense key to
1300*                be set for the user's IO request.
1301* @param[in]     additional_sense_code This parameter specifies the
1302*                additional sense code (ASC) key to be set for the user's
1303*                IO request.
1304* @param[in]     additional_sense_code_qualifier This parameter specifies
1305*                the additional sense code qualifier (ASCQ) key to be set
1306*                for the user's IO request.
1307*
1308* @return none
1309*/
1310static
1311void sati_scsi_read_error_fixed_sense_construct(
1312   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1313   void                       * scsi_io,
1314   void                       * ata_io,
1315   U8                           scsi_status,
1316   U8                           response_code,
1317   U8                           sense_key,
1318   U8                           additional_sense_code,
1319   U8                           additional_sense_code_qualifier
1320)
1321{
1322   U8 * sense_data;
1323   U32  sense_len;
1324   U8   valid = TRUE;
1325
1326   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
1327
1328   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1329
1330   if(sati_get_ata_lba_mid_ext(register_fis) > 0)
1331   {
1332      valid = FALSE;
1333   }
1334
1335   sati_set_sense_data_byte(sense_data, sense_len, 3,  sati_get_ata_lba_low_ext(register_fis));
1336   sati_set_sense_data_byte(sense_data, sense_len, 4,  sati_get_ata_lba_high(register_fis));
1337   sati_set_sense_data_byte(sense_data, sense_len, 5,  sati_get_ata_lba_mid(register_fis));
1338   sati_set_sense_data_byte(sense_data, sense_len, 6,  sati_get_ata_lba_low(register_fis));
1339
1340
1341   sati_set_sense_data_byte(
1342      sense_data,
1343      sense_len,
1344      0,
1345      (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE
1346   );
1347
1348   sati_scsi_common_fixed_sense_construct(
1349      sense_data,
1350      sense_len,
1351      sense_key,
1352      additional_sense_code,
1353      additional_sense_code_qualifier
1354   );
1355}
1356
1357void sati_scsi_read_error_sense_construct(
1358   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1359   void                       * scsi_io,
1360   void                       * ata_input_data,
1361   U8                           scsi_status,
1362   U8                           sense_key,
1363   U8                           additional_sense_code,
1364   U8                           additional_sense_code_qualifier
1365)
1366{
1367    U8 response_code;
1368
1369    response_code = sati_scsi_get_sense_data_response_code(sequence);
1370
1371    switch (response_code)
1372    {
1373    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
1374    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
1375        sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1376                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1377    break;
1378    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
1379    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
1380        sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1381                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1382        break;
1383    }
1384
1385    sequence->is_sense_response_set = TRUE;
1386}
1387
1388/*
1389 * @brief This method builds the scsi response data for a sata task management
1390 *        request.
1391 *
1392 * @param[in]     sequence This parameter specifies the translation sequence
1393 *                for which to construct the sense data.
1394 * @param[in,out] scsi_io This parameter specifies the user's IO request
1395 *                for which to construct the sense data.
1396 * @param[in]     response_data The response status for the task management
1397 *                request.
1398 */
1399void sati_scsi_response_data_construct(
1400   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1401   void                       * scsi_io,
1402   U8                           response_data
1403)
1404{
1405#ifdef SATI_TRANSPORT_SUPPORTS_SAS
1406   SCI_SSP_RESPONSE_IU_T * rsp_iu  = (SCI_SSP_RESPONSE_IU_T*)
1407                                        sati_cb_get_response_iu_address(scsi_io);
1408   rsp_iu->data_present            = 0x01;
1409   rsp_iu->response_data_length[3] = sizeof(U32);
1410   rsp_iu->status                  = 0;
1411   ((U8 *)rsp_iu->data)[3]         = response_data;
1412#else
1413#endif // SATI_TRANSPORT_SUPPORTS_SAS
1414}
1415
1416/**
1417 * @brief This method checks to make sure that the translation isn't
1418 *        exceeding the allocation length specified in the CDB prior
1419 *        to retrieving the payload data byte from the user's buffer.
1420 *
1421 * @param[in,out] scsi_io This parameter specifies the user's IO request
1422 *                for which to set the user payload data byte.
1423 * @param[in]     byte_offset This parameter specifies the offset into
1424 *                the user's payload buffer at which to write the supplied
1425 *                value.
1426 * @param[in]     value This parameter specifies the memory location into
1427 *                which to read the value from the user's payload buffer.
1428 *
1429 * @return none
1430 */
1431void sati_get_data_byte(
1432   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1433   void                       * scsi_io,
1434   U32                          byte_offset,
1435   U8                         * value
1436)
1437{
1438   if (byte_offset < sequence->allocation_length)
1439      sati_cb_get_data_byte(scsi_io, byte_offset, value);
1440}
1441
1442/**
1443 * @brief This method checks to make sure that the translation isn't
1444 *        exceeding the allocation length specified in the CDB while
1445 *        translating payload data into the user's buffer.
1446 *
1447 * @param[in]     sequence This parameter specifies the translation sequence
1448 *                for which to set the user payload data byte.
1449 * @param[in,out] scsi_io This parameter specifies the user's IO request
1450 *                for which to set the user payload data byte.
1451 * @param[in]     byte_offset This parameter specifies the offset into
1452 *                the user's payload buffer at which to write the supplied
1453 *                value.
1454 * @param[in]     value This parameter specifies the new value to be
1455 *                written out into the user's payload buffer.
1456 *
1457 * @return none
1458 */
1459void sati_set_data_byte(
1460   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1461   void                       * scsi_io,
1462   U32                          byte_offset,
1463   U8                           value
1464)
1465{
1466   if (byte_offset < sequence->allocation_length)
1467   {
1468      sequence->number_data_bytes_set++;
1469      sati_cb_set_data_byte(scsi_io, byte_offset, value);
1470   }
1471}
1472
1473/**
1474 * @brief This method checks to make sure that the translation isn't
1475 *        exceeding the allocation length specified in the CDB while
1476 *        translating payload data into the user's buffer.
1477 *
1478 * @param[in]     sequence This parameter specifies the translation sequence
1479 *                for which to set the user payload data dword.
1480 * @param[in,out] scsi_io This parameter specifies the user's IO request
1481 *                for which to set the user payload data dword.
1482 * @param[in]     byte_offset This parameter specifies the offset into
1483 *                the user's payload buffer at which to write the supplied
1484 *                value.
1485 * @param[in]     value This parameter specifies the new value to be
1486 *                written out into the user's payload buffer.
1487 *
1488 * @return none
1489 */
1490void sati_set_data_dword(
1491   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1492   void                       * scsi_io,
1493   U32                          byte_offset,
1494   U32                          value
1495)
1496{
1497   /// @todo Check to ensure that the bytes appear correctly (SAS Address).
1498
1499   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF);
1500       byte_offset++;
1501   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF);
1502       byte_offset++;
1503   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF);
1504       byte_offset++;
1505   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF);
1506}
1507
1508/**
1509 * @brief This method will construct the ATA flush cache command.
1510 *
1511 * @pre It is expected that the user has properly set the current contents
1512 *      of the register FIS to 0.
1513 *
1514 * @param[out] ata_io This parameter specifies the ATA IO request structure
1515 *             for which to build the FLUSH CACHE command.
1516 * @param[in]  sequence This parameter specifies the translator sequence
1517 *             for which the command is being constructed.
1518 *
1519 * @return none.
1520 */
1521void sati_ata_flush_cache_construct(
1522   void                       * ata_io,
1523   SATI_TRANSLATOR_SEQUENCE_T * sequence
1524)
1525{
1526   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1527
1528   sati_set_ata_command(register_fis, ATA_FLUSH_CACHE);
1529   sati_ata_non_data_command(ata_io, sequence);
1530}
1531
1532/**
1533 * @brief This method will construct the ATA standby immediate command.
1534 *
1535 * @pre It is expected that the user has properly set the current contents
1536 *      of the register FIS to 0.
1537 *
1538 * @param[out] ata_io This parameter specifies the ATA IO request structure
1539 *             for which to build the STANDBY IMMEDIATE command.
1540 * @param[in]  sequence This parameter specifies the translator sequence
1541 *             for which the command is being constructed.
1542 *
1543 * @param[in]  count This parameter specifies the time period programmed
1544 *             into the Standby Timer. See ATA8 spec for more details
1545 * @return none.
1546 */
1547void sati_ata_standby_construct(
1548   void                       * ata_io,
1549   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1550   U16                          count
1551)
1552{
1553   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1554
1555   sati_set_ata_command(register_fis, ATA_STANDBY);
1556   sati_set_ata_sector_count(register_fis, count);
1557
1558   sequence->device->ata_standby_timer = (U8) count;
1559
1560   sati_ata_non_data_command(ata_io, sequence);
1561}
1562
1563/**
1564 * @brief This method will construct the ATA standby immediate command.
1565 *
1566 * @pre It is expected that the user has properly set the current contents
1567 *      of the register FIS to 0.
1568 *
1569 * @param[out] ata_io This parameter specifies the ATA IO request structure
1570 *             for which to build the STANDBY IMMEDIATE command.
1571 * @param[in]  sequence This parameter specifies the translator sequence
1572 *             for which the command is being constructed.
1573 *
1574 * @return none.
1575 */
1576void sati_ata_standby_immediate_construct(
1577   void                       * ata_io,
1578   SATI_TRANSLATOR_SEQUENCE_T * sequence
1579)
1580{
1581   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1582
1583   sati_set_ata_command(register_fis, ATA_STANDBY_IMMED);
1584   sati_ata_non_data_command(ata_io, sequence);
1585}
1586
1587/**
1588 * @brief This method will construct the ATA idle immediate command.
1589 *
1590 * @pre It is expected that the user has properly set the current contents
1591 *      of the register FIS to 0.
1592 *
1593 * @param[out] ata_io This parameter specifies the ATA IO request structure
1594 *             for which to build the IDLE IMMEDIATE command.
1595 * @param[in]  sequence This parameter specifies the translator sequence
1596 *             for which the command is being constructed.
1597 *
1598 * @return none.
1599 */
1600void sati_ata_idle_immediate_construct(
1601   void                       * ata_io,
1602   SATI_TRANSLATOR_SEQUENCE_T * sequence
1603)
1604{
1605   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1606
1607   sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
1608   sati_set_ata_features(register_fis, 0x00);
1609   sati_set_ata_sector_count(register_fis, 0x00);
1610   sati_set_ata_lba_high(register_fis, 0x00);
1611   sati_set_ata_lba_mid(register_fis, 0x00);
1612   sati_set_ata_lba_low(register_fis, 0x00);
1613   sati_ata_non_data_command(ata_io, sequence);
1614}
1615
1616/**
1617 * @brief This method will construct the ATA idle immediate command
1618          for Unload Features.
1619 *
1620 * @pre It is expected that the user has properly set the current contents
1621 *      of the register FIS to 0.
1622 *
1623 * @param[out] ata_io This parameter specifies the ATA IO request structure
1624 *             for which to build the IDLE IMMEDIATE command.
1625 * @param[in]  sequence This parameter specifies the translator sequence
1626 *             for which the command is being constructed.
1627 *
1628 * @return none.
1629 */
1630void sati_ata_idle_immediate_unload_construct(
1631   void                       * ata_io,
1632   SATI_TRANSLATOR_SEQUENCE_T * sequence
1633)
1634{
1635   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1636
1637   sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
1638   sati_set_ata_features(register_fis, 0x44);
1639   sati_set_ata_sector_count(register_fis, 0x00);
1640   sati_set_ata_lba_high(register_fis, 0x55);
1641   sati_set_ata_lba_mid(register_fis, 0x4E);
1642   sati_set_ata_lba_low(register_fis, 0x4C);
1643   sati_ata_non_data_command(ata_io, sequence);
1644}
1645
1646/**
1647 * @brief This method will construct the ATA IDLE command.\
1648 *
1649 * @pre It is expected that the user has properly set the current contents
1650 *      of the register FIS to 0.
1651 *
1652 * @param[out] ata_io This parameter specifies the ATA IO request structure
1653 *             for which to build the ATA IDLE command.
1654 * @param[in]  sequence This parameter specifies the translator sequence
1655 *             for which the command is being constructed.
1656 *
1657 * @return none.
1658 */
1659void sati_ata_idle_construct(
1660   void                       * ata_io,
1661   SATI_TRANSLATOR_SEQUENCE_T * sequence
1662)
1663{
1664   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1665
1666   sati_set_ata_command(register_fis, ATA_IDLE);
1667   sati_set_ata_features(register_fis, 0x00);
1668   sati_set_ata_sector_count(register_fis, 0x00);
1669
1670   sequence->device->ata_standby_timer = 0x00;
1671
1672   sati_set_ata_lba_high(register_fis, 0x00);
1673   sati_set_ata_lba_mid(register_fis, 0x00);
1674   sati_set_ata_lba_low(register_fis, 0x00);
1675   sati_ata_non_data_command(ata_io, sequence);
1676}
1677
1678/**
1679 * @brief This method will construct the ATA MEDIA EJECT command.
1680 *
1681 * @pre It is expected that the user has properly set the current contents
1682 *      of the register FIS to 0.
1683 *
1684 * @param[out] ata_io This parameter specifies the ATA IO request structure
1685 *             for which to build the MEDIA EJCT command.
1686 * @param[in]  sequence This parameter specifies the translator sequence
1687 *             for which the command is being constructed.
1688 *
1689 * @return none.
1690 */
1691void sati_ata_media_eject_construct(
1692   void                       * ata_io,
1693   SATI_TRANSLATOR_SEQUENCE_T * sequence
1694)
1695{
1696   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1697
1698   sati_set_ata_command(register_fis, ATA_MEDIA_EJECT);
1699   sati_ata_non_data_command(ata_io, sequence);
1700}
1701
1702
1703/**
1704 * @brief This method will construct the ATA read verify sector(s) command.
1705 *
1706 * @pre It is expected that the user has properly set the current contents
1707 *      of the register FIS to 0.
1708 *
1709 * @param[out] ata_io This parameter specifies the ATA IO request structure
1710 *             for which to build the ATA READ VERIFY SECTOR(S) command.
1711 * @param[in]  sequence This parameter specifies the translator sequence
1712 *             for which the command is being constructed.
1713 *
1714 * @return none.
1715 */
1716void sati_ata_read_verify_sectors_construct(
1717   void                       * ata_io,
1718   SATI_TRANSLATOR_SEQUENCE_T * sequence
1719)
1720{
1721   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1722
1723   sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
1724
1725   //According to SAT-2 (v7) 9.11.3
1726   sati_set_ata_sector_count(register_fis, 1);
1727
1728   //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the
1729   //maximum LBA supported by the ATA device in its current configuration.
1730   //From the unit test, it seems we have to set LBA to a non-zero value.
1731   sati_set_ata_lba_low(register_fis, 1);
1732
1733   sati_ata_non_data_command(ata_io, sequence);
1734}
1735
1736/**
1737 * @brief This method will construct a ATA SMART Return Status command so the
1738 *        status of the ATA device can be returned. The status of the SMART
1739 *        threshold will be returned by this command.
1740 *
1741 * @return N/A
1742 *
1743 */
1744void sati_ata_smart_return_status_construct(
1745   void                       * ata_io,
1746   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1747   U8                           feature_value
1748)
1749{
1750   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1751
1752   sati_set_ata_command(register_fis, ATA_SMART);
1753
1754   sati_set_ata_features(register_fis, feature_value);
1755
1756   sati_set_ata_lba_high(register_fis, 0xC2);
1757   sati_set_ata_lba_mid(register_fis, 0x4F);
1758
1759   sati_ata_non_data_command(ata_io, sequence);
1760}
1761
1762/**
1763 * @brief This method will construct a ATA SMART Return Status command so the
1764 *        status of the ATA device can be returned. The status of the SMART
1765 *        threshold will be returned by this command.
1766 *
1767 * @return N/A
1768 *
1769 */
1770void sati_ata_smart_read_log_construct(
1771   void                       * ata_io,
1772   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1773   U8                           log_address,
1774   U32                          transfer_length
1775)
1776{
1777   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1778
1779   sati_set_ata_command(register_fis, ATA_SMART);
1780   sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG);
1781
1782   sati_set_ata_lba_high(register_fis, 0xC2);
1783   sati_set_ata_lba_mid(register_fis, 0x4F);
1784   sati_set_ata_lba_low(register_fis, log_address);
1785
1786   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1787   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1788   sequence->ata_transfer_length = transfer_length;
1789}
1790
1791/**
1792 * @brief This method will construct a Write Uncorrectable ATA command that
1793 *        will write one sector with a pseudo or flagged error. The type of
1794 *        error is specified by the feature value.
1795 *
1796 * @return N/A
1797 *
1798 */
1799void sati_ata_write_uncorrectable_construct(
1800   void                       * ata_io,
1801   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1802   U8                           feature_value
1803)
1804{
1805   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1806
1807   sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE);
1808   sati_set_ata_features(register_fis, feature_value);
1809   sati_set_ata_sector_count(register_fis, 0x0001);
1810   sati_ata_non_data_command(ata_io, sequence);
1811}
1812
1813/**
1814 * @brief This method will construct a Mode Select ATA SET FEATURES command
1815 *        For example, Enable/Disable Write Cache, Enable/Disable Read Ahead
1816 *
1817 * @return N/A
1818 *
1819 */
1820void sati_ata_set_features_construct(
1821   void                       * ata_io,
1822   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1823   U8                           feature
1824)
1825{
1826   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1827
1828   sati_set_ata_command(register_fis, ATA_SET_FEATURES);
1829   sati_set_ata_features(register_fis, feature);
1830   sati_ata_non_data_command(ata_io, sequence);
1831}
1832
1833
1834
1835/**
1836 * @brief This method will construct a Read Log ext ATA command that
1837 *        will request a log page based on the log_address.
1838 *
1839 * @param[in]  log_address This parameter specifies the log page
1840 *             to be returned from Read Log Ext.
1841 *
1842 * @param[in]  transfer_length This parameter specifies the size of the
1843 *             log page response returned by Read Log Ext.
1844 *
1845 * @return N/A
1846 *
1847 */
1848void sati_ata_read_log_ext_construct(
1849   void                          * ata_io,
1850   SATI_TRANSLATOR_SEQUENCE_T    * sequence,
1851   U8                              log_address,
1852   U32                             transfer_length
1853)
1854{
1855   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1856
1857   sati_set_ata_command(register_fis, ATA_READ_LOG_EXT);
1858
1859   sati_set_ata_lba_low(register_fis, log_address);
1860   sati_set_ata_lba_mid(register_fis, 0x00);
1861   sati_set_ata_lba_mid_exp(register_fis, 0x00);
1862
1863   sati_set_ata_sector_count(register_fis, 0x01);
1864
1865   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1866   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1867   sequence->ata_transfer_length = transfer_length;
1868
1869}
1870
1871/**
1872* @brief This method will check if the ATA device is in the stopped power
1873*        state. This is used for all medium access commands for SAT
1874*        compliance. See SAT2r07 section 9.11.1
1875*
1876* @param[in] sequence - SATI sequence data with the device state.
1877*
1878* @return TRUE If device is stopped
1879*
1880*/
1881BOOL sati_device_state_stopped(
1882   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1883   void                       * scsi_io
1884)
1885{
1886   if(sequence->device->state == SATI_DEVICE_STATE_STOPPED)
1887   {
1888      sati_scsi_sense_data_construct(
1889         sequence,
1890         scsi_io,
1891         SCSI_STATUS_CHECK_CONDITION,
1892         SCSI_SENSE_NOT_READY ,
1893         SCSI_ASC_INITIALIZING_COMMAND_REQUIRED,
1894         SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED
1895      );
1896      return TRUE;
1897   }
1898   return FALSE;
1899}
1900
1901/**
1902* @brief This method will construct a ATA Read Buffer command that
1903*        will request PIO in data containing the target device's buffer.
1904*
1905* @param[out] ata_io This parameter specifies the ATA IO request structure
1906*             for which to build the ATA READ VERIFY SECTOR(S) command.
1907* @param[in]  sequence This parameter specifies the translator sequence
1908*             for which the command is being constructed.
1909* @return N/A
1910*
1911*/
1912void sati_ata_read_buffer_construct(
1913   void                       * ata_io,
1914   SATI_TRANSLATOR_SEQUENCE_T * sequence
1915)
1916{
1917   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1918
1919   sati_set_ata_command(register_fis, ATA_READ_BUFFER);
1920   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1921   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1922   sequence->ata_transfer_length = 512;
1923}
1924
1925
1926/**
1927* @brief This method will construct a ATA Write Buffer command that
1928*        will send PIO out data to the target device's buffer.
1929*
1930* @param[out] ata_io This parameter specifies the ATA IO request structure
1931*             for which to build the ATA READ VERIFY SECTOR(S) command.
1932* @param[in]  sequence This parameter specifies the translator sequence
1933*             for which the command is being constructed.
1934* @return N/A
1935*
1936*/
1937void sati_ata_write_buffer_construct(
1938   void                       * ata_io,
1939   SATI_TRANSLATOR_SEQUENCE_T * sequence
1940)
1941{
1942   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1943
1944   sati_set_ata_command(register_fis, ATA_WRITE_BUFFER);
1945
1946   sequence->data_direction      = SATI_DATA_DIRECTION_OUT;
1947   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_OUT;
1948   sequence->ata_transfer_length = 512;
1949}
1950
1951
1952/**
1953* @brief This method will construct a ATA Download Microcode command that
1954*        will send PIO out data containing new firmware for the target drive.
1955*
1956* @param[out] ata_io This parameter specifies the ATA IO request structure
1957*             for which to build the ATA READ VERIFY SECTOR(S) command.
1958* @param[in]  sequence This parameter specifies the translator sequence
1959*             for which the command is being constructed.
1960* @param[in]  mode This parameter specifies the download microcode sub-command
1961*             code.
1962* @param[in]  allocation_length This parameter specifies the number of bytes
1963*             being sent to the target device.
1964* @param[in]  buffer_offset This parameter specifies the buffer offset for the
1965*             data sent to the target device.
1966*
1967* @return N/A
1968*
1969*/
1970void sati_ata_download_microcode_construct(
1971   void                       * ata_io,
1972   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1973   U8                           mode,
1974   U32                          allocation_length,
1975   U32                          buffer_offset
1976)
1977{
1978   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1979   U32 allocation_blocks = allocation_length >> 9;
1980   U32 buffer_blkoffset = buffer_offset >> 9;
1981
1982   sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE);
1983   sati_set_ata_features(register_fis, mode);
1984
1985   if(mode == ATA_MICROCODE_DOWNLOAD_SAVE)
1986   {
1987      sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9));
1988      sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17));
1989   }
1990   else //mode == 0x03
1991   {
1992      sati_set_ata_sector_count(register_fis, (U8) (allocation_blocks & 0xff));
1993      sati_set_ata_lba_low(register_fis, (U8) ((allocation_blocks >> 8) & 0xff));
1994      sati_set_ata_lba_mid(register_fis, (U8) (buffer_blkoffset & 0xff));
1995      sati_set_ata_lba_high(register_fis, (U8) ((buffer_blkoffset >> 8) & 0xff));
1996   }
1997
1998   if((allocation_length == 0) && (buffer_offset == 0))
1999   {
2000      sati_ata_non_data_command(ata_io, sequence);
2001   }
2002   else
2003   {
2004      sequence->data_direction      = SATI_DATA_DIRECTION_OUT;
2005      sequence->protocol            = SAT_PROTOCOL_PIO_DATA_OUT;
2006      sequence->ata_transfer_length = allocation_length;
2007   }
2008}
2009