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_mode_sense.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 mode sense (6 and 10-byte) commands.
   62  */
   63 
   64 #if !defined(DISABLE_SATI_MODE_SENSE)
   65 
   66 #include <dev/isci/scil/sati_mode_sense.h>
   67 #include <dev/isci/scil/sati_mode_pages.h>
   68 #include <dev/isci/scil/sati_callbacks.h>
   69 #include <dev/isci/scil/sati_util.h>
   70 #include <dev/isci/scil/intel_scsi.h>
   71 #include <dev/isci/scil/intel_ata.h>
   72 
   73 //******************************************************************************
   74 //* P R I V A T E   M E T H O D S
   75 //******************************************************************************
   76 
   77 #define STANDBY_TIMER_DISABLED  0x00
   78 #define STANDBY_TIMER_ENABLED   0x01
   79 #define STANDBY_TIMER_SUPPORTED 0x2000
   80 
   81 
   82 
   83 /**
   84  * @brief This method indicates if the supplied page control is supported
   85  *        by this translation implementation.  Currently savable parameters
   86  *        (i.e. non-volatile) are not supported.
   87  *        For more information on the parameters passed to this method,
   88  *        please reference sati_translate_command().
   89  *
   90  * @return This method returns an indication of whether the page control
   91  *         specified in the SCSI CDB is supported.
   92  * @retval SATI_SUCCESS This value is returned if the page control is
   93  *         supported.
   94  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
   95  *         page control is not supported.
   96  */
   97 static
   98 SATI_STATUS sati_mode_sense_is_page_control_supported(
   99    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  100    void                       * scsi_io
  101 )
  102 {
  103    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
  104 
  105    switch (sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT)
  106    {
  107       case SCSI_MODE_SENSE_PC_CURRENT:
  108       case SCSI_MODE_SENSE_PC_DEFAULT:
  109       case SCSI_MODE_SENSE_PC_CHANGEABLE:
  110          return SATI_SUCCESS;
  111       break;
  112 
  113       default:
  114       case SCSI_MODE_SENSE_PC_SAVED:
  115          sati_scsi_sense_data_construct(
  116             sequence,
  117             scsi_io,
  118             SCSI_STATUS_CHECK_CONDITION,
  119             SCSI_SENSE_ILLEGAL_REQUEST,
  120             SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED,
  121             SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED
  122          );
  123          return SATI_FAILURE_CHECK_RESPONSE_DATA;
  124       break;
  125    }
  126 }
  127 
  128 /**
  129  * @brief This method indicates if the page code field in the SCSI CDB
  130  *        is supported by this translation.
  131  *        For more information on the parameters passed to this method,
  132  *        please reference sati_translate_command().
  133  *
  134  * @param[in] cdb_length This parameter specifies the length of the SCSI
  135  *            CDB being translated (e.g. 6-byte, 10-byte, 12-byte, etc.)
  136  *
  137  * @return This method returns an indication as to whether the page code
  138  *         in the CDB is supported.
  139  * @retval SATI_SUCCESS This value is returned if the page code is
  140  *         supported.
  141  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
  142  *         page code is not supported.
  143  */
  144 static
  145 SATI_STATUS sati_mode_sense_is_page_code_supported(
  146    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  147    void                       * scsi_io,
  148    U8                           cdb_length
  149 )
  150 {
  151    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
  152 
  153    switch (sati_get_cdb_byte(cdb, 2) & SCSI_MODE_SENSE_PAGE_CODE_ENABLE)
  154    {
  155       case SCSI_MODE_PAGE_CACHING:
  156          if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
  157             sequence->type = SATI_SEQUENCE_MODE_SENSE_6_CACHING;
  158          else
  159             sequence->type = SATI_SEQUENCE_MODE_SENSE_10_CACHING;
  160       break;
  161 
  162       case SCSI_MODE_PAGE_ALL_PAGES:
  163          if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
  164             sequence->type = SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES;
  165          else
  166             sequence->type = SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES;
  167       break;
  168 
  169       case SCSI_MODE_PAGE_READ_WRITE_ERROR:
  170          if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
  171             sequence->type = SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR;
  172          else
  173             sequence->type = SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR;
  174       break;
  175 
  176       case SCSI_MODE_PAGE_DISCONNECT_RECONNECT:
  177          if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
  178             sequence->type = SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT;
  179          else
  180             sequence->type = SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT;
  181       break;
  182 
  183       case SCSI_MODE_PAGE_CONTROL:
  184          if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
  185             sequence->type = SATI_SEQUENCE_MODE_SENSE_6_CONTROL;
  186          else
  187             sequence->type = SATI_SEQUENCE_MODE_SENSE_10_CONTROL;
  188       break;
  189 
  190       case SCSI_MODE_PAGE_POWER_CONDITION:
  191          if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
  192             sequence->type = SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION;
  193          else
  194             sequence->type = SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION;
  195       break;
  196 
  197       case SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL:
  198          // The informational exceptions control page is only useful
  199          // if SMART is supported.
  200          if ((sequence->device->capabilities | SATI_DEVICE_CAP_SMART_SUPPORT)
  201              == 0)
  202          {
  203             // For a MODE SENSE, utilize INVALID FIELD IN CDB,
  204             // For a MODE SELECT, utilize INVALID FIELD IN PARAMETER LIST.
  205             if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
  206             {
  207                sati_scsi_sense_data_construct(
  208                   sequence,
  209                   scsi_io,
  210                   SCSI_STATUS_CHECK_CONDITION,
  211                   SCSI_SENSE_ILLEGAL_REQUEST,
  212                   SCSI_ASC_INVALID_FIELD_IN_CDB,
  213                   SCSI_ASCQ_INVALID_FIELD_IN_CDB
  214                );
  215             }
  216             else
  217             {
  218                sati_scsi_sense_data_construct(
  219                   sequence,
  220                   scsi_io,
  221                   SCSI_STATUS_CHECK_CONDITION,
  222                   SCSI_SENSE_ILLEGAL_REQUEST,
  223                   SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
  224                   SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
  225                );
  226             }
  227 
  228             return SATI_FAILURE_CHECK_RESPONSE_DATA;
  229          }
  230 
  231          if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
  232             sequence->type = SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL;
  233          else
  234             sequence->type = SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL;
  235       break;
  236 
  237       default:
  238          sati_scsi_sense_data_construct(
  239             sequence,
  240             scsi_io,
  241             SCSI_STATUS_CHECK_CONDITION,
  242             SCSI_SENSE_ILLEGAL_REQUEST,
  243             SCSI_ASC_INVALID_FIELD_IN_CDB,
  244             SCSI_ASCQ_INVALID_FIELD_IN_CDB
  245          );
  246          return SATI_FAILURE_CHECK_RESPONSE_DATA;
  247       break;
  248    }
  249 
  250    return SATI_SUCCESS;
  251 }
  252 
  253 //******************************************************************************
  254 //* P R O T E C T E D   M E T H O D S
  255 //******************************************************************************
  256 
  257 /**
  258  * @brief This method will calculate the size of the mode sense data header.
  259  *        This includes the block descriptor if one is requested.
  260  *
  261  * @param[in] scsi_io This parameter specifies the user's SCSI IO object
  262  *            for which to calculate the mode page header.
  263  * @param[in] cdb_size This parameter specifies the number of bytes
  264  *            associated with the CDB for which to calculate the header.
  265  *
  266  * @return This method returns the size, in bytes, for the mode page header.
  267  */
  268 U16 sati_mode_sense_calculate_page_header(
  269    void * scsi_io,
  270    U8     cdb_size
  271 )
  272 {
  273    U8 * cdb         = sati_cb_get_cdb_address(scsi_io);
  274    U16  page_length = 0;
  275 
  276    // The Mode page header length is different for 6-byte vs. 10-byte CDBs.
  277    if (cdb_size == 6)
  278       page_length += SCSI_MODE_SENSE_6_HEADER_LENGTH;
  279    else
  280       page_length += SCSI_MODE_SENSE_10_HEADER_LENGTH;
  281 
  282    // Are block descriptors disabled (DBD)?  0 indicates they are enabled.
  283    if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE) == 0)
  284    {
  285       // The LLBAA bit is not defined for 6-byte mode sense requests.
  286       if (  (cdb_size == 10)
  287          && (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_LLBAA_ENABLE) )
  288          page_length += SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH;
  289       else
  290          page_length += SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH;
  291    }
  292 
  293    return page_length;
  294 }
  295 
  296 /**
  297  * @brief This method performs command translation common to all mode sense
  298  *        requests (6 or 10 byte).
  299  *        For more information on the parameters passed to this method,
  300  *        please reference sati_translate_command().
  301  *
  302  * @param[in] cdb_length This parameter specifies the number of bytes
  303  *            in the CDB (6 or 10).
  304  *
  305  * @return This method returns an indication as to whether the translation
  306  *         succeeded.
  307  * @retval SCI_SUCCESS This value is returned if translation succeeded.
  308  * @see sati_mode_sense_is_page_control_supported() or
  309  *      sati_mode_sense_is_page_code_supported() for more information.
  310  */
  311 SATI_STATUS sati_mode_sense_translate_command(
  312    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  313    void                       * scsi_io,
  314    void                       * ata_io,
  315    U8                           cdb_length
  316 )
  317 {
  318    SATI_STATUS   status;
  319 
  320    /**
  321     * Validate that the supplied page control (PC) field is supported.
  322     */
  323    status = sati_mode_sense_is_page_control_supported(sequence, scsi_io);
  324    if (status != SATI_SUCCESS)
  325       return status;
  326 
  327    /**
  328     * Validate that the supplied page code is supported.
  329     */
  330    status = sati_mode_sense_is_page_code_supported(sequence,scsi_io,cdb_length);
  331    if (status != SATI_SUCCESS)
  332       return status;
  333 
  334    sati_ata_identify_device_construct(ata_io, sequence);
  335 
  336    return SATI_SUCCESS;
  337 }
  338 
  339 /**
  340  * @brief This method will build the standard block descriptor for a MODE
  341  *        SENSE 6 or 10 byte request.
  342  *        For more information on the parameters passed to this method,
  343  *        please reference sati_translate_command().
  344  *
  345  * @param[in] identify This parameter specifies the IDENTIFY DEVICE data
  346  *            associated with the SCSI IO.
  347  * @param[in] offset This parameter specifies the offset into the data
  348  *            buffer at which to build the block descriptor.
  349  *
  350  * @return This method returns the size of the block descriptor built.
  351  */
  352 U32 sati_mode_sense_build_std_block_descriptor(
  353    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  354    void                       * scsi_io,
  355    ATA_IDENTIFY_DEVICE_DATA_T * identify,
  356    U32                          offset
  357 )
  358 {
  359    U32  lba_low     = 0;
  360    U32  lba_high    = 0;
  361    U32  sector_size = 0;
  362 
  363    // Extract the sector information (sector size, logical blocks) from
  364    // the retrieved ATA identify device data.
  365    sati_ata_identify_device_get_sector_info(
  366       identify, &lba_high, &lba_low, &sector_size
  367    );
  368 
  369    // Fill in the 4-byte logical block address field.
  370    sati_set_data_byte(sequence, scsi_io, offset,   (U8)((lba_low>>24) & 0xFF));
  371    sati_set_data_byte(sequence, scsi_io, offset+1, (U8)((lba_low>>16) & 0xFF));
  372    sati_set_data_byte(sequence, scsi_io, offset+2, (U8)((lba_low>>8)  & 0xFF));
  373    sati_set_data_byte(sequence, scsi_io, offset+3, (U8)(lba_low & 0xFF));
  374 
  375    // Clear the reserved field.
  376    sati_set_data_byte(sequence, scsi_io, offset+4, 0);
  377 
  378    // Fill in the three byte Block Length field
  379    sati_set_data_byte(sequence,scsi_io, offset+5, (U8)((sector_size>>16) & 0xFF));
  380    sati_set_data_byte(sequence,scsi_io, offset+6, (U8)((sector_size>>8)  & 0xFF));
  381    sati_set_data_byte(sequence,scsi_io, offset+7, (U8)(sector_size & 0xFF));
  382 
  383    return SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH;
  384 }
  385 
  386 /**
  387  * @brief This method simply copies the mode sense data into the buffer
  388  *        at the location specified by page_start.  The buffer copied is
  389  *        determined by page_control (e.g. current, default, or changeable
  390  *        values).
  391  *        For more information on the parameters passed to this method,
  392  *        please reference sati_translate_command().
  393  *
  394  * @param[in] page_start This parameter specifies the starting offset at
  395  *            which to copy the mode page data.
  396  * @param[in] page_control This parameter specifies the page control
  397  *            indicating the source buffer to be copied.
  398  * @param[in] page_code This specifies the mode sense page to copy.
  399  *
  400  * @return This method returns the size of the mode page data being copied.
  401  */
  402 U32 sati_mode_sense_copy_initial_data(
  403    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  404    void                       * scsi_io,
  405    U32                          page_start,
  406    U8                           page_control,
  407    U8                           page_code
  408 )
  409 {
  410    U16 page_index  = sati_mode_page_get_page_index(page_code);
  411    U32 page_length = sat_mode_page_sizes[page_index];
  412 
  413    // Find out if the current values are requested or if the default
  414    // values are being requested.
  415    if (page_control == SCSI_MODE_SENSE_PC_CHANGEABLE)
  416    {
  417       // Copy the changeable mode page information.
  418       sati_copy_data(
  419          sequence,
  420          scsi_io,
  421          page_start,
  422          sat_changeable_mode_pages[page_index],
  423          page_length
  424       );
  425    }
  426    else
  427    {
  428       // Copy the default static values template to the user data area.
  429       sati_copy_data(
  430          sequence,
  431          scsi_io,
  432          page_start,
  433          sat_default_mode_pages[page_index],
  434          page_length
  435       );
  436    }
  437 
  438    return page_length;
  439 }
  440 
  441 /**
  442  * @brief This method performs the read/write error recovery mode page
  443  *        specific data translation based upon the contents of the remote
  444  *        device IDENTIFY DEVICE data.
  445  *        For more information on the parameters passed to this method,
  446  *        please reference sati_translate_command().
  447  *
  448  * @param[in] identify This parameter specifies the remote device's
  449  *            IDENTIFY DEVICE data received as part of the IO request.
  450  * @param[in] offset This parameter specifies the offset into the data
  451  *            buffer where the translated data is to be written.
  452  *
  453  * @return This method returns the size of the mode page data that was
  454  *         translated.
  455  */
  456 U32 sati_mode_sense_read_write_error_translate_data(
  457    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  458    void                       * scsi_io,
  459    ATA_IDENTIFY_DEVICE_DATA_T * identify,
  460    U32                          offset
  461 )
  462 {
  463    U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
  464    U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
  465    U32  page_length;
  466 
  467    page_length = sati_mode_sense_copy_initial_data(
  468                     sequence,
  469                     scsi_io,
  470                     offset,
  471                     page_control,
  472                     SCSI_MODE_PAGE_READ_WRITE_ERROR
  473                  );
  474 
  475    // Currently we do not override any bits in this mode page from the
  476    // identify data.
  477 
  478    return page_length;
  479 }
  480 
  481 /**
  482  * @brief This method performs the disconnect/reconnect mode page
  483  *        specific data translation based upon the contents of the remote
  484  *        device IDENTIFY DEVICE data.
  485  *        For more information on the parameters passed to this method,
  486  *        please reference sati_translate_command().
  487  *
  488  * @param[in] identify This parameter specifies the remote device's
  489  *            IDENTIFY DEVICE data received as part of the IO request.
  490  * @param[in] offset This parameter specifies the offset into the data
  491  *            buffer where the translated data is to be written.
  492  *
  493  * @return This method returns the size of the mode page data that was
  494  *         translated.
  495  */
  496 U32 sati_mode_sense_disconnect_reconnect_translate_data(
  497    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  498    void                       * scsi_io,
  499    ATA_IDENTIFY_DEVICE_DATA_T * identify,
  500    U32                          offset
  501 )
  502 {
  503    U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
  504    U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
  505    U32  page_length;
  506 
  507    page_length = sati_mode_sense_copy_initial_data(
  508                     sequence,
  509                     scsi_io,
  510                     offset,
  511                     page_control,
  512                     SCSI_MODE_PAGE_DISCONNECT_RECONNECT
  513                  );
  514 
  515    // Currently we do not override any bits in this mode page from the
  516    // identify data.
  517 
  518    return page_length;
  519 }
  520 
  521 /**
  522  * @brief This method performs the caching mode page specific data
  523  *        translation based upon the contents of the remote device IDENTIFY
  524  *        DEVICE data.
  525  *        For more information on the parameters passed to this method,
  526  *        please reference sati_translate_command().
  527  *
  528  * @param[in] identify This parameter specifies the remote device's
  529  *            IDENTIFY DEVICE data received as part of the IO request.
  530  * @param[in] offset This parameter specifies the offset into the data
  531  *            buffer where the translated data is to be written.
  532  *
  533  * @return This method returns the size of the mode page data that was
  534  *         translated.
  535  */
  536 U32 sati_mode_sense_caching_translate_data(
  537    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  538    void                       * scsi_io,
  539    ATA_IDENTIFY_DEVICE_DATA_T * identify,
  540    U32                          offset
  541 )
  542 {
  543    U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
  544    U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
  545    U32  page_length;
  546 
  547    page_length = sati_mode_sense_copy_initial_data(
  548                     sequence,
  549                     scsi_io,
  550                     offset,
  551                     page_control,
  552                     SCSI_MODE_PAGE_CACHING
  553                  );
  554 
  555    // If the request queried for the current values, then
  556    // we need to translate the data from the IDENTIFY DEVICE request.
  557    if (page_control == SCSI_MODE_SENSE_PC_CURRENT)
  558    {
  559       U8  value;
  560 
  561       // Update the Write Cache Enabled (WCE) bit in the mode page data
  562       // buffer based on the identify response.
  563       if ((identify->command_set_enabled0 & ATA_IDENTIFY_DEVICE_WCE_ENABLE) != 0)
  564       {
  565          sati_get_data_byte(sequence, scsi_io, offset+2, &value);
  566          value |= SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT;
  567          sati_set_data_byte(sequence, scsi_io, offset+2, value);
  568          //This byte has been set twice and needs to be decremented
  569          sequence->number_data_bytes_set--;
  570       }
  571 
  572       // Update the Disable Read Ahead (DRA) bit in the mode page data
  573       // buffer based on the identify response.
  574       if ((identify->command_set_enabled0 & ATA_IDENTIFY_DEVICE_RA_ENABLE) == 0)
  575       {
  576          // In SATA the polarity of the bits is inverse.
  577          // - SCSI = Disable Read Ahead
  578          // - ATA = Read Ahead
  579          sati_get_data_byte(sequence, scsi_io, offset+12, &value);
  580          value |= SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT;
  581          sati_set_data_byte(sequence, scsi_io, offset+12, value);
  582 
  583          //This byte has been set twice, the first time in
  584          //sati_mode_sense_copy_initial_data. number_data_bytes_set
  585          //needs to be decremented
  586          sequence->number_data_bytes_set--;
  587       }
  588    }
  589 
  590    return page_length;
  591 }
  592 
  593 /**
  594  * @brief This method performs the control mode page specific data
  595  *        translation based upon the contents of the remote device
  596  *        IDENTIFY DEVICE data.
  597  *        For more information on the parameters passed to this method,
  598  *        please reference sati_translate_command().
  599  *
  600  * @param[in] identify This parameter specifies the remote device's
  601  *            IDENTIFY DEVICE data received as part of the IO request.
  602  * @param[in] offset This parameter specifies the offset into the data
  603  *            buffer where the translated data is to be written.
  604  *
  605  * @return This method returns the size of the mode page data that was
  606  *         translated.
  607  */
  608 U32 sati_mode_sense_control_translate_data(
  609    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  610    void                       * scsi_io,
  611    ATA_IDENTIFY_DEVICE_DATA_T * identify,
  612    U32                          offset
  613 )
  614 {
  615    U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
  616    U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
  617    U32  page_length;
  618    U8   value;
  619 
  620    page_length = sati_mode_sense_copy_initial_data(
  621                     sequence,
  622                     scsi_io,
  623                     offset,
  624                     page_control,
  625                     SCSI_MODE_PAGE_CONTROL
  626                  );
  627 
  628    if (sequence->device->descriptor_sense_enable)
  629    {
  630        sati_get_data_byte(sequence, scsi_io, offset+2,
  631                &value);
  632 
  633        sati_set_data_byte(sequence, scsi_io, offset+2,
  634                value | SCSI_MODE_SELECT_MODE_PAGE_D_SENSE);
  635    }
  636 
  637    return page_length;
  638 }
  639 
  640 /**
  641  * @brief This method performs the informational exceptions control mode
  642  *        page specific data translation based upon the contents of the
  643  *        remote device IDENTIFY DEVICE data.
  644  *        For more information on the parameters passed to this method,
  645  *        please reference sati_translate_command().
  646  *
  647  * @param[in] identify This parameter specifies the remote device's
  648  *            IDENTIFY DEVICE data received as part of the IO request.
  649  * @param[in] offset This parameter specifies the offset into the data
  650  *            buffer where the translated data is to be written.
  651  *
  652  * @return This method returns the size of the mode page data that was
  653  *         translated.
  654  */
  655 U32 sati_mode_sense_informational_excp_control_translate_data(
  656    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  657    void                       * scsi_io,
  658    ATA_IDENTIFY_DEVICE_DATA_T * identify,
  659    U32                          offset
  660 )
  661 {
  662    U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
  663    U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
  664    U32  page_length;
  665 
  666    page_length = sati_mode_sense_copy_initial_data(
  667                     sequence,
  668                     scsi_io,
  669                     offset,
  670                     page_control,
  671                     SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL
  672                  );
  673 
  674    // If the request queried for the current values, then
  675    // we need to translate the data from the IDENTIFY DEVICE request.
  676    if (page_control == SCSI_MODE_SENSE_PC_CURRENT)
  677    {
  678       U8 value;
  679 
  680       sati_get_data_byte(sequence, scsi_io, offset+2, &value);
  681 
  682       // Determine if the SMART feature set is supported and enabled.
  683       if (  (identify->command_set_supported0
  684                 & ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE)
  685          && (identify->command_set_enabled0
  686                 & ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE) )
  687       {
  688          // Clear the DXCPT field since the SMART feature is supported/enabled.
  689          value &= ~SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE;
  690       }
  691       else
  692       {
  693          // Set the Disable Exception Control (DXCPT) field since the SMART
  694          // feature is not supported or enabled.
  695          value |= SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE;
  696       }
  697 
  698       sati_set_data_byte(sequence, scsi_io, offset+2, value);
  699 
  700       //This byte has been set twice, the first time in
  701       //sati_mode_sense_copy_initial_data. number_data_bytes_set
  702       //needs to be decremented
  703       sequence->number_data_bytes_set--;
  704    }
  705 
  706    return page_length;
  707 }
  708 
  709 /**
  710 * @brief This method performs the Power Condition mode page
  711 *        specific data translation based upon the contents of the
  712 *        remote device IDENTIFY DEVICE data.
  713 *        For more information on the parameters passed to this method,
  714 *        please reference sati_translate_command().
  715 *
  716 * @param[in] identify This parameter specifies the remote device's
  717 *            IDENTIFY DEVICE data received as part of the IO request.
  718 * @param[in] offset This parameter specifies the offset into the data
  719 *            buffer where the translated data is to be written.
  720 *
  721 * @return This method returns the size of the mode page data that was
  722 *         translated.
  723 */
  724 U32 sati_mode_sense_power_condition_translate_data(
  725    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  726    void                       * scsi_io,
  727    ATA_IDENTIFY_DEVICE_DATA_T * identify,
  728    U32                          offset
  729 )
  730 {
  731    U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
  732    U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
  733 
  734    U8 ata_sb_timer;
  735 
  736    //Represents tenths of seconds
  737    U32 standby_timer = 0x00000000;
  738 
  739    U8 standby_enabled = STANDBY_TIMER_DISABLED;
  740 
  741    if ((page_control == SCSI_MODE_SENSE_PC_CURRENT) &&
  742        (identify->capabilities1 & STANDBY_TIMER_SUPPORTED))
  743    {
  744       standby_enabled = STANDBY_TIMER_ENABLED;
  745 
  746       ata_sb_timer = sequence->device->ata_standby_timer;
  747 
  748       //converting ATA timer values into SCSI timer values
  749       if(ata_sb_timer <= 0xF0)
  750       {
  751          standby_timer = ata_sb_timer * 50;
  752       }
  753       else if(ata_sb_timer <= 0xFB)
  754       {
  755          standby_timer = ((ata_sb_timer - 240) * 18000);
  756       }
  757       else if(ata_sb_timer == 0xFC)
  758       {
  759          standby_timer = 12600;
  760       }
  761       else if(ata_sb_timer == 0xFD)
  762       {
  763          standby_timer = 432000;
  764       }
  765       else if(ata_sb_timer == 0xFF)
  766       {
  767          standby_timer = 12750;
  768       }
  769       else
  770       {
  771          standby_timer = 0xFFFFFFFF;
  772       }
  773    }
  774 
  775    sati_set_data_byte(sequence, scsi_io, offset, SCSI_MODE_PAGE_POWER_CONDITION);
  776    sati_set_data_byte(sequence, scsi_io, offset + 1, (SCSI_MODE_PAGE_1A_LENGTH - 2));
  777    sati_set_data_byte(sequence, scsi_io, offset + 2, 0x00);
  778    sati_set_data_byte(sequence, scsi_io, offset + 3, standby_enabled);
  779    sati_set_data_byte(sequence, scsi_io, offset + 4, 0x00);
  780    sati_set_data_byte(sequence, scsi_io, offset + 5, 0x00);
  781    sati_set_data_byte(sequence, scsi_io, offset + 6, 0x00);
  782    sati_set_data_byte(sequence, scsi_io, offset + 7, 0x00);
  783    sati_set_data_byte(sequence, scsi_io, offset + 8, (U8) (standby_timer >> 24));
  784    sati_set_data_byte(sequence, scsi_io, offset + 9, (U8) (standby_timer >> 16));
  785    sati_set_data_byte(sequence, scsi_io, offset + 10, (U8) (standby_timer >> 8));
  786    sati_set_data_byte(sequence, scsi_io, offset + 11, (U8) standby_timer);
  787 
  788    return SCSI_MODE_PAGE_1A_LENGTH;
  789 }
  790 
  791 /**
  792  * @brief This method performs the all pages mode page specific data
  793  *        translation based upon the contents of the remote device
  794  *        IDENTIFY DEVICE data.  The ALL PAGES mode sense request asks
  795  *        for all of mode pages and sub-pages in a single page.
  796  *        The mode pages are added in ascending order.
  797  *        For more information on the parameters passed to this method,
  798  *        please reference sati_translate_command().
  799  *
  800  * @param[in] identify This parameter specifies the remote device's
  801  *            IDENTIFY DEVICE data received as part of the IO request.
  802  * @param[in] offset This parameter specifies the offset into the data
  803  *            buffer where the translated data is to be written.
  804  *
  805  * @return This method returns the size of the mode page data that was
  806  *         translated.
  807  */
  808 U32 sati_mode_sense_all_pages_translate_data(
  809    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  810    void                       * scsi_io,
  811    ATA_IDENTIFY_DEVICE_DATA_T * identify,
  812    U32                          offset
  813 )
  814 {
  815    offset += sati_mode_sense_read_write_error_translate_data(
  816                 sequence, scsi_io, identify, offset
  817              );
  818 
  819    offset += sati_mode_sense_disconnect_reconnect_translate_data(
  820                 sequence, scsi_io, identify, offset
  821              );
  822 
  823    offset += sati_mode_sense_caching_translate_data(
  824                 sequence, scsi_io, identify, offset
  825              );
  826 
  827    offset += sati_mode_sense_control_translate_data(
  828                 sequence, scsi_io, identify, offset
  829              );
  830 
  831    offset += sati_mode_sense_informational_excp_control_translate_data(
  832                 sequence, scsi_io, identify, offset
  833              );
  834 
  835    return offset;
  836 }
  837 
  838 #endif // !defined(DISABLE_SATI_MODE_SENSE)
  839 

Cache object: 5976333056792c69cd683bf80270ce8c


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