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_node_context.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 structures, constants, and prototypes
   62 *        associated with the remote node context in the silicon.  It
   63 *        exists to model and manage the remote node context in the silicon.
   64 */
   65 
   66 #include <dev/isci/scil/sci_util.h>
   67 #include <dev/isci/scil/scic_sds_logger.h>
   68 #include <dev/isci/scil/scic_sds_controller.h>
   69 #include <dev/isci/scil/scic_sds_remote_device.h>
   70 #include <dev/isci/scil/scic_sds_remote_node_context.h>
   71 #include <dev/isci/scil/sci_base_state_machine.h>
   72 #include <dev/isci/scil/scic_remote_device.h>
   73 #include <dev/isci/scil/scic_sds_port.h>
   74 #include <dev/isci/scil/scu_event_codes.h>
   75 #include <dev/isci/scil/scu_task_context.h>
   76 
   77 /**
   78 * @brief
   79 */
   80    void scic_sds_remote_node_context_construct(
   81    SCIC_SDS_REMOTE_DEVICE_T       * device,
   82    SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc,
   83    U16                              remote_node_index
   84       )
   85 {
   86    memset (rnc, 0, sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T) );
   87 
   88    rnc->remote_node_index = remote_node_index;
   89    rnc->device            = device;
   90    rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
   91 
   92    rnc->parent.logger = device->parent.parent.logger;
   93 
   94    sci_base_state_machine_construct(
   95       &rnc->state_machine,
   96       &rnc->parent,
   97       scic_sds_remote_node_context_state_table,
   98       SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
   99          );
  100 
  101    sci_base_state_machine_start(&rnc->state_machine);
  102 
  103    // State logging initialization takes place late for the remote node context
  104    // see the resume state handler for the initial state.
  105 }
  106 
  107 /**
  108 * This method will return TRUE if the RNC is not in the initial state.  In
  109 * all other states the RNC is considered active and this will return TRUE.
  110 *
  111 * @note The destroy request of the state machine drives the RNC back to the
  112 *       initial state.  If the state machine changes then this routine will
  113 *       also have to be changed.
  114 *
  115 * @param[in] this_rnc The RNC for which the is posted request is being made.
  116 *
  117 * @return BOOL
  118 * @retval TRUE if the state machine is not in the initial state
  119 * @retval FALSE if the state machine is in the initial state
  120 */
  121    BOOL scic_sds_remote_node_context_is_initialized(
  122    SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
  123       )
  124 {
  125    U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
  126 
  127    if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE)
  128    {
  129       return FALSE;
  130    }
  131 
  132    return TRUE;
  133 }
  134 
  135 /**
  136 * This method will return TRUE if the remote node context is in a READY state
  137 * otherwise it will return FALSE
  138 *
  139 * @param[in] this_rnc The state of the remote node context object to check.
  140 *
  141 * @return BOOL
  142 * @retval TRUE if the remote node context is in the ready state.
  143 * @retval FALSE if the remote node context is not in the ready state.
  144 */
  145    BOOL scic_sds_remote_node_context_is_ready(
  146    SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
  147       )
  148 {
  149    U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
  150 
  151    if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE)
  152    {
  153       return TRUE;
  154    }
  155 
  156    return FALSE;
  157 }
  158 
  159 /**
  160 * This method will construct the RNC buffer for this remote device object.
  161 *
  162 * @param[in] this_device The remote device to use to construct the RNC
  163 *       buffer.
  164 * @param[in] rnc The buffer into which the remote device data will be copied.
  165 *
  166 * @return none
  167 */
  168    void scic_sds_remote_node_context_construct_buffer(
  169    SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
  170       )
  171 {
  172    SCU_REMOTE_NODE_CONTEXT_T * rnc;
  173    SCIC_SDS_CONTROLLER_T     * the_controller;
  174 
  175    the_controller = scic_sds_remote_device_get_controller(this_rnc->device);
  176 
  177    rnc = scic_sds_controller_get_remote_node_context_buffer(
  178       the_controller, this_rnc->remote_node_index);
  179 
  180    memset(
  181       rnc,
  182       0x00,
  183       sizeof(SCU_REMOTE_NODE_CONTEXT_T)
  184          * scic_sds_remote_device_node_count(this_rnc->device)
  185          );
  186 
  187    rnc->ssp.remote_node_index = this_rnc->remote_node_index;
  188    rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width;
  189    rnc->ssp.logical_port_index =
  190       scic_sds_remote_device_get_port_index(this_rnc->device);
  191 
  192    rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high);
  193    rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low);
  194 
  195    rnc->ssp.nexus_loss_timer_enable = TRUE;
  196    rnc->ssp.check_bit               = FALSE;
  197    rnc->ssp.is_valid                = FALSE;
  198    rnc->ssp.is_remote_node_context  = TRUE;
  199    rnc->ssp.function_number         = 0;
  200 
  201    rnc->ssp.arbitration_wait_time = 0;
  202 
  203 
  204    if (
  205       this_rnc->device->target_protocols.u.bits.attached_sata_device
  206          || this_rnc->device->target_protocols.u.bits.attached_stp_target
  207          )
  208    {
  209       rnc->ssp.connection_occupancy_timeout =
  210          the_controller->user_parameters.sds1.stp_max_occupancy_timeout;
  211       rnc->ssp.connection_inactivity_timeout =
  212          the_controller->user_parameters.sds1.stp_inactivity_timeout;
  213    }
  214    else
  215    {
  216       rnc->ssp.connection_occupancy_timeout  =
  217          the_controller->user_parameters.sds1.ssp_max_occupancy_timeout;
  218       rnc->ssp.connection_inactivity_timeout =
  219          the_controller->user_parameters.sds1.ssp_inactivity_timeout;
  220    }
  221 
  222    rnc->ssp.initial_arbitration_wait_time = 0;
  223 
  224    // Open Address Frame Parameters
  225    rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate;
  226    rnc->ssp.oaf_features = 0;
  227    rnc->ssp.oaf_source_zone_group = 0;
  228    rnc->ssp.oaf_more_compatibility_features = 0;
  229 }
  230 
  231 // ---------------------------------------------------------------------------
  232 
  233 #ifdef SCI_LOGGING
  234 /**
  235 * This method will enable and turn on state transition logging for the remote
  236 * node context object.
  237 *
  238 * @param[in] this_rnc The remote node context for which state transition
  239 *       logging is to be enabled.
  240 *
  241 * @return none
  242 */
  243    void scic_sds_remote_node_context_initialize_state_logging(
  244    SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
  245       )
  246 {
  247    sci_base_state_machine_logger_initialize(
  248       &this_rnc->state_machine_logger,
  249       &this_rnc->state_machine,
  250       &this_rnc->parent,
  251       scic_cb_logger_log_states,
  252       "SCIC_SDS_REMOTE_NODE_CONTEXT_T", "state machine",
  253       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  254          SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  255          SCIC_LOG_OBJECT_STP_REMOTE_TARGET
  256          );
  257 }
  258 
  259 /**
  260 * This method will stop the state machine logging for this object and should
  261 * be called before the object is destroyed.
  262 *
  263 * @param[in] this_rnc The remote node context on which to stop logging state
  264 *       transitions.
  265 *
  266 * @return none
  267 */
  268    void scic_sds_remote_node_context_deinitialize_state_logging(
  269    SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
  270       )
  271 {
  272    sci_base_state_machine_logger_deinitialize(
  273       &this_rnc->state_machine_logger,
  274       &this_rnc->state_machine
  275          );
  276 }
  277 #endif
  278 
  279 /**
  280 * This method will setup the remote node context object so it will transition
  281 * to its ready state.  If the remote node context is already setup to
  282 * transition to its final state then this function does nothing.
  283 *
  284 * @param[in] this_rnc
  285 * @param[in] the_callback
  286 * @param[in] callback_parameter
  287 *
  288 * @return none
  289 */
  290 static
  291 void scic_sds_remote_node_context_setup_to_resume(
  292    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  293    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  294    void                                   * callback_parameter
  295 )
  296 {
  297    if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
  298    {
  299       this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY;
  300       this_rnc->user_callback     = the_callback;
  301       this_rnc->user_cookie       = callback_parameter;
  302    }
  303 }
  304 
  305 /**
  306 * This method will setup the remote node context object so it will
  307 * transition to its final state.
  308 *
  309 * @param[in] this_rnc
  310 * @param[in] the_callback
  311 * @param[in] callback_parameter
  312 *
  313 * @return none
  314 */
  315 static
  316 void scic_sds_remote_node_context_setup_to_destory(
  317    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  318    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  319    void                                   * callback_parameter
  320 )
  321 {
  322    this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL;
  323    this_rnc->user_callback     = the_callback;
  324    this_rnc->user_cookie       = callback_parameter;
  325 }
  326 
  327 /**
  328 * This method will continue to resume a remote node context.  This is used
  329 * in the states where a resume is requested while a resume is in progress.
  330 *
  331 * @param[in] this_rnc
  332 * @param[in] the_callback
  333 * @param[in] callback_parameter
  334 */
  335 static
  336 SCI_STATUS scic_sds_remote_node_context_continue_to_resume_handler(
  337    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  338    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  339    void                                   * callback_parameter
  340 )
  341 {
  342    if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
  343    {
  344       this_rnc->user_callback = the_callback;
  345       this_rnc->user_cookie   = callback_parameter;
  346 
  347       return SCI_SUCCESS;
  348    }
  349 
  350    return SCI_FAILURE_INVALID_STATE;
  351 }
  352 
  353 //******************************************************************************
  354 //* REMOTE NODE CONTEXT STATE MACHINE
  355 //******************************************************************************
  356 
  357 static
  358 SCI_STATUS scic_sds_remote_node_context_default_destruct_handler(
  359    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  360    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  361    void                                   * callback_parameter
  362 )
  363 {
  364    SCIC_LOG_WARNING((
  365       sci_base_object_get_logger(this_rnc->device),
  366       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  367          SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  368          SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  369       "SCIC Remote Node Context 0x%x requested to stop while in unexpected state %d\n",
  370       this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
  371          ));
  372 
  373    // We have decided that the destruct request on the remote node context can not fail
  374    // since it is either in the initial/destroyed state or is can be destroyed.
  375    return SCI_SUCCESS;
  376 }
  377 
  378 static
  379 SCI_STATUS scic_sds_remote_node_context_default_suspend_handler(
  380    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  381    U32                                      suspend_type,
  382    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  383    void                                   * callback_parameter
  384 )
  385 {
  386    SCIC_LOG_WARNING((
  387       sci_base_object_get_logger(this_rnc->device),
  388       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  389          SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  390          SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  391       "SCIC Remote Node Context 0x%x requested to suspend while in wrong state %d\n",
  392       this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
  393          ));
  394 
  395    return SCI_FAILURE_INVALID_STATE;
  396 }
  397 
  398 static
  399 SCI_STATUS scic_sds_remote_node_context_default_resume_handler(
  400    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  401    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  402    void                                   * callback_parameter
  403 )
  404 {
  405    SCIC_LOG_WARNING((
  406       sci_base_object_get_logger(this_rnc->device),
  407       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  408          SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  409          SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  410       "SCIC Remote Node Context 0x%x requested to resume while in wrong state %d\n",
  411       this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
  412          ));
  413 
  414    return SCI_FAILURE_INVALID_STATE;
  415 }
  416 
  417 static
  418 SCI_STATUS scic_sds_remote_node_context_default_start_io_handler(
  419    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  420    struct SCIC_SDS_REQUEST             * the_request
  421 )
  422 {
  423    SCIC_LOG_WARNING((
  424       sci_base_object_get_logger(this_rnc->device),
  425       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  426          SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  427          SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  428       "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n",
  429       this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
  430          ));
  431 
  432    return SCI_FAILURE_INVALID_STATE;
  433 }
  434 
  435 static
  436 SCI_STATUS scic_sds_remote_node_context_default_start_task_handler(
  437    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  438    struct SCIC_SDS_REQUEST             * the_request
  439 )
  440 {
  441    SCIC_LOG_WARNING((
  442       sci_base_object_get_logger(this_rnc->device),
  443       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  444          SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  445          SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  446       "SCIC Remote Node Context 0x%x requested to start task 0x%x while in wrong state %d\n",
  447       this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
  448          ));
  449 
  450    return SCI_FAILURE;
  451 }
  452 
  453 static
  454 SCI_STATUS scic_sds_remote_node_context_default_event_handler(
  455    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  456    U32                                   event_code
  457 )
  458 {
  459    SCIC_LOG_WARNING((
  460       sci_base_object_get_logger(this_rnc->device),
  461       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  462          SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  463          SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  464       "SCIC Remote Node Context 0x%x requested to process event 0x%x while in wrong state %d\n",
  465       this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
  466          ));
  467 
  468    return SCI_FAILURE_INVALID_STATE;
  469 }
  470 
  471 /**
  472 * This method determines if the task request can be started by the SCU
  473 * hardware. When the RNC is in the ready state any task can be started.
  474 *
  475 * @param[in] this_rnc The rnc for which the task request is targeted.
  476 * @param[in] the_request The request which is going to be started.
  477 *
  478 * @return SCI_STATUS
  479 * @retval SCI_SUCCESS
  480 */
  481 static
  482 SCI_STATUS scic_sds_remote_node_context_success_start_task_handler(
  483    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  484    struct SCIC_SDS_REQUEST             * the_request
  485 )
  486 {
  487    return SCI_SUCCESS;
  488 }
  489 
  490 /**
  491 * This method handles destruct calls from the various state handlers.  The
  492 * remote node context can be requested to destroy from any state. If there
  493 * was a user callback it is always replaced with the request to destroy user
  494 * callback.
  495 *
  496 * @param[in] this_rnc
  497 * @param[in] the_callback
  498 * @param[in] callback_parameter
  499 *
  500 * @return SCI_STATUS
  501 */
  502 static
  503 SCI_STATUS scic_sds_remote_node_context_general_destruct_handler(
  504    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  505    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  506    void                                   * callback_parameter
  507 )
  508 {
  509    scic_sds_remote_node_context_setup_to_destory(
  510       this_rnc, the_callback, callback_parameter
  511          );
  512 
  513    sci_base_state_machine_change_state(
  514       &this_rnc->state_machine,
  515       SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
  516          );
  517 
  518    return SCI_SUCCESS;
  519 }
  520 // ---------------------------------------------------------------------------
  521 static
  522 SCI_STATUS scic_sds_remote_node_context_reset_required_start_io_handler(
  523    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  524    struct SCIC_SDS_REQUEST             * the_request
  525 )
  526 {
  527    SCIC_LOG_WARNING((
  528       sci_base_object_get_logger(this_rnc->device),
  529       SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  530          SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  531          SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  532       "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n",
  533       this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
  534          ));
  535 
  536    return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
  537 }
  538 
  539 // ---------------------------------------------------------------------------
  540 
  541 static
  542 SCI_STATUS scic_sds_remote_node_context_initial_state_resume_handler(
  543    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  544    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  545    void                                   * callback_parameter
  546 )
  547 {
  548    if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
  549    {
  550       scic_sds_remote_node_context_setup_to_resume(
  551          this_rnc, the_callback, callback_parameter
  552             );
  553 
  554       scic_sds_remote_node_context_construct_buffer(this_rnc);
  555 
  556 #if defined (SCI_LOGGING)
  557       // If a remote node context has a logger already, don't work on its state
  558       // logging.
  559       if (this_rnc->state_machine.previous_state_id
  560              != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE)
  561          scic_sds_remote_node_context_initialize_state_logging(this_rnc);
  562 #endif
  563 
  564       sci_base_state_machine_change_state(
  565          &this_rnc->state_machine,
  566          SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
  567             );
  568 
  569       return SCI_SUCCESS;
  570    }
  571 
  572    return SCI_FAILURE_INVALID_STATE;
  573 }
  574 
  575 // ---------------------------------------------------------------------------
  576 
  577 static
  578 SCI_STATUS scic_sds_remote_node_context_posting_state_event_handler(
  579    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  580    U32                                   event_code
  581 )
  582 {
  583    SCI_STATUS status;
  584 
  585    switch (scu_get_event_code(event_code))
  586    {
  587       case SCU_EVENT_POST_RNC_COMPLETE:
  588          status = SCI_SUCCESS;
  589 
  590          sci_base_state_machine_change_state(
  591             &this_rnc->state_machine,
  592             SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
  593                );
  594          break;
  595 
  596       default:
  597          status = SCI_FAILURE;
  598          SCIC_LOG_WARNING((
  599             sci_base_object_get_logger(this_rnc->device),
  600             SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  601                SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  602                SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  603             "SCIC Remote Node Context 0x%x requested to process unexpected event 0x%x while in posting state\n",
  604             this_rnc, event_code
  605                ));
  606          break;
  607    }
  608 
  609    return status;
  610 }
  611 
  612 // ---------------------------------------------------------------------------
  613 
  614 static
  615 SCI_STATUS scic_sds_remote_node_context_invalidating_state_destruct_handler(
  616    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  617    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  618    void                                   * callback_parameter
  619 )
  620 {
  621    scic_sds_remote_node_context_setup_to_destory(
  622       this_rnc, the_callback, callback_parameter
  623          );
  624 
  625    return SCI_SUCCESS;
  626 }
  627 
  628 static
  629 SCI_STATUS scic_sds_remote_node_context_invalidating_state_event_handler(
  630    SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
  631    U32                              event_code
  632 )
  633 {
  634    SCI_STATUS status;
  635 
  636    if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE)
  637    {
  638       status = SCI_SUCCESS;
  639 
  640       if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
  641       {
  642          sci_base_state_machine_change_state(
  643             &this_rnc->state_machine,
  644             SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
  645                );
  646       }
  647       else
  648       {
  649          sci_base_state_machine_change_state(
  650             &this_rnc->state_machine,
  651             SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
  652                );
  653       }
  654    }
  655    else
  656    {
  657       switch (scu_get_event_type(event_code))
  658       {
  659          case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
  660          case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
  661             // We really dont care if the hardware is going to suspend
  662             // the device since it's being invalidated anyway
  663             SCIC_LOG_INFO((
  664                sci_base_object_get_logger(this_rnc->device),
  665                SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  666                   SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  667                   SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  668                "SCIC Remote Node Context 0x%x was suspeneded by hardware while being invalidated.\n",
  669                this_rnc
  670                   ));
  671             status = SCI_SUCCESS;
  672             break;
  673 
  674          default:
  675             SCIC_LOG_WARNING((
  676                sci_base_object_get_logger(this_rnc->device),
  677                SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  678                   SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  679                   SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  680                "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
  681                this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
  682                   ));
  683             status = SCI_FAILURE;
  684             break;
  685       }
  686    }
  687 
  688    return status;
  689 }
  690 
  691 // ---------------------------------------------------------------------------
  692 
  693 static
  694 SCI_STATUS scic_sds_remote_node_context_resuming_state_event_handler(
  695    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  696    U32                                   event_code
  697 )
  698 {
  699    SCI_STATUS status;
  700 
  701    if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE)
  702    {
  703       status = SCI_SUCCESS;
  704 
  705       sci_base_state_machine_change_state(
  706          &this_rnc->state_machine,
  707          SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
  708             );
  709    }
  710    else
  711    {
  712       switch (scu_get_event_type(event_code))
  713       {
  714          case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
  715          case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
  716             // We really dont care if the hardware is going to suspend
  717             // the device since it's being resumed anyway
  718             SCIC_LOG_INFO((
  719                sci_base_object_get_logger(this_rnc->device),
  720                SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  721                   SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  722                   SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  723                "SCIC Remote Node Context 0x%x was suspeneded by hardware while being resumed.\n",
  724                this_rnc
  725                   ));
  726             status = SCI_SUCCESS;
  727             break;
  728 
  729          default:
  730             SCIC_LOG_WARNING((
  731                sci_base_object_get_logger(this_rnc->device),
  732                SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  733                   SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  734                   SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  735                "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
  736                this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
  737                   ));
  738             status = SCI_FAILURE;
  739             break;
  740       }
  741    }
  742 
  743    return status;
  744 }
  745 
  746 // ---------------------------------------------------------------------------
  747 
  748 /**
  749 * This method will handle the suspend requests from the ready state.
  750 *
  751 * @param[in] this_rnc The remote node context object being suspended.
  752 * @param[in] the_callback The callback when the suspension is complete.
  753 * @param[in] callback_parameter The parameter that is to be passed into the
  754 *       callback.
  755 *
  756 * @return SCI_SUCCESS
  757 */
  758 static
  759 SCI_STATUS scic_sds_remote_node_context_ready_state_suspend_handler(
  760    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  761    U32                                      suspend_type,
  762    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  763    void                                   * callback_parameter
  764 )
  765 {
  766    this_rnc->user_callback   = the_callback;
  767    this_rnc->user_cookie     = callback_parameter;
  768    this_rnc->suspension_code = suspend_type;
  769 
  770    if (suspend_type == SCI_SOFTWARE_SUSPENSION)
  771    {
  772       scic_sds_remote_device_post_request(
  773          this_rnc->device,
  774          SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
  775             );
  776    }
  777 
  778    sci_base_state_machine_change_state(
  779       &this_rnc->state_machine,
  780       SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
  781          );
  782 
  783    return SCI_SUCCESS;
  784 }
  785 
  786 /**
  787 * This method determines if the io request can be started by the SCU
  788 * hardware. When the RNC is in the ready state any io request can be started.
  789 *
  790 * @param[in] this_rnc The rnc for which the io request is targeted.
  791 * @param[in] the_request The request which is going to be started.
  792 *
  793 * @return SCI_STATUS
  794 * @retval SCI_SUCCESS
  795 */
  796 static
  797 SCI_STATUS scic_sds_remote_node_context_ready_state_start_io_handler(
  798    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  799    struct SCIC_SDS_REQUEST             * the_request
  800 )
  801 {
  802    return SCI_SUCCESS;
  803 }
  804 
  805 
  806 static
  807 SCI_STATUS scic_sds_remote_node_context_ready_state_event_handler(
  808    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  809    U32                                   event_code
  810 )
  811 {
  812    SCI_STATUS status;
  813 
  814    switch (scu_get_event_type(event_code))
  815    {
  816       case SCU_EVENT_TL_RNC_SUSPEND_TX:
  817          sci_base_state_machine_change_state(
  818             &this_rnc->state_machine,
  819             SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
  820                );
  821 
  822          this_rnc->suspension_code = scu_get_event_specifier(event_code);
  823          status = SCI_SUCCESS;
  824          break;
  825 
  826       case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
  827          sci_base_state_machine_change_state(
  828             &this_rnc->state_machine,
  829             SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
  830                );
  831 
  832          this_rnc->suspension_code = scu_get_event_specifier(event_code);
  833          status = SCI_SUCCESS;
  834          break;
  835 
  836       default:
  837          SCIC_LOG_WARNING((
  838             sci_base_object_get_logger(this_rnc->device),
  839             SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
  840                SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
  841                SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
  842             "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
  843             this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
  844                ));
  845 
  846          status = SCI_FAILURE;
  847          break;
  848    }
  849 
  850    return status;
  851 }
  852 
  853 // ---------------------------------------------------------------------------
  854 
  855 static
  856 SCI_STATUS scic_sds_remote_node_context_tx_suspended_state_resume_handler(
  857    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  858    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  859    void                                   * callback_parameter
  860 )
  861 {
  862    SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
  863 
  864    scic_sds_remote_node_context_setup_to_resume(
  865       this_rnc, the_callback, callback_parameter
  866          );
  867 
  868    // If this is an expander attached SATA device we must invalidate
  869    // and repost the RNC since this is the only way to clear the
  870    // TCi to NCQ tag mapping table for the RNi
  871    // All other device types we can just resume.
  872    scic_remote_device_get_protocols(this_rnc->device, &protocols);
  873 
  874    if (
  875       (protocols.u.bits.attached_stp_target == 1)
  876          && !(this_rnc->device->is_direct_attached)
  877          )
  878    {
  879       sci_base_state_machine_change_state(
  880          &this_rnc->state_machine,
  881          SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
  882             );
  883    }
  884    else
  885    {
  886       sci_base_state_machine_change_state(
  887          &this_rnc->state_machine,
  888          SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
  889             );
  890    }
  891 
  892    return SCI_SUCCESS;
  893 }
  894 
  895 /**
  896 * This method will report a success or failure attempt to start a new task
  897 * request to the hardware.  Since all task requests are sent on the high
  898 * priority queue they can be sent when the RCN is in a TX suspend state.
  899 *
  900 * @param[in] this_rnc The remote node context which is to receive the task
  901 *       request.
  902 * @param[in] the_request The task request to be transmitted to the remote
  903 *       target device.
  904 *
  905 * @return SCI_STATUS
  906 * @retval SCI_SUCCESS
  907 */
  908 static
  909 SCI_STATUS scic_sds_remote_node_context_suspended_start_task_handler(
  910    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  911    struct SCIC_SDS_REQUEST             * the_request
  912 )
  913 {
  914    scic_sds_remote_node_context_resume(this_rnc, NULL, NULL);
  915 
  916    return SCI_SUCCESS;
  917 }
  918 
  919 // ---------------------------------------------------------------------------
  920 
  921 static
  922 SCI_STATUS scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
  923    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  924    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  925    void                                   * callback_parameter
  926 )
  927 {
  928    scic_sds_remote_node_context_setup_to_resume(
  929       this_rnc, the_callback, callback_parameter
  930          );
  931 
  932    sci_base_state_machine_change_state(
  933       &this_rnc->state_machine,
  934       SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
  935          );
  936 
  937    return SCI_FAILURE_INVALID_STATE;
  938 }
  939 
  940 // ---------------------------------------------------------------------------
  941 
  942 /**
  943 *
  944 */
  945 static
  946 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_resume_handler(
  947    SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
  948    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
  949    void                                   * callback_parameter
  950 )
  951 {
  952    scic_sds_remote_node_context_setup_to_resume(
  953       this_rnc, the_callback, callback_parameter
  954          );
  955 
  956    return SCI_SUCCESS;
  957 }
  958 
  959 /**
  960 * This method will report a success or failure attempt to start a new task
  961 * request to the hardware.  Since all task requests are sent on the high
  962 * priority queue they can be sent when the RCN is in a TX suspend state.
  963 *
  964 * @param[in] this_rnc The remote node context which is to receive the task
  965 *       request.
  966 * @param[in] the_request The task request to be transmitted to the remote
  967 *       target device.
  968 *
  969 * @return SCI_STATUS
  970 * @retval SCI_SUCCESS
  971 */
  972 static
  973 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_start_task_handler(
  974    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  975    struct SCIC_SDS_REQUEST             * the_request
  976 )
  977 {
  978    return SCI_SUCCESS;
  979 }
  980 
  981 static
  982 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_event_handler(
  983    struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
  984    U32                                   event_code
  985 )
  986 {
  987    SCI_STATUS status;
  988 
  989    switch (scu_get_event_type(event_code))
  990    {
  991       case SCU_EVENT_TL_RNC_SUSPEND_TX:
  992          sci_base_state_machine_change_state(
  993             &this_rnc->state_machine,
  994             SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
  995                );
  996 
  997          this_rnc->suspension_code = scu_get_event_specifier(event_code);
  998          status = SCI_SUCCESS;
  999          break;
 1000 
 1001       case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
 1002          sci_base_state_machine_change_state(
 1003             &this_rnc->state_machine,
 1004             SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
 1005                );
 1006 
 1007          this_rnc->suspension_code = scu_get_event_specifier(event_code);
 1008          status = SCI_SUCCESS;
 1009          break;
 1010 
 1011       default:
 1012          SCIC_LOG_WARNING((
 1013             sci_base_object_get_logger(this_rnc->device),
 1014             SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 1015                SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 1016                SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 1017             "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
 1018             this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
 1019                ));
 1020 
 1021          status = SCI_FAILURE;
 1022          break;
 1023    }
 1024 
 1025    return status;
 1026 }
 1027 
 1028 // ---------------------------------------------------------------------------
 1029 
 1030    SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS
 1031    scic_sds_remote_node_context_state_handler_table[
 1032    SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
 1033 {
 1034    // SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
 1035    {
 1036       scic_sds_remote_node_context_default_destruct_handler,
 1037       scic_sds_remote_node_context_default_suspend_handler,
 1038       scic_sds_remote_node_context_initial_state_resume_handler,
 1039       scic_sds_remote_node_context_default_start_io_handler,
 1040       scic_sds_remote_node_context_default_start_task_handler,
 1041       scic_sds_remote_node_context_default_event_handler
 1042    },
 1043    // SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
 1044    {
 1045       scic_sds_remote_node_context_general_destruct_handler,
 1046       scic_sds_remote_node_context_default_suspend_handler,
 1047       scic_sds_remote_node_context_continue_to_resume_handler,
 1048       scic_sds_remote_node_context_default_start_io_handler,
 1049       scic_sds_remote_node_context_default_start_task_handler,
 1050       scic_sds_remote_node_context_posting_state_event_handler
 1051    },
 1052    // SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
 1053    {
 1054       scic_sds_remote_node_context_invalidating_state_destruct_handler,
 1055       scic_sds_remote_node_context_default_suspend_handler,
 1056       scic_sds_remote_node_context_continue_to_resume_handler,
 1057       scic_sds_remote_node_context_default_start_io_handler,
 1058       scic_sds_remote_node_context_default_start_task_handler,
 1059       scic_sds_remote_node_context_invalidating_state_event_handler
 1060    },
 1061    // SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
 1062    {
 1063       scic_sds_remote_node_context_general_destruct_handler,
 1064       scic_sds_remote_node_context_default_suspend_handler,
 1065       scic_sds_remote_node_context_continue_to_resume_handler,
 1066       scic_sds_remote_node_context_default_start_io_handler,
 1067       scic_sds_remote_node_context_success_start_task_handler,
 1068       scic_sds_remote_node_context_resuming_state_event_handler
 1069    },
 1070    // SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
 1071    {
 1072       scic_sds_remote_node_context_general_destruct_handler,
 1073       scic_sds_remote_node_context_ready_state_suspend_handler,
 1074       scic_sds_remote_node_context_default_resume_handler,
 1075       scic_sds_remote_node_context_ready_state_start_io_handler,
 1076       scic_sds_remote_node_context_success_start_task_handler,
 1077       scic_sds_remote_node_context_ready_state_event_handler
 1078    },
 1079    // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
 1080    {
 1081       scic_sds_remote_node_context_general_destruct_handler,
 1082       scic_sds_remote_node_context_default_suspend_handler,
 1083       scic_sds_remote_node_context_tx_suspended_state_resume_handler,
 1084       scic_sds_remote_node_context_reset_required_start_io_handler,
 1085       scic_sds_remote_node_context_suspended_start_task_handler,
 1086       scic_sds_remote_node_context_default_event_handler
 1087    },
 1088    // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
 1089    {
 1090       scic_sds_remote_node_context_general_destruct_handler,
 1091       scic_sds_remote_node_context_default_suspend_handler,
 1092       scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler,
 1093       scic_sds_remote_node_context_reset_required_start_io_handler,
 1094       scic_sds_remote_node_context_suspended_start_task_handler,
 1095       scic_sds_remote_node_context_default_event_handler
 1096    },
 1097    // SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
 1098    {
 1099       scic_sds_remote_node_context_general_destruct_handler,
 1100       scic_sds_remote_node_context_default_suspend_handler,
 1101       scic_sds_remote_node_context_await_suspension_state_resume_handler,
 1102       scic_sds_remote_node_context_reset_required_start_io_handler,
 1103       scic_sds_remote_node_context_await_suspension_state_start_task_handler,
 1104       scic_sds_remote_node_context_await_suspension_state_event_handler
 1105    }
 1106 };
 1107 
 1108 //*****************************************************************************
 1109 //* REMOTE NODE CONTEXT PRIVATE METHODS
 1110 //*****************************************************************************
 1111 
 1112 /**
 1113 * This method just calls the user callback function and then resets the
 1114 * callback.
 1115 *
 1116 * @param[in out] rnc
 1117 */
 1118 static
 1119 void scic_sds_remote_node_context_notify_user(
 1120    SCIC_SDS_REMOTE_NODE_CONTEXT_T *rnc
 1121 )
 1122 {
 1123    SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK local_user_callback = rnc->user_callback;
 1124    void * local_user_cookie = rnc->user_cookie;
 1125 
 1126    //we need to set the user_callback to NULL before it is called, because
 1127    //the user callback's stack may eventually also set up a new set of
 1128    //user callback. If we nullify the user_callback after it is called,
 1129    //we are in the risk to lose the freshly set user callback.
 1130    rnc->user_callback = NULL;
 1131    rnc->user_cookie = NULL;
 1132 
 1133    if (local_user_callback != NULL)
 1134    {
 1135       (*local_user_callback)(local_user_cookie);
 1136    }
 1137 }
 1138 
 1139 /**
 1140 * This method will continue the remote node context state machine by
 1141 * requesting to resume the remote node context state machine from its current
 1142 * state.
 1143 *
 1144 * @param[in] rnc
 1145 */
 1146 static
 1147 void scic_sds_remote_node_context_continue_state_transitions(
 1148    SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc
 1149 )
 1150 {
 1151    if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
 1152    {
 1153       rnc->state_handlers->resume_handler(
 1154          rnc, rnc->user_callback, rnc->user_cookie
 1155             );
 1156    }
 1157 }
 1158 
 1159 /**
 1160 * This method will mark the rnc buffer as being valid and post the request to
 1161 * the hardware.
 1162 *
 1163 * @param[in] this_rnc The remote node context object that is to be
 1164 *            validated.
 1165 *
 1166 * @return none
 1167 */
 1168 static
 1169 void scic_sds_remote_node_context_validate_context_buffer(
 1170    SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
 1171 )
 1172 {
 1173    SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
 1174 
 1175    rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
 1176       scic_sds_remote_device_get_controller(this_rnc->device),
 1177       this_rnc->remote_node_index
 1178          );
 1179 
 1180    rnc_buffer->ssp.is_valid = TRUE;
 1181 
 1182    if (
 1183       !this_rnc->device->is_direct_attached
 1184          && this_rnc->device->target_protocols.u.bits.attached_stp_target
 1185          )
 1186    {
 1187       scic_sds_remote_device_post_request(
 1188          this_rnc->device,
 1189          SCU_CONTEXT_COMMAND_POST_RNC_96
 1190             );
 1191    }
 1192    else
 1193    {
 1194       scic_sds_remote_device_post_request(
 1195          this_rnc->device,
 1196          SCU_CONTEXT_COMMAND_POST_RNC_32
 1197             );
 1198 
 1199       if (this_rnc->device->is_direct_attached)
 1200       {
 1201          scic_sds_port_setup_transports(
 1202             this_rnc->device->owning_port,
 1203             this_rnc->remote_node_index
 1204                );
 1205       }
 1206    }
 1207 }
 1208 
 1209 /**
 1210 * This method will update the RNC buffer and post the invalidate request.
 1211 *
 1212 * @param[in] this_rnc The remote node context object that is to be
 1213 *       invalidated.
 1214 *
 1215 * @return none
 1216 */
 1217 static
 1218 void scic_sds_remote_node_context_invalidate_context_buffer(
 1219    SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
 1220 )
 1221 {
 1222    SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
 1223 
 1224    rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
 1225       scic_sds_remote_device_get_controller(this_rnc->device),
 1226       this_rnc->remote_node_index
 1227          );
 1228 
 1229    rnc_buffer->ssp.is_valid = FALSE;
 1230 
 1231    scic_sds_remote_device_post_request(
 1232       this_rnc->device,
 1233       SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
 1234          );
 1235 }
 1236 
 1237 //*****************************************************************************
 1238 //* REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
 1239 //*****************************************************************************
 1240 
 1241 /**
 1242 *
 1243 *
 1244 * @param[in] object
 1245 */
 1246 static
 1247 void scic_sds_remote_node_context_initial_state_enter(
 1248    SCI_BASE_OBJECT_T * object
 1249 )
 1250 {
 1251    SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
 1252    rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
 1253 
 1254    SET_STATE_HANDLER(
 1255       rnc,
 1256       scic_sds_remote_node_context_state_handler_table,
 1257       SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
 1258          );
 1259 
 1260    // Check to see if we have gotten back to the initial state because someone
 1261    // requested to destroy the remote node context object.
 1262    if (
 1263       rnc->state_machine.previous_state_id
 1264          == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
 1265          )
 1266    {
 1267       rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
 1268 
 1269       scic_sds_remote_node_context_notify_user(rnc);
 1270 
 1271       // Since we are destroying the remote node context deinitialize the state logging
 1272       // should we resume the remote node context the state logging will be reinitialized
 1273       // on the resume handler.
 1274       scic_sds_remote_node_context_deinitialize_state_logging(rnc);
 1275    }
 1276 }
 1277 
 1278 /**
 1279 *
 1280 *
 1281 * @param[in] object
 1282 */
 1283 static
 1284 void scic_sds_remote_node_context_posting_state_enter(
 1285    SCI_BASE_OBJECT_T * object
 1286 )
 1287 {
 1288    SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc;
 1289    this_rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
 1290 
 1291    SET_STATE_HANDLER(
 1292       this_rnc,
 1293       scic_sds_remote_node_context_state_handler_table,
 1294       SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
 1295          );
 1296 
 1297    scic_sds_remote_node_context_validate_context_buffer(this_rnc);
 1298 }
 1299 
 1300 /**
 1301 *
 1302 *
 1303 * @param[in] object
 1304 */
 1305 static
 1306 void scic_sds_remote_node_context_invalidating_state_enter(
 1307    SCI_BASE_OBJECT_T * object
 1308 )
 1309 {
 1310    SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
 1311    rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
 1312 
 1313    SET_STATE_HANDLER(
 1314       rnc,
 1315       scic_sds_remote_node_context_state_handler_table,
 1316       SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
 1317          );
 1318 
 1319    scic_sds_remote_node_context_invalidate_context_buffer(rnc);
 1320 }
 1321 
 1322 /**
 1323 *
 1324 *
 1325 * @param[in] object
 1326 */
 1327 static
 1328 void scic_sds_remote_node_context_resuming_state_enter(
 1329    SCI_BASE_OBJECT_T * object
 1330 )
 1331 {
 1332    SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
 1333    SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
 1334    rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
 1335 
 1336    SET_STATE_HANDLER(
 1337       rnc,
 1338       scic_sds_remote_node_context_state_handler_table,
 1339       SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
 1340          );
 1341 
 1342    // For direct attached SATA devices we need to clear the TLCR
 1343    // NCQ to TCi tag mapping on the phy and in cases where we
 1344    // resume because of a target reset we also need to update
 1345    // the STPTLDARNI register with the RNi of the device
 1346    scic_remote_device_get_protocols(rnc->device, &protocols);
 1347 
 1348    if (
 1349       (protocols.u.bits.attached_stp_target == 1)
 1350          && (rnc->device->is_direct_attached)
 1351          )
 1352    {
 1353       scic_sds_port_setup_transports(
 1354          rnc->device->owning_port, rnc->remote_node_index
 1355             );
 1356    }
 1357 
 1358    scic_sds_remote_device_post_request(
 1359       rnc->device,
 1360       SCU_CONTEXT_COMMAND_POST_RNC_RESUME
 1361          );
 1362 }
 1363 
 1364 /**
 1365 *
 1366 *
 1367 * @param[in] object
 1368 */
 1369 static
 1370 void scic_sds_remote_node_context_ready_state_enter(
 1371    SCI_BASE_OBJECT_T * object
 1372 )
 1373 {
 1374    SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
 1375    rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
 1376 
 1377    SET_STATE_HANDLER(
 1378       rnc,
 1379       scic_sds_remote_node_context_state_handler_table,
 1380       SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
 1381          );
 1382 
 1383    rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
 1384 
 1385    if (rnc->user_callback != NULL)
 1386    {
 1387       scic_sds_remote_node_context_notify_user(rnc);
 1388    }
 1389 }
 1390 
 1391 /**
 1392 *
 1393 *
 1394 * @param[in] object
 1395 */
 1396 static
 1397 void scic_sds_remote_node_context_tx_suspended_state_enter(
 1398    SCI_BASE_OBJECT_T * object
 1399 )
 1400 {
 1401    SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
 1402    rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
 1403 
 1404    SET_STATE_HANDLER(
 1405       rnc,
 1406       scic_sds_remote_node_context_state_handler_table,
 1407       SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
 1408          );
 1409 
 1410    scic_sds_remote_node_context_continue_state_transitions(rnc);
 1411 }
 1412 
 1413 /**
 1414 *
 1415 *
 1416 * @param[in] object
 1417 */
 1418 static
 1419 void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
 1420    SCI_BASE_OBJECT_T * object
 1421 )
 1422 {
 1423    SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
 1424    rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
 1425 
 1426    SET_STATE_HANDLER(
 1427       rnc,
 1428       scic_sds_remote_node_context_state_handler_table,
 1429       SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
 1430          );
 1431 
 1432    scic_sds_remote_node_context_continue_state_transitions(rnc);
 1433 }
 1434 
 1435 /**
 1436 *
 1437 *
 1438 * @param[in] object
 1439 */
 1440 static
 1441 void scic_sds_remote_node_context_await_suspension_state_enter(
 1442    SCI_BASE_OBJECT_T * object
 1443 )
 1444 {
 1445    SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
 1446    rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
 1447 
 1448    SET_STATE_HANDLER(
 1449       rnc,
 1450       scic_sds_remote_node_context_state_handler_table,
 1451       SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
 1452          );
 1453 }
 1454 
 1455 // ---------------------------------------------------------------------------
 1456 
 1457    SCI_BASE_STATE_T
 1458    scic_sds_remote_node_context_state_table[
 1459    SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
 1460 {
 1461    {
 1462       SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
 1463       scic_sds_remote_node_context_initial_state_enter,
 1464       NULL
 1465    },
 1466    {
 1467       SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
 1468       scic_sds_remote_node_context_posting_state_enter,
 1469       NULL
 1470    },
 1471    {
 1472       SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
 1473       scic_sds_remote_node_context_invalidating_state_enter,
 1474       NULL
 1475    },
 1476    {
 1477       SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
 1478       scic_sds_remote_node_context_resuming_state_enter,
 1479       NULL
 1480    },
 1481    {
 1482       SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
 1483       scic_sds_remote_node_context_ready_state_enter,
 1484       NULL
 1485    },
 1486    {
 1487       SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
 1488       scic_sds_remote_node_context_tx_suspended_state_enter,
 1489       NULL
 1490    },
 1491    {
 1492       SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
 1493       scic_sds_remote_node_context_tx_rx_suspended_state_enter,
 1494       NULL
 1495    },
 1496    {
 1497       SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
 1498       scic_sds_remote_node_context_await_suspension_state_enter,
 1499       NULL
 1500    }
 1501 };
 1502 

Cache object: 77b54381a81e958bac4c7c10f0cb7f15


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