xref: /freebsd/sys/dev/isci/scil/sati_util.c (revision fed1ca4b719c56c930f2259d80663cd34be812bb)
1 /*-
2  * This file is provided under a dual BSD/GPLv2 license.  When using or
3  * redistributing this file, you may do so under either license.
4  *
5  * GPL LICENSE SUMMARY
6  *
7  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of version 2 of the GNU General Public License as
11  * published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21  * The full GNU General Public License is included in this distribution
22  * in the file called LICENSE.GPL.
23  *
24  * BSD LICENSE
25  *
26  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27  * All rights reserved.
28  *
29  * Redistribution and use in source and binary forms, with or without
30  * modification, are permitted provided that the following conditions
31  * are met:
32  *
33  *   * Redistributions of source code must retain the above copyright
34  *     notice, this list of conditions and the following disclaimer.
35  *   * Redistributions in binary form must reproduce the above copyright
36  *     notice, this list of conditions and the following disclaimer in
37  *     the documentation and/or other materials provided with the
38  *     distribution.
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51  */
52 
53 #include <sys/cdefs.h>
54 __FBSDID("$FreeBSD$");
55 
56 /**
57  * @file
58  * @brief This file contains all of the method implementations that
59  *        provide generic support for SATI.  Some methods can be utilized
60  *        by a user to construct ATA/ATAPI commands, copy ATA device
61  *        structure data, fill in sense data, etc.
62  */
63 
64 #include <dev/isci/scil/sati_util.h>
65 #include <dev/isci/scil/sati_callbacks.h>
66 #include <dev/isci/scil/intel_scsi.h>
67 #include <dev/isci/scil/intel_ata.h>
68 #include <dev/isci/scil/intel_sat.h>
69 #include <dev/isci/scil/intel_sas.h>
70 
71 /**
72  * @brief This method will set the data direction, protocol, and transfer
73  *        kength for an ATA non-data command.
74  *
75  * @pre It is expected that the user will use this method for setting these
76  *      values in a non-data ATA command constuct.
77  *
78  * @param[out] ata_io This parameter specifies the ATA IO request structure
79  *             for which to build the IDENTIFY DEVICE command.
80  * @param[in]  sequence This parameter specifies the translator sequence
81  *             for which the command is being constructed.
82  *
83  * @return none.
84  */
85 void sati_ata_non_data_command(
86    void                        * ata_io,
87    SATI_TRANSLATOR_SEQUENCE_T  * sequence
88 )
89 {
90    sequence->data_direction      = SATI_DATA_DIRECTION_NONE;
91    sequence->protocol            = SAT_PROTOCOL_NON_DATA;
92    sequence->ata_transfer_length = 0;
93 }
94 
95 /**
96  * @brief This method will construct the ATA identify device command.
97  *
98  * @pre It is expected that the user has properly set the current contents
99  *      of the register FIS to 0.
100  *
101  * @param[out] ata_io This parameter specifies the ATA IO request structure
102  *             for which to build the IDENTIFY DEVICE command.
103  * @param[in]  sequence This parameter specifies the translator sequence
104  *             for which the command is being constructed.
105  *
106  * @return none.
107  */
108 void sati_ata_identify_device_construct(
109    void                       * ata_io,
110    SATI_TRANSLATOR_SEQUENCE_T * sequence
111 )
112 {
113    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
114 
115    sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE);
116    sequence->data_direction      = SATI_DATA_DIRECTION_IN;
117    sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
118    sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T);
119 }
120 
121 /**
122 * @brief This method will construct the ATA Execute Device Diagnostic command.
123 *
124 * @param[out] ata_io This parameter specifies the ATA IO request structure
125 *             for which to build the IDENTIFY DEVICE command.
126 * @param[in]  sequence This parameter specifies the translator sequence
127 *             for which the command is being constructed.
128 *
129 * @return none.
130 */
131 void sati_ata_execute_device_diagnostic_construct(
132    void                       * ata_io,
133    SATI_TRANSLATOR_SEQUENCE_T * sequence
134 )
135 {
136    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
137 
138    sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG);
139 
140    sequence->data_direction = SATI_DATA_DIRECTION_IN;
141    sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC;
142    sequence->ata_transfer_length = 16;
143 }
144 
145 /**
146  * @brief This method will set data bytes in the user data area.  If the
147  *        caller requests it, the data written will be forced to ascii
148  *        printable characters if it isn't already a printable character.
149  *        A printable character is considered to be >= 0x20 and <= 0x70.
150  *
151  * @param[in]  sequence This parameter specifies the translation sequence
152  *             for which to copy and swap the data.
153  * @param[out] destination_scsi_io This parameter specifies the SCSI IO
154  *             request containing the destination buffer into which to copy.
155  * @param[in]  destination_offset This parameter specifies the offset into
156  *             the data buffer where the information will be copied to.
157  * @param[in]  source_value This parameter specifies the value retrieved
158  *             from the source buffer that is to be copied into the user
159  *             buffer area.
160  * @param[in]  use_printable_chars This parameter indicates if the copy should
161  *             ensure that the value copied is considered an ASCII printable
162  *             character (e.g. A, B, " ", etc.).  These characters reside
163  *             in the 0x20 - 0x7E ASCII range.
164  *
165  * @return none
166  */
167 static
168 void sati_set_ascii_data_byte(
169    SATI_TRANSLATOR_SEQUENCE_T * sequence,
170    void                       * destination_scsi_io,
171    U32                          destination_offset,
172    U8                           source_value,
173    BOOL                         use_printable_chars
174 )
175 {
176    // if the user requests that the copied data be ascii printable, then
177    // default to " " (i.e. 0x20) for all non-ascii printable characters.
178    if((use_printable_chars == TRUE)
179      && ((source_value < 0x20) || (source_value > 0x7E)))
180    {
181       source_value = 0x20;
182    }
183 
184    sati_set_data_byte(
185       sequence, destination_scsi_io, destination_offset, source_value
186    );
187 }
188 
189 /**
190  * @brief This method performs a copy operation using an offset into the
191  *        source buffer, an offset into the destination buffer, and a length.
192  *        It will perform the byte swap from the 16-bit identify field
193  *        into the network byte order SCSI location.
194  *
195  * @param[in]  sequence This parameter specifies the translation sequence
196  *             for which to copy and swap the data.
197  * @param[out] destination_scsi_io This parameter specifies the SCSI IO
198  *             request containing the destination buffer into which to copy.
199  * @param[in]  destination_offset This parameter specifies the offset into
200  *             the data buffer where the information will be copied to.
201  * @param[in]  source_buffer This parameter specifies the source buffer from
202  *             which the data will be copied.
203  * @param[in]  source_offset This parameter specifies the offset into the
204  *             source buffer where the copy shall begin.
205  * @param[in]  length This parameter specifies the number of bytes to copy
206  *             during this operation.
207  * @param[in]  use_printable_chars This parameter indicates if the copy should
208  *             ensure that the value copied is considered an ASCII printable
209  *             character (e.g. A, B, " ", etc.).  These characters reside
210  *             in the 0x20 - 0x7E ASCII range.
211  *
212  * @return none
213  */
214 void sati_ata_identify_device_copy_data(
215    SATI_TRANSLATOR_SEQUENCE_T * sequence,
216    void                       * destination_scsi_io,
217    U32                          destination_offset,
218    U8                         * source_buffer,
219    U32                          source_offset,
220    U32                          length,
221    BOOL                         use_printable_chars
222 )
223 {
224    source_buffer += source_offset;
225    while (length > 0)
226    {
227       sati_set_ascii_data_byte(
228          sequence,
229          destination_scsi_io,
230          destination_offset,
231          *(source_buffer+1),
232          use_printable_chars
233       );
234 
235       sati_set_ascii_data_byte(
236          sequence,
237          destination_scsi_io,
238          destination_offset+1,
239          *source_buffer,
240          use_printable_chars
241       );
242 
243       destination_offset += 2;
244       source_buffer      += 2;
245       length             -= 2;
246    }
247 }
248 
249 /**
250  * @brief This method performs a copy operation using a source buffer,
251  *        an offset into the destination buffer, and a length.
252  *
253  * @param[in]  sequence This parameter specifies the translation sequence
254  *             for which to copy and swap the data.
255  * @param[out] destination_scsi_io This parameter specifies the SCSI IO
256  *             request containing the destination buffer into which to copy.
257  * @param[in]  destination_offset This parameter specifies the offset into
258  *             the data buffer where the information will be copied to.
259  * @param[in]  source_buffer This parameter specifies the source buffer from
260  *             which the data will be copied.
261  * @param[in]  length This parameter specifies the number of bytes to copy
262  *             during this operation.
263  *
264  * @return none
265  */
266 void sati_copy_data(
267    SATI_TRANSLATOR_SEQUENCE_T * sequence,
268    void                       * destination_scsi_io,
269    U32                          destination_offset,
270    U8                         * source_buffer,
271    U32                          length
272 )
273 {
274    while (length > 0)
275    {
276       sati_set_data_byte(
277          sequence, destination_scsi_io, destination_offset, *source_buffer
278       );
279 
280       destination_offset++;
281       source_buffer++;
282       length--;
283    }
284 }
285 
286 /**
287  * @brief This method extracts the Logical Block Address high and low 32-bit
288  *        values and the sector count 32-bit value from the ATA identify
289  *        device data.
290  *
291  * @param[in]  identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA
292  *             from which to extract the sector information.
293  * @param[out] lba_high This parameter specifies the upper 32 bits for the
294  *             number of logical block addresses for the device. The upper
295  *             16-bits should always be 0, since 48-bits of LBA is the most
296  *             supported by an ATA device.
297  * @param[out] lba_low This parameter specifies the lower 32 bits for the
298  *             number of logical block addresses for the device.
299  * @param[out] sector_size This parameter specifies the 32-bits of sector
300  *             size.  If the ATA device doesn't support reporting it's
301  *             sector size, then 512 bytes is utilized as the default value.
302  *
303  * @return none
304  */
305 void sati_ata_identify_device_get_sector_info(
306    ATA_IDENTIFY_DEVICE_DATA_T * identify,
307    U32                        * lba_high,
308    U32                        * lba_low,
309    U32                        * sector_size
310 )
311 {
312    // Calculate the values to be returned
313    // Calculation will be different if the SATA device supports
314    // 48-bit addressing.  Bit 10 of Word 86 of ATA Identify
315    if (identify->command_set_enabled1
316        & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE)
317    {
318       // This drive supports 48-bit addressing
319 
320       *lba_high  = identify->max_48bit_lba[7] << 24;
321       *lba_high |= identify->max_48bit_lba[6] << 16;
322       *lba_high |= identify->max_48bit_lba[5] << 8;
323       *lba_high |= identify->max_48bit_lba[4];
324 
325       *lba_low  = identify->max_48bit_lba[3] << 24;
326       *lba_low |= identify->max_48bit_lba[2] << 16;
327       *lba_low |= identify->max_48bit_lba[1] << 8;
328       *lba_low |= identify->max_48bit_lba[0];
329    }
330    else
331    {
332       // This device doesn't support 48-bit addressing
333       // Pull out the largest LBA from words 60 and 61.
334       *lba_high  = 0;
335       *lba_low   = identify->total_num_sectors[3] << 24;
336       *lba_low  |= identify->total_num_sectors[2] << 16;
337       *lba_low  |= identify->total_num_sectors[1] << 8;
338       *lba_low  |= identify->total_num_sectors[0];
339    }
340 
341    // If the ATA device reports its sector size (bit 12 of Word 106),
342    // then use that instead.
343    if (identify->physical_logical_sector_info
344        & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE)
345    {
346       *sector_size  = identify->words_per_logical_sector[3] << 24;
347       *sector_size |= identify->words_per_logical_sector[2] << 16;
348       *sector_size |= identify->words_per_logical_sector[1] << 8;
349       *sector_size |= identify->words_per_logical_sector[0];
350    }
351    else
352    {
353       // Default the sector size to 512 bytes
354       *sector_size = 512;
355    }
356 }
357 
358 /**
359  * @brief This method will construct the ATA check power mode command.
360  *
361  * @pre It is expected that the user has properly set the current contents
362  *      of the register FIS to 0.
363  *
364  * @param[out] ata_io This parameter specifies the ATA IO request structure
365  *             for which to build the CHECK POWER MODE command.
366  * @param[in]  sequence This parameter specifies the translator sequence
367  *             for which the command is being constructed.
368  *
369  * @return none.
370  */
371 void sati_ata_check_power_mode_construct(
372    void                       * ata_io,
373    SATI_TRANSLATOR_SEQUENCE_T * sequence
374 )
375 {
376    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
377 
378    sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE);
379    sati_ata_non_data_command(ata_io, sequence);
380 }
381 
382 /**
383  * @brief This method is utilized to set a specific byte in the sense
384  *        data area.  It will ensure that the supplied byte offset
385  *        isn't larger then the length of the requested sense data.
386  *
387  * @param[in] scsi_io This parameter specifies the user SCSI IO request
388  *            for which to set the sense data byte.
389  * @param[in] byte_offset This parameter specifies the byte offset into
390  *            the sense data buffer where the data should be written.
391  * @param[in] value This parameter specifies the 8-bit value to be written
392  *            into the sense data area.
393  *
394  * @return none
395  */
396 void sati_set_sense_data_byte(
397    U8  * sense_data,
398    U32   max_sense_data_len,
399    U32   byte_offset,
400    U8    value
401 )
402 {
403    // Ensure that we don't attempt to write past the end of the sense
404    // data buffer.
405    if (byte_offset < max_sense_data_len)
406       sense_data[byte_offset] = value;
407 }
408 
409 /**
410  * @brief This method will construct the common response IU in the user
411  *           request's response IU location.
412  *
413  * @param[out] rsp_iu This parameter specifies the user request's
414  *                response IU to be constructed.
415  * @param[in]  scsi_status This parameter specifies the SCSI status
416  *                value for the user's IO request.
417  * @param[in]  sense_data_length This parameter specifies the sense data
418  *                length for response IU.
419  * @param[in]  data_present The parameter specifies the specific
420  *                data present value for response IU.
421  *
422  * @return none
423  */
424 void sati_scsi_common_response_iu_construct(
425    SCI_SSP_RESPONSE_IU_T * rsp_iu,
426    U8                      scsi_status,
427    U8                      sense_data_length,
428    U8                      data_present
429 )
430 {
431    rsp_iu->sense_data_length[3] = sense_data_length;
432    rsp_iu->sense_data_length[2] = 0;
433    rsp_iu->sense_data_length[1] = 0;
434    rsp_iu->sense_data_length[0] = 0;
435    rsp_iu->status               = scsi_status;
436    rsp_iu->data_present         = data_present;
437 }
438 
439 /**
440  * @brief This method will construct the buffer for sense data
441  *        sense data buffer location.  Additionally, it will set the user's
442  *        SCSI status.
443  *
444  * @param[in,out] scsi_io This parameter specifies the user's IO request
445  *                for which to construct the buffer for sense data.
446  * @param[in]     scsi_status This parameter specifies the SCSI status
447  *                value for the user's IO request.
448  * @param[out]    sense_data This paramater
449  *
450  * @return none
451  */
452 static
453 void sati_scsi_get_sense_data_buffer(
454     SATI_TRANSLATOR_SEQUENCE_T      * sequence,
455     void                            * scsi_io,
456     U8                                scsi_status,
457     U8                             ** sense_data,
458     U32                             * sense_len)
459 {
460 #ifdef SATI_TRANSPORT_SUPPORTS_SAS
461    SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
462                                     sati_cb_get_response_iu_address(scsi_io);
463 
464    sati_scsi_common_response_iu_construct(
465       rsp_iu,
466       scsi_status,
467       sati_scsi_get_sense_data_length(sequence, scsi_io),
468       SCSI_RESPONSE_DATA_PRES_SENSE_DATA
469    );
470 
471    *sense_data                   = (U8*) rsp_iu->data;
472    *sense_len                    = SSP_RESPONSE_IU_MAX_DATA * 4;  // dwords to bytes
473 #else
474    *sense_data = sati_cb_get_sense_data_address(scsi_io);
475    *sense_len  = sati_cb_get_sense_data_length(scsi_io);
476    sati_cb_set_scsi_status(scsi_io, scsi_status);
477 #endif // SATI_TRANSPORT_SUPPORTS_SAS
478 }
479 
480 /**
481  * @brief This method extract response code based on on device settings.
482  *
483  * @return response code
484  */
485 static
486 U8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence)
487 {
488     if (sequence->device->descriptor_sense_enable)
489     {
490        return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE;
491     }
492     else
493     {
494        return SCSI_FIXED_CURRENT_RESPONSE_CODE;
495     }
496 }
497 
498 /**
499  * @brief This method will return length of descriptor sense data for executed command.
500  *
501  * @return sense data length
502  */
503 static
504 U8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence,
505         void * scsi_io)
506 {
507     U8 * cdb = sati_cb_get_cdb_address(scsi_io);
508     //Initial value is descriptor header length
509     U8 length = 8;
510 
511     switch (sati_get_cdb_byte(cdb, 0))
512     {
513 #if !defined(DISABLE_SATI_WRITE_LONG)
514     case SCSI_WRITE_LONG_10:
515     case SCSI_WRITE_LONG_16:
516         length += SCSI_BLOCK_DESCRIPTOR_LENGTH +
517             SCSI_INFORMATION_DESCRIPTOR_LENGTH;
518         break;
519 #endif // !defined(DISABLE_SATI_WRITE_LONG)
520 #if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
521     case SCSI_REASSIGN_BLOCKS:
522         length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH +
523             SCSI_INFORMATION_DESCRIPTOR_LENGTH;
524         break;
525 #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
526     case SCSI_READ_6:
527     case SCSI_READ_10:
528     case SCSI_READ_12:
529     case SCSI_READ_16:
530     case SCSI_WRITE_6:
531     case SCSI_WRITE_10:
532     case SCSI_WRITE_12:
533     case SCSI_WRITE_16:
534 #if !defined(DISABLE_SATI_VERIFY)
535     case SCSI_VERIFY_10:
536     case SCSI_VERIFY_12:
537     case SCSI_VERIFY_16:
538 #endif // !defined(DISABLE_SATI_VERIFY)
539 #if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
540     && !defined(DISABLE_SATI_VERIFY)            \
541     && !defined(DISABLE_SATI_WRITE)
542 
543     case SCSI_WRITE_AND_VERIFY_10:
544     case SCSI_WRITE_AND_VERIFY_12:
545     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  */
561 U8 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  */
604 void 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  */
647 static
648 void 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  */
676 static
677 void 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  */
713 static
714 void 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  */
749 static
750 void 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  */
848 void 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  */
904 void 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,  0);
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 */
969 static
970 void 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,  0);
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  */
1019 static
1020 void 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 */
1068 static
1069 void 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 */
1139 static
1140 void 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 
1185 void 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 */
1240 static
1241 void 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 */
1310 static
1311 void 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 
1357 void 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  */
1399 void 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  */
1431 void 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  */
1459 void 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  */
1490 void 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  */
1521 void 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  */
1547 void 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  */
1576 void 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  */
1600 void 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  */
1630 void 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  */
1659 void 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  */
1691 void 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  */
1716 void 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  */
1744 void 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  */
1770 void 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  */
1799 void 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  */
1820 void 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  */
1848 void 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 */
1881 BOOL 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 */
1912 void 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 */
1937 void 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 */
1970 void 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