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_read_capacity.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 the method implementations required to
   61  *        translate the SCSI read capacity (10 byte) command.
   62  */
   63 
   64 #if !defined(DISABLE_SATI_READ_CAPACITY)
   65 
   66 #include <dev/isci/scil/sati_read_capacity.h>
   67 #include <dev/isci/scil/sati_callbacks.h>
   68 #include <dev/isci/scil/sati_util.h>
   69 #include <dev/isci/scil/intel_ata.h>
   70 #include <dev/isci/scil/intel_scsi.h>
   71 
   72 /**
   73  * @brief This method will translate the read capacity 10 SCSI command into
   74  *        an ATA IDENTIFY DEVICE command.
   75  *        For more information on the parameters passed to this method,
   76  *        please reference sati_translate_command().
   77  *
   78  * @return Indicate if the command translation succeeded.
   79  * @retval SCI_SUCCESS This is returned if the command translation was
   80  *         successful.
   81  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
   82  *         LBA field is not 0, the PMI bit is not 0.
   83  */
   84 SATI_STATUS sati_read_capacity_10_translate_command(
   85    SATI_TRANSLATOR_SEQUENCE_T * sequence,
   86    void                       * scsi_io,
   87    void                       * ata_io
   88 )
   89 {
   90    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
   91 
   92    /**
   93     * SAT dictates:
   94     * - the LBA field must be 0
   95     * - the PMI bit must be 0
   96     */
   97    if (
   98          (
   99             (sati_get_cdb_byte(cdb, 2) != 0)
  100          || (sati_get_cdb_byte(cdb, 3) != 0)
  101          || (sati_get_cdb_byte(cdb, 4) != 0)
  102          || (sati_get_cdb_byte(cdb, 5) != 0)
  103          )
  104          || ((sati_get_cdb_byte(cdb, 8) & SCSI_READ_CAPACITY_PMI_BIT_ENABLE)
  105               == 1)
  106       )
  107    {
  108       sati_scsi_sense_data_construct(
  109          sequence,
  110          scsi_io,
  111          SCSI_STATUS_CHECK_CONDITION,
  112          SCSI_SENSE_ILLEGAL_REQUEST,
  113          SCSI_ASC_INVALID_FIELD_IN_CDB,
  114          SCSI_ASCQ_INVALID_FIELD_IN_CDB
  115       );
  116       return SATI_FAILURE_CHECK_RESPONSE_DATA;
  117    }
  118 
  119    // The CDB is properly formed.
  120    sequence->allocation_length = SCSI_READ_CAPACITY_10_DATA_LENGTH;
  121    sequence->type              = SATI_SEQUENCE_READ_CAPACITY_10;
  122 
  123    sati_ata_identify_device_construct(ata_io, sequence);
  124    return SATI_SUCCESS;
  125 }
  126 
  127 
  128 
  129 /**
  130  * @brief This method will translate the read capacity 16 SCSI command into
  131  *        an ATA IDENTIFY DEVICE command.
  132  *        For more information on the parameters passed to this method,
  133  *        please reference sati_translate_command().
  134  *
  135  * @return Indicate if the command translation succeeded.
  136  * @retval SCI_SUCCESS This is returned if the command translation was
  137  *         successful.
  138  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
  139  *         LBA field is not 0, the PMI bit is not 0.
  140  */
  141 SATI_STATUS sati_read_capacity_16_translate_command(
  142    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  143    void                       * scsi_io,
  144    void                       * ata_io
  145 )
  146 {
  147    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
  148 
  149    /**
  150     * SAT dictates:
  151     * - the LBA field must be 0
  152     * - the PMI bit must be 0
  153     */
  154    if (
  155          (
  156             (sati_get_cdb_byte(cdb, 2) != 0)
  157          || (sati_get_cdb_byte(cdb, 3) != 0)
  158          || (sati_get_cdb_byte(cdb, 4) != 0)
  159          || (sati_get_cdb_byte(cdb, 5) != 0)
  160          || (sati_get_cdb_byte(cdb, 6) != 0)
  161          || (sati_get_cdb_byte(cdb, 7) != 0)
  162          || (sati_get_cdb_byte(cdb, 8) != 0)
  163          || (sati_get_cdb_byte(cdb, 9) != 0)
  164          )
  165          || ((sati_get_cdb_byte(cdb, 14) & SCSI_READ_CAPACITY_PMI_BIT_ENABLE)
  166               == 1)
  167       )
  168    {
  169       sati_scsi_sense_data_construct(
  170          sequence,
  171          scsi_io,
  172          SCSI_STATUS_CHECK_CONDITION,
  173          SCSI_SENSE_ILLEGAL_REQUEST,
  174          SCSI_ASC_INVALID_FIELD_IN_CDB,
  175          SCSI_ASCQ_INVALID_FIELD_IN_CDB
  176       );
  177       return SATI_FAILURE_CHECK_RESPONSE_DATA;
  178    }
  179 
  180    // The CDB is properly formed.
  181    sequence->allocation_length = (sati_get_cdb_byte(cdb, 10) << 24) |
  182                                  (sati_get_cdb_byte(cdb, 11) << 16) |
  183                                  (sati_get_cdb_byte(cdb, 12) << 8)  |
  184                                  (sati_get_cdb_byte(cdb, 13));
  185 
  186    sequence->type              = SATI_SEQUENCE_READ_CAPACITY_16;
  187 
  188    sati_ata_identify_device_construct(ata_io, sequence);
  189    return SATI_SUCCESS;
  190 }
  191 
  192 /**
  193  * @brief This method will translate the ATA Identify Device data into
  194  *        SCSI read capacity 10 data.
  195  *        For more information on the parameters passed to this method,
  196  *        please reference sati_translate_data().
  197  *
  198  * @return none
  199  */
  200 void sati_read_capacity_10_translate_data(
  201    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  202    void                       * ata_input_data,
  203    void                       * scsi_io
  204 )
  205 {
  206    U32  lba_low     = 0;
  207    U32  lba_high    = 0;
  208    U32  sector_size = 0;
  209 
  210    // Extract the sector information (sector size, logical blocks) from
  211    // the retrieved ATA identify device data.
  212    sati_ata_identify_device_get_sector_info(
  213       (ATA_IDENTIFY_DEVICE_DATA_T*)ata_input_data,
  214       &lba_high,
  215       &lba_low,
  216       &sector_size
  217    );
  218 
  219    // SATA drives report a value that is one LBA larger than the last LBA.
  220    // SCSI wants the last LBA.  Make the correction here.  lba_low is
  221    // always decremented since it is an unsigned long the value 0 will
  222    // wrap to 0xFFFFFFFF.
  223    if ((lba_low == 0) && (lba_high == 0))
  224       lba_high -= 1;
  225    lba_low -= 1;
  226 
  227    if(lba_high != 0)
  228    {
  229       sati_set_data_byte(sequence, scsi_io, 0, 0xFF);
  230       sati_set_data_byte(sequence, scsi_io, 1, 0xFF);
  231       sati_set_data_byte(sequence, scsi_io, 2, 0xFF);
  232       sati_set_data_byte(sequence, scsi_io, 3, 0xFF);
  233    }
  234    else
  235    {
  236       // Build CDB for Read Capacity 10
  237       // Fill in the Logical Block Address bytes.
  238       sati_set_data_byte(sequence, scsi_io, 0, (U8)((lba_low >> 24) & 0xFF));
  239       sati_set_data_byte(sequence, scsi_io, 1, (U8)((lba_low >> 16) & 0xFF));
  240       sati_set_data_byte(sequence, scsi_io, 2, (U8)((lba_low >> 8)  & 0xFF));
  241       sati_set_data_byte(sequence, scsi_io, 3, (U8)(lba_low & 0xFF));
  242    }
  243    // Fill in the sector size field.
  244    sati_set_data_byte(sequence, scsi_io, 4, (U8)((sector_size >> 24) & 0xFF));
  245    sati_set_data_byte(sequence, scsi_io, 5, (U8)((sector_size >> 16) & 0xFF));
  246    sati_set_data_byte(sequence, scsi_io, 6, (U8)((sector_size >> 8)  & 0xFF));
  247    sati_set_data_byte(sequence, scsi_io, 7, (U8)(sector_size & 0xFF));
  248 }
  249 
  250 /**
  251  * @brief This method will translate the ATA Identify Device data into
  252  *        SCSI read capacity 16 data.
  253  *        For more information on the parameters passed to this method,
  254  *        please reference sati_translate_data().
  255  *
  256  * @return none
  257  */
  258 void sati_read_capacity_16_translate_data(
  259    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  260    void                       * ata_input_data,
  261    void                       * scsi_io
  262 )
  263 {
  264    U32  lba_low     = 0;
  265    U32  lba_high    = 0;
  266    U32  sector_size = 0;
  267    ATA_IDENTIFY_DEVICE_DATA_T * identify_device_data;
  268    U16  physical_per_logical_enable_bit = 0;
  269    U8   physical_per_logical_sector_exponent = 0;
  270    U16  physical_per_logical_sector = 0;
  271    U16  logical_sector_alignment = 0;
  272    U16  scsi_logical_sector_alignment = 0;
  273    U8   byte14 = 0;
  274 
  275    //A number of data fields need to be extracted from ATA identify device data
  276    identify_device_data = (ATA_IDENTIFY_DEVICE_DATA_T*)ata_input_data;
  277 
  278    // Extract the sector information (sector size, logical blocks) from
  279    // the retrieved ATA identify device data.
  280    sati_ata_identify_device_get_sector_info(
  281       (ATA_IDENTIFY_DEVICE_DATA_T*)ata_input_data,
  282       &lba_high,
  283       &lba_low,
  284       &sector_size
  285    );
  286 
  287    // SATA drives report a value that is one LBA larger than the last LBA.
  288    // SCSI wants the last LBA.  Make the correction here.  lba_low is
  289    // always decremented since it is an unsigned long the value 0 will
  290    // wrap to 0xFFFFFFFF.
  291    if ((lba_low == 0) && (lba_high == 0))
  292       lba_high -= 1;
  293    lba_low -= 1;
  294 
  295    // Build the CDB for Read Capacity 16
  296    // Fill in the Logical Block Address bytes.
  297    sati_set_data_byte(sequence, scsi_io, 0, (U8)((lba_high >> 24) & 0xFF));
  298    sati_set_data_byte(sequence, scsi_io, 1, (U8)((lba_high >> 16) & 0xFF));
  299    sati_set_data_byte(sequence, scsi_io, 2, (U8)((lba_high >> 8)  & 0xFF));
  300    sati_set_data_byte(sequence, scsi_io, 3, (U8)(lba_high & 0xFF));
  301 
  302    sati_set_data_byte(sequence, scsi_io, 4, (U8)((lba_low >> 24) & 0xFF));
  303    sati_set_data_byte(sequence, scsi_io, 5, (U8)((lba_low >> 16) & 0xFF));
  304    sati_set_data_byte(sequence, scsi_io, 6, (U8)((lba_low >> 8)  & 0xFF));
  305    sati_set_data_byte(sequence, scsi_io, 7, (U8)(lba_low & 0xFF));
  306 
  307    //Fill in the sector size field.
  308    sati_set_data_byte(sequence, scsi_io, 8,  (U8)((sector_size >> 24) & 0xFF));
  309    sati_set_data_byte(sequence, scsi_io, 9,  (U8)((sector_size >> 16) & 0xFF));
  310    sati_set_data_byte(sequence, scsi_io, 10, (U8)((sector_size >> 8)  & 0xFF));
  311    sati_set_data_byte(sequence, scsi_io, 11, (U8)(sector_size & 0xFF));
  312 
  313    //Explicitly set byte 12 to 0.  SATI requires that all bytes in the data
  314    //response be explicitly set to some value.
  315    sati_set_data_byte(sequence, scsi_io, 12, 0);
  316 
  317    //Check Bit 13 of ATA_IDENTIFY_DEVICE_DATA physical_logical_sector_info
  318    //(Word 106) is enabled
  319    physical_per_logical_enable_bit = (identify_device_data->physical_logical_sector_info
  320       & ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE);
  321 
  322    //Extract the Physical per logical sector exponent field and calculate
  323    //Physical per logical sector value
  324    physical_per_logical_sector_exponent = (U8) (identify_device_data->physical_logical_sector_info
  325       & ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_MASK);
  326    physical_per_logical_sector = 1 << (physical_per_logical_sector_exponent);
  327 
  328    //If the data is valid, fill in the logical blocks per physical block exponent field.
  329    //Else set logical blocks per physical block exponent to 1
  330    if (physical_per_logical_enable_bit != 0)
  331       sati_set_data_byte(
  332          sequence,
  333          scsi_io,
  334          13,
  335          (U8)(physical_per_logical_sector_exponent & 0xFF)
  336       );
  337    else
  338       sati_set_data_byte(sequence, scsi_io, 13, 0);
  339 
  340    //Fill in the lowest aligned logical block address field.
  341    logical_sector_alignment = identify_device_data->logical_sector_alignment;
  342    if (logical_sector_alignment == 0)
  343       scsi_logical_sector_alignment = 0;
  344    else
  345       scsi_logical_sector_alignment = (physical_per_logical_sector - logical_sector_alignment)
  346          % physical_per_logical_sector;
  347 
  348    //Follow SAT for reporting tprz and tpe
  349    if ((sequence->device->capabilities & SATI_DEVICE_CAP_DSM_TRIM_SUPPORT) &&
  350        (sequence->device->capabilities & SATI_DEVICE_CAP_DETERMINISTIC_READ_AFTER_TRIM))
  351    {
  352       // tpe
  353       byte14 |= 0x80;
  354       // tprz
  355       if (sequence->device->capabilities & SATI_DEVICE_CAP_READ_ZERO_AFTER_TRIM)
  356           byte14 |= 0x40;
  357    }
  358    sati_set_data_byte(
  359        sequence,
  360        scsi_io,
  361        14,
  362        (U8)(((scsi_logical_sector_alignment >>8) & 0x3F) | byte14));
  363 
  364    sati_set_data_byte(
  365        sequence,
  366        scsi_io,
  367        15,
  368        (U8)(scsi_logical_sector_alignment & 0xFF));
  369 }
  370 
  371 #endif // !defined(DISABLE_SATI_READ_CAPACITY)
  372 

Cache object: dfc5ac63e9cf3224908d2835ce9f7846


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