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_inquiry.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  *
   61  * @brief This file contains the method implementations required to
   62  *        translate the SCSI inquiry command.
   63  *        The following (VPD) pages are currently supported:
   64  *        - Standard
   65  *        - Supported Pages
   66  *        - Unit Serial Number
   67  *        - Device Identification
   68  */
   69 
   70 #if !defined(DISABLE_SATI_INQUIRY)
   71 
   72 #include <dev/isci/scil/sati_inquiry.h>
   73 #include <dev/isci/scil/sati_callbacks.h>
   74 #include <dev/isci/scil/sati_util.h>
   75 #include <dev/isci/scil/intel_ata.h>
   76 #include <dev/isci/scil/intel_scsi.h>
   77 
   78 //******************************************************************************
   79 //* P R I V A T E   M E T H O D S
   80 //******************************************************************************
   81 /**
   82 * @brief This method builds the SCSI data associated with the SATI product
   83 *        revision that is commonly used on the Standard inquiry response and
   84 *        the ATA information page.
   85 *
   86 * @param[in]  sequence This parameter specifies the translator sequence
   87 *             object to be utilized during data translation.
   88 * @param[in]  ata_input_data This parameter specifies ata data received from
   89 *             the remote device.
   90 * @param[out] scsi_io This parameter specifies the user IO request for
   91 *             which to construct the standard inquiry data.
   92 *
   93 * @return none
   94 */
   95 static
   96 void sati_inquiry_construct_product_revision(
   97    SATI_TRANSLATOR_SEQUENCE_T * sequence,
   98    void                       * ata_input_data,
   99    void                       * scsi_io
  100 )
  101 {
  102    ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
  103       ata_input_data;
  104 
  105    // Fill in the product revision level field.
  106    // Per SAT, copy portions of the firmware revision that is not filled
  107    // with spaces.  Some devices left-align their firmware rev ID, while
  108    // others right-align.
  109    if (  (identify->firmware_revision[4] == 0x20)
  110        && (identify->firmware_revision[5] == 0x20)
  111        && (identify->firmware_revision[6] == 0x20)
  112        && (identify->firmware_revision[7] == 0x20) )
  113    {
  114       sati_ata_identify_device_copy_data(
  115          sequence,
  116          scsi_io,
  117          32,
  118          ata_input_data,
  119          ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision),
  120          4,
  121          TRUE
  122        );
  123    }
  124    else
  125    {
  126       // Since the last 4 bytes of the firmware revision are not spaces,
  127       // utilize these bytes as the firmware revision in the inquiry data.
  128       sati_ata_identify_device_copy_data(
  129          sequence,
  130          scsi_io,
  131          32,
  132          ata_input_data,
  133          ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision)+4,
  134          4,
  135          TRUE
  136       );
  137    }
  138 }
  139 
  140 
  141 //******************************************************************************
  142 //* P U B L I C   M E T H O D S
  143 //******************************************************************************
  144 
  145 /**
  146  * @brief This method builds the SCSI data associated with a SCSI standard
  147  *        inquiry request.
  148  *
  149  * @param[in]  sequence This parameter specifies the translator sequence
  150  *             object to be utilized during data translation.
  151  * @param[in]  ata_input_data This parameter specifies ata data received from
  152  *             the remote device.
  153  * @param[out] scsi_io This parameter specifies the user IO request for
  154  *             which to construct the standard inquiry data.
  155  *
  156  * @return none
  157  */
  158 void sati_inquiry_standard_translate_data(
  159    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  160    void                       * ata_input_data,
  161    void                       * scsi_io
  162 )
  163 {
  164    ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
  165                                            ata_input_data;
  166    U32  index;
  167 
  168    // Device type is disk, attached to this lun.
  169    sati_set_data_byte(sequence, scsi_io, 0, 0x00);
  170 
  171    // If the device indicates it's a removable media device, then set the
  172    // RMB bit
  173    if (identify->general_config_bits & ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE)
  174       sati_set_data_byte(sequence, scsi_io, 1, 0x80);
  175    else
  176       sati_set_data_byte(sequence, scsi_io, 1, 0x00);
  177 
  178    sati_set_data_byte(sequence, scsi_io, 2, 0x05); // Indicate SPC-3 support
  179    sati_set_data_byte(sequence, scsi_io, 3, 0x02); // Response Format SPC-3
  180 
  181    sati_set_data_byte(sequence, scsi_io, 4, 62); // 62 Additional Data Bytes.
  182                                                  // n-4 per the spec, we end at
  183                                                  // byte 66, so 66-4.
  184    sati_set_data_byte(sequence, scsi_io, 5, 0x00);
  185    sati_set_data_byte(sequence, scsi_io, 6, 0x00);
  186    sati_set_data_byte(sequence, scsi_io, 7, 0x02); // Enable Cmd Queueing
  187 
  188    // The Vender identification field is set to "ATA     "
  189    sati_set_data_byte(sequence, scsi_io, 8, 0x41);
  190    sati_set_data_byte(sequence, scsi_io, 9, 0x54);
  191    sati_set_data_byte(sequence, scsi_io, 10, 0x41);
  192    sati_set_data_byte(sequence, scsi_io, 11, 0x20);
  193    sati_set_data_byte(sequence, scsi_io, 12, 0x20);
  194    sati_set_data_byte(sequence, scsi_io, 13, 0x20);
  195    sati_set_data_byte(sequence, scsi_io, 14, 0x20);
  196    sati_set_data_byte(sequence, scsi_io, 15, 0x20);
  197 
  198    // Fill in the product ID field.
  199    sati_ata_identify_device_copy_data(
  200       sequence,
  201       scsi_io,
  202       16,
  203       ata_input_data,
  204       ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
  205       16,
  206       TRUE
  207    );
  208 
  209    sati_inquiry_construct_product_revision(
  210       sequence,
  211       ata_input_data,
  212       scsi_io
  213    );
  214 
  215    // Set the remaining fields up to the version descriptors to 0.
  216    for (index = 36; index < 58; index++)
  217       sati_set_data_byte(sequence, scsi_io, index, 0);
  218 
  219    // Add version descriptors for the various protocols in play.
  220 
  221    // SAM-4
  222    sati_set_data_byte(sequence, scsi_io, 58, 0);
  223    sati_set_data_byte(sequence, scsi_io, 59, 0x80);
  224 
  225    // SAS-2
  226    sati_set_data_byte(sequence, scsi_io, 60, 0x0C);
  227    sati_set_data_byte(sequence, scsi_io, 61, 0x20);
  228 
  229    // SPC-4
  230    sati_set_data_byte(sequence, scsi_io, 62, 0x04);
  231    sati_set_data_byte(sequence, scsi_io, 63, 0x60);
  232 
  233    // SBC-3
  234    sati_set_data_byte(sequence, scsi_io, 64, 0x04);
  235    sati_set_data_byte(sequence, scsi_io, 65, 0xC0);
  236 
  237    // ATA/ATAPI-8 ACS
  238    sati_set_data_byte(sequence, scsi_io, 66, 0x16);
  239    sati_set_data_byte(sequence, scsi_io, 67, 0x23);
  240 }
  241 
  242 /**
  243  * @brief This method builds the SCSI data associated with an SCSI inquiry
  244  *        for the supported VPD pages page.
  245  *
  246  * @param[in]  sequence This parameter specifies the translator sequence
  247  *             object to be utilized during data translation.
  248  * @param[out] scsi_io This parameter specifies the user IO request for
  249  *             which to construct the supported VPD page information.
  250  *
  251  * @return none
  252  */
  253 static
  254 void sati_inquiry_supported_pages_translate_data(
  255    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  256    void                       * scsi_io
  257 )
  258 {
  259    // Formulate the SCSI output data for the caller.
  260    sati_set_data_byte(sequence, scsi_io, 0, 0); // Qualifier and Device Type
  261    sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE);
  262    sati_set_data_byte(sequence, scsi_io, 2, 0); // Reserved.
  263    sati_set_data_byte(sequence, scsi_io, 3, 4); // # VPD pages supported
  264    sati_set_data_byte(sequence, scsi_io, 4, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE);
  265    sati_set_data_byte(sequence, scsi_io, 5, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE);
  266    sati_set_data_byte(sequence, scsi_io, 6, SCSI_INQUIRY_DEVICE_ID_PAGE);
  267    sati_set_data_byte(sequence, scsi_io, 7, SCSI_INQUIRY_ATA_INFORMATION_PAGE);
  268    sati_set_data_byte(sequence, scsi_io, 8, SCSI_INQUIRY_BLOCK_DEVICE_PAGE);
  269    sati_set_data_byte(sequence, scsi_io, 9, 0); // End of the list
  270 }
  271 
  272 /**
  273  * @brief This method builds the SCSI data associated with a request for
  274  *        the unit serial number vital product data (VPD) page.
  275  *
  276  * @param[in]  sequence This parameter specifies the translator sequence
  277  *             object to be utilized during data translation.
  278  * @param[in]  ata_input_data This parameter specifies ata data received from
  279  *             the remote device.
  280  * @param[out] scsi_io This parameter specifies the user IO request for
  281  *             which to construct the unit serial number data.
  282  *
  283  * @return none
  284  */
  285 void sati_inquiry_serial_number_translate_data(
  286    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  287    void                       * ata_input_data,
  288    void                       * scsi_io
  289 )
  290 {
  291    // Peripheral qualifier (0x0, currently connected)
  292    // Peripheral device type (0x0 direct-access block device)
  293    sati_set_data_byte(sequence, scsi_io, 0, 0x00);
  294 
  295    sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE);
  296    sati_set_data_byte(sequence, scsi_io, 2, 0x00);  // Reserved
  297    sati_set_data_byte(sequence, scsi_io, 3, ATA_IDENTIFY_SERIAL_NUMBER_LEN);
  298 
  299    sati_ata_identify_device_copy_data(
  300       sequence,
  301       scsi_io,
  302       4,
  303       ata_input_data,
  304       ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number),
  305       ATA_IDENTIFY_SERIAL_NUMBER_LEN,
  306       TRUE
  307    );
  308 }
  309 
  310 /**
  311 * @brief This method builds the SCSI data associated with a request for
  312 *        the Block Device Characteristics vital product data (VPD) page.
  313 *
  314 * @param[in]  sequence This parameter specifies the translator sequence
  315 *             object to be utilized during data translation.
  316 * @param[in]  ata_input_data This parameter specifies ata data received from
  317 *             the remote device.
  318 * @param[out] scsi_io This parameter specifies the user IO request for
  319 *             which to construct the unit serial number data.
  320 *
  321 * @return none
  322 */
  323 void sati_inquiry_block_device_translate_data(
  324    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  325    void                       * ata_input_data,
  326    void                       * scsi_io
  327 )
  328 {
  329    ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
  330       ata_input_data;
  331 
  332    U32 offset;
  333 
  334    // Peripheral qualifier (0x0, currently connected)
  335    // Peripheral device type (0x0 direct-access block device)
  336    sati_set_data_byte(sequence, scsi_io, 0, 0x00);
  337 
  338    sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_BLOCK_DEVICE_PAGE);
  339 
  340    //PAGE LENGTH 0x003C
  341    sati_set_data_byte(sequence, scsi_io, 2, 0x00);
  342    sati_set_data_byte(sequence, scsi_io, 3, SCSI_INQUIRY_BLOCK_DEVICE_LENGTH);
  343 
  344    sati_ata_identify_device_copy_data(
  345       sequence,
  346       scsi_io,
  347       4,
  348       ata_input_data,
  349       ATA_IDENTIFY_DEVICE_GET_OFFSET(nominal_media_rotation_rate),
  350       2,
  351       FALSE
  352     );
  353 
  354     sati_set_data_byte(sequence, scsi_io, 6, 0x00);
  355 
  356     sati_set_data_byte(
  357        sequence,
  358        scsi_io,
  359        7,
  360        (identify->device_nominal_form_factor & 0x0F) // only need bits 0-3
  361     );
  362 
  363     //bytes 8-63 are reserved
  364     for(offset = 8; offset < 64; offset++)
  365     {
  366        sati_set_data_byte(sequence, scsi_io, offset, 0x00);
  367     }
  368 }
  369 
  370 /**
  371  * @brief This method builds the SCSI data associated with a request for
  372  *        the device identification vital product data (VPD) page.
  373  *
  374  * @param[in]  sequence This parameter specifies the translator sequence
  375  *             object to be utilized during data translation.
  376  * @param[in]  ata_input_data This parameter specifies ata data received from
  377  *             the remote device.
  378  * @param[out] scsi_io This parameter specifies the user IO request for
  379  *             which to construct the device ID page.
  380  *
  381  * @return none
  382  */
  383 void sati_inquiry_device_id_translate_data(
  384    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  385    void                       * ata_input_data,
  386    void                       * scsi_io
  387 )
  388 {
  389    ATA_IDENTIFY_DEVICE_DATA_T * identify    = (ATA_IDENTIFY_DEVICE_DATA_T*)
  390                                               ata_input_data;
  391    U16                     byte_offset = 4;
  392    U16                     page_length;
  393 
  394    // Peripheral qualifier (0x0, currently connected)
  395    // Peripheral device type (0x0 direct-access block device)
  396    sati_set_data_byte(sequence, scsi_io, 0, 0x00);
  397 
  398    sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_DEVICE_ID_PAGE);
  399 
  400    /**
  401     * If World Wide Names are supported by this target, then build an
  402     * identification descriptor using the WWN.
  403     */
  404 
  405    if (identify->command_set_supported_extention
  406        & ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE)
  407    {
  408 
  409       sati_set_data_byte(sequence,
  410          scsi_io, 4, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET
  411       );
  412 
  413 
  414       sati_set_data_byte(sequence,
  415          scsi_io, 5, SCSI_LUN_ASSOCIATION | SCSI_NAA_IDENTIFIER_TYPE
  416       );
  417 
  418       sati_set_data_byte(sequence, scsi_io, 6, 0);
  419       sati_set_data_byte(sequence, scsi_io, 7, 0x08); // WWN are 8 bytes long
  420 
  421       // Copy data from the identify device world wide name field into the
  422       // buffer.
  423       sati_ata_identify_device_copy_data(
  424          sequence,
  425          scsi_io,
  426          8,
  427          ata_input_data,
  428          ATA_IDENTIFY_DEVICE_GET_OFFSET(world_wide_name),
  429          ATA_IDENTIFY_WWN_LEN,
  430          FALSE
  431       );
  432 
  433       byte_offset = 16;
  434    }
  435 
  436    /**
  437     * Build a identification descriptor using the model number & serial number.
  438     */
  439 
  440    sati_set_data_byte(sequence,
  441       scsi_io, byte_offset, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_ASCII_CODE_SET
  442    );
  443    byte_offset++;
  444    sati_set_data_byte(sequence,
  445       scsi_io, byte_offset, SCSI_LUN_ASSOCIATION | SCSI_T10_IDENTIFIER_TYPE
  446    );
  447    byte_offset++;
  448    sati_set_data_byte(sequence, scsi_io, byte_offset, 0);
  449    byte_offset++;
  450 
  451    // Identifier length (8 bytes for "ATA     " + 40 bytes from ATA IDENTIFY
  452    // model number field + 20 bytes from ATA IDENTIFY serial number field.
  453    sati_set_data_byte(
  454       sequence,
  455       scsi_io,
  456       byte_offset,
  457       8 + (ATA_IDENTIFY_SERIAL_NUMBER_LEN) + (ATA_IDENTIFY_MODEL_NUMBER_LEN)
  458    );
  459    byte_offset++;
  460 
  461    // Per SAT, write "ATA     ".
  462    sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41);
  463    byte_offset++;
  464    sati_set_data_byte(sequence, scsi_io, byte_offset, 0x54);
  465    byte_offset++;
  466    sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41);
  467    byte_offset++;
  468    sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
  469    byte_offset++;
  470    sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
  471    byte_offset++;
  472    sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
  473    byte_offset++;
  474    sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
  475    byte_offset++;
  476    sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
  477    byte_offset++;
  478 
  479    // Copy data from the identify device model number field into the
  480    // buffer and update the byte_offset.
  481    sati_ata_identify_device_copy_data(
  482       sequence,
  483       scsi_io,
  484       byte_offset,
  485       ata_input_data,
  486       ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
  487       ATA_IDENTIFY_MODEL_NUMBER_LEN,
  488       TRUE
  489    );
  490 
  491    byte_offset += ATA_IDENTIFY_MODEL_NUMBER_LEN;
  492 
  493    // Copy data from the identify device serial number field into the
  494    // buffer and update the byte_offset.
  495    sati_ata_identify_device_copy_data(
  496       sequence,
  497       scsi_io,
  498       byte_offset,
  499       ata_input_data,
  500       ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number),
  501       ATA_IDENTIFY_SERIAL_NUMBER_LEN,
  502       TRUE
  503    );
  504 
  505    byte_offset += ATA_IDENTIFY_SERIAL_NUMBER_LEN;
  506 
  507    /**
  508     * If the target is contained in a SAS Domain, then build a target port
  509     * ID descriptor using the SAS address.
  510     */
  511 
  512 #if     defined(SATI_TRANSPORT_SUPPORTS_SAS)       \
  513      && defined(DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT)
  514    {
  515       SCI_SAS_ADDRESS_T sas_address;
  516 
  517       sati_set_data_byte(
  518          sequence,
  519          scsi_io,
  520          byte_offset,
  521          SCSI_SAS_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET
  522       );
  523       byte_offset++;
  524 
  525       sati_set_data_byte(
  526          sequence,
  527          scsi_io,
  528          byte_offset,
  529          SCSI_PIV_ENABLE | SCSI_TARGET_PORT_ASSOCIATION |
  530          SCSI_NAA_IDENTIFIER_TYPE
  531       );
  532 
  533       byte_offset++;
  534       sati_set_data_byte(sequence, scsi_io, byte_offset, 0);
  535       byte_offset++;
  536       sati_set_data_byte(sequence, scsi_io, byte_offset, 8); // SAS Addr=8 bytes
  537       byte_offset++;
  538 
  539       sati_cb_device_get_sas_address(scsi_io, &sas_address);
  540 
  541       // Store the SAS address in the target port descriptor.
  542       sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.high);
  543       byte_offset += 4;
  544       sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.low);
  545       byte_offset += 4;
  546    }
  547 #endif // SATI_TRANSPORT_SUPPORTS_SAS && DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT
  548 
  549    /**
  550     * Set the Page length field.  The page length is n-3, where n is the
  551     * last offset in the page (considered page length - 4).
  552     */
  553 
  554    page_length = byte_offset - 4;
  555    sati_set_data_byte(sequence, scsi_io, 2, (U8)((page_length & 0xFF00) >> 8));
  556    sati_set_data_byte(sequence, scsi_io, 3, (U8)(page_length & 0x00FF));
  557 }
  558 
  559 /**
  560 * @brief This method builds the SCSI data associated with a request for
  561 *        the  ATA information vital product data (VPD) page.
  562 *
  563 * @param[in]  sequence This parameter specifies the translator sequence
  564 *             object to be utilized during data translation.
  565 * @param[in]  ata_input_data This parameter specifies ata data received from
  566 *             a identify device command processed by the remote device.
  567 * @param[out] scsi_io This parameter specifies the user IO request for
  568 *             which to construct the ATA information page.
  569 *
  570 * @return none
  571 */
  572 SATI_STATUS sati_inquiry_ata_information_translate_data(
  573    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  574    void                       * ata_input_data,
  575    void                       * scsi_io
  576 )
  577 {
  578    sati_set_data_byte(sequence, scsi_io, 0, 0x00);
  579    sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_ATA_INFORMATION_PAGE);
  580    sati_set_data_byte(sequence, scsi_io, 2, 0x02);
  581    sati_set_data_byte(sequence, scsi_io, 3, 0x38);
  582 
  583    //Reserved SAT2r07
  584    sati_set_data_byte(sequence, scsi_io, 4, 0x00);
  585    sati_set_data_byte(sequence, scsi_io, 5, 0x00);
  586    sati_set_data_byte(sequence, scsi_io, 6, 0x00);
  587    sati_set_data_byte(sequence, scsi_io, 7, 0x00);
  588 
  589    // The Vender identification field is set to "ATA     "
  590    sati_set_data_byte(sequence, scsi_io, 8, 0x41);
  591    sati_set_data_byte(sequence, scsi_io, 9, 0x54);
  592    sati_set_data_byte(sequence, scsi_io, 10, 0x41);
  593    sati_set_data_byte(sequence, scsi_io, 11, 0x20);
  594    sati_set_data_byte(sequence, scsi_io, 12, 0x20);
  595    sati_set_data_byte(sequence, scsi_io, 13, 0x20);
  596    sati_set_data_byte(sequence, scsi_io, 14, 0x20);
  597    sati_set_data_byte(sequence, scsi_io, 15, 0x20);
  598 
  599    //SAT Product identification
  600    sati_ata_identify_device_copy_data(
  601       sequence,
  602       scsi_io,
  603       16,
  604       ata_input_data,
  605       ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
  606       16,
  607       TRUE
  608    );
  609 
  610    //SAT Product Revision level bytes 32-35
  611    sati_inquiry_construct_product_revision(
  612       sequence,
  613       ata_input_data,
  614       scsi_io
  615    );
  616 
  617    //skipping ATA device signature for now
  618 
  619    //Command code
  620    sati_set_data_byte(sequence, scsi_io, 56, 0xEC);
  621 
  622    //Reserved SAT2r07
  623    sati_set_data_byte(sequence, scsi_io, 57, 0x00);
  624    sati_set_data_byte(sequence, scsi_io, 58, 0x00);
  625    sati_set_data_byte(sequence, scsi_io, 59, 0x00);
  626 
  627    //copy all ATA identify device data
  628    sati_ata_identify_device_copy_data(
  629       sequence,
  630       scsi_io,
  631       60,
  632       ata_input_data,
  633       0,
  634       sizeof(ATA_IDENTIFY_DEVICE_DATA_T),
  635       FALSE
  636    );
  637 
  638    //Need to send ATA Execute Device Diagnostic command still
  639    sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
  640 
  641    return SATI_SEQUENCE_INCOMPLETE;
  642 }
  643 
  644 /**
  645  * @brief This method will translate the inquiry SCSI command into
  646  *        an ATA IDENTIFY DEVICE command.  It will handle several different
  647  *        VPD pages and the standard inquiry page.
  648  *        For more information on the parameters passed to this method,
  649  *        please reference sati_translate_command().
  650  *
  651  * @return Indicate if the command translation succeeded.
  652  * @retval SCI_SUCCESS This is returned if the command translation was
  653  *         successful.
  654  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
  655  *         the page isn't supported, or the page code
  656  *         field is not zero when the EVPD bit is 0.
  657  */
  658 SATI_STATUS sati_inquiry_translate_command(
  659    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  660    void                       * scsi_io,
  661    void                       * ata_io
  662 )
  663 {
  664    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
  665 
  666    /**
  667     * SPC dictates:
  668     * - that the page code field must be 0, if VPD enable is 0.
  669     */
  670    if (  ((sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) == 0)
  671       && (sati_get_cdb_byte(cdb, 2) != 0) )
  672    {
  673       sati_scsi_sense_data_construct(
  674          sequence,
  675          scsi_io,
  676          SCSI_STATUS_CHECK_CONDITION,
  677          SCSI_SENSE_ILLEGAL_REQUEST,
  678          SCSI_ASC_INVALID_FIELD_IN_CDB,
  679          SCSI_ASCQ_INVALID_FIELD_IN_CDB
  680       );
  681       return SATI_FAILURE_CHECK_RESPONSE_DATA;
  682    }
  683 
  684    // Set the data length based on the allocation length field in the CDB.
  685    sequence->allocation_length = (sati_get_cdb_byte(cdb, 3) << 8) |
  686                                  (sati_get_cdb_byte(cdb, 4));
  687 
  688    // Check to see if there was a request for the vital product data or just
  689    // the standard inquiry.
  690    if (sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE)
  691    {
  692       // Parse the page code to determine which translator to invoke.
  693       switch (sati_get_cdb_byte(cdb, 2))
  694       {
  695          case SCSI_INQUIRY_SUPPORTED_PAGES_PAGE:
  696             sequence->type  = SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES;
  697             sati_inquiry_supported_pages_translate_data(sequence, scsi_io);
  698             return SATI_COMPLETE;
  699          break;
  700 
  701          case SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE:
  702             sequence->type = SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER;
  703          break;
  704 
  705          case SCSI_INQUIRY_DEVICE_ID_PAGE:
  706             sequence->type = SATI_SEQUENCE_INQUIRY_DEVICE_ID;
  707          break;
  708 
  709          case SCSI_INQUIRY_ATA_INFORMATION_PAGE:
  710 
  711             if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
  712             {
  713                sati_ata_execute_device_diagnostic_construct(
  714                   ata_io,
  715                   sequence
  716                );
  717                sequence->type = SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG;
  718             }
  719             else
  720             {
  721                sequence->type = SATI_SEQUENCE_INQUIRY_ATA_INFORMATION;
  722             }
  723          break;
  724 
  725          case SCSI_INQUIRY_BLOCK_DEVICE_PAGE:
  726             sequence->type = SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE;
  727          break;
  728 
  729          default:
  730             sati_scsi_sense_data_construct(
  731                sequence,
  732                scsi_io,
  733                SCSI_STATUS_CHECK_CONDITION,
  734                SCSI_SENSE_ILLEGAL_REQUEST,
  735                SCSI_ASC_INVALID_FIELD_IN_CDB,
  736                SCSI_ASCQ_INVALID_FIELD_IN_CDB
  737             );
  738             return SATI_FAILURE_CHECK_RESPONSE_DATA;
  739          break;
  740       }
  741    }
  742    else
  743    {
  744       sequence->type = SATI_SEQUENCE_INQUIRY_STANDARD;
  745    }
  746 
  747    sati_ata_identify_device_construct(ata_io, sequence);
  748 
  749    return SATI_SUCCESS;
  750 }
  751 
  752 /**
  753 * @brief This method finishes the construction of the SCSI data associated
  754          with a request for the  ATA information vital product data (VPD) page.
  755          The ATA device signature is written into the data response from the
  756          task fle registers after issuing a Execute Device Diagnostic command.
  757 *
  758 * @param[in]  sequence This parameter specifies the translator sequence
  759 *             object to be utilized during data translation.
  760 * @param[out] scsi_io This parameter specifies the user IO request for
  761 *             which to construct the ATA information page.
  762 * @param[in]  ata_io This parameter specifies the ATA payload
  763 *             buffer location and size to be translated.
  764 *
  765 * @return none
  766 */
  767 void sati_inquiry_ata_information_finish_translation(
  768    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  769    void                       * scsi_io,
  770    void                       * ata_io
  771 )
  772 {
  773    U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
  774    U32 offset;
  775 
  776    //SATA transport
  777    sati_set_data_byte(sequence, scsi_io, 36, 0x34);
  778    sati_set_data_byte(sequence, scsi_io, 37, 0x00);
  779    sati_set_data_byte(sequence, scsi_io, 38, (U8) sati_get_ata_status(register_fis));
  780    sati_set_data_byte(sequence, scsi_io, 39, (U8) sati_get_ata_error(register_fis));
  781    sati_set_data_byte(sequence, scsi_io, 40, sati_get_ata_lba_low(register_fis));
  782    sati_set_data_byte(sequence, scsi_io, 41, sati_get_ata_lba_mid(register_fis));
  783    sati_set_data_byte(sequence, scsi_io, 42, sati_get_ata_lba_high(register_fis));
  784    sati_set_data_byte(sequence, scsi_io, 43, sati_get_ata_device(register_fis));
  785    sati_set_data_byte(sequence, scsi_io, 44, sati_get_ata_lba_low_ext(register_fis));
  786    sati_set_data_byte(sequence, scsi_io, 45, sati_get_ata_lba_mid_ext(register_fis));
  787    sati_set_data_byte(sequence, scsi_io, 46, sati_get_ata_lba_high_ext(register_fis));
  788    sati_set_data_byte(sequence, scsi_io, 47, 0x00);
  789    sati_set_data_byte(sequence, scsi_io, 48, sati_get_ata_sector_count(register_fis));
  790    sati_set_data_byte(sequence, scsi_io, 49, sati_get_ata_sector_count_exp(register_fis));
  791 
  792    for(offset = 50; offset < 56; offset++)
  793    {
  794       sati_set_data_byte(sequence, scsi_io, offset, 0x00);
  795    }
  796 
  797    sequence->state = SATI_SEQUENCE_STATE_FINAL;
  798 }
  799 
  800 #endif // !defined(DISABLE_SATI_INQUIRY)
  801 

Cache object: 3e7f760313ac54620b24b0a52612e3de


[ 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.