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/scic_sds_stp_packet_request.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 #if !defined(DISABLE_ATAPI)
   59 
   60 #include <dev/isci/scil/scic_sds_stp_packet_request.h>
   61 #include <dev/isci/scil/scic_sds_logger.h>
   62 #include <dev/isci/scil/scic_sds_controller.h>
   63 #include <dev/isci/scil/scic_sds_remote_device.h>
   64 #include <dev/isci/scil/scic_remote_device.h>
   65 #include <dev/isci/scil/sci_util.h>
   66 #include <dev/isci/scil/intel_sas.h>
   67 #include <dev/isci/scil/intel_ata.h>
   68 #include <dev/isci/scil/intel_sata.h>
   69 #include <dev/isci/scil/scic_user_callback.h>
   70 #include <dev/isci/sci_environment.h>
   71 #include <dev/isci/scil/intel_sat.h>
   72 #include <dev/isci/scil/scic_sds_request.h>
   73 #include <dev/isci/scil/scic_controller.h>
   74 #include <dev/isci/scil/scu_completion_codes.h>
   75 #include <dev/isci/scil/scu_task_context.h>
   76 #include <dev/isci/scil/scic_sds_stp_packet_request.h>
   77 #include <dev/isci/scil/sci_base_state.h>
   78 
   79 /**
   80  * @brief This method will fill in the SCU Task Context for a PACKET fis. And
   81  *           construct the request STARTED sub-state machine for Packet Protocol
   82  *           IO.
   83  *
   84  * @param[in] this_request This parameter specifies the stp packet request object
   85  *            being constructed.
   86  *
   87  * @return none
   88  */
   89 SCI_STATUS scic_sds_stp_packet_request_construct(
   90    SCIC_SDS_REQUEST_T *this_request
   91 )
   92 {
   93    SATA_FIS_REG_H2D_T * h2d_fis =
   94       scic_stp_io_request_get_h2d_reg_address(
   95          this_request
   96       );
   97 
   98    // Work around, we currently only support PACKET DMA protocol, so we
   99    // need to make change to Packet Fis features field.
  100    h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA;
  101 
  102    scic_sds_stp_non_ncq_request_construct(this_request);
  103 
  104    // Build the Packet Fis task context structure
  105    scu_stp_raw_request_construct_task_context(
  106       (SCIC_SDS_STP_REQUEST_T*) this_request,
  107       this_request->task_context_buffer
  108    );
  109 
  110    sci_base_state_machine_construct(
  111       &this_request->started_substate_machine,
  112       &this_request->parent.parent,
  113       scic_sds_stp_packet_request_started_substate_table,
  114       SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
  115    );
  116 
  117    return SCI_SUCCESS;
  118 }
  119 
  120 
  121 /**
  122  * @brief This method will fill in the SCU Task Context for a Packet request
  123  *        command phase in PACKET DMA DATA (IN/OUT) type. The following
  124  *        important settings are utilized:
  125  *
  126  *          -# task_type == SCU_TASK_TYPE_PACKET_DMA.  This simply indicates
  127  *             that a normal request type (i.e. non-raw frame) is being
  128  *             utilized to perform task management.
  129  *          -# control_frame == 1.  This ensures that the proper endianness
  130  *             is set so that the bytes are transmitted in the right order
  131  *             for a smp request frame.
  132  *
  133  * @param[in] this_request This parameter specifies the smp request object
  134  *            being constructed.
  135  * @param[in] task_context The task_context to be reconstruct for packet
  136  *            request command phase.
  137  * @return none
  138  */
  139 void scu_stp_packet_request_command_phase_construct_task_context(
  140    SCIC_SDS_REQUEST_T * this_request,
  141    SCU_TASK_CONTEXT_T * task_context
  142 )
  143 {
  144    void * atapi_cdb;
  145    U32 atapi_cdb_length;
  146    SCIC_SDS_STP_REQUEST_T * stp_request = (SCIC_SDS_STP_REQUEST_T *)this_request;
  147 
  148    // reference: SSTL 1.13.4.2
  149    // task_type, sata_direction
  150    if ( scic_cb_io_request_get_data_direction(this_request->user_request)
  151            == SCI_IO_REQUEST_DATA_OUT )
  152    {
  153       task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
  154       task_context->sata_direction = 0;
  155    }
  156    else // todo: for NO_DATA command, we need to send out raw frame.
  157    {
  158       task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
  159       task_context->sata_direction = 1;
  160    }
  161 
  162    // sata header
  163    memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
  164    task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
  165 
  166    // Copy in the command IU with CDB so that the commandIU address doesn't
  167    // change.
  168    memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
  169 
  170    atapi_cdb =
  171       scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
  172 
  173    atapi_cdb_length =
  174       scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
  175 
  176    memcpy(((U8 *)this_request->command_buffer+sizeof(U32)), atapi_cdb, atapi_cdb_length);
  177 
  178    atapi_cdb_length =
  179       MAX(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length);
  180 
  181    task_context->ssp_command_iu_length =
  182       ((atapi_cdb_length % 4) == 0) ?
  183        (atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1);
  184 
  185    // task phase is set to TX_CMD
  186    task_context->task_phase = 0x1;
  187 
  188    // retry counter
  189    task_context->stp_retry_count = 0;
  190 
  191    if (scic_cb_request_is_initial_construction(this_request->user_request))
  192    {
  193       // data transfer size.
  194       task_context->transfer_length_bytes =
  195          scic_cb_io_request_get_transfer_length(this_request->user_request);
  196 
  197       // sgls were already built when request was constructed, so don't need to
  198       //  to do it here
  199    }
  200    else
  201    {
  202       // data transfer size, need to be 4 bytes aligned.
  203       task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2);
  204 
  205       scic_sds_stp_packet_internal_request_sense_build_sgl(this_request);
  206    }
  207 }
  208 
  209 /**
  210  * @brief This method will fill in the SCU Task Context for a DATA fis
  211  *        containing CDB in Raw Frame type. The TC for previous Packet
  212  *        fis was already there, we only need to change the H2D fis content.
  213  *
  214  * @param[in] this_request This parameter specifies the smp request object
  215  *            being constructed.
  216  * @param[in] task_context The task_context to be reconstruct for packet
  217  *            request command phase.
  218  * @return none
  219  */
  220 void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
  221    SCIC_SDS_REQUEST_T * this_request,
  222    SCU_TASK_CONTEXT_T * task_context
  223 )
  224 {
  225    void * atapi_cdb =
  226       scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
  227 
  228    U32 atapi_cdb_length =
  229       scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
  230 
  231    memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
  232    memcpy( ((U8 *)this_request->command_buffer+sizeof(U32)), atapi_cdb, atapi_cdb_length);
  233 
  234    memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
  235    task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
  236 
  237    //Note the data send out has to be 4 bytes aligned. Or else out hardware will
  238    //patch non-zero bytes and cause the target device unhappy.
  239    task_context->transfer_length_bytes = 12;
  240 }
  241 
  242 
  243 /*
  244  *@brief This methods decode the D2H status FIS and retrieve the sense data,
  245  *          then pass the sense data to user request.
  246  *
  247  *@param[in] this_request The request receive D2H status FIS.
  248  *@param[in] status_fis The D2H status fis to be processed.
  249  *
  250  */
  251 SCI_STATUS scic_sds_stp_packet_request_process_status_fis(
  252    SCIC_SDS_REQUEST_T * this_request,
  253    SATA_FIS_REG_D2H_T * status_fis
  254 )
  255 {
  256    SCI_STATUS status = SCI_SUCCESS;
  257 
  258    //TODO: Process the error status fis, retrieve sense data.
  259    if (status_fis->status & ATA_STATUS_REG_ERROR_BIT)
  260       status = SCI_FAILURE_IO_RESPONSE_VALID;
  261 
  262    return status;
  263 }
  264 
  265 /*
  266  *@brief This methods builds sgl for internal REQUEST SENSE stp packet
  267  *          command using this request response buffer, only one sge is
  268  *          needed.
  269  *
  270  *@param[in] this_request The request receive request sense data.
  271  *
  272  */
  273 void scic_sds_stp_packet_internal_request_sense_build_sgl(
  274    SCIC_SDS_REQUEST_T * this_request
  275 )
  276 {
  277    void                   *sge;
  278    SCU_SGL_ELEMENT_PAIR_T *scu_sgl_list   = NULL;
  279    SCU_TASK_CONTEXT_T     *task_context;
  280    SCI_PHYSICAL_ADDRESS    physical_address;
  281 
  282    SCI_SSP_RESPONSE_IU_T * rsp_iu =
  283       (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
  284    sge =  (void*)&rsp_iu->data[0];
  285 
  286    task_context = (SCU_TASK_CONTEXT_T *)this_request->task_context_buffer;
  287    scu_sgl_list = &task_context->sgl_pair_ab;
  288 
  289    scic_cb_io_request_get_physical_address(
  290       scic_sds_request_get_controller(this_request),
  291       this_request,
  292       ((char *)sge),
  293       &physical_address
  294    );
  295 
  296    scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address);
  297    scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address);
  298    scu_sgl_list->A.length = task_context->transfer_length_bytes;
  299    scu_sgl_list->A.address_modifier = 0;
  300 
  301    SCU_SGL_ZERO(scu_sgl_list->B);
  302 }
  303 
  304 //******************************************************************************
  305 //* STP PACKET REQUEST STATE MACHINES
  306 //******************************************************************************
  307 
  308 /**
  309 * @brief This method processes the completions transport layer (TL) status
  310 *        to determine if the Packet FIS was sent successfully. If the Packet
  311 *        FIS was sent successfully, then the state for the Packet request
  312 *        transits to waiting for a PIO SETUP frame.
  313 *
  314 * @param[in] this_request This parameter specifies the request for which
  315 *            the TC completion was received.
  316 * @param[in] completion_code This parameter indicates the completion status
  317 *            information for the TC.
  318 *
  319 * @return Indicate if the tc completion handler was successful.
  320 * @retval SCI_SUCCESS currently this method always returns success.
  321 */
  322 static
  323 SCI_STATUS scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(
  324    SCIC_SDS_REQUEST_T * this_request,
  325    U32                  completion_code
  326 )
  327 {
  328    SCI_STATUS status = SCI_SUCCESS;
  329 
  330    SCIC_LOG_TRACE((
  331       sci_base_object_get_logger(this_request),
  332       SCIC_LOG_OBJECT_STP_IO_REQUEST,
  333       "scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
  334       this_request, completion_code
  335    ));
  336 
  337    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
  338    {
  339    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
  340       scic_sds_request_set_status(
  341          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
  342       );
  343 
  344       sci_base_state_machine_change_state(
  345          &this_request->started_substate_machine,
  346          SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
  347       );
  348       break;
  349 
  350    default:
  351       // All other completion status cause the IO to be complete.  If a NAK
  352       // was received, then it is up to the user to retry the request.
  353       scic_sds_request_set_status(
  354          this_request,
  355          SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
  356          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
  357       );
  358 
  359       sci_base_state_machine_change_state(
  360          &this_request->parent.state_machine,
  361          SCI_BASE_REQUEST_STATE_COMPLETED
  362       );
  363       break;
  364    }
  365 
  366    return status;
  367 }
  368 
  369 
  370 /**
  371  * @brief This method processes an unsolicited frame while the Packet request
  372  *        is waiting for a PIO SETUP FIS.  It will release
  373  *        the unsolicited frame, and transition the request to the
  374  *        COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE state.
  375  *
  376  * @param[in] this_request This parameter specifies the request for which
  377  *            the unsolicited frame was received.
  378  * @param[in] frame_index This parameter indicates the unsolicited frame
  379  *            index that should contain the response.
  380  *
  381  * @return This method returns an indication of whether the pio setup
  382  *         frame was handled successfully or not.
  383  * @retval SCI_SUCCESS Currently this value is always returned and indicates
  384  *         successful processing of the TC response.
  385  *
  386  */
  387 static
  388 SCI_STATUS scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(
  389    SCIC_SDS_REQUEST_T * request,
  390    U32                  frame_index
  391 )
  392 {
  393    SCI_STATUS               status;
  394    SATA_FIS_HEADER_T      * frame_header;
  395    U32                    * frame_buffer;
  396    SCIC_SDS_STP_REQUEST_T * this_request;
  397 
  398    this_request = (SCIC_SDS_STP_REQUEST_T *)request;
  399 
  400    SCIC_LOG_TRACE((
  401       sci_base_object_get_logger(this_request),
  402       SCIC_LOG_OBJECT_STP_IO_REQUEST,
  403       "scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(0x%x, 0x%x) enter\n",
  404       this_request, frame_index
  405    ));
  406 
  407    status = scic_sds_unsolicited_frame_control_get_header(
  408       &(this_request->parent.owning_controller->uf_control),
  409       frame_index,
  410       (void**) &frame_header
  411    );
  412 
  413    if (status == SCI_SUCCESS)
  414    {
  415       ASSERT(frame_header->fis_type == SATA_FIS_TYPE_PIO_SETUP);
  416 
  417       // Get from the frame buffer the PIO Setup Data, although we don't need
  418       // any info from this pio setup fis.
  419       scic_sds_unsolicited_frame_control_get_buffer(
  420          &(this_request->parent.owning_controller->uf_control),
  421          frame_index,
  422          (void**) &frame_buffer
  423       );
  424 
  425       // Get the data from the PIO Setup
  426       // The SCU Hardware returns first word in the frame_header and the rest
  427       // of the data is in the frame buffer so we need to back up one dword
  428       this_request->type.packet.device_preferred_cdb_length =
  429          (U16)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->transfter_count;
  430 
  431       // Frame has been decoded return it to the controller
  432       scic_sds_controller_release_frame(
  433          this_request->parent.owning_controller, frame_index
  434       );
  435 
  436       sci_base_state_machine_change_state(
  437          &this_request->parent.started_substate_machine,
  438          SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
  439       );
  440    }
  441    else
  442    {
  443       SCIC_LOG_ERROR((
  444          sci_base_object_get_logger(this_request),
  445          SCIC_LOG_OBJECT_STP_IO_REQUEST,
  446          "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
  447          this_request, frame_index, status
  448       ));
  449    }
  450 
  451    return status;
  452 }
  453 
  454 
  455 /**
  456  * @brief This method processes the completions transport layer (TL) status
  457  *        to determine if the PACKET command data FIS was sent successfully.
  458  *        If successfully, then the state for the packet request
  459  *        transits to COMPLETE state. If not successfully, the request transits
  460  *        to COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE.
  461  *
  462  * @param[in] this_request This parameter specifies the request for which
  463  *            the TC completion was received.
  464  * @param[in] completion_code This parameter indicates the completion status
  465  *            information for the TC.
  466  *
  467  * @return Indicate if the tc completion handler was successful.
  468  * @retval SCI_SUCCESS currently this method always returns success.
  469  */
  470 static
  471 SCI_STATUS scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(
  472    SCIC_SDS_REQUEST_T * this_request,
  473    U32                  completion_code
  474 )
  475 {
  476    SCI_STATUS status = SCI_SUCCESS;
  477    U8 sat_packet_protocol = this_request->sat_protocol;
  478 
  479    SCIC_LOG_TRACE((
  480       sci_base_object_get_logger(this_request),
  481       SCIC_LOG_OBJECT_STP_IO_REQUEST,
  482       "scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
  483       this_request, completion_code
  484    ));
  485 
  486    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
  487    {
  488    case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
  489       scic_sds_request_set_status(
  490          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
  491       );
  492 
  493       if ( sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN
  494           || sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT
  495          )
  496          sci_base_state_machine_change_state(
  497             &this_request->parent.state_machine,
  498             SCI_BASE_REQUEST_STATE_COMPLETED
  499          );
  500       else
  501          sci_base_state_machine_change_state(
  502             &this_request->started_substate_machine,
  503             SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
  504          );
  505    break;
  506 
  507    case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT):
  508       if (scic_io_request_get_number_of_bytes_transferred(this_request) <
  509           scic_cb_io_request_get_transfer_length(this_request->user_request))
  510       {
  511          scic_sds_request_set_status(
  512             this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
  513          );
  514 
  515          sci_base_state_machine_change_state(
  516             &this_request->started_substate_machine,
  517             SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
  518          );
  519 
  520          //change the device state to ATAPI_ERROR.
  521          sci_base_state_machine_change_state(
  522             &this_request->target_device->ready_substate_machine,
  523             SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
  524          );
  525 
  526          status = this_request->sci_status;
  527       }
  528    break;
  529 
  530    case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
  531       //In this case, there is no UF coming after. compelte the IO now.
  532       scic_sds_request_set_status(
  533          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
  534       );
  535 
  536       sci_base_state_machine_change_state(
  537          &this_request->parent.state_machine,
  538          SCI_BASE_REQUEST_STATE_COMPLETED
  539       );
  540 
  541    break;
  542 
  543    default:
  544       if (this_request->sci_status != SCI_SUCCESS)
  545       {  //The io status was set already. This means an UF for the status
  546          //fis was received already.
  547 
  548          //A device suspension event is expected, we need to have the device
  549          //coming out of suspension, then complete the IO.
  550          sci_base_state_machine_change_state(
  551             &this_request->started_substate_machine,
  552             SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
  553          );
  554 
  555          //change the device state to ATAPI_ERROR.
  556          sci_base_state_machine_change_state(
  557             &this_request->target_device->ready_substate_machine,
  558             SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
  559          );
  560 
  561          status = this_request->sci_status;
  562       }
  563       else
  564       {  //If receiving any non-sucess TC status, no UF received yet, then an UF for
  565          //the status fis is coming after.
  566          scic_sds_request_set_status(
  567             this_request,
  568             SCU_TASK_DONE_CHECK_RESPONSE,
  569             SCI_FAILURE_IO_RESPONSE_VALID
  570          );
  571 
  572          sci_base_state_machine_change_state(
  573             &this_request->started_substate_machine,
  574             SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
  575          );
  576       }
  577    break;
  578    }
  579 
  580    return status;
  581 }
  582 
  583 
  584 /**
  585 * @brief This method processes an unsolicited frame.
  586 *
  587 * @param[in] this_request This parameter specifies the request for which
  588 *            the unsolicited frame was received.
  589 * @param[in] frame_index This parameter indicates the unsolicited frame
  590 *            index that should contain the response.
  591 *
  592 * @return This method returns an indication of whether the UF
  593 *         frame was handled successfully or not.
  594 * @retval SCI_SUCCESS Currently this value is always returned and indicates
  595 *         successful processing of the TC response.
  596 *
  597 */
  598 static
  599 SCI_STATUS scic_sds_stp_packet_request_command_phase_common_frame_handler(
  600    SCIC_SDS_REQUEST_T * request,
  601    U32                  frame_index
  602 )
  603 {
  604    SCI_STATUS               status;
  605    SATA_FIS_HEADER_T      * frame_header;
  606    U32                    * frame_buffer;
  607    SCIC_SDS_STP_REQUEST_T * this_request;
  608 
  609    this_request = (SCIC_SDS_STP_REQUEST_T *)request;
  610 
  611    SCIC_LOG_TRACE((
  612       sci_base_object_get_logger(this_request),
  613       SCIC_LOG_OBJECT_STP_IO_REQUEST,
  614       "scic_sds_stp_packet_request_command_phase_await_d2h_frame_handler(0x%x, 0x%x) enter\n",
  615       this_request, frame_index
  616    ));
  617 
  618    status = scic_sds_unsolicited_frame_control_get_header(
  619       &(this_request->parent.owning_controller->uf_control),
  620       frame_index,
  621       (void**) &frame_header
  622    );
  623 
  624    if (status == SCI_SUCCESS)
  625    {
  626       ASSERT(frame_header->fis_type == SATA_FIS_TYPE_REGD2H);
  627 
  628       // Get from the frame buffer the PIO Setup Data, although we don't need
  629       // any info from this pio setup fis.
  630       scic_sds_unsolicited_frame_control_get_buffer(
  631          &(this_request->parent.owning_controller->uf_control),
  632          frame_index,
  633          (void**) &frame_buffer
  634       );
  635 
  636       scic_sds_controller_copy_sata_response(
  637          &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
  638       );
  639 
  640       // Frame has been decoded return it to the controller
  641       scic_sds_controller_release_frame(
  642          this_request->parent.owning_controller, frame_index
  643       );
  644    }
  645 
  646    return status;
  647 }
  648 
  649 /**
  650 * @brief This method processes an unsolicited frame while the packet request is
  651 *        expecting TC completion. It will process the FIS and construct sense
  652 *        data.
  653 *
  654 * @param[in] this_request This parameter specifies the request for which
  655 *            the unsolicited frame was received.
  656 * @param[in] frame_index This parameter indicates the unsolicited frame
  657 *            index that should contain the response.
  658 *
  659 * @return This method returns an indication of whether the UF
  660 *         frame was handled successfully or not.
  661 * @retval SCI_SUCCESS Currently this value is always returned and indicates
  662 *         successful processing of the TC response.
  663 *
  664 */
  665 static
  666 SCI_STATUS scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler(
  667    SCIC_SDS_REQUEST_T * request,
  668    U32                  frame_index
  669 )
  670 {
  671    SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
  672 
  673    SCI_STATUS status =
  674       scic_sds_stp_packet_request_command_phase_common_frame_handler(
  675          request, frame_index);
  676 
  677    if (status == SCI_SUCCESS)
  678    {
  679       // The command has completed with error status from target device.
  680       status = scic_sds_stp_packet_request_process_status_fis(
  681          request, &this_request->d2h_reg_fis);
  682 
  683       if (status != SCI_SUCCESS)
  684       {
  685          scic_sds_request_set_status(
  686             &this_request->parent,
  687             SCU_TASK_DONE_CHECK_RESPONSE,
  688             status
  689          );
  690       }
  691       else
  692          scic_sds_request_set_status(
  693             &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
  694          );
  695    }
  696 
  697    return status;
  698 }
  699 
  700 
  701 /**
  702 * @brief This method processes an unsolicited frame while the packet request is
  703 *        expecting TC completion. It will process the FIS and construct sense
  704 *        data.
  705 *
  706 * @param[in] this_request This parameter specifies the request for which
  707 *            the unsolicited frame was received.
  708 * @param[in] frame_index This parameter indicates the unsolicited frame
  709 *            index that should contain the response.
  710 *
  711 * @return This method returns an indication of whether the UF
  712 *         frame was handled successfully or not.
  713 * @retval SCI_SUCCESS Currently this value is always returned and indicates
  714 *         successful processing of the TC response.
  715 *
  716 */
  717 static
  718 SCI_STATUS scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler(
  719    SCIC_SDS_REQUEST_T * request,
  720    U32                  frame_index
  721 )
  722 {
  723    SCI_STATUS status =
  724       scic_sds_stp_packet_request_command_phase_common_frame_handler(
  725          request, frame_index);
  726 
  727    SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
  728 
  729    if (status == SCI_SUCCESS)
  730    {
  731        // The command has completed with error status from target device.
  732       status = scic_sds_stp_packet_request_process_status_fis(
  733          request, &this_request->d2h_reg_fis);
  734 
  735       if (status != SCI_SUCCESS)
  736       {
  737          scic_sds_request_set_status(
  738             request,
  739             SCU_TASK_DONE_CHECK_RESPONSE,
  740             status
  741          );
  742       }
  743       else
  744          scic_sds_request_set_status(
  745             request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
  746          );
  747 
  748       //Always complete the NON_DATA command right away, no need to delay completion
  749       //even an error status fis came from target device.
  750       sci_base_state_machine_change_state(
  751          &request->parent.state_machine,
  752          SCI_BASE_REQUEST_STATE_COMPLETED
  753       );
  754    }
  755 
  756    return status;
  757 }
  758 
  759 static
  760 SCI_STATUS scic_sds_stp_packet_request_started_completion_delay_complete_handler(
  761    SCI_BASE_REQUEST_T *request
  762 )
  763 {
  764    SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)request;
  765 
  766    sci_base_state_machine_change_state(
  767       &this_request->parent.state_machine,
  768       SCI_BASE_REQUEST_STATE_COMPLETED
  769    );
  770 
  771    return this_request->sci_status;
  772 }
  773 
  774 // ---------------------------------------------------------------------------
  775 
  776 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
  777 scic_sds_stp_packet_request_started_substate_handler_table
  778 [SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES] =
  779 {
  780    // SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
  781    {
  782       {
  783          scic_sds_request_default_start_handler,
  784          scic_sds_request_started_state_abort_handler,
  785          scic_sds_request_default_complete_handler,
  786          scic_sds_request_default_destruct_handler
  787       },
  788       scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler,
  789       scic_sds_request_default_event_handler,
  790       scic_sds_request_default_frame_handler
  791    },
  792    // SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
  793    {
  794       {
  795          scic_sds_request_default_start_handler,
  796          scic_sds_request_started_state_abort_handler,
  797          scic_sds_request_default_complete_handler,
  798          scic_sds_request_default_destruct_handler
  799       },
  800       scic_sds_request_default_tc_completion_handler,
  801       scic_sds_request_default_event_handler,
  802       scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler
  803    },
  804    // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
  805    {
  806       {
  807          scic_sds_request_default_start_handler,
  808          scic_sds_request_started_state_abort_handler,
  809          scic_sds_request_default_complete_handler,
  810          scic_sds_request_default_destruct_handler
  811       },
  812       scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler,
  813       scic_sds_request_default_event_handler,
  814       scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler
  815    },
  816    // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
  817    {
  818       {
  819          scic_sds_request_default_start_handler,
  820          scic_sds_request_started_state_abort_handler,
  821          scic_sds_request_default_complete_handler,
  822          scic_sds_request_default_destruct_handler
  823       },
  824       scic_sds_request_default_tc_completion_handler,
  825       scic_sds_request_default_event_handler,
  826       scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler
  827    },
  828    // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
  829    {
  830       {
  831          scic_sds_request_default_start_handler,
  832          scic_sds_request_started_state_abort_handler,
  833          scic_sds_stp_packet_request_started_completion_delay_complete_handler,
  834          scic_sds_request_default_destruct_handler
  835       },
  836       scic_sds_request_default_tc_completion_handler,
  837       scic_sds_request_default_event_handler,
  838       scic_sds_request_default_frame_handler
  839    }
  840 };
  841 
  842 /**
  843  * @file
  844  *
  845  * @brief This file contains the Packet IO started substate machine
  846  *        for the SCIC_SDS_IO_REQUEST object.
  847  */
  848 static
  849 void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter(
  850    SCI_BASE_OBJECT_T *object
  851 )
  852 {
  853    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
  854 
  855    SET_STATE_HANDLER(
  856       this_request,
  857       scic_sds_stp_packet_request_started_substate_handler_table,
  858       SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
  859    );
  860 
  861    scic_sds_remote_device_set_working_request(
  862       this_request->target_device, this_request
  863    );
  864 }
  865 
  866 static
  867 void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter(
  868    SCI_BASE_OBJECT_T *object
  869 )
  870 {
  871    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
  872 
  873    SET_STATE_HANDLER(
  874       this_request,
  875       scic_sds_stp_packet_request_started_substate_handler_table,
  876       SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
  877    );
  878 }
  879 
  880 static
  881 void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter(
  882    SCI_BASE_OBJECT_T *object
  883 )
  884 {
  885    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
  886    U8 sat_packet_protocol = this_request->sat_protocol;
  887 
  888    SCU_TASK_CONTEXT_T *task_context;
  889    SCI_STATUS status;
  890 
  891    // Recycle the TC and reconstruct it for sending out data fis containing
  892    // CDB.
  893    task_context = scic_sds_controller_get_task_context_buffer(
  894                         this_request->owning_controller, this_request->io_tag);
  895 
  896    if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA)
  897       scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
  898          this_request, task_context);
  899    else
  900       scu_stp_packet_request_command_phase_construct_task_context(
  901          this_request, task_context);
  902 
  903    // send the new TC out.
  904    status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
  905       &this_request->owning_controller->parent,
  906       &this_request->target_device->parent,
  907       &this_request->parent
  908    );
  909 
  910    if (status == SCI_SUCCESS)
  911       SET_STATE_HANDLER(
  912          this_request,
  913          scic_sds_stp_packet_request_started_substate_handler_table,
  914          SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
  915       );
  916 }
  917 
  918 static
  919 void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter(
  920    SCI_BASE_OBJECT_T *object
  921 )
  922 {
  923    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
  924 
  925    SET_STATE_HANDLER(
  926       this_request,
  927       scic_sds_stp_packet_request_started_substate_handler_table,
  928       SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
  929    );
  930 }
  931 
  932 static
  933 void scic_sds_stp_packet_request_started_completion_delay_enter(
  934    SCI_BASE_OBJECT_T *object
  935 )
  936 {
  937    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
  938 
  939    SET_STATE_HANDLER(
  940       this_request,
  941       scic_sds_stp_packet_request_started_substate_handler_table,
  942       SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
  943    );
  944 }
  945 
  946 
  947 // ---------------------------------------------------------------------------
  948 SCI_BASE_STATE_T
  949    scic_sds_stp_packet_request_started_substate_table
  950       [SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES] =
  951 {
  952    {
  953       SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
  954       scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter,
  955       NULL
  956    },
  957    {
  958       SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE,
  959       scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter,
  960       NULL
  961    },
  962    {
  963       SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
  964       scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter,
  965       NULL
  966    },
  967    {
  968       SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE,
  969       scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter,
  970       NULL
  971    },
  972    {
  973       SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE,
  974       scic_sds_stp_packet_request_started_completion_delay_enter,
  975       NULL
  976    }
  977 };
  978 
  979 #endif //#if !defined(DISABLE_ATAPI)
  980 

Cache object: 34c73fe43dd0762e82b510fa35d198cf


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