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_remote_device.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 of remote device, it's
   62  *        methods and state machine.
   63  */
   64 
   65 #include <dev/isci/scil/intel_sas.h>
   66 #include <dev/isci/scil/sci_util.h>
   67 #include <dev/isci/scil/scic_port.h>
   68 #include <dev/isci/scil/scic_phy.h>
   69 #include <dev/isci/scil/scic_remote_device.h>
   70 #include <dev/isci/scil/scic_sds_port.h>
   71 #include <dev/isci/scil/scic_sds_phy.h>
   72 #include <dev/isci/scil/scic_sds_remote_device.h>
   73 #include <dev/isci/scil/scic_sds_request.h>
   74 #include <dev/isci/scil/scic_sds_controller.h>
   75 #include <dev/isci/scil/scic_sds_logger.h>
   76 #include <dev/isci/scil/scic_user_callback.h>
   77 #include <dev/isci/scil/scic_controller.h>
   78 #include <dev/isci/scil/scic_sds_logger.h>
   79 #include <dev/isci/scil/scic_sds_remote_node_context.h>
   80 #include <dev/isci/scil/scu_event_codes.h>
   81 
   82 #define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT  (1000)
   83 
   84 //*****************************************************************************
   85 //*  CORE REMOTE DEVICE PUBLIC METHODS
   86 //*****************************************************************************
   87 
   88 U32 scic_remote_device_get_object_size(void)
   89 {
   90    return   sizeof(SCIC_SDS_REMOTE_DEVICE_T)
   91           + sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T);
   92 }
   93 
   94 // ---------------------------------------------------------------------------
   95 
   96 void scic_remote_device_construct(
   97    SCI_PORT_HANDLE_T            port,
   98    void                       * remote_device_memory,
   99    SCI_REMOTE_DEVICE_HANDLE_T * new_remote_device_handle
  100 )
  101 {
  102    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T*)
  103                                            remote_device_memory;
  104    SCIC_SDS_PORT_T          *the_port    = (SCIC_SDS_PORT_T*) port;
  105 
  106    SCIC_LOG_TRACE((
  107       sci_base_object_get_logger(the_port),
  108       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  109       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  110       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  111       "scic_remote_device_construct(0x%x, 0x%x, 0x%x) enter\n",
  112       port, remote_device_memory, new_remote_device_handle
  113    ));
  114 
  115    memset(remote_device_memory, 0, sizeof(SCIC_SDS_REMOTE_DEVICE_T));
  116 
  117    *new_remote_device_handle          = this_device;
  118    this_device->owning_port           = the_port;
  119    this_device->started_request_count = 0;
  120    this_device->rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)
  121       ((char *)this_device + sizeof(SCIC_SDS_REMOTE_DEVICE_T));
  122 
  123    sci_base_remote_device_construct(
  124       &this_device->parent,
  125       sci_base_object_get_logger(the_port),
  126       scic_sds_remote_device_state_table
  127    );
  128 
  129    scic_sds_remote_node_context_construct(
  130       this_device,
  131       this_device->rnc,
  132       SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
  133    );
  134 
  135    sci_object_set_association(this_device->rnc, this_device);
  136 
  137    scic_sds_remote_device_initialize_state_logging(this_device);
  138 }
  139 
  140 // ---------------------------------------------------------------------------
  141 
  142 SCI_STATUS scic_remote_device_da_construct(
  143    SCI_REMOTE_DEVICE_HANDLE_T  remote_device
  144 )
  145 {
  146    SCI_STATUS                status;
  147    U16                       remote_node_index;
  148    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T*)
  149                                            remote_device;
  150    SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T  protocols;
  151    SCIC_PORT_PROPERTIES_T  properties;
  152 
  153    SCIC_LOG_TRACE((
  154       sci_base_object_get_logger(this_device->owning_port),
  155       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  156       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  157       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  158       "scic_remote_device_da_construct(0x%x) enter\n",
  159       remote_device
  160    ));
  161 
  162    // This information is request to determine how many remote node context
  163    // entries will be needed to store the remote node.
  164    scic_sds_port_get_attached_protocols(this_device->owning_port,&protocols);
  165    this_device->target_protocols.u.all = protocols.u.all;
  166    this_device->is_direct_attached = TRUE;
  167 #if !defined(DISABLE_ATAPI)
  168    this_device->is_atapi = scic_sds_remote_device_is_atapi(this_device);
  169 #endif
  170 
  171    scic_port_get_properties(this_device->owning_port, &properties);
  172    //Get accurate port width from port's phy mask for a DA device.
  173    SCI_GET_BITS_SET_COUNT(properties.phy_mask, this_device->device_port_width);
  174 
  175    status = scic_sds_controller_allocate_remote_node_context(
  176                this_device->owning_port->owning_controller,
  177                this_device,
  178                &remote_node_index
  179             );
  180 
  181    if (status == SCI_SUCCESS)
  182    {
  183       scic_sds_remote_node_context_set_remote_node_index(
  184          this_device->rnc, remote_node_index
  185       );
  186 
  187       scic_sds_port_get_attached_sas_address(
  188          this_device->owning_port, &this_device->device_address
  189       );
  190 
  191       if (this_device->target_protocols.u.bits.attached_ssp_target)
  192       {
  193          this_device->has_ready_substate_machine = FALSE;
  194       }
  195       else if (this_device->target_protocols.u.bits.attached_stp_target)
  196       {
  197          this_device->has_ready_substate_machine = TRUE;
  198 
  199          sci_base_state_machine_construct(
  200             &this_device->ready_substate_machine,
  201             &this_device->parent.parent,
  202             scic_sds_stp_remote_device_ready_substate_table,
  203             SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
  204          );
  205       }
  206       else if (this_device->target_protocols.u.bits.attached_smp_target)
  207       {
  208          this_device->has_ready_substate_machine = TRUE;
  209 
  210          //add the SMP ready substate machine construction here
  211          sci_base_state_machine_construct(
  212             &this_device->ready_substate_machine,
  213             &this_device->parent.parent,
  214             scic_sds_smp_remote_device_ready_substate_table,
  215             SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
  216          );
  217       }
  218 
  219       this_device->connection_rate = scic_sds_port_get_max_allowed_speed(
  220                                         this_device->owning_port
  221                                      );
  222 
  223       /// @todo Should I assign the port width by reading all of the phys on the port?
  224       this_device->device_port_width = 1;
  225    }
  226 
  227    return status;
  228 }
  229 
  230 
  231 // ---------------------------------------------------------------------------
  232 
  233 void scic_sds_remote_device_get_info_from_smp_discover_response(
  234    SCIC_SDS_REMOTE_DEVICE_T    * this_device,
  235    SMP_RESPONSE_DISCOVER_T     * discover_response
  236 )
  237 {
  238    // decode discover_response to set sas_address to this_device.
  239    this_device->device_address.high =
  240       discover_response->attached_sas_address.high;
  241 
  242    this_device->device_address.low =
  243       discover_response->attached_sas_address.low;
  244 
  245    this_device->target_protocols.u.all = discover_response->protocols.u.all;
  246 }
  247 
  248 
  249 // ---------------------------------------------------------------------------
  250 
  251 SCI_STATUS scic_remote_device_ea_construct(
  252    SCI_REMOTE_DEVICE_HANDLE_T    remote_device,
  253    SMP_RESPONSE_DISCOVER_T     * discover_response
  254 )
  255 {
  256    SCI_STATUS status;
  257 
  258    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  259    SCIC_SDS_CONTROLLER_T    *the_controller;
  260 
  261    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  262 
  263    SCIC_LOG_TRACE((
  264       sci_base_object_get_logger(this_device->owning_port),
  265       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  266       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  267       "scic_remote_device_ea_sas_construct0x%x, 0x%x) enter\n",
  268       remote_device, discover_response
  269    ));
  270 
  271    the_controller = scic_sds_port_get_controller(this_device->owning_port);
  272 
  273    scic_sds_remote_device_get_info_from_smp_discover_response(
  274       this_device, discover_response
  275    );
  276 
  277    status = scic_sds_controller_allocate_remote_node_context(
  278                the_controller,
  279                this_device,
  280                &this_device->rnc->remote_node_index
  281             );
  282 
  283    if (status == SCI_SUCCESS)
  284    {
  285       if (this_device->target_protocols.u.bits.attached_ssp_target)
  286       {
  287          this_device->has_ready_substate_machine = FALSE;
  288       }
  289       else if (this_device->target_protocols.u.bits.attached_smp_target)
  290       {
  291          this_device->has_ready_substate_machine = TRUE;
  292 
  293          //add the SMP ready substate machine construction here
  294          sci_base_state_machine_construct(
  295             &this_device->ready_substate_machine,
  296             &this_device->parent.parent,
  297             scic_sds_smp_remote_device_ready_substate_table,
  298             SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
  299          );
  300       }
  301       else if (this_device->target_protocols.u.bits.attached_stp_target)
  302       {
  303          this_device->has_ready_substate_machine = TRUE;
  304 
  305          sci_base_state_machine_construct(
  306             &this_device->ready_substate_machine,
  307             &this_device->parent.parent,
  308             scic_sds_stp_remote_device_ready_substate_table,
  309             SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
  310          );
  311       }
  312 
  313       // For SAS-2 the physical link rate is actually a logical link
  314       // rate that incorporates multiplexing.  The SCU doesn't
  315       // incorporate multiplexing and for the purposes of the
  316       // connection the logical link rate is that same as the
  317       // physical.  Furthermore, the SAS-2 and SAS-1.1 fields overlay
  318       // one another, so this code works for both situations.
  319       this_device->connection_rate = MIN(
  320          scic_sds_port_get_max_allowed_speed( this_device->owning_port),
  321          discover_response->u2.sas1_1.negotiated_physical_link_rate
  322          );
  323 
  324       /// @todo Should I assign the port width by reading all of the phys on the port?
  325       this_device->device_port_width = 1;
  326    }
  327 
  328    return status;
  329 }
  330 
  331 // ---------------------------------------------------------------------------
  332 
  333 SCI_STATUS scic_remote_device_destruct(
  334    SCI_REMOTE_DEVICE_HANDLE_T  remote_device
  335 )
  336 {
  337    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  338    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  339 
  340    SCIC_LOG_TRACE((
  341       sci_base_object_get_logger(this_device),
  342       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  343       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  344       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  345       "scic_remote_device_destruct(0x%x) enter\n",
  346       remote_device
  347    ));
  348 
  349    return this_device->state_handlers->parent.destruct_handler(&this_device->parent);
  350 }
  351 
  352 // ---------------------------------------------------------------------------
  353 
  354 #if !defined(DISABLE_WIDE_PORTED_TARGETS)
  355 
  356 SCI_STATUS scic_remote_device_set_port_width(
  357    SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
  358    U8                          new_port_width
  359 )
  360 {
  361    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  362 
  363    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  364 
  365    SCIC_LOG_TRACE((
  366       sci_base_object_get_logger(this_device),
  367       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  368       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  369       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  370       "scic_remote_device_set_port_width(0x%x, 0x%x) enter\n",
  371       remote_device, new_port_width
  372    ));
  373 
  374    if(new_port_width != 0)
  375    {
  376       this_device->device_port_width = new_port_width;
  377 
  378       return SCI_SUCCESS;
  379    }
  380    else
  381       return SCI_FAILURE;
  382 }
  383 
  384 // ---------------------------------------------------------------------------
  385 
  386 U8 scic_remote_device_get_port_width(
  387    SCI_REMOTE_DEVICE_HANDLE_T  remote_device
  388 )
  389 {
  390    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  391 
  392    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  393 
  394    SCIC_LOG_TRACE((
  395       sci_base_object_get_logger(this_device),
  396       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  397       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  398       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  399       "scic_remote_device_get_port_width(0x%x) enter\n",
  400       remote_device
  401    ));
  402 
  403    return (U8)this_device->device_port_width;
  404 }
  405 
  406 #endif // !defined(DISABLE_WIDE_PORTED_TARGETS)
  407 
  408 // ---------------------------------------------------------------------------
  409 
  410 SCI_STATUS scic_remote_device_start(
  411    SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
  412    U32                         timeout
  413 )
  414 {
  415    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  416    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  417 
  418    SCIC_LOG_TRACE((
  419       sci_base_object_get_logger(this_device),
  420       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  421       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  422       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  423       "scic_remote_device_start(0x%x, 0x%x) enter\n",
  424       remote_device, timeout
  425    ));
  426 
  427    return this_device->state_handlers->parent.start_handler(&this_device->parent);
  428 }
  429 
  430 // ---------------------------------------------------------------------------
  431 
  432 SCI_STATUS scic_remote_device_stop(
  433    SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
  434    U32                         timeout
  435 )
  436 {
  437    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  438    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  439 
  440    SCIC_LOG_TRACE((
  441       sci_base_object_get_logger(this_device),
  442       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  443       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  444       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  445       "scic_remote_device_stop(0x%x, 0x%x) enter\n",
  446       remote_device, timeout
  447    ));
  448 
  449    return this_device->state_handlers->parent.stop_handler(&this_device->parent);
  450 }
  451 
  452 /**
  453  * This method invokes the remote device reset handler.
  454  *
  455  * @param[in] this_device The remote device for which the reset is being
  456  *       requested.
  457  *
  458  * @return SCI_STATUS
  459  */
  460 SCI_STATUS scic_remote_device_reset(
  461    SCI_REMOTE_DEVICE_HANDLE_T  remote_device
  462 )
  463 {
  464    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  465    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  466 
  467    SCIC_LOG_TRACE((
  468       sci_base_object_get_logger(this_device),
  469       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  470       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  471       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  472       "scic_remote_device_reset(0x%x) enter\n",
  473       remote_device
  474    ));
  475 
  476    return this_device->state_handlers->parent.reset_handler(&this_device->parent);
  477 }
  478 
  479 /**
  480  * This method invokes the remote device reset handler.
  481  *
  482  * @param[in] this_device The remote device for which the reset is being
  483  *       requested.
  484  *
  485  * @return SCI_STATUS
  486  */
  487 SCI_STATUS scic_remote_device_reset_complete(
  488    SCI_REMOTE_DEVICE_HANDLE_T  remote_device
  489 )
  490 {
  491    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  492    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  493 
  494    SCIC_LOG_TRACE((
  495       sci_base_object_get_logger(this_device),
  496       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  497       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  498       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  499       "scic_remote_device_reset_complete(0x%x) enter\n",
  500       remote_device
  501    ));
  502 
  503    return this_device->state_handlers->parent.reset_complete_handler(&this_device->parent);
  504 }
  505 
  506 /**
  507  * This method invokes the remote device reset handler.
  508  *
  509  * @param[in] this_device The remote device for which the reset is being
  510  *       requested.
  511  *
  512  * @return SCI_STATUS
  513  */
  514 U32 scic_remote_device_get_suggested_reset_timeout(
  515    SCI_REMOTE_DEVICE_HANDLE_T  remote_device
  516 )
  517 {
  518    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  519    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  520 
  521    SCIC_LOG_TRACE((
  522       sci_base_object_get_logger(this_device),
  523       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  524       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  525       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  526       "scic_remote_device_get_suggested_reset_timeout(0x%x) enter\n",
  527       remote_device
  528    ));
  529 
  530    if (this_device->target_protocols.u.bits.attached_stp_target)
  531    {
  532       return SCIC_SDS_SIGNATURE_FIS_TIMEOUT;
  533    }
  534 
  535    return SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT;
  536 }
  537 
  538 // ---------------------------------------------------------------------------
  539 
  540 SCI_STATUS scic_remote_device_set_max_connection_rate(
  541    SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
  542    SCI_SAS_LINK_RATE           connection_rate
  543 )
  544 {
  545    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  546    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  547 
  548    SCIC_LOG_TRACE((
  549       sci_base_object_get_logger(this_device),
  550       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  551       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  552       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  553       "scic_remote_device_set_max_connection_rate(0x%x, 0x%x) enter\n",
  554       remote_device, connection_rate
  555    ));
  556 
  557    this_device->connection_rate = connection_rate;
  558 
  559    return SCI_SUCCESS;
  560 }
  561 
  562 // ---------------------------------------------------------------------------
  563 
  564 SCI_SAS_LINK_RATE scic_remote_device_get_connection_rate(
  565    SCI_REMOTE_DEVICE_HANDLE_T  remote_device
  566 )
  567 {
  568    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  569    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  570 
  571    SCIC_LOG_TRACE((
  572       sci_base_object_get_logger(this_device),
  573       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  574       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  575       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  576       "scic_remote_device_get_connection_rate(0x%x) enter\n",
  577       remote_device
  578    ));
  579 
  580    return this_device->connection_rate;
  581 }
  582 
  583 // ---------------------------------------------------------------------------
  584 
  585 void scic_remote_device_get_protocols(
  586    SCI_REMOTE_DEVICE_HANDLE_T          remote_device,
  587    SMP_DISCOVER_RESPONSE_PROTOCOLS_T * protocols
  588 )
  589 {
  590    SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)
  591                                             remote_device;
  592 
  593    SCIC_LOG_TRACE((
  594       sci_base_object_get_logger(this_device),
  595       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  596       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  597       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  598       "scic_remote_device_get_protocols(0x%x) enter\n",
  599       remote_device
  600    ));
  601 
  602    protocols->u.all = this_device->target_protocols.u.all;
  603 }
  604 
  605 // ---------------------------------------------------------------------------
  606 
  607 void scic_remote_device_get_sas_address(
  608    SCI_REMOTE_DEVICE_HANDLE_T   remote_device,
  609    SCI_SAS_ADDRESS_T          * sas_address
  610 )
  611 {
  612    SCIC_SDS_REMOTE_DEVICE_T *this_device;
  613    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
  614 
  615    SCIC_LOG_TRACE((
  616       sci_base_object_get_logger(this_device),
  617       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  618       SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
  619       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
  620       "scic_remote_device_get_sas_address(0x%x, 0x%x) enter\n",
  621       remote_device, sas_address
  622    ));
  623 
  624    sas_address->low = this_device->device_address.low;
  625    sas_address->high = this_device->device_address.high;
  626 }
  627 
  628 // ---------------------------------------------------------------------------
  629 #if !defined(DISABLE_ATAPI)
  630 BOOL scic_remote_device_is_atapi(
  631    SCI_REMOTE_DEVICE_HANDLE_T device_handle
  632 )
  633 {
  634   return ((SCIC_SDS_REMOTE_DEVICE_T *)device_handle)->is_atapi;
  635 }
  636 #endif
  637 
  638 
  639 //*****************************************************************************
  640 //*  SCU DRIVER STANDARD (SDS) REMOTE DEVICE IMPLEMENTATIONS
  641 //*****************************************************************************
  642 
  643 /**
  644  * Remote device timer requirements
  645  */
  646 #define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0)
  647 #define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES)
  648 
  649 /**
  650  * @brief This method returns the minimum number of timers required for all
  651  *        remote devices.
  652  *
  653  * @return U32
  654  */
  655 U32 scic_sds_remote_device_get_min_timer_count(void)
  656 {
  657    return SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT;
  658 }
  659 
  660 /**
  661  * @brief This method returns the maximum number of timers requried for all
  662  *        remote devices.
  663  *
  664  * @return U32
  665  */
  666 U32 scic_sds_remote_device_get_max_timer_count(void)
  667 {
  668    return SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT;
  669 }
  670 
  671 // ---------------------------------------------------------------------------
  672 
  673 #ifdef SCI_LOGGING
  674 /**
  675  * This method will enable and turn on state transition logging for the remote
  676  * device object.
  677  *
  678  * @param[in] this_device The device for which state transition logging is to
  679  *       be enabled.
  680  *
  681  * @return Nothing
  682  */
  683 void scic_sds_remote_device_initialize_state_logging(
  684    SCIC_SDS_REMOTE_DEVICE_T *this_device
  685 )
  686 {
  687    sci_base_state_machine_logger_initialize(
  688       &this_device->parent.state_machine_logger,
  689       &this_device->parent.state_machine,
  690       &this_device->parent.parent,
  691       scic_cb_logger_log_states,
  692       "SCIC_SDS_REMOTE_DEVICE_T", "base state machine",
  693       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  694       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  695       SCIC_LOG_OBJECT_STP_REMOTE_TARGET
  696    );
  697 
  698    if (this_device->has_ready_substate_machine)
  699    {
  700       sci_base_state_machine_logger_initialize(
  701          &this_device->ready_substate_machine_logger,
  702          &this_device->ready_substate_machine,
  703          &this_device->parent.parent,
  704          scic_cb_logger_log_states,
  705          "SCIC_SDS_REMOTE_DEVICE_T", "ready substate machine",
  706          SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  707          SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  708          SCIC_LOG_OBJECT_STP_REMOTE_TARGET
  709       );
  710    }
  711 }
  712 
  713 /**
  714  * This method will stop the state machine logging for this object and should
  715  * be called before the object is destroyed.
  716  *
  717  * @param[in] this_device The device on which to stop logging state
  718  *       transitions.
  719  *
  720  * @return Nothing
  721  */
  722 void scic_sds_remote_device_deinitialize_state_logging(
  723    SCIC_SDS_REMOTE_DEVICE_T *this_device
  724 )
  725 {
  726    sci_base_state_machine_logger_deinitialize(
  727       &this_device->parent.state_machine_logger,
  728       &this_device->parent.state_machine
  729    );
  730 
  731    if (this_device->has_ready_substate_machine)
  732    {
  733       sci_base_state_machine_logger_deinitialize(
  734          &this_device->ready_substate_machine_logger,
  735          &this_device->ready_substate_machine
  736       );
  737    }
  738 }
  739 #endif
  740 
  741 /**
  742  * This method invokes the remote device suspend state handler.
  743  *
  744  * @param[in] this_device The remote device for which the suspend is being
  745  *       requested.
  746  *
  747  * @return SCI_STATUS
  748  */
  749 SCI_STATUS scic_sds_remote_device_suspend(
  750    SCIC_SDS_REMOTE_DEVICE_T *this_device,
  751    U32                       suspend_type
  752 )
  753 {
  754    return this_device->state_handlers->suspend_handler(this_device, suspend_type);
  755 }
  756 
  757 /**
  758  * This method invokes the remote device resume state handler.
  759  *
  760  * @param[in] this_device The remote device for which the resume is being
  761  *       requested.
  762  *
  763  * @return SCI_STATUS
  764  */
  765 SCI_STATUS scic_sds_remote_device_resume(
  766    SCIC_SDS_REMOTE_DEVICE_T *this_device
  767 )
  768 {
  769    return this_device->state_handlers->resume_handler(this_device);
  770 }
  771 
  772 /**
  773  * This method invokes the frame handler for the remote device state machine
  774  *
  775  * @param[in] this_device The remote device for which the event handling is
  776  *       being requested.
  777  * @param[in] frame_index This is the frame index that is being processed.
  778  *
  779  * @return SCI_STATUS
  780  */
  781 SCI_STATUS scic_sds_remote_device_frame_handler(
  782    SCIC_SDS_REMOTE_DEVICE_T *this_device,
  783    U32                       frame_index
  784 )
  785 {
  786    return this_device->state_handlers->frame_handler(this_device, frame_index);
  787 }
  788 
  789 /**
  790  * This method invokes the remote device event handler.
  791  *
  792  * @param[in] this_device The remote device for which the event handling is
  793  *       being requested.
  794  * @param[in] event_code This is the event code that is to be processed.
  795  *
  796  * @return SCI_STATUS
  797  */
  798 SCI_STATUS scic_sds_remote_device_event_handler(
  799    SCIC_SDS_REMOTE_DEVICE_T *this_device,
  800    U32                       event_code
  801 )
  802 {
  803    return this_device->state_handlers->event_handler(this_device, event_code);
  804 }
  805 
  806 /**
  807  * This method invokes the remote device start io handler.
  808  *
  809  * @param[in] controller The controller that is starting the io request.
  810  * @param[in] this_device The remote device for which the start io handling is
  811  *       being requested.
  812  * @param[in] io_request The io request that is being started.
  813  *
  814  * @return SCI_STATUS
  815  */
  816 SCI_STATUS scic_sds_remote_device_start_io(
  817    SCIC_SDS_CONTROLLER_T    *controller,
  818    SCIC_SDS_REMOTE_DEVICE_T *this_device,
  819    SCIC_SDS_REQUEST_T       *io_request
  820 )
  821 {
  822    return this_device->state_handlers->parent.start_io_handler(
  823                                  &this_device->parent, &io_request->parent);
  824 }
  825 
  826 /**
  827  * This method invokes the remote device complete io handler.
  828  *
  829  * @param[in] controller The controller that is completing the io request.
  830  * @param[in] this_device The remote device for which the complete io handling
  831  *       is being requested.
  832  * @param[in] io_request The io request that is being completed.
  833  *
  834  * @return SCI_STATUS
  835  */
  836 SCI_STATUS scic_sds_remote_device_complete_io(
  837    SCIC_SDS_CONTROLLER_T    *controller,
  838    SCIC_SDS_REMOTE_DEVICE_T *this_device,
  839    SCIC_SDS_REQUEST_T       *io_request
  840 )
  841 {
  842    return this_device->state_handlers->parent.complete_io_handler(
  843                                  &this_device->parent, &io_request->parent);
  844 }
  845 
  846 /**
  847  * This method invokes the remote device start task handler.
  848  *
  849  * @param[in] controller The controller that is starting the task request.
  850  * @param[in] this_device The remote device for which the start task handling
  851  *       is being requested.
  852  * @param[in] io_request The task request that is being started.
  853  *
  854  * @return SCI_STATUS
  855  */
  856 SCI_STATUS scic_sds_remote_device_start_task(
  857    SCIC_SDS_CONTROLLER_T    *controller,
  858    SCIC_SDS_REMOTE_DEVICE_T *this_device,
  859    SCIC_SDS_REQUEST_T       *io_request
  860 )
  861 {
  862    return this_device->state_handlers->parent.start_task_handler(
  863                                   &this_device->parent, &io_request->parent);
  864 }
  865 
  866 /**
  867  * This method takes the request and bulids an appropriate SCU context for the
  868  * request and then requests the controller to post the request.
  869  *
  870  * @param[in] this_device
  871  * @param[in] request
  872  *
  873  * @return none
  874  */
  875 void scic_sds_remote_device_post_request(
  876    SCIC_SDS_REMOTE_DEVICE_T * this_device,
  877    U32                        request
  878 )
  879 {
  880    U32 context;
  881 
  882    context = scic_sds_remote_device_build_command_context(this_device, request);
  883 
  884    scic_sds_controller_post_request(
  885       scic_sds_remote_device_get_controller(this_device),
  886       context
  887    );
  888 }
  889 
  890 #if !defined(DISABLE_ATAPI)
  891 /**
  892  * This method check the signature fis of a stp device to decide whether
  893  * a device is atapi or not.
  894  *
  895  * @param[in] this_device The device to be checked.
  896  *
  897  * @return TRUE if a device is atapi device. False if a device is not atapi.
  898  */
  899 BOOL scic_sds_remote_device_is_atapi(
  900    SCIC_SDS_REMOTE_DEVICE_T * this_device
  901 )
  902 {
  903    if (!this_device->target_protocols.u.bits.attached_stp_target)
  904       return FALSE;
  905    else if (this_device->is_direct_attached)
  906    {
  907       SCIC_SDS_PHY_T * phy;
  908       SCIC_SATA_PHY_PROPERTIES_T properties;
  909       SATA_FIS_REG_D2H_T * signature_fis;
  910       phy = scic_sds_port_get_a_connected_phy(this_device->owning_port);
  911       scic_sata_phy_get_properties(phy, &properties);
  912 
  913       //decode the signature fis.
  914       signature_fis = &(properties.signature_fis);
  915 
  916       if (   (signature_fis->sector_count  == 0x01)
  917           && (signature_fis->lba_low       == 0x01)
  918           && (signature_fis->lba_mid       == 0x14)
  919           && (signature_fis->lba_high      == 0xEB)
  920           && ( (signature_fis->device & 0x5F) == 0x00)
  921          )
  922       {
  923          // An ATA device supporting the PACKET command set.
  924          return TRUE;
  925       }
  926       else
  927          return FALSE;
  928    }
  929    else
  930    {
  931       //Expander supported ATAPI device is not currently supported.
  932       return FALSE;
  933    }
  934 }
  935 
  936 #endif // !defined(DISABLE_ATAPI)
  937 
  938 //******************************************************************************
  939 //* REMOTE DEVICE STATE MACHINE
  940 //******************************************************************************
  941 
  942 /**
  943  * This method is called once the remote node context is ready to be
  944  * freed.  The remote device can now report that its stop operation is
  945  * complete.
  946  *
  947  * @param[in] user_parameter This is cast to a remote device object.
  948  *
  949  * @return none
  950  */
  951 static
  952 void scic_sds_cb_remote_device_rnc_destruct_complete(
  953    void * user_parameter
  954 )
  955 {
  956    SCIC_SDS_REMOTE_DEVICE_T * this_device;
  957    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_parameter;
  958 
  959    ASSERT(this_device->started_request_count == 0);
  960 
  961    sci_base_state_machine_change_state(
  962       scic_sds_remote_device_get_base_state_machine(this_device),
  963       SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
  964    );
  965 }
  966 
  967 /**
  968  * This method is called once the remote node context has transisitioned to a
  969  * ready state.  This is the indication that the remote device object can also
  970  * transition to ready.
  971  *
  972  * @param[in] user_parameter This is cast to a remote device object.
  973  *
  974  * @return none
  975  */
  976 static
  977 void scic_sds_remote_device_resume_complete_handler(
  978    void * user_parameter
  979 )
  980 {
  981    SCIC_SDS_REMOTE_DEVICE_T * this_device;
  982    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_parameter;
  983 
  984    if (
  985          sci_base_state_machine_get_state(&this_device->parent.state_machine)
  986       != SCI_BASE_REMOTE_DEVICE_STATE_READY
  987       )
  988    {
  989       sci_base_state_machine_change_state(
  990          &this_device->parent.state_machine,
  991          SCI_BASE_REMOTE_DEVICE_STATE_READY
  992       );
  993    }
  994 }
  995 
  996 /**
  997  * This method will perform the STP request start processing common
  998  * to IO requests and task requests of all types.
  999  *
 1000  * @param[in] device This parameter specifies the device for which the
 1001  *            request is being started.
 1002  * @param[in] request This parameter specifies the request being started.
 1003  * @param[in] status This parameter specifies the current start operation
 1004  *            status.
 1005  *
 1006  * @return none
 1007  */
 1008 void scic_sds_remote_device_start_request(
 1009    SCIC_SDS_REMOTE_DEVICE_T * this_device,
 1010    SCIC_SDS_REQUEST_T       * the_request,
 1011    SCI_STATUS                 status
 1012 )
 1013 {
 1014    // We still have a fault in starting the io complete it on the port
 1015    if (status == SCI_SUCCESS)
 1016       scic_sds_remote_device_increment_request_count(this_device);
 1017    else
 1018    {
 1019       this_device->owning_port->state_handlers->complete_io_handler(
 1020          this_device->owning_port, this_device, the_request
 1021       );
 1022    }
 1023 }
 1024 
 1025 
 1026 /**
 1027  * This method will continue to post tc for a STP request. This method usually
 1028  * serves as a callback when RNC gets resumed during a task management sequence.
 1029  *
 1030  * @param[in] request This parameter specifies the request being continued.
 1031  *
 1032  * @return none
 1033  */
 1034 void scic_sds_remote_device_continue_request(
 1035    SCIC_SDS_REMOTE_DEVICE_T * this_device
 1036 )
 1037 {
 1038    // we need to check if this request is still valid to continue.
 1039    if (this_device->working_request != NULL)
 1040    {
 1041       SCIC_SDS_REQUEST_T * this_request = this_device->working_request;
 1042 
 1043       this_request->owning_controller->state_handlers->parent.continue_io_handler(
 1044          &this_request->owning_controller->parent,
 1045          &this_request->target_device->parent,
 1046          &this_request->parent
 1047       );
 1048    }
 1049 }
 1050 
 1051 /**
 1052  * @brief This method will terminate all of the IO requests in the
 1053  *        controllers IO request table that were targeted for this
 1054  *        device.
 1055  *
 1056  * @param[in]  this_device This parameter specifies the remote device
 1057  *             for which to attempt to terminate all requests.
 1058  *
 1059  * @return This method returns an indication as to whether all requests
 1060  *         were successfully terminated.  If a single request fails to
 1061  *         be terminated, then this method will return the failure.
 1062  */
 1063 static
 1064 SCI_STATUS scic_sds_remote_device_terminate_requests(
 1065    SCIC_SDS_REMOTE_DEVICE_T *this_device
 1066 )
 1067 {
 1068     return scic_sds_terminate_reqests(
 1069             this_device->owning_port->owning_controller,
 1070             this_device,
 1071             NULL);
 1072 }
 1073 
 1074 //*****************************************************************************
 1075 //*  DEFAULT STATE HANDLERS
 1076 //*****************************************************************************
 1077 
 1078 /**
 1079  * This method is the default start handler.  It logs a warning and returns a
 1080  * failure.
 1081  *
 1082  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1083  *       SCIC_SDS_REMOTE_DEVICE.
 1084  *
 1085  * @return SCI_STATUS
 1086  * @retval SCI_FAILURE_INVALID_STATE
 1087  */
 1088 SCI_STATUS scic_sds_remote_device_default_start_handler(
 1089    SCI_BASE_REMOTE_DEVICE_T *device
 1090 )
 1091 {
 1092    SCIC_LOG_WARNING((
 1093       sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
 1094       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1095       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1096       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1097       "SCIC Remote Device requested to start while in wrong state %d\n",
 1098       sci_base_state_machine_get_state(
 1099          scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
 1100    ));
 1101 
 1102    return SCI_FAILURE_INVALID_STATE;
 1103 }
 1104 
 1105 /**
 1106  * This method is the default stop handler.  It logs a warning and returns a
 1107  * failure.
 1108  *
 1109  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1110  *       SCIC_SDS_REMOTE_DEVICE.
 1111  *
 1112  * @return SCI_STATUS
 1113  * @retval SCI_FAILURE_INVALID_STATE
 1114  */
 1115 SCI_STATUS scic_sds_remote_device_default_stop_handler(
 1116    SCI_BASE_REMOTE_DEVICE_T *device
 1117 )
 1118 {
 1119    SCIC_LOG_WARNING((
 1120       sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
 1121       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1122       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1123       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1124       "SCIC Remote Device requested to stop while in wrong state %d\n",
 1125       sci_base_state_machine_get_state(
 1126          scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
 1127    ));
 1128 
 1129    return SCI_FAILURE_INVALID_STATE;
 1130 }
 1131 
 1132 /**
 1133  * This method is the default fail handler.  It logs a warning and returns a
 1134  * failure.
 1135  *
 1136  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1137  *       SCIC_SDS_REMOTE_DEVICE.
 1138  *
 1139  * @return SCI_STATUS
 1140  * @retval SCI_FAILURE_INVALID_STATE
 1141  */
 1142 SCI_STATUS scic_sds_remote_device_default_fail_handler(
 1143    SCI_BASE_REMOTE_DEVICE_T *device
 1144 )
 1145 {
 1146    SCIC_LOG_WARNING((
 1147       sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
 1148       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1149       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1150       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1151       "SCIC Remote Device requested to fail while in wrong state %d\n",
 1152       sci_base_state_machine_get_state(
 1153          scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
 1154    ));
 1155 
 1156    return SCI_FAILURE_INVALID_STATE;
 1157 }
 1158 
 1159 /**
 1160  * This method is the default destruct handler.  It logs a warning and returns
 1161  * a failure.
 1162  *
 1163  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1164  *       SCIC_SDS_REMOTE_DEVICE.
 1165  *
 1166  * @return SCI_STATUS
 1167  * @retval SCI_FAILURE_INVALID_STATE
 1168  */
 1169 SCI_STATUS scic_sds_remote_device_default_destruct_handler(
 1170    SCI_BASE_REMOTE_DEVICE_T *device
 1171 )
 1172 {
 1173    SCIC_LOG_WARNING((
 1174       sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
 1175       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1176       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1177       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1178       "SCIC Remote Device requested to destroy while in wrong state %d\n",
 1179       sci_base_state_machine_get_state(
 1180          scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
 1181    ));
 1182 
 1183    return SCI_FAILURE_INVALID_STATE;
 1184 }
 1185 
 1186 /**
 1187  * This method is the default reset handler.  It logs a warning and returns a
 1188  * failure.
 1189  *
 1190  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1191  *       SCIC_SDS_REMOTE_DEVICE.
 1192  *
 1193  * @return SCI_STATUS
 1194  * @retval SCI_FAILURE_INVALID_STATE
 1195  */
 1196 SCI_STATUS scic_sds_remote_device_default_reset_handler(
 1197    SCI_BASE_REMOTE_DEVICE_T *device
 1198 )
 1199 {
 1200    SCIC_LOG_WARNING((
 1201       sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
 1202       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1203       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1204       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1205       "SCIC Remote Device requested to reset while in wrong state %d\n",
 1206       sci_base_state_machine_get_state(
 1207          scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
 1208    ));
 1209 
 1210    return SCI_FAILURE_INVALID_STATE;
 1211 }
 1212 
 1213 /**
 1214  * This method is the default reset complete handler.  It logs a warning and
 1215  * returns a failure.
 1216  *
 1217  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1218  *       SCIC_SDS_REMOTE_DEVICE.
 1219  *
 1220  * @return SCI_STATUS
 1221  * @retval SCI_FAILURE_INVALID_STATE
 1222  */
 1223 SCI_STATUS scic_sds_remote_device_default_reset_complete_handler(
 1224    SCI_BASE_REMOTE_DEVICE_T *device
 1225 )
 1226 {
 1227    SCIC_LOG_WARNING((
 1228       sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
 1229       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1230       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1231       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1232       "SCIC Remote Device requested to complete reset while in wrong state %d\n",
 1233       sci_base_state_machine_get_state(
 1234          scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
 1235    ));
 1236 
 1237    return SCI_FAILURE_INVALID_STATE;
 1238 }
 1239 
 1240 /**
 1241  * This method is the default suspend handler.  It logs a warning and returns
 1242  * a failure.
 1243  *
 1244  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1245  *       SCIC_SDS_REMOTE_DEVICE.
 1246  *
 1247  * @return SCI_STATUS
 1248  * @retval SCI_FAILURE_INVALID_STATE
 1249  */
 1250 SCI_STATUS scic_sds_remote_device_default_suspend_handler(
 1251    SCIC_SDS_REMOTE_DEVICE_T *this_device,
 1252    U32                       suspend_type
 1253 )
 1254 {
 1255    SCIC_LOG_WARNING((
 1256       sci_base_object_get_logger(this_device),
 1257       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1258       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1259       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1260       "SCIC Remote Device 0x%x requested to suspend %d while in wrong state %d\n",
 1261       this_device, suspend_type,
 1262       sci_base_state_machine_get_state(
 1263          scic_sds_remote_device_get_base_state_machine(this_device))
 1264    ));
 1265 
 1266    return SCI_FAILURE_INVALID_STATE;
 1267 }
 1268 
 1269 /**
 1270  * This method is the default resume handler.  It logs a warning and returns a
 1271  * failure.
 1272  *
 1273  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1274  *       SCIC_SDS_REMOTE_DEVICE.
 1275  *
 1276  * @return SCI_STATUS
 1277  * @retval SCI_FAILURE_INVALID_STATE
 1278  */
 1279 SCI_STATUS scic_sds_remote_device_default_resume_handler(
 1280    SCIC_SDS_REMOTE_DEVICE_T *this_device
 1281 )
 1282 {
 1283    SCIC_LOG_WARNING((
 1284       sci_base_object_get_logger(this_device),
 1285       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1286       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1287       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1288       "SCIC Remote Device requested to resume while in wrong state %d\n",
 1289       sci_base_state_machine_get_state(
 1290          scic_sds_remote_device_get_base_state_machine(this_device))
 1291    ));
 1292 
 1293    return SCI_FAILURE_INVALID_STATE;
 1294 }
 1295 
 1296 #if defined(SCI_LOGGING)
 1297 /**
 1298  *  This is a private method for emitting log messages related to events reported
 1299  *  to the remote device from the controller object.
 1300  *
 1301  *  @param [in] this_device This is the device object that is receiving the
 1302  *         event.
 1303  *  @param [in] event_code The event code to process.
 1304  *
 1305  *  @return None
 1306  */
 1307 static void scic_sds_emit_event_log_message(
 1308    SCIC_SDS_REMOTE_DEVICE_T * this_device,
 1309    U32                        event_code,
 1310    char *                     message_guts,
 1311    BOOL                       ready_state
 1312    )
 1313 {
 1314    SCIC_LOG_WARNING((
 1315       sci_base_object_get_logger(this_device),
 1316       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1317       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1318       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1319       "SCIC Remote device 0x%x (state %d) received %s %x while in the %sready %s%d\n",
 1320       this_device,
 1321       sci_base_state_machine_get_state(
 1322                scic_sds_remote_device_get_base_state_machine(this_device)),
 1323       message_guts, event_code,
 1324       (ready_state)
 1325         ? ""
 1326         : "not ",
 1327       (this_device->has_ready_substate_machine)
 1328         ? "substate "
 1329         : "",
 1330       (this_device->has_ready_substate_machine)
 1331         ? sci_base_state_machine_get_state(&this_device->ready_substate_machine)
 1332         : 0
 1333    ));
 1334 }
 1335 #else // defined(SCI_LOGGING)
 1336 #define scic_sds_emit_event_log_message(device, event_code, message, state)
 1337 #endif // defined(SCI_LOGGING)
 1338 
 1339 /**
 1340  * This method is the default event handler.  It will call the RNC state
 1341  * machine handler for any RNC events otherwise it will log a warning and
 1342  * returns a failure.
 1343  *
 1344  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1345  *       SCIC_SDS_REMOTE_DEVICE.
 1346  * @param[in] event_code The event code that the SCIC_SDS_CONTROLLER wants the
 1347  *       device object to process.
 1348  *
 1349  * @return SCI_STATUS
 1350  * @retval SCI_FAILURE_INVALID_STATE
 1351  */
 1352 static
 1353 SCI_STATUS  scic_sds_remote_device_core_event_handler(
 1354    SCIC_SDS_REMOTE_DEVICE_T *this_device,
 1355    U32                       event_code,
 1356    BOOL                      is_ready_state
 1357 )
 1358 {
 1359    SCI_STATUS status;
 1360 
 1361    switch (scu_get_event_type(event_code))
 1362    {
 1363    case SCU_EVENT_TYPE_RNC_OPS_MISC:
 1364    case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
 1365    case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
 1366       status = scic_sds_remote_node_context_event_handler(this_device->rnc, event_code);
 1367    break;
 1368    case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
 1369 
 1370        if( scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT )
 1371        {
 1372            status = SCI_SUCCESS;
 1373 
 1374            // Suspend the associated RNC
 1375            scic_sds_remote_node_context_suspend( this_device->rnc,
 1376                                                  SCI_SOFTWARE_SUSPENSION,
 1377                                                  NULL, NULL );
 1378 
 1379            scic_sds_emit_event_log_message(
 1380               this_device, event_code,
 1381                    (is_ready_state)
 1382             ? "I_T_Nexus_Timeout event"
 1383             : "I_T_Nexus_Timeout event in wrong state",
 1384                    is_ready_state );
 1385 
 1386            break;
 1387        }
 1388        // Else, fall through and treat as unhandled...
 1389 
 1390    default:
 1391       scic_sds_emit_event_log_message( this_device, event_code,
 1392                                        (is_ready_state)
 1393                                           ? "unexpected event"
 1394                                           : "unexpected event in wrong state",
 1395                                        is_ready_state );
 1396       status = SCI_FAILURE_INVALID_STATE;
 1397    break;
 1398    }
 1399 
 1400    return status;
 1401 }
 1402 /**
 1403  * This method is the default event handler.  It will call the RNC state
 1404  * machine handler for any RNC events otherwise it will log a warning and
 1405  * returns a failure.
 1406  *
 1407  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1408  *       SCIC_SDS_REMOTE_DEVICE.
 1409  * @param[in] event_code The event code that the SCIC_SDS_CONTROLLER wants the
 1410  *       device object to process.
 1411  *
 1412  * @return SCI_STATUS
 1413  * @retval SCI_FAILURE_INVALID_STATE
 1414  */
 1415 SCI_STATUS  scic_sds_remote_device_default_event_handler(
 1416    SCIC_SDS_REMOTE_DEVICE_T *this_device,
 1417    U32                       event_code
 1418 )
 1419 {
 1420    return scic_sds_remote_device_core_event_handler( this_device,
 1421                                                      event_code,
 1422                                                      FALSE );
 1423 }
 1424 
 1425 /**
 1426  * This method is the default unsolicited frame handler.  It logs a warning,
 1427  * releases the frame and returns a failure.
 1428  *
 1429  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1430  *       SCIC_SDS_REMOTE_DEVICE.
 1431  * @param[in] frame_index The frame index for which the SCIC_SDS_CONTROLLER
 1432  *       wants this device object to process.
 1433  *
 1434  * @return SCI_STATUS
 1435  * @retval SCI_FAILURE_INVALID_STATE
 1436  */
 1437 SCI_STATUS scic_sds_remote_device_default_frame_handler(
 1438    SCIC_SDS_REMOTE_DEVICE_T *this_device,
 1439    U32                       frame_index
 1440 )
 1441 {
 1442    SCIC_LOG_WARNING((
 1443       sci_base_object_get_logger(this_device),
 1444       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1445       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1446       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1447       "SCIC Remote Device requested to handle frame %x while in wrong state %d\n",
 1448       frame_index,
 1449       sci_base_state_machine_get_state(&this_device->parent.state_machine)
 1450    ));
 1451 
 1452    // Return the frame back to the controller
 1453    scic_sds_controller_release_frame(
 1454       scic_sds_remote_device_get_controller(this_device), frame_index
 1455    );
 1456 
 1457    return SCI_FAILURE_INVALID_STATE;
 1458 }
 1459 
 1460 /**
 1461  * This method is the default start io handler.  It logs a warning and returns
 1462  * a failure.
 1463  *
 1464  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1465  *       SCIC_SDS_REMOTE_DEVICE.
 1466  * @param[in] request The SCI_BASE_REQUEST which is then cast into a
 1467  *       SCIC_SDS_IO_REQUEST to start.
 1468  *
 1469  * @return SCI_STATUS
 1470  * @retval SCI_FAILURE_INVALID_STATE
 1471  */
 1472 SCI_STATUS scic_sds_remote_device_default_start_request_handler(
 1473    SCI_BASE_REMOTE_DEVICE_T *device,
 1474    SCI_BASE_REQUEST_T       *request
 1475 )
 1476 {
 1477    SCIC_LOG_WARNING((
 1478       sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
 1479       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1480       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1481       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1482       "SCIC Remote Device requested to start io request %x while in wrong state %d\n",
 1483       request,
 1484       sci_base_state_machine_get_state(
 1485          scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
 1486    ));
 1487 
 1488    return SCI_FAILURE_INVALID_STATE;
 1489 }
 1490 
 1491 /**
 1492  * This method is the default complete io handler.  It logs a warning and
 1493  * returns a failure.
 1494  *
 1495  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1496  *       SCIC_SDS_REMOTE_DEVICE.
 1497  * @param[in] request The SCI_BASE_REQUEST which is then cast into a
 1498  *       SCIC_SDS_IO_REQUEST to complete.
 1499  *
 1500  *
 1501  * @return SCI_STATUS
 1502  * @retval SCI_FAILURE_INVALID_STATE
 1503  */
 1504 SCI_STATUS scic_sds_remote_device_default_complete_request_handler(
 1505    SCI_BASE_REMOTE_DEVICE_T *device,
 1506    SCI_BASE_REQUEST_T       *request
 1507 )
 1508 {
 1509    SCIC_LOG_WARNING((
 1510       sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
 1511       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1512       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1513       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1514       "SCIC Remote Device requested to complete io_request %x while in wrong state %d\n",
 1515       request,
 1516       sci_base_state_machine_get_state(
 1517          scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
 1518    ));
 1519 
 1520    return SCI_FAILURE_INVALID_STATE;
 1521 }
 1522 
 1523 /**
 1524  * This method is the default continue io handler.  It logs a warning and
 1525  * returns a failure.
 1526  *
 1527  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1528  *       SCIC_SDS_REMOTE_DEVICE.
 1529  * @param[in] request The SCI_BASE_REQUEST which is then cast into a
 1530  *       SCIC_SDS_IO_REQUEST to continue.
 1531  *
 1532  * @return SCI_STATUS
 1533  * @retval SCI_FAILURE_INVALID_STATE
 1534  */
 1535 SCI_STATUS scic_sds_remote_device_default_continue_request_handler(
 1536    SCI_BASE_REMOTE_DEVICE_T *device,
 1537    SCI_BASE_REQUEST_T       *request
 1538 )
 1539 {
 1540    SCIC_LOG_WARNING((
 1541       sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
 1542       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1543       SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1544       SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1545       "SCIC Remote Device requested to continue io request %x while in wrong state %d\n",
 1546       request,
 1547       sci_base_state_machine_get_state(
 1548          scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
 1549    ));
 1550 
 1551    return SCI_FAILURE_INVALID_STATE;
 1552 }
 1553 
 1554 /**
 1555  * This method is the general suspend handler.
 1556  *
 1557  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1558  *       SCIC_SDS_REMOTE_DEVICE.
 1559  *
 1560  * @return SCI_STATUS
 1561  * @retval SCI_FAILURE_INVALID_STATE
 1562  */
 1563 static
 1564 SCI_STATUS scic_sds_remote_device_general_suspend_handler(
 1565    SCIC_SDS_REMOTE_DEVICE_T *this_device,
 1566    U32                       suspend_type
 1567 )
 1568 {
 1569     return scic_sds_remote_node_context_suspend(this_device->rnc, suspend_type, NULL, NULL);
 1570 }
 1571 
 1572 /**
 1573  * This method is the general suspend handler.  It logs a warning and returns
 1574  * a failure.
 1575  *
 1576  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1577  *       SCIC_SDS_REMOTE_DEVICE.
 1578  *
 1579  * @return SCI_STATUS
 1580  * @retval SCI_FAILURE_INVALID_STATE
 1581  */
 1582 static
 1583 SCI_STATUS scic_sds_remote_device_general_resume_handler(
 1584    SCIC_SDS_REMOTE_DEVICE_T *this_device
 1585 )
 1586 {
 1587     return scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL);
 1588 }
 1589 
 1590 //*****************************************************************************
 1591 //*  NORMAL STATE HANDLERS
 1592 //*****************************************************************************
 1593 
 1594 /**
 1595  * This method is a general ssp frame handler.  In most cases the device
 1596  * object needs to route the unsolicited frame processing to the io request
 1597  * object.  This method decodes the tag for the io request object and routes
 1598  * the unsolicited frame to that object.
 1599  *
 1600  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
 1601  *       SCIC_SDS_REMOTE_DEVICE.
 1602  * @param[in] frame_index The frame index for which the SCIC_SDS_CONTROLLER
 1603  *       wants this device object to process.
 1604  *
 1605  * @return SCI_STATUS
 1606  * @retval SCI_FAILURE_INVALID_STATE
 1607  */
 1608 SCI_STATUS scic_sds_remote_device_general_frame_handler(
 1609    SCIC_SDS_REMOTE_DEVICE_T *this_device,
 1610    U32                       frame_index
 1611 )
 1612 {
 1613    SCI_STATUS result;
 1614    SCI_SSP_FRAME_HEADER_T *frame_header;
 1615    SCIC_SDS_REQUEST_T     *io_request;
 1616 
 1617    result = scic_sds_unsolicited_frame_control_get_header(
 1618       &(scic_sds_remote_device_get_controller(this_device)->uf_control),
 1619       frame_index,
 1620       (void **)&frame_header
 1621    );
 1622 
 1623    if (SCI_SUCCESS == result)
 1624    {
 1625       io_request = scic_sds_controller_get_io_request_from_tag(
 1626          scic_sds_remote_device_get_controller(this_device), frame_header->tag);
 1627 
 1628       if (  (io_request == SCI_INVALID_HANDLE)
 1629          || (io_request->target_device != this_device) )
 1630       {
 1631          // We could not map this tag to a valid IO request
 1632          // Just toss the frame and continue
 1633          scic_sds_controller_release_frame(
 1634             scic_sds_remote_device_get_controller(this_device), frame_index
 1635          );
 1636       }
 1637       else
 1638       {
 1639          // The IO request is now in charge of releasing the frame
 1640          result = io_request->state_handlers->frame_handler(
 1641                                                     io_request, frame_index);
 1642       }
 1643    }
 1644 
 1645    return result;
 1646 }
 1647 
 1648 /**
 1649  *  This is a common method for handling events reported to the remote device
 1650  *  from the controller object.
 1651  *
 1652  *  @param [in] this_device This is the device object that is receiving the
 1653  *         event.
 1654  *  @param [in] event_code The event code to process.
 1655  *
 1656  *  @return SCI_STATUS
 1657  */
 1658 SCI_STATUS scic_sds_remote_device_general_event_handler(
 1659    SCIC_SDS_REMOTE_DEVICE_T * this_device,
 1660    U32                        event_code
 1661 )
 1662 {
 1663    return scic_sds_remote_device_core_event_handler( this_device,
 1664                                                      event_code,
 1665                                                      TRUE );
 1666 }
 1667 
 1668 //*****************************************************************************
 1669 //*  STOPPED STATE HANDLERS
 1670 //*****************************************************************************
 1671 
 1672 /**
 1673  * This method takes the SCIC_SDS_REMOTE_DEVICE from a stopped state and
 1674  * attempts to start it.   The RNC buffer for the device is constructed and
 1675  * the device state machine is transitioned to the
 1676  * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING.
 1677  *
 1678  * @param[in] device
 1679  *
 1680  * @return SCI_STATUS
 1681  * @retval SCI_SUCCESS if there is an RNC buffer available to construct the
 1682  *         remote device.
 1683  * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer
 1684  *         available in which to construct the remote device.
 1685  */
 1686 static
 1687 SCI_STATUS scic_sds_remote_device_stopped_state_start_handler(
 1688    SCI_BASE_REMOTE_DEVICE_T *device
 1689 )
 1690 {
 1691    SCI_STATUS status;
 1692    SCIC_SDS_REMOTE_DEVICE_T  *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 1693 
 1694    status = scic_sds_remote_node_context_resume(
 1695                this_device->rnc,
 1696                scic_sds_remote_device_resume_complete_handler,
 1697                this_device
 1698             );
 1699 
 1700    if (status == SCI_SUCCESS)
 1701    {
 1702       sci_base_state_machine_change_state(
 1703          scic_sds_remote_device_get_base_state_machine(this_device),
 1704          SCI_BASE_REMOTE_DEVICE_STATE_STARTING
 1705       );
 1706    }
 1707 
 1708    return status;
 1709 }
 1710 
 1711 /**
 1712  * This method will stop a SCIC_SDS_REMOTE_DEVICE that is already in a stopped
 1713  * state.  This is not considered an error since the device is already
 1714  * stopped.
 1715  *
 1716  * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a
 1717  *       SCIC_SDS_REMOTE_DEVICE.
 1718  *
 1719  * @return SCI_STATUS
 1720  * @retval SCI_SUCCESS
 1721  */
 1722 static
 1723 SCI_STATUS scic_sds_remote_device_stopped_state_stop_handler(
 1724    SCI_BASE_REMOTE_DEVICE_T *this_device
 1725 )
 1726 {
 1727    return SCI_SUCCESS;
 1728 }
 1729 
 1730 /**
 1731  * This method will destruct a SCIC_SDS_REMOTE_DEVICE that is in a stopped
 1732  * state.  This is the only state from which a destruct request will succeed.
 1733  * The RNi for this SCIC_SDS_REMOTE_DEVICE is returned to the free pool and
 1734  * the device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL.
 1735  *
 1736  * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a
 1737  *       SCIC_SDS_REMOTE_DEVICE.
 1738  *
 1739  * @return SCI_STATUS
 1740  * @retval SCI_SUCCESS
 1741  */
 1742 static
 1743 SCI_STATUS scic_sds_remote_device_stopped_state_destruct_handler(
 1744    SCI_BASE_REMOTE_DEVICE_T *device
 1745 )
 1746 {
 1747    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 1748 
 1749    SCIC_SDS_CONTROLLER_T * the_controller =
 1750       scic_sds_remote_device_get_controller(this_device);
 1751 
 1752    the_controller->remote_device_sequence[this_device->rnc->remote_node_index]++;
 1753 
 1754    scic_sds_controller_free_remote_node_context(
 1755       the_controller,
 1756       this_device,
 1757       this_device->rnc->remote_node_index
 1758    );
 1759 
 1760    scic_sds_remote_node_context_set_remote_node_index(
 1761       this_device->rnc,
 1762       SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
 1763    );
 1764 
 1765    sci_base_state_machine_change_state(
 1766       scic_sds_remote_device_get_base_state_machine(this_device),
 1767       SCI_BASE_REMOTE_DEVICE_STATE_FINAL
 1768    );
 1769 
 1770    scic_sds_remote_device_deinitialize_state_logging(this_device);
 1771 
 1772    return SCI_SUCCESS;
 1773 }
 1774 
 1775 //*****************************************************************************
 1776 //*  STARTING STATE HANDLERS
 1777 //*****************************************************************************
 1778 
 1779 static
 1780 SCI_STATUS scic_sds_remote_device_starting_state_stop_handler(
 1781    SCI_BASE_REMOTE_DEVICE_T *device
 1782 )
 1783 {
 1784    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 1785 
 1786    /*
 1787     * This device has not yet started so there had better be no IO requests
 1788     */
 1789    ASSERT(this_device->started_request_count == 0);
 1790 
 1791    /*
 1792     * Destroy the remote node context
 1793     */
 1794    scic_sds_remote_node_context_destruct(
 1795       this_device->rnc,
 1796       scic_sds_cb_remote_device_rnc_destruct_complete,
 1797       this_device
 1798    );
 1799 
 1800    /*
 1801     * Transition to the stopping state and wait for the remote node to
 1802     * complete being posted and invalidated.
 1803     */
 1804    sci_base_state_machine_change_state(
 1805       scic_sds_remote_device_get_base_state_machine(this_device),
 1806       SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
 1807    );
 1808 
 1809    return SCI_SUCCESS;
 1810 }
 1811 
 1812 //*****************************************************************************
 1813 //*  INITIALIZING STATE HANDLERS
 1814 //*****************************************************************************
 1815 
 1816 /* There is nothing to do here for SSP devices */
 1817 
 1818 //*****************************************************************************
 1819 //*  READY STATE HANDLERS
 1820 //*****************************************************************************
 1821 
 1822 /**
 1823  * This method is the default stop handler for the SCIC_SDS_REMOTE_DEVICE
 1824  * ready substate machine. It will stop the current substate machine and
 1825  * transition the base state machine to SCI_BASE_REMOTE_DEVICE_STATE_STOPPING.
 1826  *
 1827  * @param[in] device The SCI_BASE_REMOTE_DEVICE object which is cast to a
 1828  *       SCIC_SDS_REMOTE_DEVICE object.
 1829  *
 1830  * @return SCI_STATUS
 1831  * @retval SCI_SUCCESS
 1832  */
 1833 SCI_STATUS scic_sds_remote_device_ready_state_stop_handler(
 1834    SCI_BASE_REMOTE_DEVICE_T *device
 1835 )
 1836 {
 1837    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 1838    SCI_STATUS                status      = SCI_SUCCESS;
 1839 
 1840    // Request the parent state machine to transition to the stopping state
 1841    sci_base_state_machine_change_state(
 1842       scic_sds_remote_device_get_base_state_machine(this_device),
 1843       SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
 1844    );
 1845 
 1846    if (this_device->started_request_count == 0)
 1847    {
 1848       scic_sds_remote_node_context_destruct(
 1849          this_device->rnc,
 1850          scic_sds_cb_remote_device_rnc_destruct_complete,
 1851          this_device
 1852       );
 1853    }
 1854    else
 1855       status = scic_sds_remote_device_terminate_requests(this_device);
 1856 
 1857    return status;
 1858 }
 1859 
 1860 /**
 1861  * This is the ready state device reset handler
 1862  *
 1863  * @param[in] device The SCI_BASE_REMOTE_DEVICE object which is cast to a
 1864  *       SCIC_SDS_REMOTE_DEVICE object.
 1865  *
 1866  * @return SCI_STATUS
 1867  */
 1868 SCI_STATUS scic_sds_remote_device_ready_state_reset_handler(
 1869    SCI_BASE_REMOTE_DEVICE_T *device
 1870 )
 1871 {
 1872    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 1873 
 1874    // Request the parent state machine to transition to the stopping state
 1875    sci_base_state_machine_change_state(
 1876       scic_sds_remote_device_get_base_state_machine(this_device),
 1877       SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
 1878    );
 1879 
 1880    return SCI_SUCCESS;
 1881 }
 1882 
 1883 /**
 1884  * This method will attempt to start a task request for this device object.
 1885  * The remote device object will issue the start request for the task and if
 1886  * successful it will start the request for the port object then increment its
 1887  * own requet count.
 1888  *
 1889  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a
 1890  *       SCIC_SDS_REMOTE_DEVICE for which the request is to be started.
 1891  * @param[in] request The SCI_BASE_REQUEST which is cast to a
 1892  *       SCIC_SDS_IO_REQUEST that is to be started.
 1893  *
 1894  * @return SCI_STATUS
 1895  * @retval SCI_SUCCESS if the task request is started for this device object.
 1896  * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request object could
 1897  *         not get the resources to start.
 1898  */
 1899 static
 1900 SCI_STATUS scic_sds_remote_device_ready_state_start_task_handler(
 1901    SCI_BASE_REMOTE_DEVICE_T *device,
 1902    SCI_BASE_REQUEST_T       *request
 1903 )
 1904 {
 1905    SCI_STATUS result;
 1906    SCIC_SDS_REMOTE_DEVICE_T *this_device  = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 1907    SCIC_SDS_REQUEST_T       *task_request = (SCIC_SDS_REQUEST_T       *)request;
 1908 
 1909    // See if the port is in a state where we can start the IO request
 1910    result = scic_sds_port_start_io(
 1911       scic_sds_remote_device_get_port(this_device), this_device, task_request);
 1912 
 1913    if (result == SCI_SUCCESS)
 1914    {
 1915       result = scic_sds_remote_node_context_start_task(
 1916                   this_device->rnc, task_request
 1917                );
 1918 
 1919       if (result == SCI_SUCCESS)
 1920       {
 1921          result = scic_sds_request_start(task_request);
 1922       }
 1923 
 1924       scic_sds_remote_device_start_request(this_device, task_request, result);
 1925    }
 1926 
 1927    return result;
 1928 }
 1929 
 1930 /**
 1931  * This method will attempt to start an io request for this device object. The
 1932  * remote device object will issue the start request for the io and if
 1933  * successful it will start the request for the port object then increment its
 1934  * own requet count.
 1935  *
 1936  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a
 1937  *       SCIC_SDS_REMOTE_DEVICE for which the request is to be started.
 1938  * @param[in] request The SCI_BASE_REQUEST which is cast to a
 1939  *       SCIC_SDS_IO_REQUEST that is to be started.
 1940  *
 1941  * @return SCI_STATUS
 1942  * @retval SCI_SUCCESS if the io request is started for this device object.
 1943  * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request object could
 1944  *         not get the resources to start.
 1945  */
 1946 static
 1947 SCI_STATUS scic_sds_remote_device_ready_state_start_io_handler(
 1948    SCI_BASE_REMOTE_DEVICE_T *device,
 1949    SCI_BASE_REQUEST_T       *request
 1950 )
 1951 {
 1952    SCI_STATUS result;
 1953    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 1954    SCIC_SDS_REQUEST_T       *io_request  = (SCIC_SDS_REQUEST_T       *)request;
 1955 
 1956    // See if the port is in a state where we can start the IO request
 1957    result = scic_sds_port_start_io(
 1958       scic_sds_remote_device_get_port(this_device), this_device, io_request);
 1959 
 1960    if (result == SCI_SUCCESS)
 1961    {
 1962       result = scic_sds_remote_node_context_start_io(
 1963                   this_device->rnc, io_request
 1964                );
 1965 
 1966       if (result == SCI_SUCCESS)
 1967       {
 1968          result = scic_sds_request_start(io_request);
 1969       }
 1970 
 1971       scic_sds_remote_device_start_request(this_device, io_request, result);
 1972    }
 1973 
 1974    return result;
 1975 }
 1976 
 1977 /**
 1978  * This method will complete the request for the remote device object.  The
 1979  * method will call the completion handler for the request object and if
 1980  * successful it will complete the request on the port object then decrement
 1981  * its own started_request_count.
 1982  *
 1983  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a
 1984  *       SCIC_SDS_REMOTE_DEVICE for which the request is to be completed.
 1985  * @param[in] request The SCI_BASE_REQUEST which is cast to a
 1986  *       SCIC_SDS_IO_REQUEST that is to be completed.
 1987  *
 1988  * @return SCI_STATUS
 1989  */
 1990 static
 1991 SCI_STATUS scic_sds_remote_device_ready_state_complete_request_handler(
 1992    SCI_BASE_REMOTE_DEVICE_T *device,
 1993    SCI_BASE_REQUEST_T       *request
 1994 )
 1995 {
 1996    SCI_STATUS result;
 1997    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 1998    SCIC_SDS_REQUEST_T       *the_request = (SCIC_SDS_REQUEST_T       *)request;
 1999 
 2000    result = scic_sds_request_complete(the_request);
 2001 
 2002    if (result == SCI_SUCCESS)
 2003    {
 2004       // See if the port is in a state where we can start the IO request
 2005       result = scic_sds_port_complete_io(
 2006          scic_sds_remote_device_get_port(this_device), this_device, the_request);
 2007 
 2008       if (result == SCI_SUCCESS)
 2009       {
 2010          scic_sds_remote_device_decrement_request_count(this_device);
 2011       }
 2012    }
 2013 
 2014    return result;
 2015 }
 2016 
 2017 //*****************************************************************************
 2018 //*  STOPPING STATE HANDLERS
 2019 //*****************************************************************************
 2020 
 2021 /**
 2022  * This method will stop a SCIC_SDS_REMOTE_DEVICE that is already in the
 2023  * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an
 2024  * error since we allow a stop request on a device that is alreay stopping or
 2025  * stopped.
 2026  *
 2027  * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a
 2028  *       SCIC_SDS_REMOTE_DEVICE.
 2029  *
 2030  * @return SCI_STATUS
 2031  * @retval SCI_SUCCESS
 2032  */
 2033 static
 2034 SCI_STATUS scic_sds_remote_device_stopping_state_stop_handler(
 2035    SCI_BASE_REMOTE_DEVICE_T *device
 2036 )
 2037 {
 2038    // All requests should have been terminated, but if there is an
 2039    // attempt to stop a device already in the stopping state, then
 2040    // try again to terminate.
 2041    return scic_sds_remote_device_terminate_requests(
 2042              (SCIC_SDS_REMOTE_DEVICE_T*)device);
 2043 }
 2044 
 2045 
 2046 /**
 2047  * This method completes requests for this SCIC_SDS_REMOTE_DEVICE while it is
 2048  * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the
 2049  * complete method for the request object and if that is successful the port
 2050  * object is called to complete the task request. Then the device object
 2051  * itself completes the task request. If SCIC_SDS_REMOTE_DEVICE
 2052  * started_request_count goes to 0 and the invalidate RNC request has
 2053  * completed the device object can transition to the
 2054  * SCI_BASE_REMOTE_DEVICE_STATE_STOPPED.
 2055  *
 2056  * @param[in] device The device object for which the request is completing.
 2057  * @param[in] request The task request that is being completed.
 2058  *
 2059  * @return SCI_STATUS
 2060  */
 2061 static
 2062 SCI_STATUS scic_sds_remote_device_stopping_state_complete_request_handler(
 2063    SCI_BASE_REMOTE_DEVICE_T *device,
 2064    SCI_BASE_REQUEST_T       *request
 2065 )
 2066 {
 2067    SCI_STATUS                status = SCI_SUCCESS;
 2068    SCIC_SDS_REQUEST_T       *this_request = (SCIC_SDS_REQUEST_T   *)request;
 2069    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 2070 
 2071    status = scic_sds_request_complete(this_request);
 2072    if (status == SCI_SUCCESS)
 2073    {
 2074       status = scic_sds_port_complete_io(
 2075                   scic_sds_remote_device_get_port(this_device),
 2076                   this_device,
 2077                   this_request
 2078                );
 2079 
 2080       if (status == SCI_SUCCESS)
 2081       {
 2082          scic_sds_remote_device_decrement_request_count(this_device);
 2083 
 2084          if (scic_sds_remote_device_get_request_count(this_device) == 0)
 2085          {
 2086             scic_sds_remote_node_context_destruct(
 2087                this_device->rnc,
 2088                scic_sds_cb_remote_device_rnc_destruct_complete,
 2089                this_device
 2090             );
 2091          }
 2092       }
 2093    }
 2094 
 2095    return status;
 2096 }
 2097 
 2098 //*****************************************************************************
 2099 //*  RESETTING STATE HANDLERS
 2100 //*****************************************************************************
 2101 
 2102 /**
 2103  * This method will complete the reset operation when the device is in the
 2104  * resetting state.
 2105  *
 2106  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is to be cast into a
 2107  *       SCIC_SDS_REMOTE_DEVICE object.
 2108  *
 2109  * @return SCI_STATUS
 2110  */
 2111 static
 2112 SCI_STATUS scic_sds_remote_device_resetting_state_reset_complete_handler(
 2113    SCI_BASE_REMOTE_DEVICE_T * device
 2114 )
 2115 {
 2116    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 2117 
 2118    sci_base_state_machine_change_state(
 2119       &this_device->parent.state_machine,
 2120       SCI_BASE_REMOTE_DEVICE_STATE_READY
 2121    );
 2122 
 2123    return SCI_SUCCESS;
 2124 }
 2125 
 2126 /**
 2127  * This method will stop the remote device while in the resetting state.
 2128  *
 2129  * @param[in] device The SCI_BASE_REMOTE_DEVICE which is to be cast into a
 2130  *       SCIC_SDS_REMOTE_DEVICE object.
 2131  *
 2132  * @return SCI_STATUS
 2133  */
 2134 static
 2135 SCI_STATUS scic_sds_remote_device_resetting_state_stop_handler(
 2136    SCI_BASE_REMOTE_DEVICE_T * device
 2137 )
 2138 {
 2139    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 2140 
 2141    sci_base_state_machine_change_state(
 2142       &this_device->parent.state_machine,
 2143       SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
 2144    );
 2145 
 2146    return SCI_SUCCESS;
 2147 }
 2148 
 2149 /**
 2150  * This method completes requests for this SCIC_SDS_REMOTE_DEVICE while it is
 2151  * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the
 2152  * complete method for the request object and if that is successful the port
 2153  * object is called to complete the task request. Then the device object
 2154  * itself completes the task request.
 2155  *
 2156  * @param[in] device The device object for which the request is completing.
 2157  * @param[in] request The task request that is being completed.
 2158  *
 2159  * @return SCI_STATUS
 2160  */
 2161 static
 2162 SCI_STATUS scic_sds_remote_device_resetting_state_complete_request_handler(
 2163    SCI_BASE_REMOTE_DEVICE_T *device,
 2164    SCI_BASE_REQUEST_T       *request
 2165 )
 2166 {
 2167    SCI_STATUS status = SCI_SUCCESS;
 2168    SCIC_SDS_REQUEST_T       *this_request = (SCIC_SDS_REQUEST_T   *)request;
 2169    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
 2170 
 2171    status = scic_sds_request_complete(this_request);
 2172 
 2173    if (status == SCI_SUCCESS)
 2174    {
 2175       status = scic_sds_port_complete_io(
 2176          scic_sds_remote_device_get_port(this_device), this_device, this_request);
 2177 
 2178       if (status == SCI_SUCCESS)
 2179       {
 2180          scic_sds_remote_device_decrement_request_count(this_device);
 2181       }
 2182    }
 2183 
 2184    return status;
 2185 }
 2186 
 2187 //*****************************************************************************
 2188 //*  FAILED STATE HANDLERS
 2189 //*****************************************************************************
 2190 
 2191 SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
 2192    scic_sds_remote_device_state_handler_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
 2193 {
 2194    // SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
 2195    {
 2196       {
 2197          scic_sds_remote_device_default_start_handler,
 2198          scic_sds_remote_device_default_stop_handler,
 2199          scic_sds_remote_device_default_fail_handler,
 2200          scic_sds_remote_device_default_destruct_handler,
 2201          scic_sds_remote_device_default_reset_handler,
 2202          scic_sds_remote_device_default_reset_complete_handler,
 2203          scic_sds_remote_device_default_start_request_handler,
 2204          scic_sds_remote_device_default_complete_request_handler,
 2205          scic_sds_remote_device_default_continue_request_handler,
 2206          scic_sds_remote_device_default_start_request_handler,
 2207          scic_sds_remote_device_default_complete_request_handler
 2208       },
 2209       scic_sds_remote_device_default_suspend_handler,
 2210       scic_sds_remote_device_default_resume_handler,
 2211       scic_sds_remote_device_default_event_handler,
 2212       scic_sds_remote_device_default_frame_handler
 2213    },
 2214    // SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
 2215    {
 2216       {
 2217          scic_sds_remote_device_stopped_state_start_handler,
 2218          scic_sds_remote_device_stopped_state_stop_handler,
 2219          scic_sds_remote_device_default_fail_handler,
 2220          scic_sds_remote_device_stopped_state_destruct_handler,
 2221          scic_sds_remote_device_default_reset_handler,
 2222          scic_sds_remote_device_default_reset_complete_handler,
 2223          scic_sds_remote_device_default_start_request_handler,
 2224          scic_sds_remote_device_default_complete_request_handler,
 2225          scic_sds_remote_device_default_continue_request_handler,
 2226          scic_sds_remote_device_default_start_request_handler,
 2227          scic_sds_remote_device_default_complete_request_handler
 2228       },
 2229       scic_sds_remote_device_default_suspend_handler,
 2230       scic_sds_remote_device_default_resume_handler,
 2231       scic_sds_remote_device_default_event_handler,
 2232       scic_sds_remote_device_default_frame_handler
 2233    },
 2234    // SCI_BASE_REMOTE_DEVICE_STATE_STARTING
 2235    {
 2236       {
 2237          scic_sds_remote_device_default_start_handler,
 2238          scic_sds_remote_device_starting_state_stop_handler,
 2239          scic_sds_remote_device_default_fail_handler,
 2240          scic_sds_remote_device_default_destruct_handler,
 2241          scic_sds_remote_device_default_reset_handler,
 2242          scic_sds_remote_device_default_reset_complete_handler,
 2243          scic_sds_remote_device_default_start_request_handler,
 2244          scic_sds_remote_device_default_complete_request_handler,
 2245          scic_sds_remote_device_default_continue_request_handler,
 2246          scic_sds_remote_device_default_start_request_handler,
 2247          scic_sds_remote_device_default_complete_request_handler
 2248       },
 2249       scic_sds_remote_device_default_suspend_handler,
 2250       scic_sds_remote_device_default_resume_handler,
 2251       scic_sds_remote_device_general_event_handler,
 2252       scic_sds_remote_device_default_frame_handler
 2253    },
 2254    // SCI_BASE_REMOTE_DEVICE_STATE_READY
 2255    {
 2256       {
 2257          scic_sds_remote_device_default_start_handler,
 2258          scic_sds_remote_device_ready_state_stop_handler,
 2259          scic_sds_remote_device_default_fail_handler,
 2260          scic_sds_remote_device_default_destruct_handler,
 2261          scic_sds_remote_device_ready_state_reset_handler,
 2262          scic_sds_remote_device_default_reset_complete_handler,
 2263          scic_sds_remote_device_ready_state_start_io_handler,
 2264          scic_sds_remote_device_ready_state_complete_request_handler,
 2265          scic_sds_remote_device_default_continue_request_handler,
 2266          scic_sds_remote_device_ready_state_start_task_handler,
 2267          scic_sds_remote_device_ready_state_complete_request_handler
 2268       },
 2269       scic_sds_remote_device_general_suspend_handler,
 2270       scic_sds_remote_device_general_resume_handler,
 2271       scic_sds_remote_device_general_event_handler,
 2272       scic_sds_remote_device_general_frame_handler,
 2273    },
 2274    // SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
 2275    {
 2276       {
 2277          scic_sds_remote_device_default_start_handler,
 2278          scic_sds_remote_device_stopping_state_stop_handler,
 2279          scic_sds_remote_device_default_fail_handler,
 2280          scic_sds_remote_device_default_destruct_handler,
 2281          scic_sds_remote_device_default_reset_handler,
 2282          scic_sds_remote_device_default_reset_complete_handler,
 2283          scic_sds_remote_device_default_start_request_handler,
 2284          scic_sds_remote_device_stopping_state_complete_request_handler,
 2285          scic_sds_remote_device_default_continue_request_handler,
 2286          scic_sds_remote_device_default_start_request_handler,
 2287          scic_sds_remote_device_stopping_state_complete_request_handler
 2288       },
 2289       scic_sds_remote_device_default_suspend_handler,
 2290       scic_sds_remote_device_default_resume_handler,
 2291       scic_sds_remote_device_general_event_handler,
 2292       scic_sds_remote_device_general_frame_handler
 2293    },
 2294    // SCI_BASE_REMOTE_DEVICE_STATE_FAILED
 2295    {
 2296       {
 2297          scic_sds_remote_device_default_start_handler,
 2298          scic_sds_remote_device_default_stop_handler,
 2299          scic_sds_remote_device_default_fail_handler,
 2300          scic_sds_remote_device_default_destruct_handler,
 2301          scic_sds_remote_device_default_reset_handler,
 2302          scic_sds_remote_device_default_reset_complete_handler,
 2303          scic_sds_remote_device_default_start_request_handler,
 2304          scic_sds_remote_device_default_complete_request_handler,
 2305          scic_sds_remote_device_default_continue_request_handler,
 2306          scic_sds_remote_device_default_start_request_handler,
 2307          scic_sds_remote_device_default_complete_request_handler
 2308       },
 2309       scic_sds_remote_device_default_suspend_handler,
 2310       scic_sds_remote_device_default_resume_handler,
 2311       scic_sds_remote_device_default_event_handler,
 2312       scic_sds_remote_device_general_frame_handler
 2313    },
 2314    // SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
 2315    {
 2316       {
 2317          scic_sds_remote_device_default_start_handler,
 2318          scic_sds_remote_device_resetting_state_stop_handler,
 2319          scic_sds_remote_device_default_fail_handler,
 2320          scic_sds_remote_device_default_destruct_handler,
 2321          scic_sds_remote_device_default_reset_handler,
 2322          scic_sds_remote_device_resetting_state_reset_complete_handler,
 2323          scic_sds_remote_device_default_start_request_handler,
 2324          scic_sds_remote_device_resetting_state_complete_request_handler,
 2325          scic_sds_remote_device_default_continue_request_handler,
 2326          scic_sds_remote_device_default_start_request_handler,
 2327          scic_sds_remote_device_resetting_state_complete_request_handler
 2328       },
 2329       scic_sds_remote_device_default_suspend_handler,
 2330       scic_sds_remote_device_default_resume_handler,
 2331       scic_sds_remote_device_default_event_handler,
 2332       scic_sds_remote_device_general_frame_handler
 2333    },
 2334 #if !defined(DISABLE_WIDE_PORTED_TARGETS)
 2335    // SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH - unused by SCIC
 2336    {
 2337       {
 2338          scic_sds_remote_device_default_start_handler,
 2339          scic_sds_remote_device_default_stop_handler,
 2340          scic_sds_remote_device_default_fail_handler,
 2341          scic_sds_remote_device_default_destruct_handler,
 2342          scic_sds_remote_device_default_reset_handler,
 2343          scic_sds_remote_device_default_reset_complete_handler,
 2344          scic_sds_remote_device_default_start_request_handler,
 2345          scic_sds_remote_device_default_complete_request_handler,
 2346          scic_sds_remote_device_default_continue_request_handler,
 2347          scic_sds_remote_device_default_start_request_handler,
 2348          scic_sds_remote_device_default_complete_request_handler
 2349       },
 2350       scic_sds_remote_device_default_suspend_handler,
 2351       scic_sds_remote_device_default_resume_handler,
 2352       scic_sds_remote_device_default_event_handler,
 2353       scic_sds_remote_device_default_frame_handler
 2354    },
 2355 #endif
 2356    // SCI_BASE_REMOTE_DEVICE_STATE_FINAL
 2357    {
 2358       {
 2359          scic_sds_remote_device_default_start_handler,
 2360          scic_sds_remote_device_default_stop_handler,
 2361          scic_sds_remote_device_default_fail_handler,
 2362          scic_sds_remote_device_default_destruct_handler,
 2363          scic_sds_remote_device_default_reset_handler,
 2364          scic_sds_remote_device_default_reset_complete_handler,
 2365          scic_sds_remote_device_default_start_request_handler,
 2366          scic_sds_remote_device_default_complete_request_handler,
 2367          scic_sds_remote_device_default_continue_request_handler,
 2368          scic_sds_remote_device_default_start_request_handler,
 2369          scic_sds_remote_device_default_complete_request_handler
 2370       },
 2371       scic_sds_remote_device_default_suspend_handler,
 2372       scic_sds_remote_device_default_resume_handler,
 2373       scic_sds_remote_device_default_event_handler,
 2374       scic_sds_remote_device_default_frame_handler
 2375    }
 2376 };
 2377 
 2378 /**
 2379  * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it
 2380  * immediately transitions the remote device object to the stopped state.
 2381  *
 2382  * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
 2383  *            SCIC_SDS_REMOTE_DEVICE.
 2384  *
 2385  * @return none
 2386  */
 2387 static
 2388 void scic_sds_remote_device_initial_state_enter(
 2389    SCI_BASE_OBJECT_T *object
 2390 )
 2391 {
 2392    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
 2393 
 2394    SET_STATE_HANDLER(
 2395       this_device,
 2396       scic_sds_remote_device_state_handler_table,
 2397       SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
 2398    );
 2399 
 2400    // Initial state is a transitional state to the stopped state
 2401    sci_base_state_machine_change_state(
 2402       scic_sds_remote_device_get_base_state_machine(this_device),
 2403       SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
 2404    );
 2405 }
 2406 
 2407 /**
 2408  * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it
 2409  * sets the stopped state handlers and if this state is entered from the
 2410  * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING then the SCI User is informed that
 2411  * the device stop is complete.
 2412  *
 2413  * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
 2414  *       SCIC_SDS_REMOTE_DEVICE.
 2415  *
 2416  * @return none
 2417  */
 2418 static
 2419 void scic_sds_remote_device_stopped_state_enter(
 2420    SCI_BASE_OBJECT_T *object
 2421 )
 2422 {
 2423    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
 2424 
 2425    SET_STATE_HANDLER(
 2426       this_device,
 2427       scic_sds_remote_device_state_handler_table,
 2428       SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
 2429    );
 2430 
 2431    // If we are entering from the stopping state let the SCI User know that
 2432    // the stop operation has completed.
 2433    if (this_device->parent.state_machine.previous_state_id
 2434        == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING)
 2435    {
 2436       scic_cb_remote_device_stop_complete(
 2437          scic_sds_remote_device_get_controller(this_device),
 2438          this_device,
 2439          SCI_SUCCESS
 2440       );
 2441    }
 2442 
 2443    scic_sds_controller_remote_device_stopped(
 2444       scic_sds_remote_device_get_controller(this_device),
 2445       this_device
 2446    );
 2447 }
 2448 
 2449 /**
 2450  * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it
 2451  * sets the starting state handlers, sets the device not ready, and posts the
 2452  * remote node context to the hardware.
 2453  *
 2454  * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
 2455  *       SCIC_SDS_REMOTE_DEVICE.
 2456  *
 2457  * @return none
 2458  */
 2459 static
 2460 void scic_sds_remote_device_starting_state_enter(
 2461    SCI_BASE_OBJECT_T *object
 2462 )
 2463 {
 2464    SCIC_SDS_CONTROLLER_T    * the_controller;
 2465    SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
 2466 
 2467    the_controller = scic_sds_remote_device_get_controller(this_device);
 2468 
 2469    SET_STATE_HANDLER(
 2470       this_device,
 2471       scic_sds_remote_device_state_handler_table,
 2472       SCI_BASE_REMOTE_DEVICE_STATE_STARTING
 2473    );
 2474 
 2475    scic_cb_remote_device_not_ready(
 2476       the_controller,
 2477       this_device,
 2478       SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED
 2479    );
 2480 }
 2481 
 2482 
 2483 /**
 2484  * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets
 2485  * the ready state handlers, and starts the ready substate machine.
 2486  *
 2487  * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
 2488  *       SCIC_SDS_REMOTE_DEVICE.
 2489  *
 2490  * @return none
 2491  */
 2492 static
 2493 void scic_sds_remote_device_ready_state_enter(
 2494    SCI_BASE_OBJECT_T *object
 2495 )
 2496 {
 2497    SCIC_SDS_CONTROLLER_T    * the_controller;
 2498    SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
 2499 
 2500    the_controller = scic_sds_remote_device_get_controller(this_device);
 2501 
 2502    SET_STATE_HANDLER(
 2503       this_device,
 2504       scic_sds_remote_device_state_handler_table,
 2505       SCI_BASE_REMOTE_DEVICE_STATE_READY
 2506    );
 2507 
 2508    /// @todo Check the device object for the proper return code for this
 2509    ///       callback
 2510    scic_cb_remote_device_start_complete(
 2511       the_controller, this_device, SCI_SUCCESS
 2512    );
 2513 
 2514    scic_sds_controller_remote_device_started(
 2515       the_controller, this_device
 2516    );
 2517 
 2518    if (this_device->has_ready_substate_machine)
 2519    {
 2520       sci_base_state_machine_start(&this_device->ready_substate_machine);
 2521    }
 2522    else
 2523    {
 2524       scic_cb_remote_device_ready(the_controller, this_device);
 2525    }
 2526 }
 2527 
 2528 /**
 2529  * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does
 2530  * nothing.
 2531  *
 2532  * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
 2533  *       SCIC_SDS_REMOTE_DEVICE.
 2534  *
 2535  * @return none
 2536  */
 2537 static
 2538 void scic_sds_remote_device_ready_state_exit(
 2539    SCI_BASE_OBJECT_T *object
 2540 )
 2541 {
 2542    SCIC_SDS_CONTROLLER_T    * the_controller;
 2543    SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
 2544 
 2545    the_controller = scic_sds_remote_device_get_controller(this_device);
 2546 
 2547    if (this_device->has_ready_substate_machine)
 2548    {
 2549       sci_base_state_machine_stop(&this_device->ready_substate_machine);
 2550    }
 2551    else
 2552    {
 2553       scic_cb_remote_device_not_ready(
 2554          the_controller,
 2555          this_device,
 2556          SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED
 2557       );
 2558    }
 2559 }
 2560 
 2561 /**
 2562  * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING it
 2563  * sets the stopping state handlers and posts an RNC invalidate request to the
 2564  * SCU hardware.
 2565  *
 2566  * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
 2567  *       SCIC_SDS_REMOTE_DEVICE.
 2568  *
 2569  * @return none
 2570  */
 2571 static
 2572 void scic_sds_remote_device_stopping_state_enter(
 2573    SCI_BASE_OBJECT_T *object
 2574 )
 2575 {
 2576    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
 2577 
 2578    SET_STATE_HANDLER(
 2579       this_device,
 2580       scic_sds_remote_device_state_handler_table,
 2581       SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
 2582    );
 2583 }
 2584 
 2585 /**
 2586  * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FAILED it
 2587  * sets the stopping state handlers.
 2588  *
 2589  * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
 2590  *       SCIC_SDS_REMOTE_DEVICE.
 2591  *
 2592  * @return none
 2593  */
 2594 static
 2595 void scic_sds_remote_device_failed_state_enter(
 2596    SCI_BASE_OBJECT_T *object
 2597 )
 2598 {
 2599    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
 2600 
 2601    SET_STATE_HANDLER(
 2602       this_device,
 2603       scic_sds_remote_device_state_handler_table,
 2604       SCI_BASE_REMOTE_DEVICE_STATE_FAILED
 2605    );
 2606 }
 2607 
 2608 /**
 2609  * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it
 2610  * sets the resetting state handlers.
 2611  *
 2612  * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
 2613  *       SCIC_SDS_REMOTE_DEVICE.
 2614  *
 2615  * @return none
 2616  */
 2617 static
 2618 void scic_sds_remote_device_resetting_state_enter(
 2619    SCI_BASE_OBJECT_T *object
 2620 )
 2621 {
 2622    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
 2623 
 2624    SET_STATE_HANDLER(
 2625       this_device,
 2626       scic_sds_remote_device_state_handler_table,
 2627       SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
 2628    );
 2629 
 2630    scic_sds_remote_node_context_suspend(
 2631       this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
 2632 }
 2633 
 2634 /**
 2635  * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it
 2636  * does nothing.
 2637  *
 2638  * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
 2639  *       SCIC_SDS_REMOTE_DEVICE.
 2640  *
 2641  * @return none
 2642  */
 2643 static
 2644 void scic_sds_remote_device_resetting_state_exit(
 2645    SCI_BASE_OBJECT_T *object
 2646 )
 2647 {
 2648    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
 2649 
 2650    scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL);
 2651 }
 2652 
 2653 /**
 2654  * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FINAL it sets
 2655  * the final state handlers.
 2656  *
 2657  * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
 2658  *       SCIC_SDS_REMOTE_DEVICE.
 2659  *
 2660  * @return none
 2661  */
 2662 static
 2663 void scic_sds_remote_device_final_state_enter(
 2664    SCI_BASE_OBJECT_T *object
 2665 )
 2666 {
 2667    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
 2668 
 2669    SET_STATE_HANDLER(
 2670       this_device,
 2671       scic_sds_remote_device_state_handler_table,
 2672       SCI_BASE_REMOTE_DEVICE_STATE_FINAL
 2673    );
 2674 }
 2675 
 2676 // ---------------------------------------------------------------------------
 2677 
 2678 SCI_BASE_STATE_T
 2679    scic_sds_remote_device_state_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
 2680 {
 2681    {
 2682       SCI_BASE_REMOTE_DEVICE_STATE_INITIAL,
 2683       scic_sds_remote_device_initial_state_enter,
 2684       NULL
 2685    },
 2686    {
 2687       SCI_BASE_REMOTE_DEVICE_STATE_STOPPED,
 2688       scic_sds_remote_device_stopped_state_enter,
 2689       NULL
 2690    },
 2691    {
 2692       SCI_BASE_REMOTE_DEVICE_STATE_STARTING,
 2693       scic_sds_remote_device_starting_state_enter,
 2694       NULL
 2695    },
 2696    {
 2697       SCI_BASE_REMOTE_DEVICE_STATE_READY,
 2698       scic_sds_remote_device_ready_state_enter,
 2699       scic_sds_remote_device_ready_state_exit
 2700    },
 2701    {
 2702       SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
 2703       scic_sds_remote_device_stopping_state_enter,
 2704       NULL
 2705    },
 2706    {
 2707       SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
 2708       scic_sds_remote_device_failed_state_enter,
 2709       NULL
 2710    },
 2711    {
 2712       SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
 2713       scic_sds_remote_device_resetting_state_enter,
 2714       scic_sds_remote_device_resetting_state_exit
 2715    },
 2716 #if !defined(DISABLE_WIDE_PORTED_TARGETS)
 2717    {  //Not used by SCIC
 2718       SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH,
 2719       NULL,
 2720       NULL
 2721    },
 2722 #endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
 2723    {
 2724       SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
 2725       scic_sds_remote_device_final_state_enter,
 2726       NULL
 2727    }
 2728 };
 2729 

Cache object: e22f7dda676f85fc67a8839677f2edca


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