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_start_stop_unit.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 start stop unit command.
   62  */
   63 
   64 #if !defined(DISABLE_SATI_START_STOP_UNIT)
   65 
   66 #include <dev/isci/scil/sati_start_stop_unit.h>
   67 #include <dev/isci/scil/sati_util.h>
   68 #include <dev/isci/scil/sati_callbacks.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 start stop unit SCSI command into
   74  *        various ATA commands depends on the value in POWER CONTIDTION, LOEJ
   75  *        and START fields.
   76  *        For more information on the parameters passed to this method,
   77  *        please reference sati_translate_command().
   78  *
   79  * @return Indicate if the command translation succeeded.
   80  * @retval SCI_SUCCESS This is returned if the command translation was
   81  *         successful.
   82  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA Please refer to spec.
   83  *
   84  */
   85 SATI_STATUS sati_start_stop_unit_translate_command(
   86    SATI_TRANSLATOR_SEQUENCE_T * sequence,
   87    void                       * scsi_io,
   88    void                       * ata_io
   89 )
   90 {
   91    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
   92 
   93    switch ( SATI_START_STOP_UNIT_POWER_CONDITION(cdb) )
   94    {
   95       case SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID:
   96          if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 0
   97              && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 0 )
   98          {
   99             if ( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 1 )
  100             {
  101                //directly send ATA STANDBY_IMMEDIATE
  102                sati_ata_standby_immediate_construct(ata_io, sequence);
  103                sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED;
  104             }
  105             else
  106             {
  107                if ( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
  108                {
  109                   //First, send ATA flush command.
  110                   sati_ata_flush_cache_construct(ata_io, sequence);
  111                   sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
  112 
  113                   //remember there is next step.
  114                   sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
  115                }
  116                else
  117                {
  118                   //the first step, flush cache command, has completed.
  119                   //Send standby immediate now.
  120                   sati_ata_standby_immediate_construct(ata_io, sequence);
  121                   sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED;
  122 
  123                }
  124             }
  125          }
  126          else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 0
  127                   && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 1 )
  128          {
  129             //need to know whether the device supports removable medial feature set.
  130             if (sequence->device->capabilities & SATI_DEVICE_CAP_REMOVABLE_MEDIA)
  131             {
  132                //send ATA MEDIA EJECT command.
  133                sati_ata_media_eject_construct(ata_io, sequence);
  134                sequence->command_specific_data.translated_command = ATA_MEDIA_EJECT;
  135             }
  136             else
  137             {
  138                sati_scsi_sense_data_construct(
  139                   sequence,
  140                   scsi_io,
  141                   SCSI_STATUS_CHECK_CONDITION,
  142                   SCSI_SENSE_ILLEGAL_REQUEST,
  143                   SCSI_ASC_INVALID_FIELD_IN_CDB,
  144                   SCSI_ASCQ_INVALID_FIELD_IN_CDB
  145                );
  146                return SATI_FAILURE_CHECK_RESPONSE_DATA;
  147             }
  148          }
  149          else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 1
  150                   && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 0 )
  151          {
  152             //send an ATA verify command
  153             sati_ata_read_verify_sectors_construct(ata_io, sequence);
  154             sequence->command_specific_data.translated_command = ATA_READ_VERIFY_SECTORS;
  155          }
  156          else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 1
  157                   && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 1 )
  158          {
  159             sati_scsi_sense_data_construct(
  160                sequence,
  161                scsi_io,
  162                SCSI_STATUS_CHECK_CONDITION,
  163                SCSI_SENSE_ILLEGAL_REQUEST,
  164                SCSI_ASC_INVALID_FIELD_IN_CDB,
  165                SCSI_ASCQ_INVALID_FIELD_IN_CDB
  166             );
  167             return SATI_FAILURE_CHECK_RESPONSE_DATA;
  168          }
  169 
  170          break;
  171       //Power Condition Field is set to 0x01(Device to transition to Active state)
  172       case SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE:
  173 
  174          if( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
  175          {
  176             sati_ata_idle_construct(ata_io, sequence);
  177             sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
  178             sequence->command_specific_data.translated_command = ATA_IDLE;
  179          }
  180          else
  181          {
  182             sati_ata_read_verify_sectors_construct(ata_io, sequence);
  183             sequence->command_specific_data.translated_command = ATA_READ_VERIFY_SECTORS;
  184          }
  185          break;
  186 
  187       //Power Condition Field is set to 0x02(Device to transition to Idle state)
  188       case SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE:
  189 
  190          if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 &&
  191              sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
  192          {
  193             sati_ata_flush_cache_construct(ata_io, sequence);
  194             sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
  195             sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
  196          }
  197          else
  198          {
  199             if( SATI_START_STOP_UNIT_POWER_CONDITION_MODIFIER(cdb) == 0 )
  200             {
  201                sati_ata_idle_immediate_construct(ata_io, sequence);
  202             }
  203             else
  204             {
  205                sati_ata_idle_immediate_unload_construct(ata_io, sequence);
  206             }
  207             sequence->command_specific_data.translated_command = ATA_IDLE_IMMED;
  208          }
  209          break;
  210 
  211       //Power Condition Field is set to 0x03(Device to transition to Standby state)
  212       case SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY:
  213          if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 &&
  214             sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
  215          {
  216             sati_ata_flush_cache_construct(ata_io, sequence);
  217             sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
  218             sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
  219          }
  220          else
  221          {
  222             sati_ata_standby_immediate_construct(ata_io, sequence);
  223             sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED;
  224          }
  225          break;
  226 
  227       //Power Condition Field is set to 0xB(force Standby state)
  228       case SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL:
  229 
  230          if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 &&
  231             sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
  232          {
  233             sati_ata_flush_cache_construct(ata_io, sequence);
  234             sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
  235             sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
  236          }
  237          else
  238          {
  239             sati_ata_standby_construct(ata_io, sequence, 0);
  240             sequence->command_specific_data.translated_command = ATA_STANDBY;
  241          }
  242          break;
  243 
  244       case SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL:
  245       default:  //TBD.
  246          sati_scsi_sense_data_construct(
  247             sequence,
  248             scsi_io,
  249             SCSI_STATUS_CHECK_CONDITION,
  250             SCSI_SENSE_ILLEGAL_REQUEST,
  251             SCSI_ASC_INVALID_FIELD_IN_CDB,
  252             SCSI_ASCQ_INVALID_FIELD_IN_CDB
  253          );
  254          return SATI_FAILURE_CHECK_RESPONSE_DATA;
  255          break;
  256    }
  257 
  258    if ( SATI_START_STOP_UNIT_IMMED_BIT(cdb) == 1 )
  259    {
  260       //@todo: return good status now.
  261       ;
  262    }
  263    sequence->type = SATI_SEQUENCE_START_STOP_UNIT;
  264    return SATI_SUCCESS;
  265 }
  266 
  267 
  268 /**
  269  * @brief This method will translate the ATA command register FIS
  270  *        response into an appropriate SCSI response for START STOP UNIT.
  271  *        For more information on the parameters passed to this method,
  272  *        please reference sati_translate_response().
  273  *
  274  * @return Indicate if the response translation succeeded.
  275  * @retval SCI_SUCCESS This is returned if the data translation was
  276  *         successful.
  277  */
  278 SATI_STATUS sati_start_stop_unit_translate_response(
  279    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  280    void                       * scsi_io,
  281    void                       * ata_io
  282 )
  283 {
  284    U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
  285    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
  286 
  287    if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
  288    {
  289       switch ( sequence->command_specific_data.translated_command )
  290       {
  291          case ATA_FLUSH_CACHE:
  292          case ATA_STANDBY_IMMED:
  293          case ATA_IDLE_IMMED:
  294          case ATA_IDLE:
  295          case ATA_STANDBY:
  296             //Note: There is lack of reference in spec of the error handling for
  297             //READ_VERIFY command.
  298          case ATA_READ_VERIFY_SECTORS:
  299             sati_scsi_sense_data_construct(
  300                sequence,
  301                scsi_io,
  302                SCSI_STATUS_CHECK_CONDITION,
  303                SCSI_SENSE_ABORTED_COMMAND,
  304                SCSI_ASC_COMMAND_SEQUENCE_ERROR,
  305                SCSI_ASCQ_NO_ADDITIONAL_SENSE
  306             );
  307             break;
  308 
  309          case ATA_MEDIA_EJECT:
  310             sati_scsi_sense_data_construct(
  311                sequence,
  312                scsi_io,
  313                SCSI_STATUS_CHECK_CONDITION,
  314                SCSI_SENSE_ABORTED_COMMAND,
  315                SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED,
  316                SCSI_ASCQ_NO_ADDITIONAL_SENSE
  317             );
  318             break;
  319 
  320          default:
  321             sati_scsi_sense_data_construct(
  322                sequence,
  323                scsi_io,
  324                SCSI_STATUS_CHECK_CONDITION,
  325                SCSI_SENSE_ILLEGAL_REQUEST,
  326                SCSI_ASC_INVALID_FIELD_IN_CDB,
  327                SCSI_ASCQ_INVALID_FIELD_IN_CDB
  328             );
  329             break;
  330       }
  331       sequence->state = SATI_SEQUENCE_STATE_FINAL;
  332       return SATI_FAILURE_CHECK_RESPONSE_DATA;
  333    }
  334    else
  335    {
  336       switch ( sequence->command_specific_data.translated_command )
  337       {
  338          case ATA_READ_VERIFY_SECTORS:
  339 
  340             sati_scsi_sense_data_construct(
  341                sequence,
  342                scsi_io,
  343                SCSI_STATUS_GOOD,
  344                SCSI_SENSE_NO_SENSE,
  345                SCSI_ASC_NO_ADDITIONAL_SENSE,
  346                SCSI_ASCQ_NO_ADDITIONAL_SENSE
  347             );
  348             //device state is now operational(active)
  349             sequence->device->state = SATI_DEVICE_STATE_OPERATIONAL;
  350             sequence->state = SATI_SEQUENCE_STATE_FINAL;
  351             break;
  352 
  353          case ATA_IDLE_IMMED:
  354 
  355             sati_scsi_sense_data_construct(
  356                sequence,
  357                scsi_io,
  358                SCSI_STATUS_GOOD,
  359                SCSI_SENSE_NO_SENSE,
  360                SCSI_ASC_NO_ADDITIONAL_SENSE,
  361                SCSI_ASCQ_NO_ADDITIONAL_SENSE
  362             );
  363             sequence->device->state = SATI_DEVICE_STATE_IDLE;
  364             sequence->state = SATI_SEQUENCE_STATE_FINAL;
  365             break;
  366 
  367          //These three commands will be issued when the power condition is 0x00 or 0x03
  368          case ATA_MEDIA_EJECT:
  369          case ATA_STANDBY:
  370          case ATA_STANDBY_IMMED:
  371 
  372             sati_scsi_sense_data_construct(
  373                sequence,
  374                scsi_io,
  375                SCSI_STATUS_GOOD,
  376                SCSI_SENSE_NO_SENSE,
  377                SCSI_ASC_NO_ADDITIONAL_SENSE,
  378                SCSI_ASCQ_NO_ADDITIONAL_SENSE
  379             );
  380 
  381             if( SATI_START_STOP_UNIT_POWER_CONDITION(cdb) == 0 )
  382             {
  383                sequence->device->state = SATI_DEVICE_STATE_STOPPED;
  384             }
  385             else
  386             {
  387                sequence->device->state = SATI_DEVICE_STATE_STANDBY;
  388             }
  389             sequence->state = SATI_SEQUENCE_STATE_FINAL;
  390             break;
  391 
  392          default:
  393             //FLUSH Cache command does not require any success handling
  394             break;
  395       }
  396 
  397       if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
  398       {
  399          return SATI_SEQUENCE_INCOMPLETE;
  400       }
  401    }
  402    return SATI_COMPLETE;
  403 }
  404 
  405 #endif // !defined(DISABLE_SATI_START_STOP_UNIT)
  406 

Cache object: e4b1e292819c01a05638cd53317b8ddf


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