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_controller.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 the SCIC_SDS_CONTROLLER
   62  *        public, protected, and private methods.
   63  */
   64 
   65 #include <dev/isci/types.h>
   66 #include <dev/isci/scil/sci_util.h>
   67 #include <dev/isci/scil/scic_controller.h>
   68 #include <dev/isci/scil/scic_port.h>
   69 #include <dev/isci/scil/scic_phy.h>
   70 #include <dev/isci/scil/scic_remote_device.h>
   71 #include <dev/isci/scil/scic_user_callback.h>
   72 #include <dev/isci/scil/scic_sds_pci.h>
   73 #include <dev/isci/scil/scic_sds_library.h>
   74 #include <dev/isci/scil/scic_sds_controller.h>
   75 #include <dev/isci/scil/scic_sds_controller_registers.h>
   76 #include <dev/isci/scil/scic_sds_port.h>
   77 #include <dev/isci/scil/scic_sds_phy.h>
   78 #include <dev/isci/scil/scic_sds_remote_device.h>
   79 #include <dev/isci/scil/scic_sds_request.h>
   80 #include <dev/isci/scil/scic_sds_logger.h>
   81 #include <dev/isci/scil/scic_sds_port_configuration_agent.h>
   82 #include <dev/isci/scil/scu_constants.h>
   83 #include <dev/isci/scil/scu_event_codes.h>
   84 #include <dev/isci/scil/scu_completion_codes.h>
   85 #include <dev/isci/scil/scu_task_context.h>
   86 #include <dev/isci/scil/scu_remote_node_context.h>
   87 #include <dev/isci/scil/scu_unsolicited_frame.h>
   88 #include <dev/isci/scil/intel_pci.h>
   89 #include <dev/isci/scil/scic_sgpio.h>
   90 #include <dev/isci/scil/scic_sds_phy_registers.h>
   91 
   92 #define SCU_CONTEXT_RAM_INIT_STALL_TIME      200
   93 #define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT  3
   94 #define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT  3
   95 
   96 #define SCU_MAX_ZPT_DWORD_INDEX              131
   97 
   98 /**
   99  * The number of milliseconds to wait for a phy to start.
  100  */
  101 #define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT      100
  102 
  103 /**
  104  * The number of milliseconds to wait while a given phy is consuming
  105  * power before allowing another set of phys to consume power.
  106  * Ultimately, this will be specified by OEM parameter.
  107  */
  108 #define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500
  109 
  110 /**
  111  * This macro will return the cycle bit of the completion queue entry
  112  */
  113 #define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000)
  114 
  115 /**
  116  * This macro will normalize the completion queue get pointer so its value
  117  * can be used as an index into an array
  118  */
  119 #define NORMALIZE_GET_POINTER(x) \
  120    ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK)
  121 
  122 /**
  123  *  This macro will normalize the completion queue put pointer so its value
  124  *  can be used as an array inde
  125  */
  126 #define NORMALIZE_PUT_POINTER(x) \
  127    ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK)
  128 
  129 
  130 /**
  131  * This macro will normalize the completion queue cycle pointer so it
  132  * matches the completion queue cycle bit
  133  */
  134 #define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \
  135    (((U32)(SMU_CQGR_CYCLE_BIT & (x))) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT))
  136 
  137 /**
  138  * This macro will normalize the completion queue event entry so its value
  139  * can be used as an index.
  140  */
  141 #define NORMALIZE_EVENT_POINTER(x) \
  142    ( \
  143         ((U32)((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK)) \
  144      >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \
  145    )
  146 
  147 /**
  148  * This macro will increment the controllers completion queue index value
  149  * and possibly toggle the cycle bit if the completion queue index wraps
  150  * back to 0.
  151  */
  152 #define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \
  153    INCREMENT_QUEUE_GET( \
  154       (index), \
  155       (cycle), \
  156       (controller)->completion_queue_entries, \
  157       SMU_CQGR_CYCLE_BIT \
  158    )
  159 
  160 /**
  161  * This macro will increment the controllers event queue index value and
  162  * possibly toggle the event cycle bit if the event queue index wraps back
  163  * to 0.
  164  */
  165 #define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \
  166    INCREMENT_QUEUE_GET( \
  167       (index), \
  168       (cycle), \
  169       (controller)->completion_event_entries, \
  170       SMU_CQGR_EVENT_CYCLE_BIT \
  171    )
  172 
  173 //****************************************************************************-
  174 //* SCIC SDS Controller Initialization Methods
  175 //****************************************************************************-
  176 
  177 /**
  178  * @brief This timer is used to start another phy after we have given up on
  179  *        the previous phy to transition to the ready state.
  180  *
  181  * @param[in] controller
  182  */
  183 static
  184 void scic_sds_controller_phy_startup_timeout_handler(
  185    void *controller
  186 )
  187 {
  188    SCI_STATUS status;
  189    SCIC_SDS_CONTROLLER_T *this_controller;
  190    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
  191 
  192    this_controller->phy_startup_timer_pending = FALSE;
  193 
  194    status = SCI_FAILURE;
  195 
  196    while (status != SCI_SUCCESS)
  197    {
  198       status = scic_sds_controller_start_next_phy(this_controller);
  199    }
  200 }
  201 
  202 /**
  203  * This method initializes the phy startup operations for controller start.
  204  *
  205  * @param this_controller
  206  */
  207 static
  208 SCI_STATUS scic_sds_controller_initialize_phy_startup(
  209    SCIC_SDS_CONTROLLER_T *this_controller
  210 )
  211 {
  212    this_controller->phy_startup_timer = scic_cb_timer_create(
  213       this_controller,
  214       scic_sds_controller_phy_startup_timeout_handler,
  215       this_controller
  216    );
  217 
  218    if (this_controller->phy_startup_timer == NULL)
  219    {
  220       return SCI_FAILURE_INSUFFICIENT_RESOURCES;
  221    }
  222    else
  223    {
  224       this_controller->next_phy_to_start = 0;
  225       this_controller->phy_startup_timer_pending = FALSE;
  226    }
  227 
  228    return SCI_SUCCESS;
  229 }
  230 
  231 /**
  232  * This method initializes the power control operations for the controller
  233  * object.
  234  *
  235  * @param this_controller
  236  */
  237 void scic_sds_controller_initialize_power_control(
  238    SCIC_SDS_CONTROLLER_T *this_controller
  239 )
  240 {
  241    this_controller->power_control.timer = scic_cb_timer_create(
  242       this_controller,
  243       scic_sds_controller_power_control_timer_handler,
  244       this_controller
  245    );
  246 
  247    memset(
  248       this_controller->power_control.requesters,
  249       0,
  250       sizeof(this_controller->power_control.requesters)
  251    );
  252 
  253    this_controller->power_control.phys_waiting = 0;
  254    this_controller->power_control.remote_devices_granted_power = 0;
  255 }
  256 
  257 // ---------------------------------------------------------------------------
  258 
  259 #define SCU_REMOTE_NODE_CONTEXT_ALIGNMENT       (32)
  260 #define SCU_TASK_CONTEXT_ALIGNMENT              (256)
  261 #define SCU_UNSOLICITED_FRAME_ADDRESS_ALIGNMENT (64)
  262 #define SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT  (1024)
  263 #define SCU_UNSOLICITED_FRAME_HEADER_ALIGNMENT  (64)
  264 
  265 // ---------------------------------------------------------------------------
  266 
  267 /**
  268  * @brief This method builds the memory descriptor table for this
  269  *        controller.
  270  *
  271  * @param[in] this_controller This parameter specifies the controller
  272  *            object for which to build the memory table.
  273  *
  274  * @return none
  275  */
  276 void scic_sds_controller_build_memory_descriptor_table(
  277    SCIC_SDS_CONTROLLER_T *this_controller
  278 )
  279 {
  280    sci_base_mde_construct(
  281       &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
  282       SCU_COMPLETION_RAM_ALIGNMENT,
  283       (sizeof(U32) * this_controller->completion_queue_entries),
  284       (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
  285    );
  286 
  287    sci_base_mde_construct(
  288       &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
  289       SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
  290       this_controller->remote_node_entries * sizeof(SCU_REMOTE_NODE_CONTEXT_T),
  291       SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
  292    );
  293 
  294    sci_base_mde_construct(
  295       &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
  296       SCU_TASK_CONTEXT_ALIGNMENT,
  297       this_controller->task_context_entries * sizeof(SCU_TASK_CONTEXT_T),
  298       SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
  299    );
  300 
  301    // The UF buffer address table size must be programmed to a power
  302    // of 2.  Find the first power of 2 that is equal to or greater then
  303    // the number of unsolicited frame buffers to be utilized.
  304    scic_sds_unsolicited_frame_control_set_address_table_count(
  305       &this_controller->uf_control
  306    );
  307 
  308    sci_base_mde_construct(
  309       &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
  310       SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
  311       scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
  312       SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
  313    );
  314 }
  315 
  316 /**
  317  * @brief This method validates the driver supplied memory descriptor
  318  *        table.
  319  *
  320  * @param[in] this_controller
  321  *
  322  * @return SCI_STATUS
  323  */
  324 SCI_STATUS scic_sds_controller_validate_memory_descriptor_table(
  325    SCIC_SDS_CONTROLLER_T *this_controller
  326 )
  327 {
  328    BOOL mde_list_valid;
  329 
  330    mde_list_valid = sci_base_mde_is_valid(
  331       &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
  332       SCU_COMPLETION_RAM_ALIGNMENT,
  333       (sizeof(U32) * this_controller->completion_queue_entries),
  334       (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
  335    );
  336 
  337    if (mde_list_valid == FALSE)
  338       return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
  339 
  340    mde_list_valid = sci_base_mde_is_valid(
  341       &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
  342       SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
  343       this_controller->remote_node_entries * sizeof(SCU_REMOTE_NODE_CONTEXT_T),
  344       SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
  345    );
  346 
  347    if (mde_list_valid == FALSE)
  348       return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
  349 
  350    mde_list_valid = sci_base_mde_is_valid(
  351       &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
  352       SCU_TASK_CONTEXT_ALIGNMENT,
  353       this_controller->task_context_entries * sizeof(SCU_TASK_CONTEXT_T),
  354       SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
  355    );
  356 
  357    if (mde_list_valid == FALSE)
  358       return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
  359 
  360    mde_list_valid = sci_base_mde_is_valid(
  361       &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
  362       SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
  363       scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
  364       SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
  365    );
  366 
  367    if (mde_list_valid == FALSE)
  368       return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
  369 
  370    return SCI_SUCCESS;
  371 }
  372 
  373 /**
  374  * @brief This method initializes the controller with the physical memory
  375  *        addresses that are used to communicate with the driver.
  376  *
  377  * @param[in] this_controller
  378  *
  379  * @return none
  380  */
  381 void scic_sds_controller_ram_initialization(
  382    SCIC_SDS_CONTROLLER_T *this_controller
  383 )
  384 {
  385    SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde;
  386 
  387    // The completion queue is actually placed in cacheable memory
  388    // Therefore it no longer comes out of memory in the MDL.
  389    mde = &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE];
  390    this_controller->completion_queue = (U32*) mde->virtual_address;
  391    SMU_CQBAR_WRITE(this_controller, mde->physical_address);
  392 
  393    // Program the location of the Remote Node Context table
  394    // into the SCU.
  395    mde = &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT];
  396    this_controller->remote_node_context_table = (SCU_REMOTE_NODE_CONTEXT_T *)
  397                                                 mde->virtual_address;
  398    SMU_RNCBAR_WRITE(this_controller, mde->physical_address);
  399 
  400    // Program the location of the Task Context table into the SCU.
  401    mde = &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT];
  402    this_controller->task_context_table = (SCU_TASK_CONTEXT_T *)
  403                                          mde->virtual_address;
  404    SMU_HTTBAR_WRITE(this_controller, mde->physical_address);
  405 
  406    mde = &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER];
  407    scic_sds_unsolicited_frame_control_construct(
  408       &this_controller->uf_control, mde, this_controller
  409    );
  410 
  411    // Inform the silicon as to the location of the UF headers and
  412    // address table.
  413    SCU_UFHBAR_WRITE(
  414       this_controller,
  415       this_controller->uf_control.headers.physical_address);
  416    SCU_PUFATHAR_WRITE(
  417       this_controller,
  418       this_controller->uf_control.address_table.physical_address);
  419 
  420    //enable the ECC correction and detection.
  421    SCU_SECR0_WRITE(
  422       this_controller,
  423       (SIGNLE_BIT_ERROR_CORRECTION_ENABLE
  424        | MULTI_BIT_ERROR_REPORTING_ENABLE
  425        | SINGLE_BIT_ERROR_REPORTING_ENABLE) );
  426    SCU_SECR1_WRITE(
  427       this_controller,
  428       (SIGNLE_BIT_ERROR_CORRECTION_ENABLE
  429        | MULTI_BIT_ERROR_REPORTING_ENABLE
  430        | SINGLE_BIT_ERROR_REPORTING_ENABLE) );
  431 }
  432 
  433 /**
  434  * @brief This method initializes the task context data for the controller.
  435  *
  436  * @param[in] this_controller
  437  *
  438  * @return none
  439  */
  440 void scic_sds_controller_assign_task_entries(
  441    SCIC_SDS_CONTROLLER_T *this_controller
  442 )
  443 {
  444    U32 task_assignment;
  445 
  446    // Assign all the TCs to function 0
  447    // TODO: Do we actually need to read this register to write it back?
  448    task_assignment = SMU_TCA_READ(this_controller, 0);
  449 
  450    task_assignment =
  451       (
  452           task_assignment
  453         | (SMU_TCA_GEN_VAL(STARTING, 0))
  454         | (SMU_TCA_GEN_VAL(ENDING,  this_controller->task_context_entries - 1))
  455         | (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE))
  456       );
  457 
  458    SMU_TCA_WRITE(this_controller, 0, task_assignment);
  459 }
  460 
  461 /**
  462  * @brief This method initializes the hardware completion queue.
  463  *
  464  * @param[in] this_controller
  465  */
  466 void scic_sds_controller_initialize_completion_queue(
  467    SCIC_SDS_CONTROLLER_T *this_controller
  468 )
  469 {
  470    U32 index;
  471    U32 completion_queue_control_value;
  472    U32 completion_queue_get_value;
  473    U32 completion_queue_put_value;
  474 
  475    this_controller->completion_queue_get = 0;
  476 
  477    completion_queue_control_value = (
  478         SMU_CQC_QUEUE_LIMIT_SET(this_controller->completion_queue_entries - 1)
  479       | SMU_CQC_EVENT_LIMIT_SET(this_controller->completion_event_entries - 1)
  480    );
  481 
  482    SMU_CQC_WRITE(this_controller, completion_queue_control_value);
  483 
  484    // Set the completion queue get pointer and enable the queue
  485    completion_queue_get_value = (
  486         (SMU_CQGR_GEN_VAL(POINTER, 0))
  487       | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0))
  488       | (SMU_CQGR_GEN_BIT(ENABLE))
  489       | (SMU_CQGR_GEN_BIT(EVENT_ENABLE))
  490    );
  491 
  492    SMU_CQGR_WRITE(this_controller, completion_queue_get_value);
  493 
  494    this_controller->completion_queue_get = completion_queue_get_value;
  495 
  496    // Set the completion queue put pointer
  497    completion_queue_put_value = (
  498         (SMU_CQPR_GEN_VAL(POINTER, 0))
  499       | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0))
  500    );
  501 
  502    SMU_CQPR_WRITE(this_controller, completion_queue_put_value);
  503 
  504    // Initialize the cycle bit of the completion queue entries
  505    for (index = 0; index < this_controller->completion_queue_entries; index++)
  506    {
  507       // If get.cycle_bit != completion_queue.cycle_bit
  508       // its not a valid completion queue entry
  509       // so at system start all entries are invalid
  510       this_controller->completion_queue[index] = 0x80000000;
  511    }
  512 }
  513 
  514 /**
  515  * @brief This method initializes the hardware unsolicited frame queue.
  516  *
  517  * @param[in] this_controller
  518  */
  519 void scic_sds_controller_initialize_unsolicited_frame_queue(
  520    SCIC_SDS_CONTROLLER_T *this_controller
  521 )
  522 {
  523    U32 frame_queue_control_value;
  524    U32 frame_queue_get_value;
  525    U32 frame_queue_put_value;
  526 
  527    // Write the queue size
  528    frame_queue_control_value =
  529       SCU_UFQC_GEN_VAL(QUEUE_SIZE, this_controller->uf_control.address_table.count);
  530 
  531    SCU_UFQC_WRITE(this_controller, frame_queue_control_value);
  532 
  533    // Setup the get pointer for the unsolicited frame queue
  534    frame_queue_get_value = (
  535          SCU_UFQGP_GEN_VAL(POINTER, 0)
  536       |  SCU_UFQGP_GEN_BIT(ENABLE_BIT)
  537       );
  538 
  539    SCU_UFQGP_WRITE(this_controller, frame_queue_get_value);
  540 
  541    // Setup the put pointer for the unsolicited frame queue
  542    frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0);
  543 
  544    SCU_UFQPP_WRITE(this_controller, frame_queue_put_value);
  545 }
  546 
  547 /**
  548  * @brief This method enables the hardware port task scheduler.
  549  *
  550  * @param[in] this_controller
  551  */
  552 void scic_sds_controller_enable_port_task_scheduler(
  553    SCIC_SDS_CONTROLLER_T *this_controller
  554 )
  555 {
  556    U32 port_task_scheduler_value;
  557 
  558    port_task_scheduler_value = SCU_PTSGCR_READ(this_controller);
  559 
  560    port_task_scheduler_value |=
  561       (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE));
  562 
  563    SCU_PTSGCR_WRITE(this_controller, port_task_scheduler_value);
  564 }
  565 
  566 // ---------------------------------------------------------------------------
  567 
  568 #ifdef ARLINGTON_BUILD
  569 /**
  570  * This method will read from the lexington status register.  This is required
  571  * as a read fence to the lexington register writes.
  572  *
  573  * @param this_controller
  574  */
  575 void scic_sds_controller_lex_status_read_fence(
  576    SCIC_SDS_CONTROLLER_T *this_controller
  577 )
  578 {
  579    U32 lex_status;
  580 
  581    // Read Fence
  582    lex_status = lex_register_read(
  583                   this_controller, this_controller->lex_registers + 0xC4);
  584 
  585    SCIC_LOG_TRACE((
  586       sci_base_object_get_logger(this_controller),
  587       SCIC_LOG_OBJECT_CONTROLLER,
  588       "Controller 0x%x lex_status = 0x%08x\n",
  589       this_controller, lex_status
  590    ));
  591 }
  592 
  593 /**
  594  * This method will initialize the arlington through the LEX_BAR.
  595  *
  596  * @param this_controller
  597  */
  598 void scic_sds_controller_lex_atux_initialization(
  599    SCIC_SDS_CONTROLLER_T *this_controller
  600 )
  601 {
  602    // 1. Reset all SCU PHY
  603    lex_register_write(
  604       this_controller, this_controller->lex_registers + 0x28, 0x0020FFFF) ;
  605 
  606    // 2. Write to LEX_CTRL
  607    lex_register_write(
  608       this_controller, this_controller->lex_registers + 0xC0, 0x00000700);
  609 
  610    scic_sds_controller_lex_status_read_fence(this_controller);
  611 
  612    // 3. Enable PCI Master
  613    lex_register_write(
  614       this_controller, this_controller->lex_registers + 0x70, 0x00000002);
  615 
  616    // 4. Enable SCU Register Clock Domain
  617    lex_register_write(
  618       this_controller, this_controller->lex_registers + 0xC0, 0x00000300);
  619 
  620    scic_sds_controller_lex_status_read_fence(this_controller);
  621 
  622    // 5.1 Release PHY-A Reg Reset
  623    lex_register_write(
  624       this_controller, this_controller->lex_registers + 0x28, 0x0000FFFF);
  625 
  626    // 5.2 Initialize the AFE for PHY-A
  627    scic_sds_controller_afe_initialization(this_controller);
  628 
  629    scic_sds_controller_lex_status_read_fence(this_controller);
  630 
  631 #if 0
  632    // 5.3 Release PHY Reg Reset
  633    lex_register_write(
  634       this_controller, this_controller->lex_registers + 0x28, 0x0000FFFF);
  635 #endif
  636 
  637    // 6.1 Release PHY-B Reg Reset
  638    lex_register_write(
  639       this_controller, this_controller->lex_registers + 0x28, 0x0040FFFF) ;
  640 
  641    // 6.2 Initialize the AFE for PHY-B
  642    scic_sds_controller_afe_initialization(this_controller);
  643 
  644    scic_sds_controller_lex_status_read_fence(this_controller);
  645 
  646 #if 0
  647    // 6.3 Release PHY-B Reg Reset
  648    lex_register_write(
  649       this_controller, this_controller->lex_registers + 0x28, 0x0040FFFF) ;
  650 #endif
  651 
  652    // 7. Enable SCU clock domaion
  653    lex_register_write(
  654       this_controller, this_controller->lex_registers + 0xC0, 0x00000100);
  655 
  656    scic_sds_controller_lex_status_read_fence(this_controller);
  657 
  658    // 8. Release LEX SCU Reset
  659    lex_register_write(
  660       this_controller, this_controller->lex_registers + 0xC0, 0x00000000);
  661 
  662    scic_sds_controller_lex_status_read_fence(this_controller);
  663 
  664 #if !defined(DISABLE_INTERRUPTS)
  665    // 8a. Set legacy interrupts (SCU INTx to PCI-x INTA)
  666    lex_register_write(
  667       this_controller, this_controller->lex_registers + 0xC0, 0x00000800);
  668 
  669    scic_sds_controller_lex_status_read_fence(this_controller);
  670 #endif
  671 
  672 #if 0
  673    // 9. Override TXOLVL
  674    //write to lex_ctrl
  675    lex_register_write(
  676       this_controller, this_controller->lex_registers + 0xC0, 0x27800000);
  677 #endif
  678 
  679    // 10. Release PHY-A & PHY-B Resets
  680    lex_register_write(
  681       this_controller, this_controller->lex_registers + 0x28, 0x0000FF77);
  682 
  683    lex_register_write(
  684       this_controller, this_controller->lex_registers + 0x28, 0x0000FF55);
  685 
  686    lex_register_write(
  687       this_controller, this_controller->lex_registers + 0x28, 0x0000FF11);
  688 
  689    lex_register_write(
  690       this_controller, this_controller->lex_registers + 0x28, 0x0000FF00);
  691 
  692    lex_register_write(
  693       this_controller, this_controller->lex_registers + 0x28, 0x0003FF00);
  694 }
  695 #endif // ARLINGTON_BUILD
  696 
  697 // ---------------------------------------------------------------------------
  698 
  699 #ifdef ARLINGTON_BUILD
  700 /**
  701  * This method enables chipwatch on the arlington board
  702  *
  703  * @param[in] this_controller
  704  */
  705 void scic_sds_controller_enable_chipwatch(
  706    SCIC_SDS_CONTROLLER_T *this_controller
  707 )
  708 {
  709    lex_register_write(
  710       this_controller, this_controller->lex_registers + 0x88, 0x09090909);
  711 
  712    lex_register_write(
  713       this_controller, this_controller->lex_registers + 0x8C, 0xcac9c862);
  714 }
  715 #endif
  716 
  717 /**
  718  * This macro is used to delay between writes to the AFE registers
  719  * during AFE initialization.
  720  */
  721 #define AFE_REGISTER_WRITE_DELAY 10
  722 
  723 /**
  724  * Initialize the AFE for this phy index.
  725  *
  726  * @todo We need to read the AFE setup from the OEM parameters
  727  *
  728  * @param[in] this_controller
  729  *
  730  * @return none
  731  */
  732 #if defined(ARLINGTON_BUILD)
  733 void scic_sds_controller_afe_initialization(
  734    SCIC_SDS_CONTROLLER_T *this_controller
  735 )
  736 {
  737    // 1. Establish Power
  738    //       Hold Bias, PLL, and RX TX in reset and powerdown
  739    //       pe_afe0_rst_n = 0
  740    //       pe_afe0_txpdn0,1,2,3 = 1
  741    //       pe_afe0_rxpdn0,1,2,3 = 1
  742    //       pe_afe0_txrst0,1,2,3_n = 0
  743    //       pe_afe0_rxrst0,1,2,3_n = 0
  744    //       wait 1us
  745    //       pe_afe0_rst_n = 1
  746    //       wait 1us
  747    scu_afe_register_write(
  748       this_controller, afe_pll_control, 0x00247506);
  749 
  750    // 2. Write 0x00000000 to AFE XCVR Ctrl2
  751    scu_afe_register_write(
  752       this_controller, afe_dfx_transceiver_status_clear, 0x00000000);
  753 
  754    // 3. afe0_override_en = 0
  755    //    afe0_pll_dis_override = 0
  756    //    afe0_tx_rst_override = 0
  757    //    afe0_pll_dis = 1
  758    //    pe_afe0_txrate = 01
  759    //    pe_afe0_rxrate = 01
  760    //    pe_afe0_txdis = 11
  761    //    pe_afe0_txoob = 1
  762    //    pe_afe0_txovlv = 9'b001110000
  763    scu_afe_register_write(
  764       this_controller, afe_transceiver_control0[0], 0x0700141e);
  765 
  766    // 4. Configure PLL Unit
  767    //    Write 0x00200506 to AFE PLL Ctrl Register 0
  768    scu_afe_register_write(this_controller, afe_pll_control,     0x00200506);
  769    scu_afe_register_write(this_controller, afe_pll_dfx_control, 0x10000080);
  770 
  771    // 5. Configure Bias Unit
  772    scu_afe_register_write(this_controller, afe_bias_control[0], 0x00124814);
  773    scu_afe_register_write(this_controller, afe_bias_control[1], 0x24900000);
  774 
  775    // 6. Configure Transceiver Units
  776    scu_afe_register_write(
  777       this_controller, afe_transceiver_control0[0], 0x0702941e);
  778 
  779    scu_afe_register_write(
  780       this_controller, afe_transceiver_control1[0], 0x0000000a);
  781 
  782    // 7. Configure RX Units
  783    scu_afe_register_write(
  784       this_controller, afe_transceiver_equalization_control[0], 0x00ba2223);
  785 
  786    scu_afe_register_write(
  787       this_controller, reserved_0028_003c[2], 0x00000000);
  788 
  789    // 8. Configure TX Units
  790    scu_afe_register_write(
  791       this_controller, afe_dfx_transmit_control_register[0], 0x03815428);
  792 
  793    // 9. Transfer control to PE signals
  794    scu_afe_register_write(
  795       this_controller, afe_dfx_transceiver_status_clear, 0x00000010);
  796 
  797    // 10. Release PLL Powerdown
  798    scu_afe_register_write(this_controller, afe_pll_control, 0x00200504);
  799 
  800    // 11. Release PLL Reset
  801    scu_afe_register_write(this_controller, afe_pll_control, 0x00200505);
  802 
  803    // 12. Wait for PLL to Lock
  804    // (afe0_comm_sta [1:0] should go to 1'b11, and
  805    //                [5:2] is 0x5, 0x6, 0x7, 0x8, or 0x9
  806    scu_afe_register_write(this_controller, afe_pll_control, 0x00200501);
  807 
  808    while ((scu_afe_register_read(this_controller, afe_common_status) & 0x03) != 0x03)
  809    {
  810       // Give time for the PLLs to lock
  811       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  812    }
  813 
  814    // 13. pe_afe0_rxpdn0 = 0
  815    //     pe_afe0_rxrst0 = 1
  816    //     pe_afe0_txrst0_n = 1
  817    //     pe_afe_txoob0_n = 0
  818    scu_afe_register_write(
  819       this_controller, afe_transceiver_control0[0], 0x07028c11);
  820 }
  821 
  822 #elif defined(PLEASANT_RIDGE_BUILD)
  823 
  824 void scic_sds_controller_afe_initialization(
  825    SCIC_SDS_CONTROLLER_T *this_controller
  826 )
  827 {
  828    U32 afe_status;
  829    U32 phy_id;
  830 
  831 #if defined(SPREADSHEET_AFE_SETTINGS)
  832    // Clear DFX Status registers
  833    scu_afe_register_write(
  834       this_controller, afe_dfx_master_control0, 0x0000000f);
  835    // Configure bias currents to normal
  836    scu_afe_register_write(
  837       this_controller, afe_bias_control, 0x0000aa00);
  838    // Enable PLL
  839    scu_afe_register_write(
  840       this_controller, afe_pll_control0, 0x80000908);
  841 
  842    // Wait for the PLL to lock
  843    do
  844    {
  845       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  846       afe_status = scu_afe_register_read(
  847                      this_controller, afe_common_block_status);
  848    }
  849    while((afe_status & 0x00001000) == 0);
  850 
  851    for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
  852    {
  853       // Initialize transceiver channels
  854       scu_afe_register_write(
  855          this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000157);
  856       // Configure transceiver modes
  857       scu_afe_register_write(
  858          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016d1a);
  859       // Configure receiver parameters
  860       scu_afe_register_write(
  861          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01501014);
  862       // Configure transmitter parameters
  863       scu_afe_register_write(
  864          this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00000000);
  865       // Configure transmitter equalization
  866       scu_afe_register_write(
  867          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0, 0x000bdd08);
  868       scu_afe_register_write(
  869          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1, 0x000ffc00);
  870       scu_afe_register_write(
  871          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2, 0x000b7c09);
  872       scu_afe_register_write(
  873          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3, 0x000afc6e);
  874       // Configure transmitter SSC parameters
  875       scu_afe_register_write(
  876          this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00000000);
  877       // Configure receiver parameters
  878       scu_afe_register_write(
  879          this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x3208903f);
  880 
  881       // Start power on sequence
  882       // Enable bias currents to transceivers and wait 200ns
  883       scu_afe_register_write(
  884          this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000154);
  885       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  886       // Take receiver out of power down and wait 200ns
  887       scu_afe_register_write(
  888          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x3801611a);
  889       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  890       // Take receiver out of reset and wait 200ns
  891       scu_afe_register_write(
  892          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x3801631a);
  893       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  894       // Take transmitter out of power down and wait 200ns
  895       scu_afe_register_write(
  896          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016318);
  897       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  898       // Take transmitter out of reset and wait 200ns
  899       scu_afe_register_write(
  900          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016319);
  901       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  902       // Take transmitter out of DC idle
  903       scu_afe_register_write(
  904          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016319);
  905       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  906    }
  907 
  908    // Transfer control to the PEs
  909    scu_afe_register_write(
  910       this_controller, afe_dfx_master_control0, 0x00010f00);
  911 #else // !defined(SPREADSHEET_AFE_SETTINGS)
  912    // These are the AFEE settings used by the SV group
  913    // Clear DFX Status registers
  914    scu_afe_register_write(
  915       this_controller, afe_dfx_master_control0, 0x0081000f);
  916    // Configure bias currents to normal
  917    scu_afe_register_write(
  918       this_controller, afe_bias_control, 0x0000aa00);
  919    // Enable PLL
  920    scu_afe_register_write(
  921       this_controller, afe_pll_control0, 0x80000908);
  922 
  923    // Wait for the PLL to lock
  924    // Note: this is done later in the SV shell script however this looks
  925    //       like the location to do this since we have enabled the PLL.
  926    do
  927    {
  928       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  929       afe_status = scu_afe_register_read(
  930                      this_controller, afe_common_block_status);
  931    }
  932    while((afe_status & 0x00001000) == 0);
  933 
  934    // Make sure BIST is disabled
  935    scu_afe_register_write(
  936       this_controller, afe_dfx_master_control1, 0x00000000);
  937    // Shorten SAS SNW lock time
  938    scu_afe_register_write(
  939       this_controller, afe_pmsn_master_control0, 0x7bd316ad);
  940 
  941    for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
  942    {
  943       // Initialize transceiver channels
  944       scu_afe_register_write(
  945          this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000174);
  946       // Configure SSC control
  947       scu_afe_register_write(
  948          this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00030000);
  949       // Configure transceiver modes
  950       scu_afe_register_write(
  951          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0000651a);
  952       // Power up TX RX and RX OOB
  953       scu_afe_register_write(
  954          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006518);
  955       // Enable RX OOB Detect
  956       scu_afe_register_write(
  957          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006518);
  958       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  959       #if 0
  960       // Configure transmitter parameters
  961       scu_afe_register_write(
  962          this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00000000);
  963       // Configure transmitter equalization
  964       scu_afe_register_write(
  965          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0, 0x000bdd08);
  966       scu_afe_register_write(
  967          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1, 0x000ffc00);
  968       scu_afe_register_write(
  969          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2, 0x000b7c09);
  970       scu_afe_register_write(
  971          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3, 0x000afc6e);
  972       // Configure transmitter SSC parameters
  973       // Power up TX RX
  974 
  975       scu_afe_register_write(
  976          this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000154);
  977       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  978 
  979       // FFE = Max
  980       scu_afe_register_write(
  981          this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x00000080);
  982       // DFE1-5 = small
  983       scu_afe_register_write(
  984          this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x01041042);
  985       // Enable DFE/FFE and freeze
  986       scu_afe_register_write(
  987          this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x320891bf);
  988       #endif
  989       // Take receiver out of power down and wait 200ns
  990       scu_afe_register_write(
  991          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006118);
  992       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  993       // TX Electrical Idle
  994       scu_afe_register_write(
  995          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006108);
  996       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
  997 
  998       // Leave DFE/FFE on
  999       scu_afe_register_write(
 1000          this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x0317108f);
 1001 
 1002       // Configure receiver parameters
 1003       scu_afe_register_write(
 1004          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01e00021);
 1005 
 1006       // Bring RX out of reset
 1007       scu_afe_register_write(
 1008          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006109);
 1009       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1010 
 1011       scu_afe_register_write(
 1012          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006009);
 1013       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1014 
 1015       scu_afe_register_write(
 1016          this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006209);
 1017       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1018    }
 1019 
 1020    // Transfer control to the PEs
 1021    scu_afe_register_write(
 1022       this_controller, afe_dfx_master_control0, 0x00010f00);
 1023 #endif
 1024 }
 1025 
 1026 #elif defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
 1027 
 1028 void scic_sds_controller_afe_initialization(
 1029    SCIC_SDS_CONTROLLER_T *this_controller
 1030 )
 1031 {
 1032    U32  afe_status;
 1033    U32  phy_id;
 1034    U8   cable_selection_mask;
 1035 
 1036    if (
 1037          (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_A0)
 1038       && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_A2)
 1039       && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_B0)
 1040       && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_C0)
 1041       && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_C1)
 1042       )
 1043    {
 1044       // A programming bug has occurred if we are attempting to
 1045       // support a PCI revision other than those listed.  Default
 1046       // to B0, and attempt to limp along if it isn't B0.
 1047       ASSERT(FALSE);
 1048       this_controller->pci_revision = SCIC_SDS_PCI_REVISION_C1;
 1049    }
 1050 
 1051    cable_selection_mask =
 1052       this_controller->oem_parameters.sds1.controller.cable_selection_mask;
 1053 
 1054    // These are the AFEE settings used by the SV group
 1055    // Clear DFX Status registers
 1056    scu_afe_register_write(
 1057       this_controller, afe_dfx_master_control0, 0x0081000f);
 1058    scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1059 
 1060    if (
 1061          (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
 1062       || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
 1063       || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
 1064       )
 1065    {
 1066       // PM Rx Equalization Save, PM SPhy Rx Acknowledgement Timer, PM Stagger Timer
 1067       scu_afe_register_write(
 1068          this_controller, afe_pmsn_master_control2, 0x0007FFFF);
 1069       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1070    }
 1071 
 1072    // Configure bias currents to normal
 1073    if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
 1074       scu_afe_register_write(this_controller, afe_bias_control, 0x00005500);
 1075    else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
 1076       scu_afe_register_write(this_controller, afe_bias_control, 0x00005A00);
 1077    else if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
 1078            || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) )
 1079       scu_afe_register_write(this_controller, afe_bias_control, 0x00005F00);
 1080    else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
 1081       scu_afe_register_write(this_controller, afe_bias_control, 0x00005500);
 1082    // For C0 the AFE BIAS Control is unchanged
 1083 
 1084    scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1085 
 1086       // Enable PLL
 1087    if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
 1088       || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
 1089    {
 1090       scu_afe_register_write(this_controller, afe_pll_control0, 0x80040908);
 1091    }
 1092    else if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
 1093            || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) )
 1094    {
 1095       scu_afe_register_write(this_controller, afe_pll_control0, 0x80040A08);
 1096    }
 1097    else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
 1098    {
 1099       scu_afe_register_write(this_controller, afe_pll_control0, 0x80000b08);
 1100       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1101       scu_afe_register_write(this_controller, afe_pll_control0, 0x00000b08);
 1102       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1103       scu_afe_register_write(this_controller, afe_pll_control0, 0x80000b08);
 1104    }
 1105 
 1106    scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1107 
 1108    // Wait for the PLL to lock
 1109    // Note: this is done later in the SV shell script however this looks
 1110    //       like the location to do this since we have enabled the PLL.
 1111    do
 1112    {
 1113       afe_status = scu_afe_register_read(
 1114                       this_controller, afe_common_block_status);
 1115       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1116    }
 1117    while((afe_status & 0x00001000) == 0);
 1118 
 1119    if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
 1120       || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
 1121    {
 1122       // Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us)
 1123       scu_afe_register_write(
 1124          this_controller, afe_pmsn_master_control0, 0x7bcc96ad);
 1125       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1126    }
 1127 
 1128    for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
 1129    {
 1130       U8 cable_length_long   = (cable_selection_mask >> phy_id) & 1;
 1131       U8 cable_length_medium = (cable_selection_mask >> (phy_id + 4)) & 1;
 1132 
 1133       if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
 1134          || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
 1135       {
 1136          // All defaults, except the Receive Word Alignament/Comma Detect
 1137          // Enable....(0xe800)
 1138          scu_afe_register_write(
 1139             this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00004512
 1140          );
 1141          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1142 
 1143          scu_afe_register_write(
 1144             this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x0050100F
 1145          );
 1146          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1147       }
 1148       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
 1149       {
 1150          // Configure transmitter SSC parameters
 1151          scu_afe_register_write(
 1152             this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00030000
 1153          );
 1154          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1155       }
 1156       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
 1157       {
 1158          // Configure transmitter SSC parameters
 1159          scu_afe_register_write(
 1160             this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00010202
 1161          );
 1162          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1163 
 1164          // All defaults, except the Receive Word Alignament/Comma Detect
 1165          // Enable....(0xe800)
 1166          scu_afe_register_write(
 1167             this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00014500
 1168          );
 1169          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1170       }
 1171       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
 1172       {
 1173          // Configure transmitter SSC parameters
 1174          scu_afe_register_write(
 1175             this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00010202
 1176          );
 1177          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1178 
 1179          // All defaults, except the Receive Word Alignament/Comma Detect
 1180          // Enable....(0xe800)
 1181          scu_afe_register_write(
 1182             this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0001C500
 1183          );
 1184          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1185       }
 1186       // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
 1187       // & increase TX int & ext bias 20%....(0xe85c)
 1188       if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
 1189       {
 1190          scu_afe_register_write(
 1191             this_controller,
 1192             scu_afe_xcvr[phy_id].afe_channel_control,
 1193             0x000003D4
 1194          );
 1195       }
 1196       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
 1197       {
 1198          scu_afe_register_write(
 1199             this_controller,
 1200             scu_afe_xcvr[phy_id].afe_channel_control,
 1201             0x000003F0
 1202          );
 1203       }
 1204       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
 1205       {
 1206          // Power down TX and RX (PWRDNTX and PWRDNRX)
 1207          scu_afe_register_write(
 1208             this_controller,
 1209             scu_afe_xcvr[phy_id].afe_channel_control,
 1210             0x000003d7
 1211          );
 1212 
 1213          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1214 
 1215          // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
 1216          // & increase TX int & ext bias 20%....(0xe85c)
 1217          scu_afe_register_write(
 1218             this_controller,
 1219             scu_afe_xcvr[phy_id].afe_channel_control,
 1220             0x000003d4
 1221          );
 1222       }
 1223       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
 1224       {
 1225          scu_afe_register_write(
 1226             this_controller,
 1227             scu_afe_xcvr[phy_id].afe_channel_control,
 1228             0x000001e7
 1229          );
 1230 
 1231          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1232 
 1233          // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
 1234          // & increase TX int & ext bias 20%....(0xe85c)
 1235          scu_afe_register_write(
 1236             this_controller,
 1237             scu_afe_xcvr[phy_id].afe_channel_control,
 1238             0x000001e4
 1239          );
 1240       }
 1241       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
 1242       {
 1243          scu_afe_register_write(
 1244             this_controller,
 1245             scu_afe_xcvr[phy_id].afe_channel_control,
 1246             cable_length_long   ? 0x000002F7 :
 1247             cable_length_medium ? 0x000001F7 : 0x000001F7
 1248          );
 1249 
 1250          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1251 
 1252          // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
 1253          // & increase TX int & ext bias 20%....(0xe85c)
 1254          scu_afe_register_write(
 1255             this_controller,
 1256             scu_afe_xcvr[phy_id].afe_channel_control,
 1257             cable_length_long   ? 0x000002F4 :
 1258             cable_length_medium ? 0x000001F4 : 0x000001F4
 1259          );
 1260       }
 1261 
 1262       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1263 
 1264       if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
 1265          || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
 1266       {
 1267          // Enable TX equalization (0xe824)
 1268          scu_afe_register_write(
 1269             this_controller,
 1270             scu_afe_xcvr[phy_id].afe_tx_control,
 1271             0x00040000
 1272          );
 1273          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1274       }
 1275 
 1276       if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
 1277          || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
 1278          || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0) )
 1279       {
 1280          // RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
 1281          // RDD=0x0(RX Detect Enabled) ....(0xe800)
 1282          scu_afe_register_write(
 1283             this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00004100);
 1284          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1285       }
 1286       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
 1287       {
 1288          scu_afe_register_write(
 1289             this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00014100);
 1290          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1291       }
 1292       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
 1293       {
 1294          scu_afe_register_write(
 1295             this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0001c100);
 1296          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1297       }
 1298 
 1299       // Leave DFE/FFE on
 1300       if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
 1301       {
 1302          scu_afe_register_write(
 1303             this_controller,
 1304             scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
 1305             0x3F09983F
 1306          );
 1307       }
 1308       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
 1309       {
 1310          scu_afe_register_write(
 1311             this_controller,
 1312             scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
 1313             0x3F11103F
 1314          );
 1315       }
 1316       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
 1317       {
 1318          scu_afe_register_write(
 1319             this_controller,
 1320             scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
 1321             0x3F11103F
 1322          );
 1323          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1324 
 1325          // Enable TX equalization (0xe824)
 1326          scu_afe_register_write(
 1327             this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
 1328       }
 1329       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
 1330       {
 1331          scu_afe_register_write(
 1332             this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01400c0f);
 1333          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1334 
 1335          scu_afe_register_write(
 1336             this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x3f6f103f);
 1337          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1338 
 1339          // Enable TX equalization (0xe824)
 1340          scu_afe_register_write(
 1341             this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
 1342       }
 1343       else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
 1344       {
 1345          scu_afe_register_write(
 1346             this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1,
 1347             cable_length_long   ? 0x01500C0C :
 1348             cable_length_medium ? 0x01400C0D : 0x02400C0D
 1349          );
 1350          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1351 
 1352          scu_afe_register_write(
 1353             this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x000003e0);
 1354          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1355 
 1356          scu_afe_register_write(
 1357             this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
 1358             cable_length_long   ? 0x33091C1F :
 1359             cable_length_medium ? 0x3315181F : 0x2B17161F
 1360          );
 1361          scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1362 
 1363          // Enable TX equalization (0xe824)
 1364          scu_afe_register_write(
 1365             this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
 1366       }
 1367 
 1368       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1369 
 1370       scu_afe_register_write(
 1371          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0,
 1372          this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control0
 1373       );
 1374       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1375 
 1376       scu_afe_register_write(
 1377          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1,
 1378          this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control1
 1379       );
 1380       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1381 
 1382       scu_afe_register_write(
 1383          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2,
 1384          this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control2
 1385       );
 1386       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1387 
 1388       scu_afe_register_write(
 1389          this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3,
 1390          this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control3
 1391       );
 1392       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1393    }
 1394 
 1395    // Transfer control to the PEs
 1396    scu_afe_register_write(
 1397       this_controller, afe_dfx_master_control0, 0x00010f00);
 1398    scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
 1399 }
 1400 #else
 1401    #error "Unsupported board type"
 1402 #endif
 1403 
 1404 //****************************************************************************-
 1405 //* SCIC SDS Controller Internal Start/Stop Routines
 1406 //****************************************************************************-
 1407 
 1408 
 1409 /**
 1410  * @brief This method will attempt to transition into the ready state
 1411  *        for the controller and indicate that the controller start
 1412  *        operation has completed if all criteria are met.
 1413  *
 1414  * @param[in,out] this_controller This parameter indicates the controller
 1415  *                object for which to transition to ready.
 1416  * @param[in]     status This parameter indicates the status value to be
 1417  *                pass into the call to scic_cb_controller_start_complete().
 1418  *
 1419  * @return none.
 1420  */
 1421 static
 1422 void scic_sds_controller_transition_to_ready(
 1423    SCIC_SDS_CONTROLLER_T *this_controller,
 1424    SCI_STATUS             status
 1425 )
 1426 {
 1427    SCIC_LOG_TRACE((
 1428       sci_base_object_get_logger(this_controller),
 1429       SCIC_LOG_OBJECT_CONTROLLER,
 1430       "scic_sds_controller_transition_to_ready(0x%x, 0x%x) enter\n",
 1431       this_controller, status
 1432    ));
 1433 
 1434    if (this_controller->parent.state_machine.current_state_id
 1435        == SCI_BASE_CONTROLLER_STATE_STARTING)
 1436    {
 1437       // We move into the ready state, because some of the phys/ports
 1438       // may be up and operational.
 1439       sci_base_state_machine_change_state(
 1440          scic_sds_controller_get_base_state_machine(this_controller),
 1441          SCI_BASE_CONTROLLER_STATE_READY
 1442       );
 1443 
 1444       scic_cb_controller_start_complete(this_controller, status);
 1445    }
 1446 }
 1447 
 1448 /**
 1449  * @brief This method is the general timeout handler for the controller.
 1450  *        It will take the correct timetout action based on the current
 1451  *        controller state
 1452  *
 1453  * @param[in] controller This parameter indicates the controller on which
 1454  *            a timeout occurred.
 1455  *
 1456  * @return none
 1457  */
 1458 void scic_sds_controller_timeout_handler(
 1459    SCI_CONTROLLER_HANDLE_T controller
 1460 )
 1461 {
 1462    SCI_BASE_CONTROLLER_STATES current_state;
 1463    SCIC_SDS_CONTROLLER_T *this_controller;
 1464    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 1465 
 1466    current_state = sci_base_state_machine_get_state(
 1467                       scic_sds_controller_get_base_state_machine(this_controller)
 1468                    );
 1469 
 1470    if (current_state == SCI_BASE_CONTROLLER_STATE_STARTING)
 1471    {
 1472       scic_sds_controller_transition_to_ready(
 1473          this_controller, SCI_FAILURE_TIMEOUT
 1474       );
 1475    }
 1476    else if (current_state == SCI_BASE_CONTROLLER_STATE_STOPPING)
 1477    {
 1478       sci_base_state_machine_change_state(
 1479          scic_sds_controller_get_base_state_machine(this_controller),
 1480          SCI_BASE_CONTROLLER_STATE_FAILED
 1481       );
 1482 
 1483       scic_cb_controller_stop_complete(controller, SCI_FAILURE_TIMEOUT);
 1484    }
 1485    else
 1486    {
 1487       /// @todo Now what do we want to do in this case?
 1488       SCIC_LOG_ERROR((
 1489          sci_base_object_get_logger(this_controller),
 1490          SCIC_LOG_OBJECT_CONTROLLER,
 1491          "Controller timer fired when controller was not in a state being timed.\n"
 1492       ));
 1493    }
 1494 }
 1495 
 1496 /**
 1497  * @brief
 1498  *
 1499  * @param[in] this_controller
 1500  *
 1501  * @return SCI_STATUS
 1502  */
 1503 SCI_STATUS scic_sds_controller_stop_ports(
 1504    SCIC_SDS_CONTROLLER_T *this_controller
 1505 )
 1506 {
 1507    U32        index;
 1508    SCI_STATUS status;
 1509    SCI_STATUS port_status;
 1510 
 1511    status = SCI_SUCCESS;
 1512 
 1513    for (index = 0; index < this_controller->logical_port_entries; index++)
 1514    {
 1515       port_status = this_controller->port_table[index].
 1516          state_handlers->parent.stop_handler(&this_controller->port_table[index].parent);
 1517       if (
 1518             (port_status != SCI_SUCCESS)
 1519          && (port_status != SCI_FAILURE_INVALID_STATE)
 1520          )
 1521       {
 1522          status = SCI_FAILURE;
 1523 
 1524          SCIC_LOG_WARNING((
 1525             sci_base_object_get_logger(this_controller),
 1526             SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
 1527             "Controller stop operation failed to stop port %d because of status %d.\n",
 1528             this_controller->port_table[index].logical_port_index, port_status
 1529          ));
 1530       }
 1531    }
 1532 
 1533    return status;
 1534 }
 1535 
 1536 /**
 1537  * @brief
 1538  *
 1539  * @param[in] this_controller
 1540  */
 1541 static
 1542 void scic_sds_controller_phy_timer_start(
 1543    SCIC_SDS_CONTROLLER_T *this_controller
 1544 )
 1545 {
 1546    scic_cb_timer_start(
 1547       this_controller,
 1548       this_controller->phy_startup_timer,
 1549       SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
 1550    );
 1551 
 1552    this_controller->phy_startup_timer_pending = TRUE;
 1553 }
 1554 
 1555 /**
 1556  * @brief
 1557  *
 1558  * @param[in] this_controller
 1559  */
 1560 void scic_sds_controller_phy_timer_stop(
 1561    SCIC_SDS_CONTROLLER_T *this_controller
 1562 )
 1563 {
 1564    scic_cb_timer_stop(
 1565       this_controller,
 1566       this_controller->phy_startup_timer
 1567    );
 1568 
 1569    this_controller->phy_startup_timer_pending = FALSE;
 1570 }
 1571 
 1572 /**
 1573  * @brief This method is called internally to determine whether the
 1574  *        controller start process is complete.  This is only true when:
 1575  *          - all links have been given an opportunity to start
 1576  *          - have no indication of a connected device
 1577  *          - have an indication of a connected device and it has
 1578  *             finished the link training process.
 1579  *
 1580  * @param[in] this_controller This parameter specifies the controller
 1581  *            object for which to start the next phy.
 1582  *
 1583  * @return BOOL
 1584  */
 1585 BOOL scic_sds_controller_is_start_complete(
 1586    SCIC_SDS_CONTROLLER_T *this_controller
 1587 )
 1588 {
 1589    U8 index;
 1590 
 1591    for (index = 0; index < SCI_MAX_PHYS; index++)
 1592    {
 1593       SCIC_SDS_PHY_T *the_phy = & this_controller->phy_table[index];
 1594 
 1595       if (
 1596             (
 1597                   this_controller->oem_parameters.sds1.controller.mode_type
 1598                == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
 1599             )
 1600          || (
 1601                (
 1602                   this_controller->oem_parameters.sds1.controller.mode_type
 1603                == SCIC_PORT_MANUAL_CONFIGURATION_MODE
 1604                )
 1605             && (scic_sds_phy_get_port(the_phy) != SCI_INVALID_HANDLE)
 1606             )
 1607          )
 1608       {
 1609          /**
 1610           * The controller start operation is complete if and only
 1611           * if:
 1612           * - all links have been given an opportunity to start
 1613           * - have no indication of a connected device
 1614           * - have an indication of a connected device and it has
 1615           *   finished the link training process.
 1616           */
 1617         if (
 1618                (
 1619                   (the_phy->is_in_link_training == FALSE)
 1620                && (the_phy->parent.state_machine.current_state_id
 1621                    == SCI_BASE_PHY_STATE_INITIAL)
 1622                )
 1623             || (
 1624                   (the_phy->is_in_link_training == FALSE)
 1625                && (the_phy->parent.state_machine.current_state_id
 1626                    == SCI_BASE_PHY_STATE_STOPPED)
 1627                )
 1628             || (
 1629                   (the_phy->is_in_link_training == TRUE)
 1630                && (the_phy->parent.state_machine.current_state_id
 1631                    == SCI_BASE_PHY_STATE_STARTING)
 1632                )
 1633             || (
 1634                   this_controller->port_agent.phy_ready_mask
 1635                   != this_controller->port_agent.phy_configured_mask
 1636                )
 1637             )
 1638          {
 1639             return FALSE;
 1640          }
 1641       }
 1642    }
 1643 
 1644    return TRUE;
 1645 }
 1646 
 1647 /**
 1648  * @brief This method is called internally by the controller object to
 1649  *        start the next phy on the controller.  If all the phys have
 1650  *        been starte, then this method will attempt to transition the
 1651  *        controller to the READY state and inform the user
 1652  *        (scic_cb_controller_start_complete()).
 1653  *
 1654  * @param[in] this_controller This parameter specifies the controller
 1655  *            object for which to start the next phy.
 1656  *
 1657  * @return SCI_STATUS
 1658  */
 1659 SCI_STATUS scic_sds_controller_start_next_phy(
 1660    SCIC_SDS_CONTROLLER_T *this_controller
 1661 )
 1662 {
 1663    SCI_STATUS status;
 1664 
 1665    status = SCI_SUCCESS;
 1666 
 1667    if (this_controller->phy_startup_timer_pending == FALSE)
 1668    {
 1669       if (this_controller->next_phy_to_start == SCI_MAX_PHYS)
 1670       {
 1671          // The controller has successfully finished the start process.
 1672          // Inform the SCI Core user and transition to the READY state.
 1673          if (scic_sds_controller_is_start_complete(this_controller) == TRUE)
 1674          {
 1675             scic_sds_controller_transition_to_ready(
 1676                this_controller, SCI_SUCCESS
 1677             );
 1678          }
 1679       }
 1680       else
 1681       {
 1682          SCIC_SDS_PHY_T * the_phy;
 1683 
 1684          the_phy = &this_controller->phy_table[this_controller->next_phy_to_start];
 1685 
 1686          if (
 1687                this_controller->oem_parameters.sds1.controller.mode_type
 1688             == SCIC_PORT_MANUAL_CONFIGURATION_MODE
 1689             )
 1690          {
 1691             if (scic_sds_phy_get_port(the_phy) == SCI_INVALID_HANDLE)
 1692             {
 1693                this_controller->next_phy_to_start++;
 1694 
 1695                // Caution recursion ahead be forwarned
 1696                //
 1697                // The PHY was never added to a PORT in MPC mode so start the next phy in sequence
 1698                // This phy will never go link up and will not draw power the OEM parameters either
 1699                // configured the phy incorrectly for the PORT or it was never assigned to a PORT
 1700                return scic_sds_controller_start_next_phy(this_controller);
 1701             }
 1702          }
 1703 
 1704          status = scic_phy_start(the_phy);
 1705 
 1706          if (status == SCI_SUCCESS)
 1707          {
 1708             scic_sds_controller_phy_timer_start(this_controller);
 1709          }
 1710          else
 1711          {
 1712             SCIC_LOG_WARNING((
 1713                sci_base_object_get_logger(this_controller),
 1714                SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PHY,
 1715                "Controller stop operation failed to stop phy %d because of status %d.\n",
 1716                this_controller->phy_table[this_controller->next_phy_to_start].phy_index,
 1717                status
 1718             ));
 1719          }
 1720 
 1721          this_controller->next_phy_to_start++;
 1722       }
 1723    }
 1724 
 1725    return status;
 1726 }
 1727 
 1728 /**
 1729  * @brief
 1730  *
 1731  * @param[in] this_controller
 1732  *
 1733  * @return SCI_STATUS
 1734  */
 1735 SCI_STATUS scic_sds_controller_stop_phys(
 1736    SCIC_SDS_CONTROLLER_T *this_controller
 1737 )
 1738 {
 1739    U32        index;
 1740    SCI_STATUS status;
 1741    SCI_STATUS phy_status;
 1742 
 1743    status = SCI_SUCCESS;
 1744 
 1745    for (index = 0; index < SCI_MAX_PHYS; index++)
 1746    {
 1747       phy_status = scic_phy_stop(&this_controller->phy_table[index]);
 1748 
 1749       if (
 1750               (phy_status != SCI_SUCCESS)
 1751            && (phy_status != SCI_FAILURE_INVALID_STATE)
 1752          )
 1753       {
 1754          status = SCI_FAILURE;
 1755 
 1756          SCIC_LOG_WARNING((
 1757             sci_base_object_get_logger(this_controller),
 1758             SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PHY,
 1759             "Controller stop operation failed to stop phy %d because of status %d.\n",
 1760             this_controller->phy_table[index].phy_index, phy_status
 1761          ));
 1762       }
 1763    }
 1764 
 1765    return status;
 1766 }
 1767 
 1768 /**
 1769  * @brief
 1770  *
 1771  * @param[in] this_controller
 1772  *
 1773  * @return SCI_STATUS
 1774  */
 1775 SCI_STATUS scic_sds_controller_stop_devices(
 1776    SCIC_SDS_CONTROLLER_T *this_controller
 1777 )
 1778 {
 1779    U32        index;
 1780    SCI_STATUS status;
 1781    SCI_STATUS device_status;
 1782 
 1783    status = SCI_SUCCESS;
 1784 
 1785    for (index = 0; index < this_controller->remote_node_entries; index++)
 1786    {
 1787       if (this_controller->device_table[index] != SCI_INVALID_HANDLE)
 1788       {
 1789          /// @todo What timeout value do we want to provide to this request?
 1790          device_status = scic_remote_device_stop(this_controller->device_table[index], 0);
 1791 
 1792          if (
 1793                  (device_status != SCI_SUCCESS)
 1794               && (device_status != SCI_FAILURE_INVALID_STATE)
 1795             )
 1796          {
 1797             SCIC_LOG_WARNING((
 1798                sci_base_object_get_logger(this_controller),
 1799                SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_SSP_REMOTE_TARGET,
 1800                "Controller stop operation failed to stop device 0x%x because of status %d.\n",
 1801                this_controller->device_table[index], device_status
 1802             ));
 1803          }
 1804       }
 1805    }
 1806 
 1807    return status;
 1808 }
 1809 
 1810 //****************************************************************************-
 1811 //* SCIC SDS Controller Power Control (Staggered Spinup)
 1812 //****************************************************************************-
 1813 
 1814 /**
 1815  * This method starts the power control timer for this controller object.
 1816  *
 1817  * @param this_controller
 1818  */
 1819 static
 1820 void scic_sds_controller_power_control_timer_start(
 1821    SCIC_SDS_CONTROLLER_T *this_controller
 1822 )
 1823 {
 1824    scic_cb_timer_start(
 1825       this_controller, this_controller->power_control.timer,
 1826       SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL
 1827    );
 1828 
 1829    this_controller->power_control.timer_started = TRUE;
 1830 }
 1831 
 1832 /**
 1833  * This method stops the power control timer for this controller object.
 1834  *
 1835  * @param this_controller
 1836  */
 1837 static
 1838 void scic_sds_controller_power_control_timer_stop(
 1839    SCIC_SDS_CONTROLLER_T *this_controller
 1840 )
 1841 {
 1842    if (this_controller->power_control.timer_started)
 1843    {
 1844       scic_cb_timer_stop(
 1845          this_controller, this_controller->power_control.timer
 1846       );
 1847 
 1848       this_controller->power_control.timer_started = FALSE;
 1849    }
 1850 }
 1851 
 1852 /**
 1853  * This method stops and starts the power control timer for this controller object.
 1854  *
 1855  * @param this_controller
 1856  */
 1857 static
 1858 void scic_sds_controller_power_control_timer_restart(
 1859    SCIC_SDS_CONTROLLER_T *this_controller
 1860 )
 1861 {
 1862    scic_sds_controller_power_control_timer_stop(this_controller);
 1863    scic_sds_controller_power_control_timer_start(this_controller);
 1864 }
 1865 
 1866 
 1867 /**
 1868  * @brief
 1869  *
 1870  * @param[in] controller
 1871  */
 1872 void scic_sds_controller_power_control_timer_handler(
 1873    void *controller
 1874 )
 1875 {
 1876    SCIC_SDS_CONTROLLER_T *this_controller;
 1877    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 1878 
 1879    this_controller->power_control.remote_devices_granted_power = 0;
 1880 
 1881    if (this_controller->power_control.phys_waiting == 0)
 1882    {
 1883       this_controller->power_control.timer_started = FALSE;
 1884    }
 1885    else
 1886    {
 1887       SCIC_SDS_PHY_T *the_phy = NULL;
 1888       U8 i;
 1889 
 1890       for (i=0;
 1891               (i < SCI_MAX_PHYS)
 1892            && (this_controller->power_control.phys_waiting != 0);
 1893            i++)
 1894       {
 1895          if (this_controller->power_control.requesters[i] != NULL)
 1896          {
 1897             if ( this_controller->power_control.remote_devices_granted_power <
 1898                  this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up
 1899                )
 1900             {
 1901                the_phy = this_controller->power_control.requesters[i];
 1902                this_controller->power_control.requesters[i] = NULL;
 1903                this_controller->power_control.phys_waiting--;
 1904                this_controller->power_control.remote_devices_granted_power ++;
 1905                scic_sds_phy_consume_power_handler(the_phy);
 1906 
 1907                if (the_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
 1908                {
 1909                   U8 j;
 1910                   SCIC_SDS_PHY_T * current_requester_phy;
 1911 
 1912                   for (j = 0; j < SCI_MAX_PHYS; j++)
 1913                   {
 1914                      current_requester_phy = this_controller->power_control.requesters[j];
 1915 
 1916                      //Search the power_control queue to see if there are other phys attached to
 1917                      //the same remote device. If found, take all of them out of await_sas_power state.
 1918                      if (current_requester_phy != NULL &&
 1919                          current_requester_phy != the_phy &&
 1920                          current_requester_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high
 1921                             == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high &&
 1922                          current_requester_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low
 1923                             == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low)
 1924                      {
 1925                         this_controller->power_control.requesters[j] = NULL;
 1926                         this_controller->power_control.phys_waiting--;
 1927                         scic_sds_phy_consume_power_handler(current_requester_phy);
 1928                      }
 1929                   }
 1930                }
 1931             }
 1932             else
 1933             {
 1934                break;
 1935             }
 1936          }
 1937       }
 1938 
 1939       // It doesn't matter if the power list is empty, we need to start the
 1940       // timer in case another phy becomes ready.
 1941       scic_sds_controller_power_control_timer_start(this_controller);
 1942    }
 1943 }
 1944 
 1945 /**
 1946  * @brief This method inserts the phy in the stagger spinup control queue.
 1947  *
 1948  * @param[in] this_controller
 1949  * @param[in] the_phy
 1950  */
 1951 void scic_sds_controller_power_control_queue_insert(
 1952    SCIC_SDS_CONTROLLER_T *this_controller,
 1953    SCIC_SDS_PHY_T        *the_phy
 1954 )
 1955 {
 1956    ASSERT (the_phy != NULL);
 1957 
 1958    if( this_controller->power_control.remote_devices_granted_power <
 1959        this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up
 1960      )
 1961    {
 1962       this_controller->power_control.remote_devices_granted_power ++;
 1963       scic_sds_phy_consume_power_handler(the_phy);
 1964 
 1965       //stop and start the power_control timer. When the timer fires, the
 1966       //no_of_devices_granted_power will be set to 0
 1967       scic_sds_controller_power_control_timer_restart (this_controller);
 1968    }
 1969    else
 1970    {
 1971       //there are phys, attached to the same sas address as this phy, are already
 1972       //in READY state, this phy don't need wait.
 1973       U8 i;
 1974       SCIC_SDS_PHY_T * current_phy;
 1975       for(i = 0; i < SCI_MAX_PHYS; i++)
 1976       {
 1977          current_phy = &this_controller->phy_table[i];
 1978 
 1979          if (current_phy->parent.state_machine.current_state_id == SCI_BASE_PHY_STATE_READY &&
 1980              current_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS &&
 1981              current_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high
 1982                 == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high &&
 1983              current_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low
 1984                 == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low)
 1985          {
 1986             scic_sds_phy_consume_power_handler(the_phy);
 1987             break;
 1988          }
 1989       }
 1990 
 1991       if (i == SCI_MAX_PHYS)
 1992       {
 1993          //Add the phy in the waiting list
 1994          this_controller->power_control.requesters[the_phy->phy_index] = the_phy;
 1995          this_controller->power_control.phys_waiting++;
 1996       }
 1997    }
 1998 }
 1999 
 2000 /**
 2001  * @brief This method removes the phy from the stagger spinup control
 2002  *        queue.
 2003  *
 2004  * @param[in] this_controller
 2005  * @param[in] the_phy
 2006  */
 2007 void scic_sds_controller_power_control_queue_remove(
 2008    SCIC_SDS_CONTROLLER_T *this_controller,
 2009    SCIC_SDS_PHY_T        *the_phy
 2010 )
 2011 {
 2012    ASSERT (the_phy != NULL);
 2013 
 2014    if (this_controller->power_control.requesters[the_phy->phy_index] != NULL)
 2015    {
 2016       this_controller->power_control.phys_waiting--;
 2017    }
 2018 
 2019    this_controller->power_control.requesters[the_phy->phy_index] = NULL;
 2020 }
 2021 
 2022 //****************************************************************************-
 2023 //* SCIC SDS Controller Completion Routines
 2024 //****************************************************************************-
 2025 
 2026 /**
 2027  * @brief This method returns a TRUE value if the completion queue has
 2028  *        entries that can be processed
 2029  *
 2030  * @param[in] this_controller
 2031  *
 2032  * @return BOOL
 2033  * @retval TRUE if the completion queue has entries to process
 2034  *         FALSE if the completion queue has no entries to process
 2035  */
 2036 static
 2037 BOOL scic_sds_controller_completion_queue_has_entries(
 2038    SCIC_SDS_CONTROLLER_T *this_controller
 2039 )
 2040 {
 2041    U32 get_value = this_controller->completion_queue_get;
 2042    U32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK;
 2043    if (
 2044            NORMALIZE_GET_POINTER_CYCLE_BIT(get_value)
 2045         == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
 2046       )
 2047    {
 2048       return TRUE;
 2049    }
 2050 
 2051    return FALSE;
 2052 }
 2053 
 2054 // ---------------------------------------------------------------------------
 2055 
 2056 /**
 2057  * @brief This method processes a task completion notification.  This is
 2058  *        called from within the controller completion handler.
 2059  *
 2060  * @param[in] this_controller
 2061  * @param[in] completion_entry
 2062  *
 2063  * @return none
 2064  */
 2065 static
 2066 void scic_sds_controller_task_completion(
 2067    SCIC_SDS_CONTROLLER_T *this_controller,
 2068    U32                   completion_entry
 2069 )
 2070 {
 2071    U32 index;
 2072    SCIC_SDS_REQUEST_T *io_request;
 2073 
 2074    index = SCU_GET_COMPLETION_INDEX(completion_entry);
 2075    io_request = this_controller->io_request_table[index];
 2076 
 2077    // Make sure that we really want to process this IO request
 2078    if (
 2079            (io_request != SCI_INVALID_HANDLE)
 2080         && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)
 2081         && (
 2082                 scic_sds_io_tag_get_sequence(io_request->io_tag)
 2083              == this_controller->io_request_sequence[index]
 2084            )
 2085       )
 2086    {
 2087       // Yep this is a valid io request pass it along to the io request handler
 2088       scic_sds_io_request_tc_completion(io_request, completion_entry);
 2089    }
 2090 }
 2091 
 2092 /**
 2093  * @brief This method processes an SDMA completion event.  This is called
 2094  *        from within the controller completion handler.
 2095  *
 2096  * @param[in] this_controller
 2097  * @param[in] completion_entry
 2098  *
 2099  * @return none
 2100  */
 2101 static
 2102 void scic_sds_controller_sdma_completion(
 2103    SCIC_SDS_CONTROLLER_T *this_controller,
 2104    U32                   completion_entry
 2105 )
 2106 {
 2107    U32 index;
 2108    SCIC_SDS_REQUEST_T       *io_request;
 2109    SCIC_SDS_REMOTE_DEVICE_T *device;
 2110 
 2111    index = SCU_GET_COMPLETION_INDEX(completion_entry);
 2112 
 2113    switch (scu_get_command_request_type(completion_entry))
 2114    {
 2115    case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC:
 2116    case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC:
 2117       io_request = this_controller->io_request_table[index];
 2118       SCIC_LOG_ERROR((
 2119          sci_base_object_get_logger(this_controller),
 2120            SCIC_LOG_OBJECT_CONTROLLER
 2121          | SCIC_LOG_OBJECT_SMP_IO_REQUEST
 2122          | SCIC_LOG_OBJECT_SSP_IO_REQUEST
 2123          | SCIC_LOG_OBJECT_STP_IO_REQUEST,
 2124          "SCIC SDS Completion type SDMA %x for io request %x\n",
 2125          completion_entry,
 2126          io_request
 2127       ));
 2128       /// @todo For a post TC operation we need to fail the IO request
 2129       break;
 2130 
 2131    case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC:
 2132    case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC:
 2133    case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC:
 2134       device = this_controller->device_table[index];
 2135       SCIC_LOG_ERROR((
 2136          sci_base_object_get_logger(this_controller),
 2137            SCIC_LOG_OBJECT_CONTROLLER
 2138          | SCIC_LOG_OBJECT_SSP_REMOTE_TARGET
 2139          | SCIC_LOG_OBJECT_SMP_REMOTE_TARGET
 2140          | SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 2141          "SCIC SDS Completion type SDMA %x for remote device %x\n",
 2142          completion_entry,
 2143          device
 2144       ));
 2145       /// @todo For a port RNC operation we need to fail the device
 2146       break;
 2147 
 2148    default:
 2149       SCIC_LOG_ERROR((
 2150          sci_base_object_get_logger(this_controller),
 2151          SCIC_LOG_OBJECT_CONTROLLER,
 2152          "SCIC SDS Completion unknown SDMA completion type %x\n",
 2153          completion_entry
 2154       ));
 2155       break;
 2156    }
 2157 
 2158    /// This is an unexpected completion type and is un-recoverable
 2159    /// Transition to the failed state and wait for a controller reset
 2160    sci_base_state_machine_change_state(
 2161       scic_sds_controller_get_base_state_machine(this_controller),
 2162       SCI_BASE_CONTROLLER_STATE_FAILED
 2163    );
 2164 }
 2165 
 2166 /**
 2167  * This method processes an unsolicited frame message.  This is called from
 2168  * within the controller completion handler.
 2169  *
 2170  * @param[in] this_controller
 2171  * @param[in] completion_entry
 2172  *
 2173  * @return none
 2174  */
 2175 static
 2176 void scic_sds_controller_unsolicited_frame(
 2177    SCIC_SDS_CONTROLLER_T *this_controller,
 2178    U32                   completion_entry
 2179 )
 2180 {
 2181    U32 index;
 2182    U32 frame_index;
 2183 
 2184    SCU_UNSOLICITED_FRAME_HEADER_T * frame_header;
 2185    SCIC_SDS_PHY_T                 * phy;
 2186    SCIC_SDS_REMOTE_DEVICE_T       * device;
 2187 
 2188    SCI_STATUS result = SCI_FAILURE;
 2189 
 2190    frame_index = SCU_GET_FRAME_INDEX(completion_entry);
 2191 
 2192    frame_header
 2193       = this_controller->uf_control.buffers.array[frame_index].header;
 2194    this_controller->uf_control.buffers.array[frame_index].state
 2195       = UNSOLICITED_FRAME_IN_USE;
 2196 
 2197    if (SCU_GET_FRAME_ERROR(completion_entry))
 2198    {
 2199       /// @todo If the IAF frame or SIGNATURE FIS frame has an error will
 2200       ///       this cause a problem? We expect the phy initialization will
 2201       ///       fail if there is an error in the frame.
 2202       scic_sds_controller_release_frame(this_controller, frame_index);
 2203       return;
 2204    }
 2205 
 2206    if (frame_header->is_address_frame)
 2207    {
 2208       index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
 2209       phy = &this_controller->phy_table[index];
 2210       if (phy != NULL)
 2211       {
 2212          result = scic_sds_phy_frame_handler(phy, frame_index);
 2213       }
 2214    }
 2215    else
 2216    {
 2217 
 2218       index = SCU_GET_COMPLETION_INDEX(completion_entry);
 2219 
 2220       if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
 2221       {
 2222          // This is a signature fis or a frame from a direct attached SATA
 2223          // device that has not yet been created.  In either case forwared
 2224          // the frame to the PE and let it take care of the frame data.
 2225          index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
 2226          phy = &this_controller->phy_table[index];
 2227          result = scic_sds_phy_frame_handler(phy, frame_index);
 2228       }
 2229       else
 2230       {
 2231          if (index < this_controller->remote_node_entries)
 2232             device = this_controller->device_table[index];
 2233          else
 2234             device = NULL;
 2235 
 2236          if (device != NULL)
 2237             result = scic_sds_remote_device_frame_handler(device, frame_index);
 2238          else
 2239             scic_sds_controller_release_frame(this_controller, frame_index);
 2240       }
 2241    }
 2242 
 2243    if (result != SCI_SUCCESS)
 2244    {
 2245       /// @todo Is there any reason to report some additional error message
 2246       ///       when we get this failure notifiction?
 2247    }
 2248 }
 2249 
 2250 /**
 2251  * @brief This method processes an event completion entry.  This is called
 2252  *        from within the controller completion handler.
 2253  *
 2254  * @param[in] this_controller
 2255  * @param[in] completion_entry
 2256  *
 2257  * @return none
 2258  */
 2259 static
 2260 void scic_sds_controller_event_completion(
 2261    SCIC_SDS_CONTROLLER_T *this_controller,
 2262    U32                   completion_entry
 2263 )
 2264 {
 2265    U32 index;
 2266    SCIC_SDS_REQUEST_T       *io_request;
 2267    SCIC_SDS_REMOTE_DEVICE_T *device;
 2268    SCIC_SDS_PHY_T           *phy;
 2269 
 2270    index = SCU_GET_COMPLETION_INDEX(completion_entry);
 2271 
 2272    switch (scu_get_event_type(completion_entry))
 2273    {
 2274    case SCU_EVENT_TYPE_SMU_COMMAND_ERROR:
 2275       /// @todo The driver did something wrong and we need to fix the condtion.
 2276       SCIC_LOG_ERROR((
 2277          sci_base_object_get_logger(this_controller),
 2278          SCIC_LOG_OBJECT_CONTROLLER,
 2279          "SCIC Controller 0x%x received SMU command error 0x%x\n",
 2280          this_controller, completion_entry
 2281       ));
 2282       break;
 2283 
 2284    case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR:
 2285        // report fatal memory error
 2286        this_controller->parent.error = SCI_CONTROLLER_FATAL_MEMORY_ERROR;
 2287 
 2288        sci_base_state_machine_change_state(
 2289           scic_sds_controller_get_base_state_machine(this_controller),
 2290           SCI_BASE_CONTROLLER_STATE_FAILED
 2291        );
 2292 
 2293        //continue as in following events
 2294    case SCU_EVENT_TYPE_SMU_PCQ_ERROR:
 2295    case SCU_EVENT_TYPE_SMU_ERROR:
 2296       SCIC_LOG_ERROR((
 2297          sci_base_object_get_logger(this_controller),
 2298          SCIC_LOG_OBJECT_CONTROLLER,
 2299          "SCIC Controller 0x%x received fatal controller event 0x%x\n",
 2300          this_controller, completion_entry
 2301       ));
 2302       break;
 2303 
 2304    case SCU_EVENT_TYPE_TRANSPORT_ERROR:
 2305       io_request = this_controller->io_request_table[index];
 2306       scic_sds_io_request_event_handler(io_request, completion_entry);
 2307       break;
 2308 
 2309    case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
 2310       switch (scu_get_event_specifier(completion_entry))
 2311       {
 2312       case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE:
 2313       case SCU_EVENT_SPECIFIC_TASK_TIMEOUT:
 2314          io_request = this_controller->io_request_table[index];
 2315          if (io_request != SCI_INVALID_HANDLE)
 2316          {
 2317             scic_sds_io_request_event_handler(io_request, completion_entry);
 2318          }
 2319          else
 2320          {
 2321             SCIC_LOG_WARNING((
 2322                sci_base_object_get_logger(this_controller),
 2323                SCIC_LOG_OBJECT_CONTROLLER |
 2324                SCIC_LOG_OBJECT_SMP_IO_REQUEST |
 2325                SCIC_LOG_OBJECT_SSP_IO_REQUEST |
 2326                SCIC_LOG_OBJECT_STP_IO_REQUEST,
 2327                "SCIC Controller 0x%x received event 0x%x for io request object that doesnt exist.\n",
 2328                this_controller, completion_entry
 2329             ));
 2330          }
 2331          break;
 2332 
 2333       case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT:
 2334          device = this_controller->device_table[index];
 2335          if (device != SCI_INVALID_HANDLE)
 2336          {
 2337             scic_sds_remote_device_event_handler(device, completion_entry);
 2338          }
 2339          else
 2340          {
 2341             SCIC_LOG_WARNING((
 2342                sci_base_object_get_logger(this_controller),
 2343                SCIC_LOG_OBJECT_CONTROLLER |
 2344                SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 2345                SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 2346                SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 2347                "SCIC Controller 0x%x received event 0x%x for remote device object that doesnt exist.\n",
 2348                this_controller, completion_entry
 2349             ));
 2350          }
 2351          break;
 2352       }
 2353       break;
 2354 
 2355    case SCU_EVENT_TYPE_BROADCAST_CHANGE:
 2356       // direct the broadcast change event to the phy first and then let
 2357       // the phy redirect the broadcast change to the port object
 2358    case SCU_EVENT_TYPE_ERR_CNT_EVENT:
 2359       // direct error counter event to the phy object since that is where
 2360       // we get the event notification.  This is a type 4 event.
 2361    case SCU_EVENT_TYPE_OSSP_EVENT:
 2362       index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
 2363       phy = &this_controller->phy_table[index];
 2364       scic_sds_phy_event_handler(phy, completion_entry);
 2365       break;
 2366 
 2367    case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
 2368    case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
 2369    case SCU_EVENT_TYPE_RNC_OPS_MISC:
 2370       if (index < this_controller->remote_node_entries)
 2371       {
 2372          device = this_controller->device_table[index];
 2373 
 2374          if (device != NULL)
 2375          {
 2376             scic_sds_remote_device_event_handler(device, completion_entry);
 2377          }
 2378       }
 2379       else
 2380       {
 2381          SCIC_LOG_ERROR((
 2382             sci_base_object_get_logger(this_controller),
 2383             SCIC_LOG_OBJECT_CONTROLLER |
 2384             SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
 2385             SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
 2386             SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
 2387             "SCIC Controller 0x%x received event 0x%x for remote device object 0x%0x that doesnt exist.\n",
 2388             this_controller, completion_entry, index
 2389          ));
 2390       }
 2391       break;
 2392 
 2393    default:
 2394       SCIC_LOG_WARNING((
 2395          sci_base_object_get_logger(this_controller),
 2396          SCIC_LOG_OBJECT_CONTROLLER,
 2397          "SCIC Controller received unknown event code %x\n",
 2398          completion_entry
 2399       ));
 2400       break;
 2401    }
 2402 }
 2403 
 2404 /**
 2405  * @brief This method is a private routine for processing the completion
 2406  *        queue entries.
 2407  *
 2408  * @param[in] this_controller
 2409  *
 2410  * @return none
 2411  */
 2412 static
 2413 void scic_sds_controller_process_completions(
 2414    SCIC_SDS_CONTROLLER_T *this_controller
 2415 )
 2416 {
 2417    U32 completion_count = 0;
 2418    U32 completion_entry;
 2419    U32 get_index;
 2420    U32 get_cycle;
 2421    U32 event_index;
 2422    U32 event_cycle;
 2423 
 2424    SCIC_LOG_TRACE((
 2425       sci_base_object_get_logger(this_controller),
 2426       SCIC_LOG_OBJECT_CONTROLLER,
 2427       "scic_sds_controller_process_completions(0x%x) enter\n",
 2428       this_controller
 2429    ));
 2430 
 2431    SCIC_LOG_TRACE((
 2432       sci_base_object_get_logger(this_controller),
 2433       SCIC_LOG_OBJECT_COMPLETION_QUEUE,
 2434       "completion queue beginning get : 0x%08x\n",
 2435       this_controller->completion_queue_get
 2436    ));
 2437 
 2438    // Get the component parts of the completion queue
 2439    get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
 2440    get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
 2441 
 2442    event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
 2443    event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
 2444 
 2445    while (
 2446                NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
 2447             == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
 2448          )
 2449    {
 2450       completion_count++;
 2451 
 2452       completion_entry = this_controller->completion_queue[get_index];
 2453       INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
 2454 
 2455       SCIC_LOG_TRACE((
 2456          sci_base_object_get_logger(this_controller),
 2457          SCIC_LOG_OBJECT_COMPLETION_QUEUE,
 2458          "completion queue entry : 0x%08x\n",
 2459          completion_entry
 2460       ));
 2461 
 2462       switch (SCU_GET_COMPLETION_TYPE(completion_entry))
 2463       {
 2464       case SCU_COMPLETION_TYPE_TASK:
 2465          scic_sds_controller_task_completion(this_controller, completion_entry);
 2466          break;
 2467 
 2468       case SCU_COMPLETION_TYPE_SDMA:
 2469          scic_sds_controller_sdma_completion(this_controller, completion_entry);
 2470          break;
 2471 
 2472       case SCU_COMPLETION_TYPE_UFI:
 2473          scic_sds_controller_unsolicited_frame(this_controller, completion_entry);
 2474          break;
 2475 
 2476       case SCU_COMPLETION_TYPE_EVENT:
 2477          scic_sds_controller_event_completion(this_controller, completion_entry);
 2478          break;
 2479 
 2480       case SCU_COMPLETION_TYPE_NOTIFY:
 2481          // Presently we do the same thing with a notify event that we do with the
 2482          // other event codes.
 2483          INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
 2484          scic_sds_controller_event_completion(this_controller, completion_entry);
 2485          break;
 2486 
 2487       default:
 2488          SCIC_LOG_WARNING((
 2489             sci_base_object_get_logger(this_controller),
 2490             SCIC_LOG_OBJECT_CONTROLLER,
 2491             "SCIC Controller received unknown completion type %x\n",
 2492             completion_entry
 2493          ));
 2494          break;
 2495       }
 2496    }
 2497 
 2498    // Update the get register if we completed one or more entries
 2499    if (completion_count > 0)
 2500    {
 2501       this_controller->completion_queue_get =
 2502            SMU_CQGR_GEN_BIT(ENABLE)
 2503          | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
 2504          | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
 2505          | get_cycle   | SMU_CQGR_GEN_VAL(POINTER, get_index)  ;
 2506 
 2507       SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
 2508    }
 2509 
 2510    SCIC_LOG_TRACE((
 2511       sci_base_object_get_logger(this_controller),
 2512       SCIC_LOG_OBJECT_COMPLETION_QUEUE,
 2513       "completion queue ending get : 0x%08x\n",
 2514       this_controller->completion_queue_get
 2515    ));
 2516 
 2517 }
 2518 
 2519 /**
 2520  * @brief This method is a private routine for processing the completion
 2521  *        queue entries.
 2522  *
 2523  * @param[in] this_controller
 2524  *
 2525  * @return none
 2526  */
 2527 static
 2528 void scic_sds_controller_transitioned_process_completions(
 2529    SCIC_SDS_CONTROLLER_T * this_controller
 2530 )
 2531 {
 2532    U32 completion_count = 0;
 2533    U32 completion_entry;
 2534    U32 get_index;
 2535    U32 get_cycle;
 2536    U32 event_index;
 2537    U32 event_cycle;
 2538 
 2539    SCIC_LOG_TRACE((
 2540       sci_base_object_get_logger(this_controller),
 2541       SCIC_LOG_OBJECT_CONTROLLER,
 2542       "scic_sds_controller_transitioned_process_completions(0x%x) enter\n",
 2543       this_controller
 2544    ));
 2545 
 2546    SCIC_LOG_TRACE((
 2547       sci_base_object_get_logger(this_controller),
 2548       SCIC_LOG_OBJECT_COMPLETION_QUEUE,
 2549       "completion queue beginning get : 0x%08x\n",
 2550       this_controller->completion_queue_get
 2551    ));
 2552 
 2553    // Get the component parts of the completion queue
 2554    get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
 2555    get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
 2556 
 2557    event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
 2558    event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
 2559 
 2560    while (
 2561                NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
 2562             == COMPLETION_QUEUE_CYCLE_BIT(
 2563                   this_controller->completion_queue[get_index])
 2564          )
 2565    {
 2566       completion_count++;
 2567 
 2568       completion_entry = this_controller->completion_queue[get_index];
 2569       INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
 2570 
 2571       SCIC_LOG_TRACE((
 2572          sci_base_object_get_logger(this_controller),
 2573          SCIC_LOG_OBJECT_COMPLETION_QUEUE,
 2574          "completion queue entry : 0x%08x\n",
 2575          completion_entry
 2576       ));
 2577 
 2578       switch (SCU_GET_COMPLETION_TYPE(completion_entry))
 2579       {
 2580       case SCU_COMPLETION_TYPE_TASK:
 2581          scic_sds_controller_task_completion(this_controller, completion_entry);
 2582       break;
 2583 
 2584       case SCU_COMPLETION_TYPE_NOTIFY:
 2585          INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
 2586          // Fall-through
 2587 
 2588       case SCU_COMPLETION_TYPE_EVENT:
 2589       case SCU_COMPLETION_TYPE_SDMA:
 2590       case SCU_COMPLETION_TYPE_UFI:
 2591       default:
 2592          SCIC_LOG_WARNING((
 2593             sci_base_object_get_logger(this_controller),
 2594             SCIC_LOG_OBJECT_CONTROLLER,
 2595             "SCIC Controller ignoring completion type %x\n",
 2596             completion_entry
 2597          ));
 2598       break;
 2599       }
 2600    }
 2601 
 2602    // Update the get register if we completed one or more entries
 2603    if (completion_count > 0)
 2604    {
 2605       this_controller->completion_queue_get =
 2606            SMU_CQGR_GEN_BIT(ENABLE)
 2607          | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
 2608          | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
 2609          | get_cycle   | SMU_CQGR_GEN_VAL(POINTER, get_index)  ;
 2610 
 2611       SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
 2612    }
 2613 
 2614    SCIC_LOG_TRACE((
 2615       sci_base_object_get_logger(this_controller),
 2616       SCIC_LOG_OBJECT_COMPLETION_QUEUE,
 2617       "completion queue ending get : 0x%08x\n",
 2618       this_controller->completion_queue_get
 2619    ));
 2620 }
 2621 
 2622 //****************************************************************************-
 2623 //* SCIC SDS Controller Interrupt and Completion functions
 2624 //****************************************************************************-
 2625 
 2626 /**
 2627  * @brief This method provides standard (common) processing of interrupts
 2628  *        for polling and legacy based interrupts.
 2629  *
 2630  * @param[in] controller
 2631  * @param[in] interrupt_status
 2632  *
 2633  * @return This method returns a boolean (BOOL) indication as to
 2634  *         whether an completions are pending to be processed.
 2635  * @retval TRUE if an interrupt is to be processed
 2636  * @retval FALSE if no interrupt was pending
 2637  */
 2638 static
 2639 BOOL scic_sds_controller_standard_interrupt_handler(
 2640    SCIC_SDS_CONTROLLER_T *this_controller,
 2641    U32                    interrupt_status
 2642 )
 2643 {
 2644    BOOL  is_completion_needed = FALSE;
 2645 
 2646    SCIC_LOG_TRACE((
 2647       sci_base_object_get_logger(this_controller),
 2648       SCIC_LOG_OBJECT_CONTROLLER,
 2649       "scic_sds_controller_standard_interrupt_handler(0x%d,0x%d) enter\n",
 2650       this_controller, interrupt_status
 2651    ));
 2652 
 2653    if (
 2654          (interrupt_status & SMU_ISR_QUEUE_ERROR)
 2655       || (
 2656             (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
 2657          && (!scic_sds_controller_completion_queue_has_entries(this_controller))
 2658          )
 2659       )
 2660    {
 2661       // We have a fatal error on the read of the completion queue bar
 2662       // OR
 2663       // We have a fatal error there is nothing in the completion queue
 2664       // but we have a report from the hardware that the queue is full
 2665       /// @todo how do we request the a controller reset
 2666       is_completion_needed = TRUE;
 2667       this_controller->encountered_fatal_error = TRUE;
 2668    }
 2669 
 2670    if (scic_sds_controller_completion_queue_has_entries(this_controller))
 2671    {
 2672       is_completion_needed = TRUE;
 2673    }
 2674 
 2675    return is_completion_needed;
 2676 }
 2677 
 2678 /**
 2679  * @brief This is the method provided to handle polling for interrupts
 2680  *        for the controller object.
 2681  *
 2682  * @param[in] controller
 2683  *
 2684  * @return BOOL
 2685  * @retval TRUE if an interrupt is to be processed
 2686  * @retval FALSE if no interrupt was pending
 2687  */
 2688 static
 2689 BOOL scic_sds_controller_polling_interrupt_handler(
 2690    SCI_CONTROLLER_HANDLE_T controller
 2691 )
 2692 {
 2693    U32                    interrupt_status;
 2694    SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
 2695 
 2696    SCIC_LOG_TRACE((
 2697       sci_base_object_get_logger(controller),
 2698       SCIC_LOG_OBJECT_CONTROLLER,
 2699       "scic_sds_controller_polling_interrupt_handler(0x%d) enter\n",
 2700       controller
 2701    ));
 2702 
 2703    /*
 2704     * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the hardware
 2705     * indicates nothing is pending. Since we are not being called from a real
 2706     * interrupt, we don't want to confuse the hardware by servicing the
 2707     * completion queue before the hardware indicates it is ready. We'll
 2708     * simply wait for another polling interval and check again.
 2709     */
 2710    interrupt_status = SMU_ISR_READ(this_controller);
 2711    if ((interrupt_status &
 2712          (SMU_ISR_COMPLETION |
 2713           SMU_ISR_QUEUE_ERROR |
 2714           SMU_ISR_QUEUE_SUSPEND)) == 0)
 2715    {
 2716       return FALSE;
 2717    }
 2718 
 2719    return scic_sds_controller_standard_interrupt_handler(
 2720              controller, interrupt_status
 2721           );
 2722 }
 2723 
 2724 /**
 2725  * @brief This is the method provided to handle completions when interrupt
 2726  *        polling is in use.
 2727  *
 2728  * @param[in] controller
 2729  *
 2730  * @return none
 2731  */
 2732 static
 2733 void scic_sds_controller_polling_completion_handler(
 2734    SCI_CONTROLLER_HANDLE_T controller
 2735 )
 2736 {
 2737    SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 2738 
 2739    SCIC_LOG_TRACE((
 2740       sci_base_object_get_logger(controller),
 2741       SCIC_LOG_OBJECT_CONTROLLER,
 2742       "scic_sds_controller_polling_completion_handler(0x%d) enter\n",
 2743       controller
 2744    ));
 2745 
 2746    if (this_controller->encountered_fatal_error == TRUE)
 2747    {
 2748       SCIC_LOG_ERROR((
 2749          sci_base_object_get_logger(this_controller),
 2750          SCIC_LOG_OBJECT_CONTROLLER,
 2751          "SCIC Controller has encountered a fatal error.\n"
 2752       ));
 2753 
 2754       sci_base_state_machine_change_state(
 2755          scic_sds_controller_get_base_state_machine(this_controller),
 2756          SCI_BASE_CONTROLLER_STATE_FAILED
 2757       );
 2758    }
 2759    else if (scic_sds_controller_completion_queue_has_entries(this_controller))
 2760    {
 2761       if (this_controller->restrict_completions == FALSE)
 2762          scic_sds_controller_process_completions(this_controller);
 2763       else
 2764          scic_sds_controller_transitioned_process_completions(this_controller);
 2765    }
 2766 
 2767    /*
 2768     * The interrupt handler does not adjust the CQ's
 2769     * get pointer.  So, SCU's INTx pin stays asserted during the
 2770     * interrupt handler even though it tries to clear the interrupt
 2771     * source.  Therefore, the completion handler must ensure that the
 2772     * interrupt source is cleared.  Otherwise, we get a spurious
 2773     * interrupt for which the interrupt handler will not issue a
 2774     * corresponding completion event. Also, we unmask interrupts.
 2775     */
 2776    SMU_ISR_WRITE(
 2777       this_controller,
 2778       (U32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)
 2779    );
 2780 }
 2781 
 2782 #if !defined(DISABLE_INTERRUPTS)
 2783 /**
 2784  * @brief This is the method provided to handle legacy interrupts for the
 2785  *        controller object.
 2786  *
 2787  * @param[in] controller
 2788  *
 2789  * @return BOOL
 2790  * @retval TRUE if an interrupt is processed
 2791  *         FALSE if no interrupt was processed
 2792  */
 2793 static
 2794 BOOL scic_sds_controller_legacy_interrupt_handler(
 2795    SCI_CONTROLLER_HANDLE_T controller
 2796 )
 2797 {
 2798    U32                    interrupt_status;
 2799    BOOL                   is_completion_needed;
 2800    SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
 2801 
 2802    interrupt_status     = SMU_ISR_READ(this_controller);
 2803    is_completion_needed = scic_sds_controller_standard_interrupt_handler(
 2804                              this_controller, interrupt_status
 2805                           );
 2806 
 2807    return is_completion_needed;
 2808 }
 2809 
 2810 
 2811 /**
 2812  * @brief This is the method provided to handle legacy completions it is
 2813  *        expected that the SCI User will call this completion handler
 2814  *        anytime the interrupt handler reports that it has handled an
 2815  *        interrupt.
 2816  *
 2817  * @param[in] controller
 2818  *
 2819  * @return none
 2820  */
 2821 static
 2822 void scic_sds_controller_legacy_completion_handler(
 2823    SCI_CONTROLLER_HANDLE_T controller
 2824 )
 2825 {
 2826    SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 2827 
 2828    SCIC_LOG_TRACE((
 2829       sci_base_object_get_logger(controller),
 2830       SCIC_LOG_OBJECT_CONTROLLER,
 2831       "scic_sds_controller_legacy_completion_handler(0x%d) enter\n",
 2832       controller
 2833    ));
 2834 
 2835    scic_sds_controller_polling_completion_handler(controller);
 2836 
 2837    SMU_IMR_WRITE(this_controller, 0x00000000);
 2838 
 2839 #ifdef IMR_READ_FENCE
 2840    {
 2841       volatile U32 int_mask_value = 0;
 2842       ULONG count = 0;
 2843 
 2844       /*
 2845        * Temporary code since we have seen with legacy interrupts
 2846        * that interrupts are still masked after clearing the mask
 2847        * above. This may be an Arlington problem or it may be an
 2848        * old driver problem.  Presently this code is turned off
 2849        * since we have not seen this problem recently.
 2850        */
 2851       do
 2852       {
 2853          int_mask_value = SMU_IMR_READ(this_controler);
 2854 
 2855          if (count++ > 10)
 2856          {
 2857             #ifdef ALLOW_ENTER_DEBUGGER
 2858             __debugbreak();
 2859             #endif
 2860             break;
 2861          }
 2862       } while (int_mask_value != 0);
 2863    }
 2864 #endif
 2865 }
 2866 
 2867 /**
 2868  * @brief This is the method provided to handle an MSIX interrupt message
 2869  *        when there is just a single MSIX message being provided by the
 2870  *        hardware.  This mode of operation is single vector mode.
 2871  *
 2872  * @param[in] controller
 2873  *
 2874  * @return BOOL
 2875  * @retval TRUE if an interrupt is processed
 2876  *         FALSE if no interrupt was processed
 2877  */
 2878 static
 2879 BOOL scic_sds_controller_single_vector_interrupt_handler(
 2880    SCI_CONTROLLER_HANDLE_T controller
 2881 )
 2882 {
 2883    U32 interrupt_status;
 2884    SCIC_SDS_CONTROLLER_T *this_controller;
 2885    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 2886 
 2887    // Mask the interrupts
 2888    // There is a race in the hardware that could cause us not to be notified
 2889    // of an interrupt completion if we do not take this step.  We will unmask
 2890    // the interrupts in the completion routine.
 2891    SMU_IMR_WRITE(this_controller, 0xFFFFFFFF);
 2892 
 2893    interrupt_status = SMU_ISR_READ(this_controller);
 2894    interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
 2895 
 2896    if (
 2897            (interrupt_status == 0)
 2898         && scic_sds_controller_completion_queue_has_entries(this_controller)
 2899       )
 2900    {
 2901       // There is at least one completion queue entry to process so we can
 2902       // return a success and ignore for now the case of an error interrupt
 2903       SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
 2904 
 2905       return TRUE;
 2906    }
 2907 
 2908 
 2909    if (interrupt_status != 0)
 2910    {
 2911       // There is an error interrupt pending so let it through and handle
 2912       // in the callback
 2913       return TRUE;
 2914    }
 2915 
 2916    // Clear any offending interrupts since we could not find any to handle
 2917    // and unmask them all
 2918    SMU_ISR_WRITE(this_controller, 0x00000000);
 2919    SMU_IMR_WRITE(this_controller, 0x00000000);
 2920 
 2921    return FALSE;
 2922 }
 2923 
 2924 /**
 2925  * @brief This is the method provided to handle completions for a single
 2926  *        MSIX message.
 2927  *
 2928  * @param[in] controller
 2929  */
 2930 static
 2931 void scic_sds_controller_single_vector_completion_handler(
 2932    SCI_CONTROLLER_HANDLE_T controller
 2933 )
 2934 {
 2935    U32 interrupt_status;
 2936    SCIC_SDS_CONTROLLER_T *this_controller;
 2937    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 2938 
 2939    SCIC_LOG_TRACE((
 2940       sci_base_object_get_logger(controller),
 2941       SCIC_LOG_OBJECT_CONTROLLER,
 2942       "scic_sds_controller_single_vector_completion_handler(0x%d) enter\n",
 2943       controller
 2944    ));
 2945 
 2946    interrupt_status = SMU_ISR_READ(this_controller);
 2947    interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
 2948 
 2949    if (interrupt_status & SMU_ISR_QUEUE_ERROR)
 2950    {
 2951       SCIC_LOG_ERROR((
 2952          sci_base_object_get_logger(this_controller),
 2953          SCIC_LOG_OBJECT_CONTROLLER,
 2954          "SCIC Controller has encountered a fatal error.\n"
 2955       ));
 2956 
 2957       // We have a fatal condition and must reset the controller
 2958       // Leave the interrupt mask in place and get the controller reset
 2959       sci_base_state_machine_change_state(
 2960          scic_sds_controller_get_base_state_machine(this_controller),
 2961          SCI_BASE_CONTROLLER_STATE_FAILED
 2962       );
 2963       return;
 2964    }
 2965 
 2966    if (
 2967            (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
 2968         && !scic_sds_controller_completion_queue_has_entries(this_controller)
 2969       )
 2970    {
 2971       SCIC_LOG_ERROR((
 2972          sci_base_object_get_logger(this_controller),
 2973          SCIC_LOG_OBJECT_CONTROLLER,
 2974          "SCIC Controller has encountered a fatal error.\n"
 2975       ));
 2976 
 2977       // We have a fatal condtion and must reset the controller
 2978       // Leave the interrupt mask in place and get the controller reset
 2979       sci_base_state_machine_change_state(
 2980          scic_sds_controller_get_base_state_machine(this_controller),
 2981          SCI_BASE_CONTROLLER_STATE_FAILED
 2982       );
 2983       return;
 2984    }
 2985 
 2986    if (scic_sds_controller_completion_queue_has_entries(this_controller))
 2987    {
 2988       scic_sds_controller_process_completions(this_controller);
 2989 
 2990       // We dont care which interrupt got us to processing the completion queu
 2991       // so clear them both.
 2992       SMU_ISR_WRITE(
 2993          this_controller,
 2994          (SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND)
 2995       );
 2996    }
 2997 
 2998    SMU_IMR_WRITE(this_controller, 0x00000000);
 2999 }
 3000 
 3001 /**
 3002  * @brief This is the method provided to handle a MSIX message for a normal
 3003  *        completion.
 3004  *
 3005  * @param[in] controller
 3006  *
 3007  * @return BOOL
 3008  * @retval TRUE if an interrupt is processed
 3009  *         FALSE if no interrupt was processed
 3010  */
 3011 static
 3012 BOOL scic_sds_controller_normal_vector_interrupt_handler(
 3013    SCI_CONTROLLER_HANDLE_T controller
 3014 )
 3015 {
 3016    SCIC_SDS_CONTROLLER_T *this_controller;
 3017    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 3018 
 3019    if (scic_sds_controller_completion_queue_has_entries(this_controller))
 3020    {
 3021       return TRUE;
 3022    }
 3023    else
 3024    {
 3025       // we have a spurious interrupt it could be that we have already
 3026       // emptied the completion queue from a previous interrupt
 3027       SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
 3028 
 3029       // There is a race in the hardware that could cause us not to be notified
 3030       // of an interrupt completion if we do not take this step.  We will mask
 3031       // then unmask the interrupts so if there is another interrupt pending
 3032       // the clearing of the interrupt source we get the next interrupt message.
 3033       SMU_IMR_WRITE(this_controller, 0xFF000000);
 3034       SMU_IMR_WRITE(this_controller, 0x00000000);
 3035    }
 3036 
 3037    return FALSE;
 3038 }
 3039 
 3040 /**
 3041  * @brief This is the method provided to handle the completions for a
 3042  *        normal MSIX message.
 3043  *
 3044  * @param[in] controller
 3045  */
 3046 static
 3047 void scic_sds_controller_normal_vector_completion_handler(
 3048    SCI_CONTROLLER_HANDLE_T controller
 3049 )
 3050 {
 3051    SCIC_SDS_CONTROLLER_T *this_controller;
 3052    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 3053 
 3054    SCIC_LOG_TRACE((
 3055       sci_base_object_get_logger(controller),
 3056       SCIC_LOG_OBJECT_CONTROLLER,
 3057       "scic_sds_controller_normal_vector_completion_handler(0x%d) enter\n",
 3058       controller
 3059    ));
 3060 
 3061    // Empty out the completion queue
 3062    if (scic_sds_controller_completion_queue_has_entries(this_controller))
 3063    {
 3064       scic_sds_controller_process_completions(this_controller);
 3065    }
 3066 
 3067    // Clear the interrupt and enable all interrupts again
 3068    SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
 3069    // Could we write the value of SMU_ISR_COMPLETION?
 3070    SMU_IMR_WRITE(this_controller, 0xFF000000);
 3071    SMU_IMR_WRITE(this_controller, 0x00000000);
 3072 }
 3073 
 3074 /**
 3075  * @brief This is the method provided to handle the error MSIX message
 3076  *        interrupt.  This is the normal operating mode for the hardware if
 3077  *        MSIX is enabled.
 3078  *
 3079  * @param[in] controller
 3080  *
 3081  * @return BOOL
 3082  * @retval TRUE if an interrupt is processed
 3083  *         FALSE if no interrupt was processed
 3084  */
 3085 static
 3086 BOOL scic_sds_controller_error_vector_interrupt_handler(
 3087    SCI_CONTROLLER_HANDLE_T controller
 3088 )
 3089 {
 3090    U32 interrupt_status;
 3091    SCIC_SDS_CONTROLLER_T *this_controller;
 3092    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 3093 
 3094 
 3095    interrupt_status = SMU_ISR_READ(this_controller);
 3096    interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
 3097 
 3098    if (interrupt_status != 0)
 3099    {
 3100       // There is an error interrupt pending so let it through and handle
 3101       // in the callback
 3102       return TRUE;
 3103    }
 3104 
 3105    // There is a race in the hardware that could cause us not to be notified
 3106    // of an interrupt completion if we do not take this step.  We will mask
 3107    // then unmask the error interrupts so if there was another interrupt
 3108    // pending we will be notified.
 3109    // Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)?
 3110    SMU_IMR_WRITE(this_controller, 0x000000FF);
 3111    SMU_IMR_WRITE(this_controller, 0x00000000);
 3112 
 3113    return FALSE;
 3114 }
 3115 
 3116 /**
 3117  * @brief This is the method provided to handle the error completions when
 3118  *        the hardware is using two MSIX messages.
 3119  *
 3120  * @param[in] controller
 3121  */
 3122 static
 3123 void scic_sds_controller_error_vector_completion_handler(
 3124    SCI_CONTROLLER_HANDLE_T controller
 3125 )
 3126 {
 3127    U32 interrupt_status;
 3128    SCIC_SDS_CONTROLLER_T *this_controller;
 3129    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 3130 
 3131    SCIC_LOG_TRACE((
 3132       sci_base_object_get_logger(controller),
 3133       SCIC_LOG_OBJECT_CONTROLLER,
 3134       "scic_sds_controller_error_vector_completion_handler(0x%d) enter\n",
 3135       controller
 3136    ));
 3137 
 3138    interrupt_status = SMU_ISR_READ(this_controller);
 3139 
 3140    if (
 3141             (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
 3142          && scic_sds_controller_completion_queue_has_entries(this_controller)
 3143       )
 3144    {
 3145       scic_sds_controller_process_completions(this_controller);
 3146 
 3147       SMU_ISR_WRITE(this_controller, SMU_ISR_QUEUE_SUSPEND);
 3148    }
 3149    else
 3150    {
 3151       SCIC_LOG_ERROR((
 3152          sci_base_object_get_logger(this_controller),
 3153          SCIC_LOG_OBJECT_CONTROLLER,
 3154          "SCIC Controller reports CRC error on completion ISR %x\n",
 3155          interrupt_status
 3156       ));
 3157 
 3158       sci_base_state_machine_change_state(
 3159          scic_sds_controller_get_base_state_machine(this_controller),
 3160          SCI_BASE_CONTROLLER_STATE_FAILED
 3161       );
 3162 
 3163       return;
 3164    }
 3165 
 3166    // If we dont process any completions I am not sure that we want to do this.
 3167    // We are in the middle of a hardware fault and should probably be reset.
 3168    SMU_IMR_WRITE(this_controller, 0x00000000);
 3169 }
 3170 
 3171 #endif // !defined(DISABLE_INTERRUPTS)
 3172 
 3173 //****************************************************************************-
 3174 //* SCIC SDS Controller External Methods
 3175 //****************************************************************************-
 3176 
 3177 /**
 3178  * @brief This method returns the sizeof the SCIC SDS Controller Object
 3179  *
 3180  * @return U32
 3181  */
 3182 U32 scic_sds_controller_get_object_size(void)
 3183 {
 3184    return sizeof(SCIC_SDS_CONTROLLER_T);
 3185 }
 3186 
 3187 /**
 3188  * This method returns the minimum number of timers that are required by the
 3189  * controller object.  This will include required timers for phys and ports.
 3190  *
 3191  * @return U32
 3192  * @retval The minimum number of timers that are required to make this
 3193  *         controller operational.
 3194  */
 3195 U32 scic_sds_controller_get_min_timer_count(void)
 3196 {
 3197    return   SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT
 3198           + scic_sds_port_get_min_timer_count()
 3199           + scic_sds_phy_get_min_timer_count();
 3200 }
 3201 
 3202 /**
 3203  * This method returns the maximum number of timers that are required by the
 3204  * controller object.  This will include required timers for phys and ports.
 3205  *
 3206  * @return U32
 3207  * @retval The maximum number of timers that will be used by the controller
 3208  *         object
 3209  */
 3210 U32 scic_sds_controller_get_max_timer_count(void)
 3211 {
 3212    return   SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT
 3213           + scic_sds_port_get_max_timer_count()
 3214           + scic_sds_phy_get_max_timer_count();
 3215 }
 3216 
 3217 /**
 3218  * @brief
 3219  *
 3220  * @param[in] this_controller
 3221  * @param[in] the_port
 3222  * @param[in] the_phy
 3223  *
 3224  * @return none
 3225  */
 3226 void scic_sds_controller_link_up(
 3227    SCIC_SDS_CONTROLLER_T *this_controller,
 3228    SCIC_SDS_PORT_T       *the_port,
 3229    SCIC_SDS_PHY_T        *the_phy
 3230 )
 3231 {
 3232    if (this_controller->state_handlers->link_up_handler != NULL)
 3233    {
 3234       this_controller->state_handlers->link_up_handler(
 3235          this_controller, the_port, the_phy);
 3236    }
 3237    else
 3238    {
 3239       SCIC_LOG_INFO((
 3240          sci_base_object_get_logger(this_controller),
 3241          SCIC_LOG_OBJECT_CONTROLLER,
 3242          "SCIC Controller linkup event from phy %d in unexpected state %d\n",
 3243          the_phy->phy_index,
 3244          sci_base_state_machine_get_state(
 3245             scic_sds_controller_get_base_state_machine(this_controller))
 3246       ));
 3247    }
 3248 }
 3249 
 3250 /**
 3251  * @brief
 3252  *
 3253  * @param[in] this_controller
 3254  * @param[in] the_port
 3255  * @param[in] the_phy
 3256  */
 3257 void scic_sds_controller_link_down(
 3258    SCIC_SDS_CONTROLLER_T *this_controller,
 3259    SCIC_SDS_PORT_T       *the_port,
 3260    SCIC_SDS_PHY_T        *the_phy
 3261 )
 3262 {
 3263    if (this_controller->state_handlers->link_down_handler != NULL)
 3264    {
 3265       this_controller->state_handlers->link_down_handler(
 3266          this_controller, the_port, the_phy);
 3267    }
 3268    else
 3269    {
 3270       SCIC_LOG_INFO((
 3271          sci_base_object_get_logger(this_controller),
 3272          SCIC_LOG_OBJECT_CONTROLLER,
 3273          "SCIC Controller linkdown event from phy %d in unexpected state %d\n",
 3274          the_phy->phy_index,
 3275          sci_base_state_machine_get_state(
 3276             scic_sds_controller_get_base_state_machine(this_controller))
 3277       ));
 3278    }
 3279 }
 3280 
 3281 /**
 3282  * @brief This method is called by the remote device to inform the controller
 3283  *        that this remote device has started.
 3284  *
 3285  * @param[in] this_controller
 3286  * @param[in] the_device
 3287  */
 3288 void scic_sds_controller_remote_device_started(
 3289    SCIC_SDS_CONTROLLER_T    * this_controller,
 3290    SCIC_SDS_REMOTE_DEVICE_T * the_device
 3291 )
 3292 {
 3293    if (this_controller->state_handlers->remote_device_started_handler != NULL)
 3294    {
 3295       this_controller->state_handlers->remote_device_started_handler(
 3296          this_controller, the_device
 3297       );
 3298    }
 3299    else
 3300    {
 3301       SCIC_LOG_INFO((
 3302          sci_base_object_get_logger(this_controller),
 3303          SCIC_LOG_OBJECT_CONTROLLER,
 3304          "SCIC Controller 0x%x remote device started event from device 0x%x in unexpected state %d\n",
 3305          this_controller,
 3306          the_device,
 3307          sci_base_state_machine_get_state(
 3308             scic_sds_controller_get_base_state_machine(this_controller))
 3309       ));
 3310    }
 3311 }
 3312 
 3313 /**
 3314  * @brief This is a helper method to determine if any remote devices on this
 3315  *        controller are still in the stopping state.
 3316  *
 3317  * @param[in] this_controller
 3318  */
 3319 BOOL scic_sds_controller_has_remote_devices_stopping(
 3320    SCIC_SDS_CONTROLLER_T * this_controller
 3321 )
 3322 {
 3323    U32 index;
 3324 
 3325    for (index = 0; index < this_controller->remote_node_entries; index++)
 3326    {
 3327       if (
 3328             (this_controller->device_table[index] != NULL)
 3329          && (
 3330                this_controller->device_table[index]->parent.state_machine.current_state_id
 3331             == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
 3332             )
 3333          )
 3334       {
 3335          return TRUE;
 3336       }
 3337    }
 3338 
 3339    return FALSE;
 3340 }
 3341 
 3342 /**
 3343  * @brief This method is called by the remote device to inform the controller
 3344  *        object that the remote device has stopped.
 3345  *
 3346  * @param[in] this_controller
 3347  * @param[in] the_device
 3348  */
 3349 void scic_sds_controller_remote_device_stopped(
 3350    SCIC_SDS_CONTROLLER_T    * this_controller,
 3351    SCIC_SDS_REMOTE_DEVICE_T * the_device
 3352 )
 3353 {
 3354    if (this_controller->state_handlers->remote_device_stopped_handler != NULL)
 3355    {
 3356       this_controller->state_handlers->remote_device_stopped_handler(
 3357          this_controller, the_device
 3358       );
 3359    }
 3360    else
 3361    {
 3362       SCIC_LOG_INFO((
 3363          sci_base_object_get_logger(this_controller),
 3364          SCIC_LOG_OBJECT_CONTROLLER,
 3365          "SCIC Controller 0x%x remote device stopped event from device 0x%x in unexpected state %d\n",
 3366          this_controller,
 3367          the_device,
 3368          sci_base_state_machine_get_state(
 3369             scic_sds_controller_get_base_state_machine(this_controller))
 3370       ));
 3371    }
 3372 }
 3373 
 3374 /**
 3375  * @brief This method will write to the SCU PCP register the request value.
 3376  *        The method is used to suspend/resume ports, devices, and phys.
 3377  *
 3378  * @param[in] this_controller
 3379  * @param[in] request
 3380  */
 3381 void scic_sds_controller_post_request(
 3382    SCIC_SDS_CONTROLLER_T *this_controller,
 3383    U32                    request
 3384 )
 3385 {
 3386    SCIC_LOG_INFO((
 3387       sci_base_object_get_logger(this_controller),
 3388       SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_COMPLETION_QUEUE,
 3389       "SCIC Controller 0x%08x post request 0x%08x\n",
 3390       this_controller, request
 3391    ));
 3392 
 3393    SMU_PCP_WRITE(this_controller, request);
 3394 }
 3395 
 3396 /**
 3397  * @brief This method will copy the soft copy of the task context into
 3398  *        the physical memory accessible by the controller.
 3399  *
 3400  * @note After this call is made the SCIC_SDS_IO_REQUEST object will
 3401  *       always point to the physical memory version of the task context.
 3402  *       Thus, all subsequent updates to the task context are performed in
 3403  *       the TC table (i.e. DMAable memory).
 3404  *
 3405  * @param[in]  this_controller This parameter specifies the controller for
 3406  *             which to copy the task context.
 3407  * @param[in]  this_request This parameter specifies the request for which
 3408  *             the task context is being copied.
 3409  *
 3410  * @return none
 3411  */
 3412 void scic_sds_controller_copy_task_context(
 3413    SCIC_SDS_CONTROLLER_T *this_controller,
 3414    SCIC_SDS_REQUEST_T    *this_request
 3415 )
 3416 {
 3417    SCU_TASK_CONTEXT_T *task_context_buffer;
 3418 
 3419    task_context_buffer = scic_sds_controller_get_task_context_buffer(
 3420                             this_controller, this_request->io_tag
 3421                          );
 3422 
 3423    memcpy(
 3424       task_context_buffer,
 3425       this_request->task_context_buffer,
 3426       SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, sgl_snapshot_ac)
 3427    );
 3428 
 3429    // Now that the soft copy of the TC has been copied into the TC
 3430    // table accessible by the silicon.  Thus, any further changes to
 3431    // the TC (e.g. TC termination) occur in the appropriate location.
 3432    this_request->task_context_buffer = task_context_buffer;
 3433 }
 3434 
 3435 /**
 3436  * @brief This method returns the task context buffer for the given io tag.
 3437  *
 3438  * @param[in] this_controller
 3439  * @param[in] io_tag
 3440  *
 3441  * @return struct SCU_TASK_CONTEXT*
 3442  */
 3443 SCU_TASK_CONTEXT_T * scic_sds_controller_get_task_context_buffer(
 3444    SCIC_SDS_CONTROLLER_T * this_controller,
 3445    U16                     io_tag
 3446 )
 3447 {
 3448    U16 task_index = scic_sds_io_tag_get_index(io_tag);
 3449 
 3450    if (task_index < this_controller->task_context_entries)
 3451    {
 3452       return &this_controller->task_context_table[task_index];
 3453    }
 3454 
 3455    return NULL;
 3456 }
 3457 
 3458 /**
 3459  * @brief This method returnst the sequence value from the io tag value
 3460  *
 3461  * @param[in] this_controller
 3462  * @param[in] io_tag
 3463  *
 3464  * @return U16
 3465  */
 3466 U16 scic_sds_controller_get_io_sequence_from_tag(
 3467    SCIC_SDS_CONTROLLER_T *this_controller,
 3468    U16                    io_tag
 3469 )
 3470 {
 3471    return scic_sds_io_tag_get_sequence(io_tag);
 3472 }
 3473 
 3474 /**
 3475  * @brief This method returns the IO request associated with the tag value
 3476  *
 3477  * @param[in] this_controller
 3478  * @param[in] io_tag
 3479  *
 3480  * @return SCIC_SDS_IO_REQUEST_T*
 3481  * @retval NULL if there is no valid IO request at the tag value
 3482  */
 3483 SCIC_SDS_REQUEST_T *scic_sds_controller_get_io_request_from_tag(
 3484    SCIC_SDS_CONTROLLER_T *this_controller,
 3485    U16                    io_tag
 3486 )
 3487 {
 3488    U16 task_index;
 3489    U16 task_sequence;
 3490 
 3491    task_index = scic_sds_io_tag_get_index(io_tag);
 3492 
 3493    if (task_index  < this_controller->task_context_entries)
 3494    {
 3495       if (this_controller->io_request_table[task_index] != SCI_INVALID_HANDLE)
 3496       {
 3497          task_sequence = scic_sds_io_tag_get_sequence(io_tag);
 3498 
 3499          if (task_sequence == this_controller->io_request_sequence[task_index])
 3500          {
 3501             return this_controller->io_request_table[task_index];
 3502          }
 3503       }
 3504    }
 3505 
 3506    return SCI_INVALID_HANDLE;
 3507 }
 3508 
 3509 /**
 3510  * @brief This method allocates remote node index and the reserves the
 3511  *        remote node context space for use. This method can fail if there
 3512  *        are no more remote node index available.
 3513  *
 3514  * @param[in] this_controller This is the controller object which contains
 3515  *            the set of free remote node ids
 3516  * @param[in] the_devce This is the device object which is requesting the a
 3517  *            remote node id
 3518  * @param[out] node_id This is the remote node id that is assigned to the
 3519  *             device if one is available
 3520  *
 3521  * @return SCI_STATUS
 3522  * @retval SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote
 3523  *         node index available.
 3524  */
 3525 SCI_STATUS scic_sds_controller_allocate_remote_node_context(
 3526    SCIC_SDS_CONTROLLER_T    * this_controller,
 3527    SCIC_SDS_REMOTE_DEVICE_T * the_device,
 3528    U16                      * node_id
 3529 )
 3530 {
 3531    U16 node_index;
 3532    U32 remote_node_count = scic_sds_remote_device_node_count(the_device);
 3533 
 3534    node_index = scic_sds_remote_node_table_allocate_remote_node(
 3535                   &this_controller->available_remote_nodes, remote_node_count
 3536               );
 3537 
 3538    if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
 3539    {
 3540       this_controller->device_table[node_index] = the_device;
 3541 
 3542       *node_id = node_index;
 3543 
 3544       return SCI_SUCCESS;
 3545    }
 3546 
 3547    return SCI_FAILURE_INSUFFICIENT_RESOURCES;
 3548 }
 3549 
 3550 /**
 3551  * @brief This method frees the remote node index back to the available
 3552  *        pool.  Once this is done the remote node context buffer is no
 3553  *        longer valid and can not be used.
 3554  *
 3555  * @param[in] this_controller
 3556  * @param[in] the_device
 3557  * @param[in] node_id
 3558  *
 3559  * @return none
 3560  */
 3561 void scic_sds_controller_free_remote_node_context(
 3562    SCIC_SDS_CONTROLLER_T    * this_controller,
 3563    SCIC_SDS_REMOTE_DEVICE_T * the_device,
 3564    U16                        node_id
 3565 )
 3566 {
 3567    U32 remote_node_count = scic_sds_remote_device_node_count(the_device);
 3568 
 3569    if (this_controller->device_table[node_id] == the_device)
 3570    {
 3571       this_controller->device_table[node_id] = SCI_INVALID_HANDLE;
 3572 
 3573       scic_sds_remote_node_table_release_remote_node_index(
 3574          &this_controller->available_remote_nodes, remote_node_count, node_id
 3575       );
 3576    }
 3577 }
 3578 
 3579 /**
 3580  * @brief This method returns the SCU_REMOTE_NODE_CONTEXT for the specified
 3581  *        remote node id.
 3582  *
 3583  * @param[in] this_controller
 3584  * @param[in] node_id
 3585  *
 3586  * @return SCU_REMOTE_NODE_CONTEXT_T*
 3587  */
 3588 SCU_REMOTE_NODE_CONTEXT_T *scic_sds_controller_get_remote_node_context_buffer(
 3589    SCIC_SDS_CONTROLLER_T *this_controller,
 3590    U16                    node_id
 3591 )
 3592 {
 3593    if (
 3594            (node_id < this_controller->remote_node_entries)
 3595         && (this_controller->device_table[node_id] != SCI_INVALID_HANDLE)
 3596       )
 3597    {
 3598       return &this_controller->remote_node_context_table[node_id];
 3599    }
 3600 
 3601    return NULL;
 3602 }
 3603 
 3604 /**
 3605  * This method will combind the frame header and frame buffer to create
 3606  * a SATA D2H register FIS
 3607  *
 3608  * @param[out] resposne_buffer This is the buffer into which the D2H register
 3609  *             FIS will be constructed.
 3610  * @param[in]  frame_header This is the frame header returned by the hardware.
 3611  * @param[in]  frame_buffer This is the frame buffer returned by the hardware.
 3612  *
 3613  * @erturn none
 3614  */
 3615 void scic_sds_controller_copy_sata_response(
 3616    void * response_buffer,
 3617    void * frame_header,
 3618    void * frame_buffer
 3619 )
 3620 {
 3621    memcpy(
 3622       response_buffer,
 3623       frame_header,
 3624       sizeof(U32)
 3625    );
 3626 
 3627    memcpy(
 3628       (char *)((char *)response_buffer + sizeof(U32)),
 3629       frame_buffer,
 3630       sizeof(SATA_FIS_REG_D2H_T) - sizeof(U32)
 3631    );
 3632 }
 3633 
 3634 /**
 3635  * @brief This method releases the frame once this is done the frame is
 3636  *        available for re-use by the hardware.  The data contained in the
 3637  *        frame header and frame buffer is no longer valid.
 3638  *        The UF queue get pointer is only updated if UF control indicates
 3639  *        this is appropriate.
 3640  *
 3641  * @param[in] this_controller
 3642  * @param[in] frame_index
 3643  *
 3644  * @return none
 3645  */
 3646 void scic_sds_controller_release_frame(
 3647    SCIC_SDS_CONTROLLER_T *this_controller,
 3648    U32                    frame_index
 3649 )
 3650 {
 3651    if (scic_sds_unsolicited_frame_control_release_frame(
 3652           &this_controller->uf_control, frame_index) == TRUE)
 3653       SCU_UFQGP_WRITE(this_controller, this_controller->uf_control.get);
 3654 }
 3655 
 3656 #ifdef SCI_LOGGING
 3657 void scic_sds_controller_initialize_state_logging(
 3658    SCIC_SDS_CONTROLLER_T *this_controller
 3659 )
 3660 {
 3661    sci_base_state_machine_logger_initialize(
 3662       &this_controller->parent.state_machine_logger,
 3663       &this_controller->parent.state_machine,
 3664       &this_controller->parent.parent,
 3665       scic_cb_logger_log_states,
 3666       "SCIC_SDS_CONTROLLER_T", "base state machine",
 3667       SCIC_LOG_OBJECT_CONTROLLER
 3668    );
 3669 }
 3670 
 3671 void scic_sds_controller_deinitialize_state_logging(
 3672    SCIC_SDS_CONTROLLER_T *this_controller
 3673 )
 3674 {
 3675    sci_base_state_machine_logger_deinitialize(
 3676       &this_controller->parent.state_machine_logger,
 3677       &this_controller->parent.state_machine
 3678    );
 3679 }
 3680 #endif
 3681 
 3682 /**
 3683  * @brief This method sets user parameters and OEM parameters to
 3684  *        default values.  Users can override these values utilizing
 3685  *        the scic_user_parameters_set() and scic_oem_parameters_set()
 3686  *        methods.
 3687  *
 3688  * @param[in] controller This parameter specifies the controller for
 3689  *            which to set the configuration parameters to their
 3690  *            default values.
 3691  *
 3692  * @return none
 3693  */
 3694 static
 3695 void scic_sds_controller_set_default_config_parameters(
 3696    SCIC_SDS_CONTROLLER_T *this_controller
 3697 )
 3698 {
 3699    U16 index;
 3700 
 3701    // Default to APC mode.
 3702    this_controller->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
 3703 
 3704    // Default to 1
 3705    this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up = 1;
 3706 
 3707    // Default to no SSC operation.
 3708    this_controller->oem_parameters.sds1.controller.ssc_sata_tx_spread_level = 0;
 3709    this_controller->oem_parameters.sds1.controller.ssc_sas_tx_spread_level  = 0;
 3710    this_controller->oem_parameters.sds1.controller.ssc_sas_tx_type          = 0;
 3711 
 3712    // Default to all phys to using short cables
 3713    this_controller->oem_parameters.sds1.controller.cable_selection_mask = 0;
 3714 
 3715    // Initialize all of the port parameter information to narrow ports.
 3716    for (index = 0; index < SCI_MAX_PORTS; index++)
 3717    {
 3718       this_controller->oem_parameters.sds1.ports[index].phy_mask = 0;
 3719    }
 3720 
 3721    // Initialize all of the phy parameter information.
 3722    for (index = 0; index < SCI_MAX_PHYS; index++)
 3723    {
 3724       // Default to 6G (i.e. Gen 3) for now.  User can override if
 3725       // they choose.
 3726       this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2;
 3727 
 3728       //the frequencies cannot be 0
 3729       this_controller->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f;
 3730       this_controller->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff;
 3731       this_controller->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33;
 3732 
 3733       // Previous Vitesse based expanders had a arbitration issue that
 3734       // is worked around by having the upper 32-bits of SAS address
 3735       // with a value greater then the Vitesse company identifier.
 3736       // Hence, usage of 0x5FCFFFFF.
 3737       this_controller->oem_parameters.sds1.phys[index].sas_address.sci_format.high
 3738          = 0x5FCFFFFF;
 3739 
 3740       // Add in controller index to ensure each controller will have unique SAS addresses by default.
 3741       this_controller->oem_parameters.sds1.phys[index].sas_address.sci_format.low
 3742          = 0x00000001 + this_controller->controller_index;
 3743 
 3744       if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
 3745          || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
 3746          || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0) )
 3747       {
 3748          this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control0 = 0x000E7C03;
 3749          this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control1 = 0x000E7C03;
 3750          this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control2 = 0x000E7C03;
 3751          this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control3 = 0x000E7C03;
 3752       }
 3753       else // This must be SCIC_SDS_PCI_REVISION_C0
 3754       {
 3755          this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control0 = 0x000BDD08;
 3756          this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control1 = 0x000B7069;
 3757          this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control2 = 0x000B7C09;
 3758          this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control3 = 0x000AFC6E;
 3759       }
 3760    }
 3761 
 3762    this_controller->user_parameters.sds1.stp_inactivity_timeout = 5;
 3763    this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5;
 3764    this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5;
 3765    this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20;
 3766    this_controller->user_parameters.sds1.no_outbound_task_timeout = 20;
 3767 
 3768 }
 3769 
 3770 
 3771 /**
 3772  * @brief This method release resources in SCI controller.
 3773  *
 3774  * @param[in] this_controller This parameter specifies the core
 3775  *            controller and associated objects whose resources are to be
 3776  *            released.
 3777  *
 3778  * @return This method returns a value indicating if the operation succeeded.
 3779  * @retval SCI_SUCCESS This value indicates that all the timers are destroyed.
 3780  * @retval SCI_FAILURE This value indicates certain failure during the process
 3781  *            of cleaning timer resource.
 3782  */
 3783 static
 3784 SCI_STATUS scic_sds_controller_release_resource(
 3785    SCIC_SDS_CONTROLLER_T * this_controller
 3786 )
 3787 {
 3788    SCIC_SDS_PORT_T * port;
 3789    SCIC_SDS_PHY_T * phy;
 3790    U8 index;
 3791 
 3792    SCIC_LOG_TRACE((
 3793       sci_base_object_get_logger(this_controller),
 3794       SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
 3795       "scic_sds_controller_release_resource(0x%x) enter\n",
 3796       this_controller
 3797    ));
 3798 
 3799    if(this_controller->phy_startup_timer != NULL)
 3800    {
 3801       scic_cb_timer_destroy(this_controller, this_controller->phy_startup_timer);
 3802       this_controller->phy_startup_timer = NULL;
 3803    }
 3804 
 3805    if(this_controller->power_control.timer != NULL)
 3806    {
 3807       scic_cb_timer_destroy(this_controller, this_controller->power_control.timer);
 3808       this_controller->power_control.timer = NULL;
 3809    }
 3810 
 3811    if(this_controller->timeout_timer != NULL)
 3812    {
 3813       scic_cb_timer_destroy(this_controller, this_controller->timeout_timer);
 3814       this_controller->timeout_timer = NULL;
 3815    }
 3816 
 3817    scic_sds_port_configuration_agent_release_resource(
 3818       this_controller,
 3819       &this_controller->port_agent);
 3820 
 3821    for(index = 0; index < SCI_MAX_PORTS+1; index++)
 3822    {
 3823       port = &this_controller->port_table[index];
 3824       scic_sds_port_release_resource(this_controller, port);
 3825    }
 3826 
 3827    for(index = 0; index < SCI_MAX_PHYS; index++)
 3828    {
 3829       phy = &this_controller->phy_table[index];
 3830       scic_sds_phy_release_resource(this_controller, phy);
 3831    }
 3832 
 3833    return SCI_SUCCESS;
 3834 }
 3835 
 3836 
 3837 /**
 3838  * @brief This method process the ports configured message from port configuration
 3839  *           agent.
 3840  *
 3841  * @param[in] this_controller This parameter specifies the core
 3842  *            controller that its ports are configured.
 3843  *
 3844  * @return None.
 3845  */
 3846 void scic_sds_controller_port_agent_configured_ports(
 3847    SCIC_SDS_CONTROLLER_T * this_controller
 3848 )
 3849 {
 3850    //simply transit to ready. The function below checks the controller state
 3851    scic_sds_controller_transition_to_ready(
 3852       this_controller, SCI_SUCCESS
 3853    );
 3854 }
 3855 
 3856 
 3857 //****************************************************************************-
 3858 //* SCIC Controller Public Methods
 3859 //****************************************************************************-
 3860 
 3861 SCI_STATUS scic_controller_construct(
 3862    SCI_LIBRARY_HANDLE_T    library,
 3863    SCI_CONTROLLER_HANDLE_T controller,
 3864    void *                  user_object
 3865 )
 3866 {
 3867    SCIC_SDS_LIBRARY_T    *my_library;
 3868    SCIC_SDS_CONTROLLER_T *this_controller;
 3869 
 3870    my_library = (SCIC_SDS_LIBRARY_T *)library;
 3871    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 3872 
 3873    SCIC_LOG_TRACE((
 3874       sci_base_object_get_logger(library),
 3875       SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
 3876       "scic_controller_construct(0x%x, 0x%x) enter\n",
 3877       library, controller
 3878    ));
 3879 
 3880    // Just clear out the memory of the structure to be safe.
 3881    memset(this_controller, 0, sizeof(SCIC_SDS_CONTROLLER_T));
 3882 
 3883    // Make sure that the static data is assigned before moving onto the
 3884    // base constroller construct as this will cause the controller to
 3885    // enter its initial state and the controller_index and pci_revision
 3886    // will be required to complete those operations correctly
 3887    this_controller->controller_index =
 3888       scic_sds_library_get_controller_index(my_library, this_controller);
 3889 
 3890    this_controller->pci_revision = my_library->pci_revision;
 3891 
 3892    sci_base_controller_construct(
 3893       &this_controller->parent,
 3894       sci_base_object_get_logger(my_library),
 3895       scic_sds_controller_state_table,
 3896       this_controller->memory_descriptors,
 3897       ARRAY_SIZE(this_controller->memory_descriptors),
 3898       NULL
 3899    );
 3900 
 3901    sci_object_set_association(controller, user_object);
 3902 
 3903    scic_sds_controller_initialize_state_logging(this_controller);
 3904 
 3905    scic_sds_pci_bar_initialization(this_controller);
 3906 
 3907    return SCI_SUCCESS;
 3908 }
 3909 
 3910 // ---------------------------------------------------------------------------
 3911 
 3912 SCI_STATUS scic_controller_initialize(
 3913    SCI_CONTROLLER_HANDLE_T   controller
 3914 )
 3915 {
 3916    SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
 3917    SCIC_SDS_CONTROLLER_T *this_controller;
 3918    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 3919 
 3920    SCIC_LOG_TRACE((
 3921       sci_base_object_get_logger(controller),
 3922       SCIC_LOG_OBJECT_CONTROLLER,
 3923       "scic_controller_initialize(0x%x, 0x%d) enter\n",
 3924       controller
 3925    ));
 3926 
 3927    if (this_controller->state_handlers->parent.initialize_handler != NULL)
 3928    {
 3929       status = this_controller->state_handlers->parent.initialize_handler(
 3930                   (SCI_BASE_CONTROLLER_T *)controller
 3931                );
 3932    }
 3933    else
 3934    {
 3935       SCIC_LOG_WARNING((
 3936          sci_base_object_get_logger(this_controller),
 3937          SCIC_LOG_OBJECT_CONTROLLER,
 3938          "SCIC Controller initialize operation requested in invalid state %d\n",
 3939          sci_base_state_machine_get_state(
 3940             scic_sds_controller_get_base_state_machine(this_controller))
 3941       ));
 3942    }
 3943 
 3944    return status;
 3945 }
 3946 
 3947 // ---------------------------------------------------------------------------
 3948 
 3949 U32 scic_controller_get_suggested_start_timeout(
 3950    SCI_CONTROLLER_HANDLE_T  controller
 3951 )
 3952 {
 3953    // Validate the user supplied parameters.
 3954    if (controller == SCI_INVALID_HANDLE)
 3955       return 0;
 3956 
 3957    // The suggested minimum timeout value for a controller start operation:
 3958    //
 3959    //     Signature FIS Timeout
 3960    //   + Phy Start Timeout
 3961    //   + Number of Phy Spin Up Intervals
 3962    //   ---------------------------------
 3963    //   Number of milliseconds for the controller start operation.
 3964    //
 3965    // NOTE: The number of phy spin up intervals will be equivalent
 3966    //       to the number of phys divided by the number phys allowed
 3967    //       per interval - 1 (once OEM parameters are supported).
 3968    //       Currently we assume only 1 phy per interval.
 3969 
 3970    return (SCIC_SDS_SIGNATURE_FIS_TIMEOUT
 3971            + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
 3972            + ((SCI_MAX_PHYS-1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL));
 3973 }
 3974 
 3975 // ---------------------------------------------------------------------------
 3976 
 3977 SCI_STATUS scic_controller_start(
 3978    SCI_CONTROLLER_HANDLE_T controller,
 3979    U32 timeout
 3980 )
 3981 {
 3982    SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
 3983    SCIC_SDS_CONTROLLER_T *this_controller;
 3984    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 3985 
 3986    SCIC_LOG_TRACE((
 3987       sci_base_object_get_logger(controller),
 3988       SCIC_LOG_OBJECT_CONTROLLER,
 3989       "scic_controller_start(0x%x, 0x%d) enter\n",
 3990       controller, timeout
 3991    ));
 3992 
 3993    if (this_controller->state_handlers->parent.start_handler != NULL)
 3994    {
 3995       status = this_controller->state_handlers->parent.start_handler(
 3996                   (SCI_BASE_CONTROLLER_T *)controller, timeout
 3997                );
 3998    }
 3999    else
 4000    {
 4001       SCIC_LOG_WARNING((
 4002          sci_base_object_get_logger(this_controller),
 4003          SCIC_LOG_OBJECT_CONTROLLER,
 4004          "SCIC Controller start operation requested in invalid state %d\n",
 4005          sci_base_state_machine_get_state(
 4006             scic_sds_controller_get_base_state_machine(this_controller))
 4007       ));
 4008    }
 4009 
 4010    return status;
 4011 }
 4012 
 4013 // ---------------------------------------------------------------------------
 4014 
 4015 SCI_STATUS scic_controller_stop(
 4016    SCI_CONTROLLER_HANDLE_T controller,
 4017    U32 timeout
 4018 )
 4019 {
 4020    SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
 4021    SCIC_SDS_CONTROLLER_T *this_controller;
 4022    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4023 
 4024    SCIC_LOG_TRACE((
 4025       sci_base_object_get_logger(controller),
 4026       SCIC_LOG_OBJECT_CONTROLLER,
 4027       "scic_controller_stop(0x%x, 0x%d) enter\n",
 4028       controller, timeout
 4029    ));
 4030 
 4031    if (this_controller->state_handlers->parent.stop_handler != NULL)
 4032    {
 4033       status = this_controller->state_handlers->parent.stop_handler(
 4034                   (SCI_BASE_CONTROLLER_T *)controller, timeout
 4035                );
 4036    }
 4037    else
 4038    {
 4039       SCIC_LOG_WARNING((
 4040          sci_base_object_get_logger(this_controller),
 4041          SCIC_LOG_OBJECT_CONTROLLER,
 4042          "SCIC Controller stop operation requested in invalid state %d\n",
 4043          sci_base_state_machine_get_state(
 4044             scic_sds_controller_get_base_state_machine(this_controller))
 4045       ));
 4046    }
 4047 
 4048    return status;
 4049 }
 4050 
 4051 // ---------------------------------------------------------------------------
 4052 
 4053 SCI_STATUS scic_controller_reset(
 4054    SCI_CONTROLLER_HANDLE_T controller
 4055 )
 4056 {
 4057    SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
 4058    SCIC_SDS_CONTROLLER_T *this_controller;
 4059    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4060 
 4061    SCIC_LOG_TRACE((
 4062       sci_base_object_get_logger(controller),
 4063       SCIC_LOG_OBJECT_CONTROLLER,
 4064       "scic_controller_reset(0x%x) enter\n",
 4065       controller
 4066    ));
 4067 
 4068    if (this_controller->state_handlers->parent.reset_handler != NULL)
 4069    {
 4070       status = this_controller->state_handlers->parent.reset_handler(
 4071                   (SCI_BASE_CONTROLLER_T *)controller
 4072                );
 4073    }
 4074    else
 4075    {
 4076       SCIC_LOG_WARNING((
 4077          sci_base_object_get_logger(this_controller),
 4078          SCIC_LOG_OBJECT_CONTROLLER,
 4079          "SCIC Controller reset operation requested in invalid state %d\n",
 4080          sci_base_state_machine_get_state(
 4081             scic_sds_controller_get_base_state_machine(this_controller))
 4082       ));
 4083    }
 4084 
 4085    return status;
 4086 }
 4087 
 4088 // ---------------------------------------------------------------------------
 4089 
 4090 SCI_STATUS scic_controller_get_handler_methods(
 4091    SCIC_INTERRUPT_TYPE                interrupt_type,
 4092    U16                                message_count,
 4093    SCIC_CONTROLLER_HANDLER_METHODS_T *handler_methods
 4094 )
 4095 {
 4096    SCI_STATUS status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT;
 4097 
 4098    switch (interrupt_type)
 4099    {
 4100 #if !defined(DISABLE_INTERRUPTS)
 4101    case SCIC_LEGACY_LINE_INTERRUPT_TYPE:
 4102       if (message_count == 0)
 4103       {
 4104          handler_methods[0].interrupt_handler
 4105             = scic_sds_controller_legacy_interrupt_handler;
 4106          handler_methods[0].completion_handler
 4107             = scic_sds_controller_legacy_completion_handler;
 4108 
 4109          status = SCI_SUCCESS;
 4110       }
 4111       break;
 4112 
 4113    case SCIC_MSIX_INTERRUPT_TYPE:
 4114       if (message_count == 1)
 4115       {
 4116          handler_methods[0].interrupt_handler
 4117             = scic_sds_controller_single_vector_interrupt_handler;
 4118          handler_methods[0].completion_handler
 4119             = scic_sds_controller_single_vector_completion_handler;
 4120 
 4121          status = SCI_SUCCESS;
 4122       }
 4123       else if (message_count == 2)
 4124       {
 4125          handler_methods[0].interrupt_handler
 4126             = scic_sds_controller_normal_vector_interrupt_handler;
 4127          handler_methods[0].completion_handler
 4128             = scic_sds_controller_normal_vector_completion_handler;
 4129 
 4130          handler_methods[1].interrupt_handler
 4131             = scic_sds_controller_error_vector_interrupt_handler;
 4132          handler_methods[1].completion_handler
 4133             = scic_sds_controller_error_vector_completion_handler;
 4134 
 4135          status = SCI_SUCCESS;
 4136       }
 4137       break;
 4138 #endif // !defined(DISABLE_INTERRUPTS)
 4139 
 4140    case SCIC_NO_INTERRUPTS:
 4141       if (message_count == 0)
 4142       {
 4143 
 4144          handler_methods[0].interrupt_handler
 4145             = scic_sds_controller_polling_interrupt_handler;
 4146          handler_methods[0].completion_handler
 4147             = scic_sds_controller_polling_completion_handler;
 4148 
 4149          status = SCI_SUCCESS;
 4150       }
 4151       break;
 4152 
 4153    default:
 4154       status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4155       break;
 4156    }
 4157 
 4158    return status;
 4159 }
 4160 
 4161 // ---------------------------------------------------------------------------
 4162 
 4163 SCI_IO_STATUS scic_controller_start_io(
 4164    SCI_CONTROLLER_HANDLE_T    controller,
 4165    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
 4166    SCI_IO_REQUEST_HANDLE_T    io_request,
 4167    U16                        io_tag
 4168 )
 4169 {
 4170    SCI_STATUS          status;
 4171    SCIC_SDS_CONTROLLER_T *this_controller;
 4172    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4173 
 4174    SCIC_LOG_TRACE((
 4175       sci_base_object_get_logger(controller),
 4176       SCIC_LOG_OBJECT_CONTROLLER,
 4177       "scic_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
 4178       controller, remote_device, io_request, io_tag
 4179    ));
 4180 
 4181    status = this_controller->state_handlers->parent.start_io_handler(
 4182                &this_controller->parent,
 4183                (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
 4184                (SCI_BASE_REQUEST_T *)io_request,
 4185                io_tag
 4186             );
 4187 
 4188    return (SCI_IO_STATUS)status;
 4189 }
 4190 
 4191 // ---------------------------------------------------------------------------
 4192 
 4193 SCI_STATUS scic_controller_terminate_request(
 4194    SCI_CONTROLLER_HANDLE_T    controller,
 4195    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
 4196    SCI_IO_REQUEST_HANDLE_T    request
 4197 )
 4198 {
 4199    SCI_STATUS status;
 4200    SCIC_SDS_CONTROLLER_T *this_controller;
 4201    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4202 
 4203    SCIC_LOG_TRACE((
 4204       sci_base_object_get_logger(controller),
 4205       SCIC_LOG_OBJECT_CONTROLLER,
 4206       "scic_controller_terminate_request(0x%x, 0x%x, 0x%x) enter\n",
 4207       controller, remote_device, request
 4208    ));
 4209 
 4210    status = this_controller->state_handlers->terminate_request_handler(
 4211       &this_controller->parent,
 4212       (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
 4213       (SCI_BASE_REQUEST_T *)request
 4214    );
 4215 
 4216    return status;
 4217 }
 4218 
 4219 // ---------------------------------------------------------------------------
 4220 
 4221 SCI_STATUS scic_controller_complete_io(
 4222    SCI_CONTROLLER_HANDLE_T controller,
 4223    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
 4224    SCI_IO_REQUEST_HANDLE_T io_request
 4225 )
 4226 {
 4227    SCI_STATUS status;
 4228    SCIC_SDS_CONTROLLER_T *this_controller;
 4229    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4230 
 4231    SCIC_LOG_TRACE((
 4232       sci_base_object_get_logger(controller),
 4233       SCIC_LOG_OBJECT_CONTROLLER,
 4234       "scic_controller_complete_io(0x%x, 0x%x, 0x%x) enter\n",
 4235       controller, remote_device, io_request
 4236    ));
 4237 
 4238    status = this_controller->state_handlers->parent.complete_io_handler(
 4239       &this_controller->parent,
 4240       (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
 4241       (SCI_BASE_REQUEST_T *)io_request
 4242    );
 4243 
 4244    return status;
 4245 }
 4246 
 4247 // ---------------------------------------------------------------------------
 4248 
 4249 #if !defined(DISABLE_TASK_MANAGEMENT)
 4250 
 4251 SCI_TASK_STATUS scic_controller_start_task(
 4252    SCI_CONTROLLER_HANDLE_T    controller,
 4253    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
 4254    SCI_TASK_REQUEST_HANDLE_T  task_request,
 4255    U16                        task_tag
 4256 )
 4257 {
 4258    SCI_STATUS             status = SCI_FAILURE_INVALID_STATE;
 4259    SCIC_SDS_CONTROLLER_T *this_controller;
 4260    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4261 
 4262    SCIC_LOG_TRACE((
 4263       sci_base_object_get_logger(controller),
 4264       SCIC_LOG_OBJECT_CONTROLLER,
 4265       "scic_controller_start_task(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
 4266       controller, remote_device, task_request, task_tag
 4267    ));
 4268 
 4269    if (this_controller->state_handlers->parent.start_task_handler != NULL)
 4270    {
 4271       status = this_controller->state_handlers->parent.start_task_handler(
 4272                   &this_controller->parent,
 4273                   (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
 4274                   (SCI_BASE_REQUEST_T *)task_request,
 4275                   task_tag
 4276                );
 4277    }
 4278    else
 4279    {
 4280       SCIC_LOG_INFO((
 4281          sci_base_object_get_logger(controller),
 4282          SCIC_LOG_OBJECT_CONTROLLER,
 4283          "SCIC Controller starting task from invalid state\n"
 4284       ));
 4285    }
 4286 
 4287    return (SCI_TASK_STATUS)status;
 4288 }
 4289 
 4290 // ---------------------------------------------------------------------------
 4291 
 4292 SCI_STATUS scic_controller_complete_task(
 4293    SCI_CONTROLLER_HANDLE_T    controller,
 4294    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
 4295    SCI_TASK_REQUEST_HANDLE_T  task_request
 4296 )
 4297 {
 4298    SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
 4299    SCIC_SDS_CONTROLLER_T *this_controller;
 4300    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4301 
 4302    SCIC_LOG_TRACE((
 4303       sci_base_object_get_logger(controller),
 4304       SCIC_LOG_OBJECT_CONTROLLER,
 4305       "scic_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n",
 4306       controller, remote_device, task_request
 4307    ));
 4308 
 4309    if (this_controller->state_handlers->parent.complete_task_handler != NULL)
 4310    {
 4311       status = this_controller->state_handlers->parent.complete_task_handler(
 4312                   &this_controller->parent,
 4313                   (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
 4314                   (SCI_BASE_REQUEST_T *)task_request
 4315                );
 4316    }
 4317    else
 4318    {
 4319       SCIC_LOG_INFO((
 4320          sci_base_object_get_logger(controller),
 4321          SCIC_LOG_OBJECT_CONTROLLER,
 4322          "SCIC Controller completing task from invalid state\n"
 4323       ));
 4324    }
 4325 
 4326    return status;
 4327 }
 4328 
 4329 #endif // !defined(DISABLE_TASK_MANAGEMENT)
 4330 
 4331 // ---------------------------------------------------------------------------
 4332 
 4333 SCI_STATUS scic_controller_get_port_handle(
 4334    SCI_CONTROLLER_HANDLE_T controller,
 4335    U8                      port_index,
 4336    SCI_PORT_HANDLE_T *     port_handle
 4337 )
 4338 {
 4339    SCIC_SDS_CONTROLLER_T *this_controller;
 4340    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4341 
 4342    SCIC_LOG_TRACE((
 4343       sci_base_object_get_logger(controller),
 4344       SCIC_LOG_OBJECT_CONTROLLER,
 4345       "scic_controller_get_port_handle(0x%x, 0x%x, 0x%x) enter\n",
 4346       controller, port_index, port_handle
 4347    ));
 4348 
 4349    if (port_index < this_controller->logical_port_entries)
 4350    {
 4351       *port_handle = &this_controller->port_table[port_index];
 4352 
 4353       return SCI_SUCCESS;
 4354    }
 4355 
 4356    return SCI_FAILURE_INVALID_PORT;
 4357 }
 4358 
 4359 // ---------------------------------------------------------------------------
 4360 
 4361 SCI_STATUS scic_controller_get_phy_handle(
 4362    SCI_CONTROLLER_HANDLE_T controller,
 4363    U8                      phy_index,
 4364    SCI_PHY_HANDLE_T *      phy_handle
 4365 )
 4366 {
 4367    SCIC_SDS_CONTROLLER_T *this_controller;
 4368    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4369 
 4370    SCIC_LOG_TRACE((
 4371       sci_base_object_get_logger(controller),
 4372       SCIC_LOG_OBJECT_CONTROLLER,
 4373       "scic_controller_get_phy_handle(0x%x, 0x%x, 0x%x) enter\n",
 4374       controller, phy_index, phy_handle
 4375    ));
 4376 
 4377    if (phy_index < ARRAY_SIZE(this_controller->phy_table))
 4378    {
 4379       *phy_handle = &this_controller->phy_table[phy_index];
 4380 
 4381       return SCI_SUCCESS;
 4382    }
 4383 
 4384    SCIC_LOG_ERROR((
 4385       sci_base_object_get_logger(this_controller),
 4386       SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_CONTROLLER,
 4387       "Controller:0x%x PhyId:0x%x invalid phy index\n",
 4388       this_controller, phy_index
 4389    ));
 4390 
 4391    return SCI_FAILURE_INVALID_PHY;
 4392 }
 4393 
 4394 // ---------------------------------------------------------------------------
 4395 
 4396 U16 scic_controller_allocate_io_tag(
 4397    SCI_CONTROLLER_HANDLE_T controller
 4398 )
 4399 {
 4400    U16 task_context;
 4401    U16 sequence_count;
 4402    SCIC_SDS_CONTROLLER_T *this_controller;
 4403    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4404 
 4405    SCIC_LOG_TRACE((
 4406       sci_base_object_get_logger(controller),
 4407       SCIC_LOG_OBJECT_CONTROLLER,
 4408       "scic_controller_allocate_io_tag(0x%x) enter\n",
 4409       controller
 4410    ));
 4411 
 4412    if (!sci_pool_empty(this_controller->tci_pool))
 4413    {
 4414       sci_pool_get(this_controller->tci_pool, task_context);
 4415 
 4416       sequence_count = this_controller->io_request_sequence[task_context];
 4417 
 4418       return scic_sds_io_tag_construct(sequence_count, task_context);
 4419    }
 4420 
 4421    return SCI_CONTROLLER_INVALID_IO_TAG;
 4422 }
 4423 
 4424 // ---------------------------------------------------------------------------
 4425 
 4426 SCI_STATUS scic_controller_free_io_tag(
 4427    SCI_CONTROLLER_HANDLE_T controller,
 4428    U16                     io_tag
 4429 )
 4430 {
 4431    U16 sequence;
 4432    U16 index;
 4433 
 4434    SCIC_SDS_CONTROLLER_T *this_controller;
 4435    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4436 
 4437    ASSERT(io_tag != SCI_CONTROLLER_INVALID_IO_TAG);
 4438 
 4439    SCIC_LOG_TRACE((
 4440       sci_base_object_get_logger(controller),
 4441       SCIC_LOG_OBJECT_CONTROLLER,
 4442       "scic_controller_free_io_tag(0x%x, 0x%x) enter\n",
 4443       controller, io_tag
 4444    ));
 4445 
 4446    sequence = scic_sds_io_tag_get_sequence(io_tag);
 4447    index    = scic_sds_io_tag_get_index(io_tag);
 4448 
 4449    if (!sci_pool_full(this_controller->tci_pool))
 4450    {
 4451       if (sequence == this_controller->io_request_sequence[index])
 4452       {
 4453          scic_sds_io_sequence_increment(
 4454             this_controller->io_request_sequence[index]);
 4455 
 4456          sci_pool_put(this_controller->tci_pool, index);
 4457 
 4458          return SCI_SUCCESS;
 4459       }
 4460    }
 4461 
 4462    return SCI_FAILURE_INVALID_IO_TAG;
 4463 }
 4464 
 4465 // ---------------------------------------------------------------------------
 4466 
 4467 void scic_controller_enable_interrupts(
 4468    SCI_CONTROLLER_HANDLE_T controller
 4469 )
 4470 {
 4471    SCIC_SDS_CONTROLLER_T *this_controller;
 4472    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4473 
 4474    ASSERT(this_controller->smu_registers != NULL);
 4475 
 4476    SMU_IMR_WRITE(this_controller, 0x00000000);
 4477 }
 4478 
 4479 // ---------------------------------------------------------------------------
 4480 
 4481 void scic_controller_disable_interrupts(
 4482    SCI_CONTROLLER_HANDLE_T controller
 4483 )
 4484 {
 4485    SCIC_SDS_CONTROLLER_T *this_controller;
 4486    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4487 
 4488    ASSERT(this_controller->smu_registers != NULL);
 4489 
 4490    SMU_IMR_WRITE(this_controller, 0xffffffff);
 4491 }
 4492 
 4493 // ---------------------------------------------------------------------------
 4494 
 4495 SCI_STATUS scic_controller_set_mode(
 4496    SCI_CONTROLLER_HANDLE_T   controller,
 4497    SCI_CONTROLLER_MODE       operating_mode
 4498 )
 4499 {
 4500    SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
 4501    SCI_STATUS             status          = SCI_SUCCESS;
 4502 
 4503    SCIC_LOG_TRACE((
 4504       sci_base_object_get_logger(controller),
 4505       SCIC_LOG_OBJECT_CONTROLLER,
 4506       "scic_controller_set_mode(0x%x, 0x%x) enter\n",
 4507       controller, operating_mode
 4508    ));
 4509 
 4510    if (
 4511          (this_controller->parent.state_machine.current_state_id
 4512           == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
 4513       || (this_controller->parent.state_machine.current_state_id
 4514           == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
 4515       )
 4516    {
 4517       switch (operating_mode)
 4518       {
 4519       case SCI_MODE_SPEED:
 4520          this_controller->remote_node_entries =
 4521             MIN(this_controller->remote_node_entries, SCI_MAX_REMOTE_DEVICES);
 4522          this_controller->task_context_entries =
 4523             MIN(this_controller->task_context_entries, SCU_IO_REQUEST_COUNT);
 4524          this_controller->uf_control.buffers.count =
 4525             MIN(this_controller->uf_control.buffers.count, SCU_UNSOLICITED_FRAME_COUNT);
 4526          this_controller->completion_event_entries =
 4527             MIN(this_controller->completion_event_entries, SCU_EVENT_COUNT);
 4528          this_controller->completion_queue_entries =
 4529             MIN(this_controller->completion_queue_entries, SCU_COMPLETION_QUEUE_COUNT);
 4530 
 4531          scic_sds_controller_build_memory_descriptor_table(this_controller);
 4532       break;
 4533 
 4534       case SCI_MODE_SIZE:
 4535          this_controller->remote_node_entries =
 4536             MIN(this_controller->remote_node_entries, SCI_MIN_REMOTE_DEVICES);
 4537          this_controller->task_context_entries =
 4538             MIN(this_controller->task_context_entries, SCI_MIN_IO_REQUESTS);
 4539          this_controller->uf_control.buffers.count =
 4540             MIN(this_controller->uf_control.buffers.count, SCU_MIN_UNSOLICITED_FRAMES);
 4541          this_controller->completion_event_entries =
 4542             MIN(this_controller->completion_event_entries, SCU_MIN_EVENTS);
 4543          this_controller->completion_queue_entries =
 4544             MIN(this_controller->completion_queue_entries, SCU_MIN_COMPLETION_QUEUE_ENTRIES);
 4545 
 4546          scic_sds_controller_build_memory_descriptor_table(this_controller);
 4547       break;
 4548 
 4549       default:
 4550          status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4551       break;
 4552       }
 4553    }
 4554    else
 4555       status = SCI_FAILURE_INVALID_STATE;
 4556 
 4557    return status;
 4558 }
 4559 
 4560 /**
 4561  * This method will reset the controller hardware.
 4562  *
 4563  * @param[in] this_controller The controller that is to be reset.
 4564  */
 4565 void scic_sds_controller_reset_hardware(
 4566    SCIC_SDS_CONTROLLER_T * this_controller
 4567 )
 4568 {
 4569    // Disable interrupts so we dont take any spurious interrupts
 4570    scic_controller_disable_interrupts(this_controller);
 4571 
 4572    // Reset the SCU
 4573    SMU_SMUSRCR_WRITE(this_controller, 0xFFFFFFFF);
 4574 
 4575    // Delay for 1ms to before clearing the CQP and UFQPR.
 4576    scic_cb_stall_execution(1000);
 4577 
 4578    // The write to the CQGR clears the CQP
 4579    SMU_CQGR_WRITE(this_controller, 0x00000000);
 4580 
 4581    // The write to the UFQGP clears the UFQPR
 4582    SCU_UFQGP_WRITE(this_controller, 0x00000000);
 4583 }
 4584 
 4585 // ---------------------------------------------------------------------------
 4586 
 4587 SCI_STATUS scic_user_parameters_set(
 4588    SCI_CONTROLLER_HANDLE_T   controller,
 4589    SCIC_USER_PARAMETERS_T  * scic_parms
 4590 )
 4591 {
 4592    SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
 4593 
 4594    if (
 4595          (this_controller->parent.state_machine.current_state_id
 4596           == SCI_BASE_CONTROLLER_STATE_RESET)
 4597       || (this_controller->parent.state_machine.current_state_id
 4598           == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
 4599       || (this_controller->parent.state_machine.current_state_id
 4600           == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
 4601       )
 4602    {
 4603       U16  index;
 4604 
 4605       // Validate the user parameters.  If they are not legal, then
 4606       // return a failure.
 4607       for (index = 0; index < SCI_MAX_PHYS; index++)
 4608       {
 4609          if (!
 4610                (  scic_parms->sds1.phys[index].max_speed_generation
 4611                   <= SCIC_SDS_PARM_MAX_SPEED
 4612                && scic_parms->sds1.phys[index].max_speed_generation
 4613                   > SCIC_SDS_PARM_NO_SPEED
 4614                )
 4615             )
 4616             return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4617 
 4618          if (
 4619                (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) ||
 4620                (scic_parms->sds1.phys[index].align_insertion_frequency == 0) ||
 4621                (scic_parms->sds1.phys[index].notify_enable_spin_up_insertion_frequency == 0)
 4622             )
 4623          {
 4624             return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4625          }
 4626       }
 4627 
 4628       if (
 4629             (scic_parms->sds1.stp_inactivity_timeout == 0) ||
 4630             (scic_parms->sds1.ssp_inactivity_timeout == 0) ||
 4631             (scic_parms->sds1.stp_max_occupancy_timeout == 0) ||
 4632             (scic_parms->sds1.ssp_max_occupancy_timeout == 0) ||
 4633             (scic_parms->sds1.no_outbound_task_timeout == 0)
 4634          )
 4635       {
 4636          return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4637       }
 4638 
 4639       memcpy(
 4640          (&this_controller->user_parameters), scic_parms, sizeof(*scic_parms));
 4641 
 4642       return SCI_SUCCESS;
 4643    }
 4644 
 4645    return SCI_FAILURE_INVALID_STATE;
 4646 }
 4647 
 4648 // ---------------------------------------------------------------------------
 4649 
 4650 void scic_user_parameters_get(
 4651    SCI_CONTROLLER_HANDLE_T   controller,
 4652    SCIC_USER_PARAMETERS_T   * scic_parms
 4653 )
 4654 {
 4655    SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
 4656 
 4657    memcpy(scic_parms, (&this_controller->user_parameters), sizeof(*scic_parms));
 4658 }
 4659 
 4660 // ---------------------------------------------------------------------------
 4661 SCI_STATUS scic_oem_parameters_set(
 4662    SCI_CONTROLLER_HANDLE_T   controller,
 4663    SCIC_OEM_PARAMETERS_T   * scic_parms,
 4664    U8 scic_parms_version
 4665 )
 4666 {
 4667    SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
 4668    SCI_BIOS_OEM_PARAM_ELEMENT_T *old_oem_params =
 4669                 (SCI_BIOS_OEM_PARAM_ELEMENT_T *)(&(scic_parms->sds1));
 4670 
 4671 
 4672    if (
 4673          (this_controller->parent.state_machine.current_state_id
 4674           == SCI_BASE_CONTROLLER_STATE_RESET)
 4675       || (this_controller->parent.state_machine.current_state_id
 4676           == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
 4677       || (this_controller->parent.state_machine.current_state_id
 4678           == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
 4679       )
 4680    {
 4681       U16  index;
 4682       U8   combined_phy_mask = 0;
 4683 
 4684       /*
 4685        * Set the OEM parameter version for the controller. This comes
 4686        * from the OEM parameter block header or the registry depending
 4687        * on what WCDL is set to retrieve.
 4688        */
 4689       this_controller->oem_parameters_version = scic_parms_version;
 4690 
 4691       // Validate the oem parameters.  If they are not legal, then
 4692       // return a failure.
 4693       for(index=0; index<SCI_MAX_PORTS; index++)
 4694       {
 4695          if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX)
 4696          {
 4697             return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4698          }
 4699       }
 4700 
 4701       for(index=0; index<SCI_MAX_PHYS; index++)
 4702       {
 4703          if (
 4704              scic_parms->sds1.phys[index].sas_address.sci_format.high == 0
 4705                  && scic_parms->sds1.phys[index].sas_address.sci_format.low  == 0
 4706         )
 4707         {
 4708             return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4709         }
 4710 
 4711 #if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
 4712         if (
 4713               (scic_parms->sds1.phys[index].afe_tx_amp_control0 == 0) ||
 4714               (scic_parms->sds1.phys[index].afe_tx_amp_control1 == 0) ||
 4715               (scic_parms->sds1.phys[index].afe_tx_amp_control2 == 0) ||
 4716               (scic_parms->sds1.phys[index].afe_tx_amp_control3 == 0)
 4717               )
 4718         {
 4719            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4720         }
 4721 #endif
 4722       }
 4723 
 4724       if (scic_parms->sds1.controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
 4725       {
 4726          for(index=0; index<SCI_MAX_PHYS; index++)
 4727          {
 4728             if (scic_parms->sds1.ports[index].phy_mask != 0)
 4729             {
 4730                return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4731             }
 4732          }
 4733       }
 4734       else if (scic_parms->sds1.controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE)
 4735       {
 4736          for(index=0; index<SCI_MAX_PHYS; index++)
 4737          {
 4738             combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask;
 4739          }
 4740 
 4741          if (combined_phy_mask == 0)
 4742          {
 4743             return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4744          }
 4745       }
 4746       else
 4747       {
 4748          return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4749       }
 4750 
 4751       if (scic_parms->sds1.controller.max_number_concurrent_device_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
 4752       {
 4753          return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4754       }
 4755 
 4756       if (old_oem_params->controller.do_enable_ssc != 0)
 4757       {
 4758          if (  (scic_parms_version == SCI_OEM_PARAM_VER_1_0)
 4759             && (old_oem_params->controller.do_enable_ssc != 0x01))
 4760              return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4761 
 4762          if (scic_parms_version >= SCI_OEM_PARAM_VER_1_1)
 4763          {
 4764             SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T *oem_params =
 4765                 (SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T*)(&(scic_parms->sds1));
 4766 
 4767             U8 test = oem_params->controller.ssc_sata_tx_spread_level;
 4768             if ( !((test == 0x0) || (test == 0x2) || (test == 0x3) ||
 4769                  (test == 0x6) || (test == 0x7)) )
 4770                 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4771 
 4772             test = oem_params->controller.ssc_sas_tx_spread_level;
 4773             if (oem_params->controller.ssc_sas_tx_type == 0)
 4774             {
 4775                 if ( !((test == 0x0) || (test == 0x2) || (test == 0x3)) )
 4776                     return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4777             }
 4778             else
 4779             if (oem_params->controller.ssc_sas_tx_type == 1)
 4780             {
 4781                 if ( !((test == 0x0) || (test == 0x3) || (test == 0x6)) )
 4782                     return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4783             }
 4784          }
 4785       }
 4786 
 4787       memcpy(
 4788          (&this_controller->oem_parameters), scic_parms, sizeof(*scic_parms));
 4789       return SCI_SUCCESS;
 4790    }
 4791 
 4792    return SCI_FAILURE_INVALID_STATE;
 4793 }
 4794 
 4795 // ---------------------------------------------------------------------------
 4796 
 4797 void scic_oem_parameters_get(
 4798    SCI_CONTROLLER_HANDLE_T   controller,
 4799    SCIC_OEM_PARAMETERS_T   * scic_parms
 4800 )
 4801 {
 4802    SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
 4803 
 4804    memcpy(scic_parms, (&this_controller->oem_parameters), sizeof(*scic_parms));
 4805 }
 4806 
 4807 // ---------------------------------------------------------------------------
 4808 
 4809 #if !defined(DISABLE_INTERRUPTS)
 4810 
 4811 #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853
 4812 #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280
 4813 #define INTERRUPT_COALESCE_TIMEOUT_MAX_US                    2700000
 4814 #define INTERRUPT_COALESCE_NUMBER_MAX                        256
 4815 #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN                7
 4816 #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX                28
 4817 
 4818 SCI_STATUS scic_controller_set_interrupt_coalescence(
 4819    SCI_CONTROLLER_HANDLE_T controller,
 4820    U32                     coalesce_number,
 4821    U32                     coalesce_timeout
 4822 )
 4823 {
 4824    SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4825    U8 timeout_encode = 0;
 4826    U32 min = 0;
 4827    U32 max = 0;
 4828 
 4829    //Check if the input parameters fall in the range.
 4830    if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX)
 4831       return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4832 
 4833    //  Defined encoding for interrupt coalescing timeout:
 4834    //              Value   Min      Max     Units
 4835    //              -----   ---      ---     -----
 4836    //              0       -        -       Disabled
 4837    //              1       13.3     20.0    ns
 4838    //              2       26.7     40.0
 4839    //              3       53.3     80.0
 4840    //              4       106.7    160.0
 4841    //              5       213.3    320.0
 4842    //              6       426.7    640.0
 4843    //              7       853.3    1280.0
 4844    //              8       1.7      2.6     us
 4845    //              9       3.4      5.1
 4846    //              10      6.8      10.2
 4847    //              11      13.7     20.5
 4848    //              12      27.3     41.0
 4849    //              13      54.6     81.9
 4850    //              14      109.2    163.8
 4851    //              15      218.5    327.7
 4852    //              16      436.9    655.4
 4853    //              17      873.8    1310.7
 4854    //              18      1.7      2.6     ms
 4855    //              19      3.5      5.2
 4856    //              20      7.0      10.5
 4857    //              21      14.0     21.0
 4858    //              22      28.0     41.9
 4859    //              23      55.9     83.9
 4860    //              24      111.8    167.8
 4861    //              25      223.7    335.5
 4862    //              26      447.4    671.1
 4863    //              27      894.8    1342.2
 4864    //              28      1.8      2.7     s
 4865    //              Others Undefined
 4866 
 4867    //Use the table above to decide the encode of interrupt coalescing timeout
 4868    //value for register writing.
 4869    if (coalesce_timeout == 0)
 4870       timeout_encode = 0;
 4871    else
 4872    {
 4873       //make the timeout value in unit of (10 ns).
 4874       coalesce_timeout = coalesce_timeout * 100;
 4875       min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10;
 4876       max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10;
 4877 
 4878       //get the encode of timeout for register writing.
 4879       for ( timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN;
 4880             timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX;
 4881             timeout_encode++ )
 4882       {
 4883          if (min <= coalesce_timeout &&  max > coalesce_timeout)
 4884             break;
 4885          else if (coalesce_timeout >= max && coalesce_timeout < min*2
 4886             && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US*100)
 4887          {
 4888             if ( (coalesce_timeout-max) < (2*min - coalesce_timeout) )
 4889                break;
 4890             else
 4891             {
 4892                timeout_encode++;
 4893                break;
 4894             }
 4895          }
 4896          else
 4897          {
 4898             max = max*2;
 4899             min = min*2;
 4900          }
 4901       }
 4902 
 4903       if ( timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX+1 )
 4904          //the value is out of range.
 4905          return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4906    }
 4907 
 4908    SMU_ICC_WRITE(
 4909       scic_controller,
 4910       (SMU_ICC_GEN_VAL(NUMBER, coalesce_number)|
 4911        SMU_ICC_GEN_VAL(TIMER, timeout_encode))
 4912    );
 4913 
 4914    scic_controller->interrupt_coalesce_number = (U16)coalesce_number;
 4915    scic_controller->interrupt_coalesce_timeout = coalesce_timeout/100;
 4916 
 4917    return SCI_SUCCESS;
 4918 }
 4919 
 4920 // ---------------------------------------------------------------------------
 4921 
 4922 void scic_controller_get_interrupt_coalescence(
 4923    SCI_CONTROLLER_HANDLE_T   controller,
 4924    U32                     * coalesce_number,
 4925    U32                     * coalesce_timeout
 4926 )
 4927 {
 4928    SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4929    *coalesce_number = scic_controller->interrupt_coalesce_number;
 4930    *coalesce_timeout = scic_controller->interrupt_coalesce_timeout;
 4931 }
 4932 
 4933 #endif // !defined(DISABLE_INTERRUPTS)
 4934 
 4935 // ---------------------------------------------------------------------------
 4936 
 4937 U32 scic_controller_get_scratch_ram_size(
 4938    SCI_CONTROLLER_HANDLE_T   controller
 4939 )
 4940 {
 4941    return SCU_SCRATCH_RAM_SIZE_IN_DWORDS;
 4942 }
 4943 
 4944 // ---------------------------------------------------------------------------
 4945 
 4946 SCI_STATUS scic_controller_read_scratch_ram_dword(
 4947    SCI_CONTROLLER_HANDLE_T   controller,
 4948    U32                       offset,
 4949    U32                     * value
 4950 )
 4951 {
 4952    U32 zpt_index;
 4953    SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 4954    U32 status = SMU_SMUCSR_READ(scic_controller);
 4955 
 4956    //Check if the SCU Scratch RAM been initialized, if not return zeros
 4957    if ((status & SCU_RAM_INIT_COMPLETED) != SCU_RAM_INIT_COMPLETED)
 4958    {
 4959       *value = 0x00000000;
 4960       return SCI_SUCCESS;
 4961    }
 4962 
 4963    if (offset < scic_controller_get_scratch_ram_size(controller))
 4964    {
 4965       if(offset <= SCU_MAX_ZPT_DWORD_INDEX)
 4966       {
 4967          zpt_index = offset + (offset - (offset % 4)) + 4;
 4968 
 4969          *value = scu_controller_scratch_ram_register_read(scic_controller,zpt_index);
 4970       }
 4971       else //offset > SCU_MAX_ZPT_DWORD_INDEX
 4972       {
 4973          offset = offset - 132;
 4974 
 4975          zpt_index = offset + (offset - (offset % 4)) + 4;
 4976 
 4977          *value = scu_controller_scratch_ram_register_read_ext(scic_controller,zpt_index);
 4978       }
 4979 
 4980       return SCI_SUCCESS;
 4981    }
 4982    else
 4983    {
 4984       return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 4985    }
 4986 }
 4987 
 4988 // ---------------------------------------------------------------------------
 4989 
 4990 SCI_STATUS scic_controller_write_scratch_ram_dword(
 4991    SCI_CONTROLLER_HANDLE_T   controller,
 4992    U32                       offset,
 4993    U32                       value
 4994 )
 4995 {
 4996    U32 zpt_index;
 4997 
 4998    if (offset < scic_controller_get_scratch_ram_size(controller))
 4999    {
 5000       SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 5001 
 5002       if(offset <= SCU_MAX_ZPT_DWORD_INDEX)
 5003       {
 5004          zpt_index = offset + (offset - (offset % 4)) + 4;
 5005 
 5006          scu_controller_scratch_ram_register_write(scic_controller,zpt_index,value);
 5007       }
 5008       else //offset > SCU_MAX_ZPT_DWORD_INDEX
 5009       {
 5010          offset = offset - 132;
 5011 
 5012          zpt_index = offset + (offset - (offset % 4)) + 4;
 5013 
 5014          scu_controller_scratch_ram_register_write_ext(scic_controller,zpt_index,value);
 5015 
 5016       }
 5017 
 5018       return SCI_SUCCESS;
 5019    }
 5020    else
 5021    {
 5022       return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 5023    }
 5024 }
 5025 
 5026 // ---------------------------------------------------------------------------
 5027 
 5028 SCI_STATUS scic_controller_suspend(
 5029    SCI_CONTROLLER_HANDLE_T   controller
 5030 )
 5031 {
 5032    SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
 5033    U8 index;
 5034 
 5035    // As a precaution, disable interrupts.  The user is required
 5036    // to re-enable interrupts if so desired after the call.
 5037    scic_controller_disable_interrupts(controller);
 5038 
 5039    // Stop all the timers
 5040    // Maybe change the states of the objects to avoid processing stuff.
 5041 
 5042 
 5043    // Suspend the Ports in order to ensure no unexpected
 5044    // frame reception occurs on the links from the target
 5045    for (index = 0; index < SCI_MAX_PORTS; index++)
 5046       scic_sds_port_suspend_port_task_scheduler(
 5047          &(this_controller->port_table[index]));
 5048 
 5049    // Disable/Reset the completion queue and unsolicited frame
 5050    // queue.
 5051    SMU_CQGR_WRITE(this_controller, 0x00000000);
 5052    SCU_UFQGP_WRITE(this_controller, 0x00000000);
 5053 
 5054    // Clear any interrupts that may be pending or may have been generated
 5055    // by setting CQGR and CQPR back to 0
 5056    SMU_ISR_WRITE(this_controller, 0xFFFFFFFF);
 5057 
 5058    //reset the software get pointer to completion queue.
 5059    this_controller->completion_queue_get = 0;
 5060 
 5061    return SCI_SUCCESS;
 5062 }
 5063 
 5064 // ---------------------------------------------------------------------------
 5065 
 5066 SCI_STATUS scic_controller_resume(
 5067    SCI_CONTROLLER_HANDLE_T   controller
 5068 )
 5069 {
 5070    SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
 5071    U8 index;
 5072 
 5073    // Initialize the completion queue and unsolicited frame queue.
 5074    scic_sds_controller_initialize_completion_queue(this_controller);
 5075    scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
 5076 
 5077    this_controller->restrict_completions = FALSE;
 5078 
 5079    // Release the port suspensions to allow for further successful
 5080    // operation.
 5081    for (index = 0; index < SCI_MAX_PORTS; index++)
 5082       scic_sds_port_resume_port_task_scheduler(
 5083          &(this_controller->port_table[index]));
 5084 
 5085    //check the link layer status register DWORD sync acquired bit to detect
 5086    //link down event. If there is any link down event happened during controller
 5087    //suspension, restart phy state machine.
 5088    for (index = 0; index < SCI_MAX_PHYS; index ++)
 5089    {
 5090       SCIC_SDS_PHY_T * curr_phy = &this_controller->phy_table[index];
 5091       U32 link_layer_status = SCU_SAS_LLSTA_READ(curr_phy);
 5092 
 5093       if ((link_layer_status & SCU_SAS_LLSTA_DWORD_SYNCA_BIT) == 0)
 5094       {
 5095          //Need to put the phy back to start OOB. Then an appropriate link event
 5096          //message will be send to scic user.
 5097          scic_sds_phy_restart_starting_state(curr_phy);
 5098       }
 5099    }
 5100 
 5101    return SCI_SUCCESS;
 5102 }
 5103 
 5104 // ---------------------------------------------------------------------------
 5105 
 5106 SCI_STATUS scic_controller_transition(
 5107    SCI_CONTROLLER_HANDLE_T   controller,
 5108    BOOL                      restrict_completions
 5109 )
 5110 {
 5111    SCI_STATUS              result = SCI_FAILURE_INVALID_STATE;
 5112    SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
 5113    U8                      index;
 5114 
 5115    SCIC_LOG_TRACE((
 5116       sci_base_object_get_logger(controller),
 5117       SCIC_LOG_OBJECT_CONTROLLER,
 5118       "scic_controller_transition(0x%x) enter\n",
 5119       controller
 5120    ));
 5121 
 5122    if (this_controller->parent.state_machine.current_state_id
 5123        == SCI_BASE_CONTROLLER_STATE_READY)
 5124    {
 5125       // Ensure that there are no outstanding IO operations at this
 5126       // time.
 5127       for (index = 0; index < SCI_MAX_PORTS; index++)
 5128       {
 5129          if (this_controller->port_table[index].started_request_count != 0)
 5130             return result;
 5131       }
 5132 
 5133       scic_controller_suspend(controller);
 5134 
 5135       // Loop through the memory descriptor list and reprogram
 5136       // the silicon memory registers accordingly.
 5137       result = scic_sds_controller_validate_memory_descriptor_table(
 5138                   this_controller);
 5139       if (result == SCI_SUCCESS)
 5140       {
 5141          scic_sds_controller_ram_initialization(this_controller);
 5142          this_controller->restrict_completions = restrict_completions;
 5143       }
 5144 
 5145       scic_controller_resume(controller);
 5146    }
 5147 
 5148    return result;
 5149 }
 5150 
 5151 // ---------------------------------------------------------------------------
 5152 
 5153 SCI_STATUS scic_controller_get_max_ports(
 5154    SCI_CONTROLLER_HANDLE_T   controller,
 5155    U8                      * count
 5156 )
 5157 {
 5158    *count = SCI_MAX_PORTS;
 5159    return SCI_SUCCESS;
 5160 }
 5161 
 5162 // ---------------------------------------------------------------------------
 5163 
 5164 SCI_STATUS scic_controller_get_max_phys(
 5165    SCI_CONTROLLER_HANDLE_T   controller,
 5166    U8                      * count
 5167 )
 5168 {
 5169    *count = SCI_MAX_PHYS;
 5170    return SCI_SUCCESS;
 5171 }
 5172 
 5173 
 5174 //******************************************************************************
 5175 //* CONTROLLER STATE MACHINE
 5176 //******************************************************************************
 5177 
 5178 /**
 5179  * This macro returns the maximum number of logical ports supported by the
 5180  * hardware. The caller passes in the value read from the device context
 5181  * capacity register and this macro will mash and shift the value
 5182  * appropriately.
 5183  */
 5184 #define smu_dcc_get_max_ports(dcc_value) \
 5185    ( \
 5186      (    ((U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK)) \
 5187        >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT ) + 1\
 5188    )
 5189 
 5190 /**
 5191  * This macro returns the maximum number of task contexts supported by the
 5192  * hardware. The caller passes in the value read from the device context
 5193  * capacity register and this macro will mash and shift the value
 5194  * appropriately.
 5195  */
 5196 #define smu_dcc_get_max_task_context(dcc_value) \
 5197    ( \
 5198      (   ((U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK)) \
 5199        >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT ) + 1\
 5200    )
 5201 
 5202 /**
 5203  * This macro returns the maximum number of remote node contexts supported
 5204  * by the hardware. The caller passes in the value read from the device
 5205  * context capacity register and this macro will mash and shift the value
 5206  * appropriately.
 5207  */
 5208 #define smu_dcc_get_max_remote_node_context(dcc_value) \
 5209    ( \
 5210      (  ( (U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) )\
 5211        >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT ) + 1\
 5212    )
 5213 
 5214 //*****************************************************************************
 5215 //* DEFAULT STATE HANDLERS
 5216 //*****************************************************************************
 5217 
 5218 /**
 5219  * This method is called when the SCIC_SDS_CONTROLLER default start
 5220  * io/task handler is in place.
 5221  *    - Issue a warning message
 5222  *
 5223  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 5224  *       into a SCIC_SDS_CONTROLLER object.
 5225  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
 5226  *       used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
 5227  * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
 5228  *       would be cast to a SCIC_SDS_IO_REQUEST.
 5229  * @param[in] io_tag This is the IO tag to be assigned to the IO request or
 5230  *       SCI_CONTROLLER_INVALID_IO_TAG.
 5231  *
 5232  * @return SCI_STATUS
 5233  * @retval SCI_FAILURE_INVALID_STATE
 5234  */
 5235 static
 5236 SCI_STATUS scic_sds_controller_default_start_operation_handler(
 5237    SCI_BASE_CONTROLLER_T    *controller,
 5238    SCI_BASE_REMOTE_DEVICE_T *remote_device,
 5239    SCI_BASE_REQUEST_T       *io_request,
 5240    U16                       io_tag
 5241 )
 5242 {
 5243    SCIC_SDS_CONTROLLER_T *this_controller;
 5244    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 5245 
 5246    SCIC_LOG_WARNING((
 5247       sci_base_object_get_logger(this_controller),
 5248       SCIC_LOG_OBJECT_CONTROLLER,
 5249       "SCIC Controller requested to start an io/task from invalid state %d\n",
 5250       sci_base_state_machine_get_state(
 5251          scic_sds_controller_get_base_state_machine(this_controller))
 5252    ));
 5253 
 5254    return SCI_FAILURE_INVALID_STATE;
 5255 }
 5256 
 5257 /**
 5258  * This method is called when the SCIC_SDS_CONTROLLER default
 5259  * request handler is in place.
 5260  *    - Issue a warning message
 5261  *
 5262  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 5263  *       into a SCIC_SDS_CONTROLLER object.
 5264  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
 5265  *       used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
 5266  * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
 5267  *       would be cast to a SCIC_SDS_IO_REQUEST.
 5268  *
 5269  * @return SCI_STATUS
 5270  * @retval SCI_FAILURE_INVALID_STATE
 5271  */
 5272 static
 5273 SCI_STATUS scic_sds_controller_default_request_handler(
 5274    SCI_BASE_CONTROLLER_T    *controller,
 5275    SCI_BASE_REMOTE_DEVICE_T *remote_device,
 5276    SCI_BASE_REQUEST_T       *io_request
 5277 )
 5278 {
 5279    SCIC_SDS_CONTROLLER_T *this_controller;
 5280    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 5281 
 5282    SCIC_LOG_WARNING((
 5283       sci_base_object_get_logger(this_controller),
 5284       SCIC_LOG_OBJECT_CONTROLLER,
 5285       "SCIC Controller request operation from invalid state %d\n",
 5286       sci_base_state_machine_get_state(
 5287          scic_sds_controller_get_base_state_machine(this_controller))
 5288    ));
 5289 
 5290    return SCI_FAILURE_INVALID_STATE;
 5291 }
 5292 
 5293 //*****************************************************************************
 5294 //* GENERAL (COMMON) STATE HANDLERS
 5295 //*****************************************************************************
 5296 
 5297 /**
 5298  * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
 5299  * reset handler is in place.
 5300  *    - Transition to SCI_BASE_CONTROLLER_STATE_RESETTING
 5301  *
 5302  * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
 5303  *       SCIC_SDS_CONTROLLER object.
 5304  *
 5305  * @return SCI_STATUS
 5306  * @retval SCI_SUCCESS
 5307  */
 5308 static
 5309 SCI_STATUS scic_sds_controller_general_reset_handler(
 5310    SCI_BASE_CONTROLLER_T *controller
 5311 )
 5312 {
 5313    SCIC_SDS_CONTROLLER_T *this_controller;
 5314    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 5315 
 5316    SCIC_LOG_TRACE((
 5317       sci_base_object_get_logger(controller),
 5318       SCIC_LOG_OBJECT_CONTROLLER,
 5319       "scic_sds_controller_resetting_state_enter(0x%x) enter\n",
 5320       controller
 5321    ));
 5322 
 5323    //Release resource. So far only resource to be released are timers.
 5324    scic_sds_controller_release_resource(this_controller);
 5325 
 5326    // The reset operation is not a graceful cleanup just perform the state
 5327    // transition.
 5328    sci_base_state_machine_change_state(
 5329       scic_sds_controller_get_base_state_machine(this_controller),
 5330       SCI_BASE_CONTROLLER_STATE_RESETTING
 5331    );
 5332 
 5333    return SCI_SUCCESS;
 5334 }
 5335 
 5336 //*****************************************************************************
 5337 //* RESET STATE HANDLERS
 5338 //*****************************************************************************
 5339 
 5340 /**
 5341  * This method is the SCIC_SDS_CONTROLLER initialize handler for the reset
 5342  * state.
 5343  *    - Currently this function does nothing
 5344  *
 5345  * @param[in] controller This is the SCI_BASE_CONTROLLER object which is cast
 5346  *       into a SCIC_SDS_CONTROLLER object.
 5347  *
 5348  * @return SCI_STATUS
 5349  * @retval SCI_FAILURE
 5350  *
 5351  * @todo This function is not yet implemented and is a valid request from the
 5352  *       reset state.
 5353  */
 5354 static
 5355 SCI_STATUS scic_sds_controller_reset_state_initialize_handler(
 5356    SCI_BASE_CONTROLLER_T *controller
 5357 )
 5358 {
 5359    U32 index;
 5360    SCI_STATUS result = SCI_SUCCESS;
 5361    SCIC_SDS_CONTROLLER_T *this_controller;
 5362 
 5363    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 5364 
 5365    SCIC_LOG_TRACE((
 5366       sci_base_object_get_logger(controller),
 5367       SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
 5368       "scic_sds_controller_reset_state_initialize_handler(0x%x) enter\n",
 5369       controller
 5370    ));
 5371 
 5372    sci_base_state_machine_change_state(
 5373       scic_sds_controller_get_base_state_machine(this_controller),
 5374       SCI_BASE_CONTROLLER_STATE_INITIALIZING
 5375    );
 5376 
 5377    this_controller->timeout_timer = scic_cb_timer_create(
 5378       controller,
 5379       scic_sds_controller_timeout_handler,
 5380       controller
 5381    );
 5382 
 5383    scic_sds_controller_initialize_power_control(this_controller);
 5384 
 5385    /// todo: This should really be done in the reset state enter but
 5386    ///       the controller has not yet been initialized before getting
 5387    ///       to the reset enter state so the PCI BAR is not yet assigned
 5388    scic_sds_controller_reset_hardware(this_controller);
 5389 
 5390 #if defined(ARLINGTON_BUILD)
 5391    scic_sds_controller_lex_atux_initialization(this_controller);
 5392 #elif    defined(PLEASANT_RIDGE_BUILD) \
 5393       || defined(PBG_HBA_A0_BUILD) \
 5394       || defined(PBG_HBA_A2_BUILD)
 5395    scic_sds_controller_afe_initialization(this_controller);
 5396 #elif defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
 5397    // There is nothing to do here for B0 since we do not have to
 5398    // program the AFE registers.
 5399    /// @todo The AFE settings are supposed to be correct for the B0 but
 5400    ///       presently they seem to be wrong.
 5401    scic_sds_controller_afe_initialization(this_controller);
 5402 #else  // !defined(ARLINGTON_BUILD) && !defined(PLEASANT_RIDGE_BUILD)
 5403    // What other systems do we want to add here?
 5404 #endif // !defined(ARLINGTON_BUILD) && !defined(PLEASANT_RIDGE_BUILD)
 5405 
 5406    if (SCI_SUCCESS == result)
 5407    {
 5408       U32 status;
 5409       U32 terminate_loop;
 5410 
 5411       // Take the hardware out of reset
 5412       SMU_SMUSRCR_WRITE(this_controller, 0x00000000);
 5413 
 5414       /// @todo Provide meaningfull error code for hardware failure
 5415       //result = SCI_FAILURE_CONTROLLER_HARDWARE;
 5416       result = SCI_FAILURE;
 5417       terminate_loop = 100;
 5418 
 5419       while (terminate_loop-- && (result != SCI_SUCCESS))
 5420       {
 5421          // Loop until the hardware reports success
 5422          scic_cb_stall_execution(SCU_CONTEXT_RAM_INIT_STALL_TIME);
 5423          status = SMU_SMUCSR_READ(this_controller);
 5424 
 5425          if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED)
 5426          {
 5427             result = SCI_SUCCESS;
 5428          }
 5429       }
 5430    }
 5431 
 5432 #ifdef ARLINGTON_BUILD
 5433    scic_sds_controller_enable_chipwatch(this_controller);
 5434 #endif
 5435 
 5436    if (result == SCI_SUCCESS)
 5437    {
 5438       U32 max_supported_ports;
 5439       U32 max_supported_devices;
 5440       U32 max_supported_io_requests;
 5441       U32 device_context_capacity;
 5442 
 5443       // Determine what are the actaul device capacities that the
 5444       // hardware will support
 5445       device_context_capacity = SMU_DCC_READ(this_controller);
 5446 
 5447       max_supported_ports =
 5448          smu_dcc_get_max_ports(device_context_capacity);
 5449       max_supported_devices =
 5450          smu_dcc_get_max_remote_node_context(device_context_capacity);
 5451       max_supported_io_requests =
 5452          smu_dcc_get_max_task_context(device_context_capacity);
 5453 
 5454       // Make all PEs that are unassigned match up with the logical ports
 5455       for (index = 0; index < max_supported_ports; index++)
 5456       {
 5457          scu_register_write(
 5458             this_controller,
 5459             this_controller->scu_registers->peg0.ptsg.protocol_engine[index],
 5460             index
 5461          );
 5462       }
 5463 
 5464       // Now that we have the correct hardware reported minimum values
 5465       // build the MDL for the controller.  Default to a performance
 5466       // configuration.
 5467       scic_controller_set_mode(this_controller, SCI_MODE_SPEED);
 5468 
 5469       // Record the smaller of the two capacity values
 5470       this_controller->logical_port_entries =
 5471          MIN(max_supported_ports, this_controller->logical_port_entries);
 5472 
 5473       this_controller->task_context_entries =
 5474          MIN(max_supported_io_requests, this_controller->task_context_entries);
 5475 
 5476       this_controller->remote_node_entries =
 5477          MIN(max_supported_devices, this_controller->remote_node_entries);
 5478    }
 5479 
 5480    // Initialize hardware PCI Relaxed ordering in DMA engines
 5481    if (result == SCI_SUCCESS)
 5482    {
 5483       U32 dma_configuration;
 5484 
 5485       // Configure the payload DMA
 5486       dma_configuration = SCU_PDMACR_READ(this_controller);
 5487       dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
 5488       SCU_PDMACR_WRITE(this_controller, dma_configuration);
 5489 
 5490       // Configure the control DMA
 5491       dma_configuration = SCU_CDMACR_READ(this_controller);
 5492       dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
 5493       SCU_CDMACR_WRITE(this_controller, dma_configuration);
 5494    }
 5495 
 5496    // Initialize the PHYs before the PORTs because the PHY registers
 5497    // are accessed during the port initialization.
 5498    if (result == SCI_SUCCESS)
 5499    {
 5500       // Initialize the phys
 5501       for (index = 0;
 5502            (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS);
 5503            index++)
 5504       {
 5505          result = scic_sds_phy_initialize(
 5506             &this_controller->phy_table[index],
 5507             &this_controller->scu_registers->peg0.pe[index].tl,
 5508             &this_controller->scu_registers->peg0.pe[index].ll
 5509          );
 5510       }
 5511    }
 5512 
 5513    //Initialize the SGPIO Unit for HARDWARE controlled SGPIO
 5514    if(result == SCI_SUCCESS)
 5515    {
 5516       scic_sgpio_hardware_initialize(this_controller);
 5517    }
 5518 
 5519    if (result == SCI_SUCCESS)
 5520    {
 5521       // Initialize the logical ports
 5522       for (index = 0;
 5523               (index < this_controller->logical_port_entries)
 5524            && (result == SCI_SUCCESS);
 5525            index++)
 5526       {
 5527          result = scic_sds_port_initialize(
 5528             &this_controller->port_table[index],
 5529             &this_controller->scu_registers->peg0.ptsg.port[index],
 5530             &this_controller->scu_registers->peg0.ptsg.protocol_engine,
 5531             &this_controller->scu_registers->peg0.viit[index]
 5532          );
 5533       }
 5534    }
 5535 
 5536    if (SCI_SUCCESS == result)
 5537    {
 5538       result = scic_sds_port_configuration_agent_initialize(
 5539                   this_controller,
 5540                   &this_controller->port_agent
 5541                );
 5542    }
 5543 
 5544    // Advance the controller state machine
 5545    if (result == SCI_SUCCESS)
 5546    {
 5547       sci_base_state_machine_change_state(
 5548          scic_sds_controller_get_base_state_machine(this_controller),
 5549          SCI_BASE_CONTROLLER_STATE_INITIALIZED
 5550       );
 5551    }
 5552    else
 5553    {
 5554       //stay in the same state and release the resource
 5555       scic_sds_controller_release_resource(this_controller);
 5556 
 5557       SCIC_LOG_TRACE((
 5558          sci_base_object_get_logger(controller),
 5559          SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
 5560          "Invalid Port Configuration from scic_sds_controller_reset_state_initialize_handler(0x%x) \n",
 5561          controller
 5562       ));
 5563 
 5564    }
 5565 
 5566    return result;
 5567 }
 5568 
 5569 //*****************************************************************************
 5570 //* INITIALIZED STATE HANDLERS
 5571 //*****************************************************************************
 5572 
 5573 /**
 5574  * This method is the SCIC_SDS_CONTROLLER start handler for the initialized
 5575  * state.
 5576  *    - Validate we have a good memory descriptor table
 5577  *    - Initialze the physical memory before programming the hardware
 5578  *    - Program the SCU hardware with the physical memory addresses passed in
 5579  *      the memory descriptor table.
 5580  *    - Initialzie the TCi pool
 5581  *    - Initialize the RNi pool
 5582  *    - Initialize the completion queue
 5583  *    - Initialize the unsolicited frame data
 5584  *    - Take the SCU port task scheduler out of reset
 5585  *    - Start the first phy object.
 5586  *    - Transition to SCI_BASE_CONTROLLER_STATE_STARTING.
 5587  *
 5588  * @param[in] controller This is the SCI_BASE_CONTROLLER object which is cast
 5589  *       into a SCIC_SDS_CONTROLLER object.
 5590  * @param[in] timeout This is the allowed time for the controller object to
 5591  *       reach the started state.
 5592  *
 5593  * @return SCI_STATUS
 5594  * @retval SCI_SUCCESS if all of the controller start operations complete
 5595  * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD if one or more of the
 5596  *         memory descriptor fields is invalid.
 5597  */
 5598 static
 5599 SCI_STATUS scic_sds_controller_initialized_state_start_handler(
 5600    SCI_BASE_CONTROLLER_T * controller,
 5601    U32                     timeout
 5602 )
 5603 {
 5604    U16                     index;
 5605    SCI_STATUS              result;
 5606    SCIC_SDS_CONTROLLER_T * this_controller;
 5607 
 5608    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 5609 
 5610    // Make sure that the SCI User filled in the memory descriptor table correctly
 5611    result = scic_sds_controller_validate_memory_descriptor_table(this_controller);
 5612 
 5613    if (result == SCI_SUCCESS)
 5614    {
 5615       // The memory descriptor list looks good so program the hardware
 5616       scic_sds_controller_ram_initialization(this_controller);
 5617    }
 5618 
 5619    if (SCI_SUCCESS == result)
 5620    {
 5621       // Build the TCi free pool
 5622       sci_pool_initialize(this_controller->tci_pool);
 5623       for (index = 0; index < this_controller->task_context_entries; index++)
 5624       {
 5625          sci_pool_put(this_controller->tci_pool, index);
 5626       }
 5627 
 5628       // Build the RNi free pool
 5629       scic_sds_remote_node_table_initialize(
 5630          &this_controller->available_remote_nodes,
 5631          this_controller->remote_node_entries
 5632       );
 5633    }
 5634 
 5635    if (SCI_SUCCESS == result)
 5636    {
 5637       // Before anything else lets make sure we will not be interrupted
 5638       // by the hardware.
 5639       scic_controller_disable_interrupts(controller);
 5640 
 5641       // Enable the port task scheduler
 5642       scic_sds_controller_enable_port_task_scheduler(this_controller);
 5643 
 5644       // Assign all the task entries to this controller physical function
 5645       scic_sds_controller_assign_task_entries(this_controller);
 5646 
 5647       // Now initialze the completion queue
 5648       scic_sds_controller_initialize_completion_queue(this_controller);
 5649 
 5650       // Initialize the unsolicited frame queue for use
 5651       scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
 5652 
 5653       // Setup the phy start timer
 5654       result = scic_sds_controller_initialize_phy_startup(this_controller);
 5655    }
 5656 
 5657    // Start all of the ports on this controller
 5658    for (
 5659           index = 0;
 5660           (index < this_controller->logical_port_entries) && (result == SCI_SUCCESS);
 5661           index++
 5662        )
 5663    {
 5664       result = this_controller->port_table[index].
 5665          state_handlers->parent.start_handler(&this_controller->port_table[index].parent);
 5666    }
 5667 
 5668    if (SCI_SUCCESS == result)
 5669    {
 5670       scic_sds_controller_start_next_phy(this_controller);
 5671 
 5672       // See if the user requested to timeout this operation.
 5673       if (timeout != 0)
 5674          scic_cb_timer_start(controller, this_controller->timeout_timer, timeout);
 5675 
 5676       sci_base_state_machine_change_state(
 5677          scic_sds_controller_get_base_state_machine(this_controller),
 5678          SCI_BASE_CONTROLLER_STATE_STARTING
 5679       );
 5680    }
 5681 
 5682    return result;
 5683 }
 5684 
 5685 //*****************************************************************************
 5686 //* STARTING STATE HANDLERS
 5687 //*****************************************************************************
 5688 
 5689 /**
 5690  * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
 5691  * link up handler is called.  This method will perform the following:
 5692  *    - Stop the phy timer
 5693  *    - Start the next phy
 5694  *    - Report the link up condition to the port object
 5695  *
 5696  * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the link up
 5697  *       notification.
 5698  * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
 5699  * @param[in] phy This is the SCIC_SDS_PHY which has gone link up.
 5700  *
 5701  * @return none
 5702  */
 5703 static
 5704 void scic_sds_controller_starting_state_link_up_handler(
 5705    SCIC_SDS_CONTROLLER_T *this_controller,
 5706    SCIC_SDS_PORT_T       *port,
 5707    SCIC_SDS_PHY_T        *phy
 5708 )
 5709 {
 5710    scic_sds_controller_phy_timer_stop(this_controller);
 5711 
 5712    this_controller->port_agent.link_up_handler(
 5713       this_controller, &this_controller->port_agent, port, phy
 5714    );
 5715    //scic_sds_port_link_up(port, phy);
 5716 
 5717    scic_sds_controller_start_next_phy(this_controller);
 5718 }
 5719 
 5720 /**
 5721  * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
 5722  * link down handler is called.
 5723  *    - Report the link down condition to the port object
 5724  *
 5725  * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the
 5726  *       link down notification.
 5727  * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
 5728  * @param[in] phy This is the SCIC_SDS_PHY which has gone link down.
 5729  *
 5730  * @return none
 5731  */
 5732 static
 5733 void scic_sds_controller_starting_state_link_down_handler(
 5734    SCIC_SDS_CONTROLLER_T *this_controller,
 5735    SCIC_SDS_PORT_T       *port,
 5736    SCIC_SDS_PHY_T        *phy
 5737 )
 5738 {
 5739    this_controller->port_agent.link_down_handler(
 5740       this_controller, &this_controller->port_agent, port, phy
 5741    );
 5742    //scic_sds_port_link_down(port, phy);
 5743 }
 5744 
 5745 //*****************************************************************************
 5746 //* READY STATE HANDLERS
 5747 //*****************************************************************************
 5748 
 5749 /**
 5750  * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
 5751  * stop handler is called.
 5752  *    - Start the timeout timer
 5753  *    - Transition to SCI_BASE_CONTROLLER_STATE_STOPPING.
 5754  *
 5755  * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
 5756  *       SCIC_SDS_CONTROLLER object.
 5757  * @param[in] timeout The timeout for when the stop operation should report a
 5758  *       failure.
 5759  *
 5760  * @return SCI_STATUS
 5761  * @retval SCI_SUCCESS
 5762  */
 5763 static
 5764 SCI_STATUS scic_sds_controller_ready_state_stop_handler(
 5765    SCI_BASE_CONTROLLER_T *controller,
 5766    U32                   timeout
 5767 )
 5768 {
 5769    SCIC_SDS_CONTROLLER_T *this_controller;
 5770    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 5771 
 5772    // See if the user requested to timeout this operation
 5773    if (timeout != 0)
 5774       scic_cb_timer_start(controller, this_controller->timeout_timer, timeout);
 5775 
 5776    sci_base_state_machine_change_state(
 5777       scic_sds_controller_get_base_state_machine(this_controller),
 5778       SCI_BASE_CONTROLLER_STATE_STOPPING
 5779    );
 5780 
 5781    return SCI_SUCCESS;
 5782 }
 5783 
 5784 /**
 5785  * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
 5786  * and the start io handler is called.
 5787  *    - Start the io request on the remote device
 5788  *    - if successful
 5789  *       - assign the io_request to the io_request_table
 5790  *       - post the request to the hardware
 5791  *
 5792  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 5793  *       into a SCIC_SDS_CONTROLLER object.
 5794  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
 5795  *       SCIC_SDS_REMOTE_DEVICE object.
 5796  * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
 5797  *       SCIC_SDS_IO_REQUEST object.
 5798  * @param[in] io_tag This is the IO tag to be assigned to the IO request or
 5799  *       SCI_CONTROLLER_INVALID_IO_TAG.
 5800  *
 5801  * @return SCI_STATUS
 5802  * @retval SCI_SUCCESS if the start io operation succeeds
 5803  * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
 5804  *         allocated for the io request.
 5805  * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
 5806  *         state to accept io requests.
 5807  *
 5808  * @todo How does the io_tag parameter get assigned to the io request?
 5809  */
 5810 static
 5811 SCI_STATUS scic_sds_controller_ready_state_start_io_handler(
 5812    SCI_BASE_CONTROLLER_T    *controller,
 5813    SCI_BASE_REMOTE_DEVICE_T *remote_device,
 5814    SCI_BASE_REQUEST_T       *io_request,
 5815    U16                       io_tag
 5816 )
 5817 {
 5818    SCI_STATUS status;
 5819 
 5820    SCIC_SDS_CONTROLLER_T    *this_controller;
 5821    SCIC_SDS_REQUEST_T       *the_request;
 5822    SCIC_SDS_REMOTE_DEVICE_T *the_device;
 5823 
 5824    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 5825    the_request = (SCIC_SDS_REQUEST_T *)io_request;
 5826    the_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
 5827 
 5828    status = scic_sds_remote_device_start_io(this_controller, the_device, the_request);
 5829 
 5830    if (status == SCI_SUCCESS)
 5831    {
 5832       this_controller->io_request_table[
 5833             scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
 5834 
 5835       scic_sds_controller_post_request(
 5836          this_controller,
 5837          scic_sds_request_get_post_context(the_request)
 5838       );
 5839    }
 5840 
 5841    return status;
 5842 }
 5843 
 5844 /**
 5845  * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
 5846  * and the complete io handler is called.
 5847  *    - Complete the io request on the remote device
 5848  *    - if successful
 5849  *       - remove the io_request to the io_request_table
 5850  *
 5851  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 5852  *       into a SCIC_SDS_CONTROLLER object.
 5853  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
 5854  *       SCIC_SDS_REMOTE_DEVICE object.
 5855  * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
 5856  *       SCIC_SDS_IO_REQUEST object.
 5857  *
 5858  * @return SCI_STATUS
 5859  * @retval SCI_SUCCESS if the start io operation succeeds
 5860  * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
 5861  *         state to accept io requests.
 5862  */
 5863 static
 5864 SCI_STATUS scic_sds_controller_ready_state_complete_io_handler(
 5865    SCI_BASE_CONTROLLER_T    *controller,
 5866    SCI_BASE_REMOTE_DEVICE_T *remote_device,
 5867    SCI_BASE_REQUEST_T       *io_request
 5868 )
 5869 {
 5870    U16        index;
 5871    SCI_STATUS status;
 5872    SCIC_SDS_CONTROLLER_T    *this_controller;
 5873    SCIC_SDS_REQUEST_T       *the_request;
 5874    SCIC_SDS_REMOTE_DEVICE_T *the_device;
 5875 
 5876    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 5877    the_request = (SCIC_SDS_REQUEST_T *)io_request;
 5878    the_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
 5879 
 5880    status = scic_sds_remote_device_complete_io(
 5881                   this_controller, the_device, the_request);
 5882 
 5883    if (status == SCI_SUCCESS)
 5884    {
 5885       index = scic_sds_io_tag_get_index(the_request->io_tag);
 5886       this_controller->io_request_table[index] = SCI_INVALID_HANDLE;
 5887    }
 5888 
 5889    return status;
 5890 }
 5891 
 5892 /**
 5893  * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
 5894  * and the continue io handler is called.
 5895  *
 5896  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 5897  *       into a SCIC_SDS_CONTROLLER object.
 5898  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
 5899  *       SCIC_SDS_REMOTE_DEVICE object.
 5900  * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
 5901  *       SCIC_SDS_IO_REQUEST object.
 5902  *
 5903  * @return SCI_STATUS
 5904  */
 5905 static
 5906 SCI_STATUS scic_sds_controller_ready_state_continue_io_handler(
 5907    SCI_BASE_CONTROLLER_T    *controller,
 5908    SCI_BASE_REMOTE_DEVICE_T *remote_device,
 5909    SCI_BASE_REQUEST_T       *io_request
 5910 )
 5911 {
 5912    SCIC_SDS_CONTROLLER_T *this_controller;
 5913    SCIC_SDS_REQUEST_T    *the_request;
 5914 
 5915    the_request     = (SCIC_SDS_REQUEST_T *)io_request;
 5916    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 5917 
 5918    this_controller->io_request_table[
 5919       scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
 5920 
 5921    scic_sds_controller_post_request(
 5922       this_controller,
 5923       scic_sds_request_get_post_context(the_request)
 5924    );
 5925 
 5926    return SCI_SUCCESS;
 5927 }
 5928 
 5929 /**
 5930  * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
 5931  * and the start task handler is called.
 5932  *    - The remote device is requested to start the task request
 5933  *    - if successful
 5934  *       - assign the task to the io_request_table
 5935  *       - post the request to the SCU hardware
 5936  *
 5937  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 5938  *       into a SCIC_SDS_CONTROLLER object.
 5939  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
 5940  *       SCIC_SDS_REMOTE_DEVICE object.
 5941  * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
 5942  *       SCIC_SDS_IO_REQUEST object.
 5943  * @param[in] task_tag This is the task tag to be assigned to the task request
 5944  *       or SCI_CONTROLLER_INVALID_IO_TAG.
 5945  *
 5946  * @return SCI_STATUS
 5947  * @retval SCI_SUCCESS if the start io operation succeeds
 5948  * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
 5949  *         allocated for the io request.
 5950  * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
 5951  *         state to accept io requests.
 5952  *
 5953  * @todo How does the io tag get assigned in this code path?
 5954  */
 5955 static
 5956 SCI_STATUS scic_sds_controller_ready_state_start_task_handler(
 5957    SCI_BASE_CONTROLLER_T    *controller,
 5958    SCI_BASE_REMOTE_DEVICE_T *remote_device,
 5959    SCI_BASE_REQUEST_T       *io_request,
 5960    U16                       task_tag
 5961 )
 5962 {
 5963    SCIC_SDS_CONTROLLER_T    *this_controller = (SCIC_SDS_CONTROLLER_T *)
 5964                                                controller;
 5965    SCIC_SDS_REQUEST_T       *the_request     = (SCIC_SDS_REQUEST_T *)
 5966                                                io_request;
 5967    SCIC_SDS_REMOTE_DEVICE_T *the_device      = (SCIC_SDS_REMOTE_DEVICE_T *)
 5968                                                remote_device;
 5969    SCI_STATUS                status;
 5970 
 5971    status = scic_sds_remote_device_start_task(
 5972                this_controller, the_device, the_request
 5973             );
 5974 
 5975    if (status == SCI_SUCCESS)
 5976    {
 5977       this_controller->io_request_table[
 5978          scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
 5979 
 5980       scic_sds_controller_post_request(
 5981          this_controller,
 5982          scic_sds_request_get_post_context(the_request)
 5983       );
 5984    }
 5985    else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS)
 5986    {
 5987       this_controller->io_request_table[
 5988          scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
 5989 
 5990       //We will let framework know this task request started successfully,
 5991       //although core is still woring on starting the request (to post tc when
 5992       //RNC is resumed.)
 5993       status = SCI_SUCCESS;
 5994    }
 5995    return status;
 5996 }
 5997 
 5998 /**
 5999  * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
 6000  * and the terminate request handler is called.
 6001  *    - call the io request terminate function
 6002  *    - if successful
 6003  *       - post the terminate request to the SCU hardware
 6004  *
 6005  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 6006  *       into a SCIC_SDS_CONTROLLER object.
 6007  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
 6008  *       SCIC_SDS_REMOTE_DEVICE object.
 6009  * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
 6010  *       SCIC_SDS_IO_REQUEST object.
 6011  *
 6012  * @return SCI_STATUS
 6013  * @retval SCI_SUCCESS if the start io operation succeeds
 6014  * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
 6015  *         state to accept io requests.
 6016  */
 6017 static
 6018 SCI_STATUS scic_sds_controller_ready_state_terminate_request_handler(
 6019    SCI_BASE_CONTROLLER_T    *controller,
 6020    SCI_BASE_REMOTE_DEVICE_T *remote_device,
 6021    SCI_BASE_REQUEST_T       *io_request
 6022 )
 6023 {
 6024    SCIC_SDS_CONTROLLER_T    *this_controller = (SCIC_SDS_CONTROLLER_T *)
 6025                                                controller;
 6026    SCIC_SDS_REQUEST_T       *the_request     = (SCIC_SDS_REQUEST_T *)
 6027                                                io_request;
 6028    SCI_STATUS                status;
 6029 
 6030    status = scic_sds_io_request_terminate(the_request);
 6031    if (status == SCI_SUCCESS)
 6032    {
 6033       // Utilize the original post context command and or in the POST_TC_ABORT
 6034       // request sub-type.
 6035       scic_sds_controller_post_request(
 6036          this_controller,
 6037          scic_sds_request_get_post_context(the_request)
 6038          | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT
 6039       );
 6040    }
 6041 
 6042    return status;
 6043 }
 6044 
 6045 /**
 6046  * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
 6047  * link up handler is called.  This method will perform the following:
 6048  *    - Stop the phy timer
 6049  *    - Start the next phy
 6050  *    - Report the link up condition to the port object
 6051  *
 6052  * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the link up
 6053  *       notification.
 6054  * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
 6055  * @param[in] phy This is the SCIC_SDS_PHY which has gone link up.
 6056  *
 6057  * @return none
 6058  */
 6059 static
 6060 void scic_sds_controller_ready_state_link_up_handler(
 6061    SCIC_SDS_CONTROLLER_T *this_controller,
 6062    SCIC_SDS_PORT_T       *port,
 6063    SCIC_SDS_PHY_T        *phy
 6064 )
 6065 {
 6066    this_controller->port_agent.link_up_handler(
 6067       this_controller, &this_controller->port_agent, port, phy
 6068    );
 6069 }
 6070 
 6071 /**
 6072  * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
 6073  * link down handler is called.
 6074  *    - Report the link down condition to the port object
 6075  *
 6076  * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the
 6077  *       link down notification.
 6078  * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
 6079  * @param[in] phy This is the SCIC_SDS_PHY which has gone link down.
 6080  *
 6081  * @return none
 6082  */
 6083 static
 6084 void scic_sds_controller_ready_state_link_down_handler(
 6085    SCIC_SDS_CONTROLLER_T *this_controller,
 6086    SCIC_SDS_PORT_T       *port,
 6087    SCIC_SDS_PHY_T        *phy
 6088 )
 6089 {
 6090    this_controller->port_agent.link_down_handler(
 6091       this_controller, &this_controller->port_agent, port, phy
 6092    );
 6093 }
 6094 
 6095 //*****************************************************************************
 6096 //* STOPPING STATE HANDLERS
 6097 //*****************************************************************************
 6098 
 6099 /**
 6100  * This method is called when the SCIC_SDS_CONTROLLER is in a stopping state
 6101  * and the complete io handler is called.
 6102  *    - This function is not yet implemented
 6103  *
 6104  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 6105  *       into a SCIC_SDS_CONTROLLER object.
 6106  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
 6107  *       SCIC_SDS_REMOTE_DEVICE object.
 6108  * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
 6109  *       SCIC_SDS_IO_REQUEST object.
 6110  *
 6111  * @return SCI_STATUS
 6112  * @retval SCI_FAILURE
 6113  */
 6114 static
 6115 SCI_STATUS scic_sds_controller_stopping_state_complete_io_handler(
 6116    SCI_BASE_CONTROLLER_T    *controller,
 6117    SCI_BASE_REMOTE_DEVICE_T *remote_device,
 6118    SCI_BASE_REQUEST_T       *io_request
 6119 )
 6120 {
 6121    SCIC_SDS_CONTROLLER_T *this_controller;
 6122    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 6123 
 6124    /// @todo Implement this function
 6125    return SCI_FAILURE;
 6126 }
 6127 
 6128 /**
 6129  * This method is called when the SCIC_SDS_CONTROLLER is in a stopping state
 6130  * and the a remote device has stopped.
 6131  *
 6132  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 6133  *       into a SCIC_SDS_CONTROLLER object.
 6134  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
 6135  *       SCIC_SDS_REMOTE_DEVICE object.
 6136  *
 6137  * @return none
 6138  */
 6139 static
 6140 void scic_sds_controller_stopping_state_device_stopped_handler(
 6141    SCIC_SDS_CONTROLLER_T    * controller,
 6142    SCIC_SDS_REMOTE_DEVICE_T * remote_device
 6143 )
 6144 {
 6145    if (!scic_sds_controller_has_remote_devices_stopping(controller))
 6146    {
 6147       sci_base_state_machine_change_state(
 6148          &controller->parent.state_machine,
 6149          SCI_BASE_CONTROLLER_STATE_STOPPED
 6150       );
 6151    }
 6152 }
 6153 
 6154 //*****************************************************************************
 6155 //* STOPPED STATE HANDLERS
 6156 //*****************************************************************************
 6157 
 6158 //*****************************************************************************
 6159 //* FAILED STATE HANDLERS
 6160 //*****************************************************************************
 6161 
 6162 /**
 6163  * This method is called when the SCIC_SDS_CONTROLLER failed state start
 6164  * io/task handler is in place.
 6165  *    - Issue a warning message
 6166  *
 6167  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 6168  *       into a SCIC_SDS_CONTROLLER object.
 6169  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
 6170  *       used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
 6171  * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
 6172  *       would be cast to a SCIC_SDS_IO_REQUEST.
 6173  * @param[in] io_tag This is the IO tag to be assigned to the IO request or
 6174  *       SCI_CONTROLLER_INVALID_IO_TAG.
 6175  *
 6176  * @return SCI_FAILURE
 6177  * @retval SCI_FAILURE
 6178  */
 6179 static
 6180 SCI_STATUS scic_sds_controller_failed_state_start_operation_handler(
 6181    SCI_BASE_CONTROLLER_T    *controller,
 6182    SCI_BASE_REMOTE_DEVICE_T *remote_device,
 6183    SCI_BASE_REQUEST_T       *io_request,
 6184    U16                       io_tag
 6185 )
 6186 {
 6187    SCIC_SDS_CONTROLLER_T *this_controller;
 6188    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 6189 
 6190    SCIC_LOG_WARNING((
 6191       sci_base_object_get_logger(this_controller),
 6192       SCIC_LOG_OBJECT_CONTROLLER,
 6193       "SCIC Controller requested to start an io/task from failed state %d\n",
 6194       sci_base_state_machine_get_state(
 6195          scic_sds_controller_get_base_state_machine(this_controller))
 6196    ));
 6197 
 6198    return SCI_FAILURE;
 6199 }
 6200 
 6201 /**
 6202  * This method is called when the SCIC_SDS_CONTROLLER is in the failed state
 6203  * reset handler is in place.
 6204  *    - Transition to SCI_BASE_CONTROLLER_STATE_RESETTING
 6205  *
 6206  * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
 6207  *       SCIC_SDS_CONTROLLER object.
 6208  *
 6209  * @return SCI_STATUS
 6210  * @retval SCI_FAILURE if fatal memory error occurred
 6211  */
 6212 static
 6213 SCI_STATUS scic_sds_controller_failed_state_reset_handler(
 6214    SCI_BASE_CONTROLLER_T *controller
 6215 )
 6216 {
 6217     SCIC_SDS_CONTROLLER_T *this_controller;
 6218     this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
 6219 
 6220     if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR) {
 6221         SCIC_LOG_TRACE((
 6222            sci_base_object_get_logger(controller),
 6223            SCIC_LOG_OBJECT_CONTROLLER,
 6224            "scic_sds_controller_resetting_state_enter(0x%x) enter\n not allowed with fatal memory error",
 6225            controller
 6226         ));
 6227 
 6228         return SCI_FAILURE;
 6229     } else {
 6230         return scic_sds_controller_general_reset_handler(controller);
 6231     }
 6232 }
 6233 
 6234 /**
 6235  * This method is called when the SCIC_SDS_CONTROLLER is in the failed state
 6236  * and the terminate request handler is called.
 6237  *    - call the io request terminate function
 6238  *    - if successful
 6239  *       - post the terminate request to the SCU hardware
 6240  *
 6241  * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
 6242  *       into a SCIC_SDS_CONTROLLER object.
 6243  * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
 6244  *       SCIC_SDS_REMOTE_DEVICE object.
 6245  * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
 6246  *       SCIC_SDS_IO_REQUEST object.
 6247  *
 6248  * @return SCI_STATUS
 6249  * @retval SCI_SUCCESS if the start io operation succeeds
 6250  * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
 6251  *         state to accept io requests.
 6252  */
 6253 static
 6254 SCI_STATUS scic_sds_controller_failed_state_terminate_request_handler(
 6255    SCI_BASE_CONTROLLER_T    *controller,
 6256    SCI_BASE_REMOTE_DEVICE_T *remote_device,
 6257    SCI_BASE_REQUEST_T       *io_request
 6258 )
 6259 {
 6260    SCIC_SDS_REQUEST_T       *the_request     = (SCIC_SDS_REQUEST_T *)
 6261                                                io_request;
 6262 
 6263    return scic_sds_io_request_terminate(the_request);
 6264 }
 6265 
 6266 SCIC_SDS_CONTROLLER_STATE_HANDLER_T
 6267    scic_sds_controller_state_handler_table[SCI_BASE_CONTROLLER_MAX_STATES] =
 6268 {
 6269    // SCI_BASE_CONTROLLER_STATE_INITIAL
 6270    {
 6271       {
 6272          NULL,
 6273          NULL,
 6274          NULL,
 6275          NULL,
 6276          scic_sds_controller_default_start_operation_handler,
 6277          scic_sds_controller_default_start_operation_handler,
 6278          scic_sds_controller_default_request_handler,
 6279          scic_sds_controller_default_request_handler,
 6280          scic_sds_controller_default_request_handler,
 6281          NULL,
 6282          NULL
 6283       },
 6284       scic_sds_controller_default_request_handler,
 6285       NULL,
 6286       NULL,
 6287       NULL,
 6288       NULL
 6289    },
 6290    // SCI_BASE_CONTROLLER_STATE_RESET
 6291    {
 6292       {
 6293          NULL,
 6294          NULL,
 6295          NULL,
 6296          scic_sds_controller_reset_state_initialize_handler,
 6297          scic_sds_controller_default_start_operation_handler,
 6298          scic_sds_controller_default_start_operation_handler,
 6299          scic_sds_controller_default_request_handler,
 6300          scic_sds_controller_default_request_handler,
 6301          scic_sds_controller_default_request_handler,
 6302          NULL,
 6303          NULL
 6304       },
 6305       scic_sds_controller_default_request_handler,
 6306       NULL,
 6307       NULL,
 6308       NULL,
 6309       NULL
 6310    },
 6311    // SCI_BASE_CONTROLLER_STATE_INITIALIZING
 6312    {
 6313       {
 6314          NULL,
 6315          NULL,
 6316          NULL,
 6317          NULL,
 6318          scic_sds_controller_default_start_operation_handler,
 6319          scic_sds_controller_default_start_operation_handler,
 6320          scic_sds_controller_default_request_handler,
 6321          scic_sds_controller_default_request_handler,
 6322          scic_sds_controller_default_request_handler,
 6323          NULL,
 6324          NULL
 6325       },
 6326       scic_sds_controller_default_request_handler,
 6327       NULL,
 6328       NULL,
 6329       NULL,
 6330       NULL
 6331    },
 6332    // SCI_BASE_CONTROLLER_STATE_INITIALIZED
 6333    {
 6334       {
 6335          scic_sds_controller_initialized_state_start_handler,
 6336          NULL,
 6337          NULL,
 6338          NULL,
 6339          scic_sds_controller_default_start_operation_handler,
 6340          scic_sds_controller_default_start_operation_handler,
 6341          scic_sds_controller_default_request_handler,
 6342          scic_sds_controller_default_request_handler,
 6343          scic_sds_controller_default_request_handler,
 6344          NULL,
 6345          NULL
 6346       },
 6347       scic_sds_controller_default_request_handler,
 6348       NULL,
 6349       NULL,
 6350       NULL,
 6351       NULL
 6352    },
 6353    // SCI_BASE_CONTROLLER_STATE_STARTING
 6354    {
 6355       {
 6356          NULL,
 6357          NULL,
 6358          NULL,
 6359          NULL,
 6360          scic_sds_controller_default_start_operation_handler,
 6361          scic_sds_controller_default_start_operation_handler,
 6362          scic_sds_controller_default_request_handler,
 6363          scic_sds_controller_default_request_handler,
 6364          scic_sds_controller_default_request_handler,
 6365          NULL,
 6366          NULL
 6367       },
 6368       scic_sds_controller_default_request_handler,
 6369       scic_sds_controller_starting_state_link_up_handler,
 6370       scic_sds_controller_starting_state_link_down_handler,
 6371       NULL,
 6372       NULL
 6373    },
 6374    // SCI_BASE_CONTROLLER_STATE_READY
 6375    {
 6376       {
 6377          NULL,
 6378          scic_sds_controller_ready_state_stop_handler,
 6379          scic_sds_controller_general_reset_handler,
 6380          NULL,
 6381          scic_sds_controller_ready_state_start_io_handler,
 6382          scic_sds_controller_default_start_operation_handler,
 6383          scic_sds_controller_ready_state_complete_io_handler,
 6384          scic_sds_controller_default_request_handler,
 6385          scic_sds_controller_ready_state_continue_io_handler,
 6386          scic_sds_controller_ready_state_start_task_handler,
 6387          scic_sds_controller_ready_state_complete_io_handler
 6388       },
 6389       scic_sds_controller_ready_state_terminate_request_handler,
 6390       scic_sds_controller_ready_state_link_up_handler,
 6391       scic_sds_controller_ready_state_link_down_handler,
 6392       NULL,
 6393       NULL
 6394    },
 6395    // SCI_BASE_CONTROLLER_STATE_RESETTING
 6396    {
 6397       {
 6398          NULL,
 6399          NULL,
 6400          NULL,
 6401          NULL,
 6402          scic_sds_controller_default_start_operation_handler,
 6403          scic_sds_controller_default_start_operation_handler,
 6404          scic_sds_controller_default_request_handler,
 6405          scic_sds_controller_default_request_handler,
 6406          scic_sds_controller_default_request_handler,
 6407          NULL,
 6408          NULL
 6409       },
 6410       scic_sds_controller_default_request_handler,
 6411       NULL,
 6412       NULL,
 6413       NULL,
 6414       NULL
 6415    },
 6416    // SCI_BASE_CONTROLLER_STATE_STOPPING
 6417    {
 6418       {
 6419          NULL,
 6420          NULL,
 6421          NULL,
 6422          NULL,
 6423          scic_sds_controller_default_start_operation_handler,
 6424          scic_sds_controller_default_start_operation_handler,
 6425          scic_sds_controller_stopping_state_complete_io_handler,
 6426          scic_sds_controller_default_request_handler,
 6427          scic_sds_controller_default_request_handler,
 6428          NULL,
 6429          NULL
 6430       },
 6431       scic_sds_controller_default_request_handler,
 6432       NULL,
 6433       NULL,
 6434       NULL,
 6435       scic_sds_controller_stopping_state_device_stopped_handler
 6436    },
 6437    // SCI_BASE_CONTROLLER_STATE_STOPPED
 6438    {
 6439       {
 6440          NULL,
 6441          NULL,
 6442          scic_sds_controller_failed_state_reset_handler,
 6443          NULL,
 6444          scic_sds_controller_default_start_operation_handler,
 6445          scic_sds_controller_default_start_operation_handler,
 6446          scic_sds_controller_default_request_handler,
 6447          scic_sds_controller_default_request_handler,
 6448          scic_sds_controller_default_request_handler,
 6449          NULL,
 6450          NULL
 6451       },
 6452       scic_sds_controller_default_request_handler,
 6453       NULL,
 6454       NULL,
 6455       NULL,
 6456       NULL
 6457    },
 6458    // SCI_BASE_CONTROLLER_STATE_FAILED
 6459    {
 6460       {
 6461          NULL,
 6462          NULL,
 6463          scic_sds_controller_general_reset_handler,
 6464          NULL,
 6465          scic_sds_controller_failed_state_start_operation_handler,
 6466          scic_sds_controller_failed_state_start_operation_handler,
 6467          scic_sds_controller_default_request_handler,
 6468          scic_sds_controller_default_request_handler,
 6469          scic_sds_controller_default_request_handler,
 6470          NULL,
 6471          NULL
 6472       },
 6473       scic_sds_controller_failed_state_terminate_request_handler,
 6474       NULL,
 6475       NULL,
 6476       NULL
 6477    }
 6478 };
 6479 
 6480 /**
 6481  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
 6482  * entry to the SCI_BASE_CONTROLLER_STATE_INITIAL.
 6483  *    - Set the state handlers to the controllers initial state.
 6484  *
 6485  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6486  *       SCIC_SDS_CONTROLLER object.
 6487  *
 6488  * @return none
 6489  *
 6490  * @todo This function should initialze the controller object.
 6491  */
 6492 static
 6493 void scic_sds_controller_initial_state_enter(
 6494    SCI_BASE_OBJECT_T *object
 6495 )
 6496 {
 6497    SCIC_SDS_CONTROLLER_T *this_controller;
 6498    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6499 
 6500    scic_sds_controller_set_base_state_handlers(
 6501       this_controller, SCI_BASE_CONTROLLER_STATE_INITIAL);
 6502 
 6503    sci_base_state_machine_change_state(
 6504       &this_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_RESET);
 6505 }
 6506 
 6507 /**
 6508  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
 6509  * entry to the SCI_BASE_CONTROLLER_STATE_RESET.
 6510  *    - Set the state handlers to the controllers reset state.
 6511  *
 6512  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6513  *       SCIC_SDS_CONTROLLER object.
 6514  *
 6515  * @return none
 6516  */
 6517 static
 6518 void scic_sds_controller_reset_state_enter(
 6519    SCI_BASE_OBJECT_T *object
 6520 )
 6521 {
 6522    U8 index;
 6523    SCIC_SDS_CONTROLLER_T *this_controller;
 6524    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6525 
 6526    scic_sds_controller_set_base_state_handlers(
 6527       this_controller, SCI_BASE_CONTROLLER_STATE_RESET);
 6528 
 6529    scic_sds_port_configuration_agent_construct(&this_controller->port_agent);
 6530 
 6531    // Construct the ports for this controller
 6532    for (index = 0; index < (SCI_MAX_PORTS + 1); index++)
 6533    {
 6534       scic_sds_port_construct(
 6535          &this_controller->port_table[index],
 6536          (index == SCI_MAX_PORTS) ? SCIC_SDS_DUMMY_PORT : index,
 6537          this_controller
 6538       );
 6539    }
 6540 
 6541    // Construct the phys for this controller
 6542    for (index = 0; index < SCI_MAX_PHYS; index++)
 6543    {
 6544       // Add all the PHYs to the dummy port
 6545       scic_sds_phy_construct(
 6546          &this_controller->phy_table[index],
 6547          &this_controller->port_table[SCI_MAX_PORTS],
 6548          index
 6549       );
 6550    }
 6551 
 6552    this_controller->invalid_phy_mask = 0;
 6553 
 6554    // Set the default maximum values
 6555    this_controller->completion_event_entries      = SCU_EVENT_COUNT;
 6556    this_controller->completion_queue_entries      = SCU_COMPLETION_QUEUE_COUNT;
 6557    this_controller->remote_node_entries           = SCI_MAX_REMOTE_DEVICES;
 6558    this_controller->logical_port_entries          = SCI_MAX_PORTS;
 6559    this_controller->task_context_entries          = SCU_IO_REQUEST_COUNT;
 6560    this_controller->uf_control.buffers.count      = SCU_UNSOLICITED_FRAME_COUNT;
 6561    this_controller->uf_control.address_table.count= SCU_UNSOLICITED_FRAME_COUNT;
 6562 
 6563    // Initialize the User and OEM parameters to default values.
 6564    scic_sds_controller_set_default_config_parameters(this_controller);
 6565 }
 6566 
 6567 /**
 6568  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
 6569  * entry to the SCI_BASE_CONTROLLER_STATE_INITIALIZING.
 6570  *    - Set the state handlers to the controllers initializing state.
 6571  *
 6572  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6573  *       SCIC_SDS_CONTROLLER object.
 6574  *
 6575  * @return none
 6576  */
 6577 static
 6578 void scic_sds_controller_initializing_state_enter(
 6579    SCI_BASE_OBJECT_T *object
 6580 )
 6581 {
 6582    SCIC_SDS_CONTROLLER_T *this_controller;
 6583    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6584 
 6585    scic_sds_controller_set_base_state_handlers(
 6586       this_controller, SCI_BASE_CONTROLLER_STATE_INITIALIZING);
 6587 }
 6588 
 6589 /**
 6590  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
 6591  * entry to the SCI_BASE_CONTROLLER_STATE_INITIALIZED.
 6592  *    - Set the state handlers to the controllers initialized state.
 6593  *
 6594  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6595  *       SCIC_SDS_CONTROLLER object.
 6596  *
 6597  * @return none
 6598  */
 6599 static
 6600 void scic_sds_controller_initialized_state_enter(
 6601    SCI_BASE_OBJECT_T *object
 6602 )
 6603 {
 6604    SCIC_SDS_CONTROLLER_T *this_controller;
 6605    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6606 
 6607    scic_sds_controller_set_base_state_handlers(
 6608       this_controller, SCI_BASE_CONTROLLER_STATE_INITIALIZED);
 6609 }
 6610 
 6611 /**
 6612  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
 6613  * entry to the SCI_BASE_CONTROLLER_STATE_STARTING.
 6614  *    - Set the state handlers to the controllers starting state.
 6615  *
 6616  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6617  *       SCIC_SDS_CONTROLLER object.
 6618  *
 6619  * @return none
 6620  */
 6621 static
 6622 void scic_sds_controller_starting_state_enter(
 6623    SCI_BASE_OBJECT_T *object
 6624 )
 6625 {
 6626    SCIC_SDS_CONTROLLER_T *this_controller;
 6627    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6628 
 6629    scic_sds_controller_set_base_state_handlers(
 6630       this_controller, SCI_BASE_CONTROLLER_STATE_STARTING);
 6631 
 6632 }
 6633 
 6634 /**
 6635  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
 6636  * from the SCI_BASE_CONTROLLER_STATE_STARTING.
 6637  *    - This function stops the controller starting timeout timer.
 6638  *
 6639  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6640  *       SCIC_SDS_CONTROLLER object.
 6641  *
 6642  * @return none
 6643  */
 6644 static
 6645 void scic_sds_controller_starting_state_exit(
 6646    SCI_BASE_OBJECT_T *object
 6647 )
 6648 {
 6649    SCIC_SDS_CONTROLLER_T *this_controller;
 6650    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6651 
 6652    scic_cb_timer_stop(object, this_controller->timeout_timer);
 6653 
 6654    // We are done with this timer since we are exiting the starting
 6655    // state so remove it
 6656    scic_cb_timer_destroy(
 6657       this_controller,
 6658       this_controller->phy_startup_timer
 6659    );
 6660 
 6661    this_controller->phy_startup_timer = NULL;
 6662 }
 6663 
 6664 /**
 6665  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
 6666  * entry to the SCI_BASE_CONTROLLER_STATE_READY.
 6667  *    - Set the state handlers to the controllers ready state.
 6668  *
 6669  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6670  *       SCIC_SDS_CONTROLLER object.
 6671  *
 6672  * @return none
 6673  */
 6674 static
 6675 void scic_sds_controller_ready_state_enter(
 6676    SCI_BASE_OBJECT_T *object
 6677 )
 6678 {
 6679    U32 clock_gating_unit_value;
 6680    SCIC_SDS_CONTROLLER_T *this_controller;
 6681    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6682 
 6683    scic_sds_controller_set_base_state_handlers(
 6684       this_controller, SCI_BASE_CONTROLLER_STATE_READY);
 6685 
 6686    /**
 6687     * enable clock gating for power control of the scu unit
 6688     */
 6689    clock_gating_unit_value = SMU_CGUCR_READ(this_controller);
 6690 
 6691    clock_gating_unit_value &= ~( SMU_CGUCR_GEN_BIT(REGCLK_ENABLE)
 6692                                | SMU_CGUCR_GEN_BIT(TXCLK_ENABLE)
 6693                                | SMU_CGUCR_GEN_BIT(XCLK_ENABLE) );
 6694    clock_gating_unit_value |= SMU_CGUCR_GEN_BIT(IDLE_ENABLE);
 6695 
 6696    SMU_CGUCR_WRITE(this_controller, clock_gating_unit_value);
 6697 
 6698    //set the default interrupt coalescence number and timeout value.
 6699    scic_controller_set_interrupt_coalescence(
 6700       this_controller, 0x10, 250);
 6701 }
 6702 
 6703 /**
 6704  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
 6705  * from the SCI_BASE_CONTROLLER_STATE_READY.
 6706  *    - This function does nothing.
 6707  *
 6708  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6709  *       SCIC_SDS_CONTROLLER object.
 6710  *
 6711  * @return none
 6712  */
 6713 static
 6714 void scic_sds_controller_ready_state_exit(
 6715    SCI_BASE_OBJECT_T *object
 6716 )
 6717 {
 6718    U32 clock_gating_unit_value;
 6719    SCIC_SDS_CONTROLLER_T *this_controller;
 6720    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6721 
 6722    /**
 6723     * restore clock gating for power control of the scu unit
 6724     */
 6725    clock_gating_unit_value = SMU_CGUCR_READ(this_controller);
 6726 
 6727    clock_gating_unit_value &= ~SMU_CGUCR_GEN_BIT(IDLE_ENABLE);
 6728    clock_gating_unit_value |= ( SMU_CGUCR_GEN_BIT(REGCLK_ENABLE)
 6729                               | SMU_CGUCR_GEN_BIT(TXCLK_ENABLE)
 6730                               | SMU_CGUCR_GEN_BIT(XCLK_ENABLE) );
 6731 
 6732    SMU_CGUCR_WRITE(this_controller, clock_gating_unit_value);
 6733 
 6734    //disable interrupt coalescence.
 6735    scic_controller_set_interrupt_coalescence(this_controller, 0, 0);
 6736 }
 6737 
 6738 /**
 6739  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
 6740  * entry to the SCI_BASE_CONTROLLER_STATE_READY.
 6741  *    - Set the state handlers to the controllers ready state.
 6742  *    - Stop all of the remote devices on this controller
 6743  *    - Stop the ports on this controller
 6744  *    - Stop the phys on this controller
 6745  *
 6746  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6747  *       SCIC_SDS_CONTROLLER object.
 6748  *
 6749  * @return none
 6750  */
 6751 static
 6752 void scic_sds_controller_stopping_state_enter(
 6753    SCI_BASE_OBJECT_T *object
 6754 )
 6755 {
 6756    SCIC_SDS_CONTROLLER_T *this_controller;
 6757    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6758 
 6759    scic_sds_controller_set_base_state_handlers(
 6760       this_controller, SCI_BASE_CONTROLLER_STATE_STOPPING);
 6761 
 6762    // Stop all of the components for this controller in the reverse order
 6763    // from which they are initialized.
 6764    scic_sds_controller_stop_devices(this_controller);
 6765    scic_sds_controller_stop_ports(this_controller);
 6766 
 6767    if (!scic_sds_controller_has_remote_devices_stopping(this_controller))
 6768    {
 6769       sci_base_state_machine_change_state(
 6770          &this_controller->parent.state_machine,
 6771          SCI_BASE_CONTROLLER_STATE_STOPPED
 6772       );
 6773    }
 6774 }
 6775 
 6776 /**
 6777  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
 6778  * from the SCI_BASE_CONTROLLER_STATE_STOPPING.
 6779  *    - This function stops the controller stopping timeout timer.
 6780  *
 6781  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6782  *       SCIC_SDS_CONTROLLER object.
 6783  *
 6784  * @return none
 6785  */
 6786 static
 6787 void scic_sds_controller_stopping_state_exit(
 6788    SCI_BASE_OBJECT_T *object
 6789 )
 6790 {
 6791    SCIC_SDS_CONTROLLER_T *this_controller;
 6792    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6793 
 6794    scic_cb_timer_stop(this_controller, this_controller->timeout_timer);
 6795 }
 6796 
 6797 /**
 6798  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
 6799  * entry to the SCI_BASE_CONTROLLER_STATE_STOPPED.
 6800  *    - Set the state handlers to the controllers stopped state.
 6801  *
 6802  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6803  *       SCIC_SDS_CONTROLLER object.
 6804  *
 6805  * @return none
 6806  */
 6807 static
 6808 void scic_sds_controller_stopped_state_enter(
 6809    SCI_BASE_OBJECT_T *object
 6810 )
 6811 {
 6812    SCIC_SDS_CONTROLLER_T *this_controller;
 6813    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6814 
 6815    scic_sds_controller_set_base_state_handlers(
 6816       this_controller, SCI_BASE_CONTROLLER_STATE_STOPPED);
 6817 
 6818    // We are done with this timer until the next timer we initialize
 6819    scic_cb_timer_destroy(
 6820       this_controller,
 6821       this_controller->timeout_timer
 6822    );
 6823    this_controller->timeout_timer = NULL;
 6824 
 6825    // Controller has stopped so disable all the phys on this controller
 6826    scic_sds_controller_stop_phys(this_controller);
 6827 
 6828    scic_sds_port_configuration_agent_destroy(
 6829       this_controller,
 6830       &this_controller->port_agent
 6831    );
 6832 
 6833    scic_cb_controller_stop_complete(this_controller, SCI_SUCCESS);
 6834 }
 6835 
 6836 /**
 6837  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
 6838  * entry to the SCI_BASE_CONTROLLER_STATE_RESETTING.
 6839  *    - Set the state handlers to the controllers resetting state.
 6840  *    - Write to the SCU hardware reset register to force a reset
 6841  *    - Transition to the SCI_BASE_CONTROLLER_STATE_RESET
 6842  *
 6843  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6844  *       SCIC_SDS_CONTROLLER object.
 6845  *
 6846  * @return none
 6847  */
 6848 static
 6849 void scic_sds_controller_resetting_state_enter(
 6850    SCI_BASE_OBJECT_T *object
 6851 )
 6852 {
 6853    SCIC_SDS_CONTROLLER_T *this_controller;
 6854    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6855 
 6856    SCIC_LOG_TRACE((
 6857       sci_base_object_get_logger(this_controller),
 6858       SCIC_LOG_OBJECT_CONTROLLER,
 6859       "scic_sds_controller_resetting_state_enter(0x%x) enter\n",
 6860       this_controller
 6861    ));
 6862 
 6863    scic_sds_controller_set_base_state_handlers(
 6864       this_controller, SCI_BASE_CONTROLLER_STATE_RESETTING);
 6865 
 6866    scic_sds_controller_reset_hardware(this_controller);
 6867 
 6868    sci_base_state_machine_change_state(
 6869       scic_sds_controller_get_base_state_machine(this_controller),
 6870       SCI_BASE_CONTROLLER_STATE_RESET
 6871    );
 6872 }
 6873 
 6874 static
 6875 SCI_STATUS scic_sds_abort_reqests(
 6876         SCIC_SDS_CONTROLLER_T * controller,
 6877         SCIC_SDS_REMOTE_DEVICE_T * remote_device,
 6878         SCIC_SDS_PORT_T * port
 6879 )
 6880 {
 6881     SCI_STATUS          status           = SCI_SUCCESS;
 6882     SCI_STATUS          terminate_status = SCI_SUCCESS;
 6883     SCIC_SDS_REQUEST_T *the_request;
 6884     U32                 index;
 6885     U32                 request_count;
 6886 
 6887     if (remote_device != NULL)
 6888         request_count = remote_device->started_request_count;
 6889     else if (port != NULL)
 6890         request_count = port->started_request_count;
 6891     else
 6892         request_count = SCI_MAX_IO_REQUESTS;
 6893 
 6894 
 6895     for (index = 0;
 6896          (index < SCI_MAX_IO_REQUESTS) && (request_count > 0);
 6897          index++)
 6898     {
 6899        the_request = controller->io_request_table[index];
 6900 
 6901        if (the_request != NULL)
 6902        {
 6903            if (the_request->target_device == remote_device
 6904                    || the_request->target_device->owning_port == port
 6905                    || (remote_device == NULL && port == NULL))
 6906            {
 6907                terminate_status = scic_controller_terminate_request(
 6908                                      controller,
 6909                                      the_request->target_device,
 6910                                      the_request
 6911                                   );
 6912 
 6913                if (terminate_status != SCI_SUCCESS)
 6914                   status = terminate_status;
 6915 
 6916                request_count--;
 6917            }
 6918        }
 6919     }
 6920 
 6921     return status;
 6922 }
 6923 
 6924 SCI_STATUS scic_sds_terminate_reqests(
 6925         SCIC_SDS_CONTROLLER_T *this_controller,
 6926         SCIC_SDS_REMOTE_DEVICE_T *this_remote_device,
 6927         SCIC_SDS_PORT_T *this_port
 6928 )
 6929 {
 6930     SCI_STATUS status = SCI_SUCCESS;
 6931     SCI_STATUS abort_status = SCI_SUCCESS;
 6932 
 6933     // move all request to abort state
 6934     abort_status = scic_sds_abort_reqests(this_controller, this_remote_device, this_port);
 6935 
 6936     if (abort_status != SCI_SUCCESS)
 6937         status = abort_status;
 6938 
 6939     //move all request to complete state
 6940     if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR)
 6941         abort_status = scic_sds_abort_reqests(this_controller, this_remote_device, this_port);
 6942 
 6943     if (abort_status != SCI_SUCCESS)
 6944         status = abort_status;
 6945 
 6946     return status;
 6947 }
 6948 
 6949 static
 6950 SCI_STATUS scic_sds_terminate_all_requests(
 6951         SCIC_SDS_CONTROLLER_T * controller
 6952 )
 6953 {
 6954     return scic_sds_terminate_reqests(controller, NULL, NULL);
 6955 }
 6956 
 6957 /**
 6958  * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
 6959  * entry to the SCI_BASE_CONTROLLER_STATE_FAILED.
 6960  *    - Set the state handlers to the controllers failed state.
 6961  *
 6962  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 6963  *       SCIC_SDS_CONTROLLER object.
 6964  *
 6965  * @return none
 6966  */
 6967 static
 6968 void scic_sds_controller_failed_state_enter(
 6969    SCI_BASE_OBJECT_T *object
 6970 )
 6971 {
 6972    SCIC_SDS_CONTROLLER_T *this_controller;
 6973    this_controller= (SCIC_SDS_CONTROLLER_T *)object;
 6974 
 6975    scic_sds_controller_set_base_state_handlers(
 6976       this_controller, SCI_BASE_CONTROLLER_STATE_FAILED);
 6977 
 6978    if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR)
 6979    scic_sds_terminate_all_requests(this_controller);
 6980    else
 6981        scic_sds_controller_release_resource(this_controller);
 6982 
 6983    //notify framework the controller failed.
 6984    scic_cb_controller_error(this_controller,
 6985            this_controller->parent.error);
 6986 }
 6987 
 6988 // ---------------------------------------------------------------------------
 6989 
 6990 SCI_BASE_STATE_T
 6991    scic_sds_controller_state_table[SCI_BASE_CONTROLLER_MAX_STATES] =
 6992 {
 6993    {
 6994       SCI_BASE_CONTROLLER_STATE_INITIAL,
 6995       scic_sds_controller_initial_state_enter,
 6996       NULL,
 6997    },
 6998    {
 6999       SCI_BASE_CONTROLLER_STATE_RESET,
 7000       scic_sds_controller_reset_state_enter,
 7001       NULL,
 7002    },
 7003    {
 7004       SCI_BASE_CONTROLLER_STATE_INITIALIZING,
 7005       scic_sds_controller_initializing_state_enter,
 7006       NULL,
 7007    },
 7008    {
 7009       SCI_BASE_CONTROLLER_STATE_INITIALIZED,
 7010       scic_sds_controller_initialized_state_enter,
 7011       NULL,
 7012    },
 7013    {
 7014       SCI_BASE_CONTROLLER_STATE_STARTING,
 7015       scic_sds_controller_starting_state_enter,
 7016       scic_sds_controller_starting_state_exit,
 7017    },
 7018    {
 7019       SCI_BASE_CONTROLLER_STATE_READY,
 7020       scic_sds_controller_ready_state_enter,
 7021       scic_sds_controller_ready_state_exit,
 7022    },
 7023    {
 7024       SCI_BASE_CONTROLLER_STATE_RESETTING,
 7025       scic_sds_controller_resetting_state_enter,
 7026       NULL,
 7027    },
 7028    {
 7029       SCI_BASE_CONTROLLER_STATE_STOPPING,
 7030       scic_sds_controller_stopping_state_enter,
 7031       scic_sds_controller_stopping_state_exit,
 7032    },
 7033    {
 7034       SCI_BASE_CONTROLLER_STATE_STOPPED,
 7035       scic_sds_controller_stopped_state_enter,
 7036       NULL,
 7037    },
 7038    {
 7039       SCI_BASE_CONTROLLER_STATE_FAILED,
 7040       scic_sds_controller_failed_state_enter,
 7041       NULL,
 7042    }
 7043 };
 7044 

Cache object: 295a4011947d1808a808606a71301212


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