xref: /freebsd/sys/dev/isci/scil/sati_util.c (revision 0957b409)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3  *
4  * This file is provided under a dual BSD/GPLv2 license.  When using or
5  * redistributing this file, you may do so under either license.
6  *
7  * GPL LICENSE SUMMARY
8  *
9  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of version 2 of the GNU General Public License as
13  * published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23  * The full GNU General Public License is included in this distribution
24  * in the file called LICENSE.GPL.
25  *
26  * BSD LICENSE
27  *
28  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  *
35  *   * Redistributions of source code must retain the above copyright
36  *     notice, this list of conditions and the following disclaimer.
37  *   * Redistributions in binary form must reproduce the above copyright
38  *     notice, this list of conditions and the following disclaimer in
39  *     the documentation and/or other materials provided with the
40  *     distribution.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53  */
54 
55 #include <sys/cdefs.h>
56 __FBSDID("$FreeBSD$");
57 
58 /**
59  * @file
60  * @brief This file contains all of the method implementations that
61  *        provide generic support for SATI.  Some methods can be utilized
62  *        by a user to construct ATA/ATAPI commands, copy ATA device
63  *        structure data, fill in sense data, etc.
64  */
65 
66 #include <dev/isci/scil/sati_util.h>
67 #include <dev/isci/scil/sati_callbacks.h>
68 #include <dev/isci/scil/intel_scsi.h>
69 #include <dev/isci/scil/intel_ata.h>
70 #include <dev/isci/scil/intel_sat.h>
71 #include <dev/isci/scil/intel_sas.h>
72 
73 /**
74  * @brief This method will set the data direction, protocol, and transfer
75  *        kength for an ATA non-data command.
76  *
77  * @pre It is expected that the user will use this method for setting these
78  *      values in a non-data ATA command constuct.
79  *
80  * @param[out] ata_io This parameter specifies the ATA IO request structure
81  *             for which to build the IDENTIFY DEVICE command.
82  * @param[in]  sequence This parameter specifies the translator sequence
83  *             for which the command is being constructed.
84  *
85  * @return none.
86  */
87 void sati_ata_non_data_command(
88    void                        * ata_io,
89    SATI_TRANSLATOR_SEQUENCE_T  * sequence
90 )
91 {
92    sequence->data_direction      = SATI_DATA_DIRECTION_NONE;
93    sequence->protocol            = SAT_PROTOCOL_NON_DATA;
94    sequence->ata_transfer_length = 0;
95 }
96 
97 /**
98  * @brief This method will construct the ATA identify device command.
99  *
100  * @pre It is expected that the user has properly set the current contents
101  *      of the register FIS to 0.
102  *
103  * @param[out] ata_io This parameter specifies the ATA IO request structure
104  *             for which to build the IDENTIFY DEVICE command.
105  * @param[in]  sequence This parameter specifies the translator sequence
106  *             for which the command is being constructed.
107  *
108  * @return none.
109  */
110 void sati_ata_identify_device_construct(
111    void                       * ata_io,
112    SATI_TRANSLATOR_SEQUENCE_T * sequence
113 )
114 {
115    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
116 
117    sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE);
118    sequence->data_direction      = SATI_DATA_DIRECTION_IN;
119    sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
120    sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T);
121 }
122 
123 /**
124 * @brief This method will construct the ATA Execute Device Diagnostic command.
125 *
126 * @param[out] ata_io This parameter specifies the ATA IO request structure
127 *             for which to build the IDENTIFY DEVICE command.
128 * @param[in]  sequence This parameter specifies the translator sequence
129 *             for which the command is being constructed.
130 *
131 * @return none.
132 */
133 void sati_ata_execute_device_diagnostic_construct(
134    void                       * ata_io,
135    SATI_TRANSLATOR_SEQUENCE_T * sequence
136 )
137 {
138    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
139 
140    sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG);
141 
142    sequence->data_direction = SATI_DATA_DIRECTION_IN;
143    sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC;
144    sequence->ata_transfer_length = 16;
145 }
146 
147 /**
148  * @brief This method will set data bytes in the user data area.  If the
149  *        caller requests it, the data written will be forced to ascii
150  *        printable characters if it isn't already a printable character.
151  *        A printable character is considered to be >= 0x20 and <= 0x70.
152  *
153  * @param[in]  sequence This parameter specifies the translation sequence
154  *             for which to copy and swap the data.
155  * @param[out] destination_scsi_io This parameter specifies the SCSI IO
156  *             request containing the destination buffer into which to copy.
157  * @param[in]  destination_offset This parameter specifies the offset into
158  *             the data buffer where the information will be copied to.
159  * @param[in]  source_value This parameter specifies the value retrieved
160  *             from the source buffer that is to be copied into the user
161  *             buffer area.
162  * @param[in]  use_printable_chars This parameter indicates if the copy should
163  *             ensure that the value copied is considered an ASCII printable
164  *             character (e.g. A, B, " ", etc.).  These characters reside
165  *             in the 0x20 - 0x7E ASCII range.
166  *
167  * @return none
168  */
169 static
170 void sati_set_ascii_data_byte(
171    SATI_TRANSLATOR_SEQUENCE_T * sequence,
172    void                       * destination_scsi_io,
173    U32                          destination_offset,
174    U8                           source_value,
175    BOOL                         use_printable_chars
176 )
177 {
178    // if the user requests that the copied data be ascii printable, then
179    // default to " " (i.e. 0x20) for all non-ascii printable characters.
180    if((use_printable_chars == TRUE)
181      && ((source_value < 0x20) || (source_value > 0x7E)))
182    {
183       source_value = 0x20;
184    }
185 
186    sati_set_data_byte(
187       sequence, destination_scsi_io, destination_offset, source_value
188    );
189 }
190 
191 /**
192  * @brief This method performs a copy operation using an offset into the
193  *        source buffer, an offset into the destination buffer, and a length.
194  *        It will perform the byte swap from the 16-bit identify field
195  *        into the network byte order SCSI location.
196  *
197  * @param[in]  sequence This parameter specifies the translation sequence
198  *             for which to copy and swap the data.
199  * @param[out] destination_scsi_io This parameter specifies the SCSI IO
200  *             request containing the destination buffer into which to copy.
201  * @param[in]  destination_offset This parameter specifies the offset into
202  *             the data buffer where the information will be copied to.
203  * @param[in]  source_buffer This parameter specifies the source buffer from
204  *             which the data will be copied.
205  * @param[in]  source_offset This parameter specifies the offset into the
206  *             source buffer where the copy shall begin.
207  * @param[in]  length This parameter specifies the number of bytes to copy
208  *             during this operation.
209  * @param[in]  use_printable_chars This parameter indicates if the copy should
210  *             ensure that the value copied is considered an ASCII printable
211  *             character (e.g. A, B, " ", etc.).  These characters reside
212  *             in the 0x20 - 0x7E ASCII range.
213  *
214  * @return none
215  */
216 void sati_ata_identify_device_copy_data(
217    SATI_TRANSLATOR_SEQUENCE_T * sequence,
218    void                       * destination_scsi_io,
219    U32                          destination_offset,
220    U8                         * source_buffer,
221    U32                          source_offset,
222    U32                          length,
223    BOOL                         use_printable_chars
224 )
225 {
226    source_buffer += source_offset;
227    while (length > 0)
228    {
229       sati_set_ascii_data_byte(
230          sequence,
231          destination_scsi_io,
232          destination_offset,
233          *(source_buffer+1),
234          use_printable_chars
235       );
236 
237       sati_set_ascii_data_byte(
238          sequence,
239          destination_scsi_io,
240          destination_offset+1,
241          *source_buffer,
242          use_printable_chars
243       );
244 
245       destination_offset += 2;
246       source_buffer      += 2;
247       length             -= 2;
248    }
249 }
250 
251 /**
252  * @brief This method performs a copy operation using a source buffer,
253  *        an offset into the destination buffer, and a length.
254  *
255  * @param[in]  sequence This parameter specifies the translation sequence
256  *             for which to copy and swap the data.
257  * @param[out] destination_scsi_io This parameter specifies the SCSI IO
258  *             request containing the destination buffer into which to copy.
259  * @param[in]  destination_offset This parameter specifies the offset into
260  *             the data buffer where the information will be copied to.
261  * @param[in]  source_buffer This parameter specifies the source buffer from
262  *             which the data will be copied.
263  * @param[in]  length This parameter specifies the number of bytes to copy
264  *             during this operation.
265  *
266  * @return none
267  */
268 void sati_copy_data(
269    SATI_TRANSLATOR_SEQUENCE_T * sequence,
270    void                       * destination_scsi_io,
271    U32                          destination_offset,
272    U8                         * source_buffer,
273    U32                          length
274 )
275 {
276    while (length > 0)
277    {
278       sati_set_data_byte(
279          sequence, destination_scsi_io, destination_offset, *source_buffer
280       );
281 
282       destination_offset++;
283       source_buffer++;
284       length--;
285    }
286 }
287 
288 /**
289  * @brief This method extracts the Logical Block Address high and low 32-bit
290  *        values and the sector count 32-bit value from the ATA identify
291  *        device data.
292  *
293  * @param[in]  identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA
294  *             from which to extract the sector information.
295  * @param[out] lba_high This parameter specifies the upper 32 bits for the
296  *             number of logical block addresses for the device. The upper
297  *             16-bits should always be 0, since 48-bits of LBA is the most
298  *             supported by an ATA device.
299  * @param[out] lba_low This parameter specifies the lower 32 bits for the
300  *             number of logical block addresses for the device.
301  * @param[out] sector_size This parameter specifies the 32-bits of sector
302  *             size.  If the ATA device doesn't support reporting it's
303  *             sector size, then 512 bytes is utilized as the default value.
304  *
305  * @return none
306  */
307 void sati_ata_identify_device_get_sector_info(
308    ATA_IDENTIFY_DEVICE_DATA_T * identify,
309    U32                        * lba_high,
310    U32                        * lba_low,
311    U32                        * sector_size
312 )
313 {
314    // Calculate the values to be returned
315    // Calculation will be different if the SATA device supports
316    // 48-bit addressing.  Bit 10 of Word 86 of ATA Identify
317    if (identify->command_set_enabled1
318        & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE)
319    {
320       // This drive supports 48-bit addressing
321 
322       *lba_high  = identify->max_48bit_lba[7] << 24;
323       *lba_high |= identify->max_48bit_lba[6] << 16;
324       *lba_high |= identify->max_48bit_lba[5] << 8;
325       *lba_high |= identify->max_48bit_lba[4];
326 
327       *lba_low  = identify->max_48bit_lba[3] << 24;
328       *lba_low |= identify->max_48bit_lba[2] << 16;
329       *lba_low |= identify->max_48bit_lba[1] << 8;
330       *lba_low |= identify->max_48bit_lba[0];
331    }
332    else
333    {
334       // This device doesn't support 48-bit addressing
335       // Pull out the largest LBA from words 60 and 61.
336       *lba_high  = 0;
337       *lba_low   = identify->total_num_sectors[3] << 24;
338       *lba_low  |= identify->total_num_sectors[2] << 16;
339       *lba_low  |= identify->total_num_sectors[1] << 8;
340       *lba_low  |= identify->total_num_sectors[0];
341    }
342 
343    // If the ATA device reports its sector size (bit 12 of Word 106),
344    // then use that instead.
345    if (identify->physical_logical_sector_info
346        & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE)
347    {
348       *sector_size  = identify->words_per_logical_sector[3] << 24;
349       *sector_size |= identify->words_per_logical_sector[2] << 16;
350       *sector_size |= identify->words_per_logical_sector[1] << 8;
351       *sector_size |= identify->words_per_logical_sector[0];
352    }
353    else
354    {
355       // Default the sector size to 512 bytes
356       *sector_size = 512;
357    }
358 }
359 
360 /**
361  * @brief This method will construct the ATA check power mode command.
362  *
363  * @pre It is expected that the user has properly set the current contents
364  *      of the register FIS to 0.
365  *
366  * @param[out] ata_io This parameter specifies the ATA IO request structure
367  *             for which to build the CHECK POWER MODE command.
368  * @param[in]  sequence This parameter specifies the translator sequence
369  *             for which the command is being constructed.
370  *
371  * @return none.
372  */
373 void sati_ata_check_power_mode_construct(
374    void                       * ata_io,
375    SATI_TRANSLATOR_SEQUENCE_T * sequence
376 )
377 {
378    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
379 
380    sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE);
381    sati_ata_non_data_command(ata_io, sequence);
382 }
383 
384 /**
385  * @brief This method is utilized to set a specific byte in the sense
386  *        data area.  It will ensure that the supplied byte offset
387  *        isn't larger then the length of the requested sense data.
388  *
389  * @param[in] scsi_io This parameter specifies the user SCSI IO request
390  *            for which to set the sense data byte.
391  * @param[in] byte_offset This parameter specifies the byte offset into
392  *            the sense data buffer where the data should be written.
393  * @param[in] value This parameter specifies the 8-bit value to be written
394  *            into the sense data area.
395  *
396  * @return none
397  */
398 void sati_set_sense_data_byte(
399    U8  * sense_data,
400    U32   max_sense_data_len,
401    U32   byte_offset,
402    U8    value
403 )
404 {
405    // Ensure that we don't attempt to write past the end of the sense
406    // data buffer.
407    if (byte_offset < max_sense_data_len)
408       sense_data[byte_offset] = value;
409 }
410 
411 /**
412  * @brief This method will construct the common response IU in the user
413  *           request's response IU location.
414  *
415  * @param[out] rsp_iu This parameter specifies the user request's
416  *                response IU to be constructed.
417  * @param[in]  scsi_status This parameter specifies the SCSI status
418  *                value for the user's IO request.
419  * @param[in]  sense_data_length This parameter specifies the sense data
420  *                length for response IU.
421  * @param[in]  data_present The parameter specifies the specific
422  *                data present value for response IU.
423  *
424  * @return none
425  */
426 void sati_scsi_common_response_iu_construct(
427    SCI_SSP_RESPONSE_IU_T * rsp_iu,
428    U8                      scsi_status,
429    U8                      sense_data_length,
430    U8                      data_present
431 )
432 {
433    rsp_iu->sense_data_length[3] = sense_data_length;
434    rsp_iu->sense_data_length[2] = 0;
435    rsp_iu->sense_data_length[1] = 0;
436    rsp_iu->sense_data_length[0] = 0;
437    rsp_iu->status               = scsi_status;
438    rsp_iu->data_present         = data_present;
439 }
440 
441 /**
442  * @brief This method will construct the buffer for sense data
443  *        sense data buffer location.  Additionally, it will set the user's
444  *        SCSI status.
445  *
446  * @param[in,out] scsi_io This parameter specifies the user's IO request
447  *                for which to construct the buffer for sense data.
448  * @param[in]     scsi_status This parameter specifies the SCSI status
449  *                value for the user's IO request.
450  * @param[out]    sense_data This paramater
451  *
452  * @return none
453  */
454 static
455 void sati_scsi_get_sense_data_buffer(
456     SATI_TRANSLATOR_SEQUENCE_T      * sequence,
457     void                            * scsi_io,
458     U8                                scsi_status,
459     U8                             ** sense_data,
460     U32                             * sense_len)
461 {
462 #ifdef SATI_TRANSPORT_SUPPORTS_SAS
463    SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
464                                     sati_cb_get_response_iu_address(scsi_io);
465 
466    sati_scsi_common_response_iu_construct(
467       rsp_iu,
468       scsi_status,
469       sati_scsi_get_sense_data_length(sequence, scsi_io),
470       SCSI_RESPONSE_DATA_PRES_SENSE_DATA
471    );
472 
473    *sense_data                   = (U8*) rsp_iu->data;
474    *sense_len                    = SSP_RESPONSE_IU_MAX_DATA * 4;  // dwords to bytes
475 #else
476    *sense_data = sati_cb_get_sense_data_address(scsi_io);
477    *sense_len  = sati_cb_get_sense_data_length(scsi_io);
478    sati_cb_set_scsi_status(scsi_io, scsi_status);
479 #endif // SATI_TRANSPORT_SUPPORTS_SAS
480 }
481 
482 /**
483  * @brief This method extract response code based on on device settings.
484  *
485  * @return response code
486  */
487 static
488 U8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence)
489 {
490     if (sequence->device->descriptor_sense_enable)
491     {
492        return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE;
493     }
494     else
495     {
496        return SCSI_FIXED_CURRENT_RESPONSE_CODE;
497     }
498 }
499 
500 /**
501  * @brief This method will return length of descriptor sense data for executed command.
502  *
503  * @return sense data length
504  */
505 static
506 U8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence,
507         void * scsi_io)
508 {
509     U8 * cdb = sati_cb_get_cdb_address(scsi_io);
510     //Initial value is descriptor header length
511     U8 length = 8;
512 
513     switch (sati_get_cdb_byte(cdb, 0))
514     {
515 #if !defined(DISABLE_SATI_WRITE_LONG)
516     case SCSI_WRITE_LONG_10:
517     case SCSI_WRITE_LONG_16:
518         length += SCSI_BLOCK_DESCRIPTOR_LENGTH +
519             SCSI_INFORMATION_DESCRIPTOR_LENGTH;
520         break;
521 #endif // !defined(DISABLE_SATI_WRITE_LONG)
522 #if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
523     case SCSI_REASSIGN_BLOCKS:
524         length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH +
525             SCSI_INFORMATION_DESCRIPTOR_LENGTH;
526         break;
527 #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
528     case SCSI_READ_6:
529     case SCSI_READ_10:
530     case SCSI_READ_12:
531     case SCSI_READ_16:
532     case SCSI_WRITE_6:
533     case SCSI_WRITE_10:
534     case SCSI_WRITE_12:
535     case SCSI_WRITE_16:
536 #if !defined(DISABLE_SATI_VERIFY)
537     case SCSI_VERIFY_10:
538     case SCSI_VERIFY_12:
539     case SCSI_VERIFY_16:
540 #endif // !defined(DISABLE_SATI_VERIFY)
541 #if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
542     && !defined(DISABLE_SATI_VERIFY)            \
543     && !defined(DISABLE_SATI_WRITE)
544 
545     case SCSI_WRITE_AND_VERIFY_10:
546     case SCSI_WRITE_AND_VERIFY_12:
547     case SCSI_WRITE_AND_VERIFY_16:
548 #endif //    !defined(DISABLE_SATI_WRITE_AND_VERIFY)
549        // && !defined(DISABLE_SATI_VERIFY)
550        // && !defined(DISABLE_SATI_WRITE)
551         length += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
552         break;
553     }
554 
555     return length;
556 }
557 
558 /**
559  * @brief This method will return length of sense data.
560  *
561  * @return sense data length
562  */
563 U8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io)
564 {
565     U8 response_code;
566 
567     response_code = sati_scsi_get_sense_data_response_code(sequence);
568 
569     switch (response_code)
570     {
571     case SCSI_FIXED_CURRENT_RESPONSE_CODE:
572     case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
573         return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
574     break;
575     case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
576     case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
577         return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io);
578     break;
579     }
580 
581     return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
582 }
583 
584 /**
585  * @brief This method will construct the sense data buffer in the user's
586  *        sense data buffer location.  Additionally, it will set the user's
587  *        SCSI status.
588  *
589  * @param[in]     sequence This parameter specifies the translation sequence
590  *                for which to construct the sense data.
591  * @param[in,out] scsi_io This parameter specifies the user's IO request
592  *                for which to construct the sense data.
593  * @param[in]     scsi_status This parameter specifies the SCSI status
594  *                value for the user's IO request.
595  * @param[in]     sense_key This parameter specifies the sense key to
596  *                be set for the user's IO request.
597  * @param[in]     additional_sense_code This parameter specifies the
598  *                additional sense code (ASC) key to be set for the user's
599  *                IO request.
600  * @param[in]     additional_sense_code_qualifier This parameter specifies
601  *                the additional sense code qualifier (ASCQ) key to be set
602  *                for the user's IO request.
603  *
604  * @return none
605  */
606 void sati_scsi_sense_data_construct(
607    SATI_TRANSLATOR_SEQUENCE_T * sequence,
608    void                       * scsi_io,
609    U8                           scsi_status,
610    U8                           sense_key,
611    U8                           additional_sense_code,
612    U8                           additional_sense_code_qualifier
613 )
614 {
615     U8 response_code;
616 
617     response_code = sati_scsi_get_sense_data_response_code(sequence);
618 
619     switch (response_code)
620     {
621     case SCSI_FIXED_CURRENT_RESPONSE_CODE:
622     case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
623     sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
624                 sense_key, additional_sense_code, additional_sense_code_qualifier);
625     break;
626     case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
627     case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
628         sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
629                 sense_key, additional_sense_code, additional_sense_code_qualifier);
630         break;
631     }
632 
633     sequence->is_sense_response_set = TRUE;
634 }
635 
636 /**
637  * @brief This method will construct the block descriptor in the user's descriptor
638  *            sense data buffer location.
639  *
640  * @param[in]     sense_data This parameter specifies the user SCSI IO request
641  *                for which to set the sense data byte.
642  * @param[in]     sense_len This parameter specifies length of the sense data
643  *                to be returned by SATI.
644  * @param[out]    descriptor_len This parameter returns the length of constructed
645  *                descriptor.
646  *
647  * @return none
648  */
649 static
650 void sati_scsi_block_descriptor_construct(
651         U8 * sense_data,
652         U32 sense_len)
653 {
654     U8 ili = 1;
655 
656     sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_BLOCK_DESCRIPTOR_TYPE);
657     sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH);
658     sati_set_sense_data_byte(sense_data, sense_len, 2,  0);
659     sati_set_sense_data_byte(sense_data, sense_len, 3,  (ili << 5));
660 }
661 
662 /**
663  * @brief This method will construct the command-specific descriptor for
664  *           the descriptor sense data buffer in the user's sense data buffer
665  *           location.
666  *
667  * @param[in]     sense_data This parameter specifies the user SCSI IO request
668  *                for which to set the sense data byte.
669  * @param[in]     sense_len This parameter specifies length of the sense data
670  *                to be returned by SATI.
671  * @param[out]    descriptor_len This parameter returns the length of constructed
672  *                descriptor.
673  * @param[in]     information_buff This parameter specifies the address for which
674  *                to set the command-specific information buffer.
675  *
676  * @return none
677  */
678 static
679 void sati_scsi_command_specific_descriptor_construct(
680     U8       * sense_data,
681     U32        sense_len,
682     U8       * information_buff)
683 {
684     U8 i;
685 
686     sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE);
687     sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH);
688     sati_set_sense_data_byte(sense_data, sense_len, 2,  0);
689     sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
690 
691     // fill information buffer
692     // SBC 5.20.1 REASSIGN BLOCKS command overview
693     // If information about the first LBA not reassigned is not available
694     // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh
695     for (i=0; i<8; i++)
696         sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]);
697 }
698 
699 /**
700  * @brief This method will construct the information descriptor for
701  *           the descriptor sense data buffer in the user's sense data buffer
702  *           location.
703  *
704  * @param[in]     sense_data This parameter specifies the user SCSI IO request
705  *                for which to set the sense data byte.
706  * @param[in]     sense_len This parameter specifies length of the sense data
707  *                to be returned by SATI.
708  * @param[out]    descriptor_len This parameter returns the length of constructed
709  *                descriptor.
710  * @param[in]     information_buff This parameter specifies the address for which
711  *                to set the information buffer.
712  *
713  * @return none
714  */
715 static
716 void sati_scsi_information_descriptor_construct(
717     U8      * sense_data,
718     U32       sense_len,
719     U8      * information_buff)
720 {
721     U8 i;
722     U8 valid = 1;
723 
724     sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_INFORMATION_DESCRIPTOR_TYPE);
725     sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH);
726     sati_set_sense_data_byte(sense_data, sense_len, 2,  (valid << 7));
727     sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
728 
729     // fill information buffer
730     for (i=0; i<8; i++)
731         sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]);
732 }
733 
734 /**
735  * @brief This method will construct the descriptors in the user's descriptor
736  *           sense data buffer location.
737  *
738  * @param[in,out] scsi_io This parameter specifies the user's IO request
739  *                for which to construct the sense data.
740  * @param[in]     sense_data This parameter specifies the user SCSI IO request
741  *                for which to set the sense data byte.
742  * @param[in]     sense_len This parameter specifies length of the sense data
743  *                to be returned by SATI.
744  * @param[out]    descriptor_len This parameter returns the length of constructed
745  *                descriptor.
746  * @param[in]     information_buff This parameter specifies the address for which
747  *                to set the information buffer.
748  *
749  * @return none
750  */
751 static
752 void sati_scsi_common_descriptors_construct(
753     void    * scsi_io,
754     U8      * sense_data,
755     U32       sense_len,
756     U8      * information_buff)
757 {
758     U8 * cdb = sati_cb_get_cdb_address(scsi_io);
759     U8 offset = 0;
760 
761     switch (sati_get_cdb_byte(cdb, 0))
762     {
763 #if !defined(DISABLE_SATI_WRITE_LONG)
764     case SCSI_WRITE_LONG_10:
765     case SCSI_WRITE_LONG_16:
766         sati_scsi_block_descriptor_construct(
767                 sense_data + offset,
768                 sense_len - offset);
769 
770         offset += SCSI_BLOCK_DESCRIPTOR_LENGTH;
771         sati_scsi_information_descriptor_construct(
772                   sense_data + offset,
773                   sense_len - offset,
774                   information_buff);
775 
776         offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
777         break;
778 #endif // !defined(DISABLE_SATI_WRITE_LONG)
779 #if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
780     case SCSI_REASSIGN_BLOCKS:
781         sati_scsi_command_specific_descriptor_construct(
782           sense_data + offset,
783           sense_len - offset,
784           NULL);
785 
786         offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH;
787         sati_scsi_information_descriptor_construct(
788                   sense_data + offset,
789                   sense_len - offset,
790                   information_buff);
791 
792         offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
793         break;
794 #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
795     case SCSI_READ_6:
796     case SCSI_READ_10:
797     case SCSI_READ_12:
798     case SCSI_READ_16:
799     case SCSI_WRITE_6:
800     case SCSI_WRITE_10:
801     case SCSI_WRITE_12:
802     case SCSI_WRITE_16:
803 #if !defined(DISABLE_SATI_VERIFY)
804     case SCSI_VERIFY_10:
805     case SCSI_VERIFY_12:
806     case SCSI_VERIFY_16:
807 #endif // !defined(DISABLE_SATI_VERIFY)
808 #if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
809     && !defined(DISABLE_SATI_VERIFY)            \
810     && !defined(DISABLE_SATI_WRITE)
811 
812     case SCSI_WRITE_AND_VERIFY_10:
813     case SCSI_WRITE_AND_VERIFY_12:
814     case SCSI_WRITE_AND_VERIFY_16:
815 #endif //    !defined(DISABLE_SATI_WRITE_AND_VERIFY)
816        // && !defined(DISABLE_SATI_VERIFY)
817        // && !defined(DISABLE_SATI_WRITE)
818         sati_scsi_information_descriptor_construct(
819                   sense_data + offset,
820                   sense_len - offset,
821                   information_buff);
822 
823         offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
824         break;
825     }
826 }
827 
828 /**
829  * @brief This method will construct the descriptor sense data buffer in
830  *           the user's sense data buffer location.  Additionally, it will set
831  *           the user's SCSI status.
832  *
833  * @param[in]     sequence This parameter specifies the translation sequence
834  *                for which to construct the sense data.
835  * @param[in,out] scsi_io This parameter specifies the user's IO request
836  *                for which to construct the sense data.
837  * @param[in]     scsi_status This parameter specifies the SCSI status
838  *                value for the user's IO request.
839  * @param[in]     sense_key This parameter specifies the sense key to
840  *                be set for the user's IO request.
841  * @param[in]     additional_sense_code This parameter specifies the
842  *                additional sense code (ASC) key to be set for the user's
843  *                IO request.
844  * @param[in]     additional_sense_code_qualifier This parameter specifies
845  *                the additional sense code qualifier (ASCQ) key to be set
846  *                for the user's IO request.
847  *
848  * @return none
849  */
850 void sati_scsi_descriptor_sense_data_construct(
851    SATI_TRANSLATOR_SEQUENCE_T * sequence,
852    void                       * scsi_io,
853    U8                           scsi_status,
854    U8                           response_code,
855    U8                           sense_key,
856    U8                           additional_sense_code,
857    U8                           additional_sense_code_qualifier
858 )
859 {
860    U8 * sense_data;
861    U32    sense_len;
862 
863    sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
864 
865    sati_set_sense_data_byte(
866       sense_data,
867       sense_len,
868       0,
869       response_code
870    );
871 
872    sati_set_sense_data_byte(sense_data, sense_len, 1,  sense_key);
873    sati_set_sense_data_byte(sense_data, sense_len, 2,  additional_sense_code);
874    sati_set_sense_data_byte(sense_data, sense_len, 3,  additional_sense_code_qualifier);
875    sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
876    sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
877    sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
878 
879    sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL);
880 
881    sati_set_sense_data_byte(sense_data, sense_len, 7,  sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
882 }
883 
884 /**
885  * @brief This method will construct the fixed format sense data buffer
886  *           in the user's sense data buffer location.  Additionally, it will
887  *          set the user's SCSI status.
888  *
889  * @param[in]     sequence This parameter specifies the translation sequence
890  *                for which to construct the sense data.
891  * @param[in,out] scsi_io This parameter specifies the user's IO request
892  *                for which to construct the sense data.
893  * @param[in]     scsi_status This parameter specifies the SCSI status
894  *                value for the user's IO request.
895  * @param[in]     sense_key This parameter specifies the sense key to
896  *                be set for the user's IO request.
897  * @param[in]     additional_sense_code This parameter specifies the
898  *                additional sense code (ASC) key to be set for the user's
899  *                IO request.
900  * @param[in]     additional_sense_code_qualifier This parameter specifies
901  *                the additional sense code qualifier (ASCQ) key to be set
902  *                for the user's IO request.
903  *
904  * @return none
905  */
906 void sati_scsi_fixed_sense_data_construct(
907    SATI_TRANSLATOR_SEQUENCE_T * sequence,
908    void                       * scsi_io,
909    U8                           scsi_status,
910    U8                           response_code,
911    U8                           sense_key,
912    U8                           additional_sense_code,
913    U8                           additional_sense_code_qualifier
914 )
915 {
916     U8 * sense_data;
917     U32  sense_len;
918 
919     sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
920 
921     // Write out the sense data format per SPC-4.
922     // We utilize the fixed format sense data format.
923 
924     sati_set_sense_data_byte(
925       sense_data,
926       sense_len,
927       0,
928       response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT
929     );
930 
931     sati_set_sense_data_byte(sense_data, sense_len, 1,  0);
932     sati_set_sense_data_byte(sense_data, sense_len, 2,  sense_key);
933     sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
934     sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
935     sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
936     sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
937     sati_set_sense_data_byte(sense_data, sense_len, 7,  (sense_len < 18 ? sense_len - 1 : 17) - 7);
938     sati_set_sense_data_byte(sense_data, sense_len, 8,  0);
939     sati_set_sense_data_byte(sense_data, sense_len, 9,  0);
940     sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
941     sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
942     sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
943     sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
944     sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
945     sati_set_sense_data_byte(sense_data, sense_len, 15, 0);
946     sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
947     sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
948 }
949 
950 /**
951 * @brief This method will construct common sense data that will be identical in
952 *        both read error sense construct functions.
953 *        sati_scsi_read_ncq_error_sense_construct,
954 *        sati_scsi_read_error_sense_construct
955 *
956  * @param[in]    sense_data This parameter specifies the user SCSI IO request
957  *               for which to set the sense data byte.
958 * @param[in]     sense_len This parameter specifies length of the sense data
959 *                to be returned by SATI.
960 * @param[in]     sense_key This parameter specifies the sense key to
961 *                be set for the user's IO request.
962 * @param[in]     additional_sense_code This parameter specifies the
963 *                additional sense code (ASC) key to be set for the user's
964 *                IO request.
965 * @param[in]     additional_sense_code_qualifier This parameter specifies
966 *                the additional sense code qualifier (ASCQ) key to be set
967 *                for the user's IO request.
968 *
969 * @return none
970 */
971 static
972 void sati_scsi_common_fixed_sense_construct(
973    U8                         * sense_data,
974    U32                          sense_len,
975    U8                           sense_key,
976    U8                           additional_sense_code,
977    U8                           additional_sense_code_qualifier
978 )
979 {
980 
981    sati_set_sense_data_byte(sense_data, sense_len, 1,  0);
982    sati_set_sense_data_byte(sense_data, sense_len, 2,  sense_key);
983 
984    //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions
985 
986    sati_set_sense_data_byte(sense_data, sense_len, 7,  (sense_len < 18 ? sense_len - 1 : 17) - 7);
987    sati_set_sense_data_byte(sense_data, sense_len, 8,  0);
988    sati_set_sense_data_byte(sense_data, sense_len, 9,  0);
989    sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
990    sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
991    sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
992    sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
993    sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
994    sati_set_sense_data_byte(sense_data, sense_len, 15, 0x80);
995    sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
996    sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
997 }
998 
999 /**
1000  * @brief This method will construct the descriptor sense data buffer in
1001  *           the user's sense data buffer location.  Additionally, it will set
1002  *           the user's SCSI status.
1003  *
1004  * @param[in]     sequence This parameter specifies the translation sequence
1005  *                for which to construct the sense data.
1006  * @param[in,out] scsi_io This parameter specifies the user's IO request
1007  *                for which to construct the sense data.
1008  * @param[in]     scsi_status This parameter specifies the SCSI status
1009  *                value for the user's IO request.
1010  * @param[in]     sense_key This parameter specifies the sense key to
1011  *                be set for the user's IO request.
1012  * @param[in]     additional_sense_code This parameter specifies the
1013  *                additional sense code (ASC) key to be set for the user's
1014  *                IO request.
1015  * @param[in]     additional_sense_code_qualifier This parameter specifies
1016  *                the additional sense code qualifier (ASCQ) key to be set
1017  *                for the user's IO request.
1018  *
1019  * @return none
1020  */
1021 static
1022 void sati_scsi_common_descriptor_sense_construct(
1023     SATI_TRANSLATOR_SEQUENCE_T * sequence,
1024     void                       * scsi_io,
1025     U8                         * sense_data,
1026     U32                          sense_len,
1027     U8                           sense_key,
1028     U8                           additional_sense_code,
1029     U8                           additional_sense_code_qualifier,
1030     U8                         * information_buff
1031 )
1032 {
1033     sati_set_sense_data_byte(sense_data, sense_len, 1,  sense_key);
1034     sati_set_sense_data_byte(sense_data, sense_len, 2,  additional_sense_code);
1035     sati_set_sense_data_byte(sense_data, sense_len, 3,  additional_sense_code_qualifier);
1036     sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
1037     sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
1038     sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
1039 
1040     sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff);
1041 
1042     sati_set_sense_data_byte(sense_data, sense_len, 7,  sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
1043 }
1044 
1045 /**
1046 * @brief This method will construct the sense data buffer in the user's
1047 *        descriptor sense data buffer location.  Additionally, it will set
1048 *        the user's SCSI status. This is only used for NCQ uncorrectable
1049 *        read errors
1050 *
1051 * @param[in]     sequence This parameter specifies the translation sequence
1052 *                for which to construct the sense data.
1053 * @param[in,out] scsi_io This parameter specifies the user's IO request
1054 *                for which to construct the sense data.
1055 * @param[in]     ata_input_data This parameter specifies the user's ATA IO
1056 *                response from a Read Log Ext command.
1057 * @param[in]     scsi_status This parameter specifies the SCSI status
1058 *                value for the user's IO request.
1059 * @param[in]     sense_key This parameter specifies the sense key to
1060 *                be set for the user's IO request.
1061 * @param[in]     additional_sense_code This parameter specifies the
1062 *                additional sense code (ASC) key to be set for the user's
1063 *                IO request.
1064 * @param[in]     additional_sense_code_qualifier This parameter specifies
1065 *                the additional sense code qualifier (ASCQ) key to be set
1066 *                for the user's IO request.
1067 *
1068 * @return none
1069 */
1070 static
1071 void sati_scsi_read_ncq_error_descriptor_sense_construct(
1072    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1073    void                       * scsi_io,
1074    void                       * ata_input_data,
1075    U8                           scsi_status,
1076    U8                           response_code,
1077    U8                           sense_key,
1078    U8                           additional_sense_code,
1079    U8                           additional_sense_code_qualifier
1080 )
1081 {
1082    U8 * sense_data;
1083    U32  sense_len;
1084 
1085    U8 information_buff[8] = {0};
1086 
1087    ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
1088 
1089    sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1090 
1091    sati_set_sense_data_byte(
1092       sense_data,
1093       sense_len,
1094       0,
1095       response_code
1096    );
1097 
1098    information_buff[2] = ncq_log->lba_47_40;
1099    information_buff[3] = ncq_log->lba_39_32;
1100    information_buff[4] = ncq_log->lba_31_24;
1101    information_buff[5] = ncq_log->lba_23_16;
1102    information_buff[6] = ncq_log->lba_15_8;
1103    information_buff[7] = ncq_log->lba_7_0;
1104 
1105    sati_scsi_common_descriptor_sense_construct(
1106            sequence,
1107            scsi_io,
1108            sense_data,
1109            sense_len,
1110            sense_key,
1111            additional_sense_code,
1112            additional_sense_code_qualifier,
1113            information_buff
1114    );
1115 }
1116 
1117 /**
1118 * @brief This method will construct the sense data buffer in the user's
1119 *        sense data buffer location.  Additionally, it will set the user's
1120 *        SCSI status. This is only used for NCQ uncorrectable read errors
1121 *
1122 * @param[in]     sequence This parameter specifies the translation sequence
1123 *                for which to construct the sense data.
1124 * @param[in,out] scsi_io This parameter specifies the user's IO request
1125 *                for which to construct the sense data.
1126 * @param[in]     ata_input_data This parameter specifies the user's ATA IO
1127 *                response from a Read Log Ext command.
1128 * @param[in]     scsi_status This parameter specifies the SCSI status
1129 *                value for the user's IO request.
1130 * @param[in]     sense_key This parameter specifies the sense key to
1131 *                be set for the user's IO request.
1132 * @param[in]     additional_sense_code This parameter specifies the
1133 *                additional sense code (ASC) key to be set for the user's
1134 *                IO request.
1135 * @param[in]     additional_sense_code_qualifier This parameter specifies
1136 *                the additional sense code qualifier (ASCQ) key to be set
1137 *                for the user's IO request.
1138 *
1139 * @return none
1140 */
1141 static
1142 void sati_scsi_read_ncq_error_fixed_sense_construct(
1143    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1144    void                       * scsi_io,
1145    void                       * ata_input_data,
1146    U8                           scsi_status,
1147    U8                           response_code,
1148    U8                           sense_key,
1149    U8                           additional_sense_code,
1150    U8                           additional_sense_code_qualifier
1151 )
1152 {
1153    U8 * sense_data;
1154    U32  sense_len;
1155    U8   valid = TRUE;
1156 
1157    ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
1158 
1159    sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1160 
1161    if(ncq_log->lba_39_32 > 0)
1162    {
1163       valid = FALSE;
1164    }
1165 
1166    sati_set_sense_data_byte(
1167       sense_data,
1168       sense_len,
1169       0,
1170       (valid << 7) | response_code
1171    );
1172 
1173    sati_set_sense_data_byte(sense_data, sense_len, 3,  ncq_log->lba_31_24);
1174    sati_set_sense_data_byte(sense_data, sense_len, 4,  ncq_log->lba_23_16);
1175    sati_set_sense_data_byte(sense_data, sense_len, 5,  ncq_log->lba_15_8);
1176    sati_set_sense_data_byte(sense_data, sense_len, 6,  ncq_log->lba_7_0);
1177 
1178    sati_scsi_common_fixed_sense_construct(
1179       sense_data,
1180       sense_len,
1181       sense_key,
1182       additional_sense_code,
1183       additional_sense_code_qualifier
1184    );
1185 }
1186 
1187 void sati_scsi_read_ncq_error_sense_construct(
1188    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1189    void                       * scsi_io,
1190    void                       * ata_input_data,
1191    U8                           scsi_status,
1192    U8                           sense_key,
1193    U8                           additional_sense_code,
1194    U8                           additional_sense_code_qualifier
1195 )
1196 {
1197     U8 response_code;
1198 
1199     response_code = sati_scsi_get_sense_data_response_code(sequence);
1200 
1201     switch (response_code)
1202     {
1203     case SCSI_FIXED_CURRENT_RESPONSE_CODE:
1204     case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
1205         sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1206                 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1207     break;
1208     case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
1209     case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
1210         sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1211                 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1212         break;
1213     }
1214 
1215     sequence->is_sense_response_set = TRUE;
1216 }
1217 
1218 /**
1219 * @brief This method will construct the sense data buffer in the user's
1220 *        sense data buffer location.  Additionally, it will set the user's
1221 *        SCSI status. This is used for uncorrectable read errors.
1222 *
1223 * @param[in]     sequence This parameter specifies the translation sequence
1224 *                for which to construct the sense data.
1225 * @param[in,out] scsi_io This parameter specifies the user's IO request
1226 *                for which to construct the sense data.
1227 * @param[in]     ata_io This parameter is a pointer to the ATA IO data used
1228 *                to get the ATA register fis.
1229 * @param[in]     scsi_status This parameter specifies the SCSI status
1230 *                value for the user's IO request.
1231 * @param[in]     sense_key This parameter specifies the sense key to
1232 *                be set for the user's IO request.
1233 * @param[in]     additional_sense_code This parameter specifies the
1234 *                additional sense code (ASC) key to be set for the user's
1235 *                IO request.
1236 * @param[in]     additional_sense_code_qualifier This parameter specifies
1237 *                the additional sense code qualifier (ASCQ) key to be set
1238 *                for the user's IO request.
1239 *
1240 * @return none
1241 */
1242 static
1243 void sati_scsi_read_error_descriptor_sense_construct(
1244    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1245    void                       * scsi_io,
1246    void                       * ata_io,
1247    U8                           scsi_status,
1248    U8                           response_code,
1249    U8                           sense_key,
1250    U8                           additional_sense_code,
1251    U8                           additional_sense_code_qualifier
1252 )
1253 {
1254    U8 * sense_data;
1255    U32  sense_len;
1256    U8 information_buff[8] = {0};
1257 
1258    U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
1259 
1260    sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1261 
1262    information_buff[2] = sati_get_ata_lba_high_ext(register_fis);
1263    information_buff[3] = sati_get_ata_lba_mid_ext(register_fis);
1264    information_buff[4] = sati_get_ata_lba_low_ext(register_fis);
1265    information_buff[5] = sati_get_ata_lba_high(register_fis);
1266    information_buff[6] = sati_get_ata_lba_mid(register_fis);
1267    information_buff[7] = sati_get_ata_lba_low(register_fis);
1268 
1269    sati_set_sense_data_byte(
1270       sense_data,
1271       sense_len,
1272       0,
1273       SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE
1274    );
1275 
1276    sati_scsi_common_descriptor_sense_construct(
1277       sequence,
1278       scsi_io,
1279       sense_data,
1280       sense_len,
1281       sense_key,
1282       additional_sense_code,
1283       additional_sense_code_qualifier,
1284       information_buff
1285    );
1286 }
1287 
1288 /**
1289 * @brief This method will construct the sense data buffer in the user's
1290 *        sense data buffer location.  Additionally, it will set the user's
1291 *        SCSI status. This is used for uncorrectable read errors.
1292 *
1293 * @param[in]     sequence This parameter specifies the translation sequence
1294 *                for which to construct the sense data.
1295 * @param[in,out] scsi_io This parameter specifies the user's IO request
1296 *                for which to construct the sense data.
1297 * @param[in]     ata_io This parameter is a pointer to the ATA IO data used
1298 *                to get the ATA register fis.
1299 * @param[in]     scsi_status This parameter specifies the SCSI status
1300 *                value for the user's IO request.
1301 * @param[in]     sense_key This parameter specifies the sense key to
1302 *                be set for the user's IO request.
1303 * @param[in]     additional_sense_code This parameter specifies the
1304 *                additional sense code (ASC) key to be set for the user's
1305 *                IO request.
1306 * @param[in]     additional_sense_code_qualifier This parameter specifies
1307 *                the additional sense code qualifier (ASCQ) key to be set
1308 *                for the user's IO request.
1309 *
1310 * @return none
1311 */
1312 static
1313 void sati_scsi_read_error_fixed_sense_construct(
1314    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1315    void                       * scsi_io,
1316    void                       * ata_io,
1317    U8                           scsi_status,
1318    U8                           response_code,
1319    U8                           sense_key,
1320    U8                           additional_sense_code,
1321    U8                           additional_sense_code_qualifier
1322 )
1323 {
1324    U8 * sense_data;
1325    U32  sense_len;
1326    U8   valid = TRUE;
1327 
1328    U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
1329 
1330    sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1331 
1332    if(sati_get_ata_lba_mid_ext(register_fis) > 0)
1333    {
1334       valid = FALSE;
1335    }
1336 
1337    sati_set_sense_data_byte(sense_data, sense_len, 3,  sati_get_ata_lba_low_ext(register_fis));
1338    sati_set_sense_data_byte(sense_data, sense_len, 4,  sati_get_ata_lba_high(register_fis));
1339    sati_set_sense_data_byte(sense_data, sense_len, 5,  sati_get_ata_lba_mid(register_fis));
1340    sati_set_sense_data_byte(sense_data, sense_len, 6,  sati_get_ata_lba_low(register_fis));
1341 
1342 
1343    sati_set_sense_data_byte(
1344       sense_data,
1345       sense_len,
1346       0,
1347       (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE
1348    );
1349 
1350    sati_scsi_common_fixed_sense_construct(
1351       sense_data,
1352       sense_len,
1353       sense_key,
1354       additional_sense_code,
1355       additional_sense_code_qualifier
1356    );
1357 }
1358 
1359 void sati_scsi_read_error_sense_construct(
1360    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1361    void                       * scsi_io,
1362    void                       * ata_input_data,
1363    U8                           scsi_status,
1364    U8                           sense_key,
1365    U8                           additional_sense_code,
1366    U8                           additional_sense_code_qualifier
1367 )
1368 {
1369     U8 response_code;
1370 
1371     response_code = sati_scsi_get_sense_data_response_code(sequence);
1372 
1373     switch (response_code)
1374     {
1375     case SCSI_FIXED_CURRENT_RESPONSE_CODE:
1376     case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
1377         sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1378                 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1379     break;
1380     case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
1381     case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
1382         sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1383                 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1384         break;
1385     }
1386 
1387     sequence->is_sense_response_set = TRUE;
1388 }
1389 
1390 /*
1391  * @brief This method builds the scsi response data for a sata task management
1392  *        request.
1393  *
1394  * @param[in]     sequence This parameter specifies the translation sequence
1395  *                for which to construct the sense data.
1396  * @param[in,out] scsi_io This parameter specifies the user's IO request
1397  *                for which to construct the sense data.
1398  * @param[in]     response_data The response status for the task management
1399  *                request.
1400  */
1401 void sati_scsi_response_data_construct(
1402    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1403    void                       * scsi_io,
1404    U8                           response_data
1405 )
1406 {
1407 #ifdef SATI_TRANSPORT_SUPPORTS_SAS
1408    SCI_SSP_RESPONSE_IU_T * rsp_iu  = (SCI_SSP_RESPONSE_IU_T*)
1409                                         sati_cb_get_response_iu_address(scsi_io);
1410    rsp_iu->data_present            = 0x01;
1411    rsp_iu->response_data_length[3] = sizeof(U32);
1412    rsp_iu->status                  = 0;
1413    ((U8 *)rsp_iu->data)[3]         = response_data;
1414 #else
1415 #endif // SATI_TRANSPORT_SUPPORTS_SAS
1416 }
1417 
1418 /**
1419  * @brief This method checks to make sure that the translation isn't
1420  *        exceeding the allocation length specified in the CDB prior
1421  *        to retrieving the payload data byte from the user's buffer.
1422  *
1423  * @param[in,out] scsi_io This parameter specifies the user's IO request
1424  *                for which to set the user payload data byte.
1425  * @param[in]     byte_offset This parameter specifies the offset into
1426  *                the user's payload buffer at which to write the supplied
1427  *                value.
1428  * @param[in]     value This parameter specifies the memory location into
1429  *                which to read the value from the user's payload buffer.
1430  *
1431  * @return none
1432  */
1433 void sati_get_data_byte(
1434    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1435    void                       * scsi_io,
1436    U32                          byte_offset,
1437    U8                         * value
1438 )
1439 {
1440    if (byte_offset < sequence->allocation_length)
1441       sati_cb_get_data_byte(scsi_io, byte_offset, value);
1442 }
1443 
1444 /**
1445  * @brief This method checks to make sure that the translation isn't
1446  *        exceeding the allocation length specified in the CDB while
1447  *        translating payload data into the user's buffer.
1448  *
1449  * @param[in]     sequence This parameter specifies the translation sequence
1450  *                for which to set the user payload data byte.
1451  * @param[in,out] scsi_io This parameter specifies the user's IO request
1452  *                for which to set the user payload data byte.
1453  * @param[in]     byte_offset This parameter specifies the offset into
1454  *                the user's payload buffer at which to write the supplied
1455  *                value.
1456  * @param[in]     value This parameter specifies the new value to be
1457  *                written out into the user's payload buffer.
1458  *
1459  * @return none
1460  */
1461 void sati_set_data_byte(
1462    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1463    void                       * scsi_io,
1464    U32                          byte_offset,
1465    U8                           value
1466 )
1467 {
1468    if (byte_offset < sequence->allocation_length)
1469    {
1470       sequence->number_data_bytes_set++;
1471       sati_cb_set_data_byte(scsi_io, byte_offset, value);
1472    }
1473 }
1474 
1475 /**
1476  * @brief This method checks to make sure that the translation isn't
1477  *        exceeding the allocation length specified in the CDB while
1478  *        translating payload data into the user's buffer.
1479  *
1480  * @param[in]     sequence This parameter specifies the translation sequence
1481  *                for which to set the user payload data dword.
1482  * @param[in,out] scsi_io This parameter specifies the user's IO request
1483  *                for which to set the user payload data dword.
1484  * @param[in]     byte_offset This parameter specifies the offset into
1485  *                the user's payload buffer at which to write the supplied
1486  *                value.
1487  * @param[in]     value This parameter specifies the new value to be
1488  *                written out into the user's payload buffer.
1489  *
1490  * @return none
1491  */
1492 void sati_set_data_dword(
1493    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1494    void                       * scsi_io,
1495    U32                          byte_offset,
1496    U32                          value
1497 )
1498 {
1499    /// @todo Check to ensure that the bytes appear correctly (SAS Address).
1500 
1501    sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF);
1502        byte_offset++;
1503    sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF);
1504        byte_offset++;
1505    sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF);
1506        byte_offset++;
1507    sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF);
1508 }
1509 
1510 /**
1511  * @brief This method will construct the ATA flush cache command.
1512  *
1513  * @pre It is expected that the user has properly set the current contents
1514  *      of the register FIS to 0.
1515  *
1516  * @param[out] ata_io This parameter specifies the ATA IO request structure
1517  *             for which to build the FLUSH CACHE command.
1518  * @param[in]  sequence This parameter specifies the translator sequence
1519  *             for which the command is being constructed.
1520  *
1521  * @return none.
1522  */
1523 void sati_ata_flush_cache_construct(
1524    void                       * ata_io,
1525    SATI_TRANSLATOR_SEQUENCE_T * sequence
1526 )
1527 {
1528    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1529 
1530    sati_set_ata_command(register_fis, ATA_FLUSH_CACHE);
1531    sati_ata_non_data_command(ata_io, sequence);
1532 }
1533 
1534 /**
1535  * @brief This method will construct the ATA standby immediate command.
1536  *
1537  * @pre It is expected that the user has properly set the current contents
1538  *      of the register FIS to 0.
1539  *
1540  * @param[out] ata_io This parameter specifies the ATA IO request structure
1541  *             for which to build the STANDBY IMMEDIATE command.
1542  * @param[in]  sequence This parameter specifies the translator sequence
1543  *             for which the command is being constructed.
1544  *
1545  * @param[in]  count This parameter specifies the time period programmed
1546  *             into the Standby Timer. See ATA8 spec for more details
1547  * @return none.
1548  */
1549 void sati_ata_standby_construct(
1550    void                       * ata_io,
1551    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1552    U16                          count
1553 )
1554 {
1555    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1556 
1557    sati_set_ata_command(register_fis, ATA_STANDBY);
1558    sati_set_ata_sector_count(register_fis, count);
1559 
1560    sequence->device->ata_standby_timer = (U8) count;
1561 
1562    sati_ata_non_data_command(ata_io, sequence);
1563 }
1564 
1565 /**
1566  * @brief This method will construct the ATA standby immediate command.
1567  *
1568  * @pre It is expected that the user has properly set the current contents
1569  *      of the register FIS to 0.
1570  *
1571  * @param[out] ata_io This parameter specifies the ATA IO request structure
1572  *             for which to build the STANDBY IMMEDIATE command.
1573  * @param[in]  sequence This parameter specifies the translator sequence
1574  *             for which the command is being constructed.
1575  *
1576  * @return none.
1577  */
1578 void sati_ata_standby_immediate_construct(
1579    void                       * ata_io,
1580    SATI_TRANSLATOR_SEQUENCE_T * sequence
1581 )
1582 {
1583    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1584 
1585    sati_set_ata_command(register_fis, ATA_STANDBY_IMMED);
1586    sati_ata_non_data_command(ata_io, sequence);
1587 }
1588 
1589 /**
1590  * @brief This method will construct the ATA idle immediate command.
1591  *
1592  * @pre It is expected that the user has properly set the current contents
1593  *      of the register FIS to 0.
1594  *
1595  * @param[out] ata_io This parameter specifies the ATA IO request structure
1596  *             for which to build the IDLE IMMEDIATE command.
1597  * @param[in]  sequence This parameter specifies the translator sequence
1598  *             for which the command is being constructed.
1599  *
1600  * @return none.
1601  */
1602 void sati_ata_idle_immediate_construct(
1603    void                       * ata_io,
1604    SATI_TRANSLATOR_SEQUENCE_T * sequence
1605 )
1606 {
1607    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1608 
1609    sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
1610    sati_set_ata_features(register_fis, 0x00);
1611    sati_set_ata_sector_count(register_fis, 0x00);
1612    sati_set_ata_lba_high(register_fis, 0x00);
1613    sati_set_ata_lba_mid(register_fis, 0x00);
1614    sati_set_ata_lba_low(register_fis, 0x00);
1615    sati_ata_non_data_command(ata_io, sequence);
1616 }
1617 
1618 /**
1619  * @brief This method will construct the ATA idle immediate command
1620           for Unload Features.
1621  *
1622  * @pre It is expected that the user has properly set the current contents
1623  *      of the register FIS to 0.
1624  *
1625  * @param[out] ata_io This parameter specifies the ATA IO request structure
1626  *             for which to build the IDLE IMMEDIATE command.
1627  * @param[in]  sequence This parameter specifies the translator sequence
1628  *             for which the command is being constructed.
1629  *
1630  * @return none.
1631  */
1632 void sati_ata_idle_immediate_unload_construct(
1633    void                       * ata_io,
1634    SATI_TRANSLATOR_SEQUENCE_T * sequence
1635 )
1636 {
1637    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1638 
1639    sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
1640    sati_set_ata_features(register_fis, 0x44);
1641    sati_set_ata_sector_count(register_fis, 0x00);
1642    sati_set_ata_lba_high(register_fis, 0x55);
1643    sati_set_ata_lba_mid(register_fis, 0x4E);
1644    sati_set_ata_lba_low(register_fis, 0x4C);
1645    sati_ata_non_data_command(ata_io, sequence);
1646 }
1647 
1648 /**
1649  * @brief This method will construct the ATA IDLE command.\
1650  *
1651  * @pre It is expected that the user has properly set the current contents
1652  *      of the register FIS to 0.
1653  *
1654  * @param[out] ata_io This parameter specifies the ATA IO request structure
1655  *             for which to build the ATA IDLE command.
1656  * @param[in]  sequence This parameter specifies the translator sequence
1657  *             for which the command is being constructed.
1658  *
1659  * @return none.
1660  */
1661 void sati_ata_idle_construct(
1662    void                       * ata_io,
1663    SATI_TRANSLATOR_SEQUENCE_T * sequence
1664 )
1665 {
1666    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1667 
1668    sati_set_ata_command(register_fis, ATA_IDLE);
1669    sati_set_ata_features(register_fis, 0x00);
1670    sati_set_ata_sector_count(register_fis, 0x00);
1671 
1672    sequence->device->ata_standby_timer = 0x00;
1673 
1674    sati_set_ata_lba_high(register_fis, 0x00);
1675    sati_set_ata_lba_mid(register_fis, 0x00);
1676    sati_set_ata_lba_low(register_fis, 0x00);
1677    sati_ata_non_data_command(ata_io, sequence);
1678 }
1679 
1680 /**
1681  * @brief This method will construct the ATA MEDIA EJECT command.
1682  *
1683  * @pre It is expected that the user has properly set the current contents
1684  *      of the register FIS to 0.
1685  *
1686  * @param[out] ata_io This parameter specifies the ATA IO request structure
1687  *             for which to build the MEDIA EJCT command.
1688  * @param[in]  sequence This parameter specifies the translator sequence
1689  *             for which the command is being constructed.
1690  *
1691  * @return none.
1692  */
1693 void sati_ata_media_eject_construct(
1694    void                       * ata_io,
1695    SATI_TRANSLATOR_SEQUENCE_T * sequence
1696 )
1697 {
1698    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1699 
1700    sati_set_ata_command(register_fis, ATA_MEDIA_EJECT);
1701    sati_ata_non_data_command(ata_io, sequence);
1702 }
1703 
1704 
1705 /**
1706  * @brief This method will construct the ATA read verify sector(s) command.
1707  *
1708  * @pre It is expected that the user has properly set the current contents
1709  *      of the register FIS to 0.
1710  *
1711  * @param[out] ata_io This parameter specifies the ATA IO request structure
1712  *             for which to build the ATA READ VERIFY SECTOR(S) command.
1713  * @param[in]  sequence This parameter specifies the translator sequence
1714  *             for which the command is being constructed.
1715  *
1716  * @return none.
1717  */
1718 void sati_ata_read_verify_sectors_construct(
1719    void                       * ata_io,
1720    SATI_TRANSLATOR_SEQUENCE_T * sequence
1721 )
1722 {
1723    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1724 
1725    sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
1726 
1727    //According to SAT-2 (v7) 9.11.3
1728    sati_set_ata_sector_count(register_fis, 1);
1729 
1730    //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the
1731    //maximum LBA supported by the ATA device in its current configuration.
1732    //From the unit test, it seems we have to set LBA to a non-zero value.
1733    sati_set_ata_lba_low(register_fis, 1);
1734 
1735    sati_ata_non_data_command(ata_io, sequence);
1736 }
1737 
1738 /**
1739  * @brief This method will construct a ATA SMART Return Status command so the
1740  *        status of the ATA device can be returned. The status of the SMART
1741  *        threshold will be returned by this command.
1742  *
1743  * @return N/A
1744  *
1745  */
1746 void sati_ata_smart_return_status_construct(
1747    void                       * ata_io,
1748    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1749    U8                           feature_value
1750 )
1751 {
1752    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1753 
1754    sati_set_ata_command(register_fis, ATA_SMART);
1755 
1756    sati_set_ata_features(register_fis, feature_value);
1757 
1758    sati_set_ata_lba_high(register_fis, 0xC2);
1759    sati_set_ata_lba_mid(register_fis, 0x4F);
1760 
1761    sati_ata_non_data_command(ata_io, sequence);
1762 }
1763 
1764 /**
1765  * @brief This method will construct a ATA SMART Return Status command so the
1766  *        status of the ATA device can be returned. The status of the SMART
1767  *        threshold will be returned by this command.
1768  *
1769  * @return N/A
1770  *
1771  */
1772 void sati_ata_smart_read_log_construct(
1773    void                       * ata_io,
1774    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1775    U8                           log_address,
1776    U32                          transfer_length
1777 )
1778 {
1779    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1780 
1781    sati_set_ata_command(register_fis, ATA_SMART);
1782    sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG);
1783 
1784    sati_set_ata_lba_high(register_fis, 0xC2);
1785    sati_set_ata_lba_mid(register_fis, 0x4F);
1786    sati_set_ata_lba_low(register_fis, log_address);
1787 
1788    sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1789    sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1790    sequence->ata_transfer_length = transfer_length;
1791 }
1792 
1793 /**
1794  * @brief This method will construct a Write Uncorrectable ATA command that
1795  *        will write one sector with a pseudo or flagged error. The type of
1796  *        error is specified by the feature value.
1797  *
1798  * @return N/A
1799  *
1800  */
1801 void sati_ata_write_uncorrectable_construct(
1802    void                       * ata_io,
1803    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1804    U8                           feature_value
1805 )
1806 {
1807    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1808 
1809    sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE);
1810    sati_set_ata_features(register_fis, feature_value);
1811    sati_set_ata_sector_count(register_fis, 0x0001);
1812    sati_ata_non_data_command(ata_io, sequence);
1813 }
1814 
1815 /**
1816  * @brief This method will construct a Mode Select ATA SET FEATURES command
1817  *        For example, Enable/Disable Write Cache, Enable/Disable Read Ahead
1818  *
1819  * @return N/A
1820  *
1821  */
1822 void sati_ata_set_features_construct(
1823    void                       * ata_io,
1824    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1825    U8                           feature
1826 )
1827 {
1828    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1829 
1830    sati_set_ata_command(register_fis, ATA_SET_FEATURES);
1831    sati_set_ata_features(register_fis, feature);
1832    sati_ata_non_data_command(ata_io, sequence);
1833 }
1834 
1835 
1836 
1837 /**
1838  * @brief This method will construct a Read Log ext ATA command that
1839  *        will request a log page based on the log_address.
1840  *
1841  * @param[in]  log_address This parameter specifies the log page
1842  *             to be returned from Read Log Ext.
1843  *
1844  * @param[in]  transfer_length This parameter specifies the size of the
1845  *             log page response returned by Read Log Ext.
1846  *
1847  * @return N/A
1848  *
1849  */
1850 void sati_ata_read_log_ext_construct(
1851    void                          * ata_io,
1852    SATI_TRANSLATOR_SEQUENCE_T    * sequence,
1853    U8                              log_address,
1854    U32                             transfer_length
1855 )
1856 {
1857    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1858 
1859    sati_set_ata_command(register_fis, ATA_READ_LOG_EXT);
1860 
1861    sati_set_ata_lba_low(register_fis, log_address);
1862    sati_set_ata_lba_mid(register_fis, 0x00);
1863    sati_set_ata_lba_mid_exp(register_fis, 0x00);
1864 
1865    sati_set_ata_sector_count(register_fis, 0x01);
1866 
1867    sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1868    sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1869    sequence->ata_transfer_length = transfer_length;
1870 
1871 }
1872 
1873 /**
1874 * @brief This method will check if the ATA device is in the stopped power
1875 *        state. This is used for all medium access commands for SAT
1876 *        compliance. See SAT2r07 section 9.11.1
1877 *
1878 * @param[in] sequence - SATI sequence data with the device state.
1879 *
1880 * @return TRUE If device is stopped
1881 *
1882 */
1883 BOOL sati_device_state_stopped(
1884    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1885    void                       * scsi_io
1886 )
1887 {
1888    if(sequence->device->state == SATI_DEVICE_STATE_STOPPED)
1889    {
1890       sati_scsi_sense_data_construct(
1891          sequence,
1892          scsi_io,
1893          SCSI_STATUS_CHECK_CONDITION,
1894          SCSI_SENSE_NOT_READY ,
1895          SCSI_ASC_INITIALIZING_COMMAND_REQUIRED,
1896          SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED
1897       );
1898       return TRUE;
1899    }
1900    return FALSE;
1901 }
1902 
1903 /**
1904 * @brief This method will construct a ATA Read Buffer command that
1905 *        will request PIO in data containing the target device's buffer.
1906 *
1907 * @param[out] ata_io This parameter specifies the ATA IO request structure
1908 *             for which to build the ATA READ VERIFY SECTOR(S) command.
1909 * @param[in]  sequence This parameter specifies the translator sequence
1910 *             for which the command is being constructed.
1911 * @return N/A
1912 *
1913 */
1914 void sati_ata_read_buffer_construct(
1915    void                       * ata_io,
1916    SATI_TRANSLATOR_SEQUENCE_T * sequence
1917 )
1918 {
1919    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1920 
1921    sati_set_ata_command(register_fis, ATA_READ_BUFFER);
1922    sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1923    sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1924    sequence->ata_transfer_length = 512;
1925 }
1926 
1927 
1928 /**
1929 * @brief This method will construct a ATA Write Buffer command that
1930 *        will send PIO out data to the target device's buffer.
1931 *
1932 * @param[out] ata_io This parameter specifies the ATA IO request structure
1933 *             for which to build the ATA READ VERIFY SECTOR(S) command.
1934 * @param[in]  sequence This parameter specifies the translator sequence
1935 *             for which the command is being constructed.
1936 * @return N/A
1937 *
1938 */
1939 void sati_ata_write_buffer_construct(
1940    void                       * ata_io,
1941    SATI_TRANSLATOR_SEQUENCE_T * sequence
1942 )
1943 {
1944    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1945 
1946    sati_set_ata_command(register_fis, ATA_WRITE_BUFFER);
1947 
1948    sequence->data_direction      = SATI_DATA_DIRECTION_OUT;
1949    sequence->protocol            = SAT_PROTOCOL_PIO_DATA_OUT;
1950    sequence->ata_transfer_length = 512;
1951 }
1952 
1953 
1954 /**
1955 * @brief This method will construct a ATA Download Microcode command that
1956 *        will send PIO out data containing new firmware for the target drive.
1957 *
1958 * @param[out] ata_io This parameter specifies the ATA IO request structure
1959 *             for which to build the ATA READ VERIFY SECTOR(S) command.
1960 * @param[in]  sequence This parameter specifies the translator sequence
1961 *             for which the command is being constructed.
1962 * @param[in]  mode This parameter specifies the download microcode sub-command
1963 *             code.
1964 * @param[in]  allocation_length This parameter specifies the number of bytes
1965 *             being sent to the target device.
1966 * @param[in]  buffer_offset This parameter specifies the buffer offset for the
1967 *             data sent to the target device.
1968 *
1969 * @return N/A
1970 *
1971 */
1972 void sati_ata_download_microcode_construct(
1973    void                       * ata_io,
1974    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1975    U8                           mode,
1976    U32                          allocation_length,
1977    U32                          buffer_offset
1978 )
1979 {
1980    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1981    U32 allocation_blocks = allocation_length >> 9;
1982    U32 buffer_blkoffset = buffer_offset >> 9;
1983 
1984    sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE);
1985    sati_set_ata_features(register_fis, mode);
1986 
1987    if(mode == ATA_MICROCODE_DOWNLOAD_SAVE)
1988    {
1989       sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9));
1990       sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17));
1991    }
1992    else //mode == 0x03
1993    {
1994       sati_set_ata_sector_count(register_fis, (U8) (allocation_blocks & 0xff));
1995       sati_set_ata_lba_low(register_fis, (U8) ((allocation_blocks >> 8) & 0xff));
1996       sati_set_ata_lba_mid(register_fis, (U8) (buffer_blkoffset & 0xff));
1997       sati_set_ata_lba_high(register_fis, (U8) ((buffer_blkoffset >> 8) & 0xff));
1998    }
1999 
2000    if((allocation_length == 0) && (buffer_offset == 0))
2001    {
2002       sati_ata_non_data_command(ata_io, sequence);
2003    }
2004    else
2005    {
2006       sequence->data_direction      = SATI_DATA_DIRECTION_OUT;
2007       sequence->protocol            = SAT_PROTOCOL_PIO_DATA_OUT;
2008       sequence->ata_transfer_length = allocation_length;
2009    }
2010 }
2011