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 */
85void 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 */
108void 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*/
131void 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 */
167static
168void 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 */
214void 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 */
266void 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 */
305void 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 */
371void 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 */
396void 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 */
424void 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 */
452static
453void 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 */
485static
486U8 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 */
503static
504U8 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 */
561U8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io)
562{
563    U8 response_code;
564
565    response_code = sati_scsi_get_sense_data_response_code(sequence);
566
567    switch (response_code)
568    {
569    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
570    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
571        return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
572    break;
573    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
574    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
575        return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io);
576    break;
577    }
578
579    return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
580}
581
582/**
583 * @brief This method will construct the sense data buffer in the user's
584 *        sense data buffer location.  Additionally, it will set the user's
585 *        SCSI status.
586 *
587 * @param[in]     sequence This parameter specifies the translation sequence
588 *                for which to construct the sense data.
589 * @param[in,out] scsi_io This parameter specifies the user's IO request
590 *                for which to construct the sense data.
591 * @param[in]     scsi_status This parameter specifies the SCSI status
592 *                value for the user's IO request.
593 * @param[in]     sense_key This parameter specifies the sense key to
594 *                be set for the user's IO request.
595 * @param[in]     additional_sense_code This parameter specifies the
596 *                additional sense code (ASC) key to be set for the user's
597 *                IO request.
598 * @param[in]     additional_sense_code_qualifier This parameter specifies
599 *                the additional sense code qualifier (ASCQ) key to be set
600 *                for the user's IO request.
601 *
602 * @return none
603 */
604void sati_scsi_sense_data_construct(
605   SATI_TRANSLATOR_SEQUENCE_T * sequence,
606   void                       * scsi_io,
607   U8                           scsi_status,
608   U8                           sense_key,
609   U8                           additional_sense_code,
610   U8                           additional_sense_code_qualifier
611)
612{
613    U8 response_code;
614
615    response_code = sati_scsi_get_sense_data_response_code(sequence);
616
617    switch (response_code)
618    {
619    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
620    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
621    sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
622                sense_key, additional_sense_code, additional_sense_code_qualifier);
623    break;
624    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
625    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
626        sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
627                sense_key, additional_sense_code, additional_sense_code_qualifier);
628        break;
629    }
630
631    sequence->is_sense_response_set = TRUE;
632}
633
634/**
635 * @brief This method will construct the block descriptor in the user's descriptor
636 *            sense data buffer location.
637 *
638 * @param[in]     sense_data This parameter specifies the user SCSI IO request
639 *                for which to set the sense data byte.
640 * @param[in]     sense_len This parameter specifies length of the sense data
641 *                to be returned by SATI.
642 * @param[out]    descriptor_len This parameter returns the length of constructed
643 *                descriptor.
644 *
645 * @return none
646 */
647static
648void sati_scsi_block_descriptor_construct(
649        U8 * sense_data,
650        U32 sense_len)
651{
652    U8 ili = 1;
653
654    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_BLOCK_DESCRIPTOR_TYPE);
655    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH);
656    sati_set_sense_data_byte(sense_data, sense_len, 2,  0);
657    sati_set_sense_data_byte(sense_data, sense_len, 3,  (ili << 5));
658}
659
660/**
661 * @brief This method will construct the command-specific descriptor for
662 *           the descriptor sense data buffer in the user's sense data buffer
663 *           location.
664 *
665 * @param[in]     sense_data This parameter specifies the user SCSI IO request
666 *                for which to set the sense data byte.
667 * @param[in]     sense_len This parameter specifies length of the sense data
668 *                to be returned by SATI.
669 * @param[out]    descriptor_len This parameter returns the length of constructed
670 *                descriptor.
671 * @param[in]     information_buff This parameter specifies the address for which
672 *                to set the command-specific information buffer.
673 *
674 * @return none
675 */
676static
677void sati_scsi_command_specific_descriptor_construct(
678    U8       * sense_data,
679    U32        sense_len,
680    U8       * information_buff)
681{
682    U8 i;
683
684    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE);
685    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH);
686    sati_set_sense_data_byte(sense_data, sense_len, 2,  0);
687    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
688
689    // fill information buffer
690    // SBC 5.20.1 REASSIGN BLOCKS command overview
691    // If information about the first LBA not reassigned is not available
692    // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh
693    for (i=0; i<8; i++)
694        sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]);
695}
696
697/**
698 * @brief This method will construct the information descriptor for
699 *           the descriptor sense data buffer in the user's sense data buffer
700 *           location.
701 *
702 * @param[in]     sense_data This parameter specifies the user SCSI IO request
703 *                for which to set the sense data byte.
704 * @param[in]     sense_len This parameter specifies length of the sense data
705 *                to be returned by SATI.
706 * @param[out]    descriptor_len This parameter returns the length of constructed
707 *                descriptor.
708 * @param[in]     information_buff This parameter specifies the address for which
709 *                to set the information buffer.
710 *
711 * @return none
712 */
713static
714void sati_scsi_information_descriptor_construct(
715    U8      * sense_data,
716    U32       sense_len,
717    U8      * information_buff)
718{
719    U8 i;
720    U8 valid = 1;
721
722    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_INFORMATION_DESCRIPTOR_TYPE);
723    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH);
724    sati_set_sense_data_byte(sense_data, sense_len, 2,  (valid << 7));
725    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
726
727    // fill information buffer
728    for (i=0; i<8; i++)
729        sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]);
730}
731
732/**
733 * @brief This method will construct the descriptors in the user's descriptor
734 *           sense data buffer location.
735 *
736 * @param[in,out] scsi_io This parameter specifies the user's IO request
737 *                for which to construct the sense data.
738 * @param[in]     sense_data This parameter specifies the user SCSI IO request
739 *                for which to set the sense data byte.
740 * @param[in]     sense_len This parameter specifies length of the sense data
741 *                to be returned by SATI.
742 * @param[out]    descriptor_len This parameter returns the length of constructed
743 *                descriptor.
744 * @param[in]     information_buff This parameter specifies the address for which
745 *                to set the information buffer.
746 *
747 * @return none
748 */
749static
750void sati_scsi_common_descriptors_construct(
751    void    * scsi_io,
752    U8      * sense_data,
753    U32       sense_len,
754    U8      * information_buff)
755{
756    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
757    U8 offset = 0;
758
759    switch (sati_get_cdb_byte(cdb, 0))
760    {
761#if !defined(DISABLE_SATI_WRITE_LONG)
762    case SCSI_WRITE_LONG_10:
763    case SCSI_WRITE_LONG_16:
764        sati_scsi_block_descriptor_construct(
765                sense_data + offset,
766                sense_len - offset);
767
768        offset += SCSI_BLOCK_DESCRIPTOR_LENGTH;
769        sati_scsi_information_descriptor_construct(
770                  sense_data + offset,
771                  sense_len - offset,
772                  information_buff);
773
774        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
775        break;
776#endif // !defined(DISABLE_SATI_WRITE_LONG)
777#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
778    case SCSI_REASSIGN_BLOCKS:
779        sati_scsi_command_specific_descriptor_construct(
780          sense_data + offset,
781          sense_len - offset,
782          NULL);
783
784        offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH;
785        sati_scsi_information_descriptor_construct(
786                  sense_data + offset,
787                  sense_len - offset,
788                  information_buff);
789
790        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
791        break;
792#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
793    case SCSI_READ_6:
794    case SCSI_READ_10:
795    case SCSI_READ_12:
796    case SCSI_READ_16:
797    case SCSI_WRITE_6:
798    case SCSI_WRITE_10:
799    case SCSI_WRITE_12:
800    case SCSI_WRITE_16:
801#if !defined(DISABLE_SATI_VERIFY)
802    case SCSI_VERIFY_10:
803    case SCSI_VERIFY_12:
804    case SCSI_VERIFY_16:
805#endif // !defined(DISABLE_SATI_VERIFY)
806#if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
807    && !defined(DISABLE_SATI_VERIFY)            \
808    && !defined(DISABLE_SATI_WRITE)
809
810    case SCSI_WRITE_AND_VERIFY_10:
811    case SCSI_WRITE_AND_VERIFY_12:
812    case SCSI_WRITE_AND_VERIFY_16:
813#endif //    !defined(DISABLE_SATI_WRITE_AND_VERIFY)
814       // && !defined(DISABLE_SATI_VERIFY)
815       // && !defined(DISABLE_SATI_WRITE)
816        sati_scsi_information_descriptor_construct(
817                  sense_data + offset,
818                  sense_len - offset,
819                  information_buff);
820
821        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
822        break;
823    }
824}
825
826/**
827 * @brief This method will construct the descriptor sense data buffer in
828 *           the user's sense data buffer location.  Additionally, it will set
829 *           the user's SCSI status.
830 *
831 * @param[in]     sequence This parameter specifies the translation sequence
832 *                for which to construct the sense data.
833 * @param[in,out] scsi_io This parameter specifies the user's IO request
834 *                for which to construct the sense data.
835 * @param[in]     scsi_status This parameter specifies the SCSI status
836 *                value for the user's IO request.
837 * @param[in]     sense_key This parameter specifies the sense key to
838 *                be set for the user's IO request.
839 * @param[in]     additional_sense_code This parameter specifies the
840 *                additional sense code (ASC) key to be set for the user's
841 *                IO request.
842 * @param[in]     additional_sense_code_qualifier This parameter specifies
843 *                the additional sense code qualifier (ASCQ) key to be set
844 *                for the user's IO request.
845 *
846 * @return none
847 */
848void sati_scsi_descriptor_sense_data_construct(
849   SATI_TRANSLATOR_SEQUENCE_T * sequence,
850   void                       * scsi_io,
851   U8                           scsi_status,
852   U8                           response_code,
853   U8                           sense_key,
854   U8                           additional_sense_code,
855   U8                           additional_sense_code_qualifier
856)
857{
858   U8 * sense_data;
859   U32    sense_len;
860
861   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
862
863   sati_set_sense_data_byte(
864      sense_data,
865      sense_len,
866      0,
867      response_code
868   );
869
870   sati_set_sense_data_byte(sense_data, sense_len, 1,  sense_key);
871   sati_set_sense_data_byte(sense_data, sense_len, 2,  additional_sense_code);
872   sati_set_sense_data_byte(sense_data, sense_len, 3,  additional_sense_code_qualifier);
873   sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
874   sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
875   sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
876
877   sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL);
878
879   sati_set_sense_data_byte(sense_data, sense_len, 7,  sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
880}
881
882/**
883 * @brief This method will construct the fixed format sense data buffer
884 *           in the user's sense data buffer location.  Additionally, it will
885 *          set the user's SCSI status.
886 *
887 * @param[in]     sequence This parameter specifies the translation sequence
888 *                for which to construct the sense data.
889 * @param[in,out] scsi_io This parameter specifies the user's IO request
890 *                for which to construct the sense data.
891 * @param[in]     scsi_status This parameter specifies the SCSI status
892 *                value for the user's IO request.
893 * @param[in]     sense_key This parameter specifies the sense key to
894 *                be set for the user's IO request.
895 * @param[in]     additional_sense_code This parameter specifies the
896 *                additional sense code (ASC) key to be set for the user's
897 *                IO request.
898 * @param[in]     additional_sense_code_qualifier This parameter specifies
899 *                the additional sense code qualifier (ASCQ) key to be set
900 *                for the user's IO request.
901 *
902 * @return none
903 */
904void sati_scsi_fixed_sense_data_construct(
905   SATI_TRANSLATOR_SEQUENCE_T * sequence,
906   void                       * scsi_io,
907   U8                           scsi_status,
908   U8                           response_code,
909   U8                           sense_key,
910   U8                           additional_sense_code,
911   U8                           additional_sense_code_qualifier
912)
913{
914    U8 * sense_data;
915    U32  sense_len;
916
917    sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
918
919    // Write out the sense data format per SPC-4.
920    // We utilize the fixed format sense data format.
921
922    sati_set_sense_data_byte(
923      sense_data,
924      sense_len,
925      0,
926      response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT
927    );
928
929    sati_set_sense_data_byte(sense_data, sense_len, 1,  0);
930    sati_set_sense_data_byte(sense_data, sense_len, 2,  sense_key);
931    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
932    sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
933    sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
934    sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
935    sati_set_sense_data_byte(sense_data, sense_len, 7,  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*/
969static
970void sati_scsi_common_fixed_sense_construct(
971   U8                         * sense_data,
972   U32                          sense_len,
973   U8                           sense_key,
974   U8                           additional_sense_code,
975   U8                           additional_sense_code_qualifier
976)
977{
978
979   sati_set_sense_data_byte(sense_data, sense_len, 1,  0);
980   sati_set_sense_data_byte(sense_data, sense_len, 2,  sense_key);
981
982   //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions
983
984   sati_set_sense_data_byte(sense_data, sense_len, 7,  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 */
1019static
1020void sati_scsi_common_descriptor_sense_construct(
1021    SATI_TRANSLATOR_SEQUENCE_T * sequence,
1022    void                       * scsi_io,
1023    U8                         * sense_data,
1024    U32                          sense_len,
1025    U8                           sense_key,
1026    U8                           additional_sense_code,
1027    U8                           additional_sense_code_qualifier,
1028    U8                         * information_buff
1029)
1030{
1031    sati_set_sense_data_byte(sense_data, sense_len, 1,  sense_key);
1032    sati_set_sense_data_byte(sense_data, sense_len, 2,  additional_sense_code);
1033    sati_set_sense_data_byte(sense_data, sense_len, 3,  additional_sense_code_qualifier);
1034    sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
1035    sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
1036    sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
1037
1038    sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff);
1039
1040    sati_set_sense_data_byte(sense_data, sense_len, 7,  sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
1041}
1042
1043/**
1044* @brief This method will construct the sense data buffer in the user's
1045*        descriptor sense data buffer location.  Additionally, it will set
1046*        the user's SCSI status. This is only used for NCQ uncorrectable
1047*        read errors
1048*
1049* @param[in]     sequence This parameter specifies the translation sequence
1050*                for which to construct the sense data.
1051* @param[in,out] scsi_io This parameter specifies the user's IO request
1052*                for which to construct the sense data.
1053* @param[in]     ata_input_data This parameter specifies the user's ATA IO
1054*                response from a Read Log Ext command.
1055* @param[in]     scsi_status This parameter specifies the SCSI status
1056*                value for the user's IO request.
1057* @param[in]     sense_key This parameter specifies the sense key to
1058*                be set for the user's IO request.
1059* @param[in]     additional_sense_code This parameter specifies the
1060*                additional sense code (ASC) key to be set for the user's
1061*                IO request.
1062* @param[in]     additional_sense_code_qualifier This parameter specifies
1063*                the additional sense code qualifier (ASCQ) key to be set
1064*                for the user's IO request.
1065*
1066* @return none
1067*/
1068static
1069void sati_scsi_read_ncq_error_descriptor_sense_construct(
1070   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1071   void                       * scsi_io,
1072   void                       * ata_input_data,
1073   U8                           scsi_status,
1074   U8                           response_code,
1075   U8                           sense_key,
1076   U8                           additional_sense_code,
1077   U8                           additional_sense_code_qualifier
1078)
1079{
1080   U8 * sense_data;
1081   U32  sense_len;
1082
1083   U8 information_buff[8] = {0};
1084
1085   ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
1086
1087   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1088
1089   sati_set_sense_data_byte(
1090      sense_data,
1091      sense_len,
1092      0,
1093      response_code
1094   );
1095
1096   information_buff[2] = ncq_log->lba_47_40;
1097   information_buff[3] = ncq_log->lba_39_32;
1098   information_buff[4] = ncq_log->lba_31_24;
1099   information_buff[5] = ncq_log->lba_23_16;
1100   information_buff[6] = ncq_log->lba_15_8;
1101   information_buff[7] = ncq_log->lba_7_0;
1102
1103   sati_scsi_common_descriptor_sense_construct(
1104           sequence,
1105           scsi_io,
1106           sense_data,
1107           sense_len,
1108           sense_key,
1109           additional_sense_code,
1110           additional_sense_code_qualifier,
1111           information_buff
1112   );
1113}
1114
1115/**
1116* @brief This method will construct the sense data buffer in the user's
1117*        sense data buffer location.  Additionally, it will set the user's
1118*        SCSI status. This is only used for NCQ uncorrectable read errors
1119*
1120* @param[in]     sequence This parameter specifies the translation sequence
1121*                for which to construct the sense data.
1122* @param[in,out] scsi_io This parameter specifies the user's IO request
1123*                for which to construct the sense data.
1124* @param[in]     ata_input_data This parameter specifies the user's ATA IO
1125*                response from a Read Log Ext command.
1126* @param[in]     scsi_status This parameter specifies the SCSI status
1127*                value for the user's IO request.
1128* @param[in]     sense_key This parameter specifies the sense key to
1129*                be set for the user's IO request.
1130* @param[in]     additional_sense_code This parameter specifies the
1131*                additional sense code (ASC) key to be set for the user's
1132*                IO request.
1133* @param[in]     additional_sense_code_qualifier This parameter specifies
1134*                the additional sense code qualifier (ASCQ) key to be set
1135*                for the user's IO request.
1136*
1137* @return none
1138*/
1139static
1140void sati_scsi_read_ncq_error_fixed_sense_construct(
1141   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1142   void                       * scsi_io,
1143   void                       * ata_input_data,
1144   U8                           scsi_status,
1145   U8                           response_code,
1146   U8                           sense_key,
1147   U8                           additional_sense_code,
1148   U8                           additional_sense_code_qualifier
1149)
1150{
1151   U8 * sense_data;
1152   U32  sense_len;
1153   U8   valid = TRUE;
1154
1155   ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
1156
1157   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1158
1159   if(ncq_log->lba_39_32 > 0)
1160   {
1161      valid = FALSE;
1162   }
1163
1164   sati_set_sense_data_byte(
1165      sense_data,
1166      sense_len,
1167      0,
1168      (valid << 7) | response_code
1169   );
1170
1171   sati_set_sense_data_byte(sense_data, sense_len, 3,  ncq_log->lba_31_24);
1172   sati_set_sense_data_byte(sense_data, sense_len, 4,  ncq_log->lba_23_16);
1173   sati_set_sense_data_byte(sense_data, sense_len, 5,  ncq_log->lba_15_8);
1174   sati_set_sense_data_byte(sense_data, sense_len, 6,  ncq_log->lba_7_0);
1175
1176   sati_scsi_common_fixed_sense_construct(
1177      sense_data,
1178      sense_len,
1179      sense_key,
1180      additional_sense_code,
1181      additional_sense_code_qualifier
1182   );
1183}
1184
1185void sati_scsi_read_ncq_error_sense_construct(
1186   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1187   void                       * scsi_io,
1188   void                       * ata_input_data,
1189   U8                           scsi_status,
1190   U8                           sense_key,
1191   U8                           additional_sense_code,
1192   U8                           additional_sense_code_qualifier
1193)
1194{
1195    U8 response_code;
1196
1197    response_code = sati_scsi_get_sense_data_response_code(sequence);
1198
1199    switch (response_code)
1200    {
1201    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
1202    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
1203        sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1204                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1205    break;
1206    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
1207    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
1208        sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1209                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1210        break;
1211    }
1212
1213    sequence->is_sense_response_set = TRUE;
1214}
1215
1216/**
1217* @brief This method will construct the sense data buffer in the user's
1218*        sense data buffer location.  Additionally, it will set the user's
1219*        SCSI status. This is used for uncorrectable read errors.
1220*
1221* @param[in]     sequence This parameter specifies the translation sequence
1222*                for which to construct the sense data.
1223* @param[in,out] scsi_io This parameter specifies the user's IO request
1224*                for which to construct the sense data.
1225* @param[in]     ata_io This parameter is a pointer to the ATA IO data used
1226*                to get the ATA register fis.
1227* @param[in]     scsi_status This parameter specifies the SCSI status
1228*                value for the user's IO request.
1229* @param[in]     sense_key This parameter specifies the sense key to
1230*                be set for the user's IO request.
1231* @param[in]     additional_sense_code This parameter specifies the
1232*                additional sense code (ASC) key to be set for the user's
1233*                IO request.
1234* @param[in]     additional_sense_code_qualifier This parameter specifies
1235*                the additional sense code qualifier (ASCQ) key to be set
1236*                for the user's IO request.
1237*
1238* @return none
1239*/
1240static
1241void sati_scsi_read_error_descriptor_sense_construct(
1242   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1243   void                       * scsi_io,
1244   void                       * ata_io,
1245   U8                           scsi_status,
1246   U8                           response_code,
1247   U8                           sense_key,
1248   U8                           additional_sense_code,
1249   U8                           additional_sense_code_qualifier
1250)
1251{
1252   U8 * sense_data;
1253   U32  sense_len;
1254   U8 information_buff[8] = {0};
1255
1256   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
1257
1258   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1259
1260   information_buff[2] = sati_get_ata_lba_high_ext(register_fis);
1261   information_buff[3] = sati_get_ata_lba_mid_ext(register_fis);
1262   information_buff[4] = sati_get_ata_lba_low_ext(register_fis);
1263   information_buff[5] = sati_get_ata_lba_high(register_fis);
1264   information_buff[6] = sati_get_ata_lba_mid(register_fis);
1265   information_buff[7] = sati_get_ata_lba_low(register_fis);
1266
1267   sati_set_sense_data_byte(
1268      sense_data,
1269      sense_len,
1270      0,
1271      SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE
1272   );
1273
1274   sati_scsi_common_descriptor_sense_construct(
1275      sequence,
1276      scsi_io,
1277      sense_data,
1278      sense_len,
1279      sense_key,
1280      additional_sense_code,
1281      additional_sense_code_qualifier,
1282      information_buff
1283   );
1284}
1285
1286/**
1287* @brief This method will construct the sense data buffer in the user's
1288*        sense data buffer location.  Additionally, it will set the user's
1289*        SCSI status. This is used for uncorrectable read errors.
1290*
1291* @param[in]     sequence This parameter specifies the translation sequence
1292*                for which to construct the sense data.
1293* @param[in,out] scsi_io This parameter specifies the user's IO request
1294*                for which to construct the sense data.
1295* @param[in]     ata_io This parameter is a pointer to the ATA IO data used
1296*                to get the ATA register fis.
1297* @param[in]     scsi_status This parameter specifies the SCSI status
1298*                value for the user's IO request.
1299* @param[in]     sense_key This parameter specifies the sense key to
1300*                be set for the user's IO request.
1301* @param[in]     additional_sense_code This parameter specifies the
1302*                additional sense code (ASC) key to be set for the user's
1303*                IO request.
1304* @param[in]     additional_sense_code_qualifier This parameter specifies
1305*                the additional sense code qualifier (ASCQ) key to be set
1306*                for the user's IO request.
1307*
1308* @return none
1309*/
1310static
1311void sati_scsi_read_error_fixed_sense_construct(
1312   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1313   void                       * scsi_io,
1314   void                       * ata_io,
1315   U8                           scsi_status,
1316   U8                           response_code,
1317   U8                           sense_key,
1318   U8                           additional_sense_code,
1319   U8                           additional_sense_code_qualifier
1320)
1321{
1322   U8 * sense_data;
1323   U32  sense_len;
1324   U8   valid = TRUE;
1325
1326   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
1327
1328   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1329
1330   if(sati_get_ata_lba_mid_ext(register_fis) > 0)
1331   {
1332      valid = FALSE;
1333   }
1334
1335   sati_set_sense_data_byte(sense_data, sense_len, 3,  sati_get_ata_lba_low_ext(register_fis));
1336   sati_set_sense_data_byte(sense_data, sense_len, 4,  sati_get_ata_lba_high(register_fis));
1337   sati_set_sense_data_byte(sense_data, sense_len, 5,  sati_get_ata_lba_mid(register_fis));
1338   sati_set_sense_data_byte(sense_data, sense_len, 6,  sati_get_ata_lba_low(register_fis));
1339
1340
1341   sati_set_sense_data_byte(
1342      sense_data,
1343      sense_len,
1344      0,
1345      (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE
1346   );
1347
1348   sati_scsi_common_fixed_sense_construct(
1349      sense_data,
1350      sense_len,
1351      sense_key,
1352      additional_sense_code,
1353      additional_sense_code_qualifier
1354   );
1355}
1356
1357void sati_scsi_read_error_sense_construct(
1358   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1359   void                       * scsi_io,
1360   void                       * ata_input_data,
1361   U8                           scsi_status,
1362   U8                           sense_key,
1363   U8                           additional_sense_code,
1364   U8                           additional_sense_code_qualifier
1365)
1366{
1367    U8 response_code;
1368
1369    response_code = sati_scsi_get_sense_data_response_code(sequence);
1370
1371    switch (response_code)
1372    {
1373    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
1374    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
1375        sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1376                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1377    break;
1378    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
1379    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
1380        sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1381                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1382        break;
1383    }
1384
1385    sequence->is_sense_response_set = TRUE;
1386}
1387
1388/*
1389 * @brief This method builds the scsi response data for a sata task management
1390 *        request.
1391 *
1392 * @param[in]     sequence This parameter specifies the translation sequence
1393 *                for which to construct the sense data.
1394 * @param[in,out] scsi_io This parameter specifies the user's IO request
1395 *                for which to construct the sense data.
1396 * @param[in]     response_data The response status for the task management
1397 *                request.
1398 */
1399void sati_scsi_response_data_construct(
1400   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1401   void                       * scsi_io,
1402   U8                           response_data
1403)
1404{
1405#ifdef SATI_TRANSPORT_SUPPORTS_SAS
1406   SCI_SSP_RESPONSE_IU_T * rsp_iu  = (SCI_SSP_RESPONSE_IU_T*)
1407                                        sati_cb_get_response_iu_address(scsi_io);
1408   rsp_iu->data_present            = 0x01;
1409   rsp_iu->response_data_length[3] = sizeof(U32);
1410   rsp_iu->status                  = 0;
1411   ((U8 *)rsp_iu->data)[3]         = response_data;
1412#else
1413#endif // SATI_TRANSPORT_SUPPORTS_SAS
1414}
1415
1416/**
1417 * @brief This method checks to make sure that the translation isn't
1418 *        exceeding the allocation length specified in the CDB prior
1419 *        to retrieving the payload data byte from the user's buffer.
1420 *
1421 * @param[in,out] scsi_io This parameter specifies the user's IO request
1422 *                for which to set the user payload data byte.
1423 * @param[in]     byte_offset This parameter specifies the offset into
1424 *                the user's payload buffer at which to write the supplied
1425 *                value.
1426 * @param[in]     value This parameter specifies the memory location into
1427 *                which to read the value from the user's payload buffer.
1428 *
1429 * @return none
1430 */
1431void sati_get_data_byte(
1432   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1433   void                       * scsi_io,
1434   U32                          byte_offset,
1435   U8                         * value
1436)
1437{
1438   if (byte_offset < sequence->allocation_length)
1439      sati_cb_get_data_byte(scsi_io, byte_offset, value);
1440}
1441
1442/**
1443 * @brief This method checks to make sure that the translation isn't
1444 *        exceeding the allocation length specified in the CDB while
1445 *        translating payload data into the user's buffer.
1446 *
1447 * @param[in]     sequence This parameter specifies the translation sequence
1448 *                for which to set the user payload data byte.
1449 * @param[in,out] scsi_io This parameter specifies the user's IO request
1450 *                for which to set the user payload data byte.
1451 * @param[in]     byte_offset This parameter specifies the offset into
1452 *                the user's payload buffer at which to write the supplied
1453 *                value.
1454 * @param[in]     value This parameter specifies the new value to be
1455 *                written out into the user's payload buffer.
1456 *
1457 * @return none
1458 */
1459void sati_set_data_byte(
1460   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1461   void                       * scsi_io,
1462   U32                          byte_offset,
1463   U8                           value
1464)
1465{
1466   if (byte_offset < sequence->allocation_length)
1467   {
1468      sequence->number_data_bytes_set++;
1469      sati_cb_set_data_byte(scsi_io, byte_offset, value);
1470   }
1471}
1472
1473/**
1474 * @brief This method checks to make sure that the translation isn't
1475 *        exceeding the allocation length specified in the CDB while
1476 *        translating payload data into the user's buffer.
1477 *
1478 * @param[in]     sequence This parameter specifies the translation sequence
1479 *                for which to set the user payload data dword.
1480 * @param[in,out] scsi_io This parameter specifies the user's IO request
1481 *                for which to set the user payload data dword.
1482 * @param[in]     byte_offset This parameter specifies the offset into
1483 *                the user's payload buffer at which to write the supplied
1484 *                value.
1485 * @param[in]     value This parameter specifies the new value to be
1486 *                written out into the user's payload buffer.
1487 *
1488 * @return none
1489 */
1490void sati_set_data_dword(
1491   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1492   void                       * scsi_io,
1493   U32                          byte_offset,
1494   U32                          value
1495)
1496{
1497   /// @todo Check to ensure that the bytes appear correctly (SAS Address).
1498
1499   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF);
1500       byte_offset++;
1501   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF);
1502       byte_offset++;
1503   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF);
1504       byte_offset++;
1505   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF);
1506}
1507
1508/**
1509 * @brief This method will construct the ATA flush cache command.
1510 *
1511 * @pre It is expected that the user has properly set the current contents
1512 *      of the register FIS to 0.
1513 *
1514 * @param[out] ata_io This parameter specifies the ATA IO request structure
1515 *             for which to build the FLUSH CACHE command.
1516 * @param[in]  sequence This parameter specifies the translator sequence
1517 *             for which the command is being constructed.
1518 *
1519 * @return none.
1520 */
1521void sati_ata_flush_cache_construct(
1522   void                       * ata_io,
1523   SATI_TRANSLATOR_SEQUENCE_T * sequence
1524)
1525{
1526   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1527
1528   sati_set_ata_command(register_fis, ATA_FLUSH_CACHE);
1529   sati_ata_non_data_command(ata_io, sequence);
1530}
1531
1532/**
1533 * @brief This method will construct the ATA standby immediate command.
1534 *
1535 * @pre It is expected that the user has properly set the current contents
1536 *      of the register FIS to 0.
1537 *
1538 * @param[out] ata_io This parameter specifies the ATA IO request structure
1539 *             for which to build the STANDBY IMMEDIATE command.
1540 * @param[in]  sequence This parameter specifies the translator sequence
1541 *             for which the command is being constructed.
1542 *
1543 * @param[in]  count This parameter specifies the time period programmed
1544 *             into the Standby Timer. See ATA8 spec for more details
1545 * @return none.
1546 */
1547void sati_ata_standby_construct(
1548   void                       * ata_io,
1549   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1550   U16                          count
1551)
1552{
1553   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1554
1555   sati_set_ata_command(register_fis, ATA_STANDBY);
1556   sati_set_ata_sector_count(register_fis, count);
1557
1558   sequence->device->ata_standby_timer = (U8) count;
1559
1560   sati_ata_non_data_command(ata_io, sequence);
1561}
1562
1563/**
1564 * @brief This method will construct the ATA standby immediate command.
1565 *
1566 * @pre It is expected that the user has properly set the current contents
1567 *      of the register FIS to 0.
1568 *
1569 * @param[out] ata_io This parameter specifies the ATA IO request structure
1570 *             for which to build the STANDBY IMMEDIATE command.
1571 * @param[in]  sequence This parameter specifies the translator sequence
1572 *             for which the command is being constructed.
1573 *
1574 * @return none.
1575 */
1576void sati_ata_standby_immediate_construct(
1577   void                       * ata_io,
1578   SATI_TRANSLATOR_SEQUENCE_T * sequence
1579)
1580{
1581   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1582
1583   sati_set_ata_command(register_fis, ATA_STANDBY_IMMED);
1584   sati_ata_non_data_command(ata_io, sequence);
1585}
1586
1587/**
1588 * @brief This method will construct the ATA idle immediate command.
1589 *
1590 * @pre It is expected that the user has properly set the current contents
1591 *      of the register FIS to 0.
1592 *
1593 * @param[out] ata_io This parameter specifies the ATA IO request structure
1594 *             for which to build the IDLE IMMEDIATE command.
1595 * @param[in]  sequence This parameter specifies the translator sequence
1596 *             for which the command is being constructed.
1597 *
1598 * @return none.
1599 */
1600void sati_ata_idle_immediate_construct(
1601   void                       * ata_io,
1602   SATI_TRANSLATOR_SEQUENCE_T * sequence
1603)
1604{
1605   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1606
1607   sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
1608   sati_set_ata_features(register_fis, 0x00);
1609   sati_set_ata_sector_count(register_fis, 0x00);
1610   sati_set_ata_lba_high(register_fis, 0x00);
1611   sati_set_ata_lba_mid(register_fis, 0x00);
1612   sati_set_ata_lba_low(register_fis, 0x00);
1613   sati_ata_non_data_command(ata_io, sequence);
1614}
1615
1616/**
1617 * @brief This method will construct the ATA idle immediate command
1618          for Unload Features.
1619 *
1620 * @pre It is expected that the user has properly set the current contents
1621 *      of the register FIS to 0.
1622 *
1623 * @param[out] ata_io This parameter specifies the ATA IO request structure
1624 *             for which to build the IDLE IMMEDIATE command.
1625 * @param[in]  sequence This parameter specifies the translator sequence
1626 *             for which the command is being constructed.
1627 *
1628 * @return none.
1629 */
1630void sati_ata_idle_immediate_unload_construct(
1631   void                       * ata_io,
1632   SATI_TRANSLATOR_SEQUENCE_T * sequence
1633)
1634{
1635   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1636
1637   sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
1638   sati_set_ata_features(register_fis, 0x44);
1639   sati_set_ata_sector_count(register_fis, 0x00);
1640   sati_set_ata_lba_high(register_fis, 0x55);
1641   sati_set_ata_lba_mid(register_fis, 0x4E);
1642   sati_set_ata_lba_low(register_fis, 0x4C);
1643   sati_ata_non_data_command(ata_io, sequence);
1644}
1645
1646/**
1647 * @brief This method will construct the ATA IDLE command.\
1648 *
1649 * @pre It is expected that the user has properly set the current contents
1650 *      of the register FIS to 0.
1651 *
1652 * @param[out] ata_io This parameter specifies the ATA IO request structure
1653 *             for which to build the ATA IDLE command.
1654 * @param[in]  sequence This parameter specifies the translator sequence
1655 *             for which the command is being constructed.
1656 *
1657 * @return none.
1658 */
1659void sati_ata_idle_construct(
1660   void                       * ata_io,
1661   SATI_TRANSLATOR_SEQUENCE_T * sequence
1662)
1663{
1664   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1665
1666   sati_set_ata_command(register_fis, ATA_IDLE);
1667   sati_set_ata_features(register_fis, 0x00);
1668   sati_set_ata_sector_count(register_fis, 0x00);
1669
1670   sequence->device->ata_standby_timer = 0x00;
1671
1672   sati_set_ata_lba_high(register_fis, 0x00);
1673   sati_set_ata_lba_mid(register_fis, 0x00);
1674   sati_set_ata_lba_low(register_fis, 0x00);
1675   sati_ata_non_data_command(ata_io, sequence);
1676}
1677
1678/**
1679 * @brief This method will construct the ATA MEDIA EJECT command.
1680 *
1681 * @pre It is expected that the user has properly set the current contents
1682 *      of the register FIS to 0.
1683 *
1684 * @param[out] ata_io This parameter specifies the ATA IO request structure
1685 *             for which to build the MEDIA EJCT command.
1686 * @param[in]  sequence This parameter specifies the translator sequence
1687 *             for which the command is being constructed.
1688 *
1689 * @return none.
1690 */
1691void sati_ata_media_eject_construct(
1692   void                       * ata_io,
1693   SATI_TRANSLATOR_SEQUENCE_T * sequence
1694)
1695{
1696   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1697
1698   sati_set_ata_command(register_fis, ATA_MEDIA_EJECT);
1699   sati_ata_non_data_command(ata_io, sequence);
1700}
1701
1702
1703/**
1704 * @brief This method will construct the ATA read verify sector(s) command.
1705 *
1706 * @pre It is expected that the user has properly set the current contents
1707 *      of the register FIS to 0.
1708 *
1709 * @param[out] ata_io This parameter specifies the ATA IO request structure
1710 *             for which to build the ATA READ VERIFY SECTOR(S) command.
1711 * @param[in]  sequence This parameter specifies the translator sequence
1712 *             for which the command is being constructed.
1713 *
1714 * @return none.
1715 */
1716void sati_ata_read_verify_sectors_construct(
1717   void                       * ata_io,
1718   SATI_TRANSLATOR_SEQUENCE_T * sequence
1719)
1720{
1721   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1722
1723   sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
1724
1725   //According to SAT-2 (v7) 9.11.3
1726   sati_set_ata_sector_count(register_fis, 1);
1727
1728   //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the
1729   //maximum LBA supported by the ATA device in its current configuration.
1730   //From the unit test, it seems we have to set LBA to a non-zero value.
1731   sati_set_ata_lba_low(register_fis, 1);
1732
1733   sati_ata_non_data_command(ata_io, sequence);
1734}
1735
1736/**
1737 * @brief This method will construct a ATA SMART Return Status command so the
1738 *        status of the ATA device can be returned. The status of the SMART
1739 *        threshold will be returned by this command.
1740 *
1741 * @return N/A
1742 *
1743 */
1744void sati_ata_smart_return_status_construct(
1745   void                       * ata_io,
1746   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1747   U8                           feature_value
1748)
1749{
1750   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1751
1752   sati_set_ata_command(register_fis, ATA_SMART);
1753
1754   sati_set_ata_features(register_fis, feature_value);
1755
1756   sati_set_ata_lba_high(register_fis, 0xC2);
1757   sati_set_ata_lba_mid(register_fis, 0x4F);
1758
1759   sati_ata_non_data_command(ata_io, sequence);
1760}
1761
1762/**
1763 * @brief This method will construct a ATA SMART Return Status command so the
1764 *        status of the ATA device can be returned. The status of the SMART
1765 *        threshold will be returned by this command.
1766 *
1767 * @return N/A
1768 *
1769 */
1770void sati_ata_smart_read_log_construct(
1771   void                       * ata_io,
1772   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1773   U8                           log_address,
1774   U32                          transfer_length
1775)
1776{
1777   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1778
1779   sati_set_ata_command(register_fis, ATA_SMART);
1780   sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG);
1781
1782   sati_set_ata_lba_high(register_fis, 0xC2);
1783   sati_set_ata_lba_mid(register_fis, 0x4F);
1784   sati_set_ata_lba_low(register_fis, log_address);
1785
1786   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1787   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1788   sequence->ata_transfer_length = transfer_length;
1789}
1790
1791/**
1792 * @brief This method will construct a Write Uncorrectable ATA command that
1793 *        will write one sector with a psuedo or flagged error. The type of
1794 *        error is specified by the feature value.
1795 *
1796 * @return N/A
1797 *
1798 */
1799void sati_ata_write_uncorrectable_construct(
1800   void                       * ata_io,
1801   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1802   U8                           feature_value
1803)
1804{
1805   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1806
1807   sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE);
1808   sati_set_ata_features(register_fis, feature_value);
1809   sati_set_ata_sector_count(register_fis, 0x0001);
1810   sati_ata_non_data_command(ata_io, sequence);
1811}
1812
1813/**
1814 * @brief This method will construct a Mode Select ATA SET FEATURES command
1815 *        For example, Enable/Disable Write Cache, Enable/Disable Read Ahead
1816 *
1817 * @return N/A
1818 *
1819 */
1820void sati_ata_set_features_construct(
1821   void                       * ata_io,
1822   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1823   U8                           feature
1824)
1825{
1826   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1827
1828   sati_set_ata_command(register_fis, ATA_SET_FEATURES);
1829   sati_set_ata_features(register_fis, feature);
1830   sati_ata_non_data_command(ata_io, sequence);
1831}
1832
1833
1834
1835/**
1836 * @brief This method will construct a Read Log ext ATA command that
1837 *        will request a log page based on the log_address.
1838 *
1839 * @param[in]  log_address This parameter specifies the log page
1840 *             to be returned from Read Log Ext.
1841 *
1842 * @param[in]  transfer_length This parameter specifies the size of the
1843 *             log page response returned by Read Log Ext.
1844 *
1845 * @return N/A
1846 *
1847 */
1848void sati_ata_read_log_ext_construct(
1849   void                          * ata_io,
1850   SATI_TRANSLATOR_SEQUENCE_T    * sequence,
1851   U8                              log_address,
1852   U32                             transfer_length
1853)
1854{
1855   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1856
1857   sati_set_ata_command(register_fis, ATA_READ_LOG_EXT);
1858
1859   sati_set_ata_lba_low(register_fis, log_address);
1860   sati_set_ata_lba_mid(register_fis, 0x00);
1861   sati_set_ata_lba_mid_exp(register_fis, 0x00);
1862
1863   sati_set_ata_sector_count(register_fis, 0x01);
1864
1865   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1866   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1867   sequence->ata_transfer_length = transfer_length;
1868
1869}
1870
1871/**
1872* @brief This method will check if the ATA device is in the stopped power
1873*        state. This is used for all medium access commands for SAT
1874*        compliance. See SAT2r07 section 9.11.1
1875*
1876* @param[in] sequence - SATI sequence data with the device state.
1877*
1878* @return TRUE If device is stopped
1879*
1880*/
1881BOOL sati_device_state_stopped(
1882   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1883   void                       * scsi_io
1884)
1885{
1886   if(sequence->device->state == SATI_DEVICE_STATE_STOPPED)
1887   {
1888      sati_scsi_sense_data_construct(
1889         sequence,
1890         scsi_io,
1891         SCSI_STATUS_CHECK_CONDITION,
1892         SCSI_SENSE_NOT_READY ,
1893         SCSI_ASC_INITIALIZING_COMMAND_REQUIRED,
1894         SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED
1895      );
1896      return TRUE;
1897   }
1898   return FALSE;
1899}
1900
1901/**
1902* @brief This method will construct a ATA Read Buffer command that
1903*        will request PIO in data containing the target device's buffer.
1904*
1905* @param[out] ata_io This parameter specifies the ATA IO request structure
1906*             for which to build the ATA READ VERIFY SECTOR(S) command.
1907* @param[in]  sequence This parameter specifies the translator sequence
1908*             for which the command is being constructed.
1909* @return N/A
1910*
1911*/
1912void sati_ata_read_buffer_construct(
1913   void                       * ata_io,
1914   SATI_TRANSLATOR_SEQUENCE_T * sequence
1915)
1916{
1917   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1918
1919   sati_set_ata_command(register_fis, ATA_READ_BUFFER);
1920   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
1921   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
1922   sequence->ata_transfer_length = 512;
1923}
1924
1925
1926/**
1927* @brief This method will construct a ATA Write Buffer command that
1928*        will send PIO out data to the target device's buffer.
1929*
1930* @param[out] ata_io This parameter specifies the ATA IO request structure
1931*             for which to build the ATA READ VERIFY SECTOR(S) command.
1932* @param[in]  sequence This parameter specifies the translator sequence
1933*             for which the command is being constructed.
1934* @return N/A
1935*
1936*/
1937void sati_ata_write_buffer_construct(
1938   void                       * ata_io,
1939   SATI_TRANSLATOR_SEQUENCE_T * sequence
1940)
1941{
1942   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1943
1944   sati_set_ata_command(register_fis, ATA_WRITE_BUFFER);
1945
1946   sequence->data_direction      = SATI_DATA_DIRECTION_OUT;
1947   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_OUT;
1948   sequence->ata_transfer_length = 512;
1949}
1950
1951
1952/**
1953* @brief This method will construct a ATA Download Microcode command that
1954*        will send PIO out data containing new firmware for the target drive.
1955*
1956* @param[out] ata_io This parameter specifies the ATA IO request structure
1957*             for which to build the ATA READ VERIFY SECTOR(S) command.
1958* @param[in]  sequence This parameter specifies the translator sequence
1959*             for which the command is being constructed.
1960* @param[in]  mode This parameter specifies the download microcode sub-command
1961*             code.
1962* @param[in]  allocation_length This parameter specifies the number of bytes
1963*             being sent to the target device.
1964* @param[in]  buffer_offset This parameter specifies the buffer offset for the
1965*             data sent to the target device.
1966*
1967* @return N/A
1968*
1969*/
1970void sati_ata_download_microcode_construct(
1971   void                       * ata_io,
1972   SATI_TRANSLATOR_SEQUENCE_T * sequence,
1973   U8                           mode,
1974   U32                          allocation_length,
1975   U32                          buffer_offset
1976)
1977{
1978   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1979   U32 allocation_blocks = allocation_length >> 9;
1980   U32 buffer_blkoffset = buffer_offset >> 9;
1981
1982   sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE);
1983   sati_set_ata_features(register_fis, mode);
1984
1985   if(mode == ATA_MICROCODE_DOWNLOAD_SAVE)
1986   {
1987      sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9));
1988      sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17));
1989   }
1990   else //mode == 0x03
1991   {
1992      sati_set_ata_sector_count(register_fis, (U8) (allocation_blocks & 0xff));
1993      sati_set_ata_lba_low(register_fis, (U8) ((allocation_blocks >> 8) & 0xff));
1994      sati_set_ata_lba_mid(register_fis, (U8) (buffer_blkoffset & 0xff));
1995      sati_set_ata_lba_high(register_fis, (U8) ((buffer_blkoffset >> 8) & 0xff));
1996   }
1997
1998   if((allocation_length == 0) && (buffer_offset == 0))
1999   {
2000      sati_ata_non_data_command(ata_io, sequence);
2001   }
2002   else
2003   {
2004      sequence->data_direction      = SATI_DATA_DIRECTION_OUT;
2005      sequence->protocol            = SAT_PROTOCOL_PIO_DATA_OUT;
2006      sequence->ata_transfer_length = allocation_length;
2007   }
2008}
2009