The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isci/scil/sati_util.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 parameter
  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 }

Cache object: 82dc436cfc129b2b984d788501478377


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.