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_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 /**
   59  * @file
   60  *
   61  * @brief This file contains the implementation for the operations on an
   62  *        SCIC_SDS_IO_REQUEST object.
   63  */
   64 
   65 #include <dev/isci/scil/intel_sat.h>
   66 #include <dev/isci/scil/intel_sata.h>
   67 #include <dev/isci/scil/intel_sas.h>
   68 #include <dev/isci/scil/sci_util.h>
   69 #include <dev/isci/scil/sci_base_request.h>
   70 #include <dev/isci/scil/scic_controller.h>
   71 #include <dev/isci/scil/scic_io_request.h>
   72 #include <dev/isci/scil/scic_remote_device.h>
   73 #include <dev/isci/scil/scic_user_callback.h>
   74 #include <dev/isci/scil/scic_sds_logger.h>
   75 #include <dev/isci/scil/scic_sds_request.h>
   76 #include <dev/isci/scil/scic_sds_pci.h>
   77 #include <dev/isci/scil/scic_sds_stp_request.h>
   78 #include <dev/isci/scil/scic_sds_controller.h>
   79 #include <dev/isci/scil/scic_sds_controller_registers.h>
   80 #include <dev/isci/scil/scic_sds_remote_device.h>
   81 #include <dev/isci/scil/scic_sds_port.h>
   82 #include <dev/isci/scil/scic_task_request.h>
   83 #include <dev/isci/scil/scu_constants.h>
   84 #include <dev/isci/scil/scu_task_context.h>
   85 #include <dev/isci/scil/scic_sds_smp_request.h>
   86 #include <dev/isci/sci_environment.h>
   87 #include <dev/isci/scil/scic_sds_unsolicited_frame_control.h>
   88 #include <dev/isci/scil/sci_types.h>
   89 #include <dev/isci/scil/scu_completion_codes.h>
   90 #include <dev/isci/scil/intel_scsi.h>
   91 
   92 #if !defined(DISABLE_ATAPI)
   93 #include <dev/isci/scil/scic_sds_stp_packet_request.h>
   94 #endif
   95 
   96 /**
   97 * @struct SCI_SINGLE_LEVEL_LUN
   98 *
   99 * @brief this struct describes the single level LUN structure
  100 *        as per the SAM 4.
  101 */
  102 typedef struct SCI_SINGLE_LEVEL_LUN
  103 {
  104     U8  bus_id              : 6;
  105     U8  address_method      : 2;
  106     U8  lun_number;
  107     U8  second_level_lun[2];
  108     U8  third_level_lun[2];
  109     U8  forth_level_lun[2];
  110 
  111 } SCI_SINGLE_LEVEL_LUN_T;
  112 
  113 
  114 //****************************************************************************
  115 //* SCIC SDS IO REQUEST CONSTANTS
  116 //****************************************************************************
  117 
  118 /**
  119  * We have no timer requirements for IO requests right now
  120  */
  121 #define SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT (0)
  122 #define SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT (0)
  123 
  124 //****************************************************************************
  125 //* SCIC SDS IO REQUEST MACROS
  126 //****************************************************************************
  127 
  128 /**
  129  * This is a helper macro to return the os handle for this request object.
  130  */
  131 #define scic_sds_request_get_user_request(request) \
  132    ((request)->user_request)
  133 
  134 
  135 /**
  136  * This macro returns the sizeof memory required to store the an SSP IO
  137  * request.  This does not include the size of the SGL or SCU Task Context
  138  * memory.The sizeof(U32) are needed for DWORD alignment of the command IU
  139  * and response IU
  140  */
  141 #define scic_ssp_io_request_get_object_size() \
  142    ( \
  143        sizeof(SCI_SSP_COMMAND_IU_T) \
  144      + sizeof (U32) \
  145      + sizeof(SCI_SSP_RESPONSE_IU_T) \
  146      + sizeof (U32) \
  147    )
  148 
  149 /**
  150  * This macro returns the address of the ssp command buffer in the io
  151  * request memory
  152  */
  153 #define scic_sds_ssp_request_get_command_buffer_unaligned(memory) \
  154    ((SCI_SSP_COMMAND_IU_T *)( \
  155       ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) \
  156    ))
  157 
  158 /**
  159  * This macro aligns the ssp command buffer in DWORD alignment
  160 */
  161 #define scic_sds_ssp_request_align_command_buffer(address) \
  162    ((SCI_SSP_COMMAND_IU_T *)( \
  163       (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
  164          & ~(sizeof(U32)- 1) \
  165    ))
  166 
  167 /**
  168  * This macro returns the DWORD-aligned ssp command buffer
  169 */
  170 #define scic_sds_ssp_request_get_command_buffer(memory) \
  171    ((SCI_SSP_COMMAND_IU_T *)  \
  172       ((char *)scic_sds_ssp_request_align_command_buffer( \
  173          (char *) scic_sds_ssp_request_get_command_buffer_unaligned(memory) \
  174    )))
  175 
  176 /**
  177  * This macro returns the address of the ssp response buffer in the io
  178  * request memory
  179  */
  180 #define scic_sds_ssp_request_get_response_buffer_unaligned(memory) \
  181    ((SCI_SSP_RESPONSE_IU_T *)( \
  182          ((char *)(scic_sds_ssp_request_get_command_buffer(memory))) \
  183        + sizeof(SCI_SSP_COMMAND_IU_T) \
  184    ))
  185 
  186 /**
  187  * This macro aligns the ssp response buffer in DWORD-aligned fashion
  188  */
  189 #define scic_sds_ssp_request_align_response_buffer(memory) \
  190    ((SCI_SSP_RESPONSE_IU_T *)( \
  191       (((POINTER_UINT)(memory)) + (sizeof(U32) - 1)) \
  192          & ~(sizeof(U32)- 1) \
  193    ))
  194 
  195 /**
  196  * This macro returns the DWORD-aligned ssp response buffer
  197 */
  198 #define scic_sds_ssp_request_get_response_buffer(memory) \
  199    ((SCI_SSP_RESPONSE_IU_T *) \
  200       ((char *)scic_sds_ssp_request_align_response_buffer ( \
  201          (char *)scic_sds_ssp_request_get_response_buffer_unaligned(memory) \
  202    )))
  203 
  204 /**
  205  * This macro returns the address of the task context buffer in the io
  206  * request memory
  207  */
  208 #define scic_sds_ssp_request_get_task_context_buffer_unaligned(memory) \
  209    ((SCU_TASK_CONTEXT_T *)( \
  210         ((char *)(scic_sds_ssp_request_get_response_buffer(memory))) \
  211       + sizeof(SCI_SSP_RESPONSE_IU_T) \
  212    ))
  213 
  214 /**
  215  * This macro returns the aligned task context buffer
  216  */
  217 #define scic_sds_ssp_request_get_task_context_buffer(memory) \
  218    ((SCU_TASK_CONTEXT_T *)( \
  219       ((char *)scic_sds_request_align_task_context_buffer( \
  220          (char *)scic_sds_ssp_request_get_task_context_buffer_unaligned(memory)) \
  221     )))
  222 
  223 /**
  224  * This macro returns the address of the sgl elment pairs in the io request
  225  * memory buffer
  226  */
  227 #define scic_sds_ssp_request_get_sgl_element_buffer(memory) \
  228    ((SCU_SGL_ELEMENT_PAIR_T *)( \
  229         ((char *)(scic_sds_ssp_request_get_task_context_buffer(memory))) \
  230       + sizeof(SCU_TASK_CONTEXT_T) \
  231     ))
  232 
  233 #if !defined(DISABLE_TASK_MANAGEMENT)
  234 
  235 /**
  236  * This macro returns the sizeof of memory required to store an SSP Task
  237  * request.  This does not include the size of the SCU Task Context memory.
  238  */
  239 #define scic_ssp_task_request_get_object_size() \
  240    ( \
  241        sizeof(SCI_SSP_TASK_IU_T) \
  242      + sizeof(SCI_SSP_RESPONSE_IU_T) \
  243    )
  244 
  245 /**
  246  * This macro returns the address of the ssp command buffer in the task
  247  * request memory.  Yes its the same as the above macro except for the
  248  * name.
  249  */
  250 #define scic_sds_ssp_task_request_get_command_buffer(memory) \
  251    ((SCI_SSP_TASK_IU_T *)( \
  252         ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) \
  253    ))
  254 
  255 /**
  256  * This macro returns the address of the ssp response buffer in the task
  257  * request memory.
  258  */
  259 #define scic_sds_ssp_task_request_get_response_buffer(memory) \
  260    ((SCI_SSP_RESPONSE_IU_T *)( \
  261         ((char *)(scic_sds_ssp_task_request_get_command_buffer(memory))) \
  262       + sizeof(SCI_SSP_TASK_IU_T) \
  263    ))
  264 
  265 /**
  266  * This macro returs the task context buffer for the SSP task request.
  267  */
  268 #define scic_sds_ssp_task_request_get_task_context_buffer(memory) \
  269    ((SCU_TASK_CONTEXT_T *)( \
  270         ((char *)(scic_sds_ssp_task_request_get_response_buffer(memory))) \
  271       + sizeof(SCI_SSP_RESPONSE_IU_T) \
  272    ))
  273 
  274 #endif // !defined(DISABLE_TASK_MANAGEMENT)
  275 
  276 
  277 //****************************************************************************
  278 //* SCIC SDS IO REQUEST PRIVATE METHODS
  279 //****************************************************************************
  280 
  281 #ifdef SCI_LOGGING
  282 /**
  283  * This method will initialize state transition logging for the task request
  284  * object.
  285  *
  286  * @param[in] this_request This is the request for which to track state
  287  *       transitions.
  288  */
  289 void scic_sds_request_initialize_state_logging(
  290    SCIC_SDS_REQUEST_T *this_request
  291 )
  292 {
  293    sci_base_state_machine_logger_initialize(
  294       &this_request->parent.state_machine_logger,
  295       &this_request->parent.state_machine,
  296       &this_request->parent.parent,
  297       scic_cb_logger_log_states,
  298       this_request->is_task_management_request ?
  299       "SCIC_SDS_IO_REQUEST_T(Task)" : "SCIC_SDS_IO_REQUEST_T(IO)",
  300       "base state machine",
  301       SCIC_LOG_OBJECT_SMP_IO_REQUEST |
  302       SCIC_LOG_OBJECT_STP_IO_REQUEST |
  303       SCIC_LOG_OBJECT_SSP_IO_REQUEST
  304    );
  305 
  306    if (this_request->has_started_substate_machine)
  307    {
  308       sci_base_state_machine_logger_initialize(
  309          &this_request->started_substate_machine_logger,
  310          &this_request->started_substate_machine,
  311          &this_request->parent.parent,
  312          scic_cb_logger_log_states,
  313          "SCIC_SDS_IO_REQUEST_T(Task)", "starting substate machine",
  314          SCIC_LOG_OBJECT_SMP_IO_REQUEST |
  315          SCIC_LOG_OBJECT_STP_IO_REQUEST |
  316          SCIC_LOG_OBJECT_SSP_IO_REQUEST
  317      );
  318    }
  319 }
  320 
  321 /**
  322  * This method will stop the state transition logging for the task request
  323  * object.
  324  *
  325  * @param[in] this_request The task request object on which to stop state
  326  *       transition logging.
  327  */
  328 void scic_sds_request_deinitialize_state_logging(
  329    SCIC_SDS_REQUEST_T *this_request
  330 )
  331 {
  332    sci_base_state_machine_logger_deinitialize(
  333       &this_request->parent.state_machine_logger,
  334       &this_request->parent.state_machine
  335    );
  336 
  337    if (this_request->has_started_substate_machine)
  338    {
  339       sci_base_state_machine_logger_deinitialize(
  340          &this_request->started_substate_machine_logger,
  341          &this_request->started_substate_machine
  342       );
  343    }
  344 }
  345 #endif // SCI_LOGGING
  346 
  347 /**
  348  * This method returns the size required to store an SSP IO request object.
  349  *
  350  * @return U32
  351  */
  352 static
  353 U32 scic_sds_ssp_request_get_object_size(void)
  354 {
  355    return   sizeof(SCIC_SDS_REQUEST_T)
  356           + scic_ssp_io_request_get_object_size()
  357           + sizeof(SCU_TASK_CONTEXT_T)
  358           + CACHE_LINE_SIZE
  359           + sizeof(SCU_SGL_ELEMENT_PAIR_T) * SCU_MAX_SGL_ELEMENT_PAIRS;
  360 }
  361 
  362 /**
  363  * @brief This method returns the sgl element pair for the specificed
  364  *        sgl_pair index.
  365  *
  366  * @param[in] this_request This parameter specifies the IO request for which
  367  *            to retrieve the Scatter-Gather List element pair.
  368  * @param[in] sgl_pair_index This parameter specifies the index into the SGL
  369  *            element pair to be retrieved.
  370  *
  371  * @return This method returns a pointer to an SCU_SGL_ELEMENT_PAIR.
  372  */
  373 SCU_SGL_ELEMENT_PAIR_T *scic_sds_request_get_sgl_element_pair(
  374    SCIC_SDS_REQUEST_T *this_request,
  375    U32                 sgl_pair_index
  376 )
  377 {
  378    SCU_TASK_CONTEXT_T *task_context;
  379 
  380    task_context = (SCU_TASK_CONTEXT_T *)this_request->task_context_buffer;
  381 
  382    if (sgl_pair_index == 0)
  383    {
  384       return &task_context->sgl_pair_ab;
  385    }
  386    else if (sgl_pair_index == 1)
  387    {
  388       return &task_context->sgl_pair_cd;
  389    }
  390 
  391    return &this_request->sgl_element_pair_buffer[sgl_pair_index - 2];
  392 }
  393 
  394 /**
  395  * @brief This function will build the SGL list for an IO request.
  396  *
  397  * @param[in] this_request This parameter specifies the IO request for which
  398  *            to build the Scatter-Gather List.
  399  *
  400  * @return none
  401  */
  402 void scic_sds_request_build_sgl(
  403    SCIC_SDS_REQUEST_T *this_request
  404 )
  405 {
  406    void                   *os_sge;
  407    void                   *os_handle;
  408    SCI_PHYSICAL_ADDRESS    physical_address;
  409    U32                     sgl_pair_index = 0;
  410    SCU_SGL_ELEMENT_PAIR_T *scu_sgl_list   = NULL;
  411    SCU_SGL_ELEMENT_PAIR_T *previous_pair  = NULL;
  412 
  413    os_handle = scic_sds_request_get_user_request(this_request);
  414    scic_cb_io_request_get_next_sge(os_handle, NULL, &os_sge);
  415 
  416    while (os_sge != NULL)
  417    {
  418       scu_sgl_list =
  419          scic_sds_request_get_sgl_element_pair(this_request, sgl_pair_index);
  420 
  421       SCU_SGL_COPY(os_handle, scu_sgl_list->A, os_sge);
  422 
  423       scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
  424 
  425       if (os_sge != NULL)
  426       {
  427          SCU_SGL_COPY(os_handle, scu_sgl_list->B, os_sge);
  428 
  429          scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
  430       }
  431       else
  432       {
  433          SCU_SGL_ZERO(scu_sgl_list->B);
  434       }
  435 
  436       if (previous_pair != NULL)
  437       {
  438          scic_cb_io_request_get_physical_address(
  439             scic_sds_request_get_controller(this_request),
  440             this_request,
  441             scu_sgl_list,
  442             &physical_address
  443          );
  444 
  445          previous_pair->next_pair_upper =
  446             sci_cb_physical_address_upper(physical_address);
  447          previous_pair->next_pair_lower =
  448             sci_cb_physical_address_lower(physical_address);
  449       }
  450 
  451       previous_pair = scu_sgl_list;
  452       sgl_pair_index++;
  453    }
  454 
  455    if (scu_sgl_list != NULL)
  456    {
  457       scu_sgl_list->next_pair_upper = 0;
  458       scu_sgl_list->next_pair_lower = 0;
  459    }
  460 }
  461 
  462 /**
  463  * @brief This method initializes common portions of the io request object.
  464  *        This includes construction of the SCI_BASE_REQUEST_T parent.
  465  *
  466  * @param[in] the_controller This parameter specifies the controller for which
  467  *            the request is being constructed.
  468  * @param[in] the_target This parameter specifies the remote device for which
  469  *            the request is being constructed.
  470  * @param[in] io_tag This parameter specifies the IO tag to be utilized for
  471  *            this request.  This parameter can be set to
  472  *            SCI_CONTROLLER_INVALID_IO_TAG.
  473  * @param[in] user_io_request_object This parameter specifies the user
  474  *            request object for which the request is being constructed.
  475  * @param[in] this_request This parameter specifies the request being
  476  *            constructed.
  477  *
  478  * @return none
  479  */
  480 static
  481 void scic_sds_general_request_construct(
  482    SCIC_SDS_CONTROLLER_T    * the_controller,
  483    SCIC_SDS_REMOTE_DEVICE_T * the_target,
  484    U16                        io_tag,
  485    void                     * user_io_request_object,
  486    SCIC_SDS_REQUEST_T       * this_request
  487 )
  488 {
  489    sci_base_request_construct(
  490       &this_request->parent,
  491       sci_base_object_get_logger(the_controller),
  492       scic_sds_request_state_table
  493    );
  494 
  495    this_request->io_tag = io_tag;
  496    this_request->user_request = user_io_request_object;
  497    this_request->owning_controller = the_controller;
  498    this_request->target_device = the_target;
  499    this_request->has_started_substate_machine = FALSE;
  500    this_request->protocol = SCIC_NO_PROTOCOL;
  501    this_request->sat_protocol = 0xFF;
  502    this_request->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX;
  503    this_request->device_sequence = scic_sds_remote_device_get_sequence(the_target);
  504 
  505    this_request->sci_status   = SCI_SUCCESS;
  506    this_request->scu_status   = 0;
  507    this_request->post_context = 0xFFFFFFFF;
  508 
  509    this_request->is_task_management_request = FALSE;
  510 
  511    if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG)
  512    {
  513       this_request->was_tag_assigned_by_user = FALSE;
  514       this_request->task_context_buffer = NULL;
  515    }
  516    else
  517    {
  518       this_request->was_tag_assigned_by_user = TRUE;
  519 
  520       this_request->task_context_buffer =
  521          scic_sds_controller_get_task_context_buffer(
  522             this_request->owning_controller, io_tag);
  523    }
  524 }
  525 
  526 /**
  527  * @brief This method build the remainder of the IO request object.
  528  *
  529  * @pre The scic_sds_general_request_construct() must be called before this
  530  *      call is valid.
  531  *
  532  * @param[in] this_request This parameter specifies the request object being
  533  *            constructed.
  534  *
  535  * @return none
  536  */
  537 void scic_sds_ssp_io_request_assign_buffers(
  538    SCIC_SDS_REQUEST_T *this_request
  539 )
  540 {
  541    this_request->command_buffer =
  542       scic_sds_ssp_request_get_command_buffer(this_request);
  543    this_request->response_buffer =
  544       scic_sds_ssp_request_get_response_buffer(this_request);
  545    this_request->sgl_element_pair_buffer =
  546       scic_sds_ssp_request_get_sgl_element_buffer(this_request);
  547    this_request->sgl_element_pair_buffer =
  548       scic_sds_request_align_sgl_element_buffer(this_request->sgl_element_pair_buffer);
  549 
  550    if (this_request->was_tag_assigned_by_user == FALSE)
  551    {
  552       this_request->task_context_buffer =
  553          scic_sds_ssp_request_get_task_context_buffer(this_request);
  554    }
  555 }
  556 
  557 /**
  558  * @brief This method constructs the SSP Command IU data for this io
  559  *        request object.
  560  *
  561  * @param[in] this_request This parameter specifies the request object for
  562  *            which the SSP command information unit is being built.
  563  *
  564  * @return none
  565  */
  566 static
  567 void scic_sds_io_request_build_ssp_command_iu(
  568    SCIC_SDS_REQUEST_T   *this_request
  569 )
  570 {
  571    SCI_SINGLE_LEVEL_LUN_T lun;
  572    SCI_SSP_COMMAND_IU_T *command_frame;
  573    void                 *os_handle;
  574    U32  cdb_length;
  575    U32 *cdb_buffer;
  576 
  577    command_frame =
  578       (SCI_SSP_COMMAND_IU_T *)this_request->command_buffer;
  579 
  580    os_handle = scic_sds_request_get_user_request(this_request);
  581 
  582    ((U32 *)&lun)[0] = 0;
  583    ((U32 *)&lun)[1] = 0;
  584    lun.lun_number = scic_cb_ssp_io_request_get_lun(os_handle) &0xff;
  585    /// @todo Is it ok to leave junk at the end of the cdb buffer?
  586    scic_word_copy_with_swap(
  587        (U32 *)command_frame->lun,
  588        (U32 *)&lun,
  589        sizeof(lun));
  590 
  591    ((U32 *)command_frame)[2] = 0;
  592 
  593    cdb_length = scic_cb_ssp_io_request_get_cdb_length(os_handle);
  594    cdb_buffer = (U32 *)scic_cb_ssp_io_request_get_cdb_address(os_handle);
  595 
  596    if (cdb_length > 16)
  597    {
  598       command_frame->additional_cdb_length = cdb_length - 16;
  599    }
  600 
  601    /// @todo Is it ok to leave junk at the end of the cdb buffer?
  602    scic_word_copy_with_swap(
  603       (U32 *)(&command_frame->cdb),
  604       (U32 *)(cdb_buffer),
  605       (cdb_length + 3) / sizeof(U32)
  606    );
  607 
  608    command_frame->enable_first_burst = 0;
  609    command_frame->task_priority =
  610       scic_cb_ssp_io_request_get_command_priority(os_handle);
  611    command_frame->task_attribute =
  612       scic_cb_ssp_io_request_get_task_attribute(os_handle);
  613 }
  614 
  615 #if !defined(DISABLE_TASK_MANAGEMENT)
  616 
  617 /**
  618  * @brief This method constructs the SSP Task IU data for this io request
  619  *        object.
  620  *
  621  * @param[in] this_request
  622  *
  623  * @return none
  624  */
  625 static
  626 void scic_sds_task_request_build_ssp_task_iu(
  627    SCIC_SDS_REQUEST_T *this_request
  628 )
  629 {
  630    SCI_SSP_TASK_IU_T *command_frame;
  631    void              *os_handle;
  632 
  633    command_frame =
  634       (SCI_SSP_TASK_IU_T *)this_request->command_buffer;
  635 
  636    os_handle = scic_sds_request_get_user_request(this_request);
  637 
  638    command_frame->lun_upper = 0;
  639    command_frame->lun_lower = scic_cb_ssp_task_request_get_lun(os_handle);
  640 
  641    ((U32 *)command_frame)[2] = 0;
  642 
  643    command_frame->task_function =
  644       scic_cb_ssp_task_request_get_function(os_handle);
  645    command_frame->task_tag =
  646       scic_cb_ssp_task_request_get_io_tag_to_manage(os_handle);
  647 }
  648 
  649 #endif // !defined(DISABLE_TASK_MANAGEMENT)
  650 
  651 /**
  652  * @brief This method is will fill in the SCU Task Context for any type of
  653  *        SSP request.
  654  *
  655  * @param[in] this_request
  656  * @param[in] task_context
  657  *
  658  * @return none
  659  */
  660 static
  661 void scu_ssp_reqeust_construct_task_context(
  662    SCIC_SDS_REQUEST_T * this_request,
  663    SCU_TASK_CONTEXT_T * task_context
  664 )
  665 {
  666    SCI_PHYSICAL_ADDRESS      physical_address;
  667    SCIC_SDS_CONTROLLER_T    *owning_controller;
  668    SCIC_SDS_REMOTE_DEVICE_T *target_device;
  669    SCIC_SDS_PORT_T          *target_port;
  670 
  671    owning_controller = scic_sds_request_get_controller(this_request);
  672    target_device = scic_sds_request_get_device(this_request);
  673    target_port = scic_sds_request_get_port(this_request);
  674 
  675    // Fill in the TC with the its required data
  676    task_context->abort = 0;
  677    task_context->priority = 0;
  678    task_context->initiator_request = 1;
  679    task_context->connection_rate =
  680       scic_remote_device_get_connection_rate(target_device);
  681    task_context->protocol_engine_index =
  682       scic_sds_controller_get_protocol_engine_group(owning_controller);
  683    task_context->logical_port_index =
  684       scic_sds_port_get_index(target_port);
  685    task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
  686    task_context->valid = SCU_TASK_CONTEXT_VALID;
  687    task_context->context_type = SCU_TASK_CONTEXT_TYPE;
  688 
  689    task_context->remote_node_index =
  690       scic_sds_remote_device_get_index(this_request->target_device);
  691    task_context->command_code = 0;
  692 
  693    task_context->link_layer_control = 0;
  694    task_context->do_not_dma_ssp_good_response = 1;
  695    task_context->strict_ordering = 0;
  696    task_context->control_frame = 0;
  697    task_context->timeout_enable = 0;
  698    task_context->block_guard_enable = 0;
  699 
  700    task_context->address_modifier = 0;
  701 
  702    //task_context->type.ssp.tag = this_request->io_tag;
  703    task_context->task_phase = 0x01;
  704 
  705    if (this_request->was_tag_assigned_by_user)
  706    {
  707       // Build the task context now since we have already read the data
  708       this_request->post_context = (
  709            SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
  710          | (
  711                 scic_sds_controller_get_protocol_engine_group(owning_controller)
  712              << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
  713            )
  714          | (
  715                  scic_sds_port_get_index(target_port)
  716               << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
  717            )
  718          | scic_sds_io_tag_get_index(this_request->io_tag)
  719       );
  720    }
  721    else
  722    {
  723       // Build the task context now since we have already read the data
  724       this_request->post_context = (
  725            SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
  726          | (
  727                scic_sds_controller_get_protocol_engine_group(owning_controller)
  728             << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
  729            )
  730          | (
  731                 scic_sds_port_get_index(target_port)
  732              << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
  733            )
  734          // This is not assigned because we have to wait until we get a TCi
  735       );
  736    }
  737 
  738    // Copy the physical address for the command buffer to the SCU Task Context
  739    scic_cb_io_request_get_physical_address(
  740       scic_sds_request_get_controller(this_request),
  741       this_request,
  742       this_request->command_buffer,
  743       &physical_address
  744    );
  745 
  746    task_context->command_iu_upper =
  747       sci_cb_physical_address_upper(physical_address);
  748    task_context->command_iu_lower =
  749       sci_cb_physical_address_lower(physical_address);
  750 
  751    // Copy the physical address for the response buffer to the SCU Task Context
  752    scic_cb_io_request_get_physical_address(
  753       scic_sds_request_get_controller(this_request),
  754       this_request,
  755       this_request->response_buffer,
  756       &physical_address
  757    );
  758 
  759    task_context->response_iu_upper =
  760       sci_cb_physical_address_upper(physical_address);
  761    task_context->response_iu_lower =
  762       sci_cb_physical_address_lower(physical_address);
  763 }
  764 
  765 /**
  766  * @brief This method is will fill in the SCU Task Context for a SSP IO
  767  *        request.
  768  *
  769  * @param[in] this_request
  770  *
  771  * @return none
  772  */
  773 static
  774 void scu_ssp_io_request_construct_task_context(
  775    SCIC_SDS_REQUEST_T *this_request,
  776    SCI_IO_REQUEST_DATA_DIRECTION data_direction,
  777    U32 transfer_length_bytes
  778 )
  779 {
  780    SCU_TASK_CONTEXT_T *task_context;
  781 
  782    task_context = scic_sds_request_get_task_context(this_request);
  783 
  784    scu_ssp_reqeust_construct_task_context(this_request, task_context);
  785 
  786    task_context->ssp_command_iu_length = sizeof(SCI_SSP_COMMAND_IU_T) / sizeof(U32);
  787    task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME;
  788 
  789    switch (data_direction)
  790    {
  791    case SCI_IO_REQUEST_DATA_IN:
  792    case SCI_IO_REQUEST_NO_DATA:
  793       task_context->task_type = SCU_TASK_TYPE_IOREAD;
  794       break;
  795    case SCI_IO_REQUEST_DATA_OUT:
  796       task_context->task_type = SCU_TASK_TYPE_IOWRITE;
  797       break;
  798    }
  799 
  800    task_context->transfer_length_bytes = transfer_length_bytes;
  801 
  802    if (task_context->transfer_length_bytes > 0)
  803    {
  804       scic_sds_request_build_sgl(this_request);
  805    }
  806 }
  807 
  808 #if !defined(DISABLE_TASK_MANAGEMENT)
  809 
  810 /**
  811  * @brief This method will fill in the remainder of the io request object
  812  *        for SSP Task requests.
  813  *
  814  * @param[in] this_request
  815  *
  816  * @return none
  817  */
  818 void scic_sds_ssp_task_request_assign_buffers(
  819    SCIC_SDS_REQUEST_T *this_request
  820 )
  821 {
  822    // Assign all of the buffer pointers
  823    this_request->command_buffer =
  824       scic_sds_ssp_task_request_get_command_buffer(this_request);
  825    this_request->response_buffer =
  826       scic_sds_ssp_task_request_get_response_buffer(this_request);
  827    this_request->sgl_element_pair_buffer = NULL;
  828 
  829    if (this_request->was_tag_assigned_by_user == FALSE)
  830    {
  831       this_request->task_context_buffer =
  832          scic_sds_ssp_task_request_get_task_context_buffer(this_request);
  833       this_request->task_context_buffer =
  834          scic_sds_request_align_task_context_buffer(this_request->task_context_buffer);
  835    }
  836 }
  837 
  838 /**
  839  * @brief This method will fill in the SCU Task Context for a SSP Task
  840  *        request.  The following important settings are utilized:
  841  *          -# priority == SCU_TASK_PRIORITY_HIGH.  This ensures that the
  842  *             task request is issued ahead of other task destined for the
  843  *             same Remote Node.
  844  *          -# task_type == SCU_TASK_TYPE_IOREAD.  This simply indicates
  845  *             that a normal request type (i.e. non-raw frame) is being
  846  *             utilized to perform task management.
  847  *          -# control_frame == 1.  This ensures that the proper endianness
  848  *             is set so that the bytes are transmitted in the right order
  849  *             for a task frame.
  850  *
  851  * @param[in] this_request This parameter specifies the task request object
  852  *            being constructed.
  853  *
  854  * @return none
  855  */
  856 static
  857 void scu_ssp_task_request_construct_task_context(
  858    SCIC_SDS_REQUEST_T *this_request
  859 )
  860 {
  861    SCU_TASK_CONTEXT_T *task_context;
  862 
  863    task_context = scic_sds_request_get_task_context(this_request);
  864 
  865    scu_ssp_reqeust_construct_task_context(this_request, task_context);
  866 
  867    task_context->control_frame                = 1;
  868    task_context->priority                     = SCU_TASK_PRIORITY_HIGH;
  869    task_context->task_type                    = SCU_TASK_TYPE_RAW_FRAME;
  870    task_context->transfer_length_bytes        = 0;
  871    task_context->type.ssp.frame_type          = SCI_SAS_TASK_FRAME;
  872    task_context->ssp_command_iu_length = sizeof(SCI_SSP_TASK_IU_T) / sizeof(U32);
  873 }
  874 
  875 #endif // !defined(DISABLE_TASK_MANAGEMENT)
  876 
  877 #if !defined(DISABLE_PASS_THROUGH)
  878 /**
  879  * @brief This method constructs the SSP Command IU data for this
  880  *        ssp passthrough comand request object.
  881  *
  882  * @param[in] this_request This parameter specifies the request object for
  883  *            which the SSP command information unit is being built.
  884  *
  885  * @return SCI_STATUS, returns invalid parameter is cdb > 16
  886  */
  887 static
  888 SCI_STATUS scic_sds_io_request_build_ssp_command_iu_pass_through(
  889    SCIC_SDS_REQUEST_T   *this_request,
  890    SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS_T *ssp_passthru_cb
  891 )
  892 {
  893    SCI_SSP_COMMAND_IU_T *command_frame;
  894    U32  cdb_length = 0, additional_cdb_length = 0;
  895    U8 *cdb_buffer, *additional_cdb_buffer;
  896    U8 *scsi_lun;
  897    SCI_STATUS sci_status = SCI_SUCCESS;
  898    SCI_SINGLE_LEVEL_LUN_T lun;
  899 
  900    command_frame =
  901       (SCI_SSP_COMMAND_IU_T *)this_request->command_buffer;
  902 
  903    //get the lun
  904    ssp_passthru_cb->scic_cb_ssp_passthru_get_lun (
  905       this_request,
  906      &scsi_lun
  907    );
  908    memset(&lun, 0, sizeof(lun));
  909    lun.lun_number = *scsi_lun;
  910    scic_word_copy_with_swap(
  911        (U32 *)command_frame->lun,
  912        (U32 *)&lun,
  913        sizeof(lun));
  914 
  915    ((U32 *)command_frame)[2] = 0;
  916 
  917    ssp_passthru_cb->scic_cb_ssp_passthru_get_cdb(
  918       this_request,
  919      &cdb_length,
  920      &cdb_buffer,
  921      &additional_cdb_length,
  922      &additional_cdb_buffer
  923    );
  924 
  925    command_frame->additional_cdb_length = additional_cdb_length;
  926 
  927    // ----------- TODO
  928    ///todo: what to do with additional cdb length and buffer as the current command buffer is
  929    // 16 bytes in intel_sas.h
  930    // ??? see the SAS command IU
  931    if (additional_cdb_length > 0)
  932    {
  933      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
  934    }
  935 
  936    /// @todo Is it ok to leave junk at the end of the cdb buffer?
  937    scic_word_copy_with_swap(
  938       (U32 *)(&command_frame->cdb),
  939       (U32 *)(cdb_buffer),
  940       (cdb_length + 3) / sizeof(U32)
  941    );
  942 
  943    /////-------- End fo TODO
  944 
  945    command_frame->enable_first_burst = 0;
  946    command_frame->task_priority = 0;  //todo: check with Richard ????
  947 
  948    //get the task attribute
  949    command_frame->task_attribute = ssp_passthru_cb->scic_cb_ssp_passthru_get_task_attribute (
  950                                       this_request
  951                              );
  952 
  953    return sci_status;
  954 }
  955 #endif // !defined(DISABLE_PASS_THROUGH)
  956 
  957 //****************************************************************************
  958 //* SCIC Interface Implementation
  959 //****************************************************************************
  960 
  961 #if !defined(DISABLE_TASK_MANAGEMENT)
  962 /**
  963  * This method returns the size required to store an SSP task request object.
  964  *
  965  * @return U32
  966  */
  967 static
  968 U32 scic_sds_ssp_task_request_get_object_size(void)
  969 {
  970    return   sizeof(SCIC_SDS_REQUEST_T)
  971           + scic_ssp_task_request_get_object_size()
  972           + sizeof(SCU_TASK_CONTEXT_T)
  973           + CACHE_LINE_SIZE;
  974 }
  975 
  976 
  977 U32 scic_task_request_get_object_size(void)
  978 {
  979    U32 ssp_task_request_size;
  980    U32 stp_task_request_size;
  981 
  982    ssp_task_request_size = scic_sds_ssp_task_request_get_object_size();
  983    stp_task_request_size = scic_sds_stp_task_request_get_object_size();
  984 
  985    return MAX(ssp_task_request_size, stp_task_request_size);
  986 }
  987 
  988 #endif // !defined(DISABLE_TASK_MANAGEMENT)
  989 
  990 // ---------------------------------------------------------------------------
  991 
  992 U32 scic_io_request_get_object_size(void)
  993 {
  994    U32 ssp_request_size;
  995    U32 stp_request_size;
  996    U32 smp_request_size;
  997 
  998    ssp_request_size = scic_sds_ssp_request_get_object_size();
  999    stp_request_size = scic_sds_stp_request_get_object_size();
 1000    smp_request_size = scic_sds_smp_request_get_object_size();
 1001 
 1002    return MAX(ssp_request_size, MAX(stp_request_size, smp_request_size));
 1003 }
 1004 
 1005 // ---------------------------------------------------------------------------
 1006 
 1007 SCIC_TRANSPORT_PROTOCOL scic_io_request_get_protocol(
 1008    SCI_IO_REQUEST_HANDLE_T  scic_io_request
 1009 )
 1010 {
 1011    SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
 1012    return this_request->protocol;
 1013 }
 1014 
 1015 // ---------------------------------------------------------------------------
 1016 
 1017 U32 scic_sds_request_get_min_timer_count(void)
 1018 {
 1019    return SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT;
 1020 }
 1021 
 1022 // ---------------------------------------------------------------------------
 1023 
 1024 U32 scic_sds_request_get_max_timer_count(void)
 1025 {
 1026    return SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT;
 1027 }
 1028 
 1029 // ---------------------------------------------------------------------------
 1030 
 1031 SCI_STATUS scic_io_request_construct(
 1032    SCI_CONTROLLER_HANDLE_T      scic_controller,
 1033    SCI_REMOTE_DEVICE_HANDLE_T   scic_remote_device,
 1034    U16                          io_tag,
 1035    void                       * user_io_request_object,
 1036    void                       * scic_io_request_memory,
 1037    SCI_IO_REQUEST_HANDLE_T    * new_scic_io_request_handle
 1038 )
 1039 {
 1040    SCI_STATUS                          status = SCI_SUCCESS;
 1041    SCIC_SDS_REQUEST_T                * this_request;
 1042    SMP_DISCOVER_RESPONSE_PROTOCOLS_T   device_protocol;
 1043 
 1044    this_request = (SCIC_SDS_REQUEST_T * )scic_io_request_memory;
 1045 
 1046    SCIC_LOG_TRACE((
 1047       sci_base_object_get_logger(scic_controller),
 1048       (SCIC_LOG_OBJECT_SSP_IO_REQUEST
 1049       |SCIC_LOG_OBJECT_SMP_IO_REQUEST
 1050       |SCIC_LOG_OBJECT_STP_IO_REQUEST),
 1051       "scic_io_request_construct(0x%x, 0x%x, 0x02x, 0x%x, 0x%x, 0x%x) enter\n",
 1052       scic_controller, scic_remote_device,
 1053       io_tag, user_io_request_object,
 1054       this_request, new_scic_io_request_handle
 1055    ));
 1056 
 1057    // Build the common part of the request
 1058    scic_sds_general_request_construct(
 1059       (SCIC_SDS_CONTROLLER_T *)scic_controller,
 1060       (SCIC_SDS_REMOTE_DEVICE_T *)scic_remote_device,
 1061       io_tag,
 1062       user_io_request_object,
 1063       this_request
 1064    );
 1065 
 1066    if (
 1067          scic_sds_remote_device_get_index((SCIC_SDS_REMOTE_DEVICE_T *)scic_remote_device)
 1068       == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
 1069       )
 1070    {
 1071       return SCI_FAILURE_INVALID_REMOTE_DEVICE;
 1072    }
 1073 
 1074    scic_remote_device_get_protocols(scic_remote_device, &device_protocol);
 1075 
 1076    if (device_protocol.u.bits.attached_ssp_target)
 1077    {
 1078       scic_sds_ssp_io_request_assign_buffers(this_request);
 1079    }
 1080    else if (device_protocol.u.bits.attached_stp_target)
 1081    {
 1082       scic_sds_stp_request_assign_buffers(this_request);
 1083       memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
 1084    }
 1085    else if (device_protocol.u.bits.attached_smp_target)
 1086    {
 1087       scic_sds_smp_request_assign_buffers(this_request);
 1088       memset(this_request->command_buffer, 0, sizeof(SMP_REQUEST_T));
 1089    }
 1090    else
 1091    {
 1092       status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
 1093    }
 1094 
 1095    if (status == SCI_SUCCESS)
 1096    {
 1097       memset(
 1098          this_request->task_context_buffer,
 1099          0,
 1100          SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, sgl_pair_ab)
 1101       );
 1102       *new_scic_io_request_handle = scic_io_request_memory;
 1103    }
 1104 
 1105    return status;
 1106 }
 1107 
 1108 // ---------------------------------------------------------------------------
 1109 
 1110 #if !defined(DISABLE_TASK_MANAGEMENT)
 1111 
 1112 SCI_STATUS scic_task_request_construct(
 1113    SCI_CONTROLLER_HANDLE_T     controller,
 1114    SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
 1115    U16                         io_tag,
 1116    void                       *user_io_request_object,
 1117    void                       *scic_task_request_memory,
 1118    SCI_TASK_REQUEST_HANDLE_T  *new_scic_task_request_handle
 1119 )
 1120 {
 1121    SCI_STATUS           status = SCI_SUCCESS;
 1122    SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)
 1123                                        scic_task_request_memory;
 1124    SMP_DISCOVER_RESPONSE_PROTOCOLS_T   device_protocol;
 1125 
 1126    SCIC_LOG_TRACE((
 1127       sci_base_object_get_logger(controller),
 1128       (SCIC_LOG_OBJECT_SSP_IO_REQUEST
 1129       |SCIC_LOG_OBJECT_SMP_IO_REQUEST
 1130       |SCIC_LOG_OBJECT_STP_IO_REQUEST),
 1131       "scic_task_request_construct(0x%x, 0x%x, 0x02x, 0x%x, 0x%x, 0x%x) enter\n",
 1132       controller, remote_device,
 1133       io_tag, user_io_request_object,
 1134       scic_task_request_memory, new_scic_task_request_handle
 1135    ));
 1136 
 1137    // Build the common part of the request
 1138    scic_sds_general_request_construct(
 1139       (SCIC_SDS_CONTROLLER_T *)controller,
 1140       (SCIC_SDS_REMOTE_DEVICE_T *)remote_device,
 1141       io_tag,
 1142       user_io_request_object,
 1143       this_request
 1144    );
 1145 
 1146    scic_remote_device_get_protocols(remote_device, &device_protocol);
 1147 
 1148    if (device_protocol.u.bits.attached_ssp_target)
 1149    {
 1150       scic_sds_ssp_task_request_assign_buffers(this_request);
 1151 
 1152       this_request->has_started_substate_machine = TRUE;
 1153 
 1154       // Construct the started sub-state machine.
 1155       sci_base_state_machine_construct(
 1156          &this_request->started_substate_machine,
 1157          &this_request->parent.parent,
 1158          scic_sds_io_request_started_task_mgmt_substate_table,
 1159          SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
 1160       );
 1161    }
 1162    else if (device_protocol.u.bits.attached_stp_target)
 1163    {
 1164       scic_sds_stp_request_assign_buffers(this_request);
 1165    }
 1166    else
 1167    {
 1168       status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
 1169    }
 1170 
 1171    if (status == SCI_SUCCESS)
 1172    {
 1173       this_request->is_task_management_request = TRUE;
 1174       memset(this_request->task_context_buffer, 0x00, sizeof(SCU_TASK_CONTEXT_T));
 1175       *new_scic_task_request_handle            = scic_task_request_memory;
 1176    }
 1177 
 1178    return status;
 1179 }
 1180 
 1181 #endif // !defined(DISABLE_TASK_MANAGEMENT)
 1182 
 1183 // ---------------------------------------------------------------------------
 1184 
 1185 SCI_STATUS scic_io_request_construct_basic_ssp(
 1186    SCI_IO_REQUEST_HANDLE_T  scic_io_request
 1187 )
 1188 {
 1189    void               *os_handle;
 1190    SCIC_SDS_REQUEST_T *this_request;
 1191    this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
 1192 
 1193    SCIC_LOG_TRACE((
 1194       sci_base_object_get_logger(this_request),
 1195       SCIC_LOG_OBJECT_SSP_IO_REQUEST,
 1196       "scic_io_request_construct_basic_ssp(0x%x) enter\n",
 1197       this_request
 1198    ));
 1199 
 1200    this_request->protocol = SCIC_SSP_PROTOCOL;
 1201 
 1202    os_handle = scic_sds_request_get_user_request(this_request);
 1203 
 1204    scu_ssp_io_request_construct_task_context(
 1205       this_request,
 1206       scic_cb_io_request_get_data_direction(os_handle),
 1207       scic_cb_io_request_get_transfer_length(os_handle)
 1208    );
 1209 
 1210 
 1211    scic_sds_io_request_build_ssp_command_iu(this_request);
 1212 
 1213    scic_sds_request_initialize_state_logging(this_request);
 1214 
 1215    sci_base_state_machine_change_state(
 1216       &this_request->parent.state_machine,
 1217       SCI_BASE_REQUEST_STATE_CONSTRUCTED
 1218    );
 1219 
 1220    return SCI_SUCCESS;
 1221 }
 1222 
 1223 // ---------------------------------------------------------------------------
 1224 
 1225 #if !defined(DISABLE_TASK_MANAGEMENT)
 1226 
 1227 SCI_STATUS scic_task_request_construct_ssp(
 1228    SCI_TASK_REQUEST_HANDLE_T  scic_task_request
 1229 )
 1230 {
 1231    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)
 1232                                       scic_task_request;
 1233 
 1234    SCIC_LOG_TRACE((
 1235       sci_base_object_get_logger(this_request),
 1236       SCIC_LOG_OBJECT_SSP_IO_REQUEST,
 1237       "scic_task_request_construct_ssp(0x%x) enter\n",
 1238       this_request
 1239    ));
 1240 
 1241    // Construct the SSP Task SCU Task Context
 1242    scu_ssp_task_request_construct_task_context(this_request);
 1243 
 1244    // Fill in the SSP Task IU
 1245    scic_sds_task_request_build_ssp_task_iu(this_request);
 1246 
 1247    scic_sds_request_initialize_state_logging(this_request);
 1248 
 1249    sci_base_state_machine_change_state(
 1250       &this_request->parent.state_machine,
 1251       SCI_BASE_REQUEST_STATE_CONSTRUCTED
 1252    );
 1253 
 1254    return SCI_SUCCESS;
 1255 }
 1256 
 1257 #endif // !defined(DISABLE_TASK_MANAGEMENT)
 1258 
 1259 // ---------------------------------------------------------------------------
 1260 
 1261 SCI_STATUS scic_io_request_construct_advanced_ssp(
 1262    SCI_IO_REQUEST_HANDLE_T    scic_io_request,
 1263    SCIC_IO_SSP_PARAMETERS_T * io_parameters
 1264 )
 1265 {
 1266    SCIC_LOG_TRACE((
 1267       sci_base_object_get_logger(scic_io_request),
 1268       SCIC_LOG_OBJECT_SSP_IO_REQUEST,
 1269       "scic_io_request_construct_advanced_ssp(0x%x, 0x%x) enter\n",
 1270       io_parameters, scic_io_request
 1271    ));
 1272 
 1273    /// @todo Implement after 1.1
 1274    return SCI_FAILURE;
 1275 }
 1276 
 1277 // ---------------------------------------------------------------------------
 1278 
 1279 #if !defined(DISABLE_PASS_THROUGH)
 1280 SCI_STATUS scic_io_request_construct_ssp_pass_through (
 1281    void                    * scic_io_request,
 1282    SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS_T *ssp_passthru_cb
 1283 )
 1284 {
 1285    SCI_STATUS               status = SCI_SUCCESS;
 1286    SCIC_SDS_REQUEST_T       * this_request;
 1287 
 1288    this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
 1289 
 1290    SCIC_LOG_TRACE((
 1291       sci_base_object_get_logger(scic_io_request),
 1292       SCIC_LOG_OBJECT_STP_IO_REQUEST,
 1293       "scic_io_request_construct_ssp_pass_through(0x%x) enter\n",
 1294       scic_io_request
 1295    ));
 1296 
 1297    //build the task context from the pass through buffer
 1298    scu_ssp_io_request_construct_task_context(
 1299       this_request,
 1300       ssp_passthru_cb->common_callbacks.scic_cb_passthru_get_data_direction (this_request),
 1301       ssp_passthru_cb->common_callbacks.scic_cb_passthru_get_transfer_length(this_request)
 1302    );
 1303 
 1304    //build the ssp command iu from the pass through buffer
 1305    status = scic_sds_io_request_build_ssp_command_iu_pass_through (
 1306                this_request,
 1307                ssp_passthru_cb
 1308             );
 1309    if (status != SCI_SUCCESS)
 1310    {
 1311       return status;
 1312    }
 1313 
 1314    /* initialize the logging */
 1315    scic_sds_request_initialize_state_logging(this_request);
 1316 
 1317    sci_base_state_machine_change_state(
 1318       &this_request->parent.state_machine,
 1319       SCI_BASE_REQUEST_STATE_CONSTRUCTED
 1320    );
 1321 
 1322    return status;
 1323 }
 1324 #endif // !defined(DISABLE_PASS_THROUGH)
 1325 
 1326 // ---------------------------------------------------------------------------
 1327 
 1328 #if !defined(DISABLE_TASK_MANAGEMENT)
 1329 
 1330 SCI_STATUS scic_task_request_construct_sata(
 1331    SCI_TASK_REQUEST_HANDLE_T scic_task_request
 1332 )
 1333 {
 1334    SCI_STATUS           status;
 1335    SCIC_SDS_REQUEST_T * this_request;
 1336    U8                   sat_protocol;
 1337 
 1338    this_request = (SCIC_SDS_REQUEST_T *)scic_task_request;
 1339 
 1340    SCIC_LOG_TRACE((
 1341       sci_base_object_get_logger(this_request),
 1342       SCIC_LOG_OBJECT_STP_IO_REQUEST,
 1343       "scic_task_request_construct_sata(0x%x) enter\n",
 1344       this_request
 1345    ));
 1346 
 1347    sat_protocol =
 1348       scic_cb_request_get_sat_protocol(this_request->user_request);
 1349 
 1350    this_request->sat_protocol = sat_protocol;
 1351 
 1352    switch (sat_protocol)
 1353    {
 1354    case SAT_PROTOCOL_ATA_HARD_RESET:
 1355    case SAT_PROTOCOL_SOFT_RESET:
 1356       status = scic_sds_stp_soft_reset_request_construct(this_request);
 1357       break;
 1358 
 1359    case SAT_PROTOCOL_PIO_DATA_IN:
 1360       status = scic_sds_stp_pio_request_construct(this_request, sat_protocol, FALSE);
 1361       break;
 1362 
 1363    default:
 1364       SCIC_LOG_ERROR((
 1365          sci_base_object_get_logger(this_request),
 1366          SCIC_LOG_OBJECT_STP_IO_REQUEST,
 1367          "SCIC IO Request 0x%x received un-handled SAT Protocl %d.\n",
 1368          this_request, sat_protocol
 1369       ));
 1370 
 1371       status = SCI_FAILURE;
 1372       break;
 1373    }
 1374 
 1375    if (status == SCI_SUCCESS)
 1376    {
 1377       scic_sds_request_initialize_state_logging(this_request);
 1378 
 1379       sci_base_state_machine_change_state(
 1380          &this_request->parent.state_machine,
 1381          SCI_BASE_REQUEST_STATE_CONSTRUCTED
 1382       );
 1383    }
 1384 
 1385    return status;
 1386 }
 1387 
 1388 #endif // !defined(DISABLE_TASK_MANAGEMENT)
 1389 
 1390 // ---------------------------------------------------------------------------
 1391 
 1392 #if !defined(DISABLE_PASS_THROUGH)
 1393 SCI_STATUS scic_io_request_construct_sata_pass_through(
 1394    SCI_IO_REQUEST_HANDLE_T scic_io_request,
 1395    SCIC_STP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb
 1396 )
 1397 {
 1398    SCI_STATUS                       status = SCI_SUCCESS;
 1399    SCIC_SDS_REQUEST_T               * this_request;
 1400    U8                               sat_protocol;
 1401    U8                               * reg_fis;
 1402    U32                              transfer_length;
 1403    SCI_IO_REQUEST_DATA_DIRECTION    data_direction;
 1404 
 1405    this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
 1406 
 1407    SCIC_LOG_TRACE((
 1408       sci_base_object_get_logger(scic_io_request),
 1409       SCIC_LOG_OBJECT_STP_IO_REQUEST,
 1410       "scic_io_request_construct_sata_pass_through(0x%x) enter\n",
 1411       scic_io_request
 1412    ));
 1413 
 1414    passthru_cb->scic_cb_stp_passthru_get_register_fis(this_request, &reg_fis);
 1415 
 1416    if (reg_fis == NULL)
 1417    {
 1418       status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
 1419    }
 1420 
 1421    if (status == SCI_SUCCESS)
 1422    {
 1423       //copy the H2D Reg fis blindly from the request to the SCU command buffer
 1424       memcpy ((U8 *)this_request->command_buffer, (U8 *)reg_fis, sizeof(SATA_FIS_REG_H2D_T));
 1425 
 1426       //continue to create the request
 1427       sat_protocol = passthru_cb->scic_cb_stp_passthru_get_protocol(this_request);
 1428       transfer_length = passthru_cb->common_callbacks.scic_cb_passthru_get_transfer_length(this_request);
 1429       data_direction = passthru_cb->common_callbacks.scic_cb_passthru_get_data_direction(this_request);
 1430 
 1431       status = scic_sds_io_request_construct_sata(
 1432                   this_request,
 1433                   sat_protocol,
 1434                   transfer_length,
 1435                   data_direction,
 1436                   TRUE,
 1437                   TRUE
 1438                );
 1439 
 1440       this_request->protocol = SCIC_STP_PROTOCOL;
 1441    }
 1442 
 1443    return status;
 1444 }
 1445 #endif // !defined(DISABLE_PASS_THROUGH)
 1446 
 1447 // ---------------------------------------------------------------------------
 1448 
 1449 U16 scic_io_request_get_io_tag(
 1450    SCI_IO_REQUEST_HANDLE_T  scic_io_request
 1451 )
 1452 {
 1453    SCIC_SDS_REQUEST_T *this_request;
 1454    this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
 1455 
 1456    SCIC_LOG_TRACE((
 1457       sci_base_object_get_logger(scic_io_request),
 1458       SCIC_LOG_OBJECT_SMP_IO_REQUEST,
 1459       "scic_io_request_get_io_tag(0x%x) enter\n",
 1460       scic_io_request
 1461    ));
 1462 
 1463    return this_request->io_tag;
 1464 }
 1465 
 1466 // ---------------------------------------------------------------------------
 1467 
 1468 U32 scic_request_get_controller_status(
 1469    SCI_IO_REQUEST_HANDLE_T  io_request
 1470 )
 1471 {
 1472    SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T*)io_request;
 1473    return this_request->scu_status;
 1474 }
 1475 
 1476 U32 scic_request_get_sci_status(
 1477    SCI_IO_REQUEST_HANDLE_T  io_request
 1478 )
 1479 {
 1480    SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T*)io_request;
 1481    return this_request->sci_status;
 1482 }
 1483 
 1484 // ---------------------------------------------------------------------------
 1485 
 1486 void * scic_io_request_get_rx_frame(
 1487    SCI_IO_REQUEST_HANDLE_T  scic_io_request,
 1488    U32                      offset
 1489 )
 1490 {
 1491    void               * frame_buffer = NULL;
 1492    SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
 1493 
 1494    ASSERT(offset < SCU_UNSOLICITED_FRAME_BUFFER_SIZE);
 1495 
 1496    if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX)
 1497    {
 1498       scic_sds_unsolicited_frame_control_get_buffer(
 1499          &(this_request->owning_controller->uf_control),
 1500          this_request->saved_rx_frame_index,
 1501          &frame_buffer
 1502       );
 1503    }
 1504 
 1505    return frame_buffer;
 1506 }
 1507 
 1508 void * scic_io_request_get_command_iu_address(
 1509    SCI_IO_REQUEST_HANDLE_T  scic_io_request
 1510 )
 1511 {
 1512    SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
 1513 
 1514    return this_request->command_buffer;
 1515 }
 1516 
 1517 // ---------------------------------------------------------------------------
 1518 
 1519 void * scic_io_request_get_response_iu_address(
 1520    SCI_IO_REQUEST_HANDLE_T scic_io_request
 1521 )
 1522 {
 1523    SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
 1524 
 1525    return this_request->response_buffer;
 1526 }
 1527 
 1528 // ---------------------------------------------------------------------------
 1529 #define SCU_TASK_CONTEXT_SRAM 0x200000
 1530 U32 scic_io_request_get_number_of_bytes_transferred (
 1531    SCI_IO_REQUEST_HANDLE_T  scic_io_request
 1532 )
 1533 {
 1534    U32 ret_val = 0;
 1535    SCIC_SDS_REQUEST_T       * scic_sds_request;
 1536 
 1537    scic_sds_request = (SCIC_SDS_REQUEST_T *) scic_io_request;
 1538 
 1539    if ( SMU_AMR_READ (scic_sds_request->owning_controller) == 0)
 1540    {
 1541       //get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where
 1542       //   BAR1 is the scu_registers
 1543       //   0x20002C = 0x200000 + 0x2c
 1544       //            = start of task context SRAM + offset of (type.ssp.data_offset)
 1545       //   TCi is the io_tag of SCIC_SDS_REQUEST
 1546       ret_val =  scic_sds_pci_read_scu_dword(
 1547                     scic_sds_request->owning_controller,
 1548                     (
 1549                        (U8 *) scic_sds_request->owning_controller->scu_registers +
 1550                           ( SCU_TASK_CONTEXT_SRAM + SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, type.ssp.data_offset) ) +
 1551                        ( ( sizeof (SCU_TASK_CONTEXT_T) ) * scic_sds_io_tag_get_index (scic_sds_request->io_tag))
 1552                     )
 1553                  );
 1554    }
 1555 
 1556    return ret_val;
 1557 }
 1558 
 1559 //****************************************************************************
 1560 //* SCIC SDS Interface Implementation
 1561 //****************************************************************************
 1562 
 1563 /**
 1564  * This method invokes the base state start request handler for the
 1565  * SCIC_SDS_IO_REQUEST_T object.
 1566  *
 1567  * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
 1568  *       start operation is to be executed.
 1569  *
 1570  * @return SCI_STATUS
 1571  */
 1572 SCI_STATUS scic_sds_request_start(
 1573    SCIC_SDS_REQUEST_T *this_request
 1574 )
 1575 {
 1576    if (
 1577          this_request->device_sequence
 1578       == scic_sds_remote_device_get_sequence(this_request->target_device)
 1579       )
 1580    {
 1581       return this_request->state_handlers->parent.start_handler(
 1582                 &this_request->parent
 1583              );
 1584    }
 1585 
 1586    return SCI_FAILURE;
 1587 }
 1588 
 1589 /**
 1590  * This method invokes the base state terminate request handber for the
 1591  * SCIC_SDS_IO_REQUEST_T object.
 1592  *
 1593  * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
 1594  *       start operation is to be executed.
 1595  *
 1596  * @return SCI_STATUS
 1597  */
 1598 SCI_STATUS scic_sds_io_request_terminate(
 1599    SCIC_SDS_REQUEST_T *this_request
 1600 )
 1601 {
 1602    return this_request->state_handlers->parent.abort_handler(
 1603                                                       &this_request->parent);
 1604 }
 1605 
 1606 /**
 1607  * This method invokes the base state request completion handler for the
 1608  * SCIC_SDS_IO_REQUEST_T object.
 1609  *
 1610  * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
 1611  *       start operation is to be executed.
 1612  *
 1613  * @return SCI_STATUS
 1614  */
 1615 SCI_STATUS scic_sds_io_request_complete(
 1616    SCIC_SDS_REQUEST_T *this_request
 1617 )
 1618 {
 1619    return this_request->state_handlers->parent.complete_handler(
 1620                                                       &this_request->parent);
 1621 }
 1622 
 1623 /**
 1624  * This method invokes the core state handler for the SCIC_SDS_IO_REQUEST_T
 1625  * object.
 1626  *
 1627  * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
 1628  *       start operation is to be executed.
 1629  * @param[in] event_code The event code returned by the hardware for the task
 1630  *       reqeust.
 1631  *
 1632  * @return SCI_STATUS
 1633  */
 1634 SCI_STATUS scic_sds_io_request_event_handler(
 1635    SCIC_SDS_REQUEST_T * this_request,
 1636    U32                  event_code
 1637 )
 1638 {
 1639    return this_request->state_handlers->event_handler(this_request, event_code);
 1640 }
 1641 
 1642 /**
 1643  * This method invokes the core state frame handler for the
 1644  * SCIC_SDS_IO_REQUEST_T object.
 1645  *
 1646  * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
 1647  *       start operation is to be executed.
 1648  * @param[in] frame_index The frame index returned by the hardware for the
 1649  *       reqeust object.
 1650  *
 1651  * @return SCI_STATUS
 1652  */
 1653 SCI_STATUS scic_sds_io_request_frame_handler(
 1654    SCIC_SDS_REQUEST_T * this_request,
 1655    U32                  frame_index
 1656 )
 1657 {
 1658    return this_request->state_handlers->frame_handler(this_request, frame_index);
 1659 }
 1660 
 1661 /**
 1662  * This method invokes the core state task complete handler for the
 1663  * SCIC_SDS_IO_REQUEST_T object.
 1664  *
 1665  * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the task
 1666  *       start operation is to be executed.
 1667  *
 1668  * @return SCI_STATUS
 1669  */
 1670 SCI_STATUS scic_sds_task_request_complete(
 1671    SCIC_SDS_REQUEST_T *this_request
 1672 )
 1673 {
 1674    return this_request->state_handlers->parent.complete_handler(&this_request->parent);
 1675 }
 1676 
 1677 //****************************************************************************
 1678 //* SCIC SDS PROTECTED METHODS
 1679 //****************************************************************************
 1680 
 1681 /**
 1682  * @brief This method copies response data for requests returning response
 1683  *        data instead of sense data.
 1684  *
 1685  * @param[in]  this_request This parameter specifies the request object for
 1686  *             which to copy the response data.
 1687  *
 1688  * @return none
 1689  */
 1690 void scic_sds_io_request_copy_response(
 1691    SCIC_SDS_REQUEST_T *this_request
 1692 )
 1693 {
 1694    void                  * response_buffer;
 1695    U32                     user_response_length;
 1696    U32                     core_response_length;
 1697    SCI_SSP_RESPONSE_IU_T * ssp_response;
 1698 
 1699    ssp_response = (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
 1700 
 1701    response_buffer = scic_cb_ssp_task_request_get_response_data_address(
 1702                         this_request->user_request
 1703                      );
 1704 
 1705    user_response_length = scic_cb_ssp_task_request_get_response_data_length(
 1706                         this_request->user_request
 1707                      );
 1708 
 1709    core_response_length = sci_ssp_get_response_data_length(
 1710                            ssp_response->response_data_length
 1711                      );
 1712 
 1713    user_response_length = MIN(user_response_length, core_response_length);
 1714 
 1715    memcpy(response_buffer, ssp_response->data, user_response_length);
 1716 }
 1717 
 1718 //******************************************************************************
 1719 //* REQUEST STATE MACHINE
 1720 //******************************************************************************
 1721 
 1722 //*****************************************************************************
 1723 //*  DEFAULT STATE HANDLERS
 1724 //*****************************************************************************
 1725 
 1726 /**
 1727  * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
 1728  * object receives a scic_sds_request_start() request.  The default action is
 1729  * to log a warning and return a failure status.
 1730  *
 1731  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 1732  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 1733  *       requested.
 1734  *
 1735  * @return SCI_STATUS
 1736  * @retval SCI_FAILURE_INVALID_STATE
 1737  */
 1738 SCI_STATUS scic_sds_request_default_start_handler(
 1739    SCI_BASE_REQUEST_T *request
 1740 )
 1741 {
 1742    SCIC_LOG_WARNING((
 1743       sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
 1744       (
 1745           SCIC_LOG_OBJECT_SSP_IO_REQUEST
 1746         | SCIC_LOG_OBJECT_STP_IO_REQUEST
 1747         | SCIC_LOG_OBJECT_SMP_IO_REQUEST
 1748       ),
 1749       "SCIC IO Request requested to start while in wrong state %d\n",
 1750       sci_base_state_machine_get_state(
 1751          &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
 1752    ));
 1753 
 1754    return SCI_FAILURE_INVALID_STATE;
 1755 }
 1756 
 1757 /**
 1758  * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
 1759  * object receives a scic_sds_request_terminate() request.  The default action
 1760  * is to log a warning and return a failure status.
 1761  *
 1762  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 1763  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 1764  *       requested.
 1765  *
 1766  * @return SCI_STATUS
 1767  * @retval SCI_FAILURE_INVALID_STATE
 1768  */
 1769 SCI_STATUS scic_sds_request_default_abort_handler(
 1770    SCI_BASE_REQUEST_T *request
 1771 )
 1772 {
 1773    SCIC_LOG_WARNING((
 1774       sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
 1775       (
 1776           SCIC_LOG_OBJECT_SSP_IO_REQUEST
 1777         | SCIC_LOG_OBJECT_STP_IO_REQUEST
 1778         | SCIC_LOG_OBJECT_SMP_IO_REQUEST
 1779       ),
 1780       "SCIC IO Request requested to abort while in wrong state %d\n",
 1781       sci_base_state_machine_get_state(
 1782          &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
 1783    ));
 1784 
 1785    return SCI_FAILURE_INVALID_STATE;
 1786 }
 1787 
 1788 /**
 1789  * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
 1790  * object receives a scic_sds_request_complete() request.  The default action
 1791  * is to log a warning and return a failure status.
 1792  *
 1793  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 1794  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 1795  *       requested.
 1796  *
 1797  * @return SCI_STATUS
 1798  * @retval SCI_FAILURE_INVALID_STATE
 1799  */
 1800 SCI_STATUS scic_sds_request_default_complete_handler(
 1801    SCI_BASE_REQUEST_T *request
 1802 )
 1803 {
 1804    SCIC_LOG_WARNING((
 1805       sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
 1806       (
 1807           SCIC_LOG_OBJECT_SSP_IO_REQUEST
 1808         | SCIC_LOG_OBJECT_STP_IO_REQUEST
 1809         | SCIC_LOG_OBJECT_SMP_IO_REQUEST
 1810       ),
 1811       "SCIC IO Request requested to complete while in wrong state %d\n",
 1812       sci_base_state_machine_get_state(
 1813          &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
 1814    ));
 1815 
 1816    return SCI_FAILURE_INVALID_STATE;
 1817 }
 1818 
 1819 /**
 1820  * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
 1821  * object receives a scic_sds_request_complete() request.  The default action
 1822  * is to log a warning and return a failure status.
 1823  *
 1824  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 1825  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 1826  *       requested.
 1827  *
 1828  * @return SCI_STATUS
 1829  * @retval SCI_FAILURE_INVALID_STATE
 1830  */
 1831 SCI_STATUS scic_sds_request_default_destruct_handler(
 1832    SCI_BASE_REQUEST_T *request
 1833 )
 1834 {
 1835    SCIC_LOG_WARNING((
 1836       sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
 1837       (
 1838           SCIC_LOG_OBJECT_SSP_IO_REQUEST
 1839         | SCIC_LOG_OBJECT_STP_IO_REQUEST
 1840         | SCIC_LOG_OBJECT_SMP_IO_REQUEST
 1841       ),
 1842       "SCIC IO Request requested to destroy while in wrong state %d\n",
 1843       sci_base_state_machine_get_state(
 1844          &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
 1845    ));
 1846 
 1847    return SCI_FAILURE_INVALID_STATE;
 1848 }
 1849 
 1850 /**
 1851  * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
 1852  * object receives a scic_sds_task_request_complete() request.  The default
 1853  * action is to log a warning and return a failure status.
 1854  *
 1855  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 1856  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 1857  *       requested.
 1858  *
 1859  * @return SCI_STATUS
 1860  * @retval SCI_FAILURE_INVALID_STATE
 1861  */
 1862 SCI_STATUS scic_sds_request_default_tc_completion_handler(
 1863    SCIC_SDS_REQUEST_T * this_request,
 1864    U32                  completion_code
 1865 )
 1866 {
 1867    SCIC_LOG_WARNING((
 1868       sci_base_object_get_logger(this_request),
 1869       (
 1870           SCIC_LOG_OBJECT_SSP_IO_REQUEST
 1871         | SCIC_LOG_OBJECT_STP_IO_REQUEST
 1872         | SCIC_LOG_OBJECT_SMP_IO_REQUEST
 1873       ),
 1874       "SCIC IO Request given task completion notification %x while in wrong state %d\n",
 1875       completion_code,
 1876       sci_base_state_machine_get_state(&this_request->parent.state_machine)
 1877    ));
 1878 
 1879    return SCI_FAILURE_INVALID_STATE;
 1880 
 1881 }
 1882 
 1883 /**
 1884  * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
 1885  * object receives a scic_sds_request_event_handler() request.  The default
 1886  * action is to log a warning and return a failure status.
 1887  *
 1888  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 1889  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 1890  *       requested.
 1891  *
 1892  * @return SCI_STATUS
 1893  * @retval SCI_FAILURE_INVALID_STATE
 1894  */
 1895 SCI_STATUS scic_sds_request_default_event_handler(
 1896    SCIC_SDS_REQUEST_T * this_request,
 1897    U32                  event_code
 1898 )
 1899 {
 1900    SCIC_LOG_WARNING((
 1901       sci_base_object_get_logger(this_request),
 1902       (
 1903           SCIC_LOG_OBJECT_SSP_IO_REQUEST
 1904         | SCIC_LOG_OBJECT_STP_IO_REQUEST
 1905         | SCIC_LOG_OBJECT_SMP_IO_REQUEST
 1906       ),
 1907       "SCIC IO Request given event code notification %x while in wrong state %d\n",
 1908       event_code,
 1909       sci_base_state_machine_get_state(&this_request->parent.state_machine)
 1910    ));
 1911 
 1912    return SCI_FAILURE_INVALID_STATE;
 1913 }
 1914 
 1915 /**
 1916  * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
 1917  * object receives a scic_sds_request_event_handler() request.  The default
 1918  * action is to log a warning and return a failure status.
 1919  *
 1920  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 1921  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 1922  *       requested.
 1923  *
 1924  * @return SCI_STATUS
 1925  * @retval SCI_FAILURE_INVALID_STATE
 1926  */
 1927 SCI_STATUS scic_sds_request_default_frame_handler(
 1928    SCIC_SDS_REQUEST_T * this_request,
 1929    U32                  frame_index
 1930 )
 1931 {
 1932    SCIC_LOG_WARNING((
 1933       sci_base_object_get_logger(this_request),
 1934       (
 1935           SCIC_LOG_OBJECT_SSP_IO_REQUEST
 1936         | SCIC_LOG_OBJECT_STP_IO_REQUEST
 1937         | SCIC_LOG_OBJECT_SMP_IO_REQUEST
 1938       ),
 1939       "SCIC IO Request given unexpected frame %x while in state %d\n",
 1940       frame_index,
 1941       sci_base_state_machine_get_state(&this_request->parent.state_machine)
 1942    ));
 1943 
 1944    scic_sds_controller_release_frame(
 1945       this_request->owning_controller, frame_index);
 1946 
 1947    return SCI_FAILURE_INVALID_STATE;
 1948 }
 1949 
 1950 //*****************************************************************************
 1951 //*  CONSTRUCTED STATE HANDLERS
 1952 //*****************************************************************************
 1953 
 1954 /**
 1955  * This method implements the action taken when a constructed
 1956  * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request.
 1957  *
 1958  * This method will, if necessary, allocate a TCi for the io request object
 1959  * and then will, if necessary, copy the constructed TC data into the actual
 1960  * TC buffer.  If everything is successful the post context field is updated
 1961  * with the TCi so the controller can post the request to the hardware.
 1962  *
 1963  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 1964  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 1965  *       requested.
 1966  *
 1967  * @return SCI_STATUS
 1968  * @retval SCI_SUCCESS
 1969  * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES
 1970  */
 1971 static
 1972 SCI_STATUS scic_sds_request_constructed_state_start_handler(
 1973    SCI_BASE_REQUEST_T *request
 1974 )
 1975 {
 1976    SCU_TASK_CONTEXT_T *task_context;
 1977    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
 1978 
 1979    if (this_request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG)
 1980    {
 1981       this_request->io_tag =
 1982          scic_controller_allocate_io_tag(this_request->owning_controller);
 1983    }
 1984 
 1985    // Record the IO Tag in the request
 1986    if (this_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)
 1987    {
 1988       task_context = this_request->task_context_buffer;
 1989 
 1990       task_context->task_index = scic_sds_io_tag_get_index(this_request->io_tag);
 1991 
 1992       switch (task_context->protocol_type)
 1993       {
 1994       case SCU_TASK_CONTEXT_PROTOCOL_SMP:
 1995       case SCU_TASK_CONTEXT_PROTOCOL_SSP:
 1996          // SSP/SMP Frame
 1997          task_context->type.ssp.tag = this_request->io_tag;
 1998          task_context->type.ssp.target_port_transfer_tag = 0xFFFF;
 1999          break;
 2000 
 2001       case SCU_TASK_CONTEXT_PROTOCOL_STP:
 2002          // STP/SATA Frame
 2003          //task_context->type.stp.ncq_tag = this_request->ncq_tag;
 2004          break;
 2005 
 2006       case SCU_TASK_CONTEXT_PROTOCOL_NONE:
 2007          /// @todo When do we set no protocol type?
 2008          break;
 2009 
 2010       default:
 2011          // This should never happen since we build the IO requests
 2012          break;
 2013       }
 2014 
 2015       // Check to see if we need to copy the task context buffer
 2016       // or have been building into the task context buffer
 2017       if (this_request->was_tag_assigned_by_user == FALSE)
 2018       {
 2019          scic_sds_controller_copy_task_context(
 2020             this_request->owning_controller, this_request
 2021          );
 2022       }
 2023 
 2024       // Add to the post_context the io tag value
 2025       this_request->post_context |= scic_sds_io_tag_get_index(this_request->io_tag);
 2026 
 2027       // Everything is good go ahead and change state
 2028       sci_base_state_machine_change_state(
 2029          &this_request->parent.state_machine,
 2030          SCI_BASE_REQUEST_STATE_STARTED
 2031       );
 2032 
 2033       return SCI_SUCCESS;
 2034    }
 2035 
 2036    return SCI_FAILURE_INSUFFICIENT_RESOURCES;
 2037 }
 2038 
 2039 /**
 2040  * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
 2041  * object receives a scic_sds_request_terminate() request.
 2042  *
 2043  * Since the request has not yet been posted to the hardware the request
 2044  * transitions to the completed state.
 2045  *
 2046  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 2047  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 2048  *       requested.
 2049  *
 2050  * @return SCI_STATUS
 2051  * @retval SCI_SUCCESS
 2052  */
 2053 static
 2054 SCI_STATUS scic_sds_request_constructed_state_abort_handler(
 2055    SCI_BASE_REQUEST_T *request
 2056 )
 2057 {
 2058    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
 2059 
 2060    // This request has been terminated by the user make sure that the correct
 2061    // status code is returned
 2062    scic_sds_request_set_status(
 2063       this_request,
 2064       SCU_TASK_DONE_TASK_ABORT,
 2065       SCI_FAILURE_IO_TERMINATED
 2066    );
 2067 
 2068    sci_base_state_machine_change_state(
 2069       &this_request->parent.state_machine,
 2070       SCI_BASE_REQUEST_STATE_COMPLETED
 2071    );
 2072 
 2073    return SCI_SUCCESS;
 2074 }
 2075 
 2076 //*****************************************************************************
 2077 //*  STARTED STATE HANDLERS
 2078 //*****************************************************************************
 2079 
 2080 /**
 2081  * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
 2082  * object receives a scic_sds_request_terminate() request.
 2083  *
 2084  * Since the request has been posted to the hardware the io request state is
 2085  * changed to the aborting state.
 2086  *
 2087  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 2088  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 2089  *       requested.
 2090  *
 2091  * @return SCI_STATUS
 2092  * @retval SCI_SUCCESS
 2093  */
 2094 SCI_STATUS scic_sds_request_started_state_abort_handler(
 2095    SCI_BASE_REQUEST_T *request
 2096 )
 2097 {
 2098    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
 2099 
 2100    if (this_request->has_started_substate_machine)
 2101    {
 2102       sci_base_state_machine_stop(&this_request->started_substate_machine);
 2103    }
 2104 
 2105    sci_base_state_machine_change_state(
 2106       &this_request->parent.state_machine,
 2107       SCI_BASE_REQUEST_STATE_ABORTING
 2108    );
 2109 
 2110    return SCI_SUCCESS;
 2111 }
 2112 
 2113 /**
 2114  * @brief This method process TC (task context) completions for normal IO
 2115  *        request (i.e. Task/Abort Completions of type 0).  This method will
 2116  *        update the SCIC_SDS_IO_REQUEST_T::status field.
 2117  *
 2118  * @param[in] this_request This parameter specifies the request for which
 2119  *             a completion occurred.
 2120  * @param[in]  completion_code This parameter specifies the completion code
 2121  *             received from the SCU.
 2122  *
 2123  * @return none
 2124  */
 2125 SCI_STATUS scic_sds_request_started_state_tc_completion_handler(
 2126    SCIC_SDS_REQUEST_T * this_request,
 2127    U32                  completion_code
 2128 )
 2129 {
 2130    U8                      data_present;
 2131    SCI_SSP_RESPONSE_IU_T * response_buffer;
 2132 
 2133    /**
 2134     * @todo Any SDMA return code of other than 0 is bad
 2135     *       decode 0x003C0000 to determine SDMA status
 2136     */
 2137    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
 2138    {
 2139    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
 2140       scic_sds_request_set_status(
 2141          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
 2142       );
 2143       break;
 2144 
 2145    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP):
 2146    {
 2147       // There are times when the SCU hardware will return an early response
 2148       // because the io request specified more data than is returned by the
 2149       // target device (mode pages, inquiry data, etc.).  We must check the
 2150       // response stats to see if this is truly a failed request or a good
 2151       // request that just got completed early.
 2152       SCI_SSP_RESPONSE_IU_T *response = (SCI_SSP_RESPONSE_IU_T *)
 2153                                         this_request->response_buffer;
 2154       scic_word_copy_with_swap(
 2155          this_request->response_buffer,
 2156          this_request->response_buffer,
 2157          sizeof(SCI_SSP_RESPONSE_IU_T) / sizeof(U32)
 2158       );
 2159 
 2160       if (response->status == 0)
 2161       {
 2162          scic_sds_request_set_status(
 2163             this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
 2164          );
 2165       }
 2166       else
 2167       {
 2168          scic_sds_request_set_status(
 2169             this_request,
 2170             SCU_TASK_DONE_CHECK_RESPONSE,
 2171             SCI_FAILURE_IO_RESPONSE_VALID
 2172          );
 2173       }
 2174    }
 2175    break;
 2176 
 2177    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE):
 2178       scic_word_copy_with_swap(
 2179          this_request->response_buffer,
 2180          this_request->response_buffer,
 2181          sizeof(SCI_SSP_RESPONSE_IU_T) / sizeof(U32)
 2182       );
 2183 
 2184       scic_sds_request_set_status(
 2185          this_request,
 2186          SCU_TASK_DONE_CHECK_RESPONSE,
 2187          SCI_FAILURE_IO_RESPONSE_VALID
 2188       );
 2189       break;
 2190 
 2191    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR):
 2192       /// @todo With TASK_DONE_RESP_LEN_ERR is the response frame guaranteed
 2193       ///       to be received before this completion status is posted?
 2194       response_buffer =
 2195          (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
 2196       data_present =
 2197          response_buffer->data_present & SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK;
 2198 
 2199       if ((data_present == 0x01) || (data_present == 0x02))
 2200       {
 2201          scic_sds_request_set_status(
 2202             this_request,
 2203             SCU_TASK_DONE_CHECK_RESPONSE,
 2204             SCI_FAILURE_IO_RESPONSE_VALID
 2205          );
 2206       }
 2207       else
 2208       {
 2209          scic_sds_request_set_status(
 2210             this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
 2211          );
 2212       }
 2213       break;
 2214 
 2215    //only stp device gets suspended.
 2216    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO):
 2217    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_PERR):
 2218    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_ERR):
 2219    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_DATA_LEN_ERR):
 2220    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_ABORT_ERR):
 2221    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_WD_LEN):
 2222    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
 2223    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_RESP):
 2224    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS):
 2225    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR):
 2226    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR):
 2227       if (this_request->protocol == SCIC_STP_PROTOCOL)
 2228       {
 2229          SCIC_LOG_ERROR((
 2230             sci_base_object_get_logger(this_request),
 2231             SCIC_LOG_OBJECT_STP_IO_REQUEST,
 2232             "SCIC IO Request 0x%x returning REMOTE_DEVICE_RESET_REQUIRED for completion code 0x%x\n",
 2233             this_request, completion_code
 2234          ));
 2235          scic_sds_request_set_status(
 2236             this_request,
 2237             SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
 2238             SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
 2239          );
 2240       }
 2241       else
 2242       {
 2243          SCIC_LOG_ERROR((
 2244             sci_base_object_get_logger(this_request),
 2245             SCIC_LOG_OBJECT_SSP_IO_REQUEST,
 2246             "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n",
 2247             this_request, completion_code
 2248          ));
 2249          scic_sds_request_set_status(
 2250             this_request,
 2251             SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
 2252             SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
 2253          );
 2254       }
 2255       break;
 2256 
 2257    //both stp/ssp device gets suspended
 2258    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LF_ERR):
 2259    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_WRONG_DESTINATION):
 2260    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1):
 2261    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2):
 2262    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3):
 2263    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_BAD_DESTINATION):
 2264    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_ZONE_VIOLATION):
 2265    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY):
 2266    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED):
 2267    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED):
 2268       scic_sds_request_set_status(
 2269          this_request,
 2270          SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
 2271          SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
 2272       );
 2273      break;
 2274 
 2275    //neither ssp nor stp gets suspended.
 2276    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_CMD_ERR):
 2277    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_XR):
 2278    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_IU_LEN_ERR):
 2279    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDMA_ERR):
 2280    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OFFSET_ERR):
 2281    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EXCESS_DATA):
 2282    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
 2283    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
 2284    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
 2285    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
 2286    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_DATA):
 2287    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OPEN_FAIL):
 2288    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_VIIT_ENTRY_NV):
 2289    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV):
 2290    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND):
 2291    default:
 2292       SCIC_LOG_ERROR((
 2293          sci_base_object_get_logger(this_request),
 2294          SCIC_LOG_OBJECT_SSP_IO_REQUEST | SCIC_LOG_OBJECT_STP_IO_REQUEST,
 2295          "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n",
 2296          this_request, completion_code
 2297       ));
 2298       scic_sds_request_set_status(
 2299          this_request,
 2300          SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
 2301          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
 2302       );
 2303       break;
 2304    }
 2305 
 2306    /**
 2307     * @todo This is probably wrong for ACK/NAK timeout conditions
 2308     */
 2309 
 2310    // In all cases we will treat this as the completion of the IO request.
 2311    sci_base_state_machine_change_state(
 2312       &this_request->parent.state_machine,
 2313       SCI_BASE_REQUEST_STATE_COMPLETED
 2314    );
 2315 
 2316    return SCI_SUCCESS;
 2317 }
 2318 
 2319 /**
 2320  * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
 2321  * object receives a scic_sds_request_frame_handler() request.
 2322  *
 2323  * This method first determines the frame type received.  If this is a
 2324  * response frame then the response data is copied to the io request response
 2325  * buffer for processing at completion time.
 2326  *
 2327  * If the frame type is not a response buffer an error is logged.
 2328  *
 2329  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 2330  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 2331  *       requested.
 2332  * @param[in] frame_index This is the index of the unsolicited frame to be
 2333  *       processed.
 2334  *
 2335  * @return SCI_STATUS
 2336  * @retval SCI_SUCCESS
 2337  * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE
 2338  */
 2339 static
 2340 SCI_STATUS scic_sds_request_started_state_frame_handler(
 2341    SCIC_SDS_REQUEST_T * this_request,
 2342    U32                  frame_index
 2343 )
 2344 {
 2345    SCI_STATUS status;
 2346    SCI_SSP_FRAME_HEADER_T *frame_header;
 2347 
 2348    /// @todo If this is a response frame we must record that we received it
 2349    status = scic_sds_unsolicited_frame_control_get_header(
 2350       &(scic_sds_request_get_controller(this_request)->uf_control),
 2351       frame_index,
 2352       (void**) &frame_header
 2353    );
 2354 
 2355    if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME)
 2356    {
 2357       SCI_SSP_RESPONSE_IU_T *response_buffer;
 2358 
 2359       status = scic_sds_unsolicited_frame_control_get_buffer(
 2360          &(scic_sds_request_get_controller(this_request)->uf_control),
 2361          frame_index,
 2362          (void**) &response_buffer
 2363       );
 2364 
 2365       scic_word_copy_with_swap(
 2366          this_request->response_buffer,
 2367          (U32 *)response_buffer,
 2368          sizeof(SCI_SSP_RESPONSE_IU_T)
 2369       );
 2370 
 2371       response_buffer = (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
 2372 
 2373       if (
 2374             (response_buffer->data_present == 0x01)
 2375          || (response_buffer->data_present == 0x02)
 2376          )
 2377       {
 2378          scic_sds_request_set_status(
 2379             this_request,
 2380             SCU_TASK_DONE_CHECK_RESPONSE,
 2381             SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
 2382          );
 2383       }
 2384       else
 2385       {
 2386          scic_sds_request_set_status(
 2387             this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
 2388          );
 2389       }
 2390 
 2391    }
 2392    else
 2393    {
 2394       // This was not a response frame why did it get forwarded?
 2395       SCIC_LOG_ERROR((
 2396          sci_base_object_get_logger(this_request),
 2397          SCIC_LOG_OBJECT_SSP_IO_REQUEST,
 2398          "SCIC IO Request 0x%x received unexpected frame %d type 0x%02x\n",
 2399          this_request, frame_index, frame_header->frame_type
 2400       ));
 2401    }
 2402 
 2403    // In any case we are done with this frame buffer return it to the
 2404    // controller
 2405    scic_sds_controller_release_frame(
 2406       this_request->owning_controller, frame_index
 2407    );
 2408 
 2409    return SCI_SUCCESS;
 2410 }
 2411 
 2412 //*****************************************************************************
 2413 //*  COMPLETED STATE HANDLERS
 2414 //*****************************************************************************
 2415 
 2416 
 2417 /**
 2418  * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
 2419  * object receives a scic_sds_request_complete() request.
 2420  *
 2421  * This method frees up any io request resources that have been allocated and
 2422  * transitions the request to its final state.
 2423  *
 2424  * @todo Consider stopping the state machine instead of transitioning to the
 2425  *       final state?
 2426  *
 2427  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 2428  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 2429  *       requested.
 2430  *
 2431  * @return SCI_STATUS
 2432  * @retval SCI_SUCCESS
 2433  */
 2434 static
 2435 SCI_STATUS scic_sds_request_completed_state_complete_handler(
 2436    SCI_BASE_REQUEST_T *request
 2437 )
 2438 {
 2439    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
 2440 
 2441    if (this_request->was_tag_assigned_by_user != TRUE)
 2442    {
 2443       scic_controller_free_io_tag(
 2444          this_request->owning_controller, this_request->io_tag
 2445       );
 2446    }
 2447 
 2448    if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX)
 2449    {
 2450       scic_sds_controller_release_frame(
 2451          this_request->owning_controller, this_request->saved_rx_frame_index);
 2452    }
 2453 
 2454    sci_base_state_machine_change_state(
 2455       &this_request->parent.state_machine,
 2456       SCI_BASE_REQUEST_STATE_FINAL
 2457    );
 2458 
 2459    scic_sds_request_deinitialize_state_logging(this_request);
 2460 
 2461    return SCI_SUCCESS;
 2462 }
 2463 
 2464 //*****************************************************************************
 2465 //*  ABORTING STATE HANDLERS
 2466 //*****************************************************************************
 2467 
 2468 /**
 2469  * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
 2470  * object receives a scic_sds_request_terminate() request.
 2471  *
 2472  * This method is the io request aborting state abort handlers.  On receipt of
 2473  * a multiple terminate requests the io request will transition to the
 2474  * completed state.  This should not happen in normal operation.
 2475  *
 2476  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 2477  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 2478  *       requested.
 2479  *
 2480  * @return SCI_STATUS
 2481  * @retval SCI_SUCCESS
 2482  */
 2483 static
 2484 SCI_STATUS scic_sds_request_aborting_state_abort_handler(
 2485    SCI_BASE_REQUEST_T *request
 2486 )
 2487 {
 2488    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
 2489 
 2490    sci_base_state_machine_change_state(
 2491       &this_request->parent.state_machine,
 2492       SCI_BASE_REQUEST_STATE_COMPLETED
 2493    );
 2494 
 2495    return SCI_SUCCESS;
 2496 }
 2497 
 2498 /**
 2499  * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
 2500  * object receives a scic_sds_request_task_completion() request.
 2501  *
 2502  * This method decodes the completion type waiting for the abort task complete
 2503  * notification. When the abort task complete is received the io request
 2504  * transitions to the completed state.
 2505  *
 2506  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 2507  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 2508  *       requested.
 2509  *
 2510  * @return SCI_STATUS
 2511  * @retval SCI_SUCCESS
 2512  */
 2513 static
 2514 SCI_STATUS scic_sds_request_aborting_state_tc_completion_handler(
 2515    SCIC_SDS_REQUEST_T * this_request,
 2516    U32                  completion_code
 2517 )
 2518 {
 2519    SCIC_LOG_TRACE((
 2520       sci_base_object_get_logger(this_request),
 2521       SCIC_LOG_OBJECT_TASK_MANAGEMENT,
 2522       "scic_sds_request_aborting_state_tc_completion_handler(0x%x,0x%x) enter\n",
 2523       this_request, completion_code
 2524    ));
 2525 
 2526    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
 2527    {
 2528    case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
 2529    case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT):
 2530       scic_sds_request_set_status(
 2531          this_request, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED
 2532       );
 2533 
 2534       sci_base_state_machine_change_state(
 2535          &this_request->parent.state_machine,
 2536          SCI_BASE_REQUEST_STATE_COMPLETED
 2537       );
 2538       break;
 2539 
 2540    default:
 2541       // Unless we get some strange error wait for the task abort to complete
 2542       // TODO: Should there be a state change for this completion?
 2543       break;
 2544    }
 2545 
 2546    return SCI_SUCCESS;
 2547 }
 2548 
 2549 /**
 2550  * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
 2551  * object receives a scic_sds_request_frame_handler() request.
 2552  *
 2553  * This method discards the unsolicited frame since we are waiting for the
 2554  * abort task completion.
 2555  *
 2556  * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
 2557  *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
 2558  *       requested.
 2559  *
 2560  * @return SCI_STATUS
 2561  * @retval SCI_SUCCESS
 2562  */
 2563 static
 2564 SCI_STATUS scic_sds_request_aborting_state_frame_handler(
 2565    SCIC_SDS_REQUEST_T * this_request,
 2566    U32                  frame_index
 2567 )
 2568 {
 2569    // TODO: Is it even possible to get an unsolicited frame in the aborting state?
 2570 
 2571    scic_sds_controller_release_frame(
 2572       this_request->owning_controller, frame_index);
 2573 
 2574    return SCI_SUCCESS;
 2575 }
 2576 
 2577 // ---------------------------------------------------------------------------
 2578 
 2579 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
 2580    scic_sds_request_state_handler_table[SCI_BASE_REQUEST_MAX_STATES] =
 2581 {
 2582    // SCI_BASE_REQUEST_STATE_INITIAL
 2583    {
 2584       {
 2585          scic_sds_request_default_start_handler,
 2586          scic_sds_request_default_abort_handler,
 2587          scic_sds_request_default_complete_handler,
 2588          scic_sds_request_default_destruct_handler
 2589       },
 2590       scic_sds_request_default_tc_completion_handler,
 2591       scic_sds_request_default_event_handler,
 2592       scic_sds_request_default_frame_handler
 2593    },
 2594    // SCI_BASE_REQUEST_STATE_CONSTRUCTED
 2595    {
 2596       {
 2597          scic_sds_request_constructed_state_start_handler,
 2598          scic_sds_request_constructed_state_abort_handler,
 2599          scic_sds_request_default_complete_handler,
 2600          scic_sds_request_default_destruct_handler
 2601       },
 2602       scic_sds_request_default_tc_completion_handler,
 2603       scic_sds_request_default_event_handler,
 2604       scic_sds_request_default_frame_handler
 2605    },
 2606    // SCI_BASE_REQUEST_STATE_STARTED
 2607    {
 2608       {
 2609          scic_sds_request_default_start_handler,
 2610          scic_sds_request_started_state_abort_handler,
 2611          scic_sds_request_default_complete_handler,
 2612          scic_sds_request_default_destruct_handler
 2613       },
 2614       scic_sds_request_started_state_tc_completion_handler,
 2615       scic_sds_request_default_event_handler,
 2616       scic_sds_request_started_state_frame_handler
 2617    },
 2618    // SCI_BASE_REQUEST_STATE_COMPLETED
 2619    {
 2620       {
 2621          scic_sds_request_default_start_handler,
 2622          scic_sds_request_default_abort_handler,
 2623          scic_sds_request_completed_state_complete_handler,
 2624          scic_sds_request_default_destruct_handler
 2625       },
 2626       scic_sds_request_default_tc_completion_handler,
 2627       scic_sds_request_default_event_handler,
 2628       scic_sds_request_default_frame_handler
 2629    },
 2630    // SCI_BASE_REQUEST_STATE_ABORTING
 2631    {
 2632       {
 2633          scic_sds_request_default_start_handler,
 2634          scic_sds_request_aborting_state_abort_handler,
 2635          scic_sds_request_default_complete_handler,
 2636          scic_sds_request_default_destruct_handler
 2637       },
 2638       scic_sds_request_aborting_state_tc_completion_handler,
 2639       scic_sds_request_default_event_handler,
 2640       scic_sds_request_aborting_state_frame_handler,
 2641    },
 2642    // SCI_BASE_REQUEST_STATE_FINAL
 2643    {
 2644       {
 2645          scic_sds_request_default_start_handler,
 2646          scic_sds_request_default_abort_handler,
 2647          scic_sds_request_default_complete_handler,
 2648          scic_sds_request_default_destruct_handler
 2649       },
 2650       scic_sds_request_default_tc_completion_handler,
 2651       scic_sds_request_default_event_handler,
 2652       scic_sds_request_default_frame_handler
 2653    }
 2654 };
 2655 
 2656 /**
 2657  * This method implements the actions taken when entering the
 2658  * SCI_BASE_REQUEST_STATE_INITIAL state. This state is entered when the
 2659  * initial base request is constructed. Entry into the initial state sets all
 2660  * handlers for the io request object to their default handlers.
 2661  *
 2662  * @param[in] object This parameter specifies the base object for which the
 2663  *       state transition is occurring.
 2664  *
 2665  * @return none
 2666  */
 2667 static
 2668 void scic_sds_request_initial_state_enter(
 2669    SCI_BASE_OBJECT_T *object
 2670 )
 2671 {
 2672    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
 2673 
 2674    SET_STATE_HANDLER(
 2675       this_request,
 2676       scic_sds_request_state_handler_table,
 2677       SCI_BASE_REQUEST_STATE_INITIAL
 2678    );
 2679 }
 2680 
 2681 /**
 2682  * This method implements the actions taken when entering the
 2683  * SCI_BASE_REQUEST_STATE_CONSTRUCTED state.
 2684  * The method sets the state handlers for the constructed state.
 2685  *
 2686  * @param[in] object The io request object that is to enter the constructed
 2687  *       state.
 2688  *
 2689  * @return none
 2690  */
 2691 static
 2692 void scic_sds_request_constructed_state_enter(
 2693    SCI_BASE_OBJECT_T *object
 2694 )
 2695 {
 2696    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
 2697 
 2698    SET_STATE_HANDLER(
 2699       this_request,
 2700       scic_sds_request_state_handler_table,
 2701       SCI_BASE_REQUEST_STATE_CONSTRUCTED
 2702    );
 2703 }
 2704 
 2705 /**
 2706  * This method implements the actions taken when entering the
 2707  * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a
 2708  * SCSI Task request we must enter the started substate machine.
 2709  *
 2710  * @param[in] object This parameter specifies the base object for which the
 2711  *       state transition is occurring.  This is cast into a
 2712  *       SCIC_SDS_IO_REQUEST object.
 2713  *
 2714  * @return none
 2715  */
 2716 static
 2717 void scic_sds_request_started_state_enter(
 2718    SCI_BASE_OBJECT_T *object
 2719 )
 2720 {
 2721    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
 2722 
 2723    SET_STATE_HANDLER(
 2724       this_request,
 2725       scic_sds_request_state_handler_table,
 2726       SCI_BASE_REQUEST_STATE_STARTED
 2727    );
 2728 
 2729    // Most of the request state machines have a started substate machine so
 2730    // start its execution on the entry to the started state.
 2731    if (this_request->has_started_substate_machine == TRUE)
 2732       sci_base_state_machine_start(&this_request->started_substate_machine);
 2733 }
 2734 
 2735 /**
 2736  * This method implements the actions taken when exiting the
 2737  * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be
 2738  * to stop the started substate machine.
 2739  *
 2740  * @param[in] object This parameter specifies the base object for which the
 2741  *       state transition is occurring.  This object is cast into a
 2742  *       SCIC_SDS_IO_REQUEST object.
 2743  *
 2744  * @return none
 2745  */
 2746 static
 2747 void scic_sds_request_started_state_exit(
 2748    SCI_BASE_OBJECT_T *object
 2749 )
 2750 {
 2751    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
 2752 
 2753    if (this_request->has_started_substate_machine == TRUE)
 2754       sci_base_state_machine_stop(&this_request->started_substate_machine);
 2755 }
 2756 
 2757 /**
 2758  * This method implements the actions taken when entering the
 2759  * SCI_BASE_REQUEST_STATE_COMPLETED state.  This state is entered when the
 2760  * SCIC_SDS_IO_REQUEST has completed.  The method will decode the request
 2761  * completion status and convert it to an SCI_STATUS to return in the
 2762  * completion callback function.
 2763  *
 2764  * @param[in] object This parameter specifies the base object for which the
 2765  *       state transition is occurring.  This object is cast into a
 2766  *       SCIC_SDS_IO_REQUEST object.
 2767  *
 2768  * @return none
 2769  */
 2770 static
 2771 void scic_sds_request_completed_state_enter(
 2772    SCI_BASE_OBJECT_T *object
 2773 )
 2774 {
 2775    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
 2776 
 2777    SET_STATE_HANDLER(
 2778       this_request,
 2779       scic_sds_request_state_handler_table,
 2780       SCI_BASE_REQUEST_STATE_COMPLETED
 2781    );
 2782 
 2783    // Tell the SCI_USER that the IO request is complete
 2784    if (this_request->is_task_management_request == FALSE)
 2785    {
 2786       scic_cb_io_request_complete(
 2787          scic_sds_request_get_controller(this_request),
 2788          scic_sds_request_get_device(this_request),
 2789          this_request,
 2790          this_request->sci_status
 2791       );
 2792    }
 2793    else
 2794    {
 2795       scic_cb_task_request_complete(
 2796          scic_sds_request_get_controller(this_request),
 2797          scic_sds_request_get_device(this_request),
 2798          this_request,
 2799          this_request->sci_status
 2800       );
 2801    }
 2802 }
 2803 
 2804 /**
 2805  * This method implements the actions taken when entering the
 2806  * SCI_BASE_REQUEST_STATE_ABORTING state.
 2807  *
 2808  * @param[in] object This parameter specifies the base object for which the
 2809  *       state transition is occurring.  This object is cast into a
 2810  *       SCIC_SDS_IO_REQUEST object.
 2811  *
 2812  * @return none
 2813  */
 2814 static
 2815 void scic_sds_request_aborting_state_enter(
 2816    SCI_BASE_OBJECT_T *object
 2817 )
 2818 {
 2819    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
 2820 
 2821    // Setting the abort bit in the Task Context is required by the silicon.
 2822    this_request->task_context_buffer->abort = 1;
 2823 
 2824    SET_STATE_HANDLER(
 2825       this_request,
 2826       scic_sds_request_state_handler_table,
 2827       SCI_BASE_REQUEST_STATE_ABORTING
 2828    );
 2829 }
 2830 
 2831 /**
 2832  * This method implements the actions taken when entering the
 2833  * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the
 2834  * state handlers in place.
 2835  *
 2836  * @param[in] object This parameter specifies the base object for which the
 2837  *       state transition is occurring.  This is cast into a
 2838  *       SCIC_SDS_IO_REQUEST object.
 2839  *
 2840  * @return none
 2841  */
 2842 static
 2843 void scic_sds_request_final_state_enter(
 2844    SCI_BASE_OBJECT_T *object
 2845 )
 2846 {
 2847    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
 2848 
 2849    SET_STATE_HANDLER(
 2850       this_request,
 2851       scic_sds_request_state_handler_table,
 2852       SCI_BASE_REQUEST_STATE_FINAL
 2853    );
 2854 }
 2855 
 2856 // ---------------------------------------------------------------------------
 2857 
 2858 SCI_BASE_STATE_T
 2859    scic_sds_request_state_table[SCI_BASE_REQUEST_MAX_STATES] =
 2860 {
 2861    {
 2862       SCI_BASE_REQUEST_STATE_INITIAL,
 2863       scic_sds_request_initial_state_enter,
 2864       NULL
 2865    },
 2866    {
 2867       SCI_BASE_REQUEST_STATE_CONSTRUCTED,
 2868       scic_sds_request_constructed_state_enter,
 2869       NULL
 2870    },
 2871    {
 2872       SCI_BASE_REQUEST_STATE_STARTED,
 2873       scic_sds_request_started_state_enter,
 2874       scic_sds_request_started_state_exit
 2875    },
 2876    {
 2877       SCI_BASE_REQUEST_STATE_COMPLETED,
 2878       scic_sds_request_completed_state_enter,
 2879       NULL
 2880    },
 2881    {
 2882       SCI_BASE_REQUEST_STATE_ABORTING,
 2883       scic_sds_request_aborting_state_enter,
 2884       NULL
 2885    },
 2886    {
 2887       SCI_BASE_REQUEST_STATE_FINAL,
 2888       scic_sds_request_final_state_enter,
 2889       NULL
 2890    }
 2891 };
 2892 

Cache object: 6177d62b37957c4de2887b05bd33093f


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