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_phy.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_PHY public and
   62  *        protected methods.
   63  */
   64 
   65 #include <dev/isci/scil/scic_user_callback.h>
   66 #include <dev/isci/scil/scic_phy.h>
   67 #include <dev/isci/scil/scic_sds_phy.h>
   68 #include <dev/isci/scil/scic_sds_port.h>
   69 #include <dev/isci/scil/scic_sds_controller_registers.h>
   70 #include <dev/isci/scil/scic_sds_phy_registers.h>
   71 #include <dev/isci/scil/scic_sds_logger.h>
   72 #include <dev/isci/scil/scic_sds_remote_node_context.h>
   73 #include <dev/isci/scil/sci_util.h>
   74 #include <dev/isci/scil/scic_sds_controller.h>
   75 #include <dev/isci/scil/scu_event_codes.h>
   76 #include <dev/isci/scil/sci_base_state.h>
   77 #include <dev/isci/scil/intel_ata.h>
   78 #include <dev/isci/scil/intel_sata.h>
   79 #include <dev/isci/scil/sci_base_state_machine.h>
   80 #include <dev/isci/scil/scic_sds_port_registers.h>
   81 
   82 #define SCIC_SDS_PHY_MIN_TIMER_COUNT  (SCI_MAX_PHYS)
   83 #define SCIC_SDS_PHY_MAX_TIMER_COUNT  (SCI_MAX_PHYS)
   84 
   85 // Maximum arbitration wait time in micro-seconds
   86 #define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME  (700)
   87 
   88 #define AFE_REGISTER_WRITE_DELAY 10
   89 
   90 //*****************************************************************************
   91 //* SCIC SDS PHY Internal Methods
   92 //*****************************************************************************
   93 
   94 /**
   95  * @brief This method will initialize the phy transport layer registers
   96  *
   97  * @param[in] this_phy
   98  * @param[in] transport_layer_registers
   99  *
  100  * @return SCI_STATUS
  101  */
  102 static
  103 SCI_STATUS scic_sds_phy_transport_layer_initialization(
  104    SCIC_SDS_PHY_T                  *this_phy,
  105    SCU_TRANSPORT_LAYER_REGISTERS_T *transport_layer_registers
  106 )
  107 {
  108    U32 tl_control;
  109 
  110    SCIC_LOG_TRACE((
  111       sci_base_object_get_logger(this_phy),
  112       SCIC_LOG_OBJECT_PHY,
  113       "scic_sds_phy_link_layer_initialization(this_phy:0x%x, link_layer_registers:0x%x)\n",
  114       this_phy, transport_layer_registers
  115    ));
  116 
  117    this_phy->transport_layer_registers = transport_layer_registers;
  118 
  119    SCU_STPTLDARNI_WRITE(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);
  120 
  121    // Hardware team recommends that we enable the STP prefetch for all transports
  122    tl_control = SCU_TLCR_READ(this_phy);
  123    tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH);
  124    SCU_TLCR_WRITE(this_phy, tl_control);
  125 
  126    return SCI_SUCCESS;
  127 }
  128 
  129 /**
  130  * @brief This method will initialize the phy link layer registers
  131  *
  132  * @param[in] this_phy
  133  * @param[in] link_layer_registers
  134  *
  135  * @return SCI_STATUS
  136  */
  137 static
  138 SCI_STATUS scic_sds_phy_link_layer_initialization(
  139    SCIC_SDS_PHY_T             *this_phy,
  140    SCU_LINK_LAYER_REGISTERS_T *link_layer_registers
  141 )
  142 {
  143    U32                phy_configuration;
  144    SAS_CAPABILITIES_T phy_capabilities;
  145    U32                parity_check = 0;
  146    U32                parity_count = 0;
  147    U32                link_layer_control;
  148    U32                phy_timer_timeout_values;
  149    U32                clksm_value = 0;
  150 
  151    SCIC_LOG_TRACE((
  152       sci_base_object_get_logger(this_phy),
  153       SCIC_LOG_OBJECT_PHY,
  154       "scic_sds_phy_link_layer_initialization(this_phy:0x%x, link_layer_registers:0x%x)\n",
  155       this_phy, link_layer_registers
  156    ));
  157 
  158    this_phy->link_layer_registers = link_layer_registers;
  159 
  160    // Set our IDENTIFY frame data
  161    #define SCI_END_DEVICE 0x01
  162 
  163    SCU_SAS_TIID_WRITE(
  164       this_phy,
  165       (   SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR)
  166         | SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR)
  167         | SCU_SAS_TIID_GEN_BIT(STP_INITIATOR)
  168         | SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST)
  169         | SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE) )
  170       );
  171 
  172    // Write the device SAS Address
  173    SCU_SAS_TIDNH_WRITE(this_phy, 0xFEDCBA98);
  174    SCU_SAS_TIDNL_WRITE(this_phy, this_phy->phy_index);
  175 
  176    // Write the source SAS Address
  177    SCU_SAS_TISSAH_WRITE(
  178       this_phy,
  179       this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[
  180           this_phy->phy_index].sas_address.sci_format.high
  181    );
  182    SCU_SAS_TISSAL_WRITE(
  183       this_phy,
  184       this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[
  185           this_phy->phy_index].sas_address.sci_format.low
  186    );
  187 
  188    // Clear and Set the PHY Identifier
  189    SCU_SAS_TIPID_WRITE(this_phy, 0x00000000);
  190    SCU_SAS_TIPID_WRITE(this_phy, SCU_SAS_TIPID_GEN_VALUE(ID, this_phy->phy_index));
  191 
  192    // Change the initial state of the phy configuration register
  193    phy_configuration = SCU_SAS_PCFG_READ(this_phy);
  194 
  195    // Hold OOB state machine in reset
  196    phy_configuration |=  SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
  197    SCU_SAS_PCFG_WRITE(this_phy, phy_configuration);
  198 
  199    // Configure the SNW capabilities
  200    phy_capabilities.u.all = 0;
  201    phy_capabilities.u.bits.start                      = 1;
  202    phy_capabilities.u.bits.gen3_without_ssc_supported = 1;
  203    phy_capabilities.u.bits.gen2_without_ssc_supported = 1;
  204    phy_capabilities.u.bits.gen1_without_ssc_supported = 1;
  205 
  206    /*
  207     * Set up SSC settings according to version of OEM Parameters.
  208     */
  209    {
  210        U8 header_version, enable_sata, enable_sas,
  211           sata_spread, sas_type, sas_spread;
  212        OEM_SSC_PARAMETERS_T ssc;
  213 
  214        header_version = this_phy->owning_port->owning_controller->
  215                         oem_parameters_version;
  216 
  217        ssc.bf.ssc_sata_tx_spread_level =
  218           this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sata_tx_spread_level;
  219        ssc.bf.ssc_sas_tx_spread_level =
  220           this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sas_tx_spread_level;
  221        ssc.bf.ssc_sas_tx_type =
  222           this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sas_tx_type;
  223        enable_sata = enable_sas = sata_spread = sas_type = sas_spread = 0;
  224 
  225        if (header_version == SCI_OEM_PARAM_VER_1_0)
  226        {
  227            /*
  228             * Version 1.0 is merely turning SSC on to default values.;
  229             */
  230            if (ssc.do_enable_ssc != 0)
  231            {
  232                enable_sas = enable_sata = TRUE;
  233                sas_type = 0x0;      // Downspreading
  234                sata_spread = 0x2;   // +0 to -1419 PPM
  235                sas_spread = 0x2;    // +0 to -1419 PPM
  236            }
  237        }
  238        else // header_version >= SCI_OEM_PARAM_VER_1_1
  239        {
  240           /*
  241            * Version 1.1 can turn on SAS and SATA independently and
  242            * specify spread levels. Also can specify spread type for SAS.
  243            */
  244           if ((sata_spread = ssc.bf.ssc_sata_tx_spread_level) != 0)
  245              enable_sata = TRUE;  // Downspreading only
  246           if ((sas_spread = ssc.bf.ssc_sas_tx_spread_level) != 0)
  247           {
  248              enable_sas = TRUE;
  249              sas_type = ssc.bf.ssc_sas_tx_type;
  250           }
  251        }
  252 
  253        if (enable_sas == TRUE)
  254        {
  255            U32 reg_val = scu_afe_register_read(
  256                              this_phy->owning_port->owning_controller,
  257                              scu_afe_xcvr[this_phy->phy_index].
  258                              afe_xcvr_control0);
  259            reg_val |= (0x00100000 | (((U32)sas_type) << 19));
  260            scu_afe_register_write(
  261                this_phy->owning_port->owning_controller,
  262                scu_afe_xcvr[this_phy->phy_index].afe_xcvr_control0,
  263                reg_val);
  264 
  265            reg_val = scu_afe_register_read(
  266                              this_phy->owning_port->owning_controller,
  267                              scu_afe_xcvr[this_phy->phy_index].
  268                              afe_tx_ssc_control);
  269            reg_val |= (((U32)(sas_spread)) << 8);
  270            scu_afe_register_write(
  271                this_phy->owning_port->owning_controller,
  272                scu_afe_xcvr[this_phy->phy_index].afe_tx_ssc_control,
  273                reg_val);
  274       phy_capabilities.u.bits.gen3_with_ssc_supported = 1;
  275       phy_capabilities.u.bits.gen2_with_ssc_supported = 1;
  276       phy_capabilities.u.bits.gen1_with_ssc_supported = 1;
  277    }
  278 
  279        if (enable_sata == TRUE)
  280        {
  281            U32 reg_val = scu_afe_register_read(
  282                          this_phy->owning_port->owning_controller,
  283                          scu_afe_xcvr[this_phy->phy_index].
  284                          afe_tx_ssc_control);
  285            reg_val |= (U32)sata_spread;
  286            scu_afe_register_write(
  287                this_phy->owning_port->owning_controller,
  288                scu_afe_xcvr[this_phy->phy_index].afe_tx_ssc_control,
  289                reg_val);
  290 
  291            reg_val = scu_link_layer_register_read(
  292                          this_phy,
  293                          stp_control);
  294            reg_val |= (U32)(1 << 12);
  295            scu_link_layer_register_write(
  296                this_phy,
  297                stp_control,
  298                reg_val);
  299        }
  300    }
  301 
  302    // The SAS specification indicates that the phy_capabilities that
  303    // are transmitted shall have an even parity.  Calculate the parity.
  304    parity_check = phy_capabilities.u.all;
  305    while (parity_check != 0)
  306    {
  307       if (parity_check & 0x1)
  308          parity_count++;
  309       parity_check >>= 1;
  310    }
  311 
  312    // If parity indicates there are an odd number of bits set, then
  313    // set the parity bit to 1 in the phy capabilities.
  314    if ((parity_count % 2) != 0)
  315       phy_capabilities.u.bits.parity = 1;
  316 
  317    SCU_SAS_PHYCAP_WRITE(this_phy, phy_capabilities.u.all);
  318 
  319    // Set the enable spinup period but disable the ability to send notify enable spinup
  320    SCU_SAS_ENSPINUP_WRITE(
  321      this_phy,
  322      SCU_ENSPINUP_GEN_VAL(
  323         COUNT,
  324         this_phy->owning_port->owning_controller->user_parameters.sds1.
  325            phys[this_phy->phy_index].notify_enable_spin_up_insertion_frequency
  326      )
  327    );
  328 
  329    // Write the ALIGN Insertion Ferequency for connected phy and inpendent of connected state
  330    clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL (
  331                      CONNECTED,
  332                      this_phy->owning_port->owning_controller->user_parameters.sds1.
  333                         phys[this_phy->phy_index].in_connection_align_insertion_frequency
  334                  );
  335 
  336    clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL (
  337                      GENERAL,
  338                      this_phy->owning_port->owning_controller->user_parameters.sds1.
  339                         phys[this_phy->phy_index].align_insertion_frequency
  340                   );
  341 
  342    SCU_SAS_CLKSM_WRITE ( this_phy, clksm_value);
  343 
  344 
  345 #if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD)
  346    /// @todo Provide a way to write this register correctly
  347    scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421);
  348 #elif defined(PBG_BUILD)
  349    if (
  350          (this_phy->owning_port->owning_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
  351       || (this_phy->owning_port->owning_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
  352       )
  353    {
  354       scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x04210400);
  355       scu_link_layer_register_write(this_phy, sas_primitive_timeout, 0x20A7C05);
  356    }
  357    else
  358    {
  359       scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421);
  360    }
  361 #else
  362    /// @todo Provide a way to write this register correctly
  363    scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x0e739ce7);
  364 #endif
  365 
  366    link_layer_control = SCU_SAS_LLCTL_GEN_VAL(
  367                            NO_OUTBOUND_TASK_TIMEOUT,
  368                            (U8) this_phy->owning_port->owning_controller->
  369                            user_parameters.sds1.no_outbound_task_timeout
  370                         );
  371 
  372 #if PHY_MAX_LINK_SPEED_GENERATION == SCIC_SDS_PARM_GEN1_SPEED
  373 #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1
  374 #elif PHY_MAX_LINK_SPEED_GENERATION == SCIC_SDS_PARM_GEN2_SPEED
  375 #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2
  376 #else
  377 #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3
  378 #endif // PHY_MAX_LINK_SPEED_GENERATION
  379 
  380    if (this_phy->owning_port->owning_controller->user_parameters.sds1.
  381        phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED)
  382    {
  383       link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
  384                                MAX_LINK_RATE, COMPILED_MAX_LINK_RATE
  385                             );
  386    }
  387    else if (this_phy->owning_port->owning_controller->user_parameters.sds1.
  388        phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED)
  389    {
  390       link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
  391                                MAX_LINK_RATE,
  392                                MIN(
  393                                   SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2,
  394                                   COMPILED_MAX_LINK_RATE)
  395                             );
  396    }
  397    else
  398    {
  399       link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
  400                                MAX_LINK_RATE,
  401                                MIN(
  402                                   SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1,
  403                                   COMPILED_MAX_LINK_RATE)
  404                             );
  405    }
  406 
  407    scu_link_layer_register_write(
  408       this_phy, link_layer_control, link_layer_control
  409    );
  410 
  411    phy_timer_timeout_values = scu_link_layer_register_read(
  412                                  this_phy,
  413                                  phy_timer_timeout_values
  414                               );
  415 
  416    // Clear the default 0x36 (54us) RATE_CHANGE timeout value.
  417    phy_timer_timeout_values &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF);
  418 
  419    // Set RATE_CHANGE timeout value to 0x3B (59us).  This ensures SCU can
  420    //  lock with 3Gb drive when SCU max rate is set to 1.5Gb.
  421    phy_timer_timeout_values |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B);
  422 
  423    scu_link_layer_register_write(
  424       this_phy, phy_timer_timeout_values, phy_timer_timeout_values
  425    );
  426 
  427    // Program the max ARB time for the PHY to 700us so we inter-operate with
  428    // the PMC expander which shuts down PHYs if the expander PHY generates too
  429    // many breaks.  This time value will guarantee that the initiator PHY will
  430    // generate the break.
  431 #if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD)
  432    scu_link_layer_register_write(
  433       this_phy,
  434       maximum_arbitration_wait_timer_timeout,
  435       SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME
  436    );
  437 #endif // defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD)
  438 
  439    // Disable the link layer hang detection timer
  440    scu_link_layer_register_write(
  441       this_phy, link_layer_hang_detection_timeout, 0x00000000
  442    );
  443 
  444    // We can exit the initial state to the stopped state
  445    sci_base_state_machine_change_state(
  446       scic_sds_phy_get_base_state_machine(this_phy),
  447       SCI_BASE_PHY_STATE_STOPPED
  448    );
  449 
  450    return SCI_SUCCESS;
  451 }
  452 
  453 /**
  454  * This function will handle the sata SIGNATURE FIS timeout condition.  It
  455  * will restart the starting substate machine since we dont know what has
  456  * actually happening.
  457  *
  458  * @param[in] cookie This object is cast to the SCIC_SDS_PHY_T object.
  459  *
  460  * @return none
  461  */
  462 void scic_sds_phy_sata_timeout( SCI_OBJECT_HANDLE_T cookie)
  463 {
  464    SCIC_SDS_PHY_T * this_phy = (SCIC_SDS_PHY_T *)cookie;
  465 
  466    SCIC_LOG_INFO((
  467       sci_base_object_get_logger(this_phy),
  468       SCIC_LOG_OBJECT_PHY,
  469       "SCIC SDS Phy 0x%x did not receive signature fis before timeout.\n",
  470       this_phy
  471    ));
  472 
  473    sci_base_state_machine_stop(
  474       scic_sds_phy_get_starting_substate_machine(this_phy));
  475 
  476    sci_base_state_machine_change_state(
  477       scic_sds_phy_get_base_state_machine(this_phy),
  478       SCI_BASE_PHY_STATE_STARTING
  479    );
  480 }
  481 
  482 //*****************************************************************************
  483 //* SCIC SDS PHY External Methods
  484 //*****************************************************************************
  485 
  486 /**
  487  * @brief This method returns the object size for a phy object.
  488  *
  489  * @return U32
  490  */
  491 U32 scic_sds_phy_get_object_size(void)
  492 {
  493    return sizeof(SCIC_SDS_PHY_T);
  494 }
  495 
  496 /**
  497  * @brief This method returns the minimum number of timers required for a
  498  *        phy object.
  499  *
  500  * @return U32
  501  */
  502 U32 scic_sds_phy_get_min_timer_count(void)
  503 {
  504    return SCIC_SDS_PHY_MIN_TIMER_COUNT;
  505 }
  506 
  507 /**
  508  * @brief This method returns the maximum number of timers required for a
  509  *        phy object.
  510  *
  511  * @return U32
  512  */
  513 U32 scic_sds_phy_get_max_timer_count(void)
  514 {
  515    return SCIC_SDS_PHY_MAX_TIMER_COUNT;
  516 }
  517 
  518 #ifdef SCI_LOGGING
  519 static
  520 void scic_sds_phy_initialize_state_logging(
  521    SCIC_SDS_PHY_T *this_phy
  522 )
  523 {
  524    sci_base_state_machine_logger_initialize(
  525       &this_phy->parent.state_machine_logger,
  526       &this_phy->parent.state_machine,
  527       &this_phy->parent.parent,
  528       scic_cb_logger_log_states,
  529       "SCIC_SDS_PHY_T", "base state machine",
  530       SCIC_LOG_OBJECT_PHY
  531    );
  532 
  533    sci_base_state_machine_logger_initialize(
  534       &this_phy->starting_substate_machine_logger,
  535       &this_phy->starting_substate_machine,
  536       &this_phy->parent.parent,
  537       scic_cb_logger_log_states,
  538       "SCIC_SDS_PHY_T", "starting substate machine",
  539       SCIC_LOG_OBJECT_PHY
  540    );
  541 }
  542 #endif // SCI_LOGGING
  543 
  544 #ifdef SCIC_DEBUG_ENABLED
  545 /**
  546  * Debug code to record the state transitions in the phy
  547  *
  548  * @param our_observer
  549  * @param the_state_machine
  550  */
  551 void scic_sds_phy_observe_state_change(
  552    SCI_BASE_OBSERVER_T * our_observer,
  553    SCI_BASE_SUBJECT_T  * the_subject
  554 )
  555 {
  556    SCIC_SDS_PHY_T           *this_phy;
  557    SCI_BASE_STATE_MACHINE_T *the_state_machine;
  558 
  559    U8  transition_requestor;
  560    U32 base_state_id;
  561    U32 starting_substate_id;
  562 
  563    the_state_machine = (SCI_BASE_STATE_MACHINE_T *)the_subject;
  564    this_phy = (SCIC_SDS_PHY_T *)the_state_machine->state_machine_owner;
  565 
  566    if (the_state_machine == &this_phy->parent.state_machine)
  567    {
  568       transition_requestor = 0x01;
  569    }
  570    else if (the_state_machine == &this_phy->starting_substate_machine)
  571    {
  572       transition_requestor = 0x02;
  573    }
  574    else
  575    {
  576       transition_requestor = 0xFF;
  577    }
  578 
  579    base_state_id =
  580       sci_base_state_machine_get_state(&this_phy->parent.state_machine);
  581    starting_substate_id =
  582       sci_base_state_machine_get_state(&this_phy->starting_substate_machine);
  583 
  584    this_phy->state_record.state_transition_table[
  585       this_phy->state_record.index++] = ( (transition_requestor << 24)
  586                                         | ((U8)base_state_id << 8)
  587                                         | ((U8)starting_substate_id));
  588 
  589    this_phy->state_record.index =
  590       this_phy->state_record.index & (MAX_STATE_TRANSITION_RECORD - 1);
  591 
  592 }
  593 #endif // SCIC_DEBUG_ENABLED
  594 
  595 #ifdef SCIC_DEBUG_ENABLED
  596 /**
  597  * This method initializes the state record debug information for the phy
  598  * object.
  599  *
  600  * @pre The state machines for the phy object must be constructed before this
  601  *      function is called.
  602  *
  603  * @param this_phy The phy which is being initialized.
  604  */
  605 void scic_sds_phy_initialize_state_recording(
  606    SCIC_SDS_PHY_T *this_phy
  607 )
  608 {
  609    this_phy->state_record.index = 0;
  610 
  611    sci_base_observer_initialize(
  612       &this_phy->state_record.base_state_observer,
  613       scic_sds_phy_observe_state_change,
  614       &this_phy->parent.state_machine.parent
  615    );
  616 
  617    sci_base_observer_initialize(
  618       &this_phy->state_record.starting_state_observer,
  619       scic_sds_phy_observe_state_change,
  620       &this_phy->starting_substate_machine.parent
  621    );
  622 }
  623 #endif // SCIC_DEBUG_ENABLED
  624 
  625 /**
  626  * @brief This method will construct the SCIC_SDS_PHY object
  627  *
  628  * @param[in] this_phy
  629  * @param[in] owning_port
  630  * @param[in] phy_index
  631  *
  632  * @return none
  633  */
  634 void scic_sds_phy_construct(
  635    SCIC_SDS_PHY_T  *this_phy,
  636    SCIC_SDS_PORT_T *owning_port,
  637    U8              phy_index
  638 )
  639 {
  640    // Call the base constructor first
  641    // Copy the logger from the port (this could be the dummy port)
  642    sci_base_phy_construct(
  643       &this_phy->parent,
  644       sci_base_object_get_logger(owning_port),
  645       scic_sds_phy_state_table
  646       );
  647 
  648    // Copy the rest of the input data to our locals
  649    this_phy->owning_port = owning_port;
  650    this_phy->phy_index = phy_index;
  651    this_phy->bcn_received_while_port_unassigned = FALSE;
  652    this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
  653    this_phy->link_layer_registers = NULL;
  654    this_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE;
  655    this_phy->sata_timeout_timer = NULL;
  656 
  657    // Clear out the identification buffer data
  658    memset(&this_phy->phy_type, 0, sizeof(this_phy->phy_type));
  659 
  660    // Clear out the error counter data
  661    memset(this_phy->error_counter, 0, sizeof(this_phy->error_counter));
  662 
  663    // Initialize the substate machines
  664    sci_base_state_machine_construct(
  665       &this_phy->starting_substate_machine,
  666       &this_phy->parent.parent,
  667       scic_sds_phy_starting_substates,
  668       SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL
  669       );
  670 
  671    #ifdef SCI_LOGGING
  672    scic_sds_phy_initialize_state_logging(this_phy);
  673    #endif // SCI_LOGGING
  674 
  675    #ifdef SCIC_DEBUG_ENABLED
  676    scic_sds_phy_initialize_state_recording(this_phy);
  677    #endif // SCIC_DEBUG_ENABLED
  678 }
  679 
  680 /**
  681  * @brief This method returns the port currently containing this phy.
  682  *        If the phy is currently contained by the dummy port, then
  683  *        the phy is considered to not be part of a port.
  684  *
  685  * @param[in] this_phy This parameter specifies the phy for which to
  686  *            retrieve the containing port.
  687  *
  688  * @return This method returns a handle to a port that contains
  689  *         the supplied phy.
  690  * @retval SCI_INVALID_HANDLE This value is returned if the phy is not
  691  *         part of a real port (i.e. it's contained in the dummy port).
  692  * @retval !SCI_INVALID_HANDLE All other values indicate a handle/pointer
  693  *         to the port containing the phy.
  694  */
  695 SCI_PORT_HANDLE_T scic_sds_phy_get_port(
  696    SCIC_SDS_PHY_T *this_phy
  697 )
  698 {
  699    SCIC_LOG_TRACE((
  700       sci_base_object_get_logger(this_phy),
  701       SCIC_LOG_OBJECT_PHY,
  702       "scic_phy_get_port(0x%x) enter\n",
  703       this_phy
  704    ));
  705 
  706    if (scic_sds_port_get_index(this_phy->owning_port) == SCIC_SDS_DUMMY_PORT)
  707       return SCI_INVALID_HANDLE;
  708 
  709    return this_phy->owning_port;
  710 }
  711 
  712 /**
  713  * @brief This method will assign a port to the phy object.
  714  *
  715  * @param[in, out] this_phy This parameter specifies the phy for which
  716  *    to assign a port object.
  717  * @param[in] the_port This parameter is the port to assing to the phy.
  718  */
  719 void scic_sds_phy_set_port(
  720    SCIC_SDS_PHY_T * this_phy,
  721    SCIC_SDS_PORT_T * the_port
  722 )
  723 {
  724    this_phy->owning_port = the_port;
  725 
  726    if (this_phy->bcn_received_while_port_unassigned)
  727    {
  728       this_phy->bcn_received_while_port_unassigned = FALSE;
  729       scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy);
  730    }
  731 }
  732 
  733 /**
  734  * @brief This method will initialize the constructed phy
  735  *
  736  * @param[in] this_phy
  737  * @param[in] link_layer_registers
  738  *
  739  * @return SCI_STATUS
  740  */
  741 SCI_STATUS scic_sds_phy_initialize(
  742    SCIC_SDS_PHY_T             *this_phy,
  743    void                       *transport_layer_registers,
  744    SCU_LINK_LAYER_REGISTERS_T *link_layer_registers
  745 )
  746 {
  747    SCIC_LOG_TRACE((
  748       sci_base_object_get_logger(this_phy),
  749       SCIC_LOG_OBJECT_PHY,
  750       "scic_sds_phy_initialize(this_phy:0x%x, link_layer_registers:0x%x)\n",
  751       this_phy, link_layer_registers
  752    ));
  753 
  754    // Perform the initialization of the TL hardware
  755    scic_sds_phy_transport_layer_initialization(this_phy, transport_layer_registers);
  756 
  757    // Perofrm the initialization of the PE hardware
  758    scic_sds_phy_link_layer_initialization(this_phy, link_layer_registers);
  759 
  760    // There is nothing that needs to be done in this state just
  761    // transition to the stopped state.
  762    sci_base_state_machine_change_state(
  763       scic_sds_phy_get_base_state_machine(this_phy),
  764       SCI_BASE_PHY_STATE_STOPPED
  765    );
  766 
  767    return SCI_SUCCESS;
  768 }
  769 
  770 /**
  771  * This method assigns the direct attached device ID for this phy.
  772  *
  773  * @param[in] this_phy The phy for which the direct attached device id is to
  774  *       be assigned.
  775  * @param[in] device_id The direct attached device ID to assign to the phy.
  776  *       This will either be the RNi for the device or an invalid RNi if there
  777  *       is no current device assigned to the phy.
  778  */
  779 void scic_sds_phy_setup_transport(
  780    SCIC_SDS_PHY_T * this_phy,
  781    U32              device_id
  782 )
  783 {
  784    U32 tl_control;
  785 
  786    SCU_STPTLDARNI_WRITE(this_phy, device_id);
  787 
  788    // The read should guarntee that the first write gets posted
  789    // before the next write
  790    tl_control = SCU_TLCR_READ(this_phy);
  791    tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
  792    SCU_TLCR_WRITE(this_phy, tl_control);
  793 }
  794 
  795 /**
  796  * This function will perform the register reads/writes to suspend the SCU
  797  * hardware protocol engine.
  798  *
  799  * @param[in,out] this_phy The phy object to be suspended.
  800  *
  801  * @return none
  802  */
  803 void scic_sds_phy_suspend(
  804    SCIC_SDS_PHY_T * this_phy
  805 )
  806 {
  807    U32 scu_sas_pcfg_value;
  808 
  809    scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
  810    scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
  811    SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
  812 
  813    scic_sds_phy_setup_transport(
  814       this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
  815    );
  816 }
  817 
  818 /**
  819  * This function will perform the register reads/writes required to resume the
  820  * SCU hardware protocol engine.
  821  *
  822  * @param[in,out] this_phy The phy object to resume.
  823  *
  824  * @return none
  825  */
  826 void scic_sds_phy_resume(
  827    SCIC_SDS_PHY_T * this_phy
  828 )
  829 {
  830    U32 scu_sas_pcfg_value;
  831 
  832    scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
  833 
  834    scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
  835 
  836    SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
  837 }
  838 
  839 /**
  840  * @brief This method returns the local sas address assigned to this phy.
  841  *
  842  * @param[in] this_phy This parameter specifies the phy for which
  843  *            to retrieve the local SAS address.
  844  * @param[out] sas_address This parameter specifies the location into
  845  *             which to copy the local SAS address.
  846  *
  847  * @return none
  848  */
  849 void scic_sds_phy_get_sas_address(
  850    SCIC_SDS_PHY_T *this_phy,
  851    SCI_SAS_ADDRESS_T *sas_address
  852 )
  853 {
  854    SCIC_LOG_TRACE((
  855       sci_base_object_get_logger(this_phy),
  856       SCIC_LOG_OBJECT_PHY,
  857       "scic_sds_phy_get_sas_address(this_phy:0x%x, sas_address:0x%x)\n",
  858       this_phy, sas_address
  859    ));
  860 
  861    sas_address->high = SCU_SAS_TISSAH_READ(this_phy);
  862    sas_address->low  = SCU_SAS_TISSAL_READ(this_phy);
  863 }
  864 
  865 /**
  866  * @brief This method returns the remote end-point (i.e. attached)
  867  *        sas address assigned to this phy.
  868  *
  869  * @param[in] this_phy This parameter specifies the phy for which
  870  *            to retrieve the remote end-point SAS address.
  871  * @param[out] sas_address This parameter specifies the location into
  872  *             which to copy the remote end-point SAS address.
  873  *
  874  * @return none
  875  */
  876 void scic_sds_phy_get_attached_sas_address(
  877    SCIC_SDS_PHY_T    *this_phy,
  878    SCI_SAS_ADDRESS_T *sas_address
  879 )
  880 {
  881    SCIC_LOG_TRACE((
  882       sci_base_object_get_logger(this_phy),
  883       SCIC_LOG_OBJECT_PHY,
  884       "scic_sds_phy_get_attached_sas_address(0x%x, 0x%x) enter\n",
  885       this_phy, sas_address
  886    ));
  887 
  888    sas_address->high
  889       = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high;
  890    sas_address->low
  891       = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low;
  892 }
  893 
  894 /**
  895  * @brief This method returns the supported protocols assigned to
  896  *        this phy
  897  *
  898  * @param[in] this_phy
  899  * @param[out] protocols
  900  */
  901 void scic_sds_phy_get_protocols(
  902    SCIC_SDS_PHY_T *this_phy,
  903    SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
  904 )
  905 {
  906    U32 tiid_value = SCU_SAS_TIID_READ(this_phy);
  907 
  908    //Check each bit of this register. please refer to
  909    //SAS Transmit Identification Register (SAS_TIID).
  910    if (tiid_value & 0x2)
  911       protocols->u.bits.smp_target = 1;
  912 
  913    if (tiid_value & 0x4)
  914       protocols->u.bits.stp_target = 1;
  915 
  916    if (tiid_value & 0x8)
  917       protocols->u.bits.ssp_target = 1;
  918 
  919    if (tiid_value & 0x200)
  920       protocols->u.bits.smp_initiator = 1;
  921 
  922    if ((tiid_value & 0x400))
  923       protocols->u.bits.stp_initiator = 1;
  924 
  925    if (tiid_value & 0x800)
  926       protocols->u.bits.ssp_initiator = 1;
  927 
  928    SCIC_LOG_TRACE((
  929       sci_base_object_get_logger(this_phy),
  930       SCIC_LOG_OBJECT_PHY,
  931       "scic_sds_phy_get_protocols(this_phy:0x%x, protocols:0x%x)\n",
  932       this_phy, protocols->u.all
  933    ));
  934 }
  935 
  936 /**
  937  * This method returns the supported protocols for the attached phy.  If this
  938  * is a SAS phy the protocols are returned from the identify address frame.
  939  * If this is a SATA phy then protocols are made up and the target phy is an
  940  * STP target phy.
  941  *
  942  * @note The caller will get the entire set of bits for the protocol value.
  943  *
  944  * @param[in] this_phy The parameter is the phy object for which the attached
  945  *       phy protcols are to be returned.
  946  * @param[out] protocols The parameter is the returned protocols for the
  947  *       attached phy.
  948  */
  949 void scic_sds_phy_get_attached_phy_protocols(
  950    SCIC_SDS_PHY_T *this_phy,
  951    SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
  952 )
  953 {
  954    SCIC_LOG_TRACE((
  955       sci_base_object_get_logger(this_phy),
  956       SCIC_LOG_OBJECT_PHY,
  957       "scic_sds_phy_get_attached_phy_protocols(this_phy:0x%x, protocols:0x%x[0x%x])\n",
  958       this_phy, protocols, protocols->u.all
  959    ));
  960 
  961    protocols->u.all = 0;
  962 
  963    if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
  964    {
  965       protocols->u.all =
  966          this_phy->phy_type.sas.identify_address_frame_buffer.protocols.u.all;
  967    }
  968    else if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)
  969    {
  970       protocols->u.bits.stp_target = 1;
  971    }
  972 }
  973 
  974 
  975 /**
  976  * @brief This method release resources in for a scic phy.
  977  *
  978  * @param[in] controller This parameter specifies the core controller, one of
  979  *            its phy's resources are to be released.
  980  * @param[in] this_phy This parameter specifies the phy whose resource is to
  981  *            be released.
  982  */
  983 void scic_sds_phy_release_resource(
  984    SCIC_SDS_CONTROLLER_T * controller,
  985    SCIC_SDS_PHY_T        * this_phy
  986 )
  987 {
  988    SCIC_LOG_TRACE((
  989       sci_base_object_get_logger(this_phy),
  990       SCIC_LOG_OBJECT_PHY,
  991       "scic_sds_phy_release_resource(0x%x, 0x%x)\n",
  992       controller, this_phy
  993    ));
  994 
  995    //Currently, the only resource to be released is a timer.
  996    if (this_phy->sata_timeout_timer != NULL)
  997    {
  998       scic_cb_timer_destroy(controller, this_phy->sata_timeout_timer);
  999       this_phy->sata_timeout_timer = NULL;
 1000    }
 1001 }
 1002 
 1003 
 1004 //*****************************************************************************
 1005 //* SCIC SDS PHY Handler Redirects
 1006 //*****************************************************************************
 1007 
 1008 /**
 1009  * @brief This method will attempt to reset the phy.  This
 1010  *        request is only valid when the phy is in an ready
 1011  *        state
 1012  *
 1013  * @param[in] this_phy
 1014  *
 1015  * @return SCI_STATUS
 1016  */
 1017 SCI_STATUS scic_sds_phy_reset(
 1018    SCIC_SDS_PHY_T * this_phy
 1019 )
 1020 {
 1021    SCIC_LOG_TRACE((
 1022       sci_base_object_get_logger(this_phy),
 1023       SCIC_LOG_OBJECT_PHY,
 1024       "scic_sds_phy_reset(this_phy:0x%08x)\n",
 1025       this_phy
 1026    ));
 1027 
 1028    return this_phy->state_handlers->parent.reset_handler(
 1029                                              &this_phy->parent
 1030                                            );
 1031 }
 1032 
 1033 /**
 1034  * @brief This method will process the event code received.
 1035  *
 1036  * @param[in] this_phy
 1037  * @param[in] event_code
 1038  *
 1039  * @return SCI_STATUS
 1040  */
 1041 SCI_STATUS scic_sds_phy_event_handler(
 1042    SCIC_SDS_PHY_T *this_phy,
 1043    U32 event_code
 1044 )
 1045 {
 1046    SCIC_LOG_TRACE((
 1047       sci_base_object_get_logger(this_phy),
 1048       SCIC_LOG_OBJECT_PHY,
 1049       "scic_sds_phy_event_handler(this_phy:0x%08x, event_code:%x)\n",
 1050       this_phy, event_code
 1051    ));
 1052 
 1053    return this_phy->state_handlers->event_handler(this_phy, event_code);
 1054 }
 1055 
 1056 /**
 1057  * @brief This method will process the frame index received.
 1058  *
 1059  * @param[in] this_phy
 1060  * @param[in] frame_index
 1061  *
 1062  * @return SCI_STATUS
 1063  */
 1064 SCI_STATUS scic_sds_phy_frame_handler(
 1065    SCIC_SDS_PHY_T *this_phy,
 1066    U32 frame_index
 1067 )
 1068 {
 1069    SCIC_LOG_TRACE((
 1070       sci_base_object_get_logger(this_phy),
 1071       SCIC_LOG_OBJECT_PHY,
 1072       "scic_sds_phy_frame_handler(this_phy:0x%08x, frame_index:%d)\n",
 1073       this_phy, frame_index
 1074    ));
 1075 
 1076    return this_phy->state_handlers->frame_handler(this_phy, frame_index);
 1077 }
 1078 
 1079 /**
 1080  * @brief This method will give the phy permission to consume power
 1081  *
 1082  * @param[in] this_phy
 1083  *
 1084  * @return SCI_STATUS
 1085  */
 1086 SCI_STATUS scic_sds_phy_consume_power_handler(
 1087    SCIC_SDS_PHY_T *this_phy
 1088 )
 1089 {
 1090    SCIC_LOG_TRACE((
 1091       sci_base_object_get_logger(this_phy),
 1092       SCIC_LOG_OBJECT_PHY,
 1093       "scic_sds_phy_consume_power_handler(this_phy:0x%08x)\n",
 1094       this_phy
 1095    ));
 1096 
 1097    return this_phy->state_handlers->consume_power_handler(this_phy);
 1098 }
 1099 
 1100 //*****************************************************************************
 1101 //* SCIC PHY Public Methods
 1102 //*****************************************************************************
 1103 
 1104 SCI_STATUS scic_phy_get_properties(
 1105    SCI_PHY_HANDLE_T        phy,
 1106    SCIC_PHY_PROPERTIES_T * properties
 1107 )
 1108 {
 1109    SCIC_SDS_PHY_T *this_phy;
 1110    U8 max_speed_generation;
 1111 
 1112    this_phy = (SCIC_SDS_PHY_T *)phy;
 1113 
 1114    SCIC_LOG_TRACE((
 1115       sci_base_object_get_logger(this_phy),
 1116       SCIC_LOG_OBJECT_PHY,
 1117       "scic_phy_get_properties(0x%x, 0x%x) enter\n",
 1118       this_phy, properties
 1119    ));
 1120 
 1121    if (phy == SCI_INVALID_HANDLE)
 1122    {
 1123       return SCI_FAILURE_INVALID_PHY;
 1124    }
 1125 
 1126    memset(properties, 0, sizeof(SCIC_PHY_PROPERTIES_T));
 1127 
 1128    //get max link rate of this phy set by user.
 1129    max_speed_generation =
 1130       this_phy->owning_port->owning_controller->user_parameters.sds1.
 1131          phys[this_phy->phy_index].max_speed_generation;
 1132 
 1133    properties->negotiated_link_rate     = this_phy->max_negotiated_speed;
 1134 
 1135    if (max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED)
 1136       properties->max_link_rate            = SCI_SAS_600_GB;
 1137    else if (max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED)
 1138       properties->max_link_rate            = SCI_SAS_300_GB;
 1139    else
 1140       properties->max_link_rate            = SCI_SAS_150_GB;
 1141 
 1142    properties->index                    = this_phy->phy_index;
 1143    properties->owning_port              = scic_sds_phy_get_port(this_phy);
 1144 
 1145    scic_sds_phy_get_protocols(this_phy, &properties->transmit_iaf.protocols);
 1146 
 1147    properties->transmit_iaf.sas_address.high =
 1148       this_phy->owning_port->owning_controller->oem_parameters.sds1.
 1149          phys[this_phy->phy_index].sas_address.sci_format.high;
 1150 
 1151    properties->transmit_iaf.sas_address.low =
 1152       this_phy->owning_port->owning_controller->oem_parameters.sds1.
 1153          phys[this_phy->phy_index].sas_address.sci_format.low;
 1154 
 1155    return SCI_SUCCESS;
 1156 }
 1157 
 1158 // ---------------------------------------------------------------------------
 1159 
 1160 SCI_STATUS scic_sas_phy_get_properties(
 1161    SCI_PHY_HANDLE_T            phy,
 1162    SCIC_SAS_PHY_PROPERTIES_T * properties
 1163 )
 1164 {
 1165    SCIC_SDS_PHY_T *this_phy;
 1166    this_phy = (SCIC_SDS_PHY_T *)phy;
 1167 
 1168    SCIC_LOG_TRACE((
 1169       sci_base_object_get_logger(this_phy),
 1170       SCIC_LOG_OBJECT_PHY,
 1171       "scic_sas_phy_get_properties(0x%x, 0x%x) enter\n",
 1172       this_phy, properties
 1173    ));
 1174 
 1175    if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
 1176    {
 1177       memcpy(
 1178          &properties->received_iaf,
 1179          &this_phy->phy_type.sas.identify_address_frame_buffer,
 1180          sizeof(SCI_SAS_IDENTIFY_ADDRESS_FRAME_T)
 1181       );
 1182 
 1183       properties->received_capabilities.u.all
 1184          = SCU_SAS_RECPHYCAP_READ(this_phy);
 1185 
 1186       return SCI_SUCCESS;
 1187    }
 1188 
 1189    return SCI_FAILURE;
 1190 }
 1191 
 1192 // ---------------------------------------------------------------------------
 1193 
 1194 SCI_STATUS scic_sata_phy_get_properties(
 1195    SCI_PHY_HANDLE_T             phy,
 1196    SCIC_SATA_PHY_PROPERTIES_T * properties
 1197 )
 1198 {
 1199    SCIC_SDS_PHY_T *this_phy;
 1200    this_phy = (SCIC_SDS_PHY_T *)phy;
 1201 
 1202    SCIC_LOG_TRACE((
 1203       sci_base_object_get_logger(this_phy),
 1204       SCIC_LOG_OBJECT_PHY,
 1205       "scic_sata_phy_get_properties(0x%x, 0x%x) enter\n",
 1206       this_phy, properties
 1207    ));
 1208 
 1209    if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)
 1210    {
 1211       memcpy(
 1212          &properties->signature_fis,
 1213          &this_phy->phy_type.sata.signature_fis_buffer,
 1214          sizeof(SATA_FIS_REG_D2H_T)
 1215       );
 1216 
 1217       /// @todo add support for port selectors.
 1218       properties->is_port_selector_present = FALSE;
 1219 
 1220       return SCI_SUCCESS;
 1221    }
 1222 
 1223    return SCI_FAILURE;
 1224 }
 1225 
 1226 // ---------------------------------------------------------------------------
 1227 
 1228 #if !defined(DISABLE_PORT_SELECTORS)
 1229 
 1230 SCI_STATUS scic_sata_phy_send_port_selection_signal(
 1231    SCI_PHY_HANDLE_T  phy
 1232 )
 1233 {
 1234    SCIC_SDS_PHY_T *this_phy;
 1235    this_phy = (SCIC_SDS_PHY_T *)phy;
 1236 
 1237    SCIC_LOG_TRACE((
 1238       sci_base_object_get_logger(this_phy),
 1239       SCIC_LOG_OBJECT_PHY,
 1240       "scic_sata_phy_send_port_selection_signals(0x%x) enter\n",
 1241       this_phy
 1242    ));
 1243 
 1244    /// @todo To be implemented
 1245    ASSERT(FALSE);
 1246    return SCI_FAILURE;
 1247 }
 1248 
 1249 #endif // !defined(DISABLE_PORT_SELECTORS)
 1250 
 1251 // ---------------------------------------------------------------------------
 1252 
 1253 #if !defined(DISABLE_PHY_COUNTERS)
 1254 
 1255 SCI_STATUS scic_phy_enable_counter(
 1256    SCI_PHY_HANDLE_T       phy,
 1257    SCIC_PHY_COUNTER_ID_T  counter_id
 1258 )
 1259 {
 1260    SCIC_SDS_PHY_T *this_phy;
 1261    SCI_STATUS status = SCI_SUCCESS;
 1262    this_phy = (SCIC_SDS_PHY_T *)phy;
 1263 
 1264    SCIC_LOG_TRACE((
 1265       sci_base_object_get_logger(this_phy),
 1266       SCIC_LOG_OBJECT_PHY,
 1267       "scic_phy_enable_counter(0x%x, 0x%x) enter\n",
 1268       this_phy, counter_id
 1269    ));
 1270 
 1271    switch(counter_id)
 1272    {
 1273       case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
 1274          {
 1275             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1276             control |= (1 << SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX);
 1277             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1278          }
 1279          break;
 1280       case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
 1281          {
 1282             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1283             control |= (1 << SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX);
 1284             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1285          }
 1286          break;
 1287       case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
 1288          {
 1289             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1290             control |= (1 << SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX);
 1291             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1292          }
 1293          break;
 1294       case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
 1295          {
 1296             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1297             control |= (1 << SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX);
 1298             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1299          }
 1300          break;
 1301       case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
 1302          {
 1303             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1304             control |= (1 << SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX);
 1305             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1306          }
 1307          break;
 1308       case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
 1309          {
 1310             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1311             control |= (1 << SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX);
 1312             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1313          }
 1314          break;
 1315 
 1316          // These error counters are enabled by default, and cannot be
 1317          //  disabled.  Return SCI_SUCCESS to denote that they are
 1318          //  enabled, hiding the fact that enabling the counter is
 1319          //  a no-op.
 1320       case SCIC_PHY_COUNTER_RECEIVED_FRAME:
 1321       case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
 1322       case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
 1323       case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
 1324       case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
 1325       case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
 1326       case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
 1327       case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
 1328       case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
 1329       case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
 1330       case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
 1331          break;
 1332 
 1333       default:
 1334          status = SCI_FAILURE;
 1335          break;
 1336    }
 1337    return status;
 1338 }
 1339 
 1340 // ---------------------------------------------------------------------------
 1341 
 1342 SCI_STATUS scic_phy_disable_counter(
 1343    SCI_PHY_HANDLE_T       phy,
 1344    SCIC_PHY_COUNTER_ID_T  counter_id
 1345 )
 1346 {
 1347    SCIC_SDS_PHY_T *this_phy;
 1348    SCI_STATUS status = SCI_SUCCESS;
 1349 
 1350    this_phy = (SCIC_SDS_PHY_T *)phy;
 1351 
 1352    SCIC_LOG_TRACE((
 1353       sci_base_object_get_logger(this_phy),
 1354       SCIC_LOG_OBJECT_PHY,
 1355       "scic_phy_disable_counter(0x%x, 0x%x) enter\n",
 1356       this_phy, counter_id
 1357    ));
 1358 
 1359    switch(counter_id)
 1360    {
 1361       case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
 1362          {
 1363             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1364             control &= ~(1 << SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX);
 1365             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1366          }
 1367          break;
 1368       case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
 1369          {
 1370             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1371             control &= ~(1 << SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX);
 1372             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1373          }
 1374          break;
 1375       case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
 1376          {
 1377             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1378             control &= ~(1 << SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX);
 1379             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1380          }
 1381          break;
 1382       case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
 1383          {
 1384             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1385             control &= ~(1 << SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX);
 1386             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1387          }
 1388          break;
 1389       case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
 1390          {
 1391             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1392             control &= ~(1 << SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX);
 1393             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1394          }
 1395          break;
 1396       case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
 1397          {
 1398             U32 control = SCU_SAS_ECENCR_READ(this_phy);
 1399             control &= ~(1 << SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX);
 1400             SCU_SAS_ECENCR_WRITE(this_phy, control);
 1401          }
 1402          break;
 1403 
 1404          // These error counters cannot be disabled, so return SCI_FAILURE.
 1405       case SCIC_PHY_COUNTER_RECEIVED_FRAME:
 1406       case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
 1407       case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
 1408       case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
 1409       case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
 1410       case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
 1411       case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
 1412       case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
 1413       case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
 1414       case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
 1415       case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
 1416       default:
 1417          status = SCI_FAILURE;
 1418          break;
 1419    }
 1420    return status;
 1421 }
 1422 
 1423 // ---------------------------------------------------------------------------
 1424 
 1425 SCI_STATUS scic_phy_get_counter(
 1426    SCI_PHY_HANDLE_T        phy,
 1427    SCIC_PHY_COUNTER_ID_T   counter_id,
 1428    U32                   * data
 1429 )
 1430 {
 1431    SCIC_SDS_PHY_T *this_phy;
 1432    SCI_STATUS status = SCI_SUCCESS;
 1433    this_phy = (SCIC_SDS_PHY_T *)phy;
 1434 
 1435    SCIC_LOG_TRACE((
 1436       sci_base_object_get_logger(this_phy),
 1437       SCIC_LOG_OBJECT_PHY,
 1438       "scic_phy_get_counter(0x%x, 0x%x) enter\n",
 1439       this_phy, counter_id
 1440    ));
 1441 
 1442    switch(counter_id)
 1443    {
 1444       case SCIC_PHY_COUNTER_RECEIVED_FRAME:
 1445          *data = scu_link_layer_register_read(this_phy, received_frame_count);
 1446          break;
 1447       case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
 1448          *data = scu_link_layer_register_read(this_phy, transmit_frame_count);
 1449          break;
 1450       case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
 1451          *data = scu_link_layer_register_read(this_phy, received_dword_count);
 1452          break;
 1453       case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
 1454          *data = scu_link_layer_register_read(this_phy, transmit_dword_count);
 1455          break;
 1456       case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
 1457          *data = scu_link_layer_register_read(this_phy, loss_of_sync_error_count);
 1458          break;
 1459       case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
 1460          *data = scu_link_layer_register_read(this_phy, running_disparity_error_count);
 1461          break;
 1462       case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
 1463          *data = scu_link_layer_register_read(this_phy, received_frame_crc_error_count);
 1464          break;
 1465       case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
 1466          *data = this_phy->error_counter[SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX];
 1467          break;
 1468       case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
 1469          *data = this_phy->error_counter[SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX];
 1470          break;
 1471       case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
 1472          *data = this_phy->error_counter[SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX];
 1473          break;
 1474       case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
 1475          *data = this_phy->error_counter[SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX];
 1476          break;
 1477       case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
 1478          *data = this_phy->error_counter[SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX];
 1479          break;
 1480       case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
 1481          *data = this_phy->error_counter[SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX];
 1482          break;
 1483       case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
 1484          *data = scu_link_layer_register_read(this_phy, received_short_frame_count);
 1485          break;
 1486       case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
 1487          *data = scu_link_layer_register_read(this_phy, received_frame_without_credit_count);
 1488          break;
 1489       case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
 1490          *data = scu_link_layer_register_read(this_phy, received_frame_after_done_count);
 1491          break;
 1492       case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
 1493          *data = scu_link_layer_register_read(this_phy, phy_reset_problem_count);
 1494          break;
 1495       default:
 1496          status = SCI_FAILURE;
 1497          break;
 1498    }
 1499 
 1500    return status;
 1501 }
 1502 
 1503 // ---------------------------------------------------------------------------
 1504 
 1505 SCI_STATUS scic_phy_clear_counter(
 1506    SCI_PHY_HANDLE_T       phy,
 1507    SCIC_PHY_COUNTER_ID_T  counter_id
 1508 )
 1509 {
 1510    SCIC_SDS_PHY_T *this_phy;
 1511    SCI_STATUS status = SCI_SUCCESS;
 1512    this_phy = (SCIC_SDS_PHY_T *)phy;
 1513 
 1514    SCIC_LOG_TRACE((
 1515       sci_base_object_get_logger(this_phy),
 1516       SCIC_LOG_OBJECT_PHY,
 1517       "scic_phy_clear_counter(0x%x, 0x%x) enter\n",
 1518       this_phy, counter_id
 1519    ));
 1520 
 1521    switch(counter_id)
 1522    {
 1523       case SCIC_PHY_COUNTER_RECEIVED_FRAME:
 1524          scu_link_layer_register_write(this_phy, received_frame_count, 0);
 1525          break;
 1526       case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
 1527          scu_link_layer_register_write(this_phy, transmit_frame_count, 0);
 1528          break;
 1529       case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
 1530          scu_link_layer_register_write(this_phy, received_dword_count, 0);
 1531          break;
 1532       case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
 1533          scu_link_layer_register_write(this_phy, transmit_dword_count, 0);
 1534          break;
 1535       case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
 1536          scu_link_layer_register_write(this_phy, loss_of_sync_error_count, 0);
 1537          break;
 1538       case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
 1539          scu_link_layer_register_write(this_phy, running_disparity_error_count, 0);
 1540          break;
 1541       case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
 1542          scu_link_layer_register_write(this_phy, received_frame_crc_error_count, 0);
 1543          break;
 1544       case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
 1545          this_phy->error_counter[SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX] = 0;
 1546          break;
 1547       case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
 1548          this_phy->error_counter[SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX] = 0;
 1549          break;
 1550       case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
 1551          this_phy->error_counter[SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX] = 0;
 1552          break;
 1553       case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
 1554          this_phy->error_counter[SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX] = 0;
 1555          break;
 1556       case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
 1557          this_phy->error_counter[SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX] = 0;
 1558          break;
 1559       case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
 1560          this_phy->error_counter[SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX] = 0;
 1561          break;
 1562       case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
 1563          scu_link_layer_register_write(this_phy, received_short_frame_count, 0);
 1564          break;
 1565       case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
 1566          scu_link_layer_register_write(this_phy, received_frame_without_credit_count, 0);
 1567          break;
 1568       case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
 1569          scu_link_layer_register_write(this_phy, received_frame_after_done_count, 0);
 1570          break;
 1571       case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
 1572          scu_link_layer_register_write(this_phy, phy_reset_problem_count, 0);
 1573          break;
 1574       default:
 1575          status = SCI_FAILURE;
 1576    }
 1577 
 1578    return status;
 1579 }
 1580 
 1581 #endif // !defined(DISABLE_PHY_COUNTERS)
 1582 
 1583 SCI_STATUS scic_phy_stop(
 1584    SCI_PHY_HANDLE_T       phy
 1585 )
 1586 {
 1587    SCIC_SDS_PHY_T *this_phy;
 1588    this_phy = (SCIC_SDS_PHY_T *)phy;
 1589 
 1590    SCIC_LOG_TRACE((
 1591       sci_base_object_get_logger(this_phy),
 1592       SCIC_LOG_OBJECT_PHY,
 1593       "scic_phy_stop(this_phy:0x%x)\n",
 1594       this_phy
 1595    ));
 1596 
 1597    return this_phy->state_handlers->parent.stop_handler(&this_phy->parent);
 1598 }
 1599 
 1600 SCI_STATUS scic_phy_start(
 1601    SCI_PHY_HANDLE_T       phy
 1602 )
 1603 {
 1604    SCIC_SDS_PHY_T *this_phy;
 1605    this_phy = (SCIC_SDS_PHY_T *)phy;
 1606 
 1607    SCIC_LOG_TRACE((
 1608       sci_base_object_get_logger(this_phy),
 1609       SCIC_LOG_OBJECT_PHY,
 1610       "scic_phy_start(this_phy:0x%x)\n",
 1611       this_phy
 1612    ));
 1613 
 1614    return this_phy->state_handlers->parent.start_handler(&this_phy->parent);
 1615 }
 1616 
 1617 //******************************************************************************
 1618 //* PHY STATE MACHINE
 1619 //******************************************************************************
 1620 
 1621 //***************************************************************************
 1622 //*  DEFAULT HANDLERS
 1623 //***************************************************************************
 1624 
 1625 /**
 1626  * This is the default method for phy a start request.  It will report a
 1627  * warning and exit.
 1628  *
 1629  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1630  *       SCIC_SDS_PHY object.
 1631  *
 1632  * @return SCI_STATUS
 1633  * @retval SCI_FAILURE_INVALID_STATE
 1634  */
 1635 SCI_STATUS scic_sds_phy_default_start_handler(
 1636    SCI_BASE_PHY_T *phy
 1637 )
 1638 {
 1639    SCIC_SDS_PHY_T *this_phy;
 1640    this_phy = (SCIC_SDS_PHY_T *)phy;
 1641 
 1642    SCIC_LOG_WARNING((
 1643       sci_base_object_get_logger(this_phy),
 1644       SCIC_LOG_OBJECT_PHY,
 1645       "SCIC Phy 0x%08x requested to start from invalid state %d\n",
 1646       this_phy,
 1647       sci_base_state_machine_get_state(&this_phy->parent.state_machine)
 1648    ));
 1649 
 1650    return SCI_FAILURE_INVALID_STATE;
 1651 
 1652 }
 1653 
 1654 /**
 1655  * This is the default method for phy a stop request.  It will report a
 1656  * warning and exit.
 1657  *
 1658  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1659  *       SCIC_SDS_PHY object.
 1660  *
 1661  * @return SCI_STATUS
 1662  * @retval SCI_FAILURE_INVALID_STATE
 1663  */
 1664 SCI_STATUS scic_sds_phy_default_stop_handler(
 1665    SCI_BASE_PHY_T *phy
 1666 )
 1667 {
 1668    SCIC_SDS_PHY_T *this_phy;
 1669    this_phy = (SCIC_SDS_PHY_T *)phy;
 1670 
 1671    SCIC_LOG_WARNING((
 1672       sci_base_object_get_logger(this_phy),
 1673       SCIC_LOG_OBJECT_PHY,
 1674       "SCIC Phy 0x%08x requested to stop from invalid state %d\n",
 1675       this_phy,
 1676       sci_base_state_machine_get_state(&this_phy->parent.state_machine)
 1677    ));
 1678 
 1679    return SCI_FAILURE_INVALID_STATE;
 1680 }
 1681 
 1682 /**
 1683  * This is the default method for phy a reset request.  It will report a
 1684  * warning and exit.
 1685  *
 1686  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1687  *       SCIC_SDS_PHY object.
 1688  *
 1689  * @return SCI_STATUS
 1690  * @retval SCI_FAILURE_INVALID_STATE
 1691  */
 1692 SCI_STATUS scic_sds_phy_default_reset_handler(
 1693    SCI_BASE_PHY_T * phy
 1694 )
 1695 {
 1696    SCIC_SDS_PHY_T *this_phy;
 1697    this_phy = (SCIC_SDS_PHY_T *)phy;
 1698 
 1699    SCIC_LOG_WARNING((
 1700       sci_base_object_get_logger(this_phy),
 1701       SCIC_LOG_OBJECT_PHY,
 1702       "SCIC Phy 0x%08x requested to reset from invalid state %d\n",
 1703       this_phy,
 1704       sci_base_state_machine_get_state(&this_phy->parent.state_machine)
 1705    ));
 1706 
 1707    return SCI_FAILURE_INVALID_STATE;
 1708 }
 1709 
 1710 /**
 1711  * This is the default method for phy a destruct request.  It will report a
 1712  * warning and exit.
 1713  *
 1714  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1715  *       SCIC_SDS_PHY object.
 1716  *
 1717  * @return SCI_STATUS
 1718  * @retval SCI_FAILURE_INVALID_STATE
 1719  */
 1720 SCI_STATUS scic_sds_phy_default_destroy_handler(
 1721    SCI_BASE_PHY_T *phy
 1722 )
 1723 {
 1724    SCIC_SDS_PHY_T *this_phy;
 1725    this_phy = (SCIC_SDS_PHY_T *)phy;
 1726 
 1727    /// @todo Implement something for the default
 1728    SCIC_LOG_WARNING((
 1729       sci_base_object_get_logger(this_phy),
 1730       SCIC_LOG_OBJECT_PHY,
 1731       "SCIC Phy 0x%08x requested to destroy from invalid state %d\n",
 1732       this_phy,
 1733       sci_base_state_machine_get_state(&this_phy->parent.state_machine)
 1734    ));
 1735 
 1736    return SCI_FAILURE_INVALID_STATE;
 1737 }
 1738 
 1739 /**
 1740  * This is the default method for a phy frame handling request.  It will
 1741  * report a warning, release the frame and exit.
 1742  *
 1743  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1744  *       SCIC_SDS_PHY object.
 1745  * @param[in] frame_index This is the frame index that was received from the
 1746  *       SCU hardware.
 1747  *
 1748  * @return SCI_STATUS
 1749  * @retval SCI_FAILURE_INVALID_STATE
 1750  */
 1751 SCI_STATUS scic_sds_phy_default_frame_handler(
 1752    SCIC_SDS_PHY_T *this_phy,
 1753    U32            frame_index
 1754 )
 1755 {
 1756    SCIC_LOG_WARNING((
 1757       sci_base_object_get_logger(this_phy),
 1758       SCIC_LOG_OBJECT_PHY,
 1759       "SCIC Phy 0x%08x received unexpected frame data %d while in state %d\n",
 1760       this_phy, frame_index,
 1761       sci_base_state_machine_get_state(&this_phy->parent.state_machine)
 1762    ));
 1763 
 1764    scic_sds_controller_release_frame(
 1765       scic_sds_phy_get_controller(this_phy), frame_index);
 1766 
 1767    return SCI_FAILURE_INVALID_STATE;
 1768 }
 1769 
 1770 /**
 1771  * This is the default method for a phy event handler.  It will report a
 1772  * warning and exit.
 1773  *
 1774  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1775  *       SCIC_SDS_PHY object.
 1776  * @param[in] event_code This is the event code that was received from the SCU
 1777  *       hardware.
 1778  *
 1779  * @return SCI_STATUS
 1780  * @retval SCI_FAILURE_INVALID_STATE
 1781  */
 1782 SCI_STATUS scic_sds_phy_default_event_handler(
 1783    SCIC_SDS_PHY_T *this_phy,
 1784    U32            event_code
 1785 )
 1786 {
 1787    SCIC_LOG_WARNING((
 1788       sci_base_object_get_logger(this_phy),
 1789       SCIC_LOG_OBJECT_PHY,
 1790       "SCIC Phy 0x%08x received unexpected event status %x while in state %d\n",
 1791       this_phy, event_code,
 1792       sci_base_state_machine_get_state(&this_phy->parent.state_machine)
 1793    ));
 1794 
 1795    return SCI_FAILURE_INVALID_STATE;
 1796 }
 1797 
 1798 /**
 1799  * This is the default method for a phy consume power handler.  It will report
 1800  * a warning and exit.
 1801  *
 1802  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1803  *       SCIC_SDS_PHY object.
 1804  *
 1805  * @return SCI_STATUS
 1806  * @retval SCI_FAILURE_INVALID_STATE
 1807  */
 1808 SCI_STATUS scic_sds_phy_default_consume_power_handler(
 1809    SCIC_SDS_PHY_T *this_phy
 1810 )
 1811 {
 1812    SCIC_LOG_WARNING((
 1813       sci_base_object_get_logger(this_phy),
 1814       SCIC_LOG_OBJECT_PHY,
 1815       "SCIC Phy 0x%08x given unexpected permission to consume power while in state %d\n",
 1816       this_phy,
 1817       sci_base_state_machine_get_state(&this_phy->parent.state_machine)
 1818    ));
 1819 
 1820    return SCI_FAILURE_INVALID_STATE;
 1821 }
 1822 
 1823 //******************************************************************************
 1824 //* PHY STOPPED STATE HANDLERS
 1825 //******************************************************************************
 1826 
 1827 /**
 1828  * This method takes the SCIC_SDS_PHY from a stopped state and attempts to
 1829  * start it.
 1830  *    - The phy state machine is transitioned to the
 1831  *      SCI_BASE_PHY_STATE_STARTING.
 1832  *
 1833  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1834  *       SCIC_SDS_PHY object.
 1835  *
 1836  * @return SCI_STATUS
 1837  * @retval SCI_SUCCESS
 1838  */
 1839 static
 1840 SCI_STATUS scic_sds_phy_stopped_state_start_handler(
 1841    SCI_BASE_PHY_T *phy
 1842 )
 1843 {
 1844    SCIC_SDS_PHY_T *this_phy;
 1845    this_phy = (SCIC_SDS_PHY_T *)phy;
 1846 
 1847 
 1848 
 1849    // Create the SIGNATURE FIS Timeout timer for this phy
 1850    this_phy->sata_timeout_timer = scic_cb_timer_create(
 1851       scic_sds_phy_get_controller(this_phy),
 1852       scic_sds_phy_sata_timeout,
 1853       this_phy
 1854    );
 1855 
 1856    if (this_phy->sata_timeout_timer != NULL)
 1857    {
 1858       sci_base_state_machine_change_state(
 1859          scic_sds_phy_get_base_state_machine(this_phy),
 1860          SCI_BASE_PHY_STATE_STARTING
 1861       );
 1862    }
 1863 
 1864    return SCI_SUCCESS;
 1865 }
 1866 
 1867 /**
 1868  * This method takes the SCIC_SDS_PHY from a stopped state and destroys it.
 1869  *    - This function takes no action.
 1870  *
 1871  * @todo Shouldn't this function transition the SCI_BASE_PHY::state_machine to
 1872  *        the SCI_BASE_PHY_STATE_FINAL?
 1873  *
 1874  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1875  *       SCIC_SDS_PHY object.
 1876  *
 1877  * @return SCI_STATUS
 1878  * @retval SCI_SUCCESS
 1879  */
 1880 static
 1881 SCI_STATUS scic_sds_phy_stopped_state_destroy_handler(
 1882    SCI_BASE_PHY_T *phy
 1883 )
 1884 {
 1885    SCIC_SDS_PHY_T *this_phy;
 1886    this_phy = (SCIC_SDS_PHY_T *)phy;
 1887 
 1888    /// @todo what do we actually need to do here?
 1889    return SCI_SUCCESS;
 1890 }
 1891 
 1892 //******************************************************************************
 1893 //* PHY STARTING STATE HANDLERS
 1894 //******************************************************************************
 1895 
 1896 // All of these state handlers are mapped to the starting sub-state machine
 1897 
 1898 //******************************************************************************
 1899 //* PHY READY STATE HANDLERS
 1900 //******************************************************************************
 1901 
 1902 /**
 1903  * This method takes the SCIC_SDS_PHY from a ready state and attempts to stop
 1904  * it.
 1905  *    - The phy state machine is transitioned to the SCI_BASE_PHY_STATE_STOPPED.
 1906  *
 1907  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1908  *       SCIC_SDS_PHY object.
 1909  *
 1910  * @return SCI_STATUS
 1911  * @retval SCI_SUCCESS
 1912  */
 1913 static
 1914 SCI_STATUS scic_sds_phy_ready_state_stop_handler(
 1915    SCI_BASE_PHY_T *phy
 1916 )
 1917 {
 1918    SCIC_SDS_PHY_T *this_phy;
 1919    this_phy = (SCIC_SDS_PHY_T *)phy;
 1920 
 1921    sci_base_state_machine_change_state(
 1922       scic_sds_phy_get_base_state_machine(this_phy),
 1923       SCI_BASE_PHY_STATE_STOPPED
 1924    );
 1925 
 1926    scic_sds_controller_link_down(
 1927       scic_sds_phy_get_controller(this_phy),
 1928       scic_sds_phy_get_port(this_phy),
 1929       this_phy
 1930    );
 1931 
 1932    return SCI_SUCCESS;
 1933 }
 1934 
 1935 /**
 1936  * This method takes the SCIC_SDS_PHY from a ready state and attempts to reset
 1937  * it.
 1938  *    - The phy state machine is transitioned to the SCI_BASE_PHY_STATE_STARTING.
 1939  *
 1940  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 1941  *       SCIC_SDS_PHY object.
 1942  *
 1943  * @return SCI_STATUS
 1944  * @retval SCI_SUCCESS
 1945  */
 1946 static
 1947 SCI_STATUS scic_sds_phy_ready_state_reset_handler(
 1948    SCI_BASE_PHY_T * phy
 1949 )
 1950 {
 1951    SCIC_SDS_PHY_T * this_phy;
 1952    this_phy = (SCIC_SDS_PHY_T *)phy;
 1953 
 1954    sci_base_state_machine_change_state(
 1955       scic_sds_phy_get_base_state_machine(this_phy),
 1956       SCI_BASE_PHY_STATE_RESETTING
 1957    );
 1958 
 1959    return SCI_SUCCESS;
 1960 }
 1961 
 1962 /**
 1963  * This method request the SCIC_SDS_PHY handle the received event.  The only
 1964  * event that we are interested in while in the ready state is the link
 1965  * failure event.
 1966  *    - decoded event is a link failure
 1967  *       - transition the SCIC_SDS_PHY back to the SCI_BASE_PHY_STATE_STARTING
 1968  *         state.
 1969  *    - any other event received will report a warning message
 1970  *
 1971  * @param[in] phy This is the SCIC_SDS_PHY object which has received the
 1972  *       event.
 1973  *
 1974  * @return SCI_STATUS
 1975  * @retval SCI_SUCCESS if the event received is a link failure
 1976  * @retval SCI_FAILURE_INVALID_STATE for any other event received.
 1977  */
 1978 static
 1979 SCI_STATUS scic_sds_phy_ready_state_event_handler(
 1980    SCIC_SDS_PHY_T *this_phy,
 1981    U32            event_code
 1982 )
 1983 {
 1984    SCI_STATUS result = SCI_FAILURE;
 1985 
 1986    switch (scu_get_event_code(event_code))
 1987    {
 1988    case SCU_EVENT_LINK_FAILURE:
 1989       // Link failure change state back to the starting state
 1990       sci_base_state_machine_change_state(
 1991          scic_sds_phy_get_base_state_machine(this_phy),
 1992          SCI_BASE_PHY_STATE_STARTING
 1993          );
 1994 
 1995       result = SCI_SUCCESS;
 1996       break;
 1997 
 1998    case SCU_EVENT_BROADCAST_CHANGE:
 1999       // Broadcast change received. Notify the port.
 2000       if (scic_sds_phy_get_port(this_phy) != SCI_INVALID_HANDLE)
 2001          scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy);
 2002       else
 2003          this_phy->bcn_received_while_port_unassigned = TRUE;
 2004       break;
 2005 
 2006    case SCU_EVENT_ERR_CNT(RX_CREDIT_BLOCKED_RECEIVED):
 2007    case SCU_EVENT_ERR_CNT(TX_DONE_CREDIT_TIMEOUT):
 2008    case SCU_EVENT_ERR_CNT(RX_DONE_CREDIT_TIMEOUT):
 2009    case SCU_EVENT_ERR_CNT(INACTIVITY_TIMER_EXPIRED):
 2010    case SCU_EVENT_ERR_CNT(TX_DONE_ACK_NAK_TIMEOUT):
 2011    case SCU_EVENT_ERR_CNT(RX_DONE_ACK_NAK_TIMEOUT):
 2012       {
 2013          U32 error_counter_index =
 2014                 scu_get_event_specifier(event_code) >> SCU_EVENT_SPECIFIC_CODE_SHIFT;
 2015 
 2016          this_phy->error_counter[error_counter_index]++;
 2017          result = SCI_SUCCESS;
 2018       }
 2019       break;
 2020 
 2021    default:
 2022       SCIC_LOG_WARNING((
 2023          sci_base_object_get_logger(this_phy),
 2024          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
 2025          "SCIC PHY 0x%x ready state machine received unexpected event_code %x\n",
 2026          this_phy, event_code
 2027       ));
 2028       result = SCI_FAILURE_INVALID_STATE;
 2029       break;
 2030    }
 2031 
 2032    return result;
 2033 }
 2034 
 2035 // ---------------------------------------------------------------------------
 2036 
 2037 /**
 2038  * This is the resetting state event handler.
 2039  *
 2040  * @param[in] this_phy This is the SCIC_SDS_PHY object which is receiving the
 2041  *       event.
 2042  * @param[in] event_code This is the event code to be processed.
 2043  *
 2044  * @return SCI_STATUS
 2045  * @retval SCI_FAILURE_INVALID_STATE
 2046  */
 2047 static
 2048 SCI_STATUS scic_sds_phy_resetting_state_event_handler(
 2049    SCIC_SDS_PHY_T *this_phy,
 2050    U32            event_code
 2051 )
 2052 {
 2053    SCI_STATUS result = SCI_FAILURE;
 2054 
 2055    switch (scu_get_event_code(event_code))
 2056    {
 2057    case SCU_EVENT_HARD_RESET_TRANSMITTED:
 2058       // Link failure change state back to the starting state
 2059       sci_base_state_machine_change_state(
 2060          scic_sds_phy_get_base_state_machine(this_phy),
 2061          SCI_BASE_PHY_STATE_STARTING
 2062          );
 2063 
 2064       result = SCI_SUCCESS;
 2065       break;
 2066 
 2067    default:
 2068       SCIC_LOG_WARNING((
 2069          sci_base_object_get_logger(this_phy),
 2070          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
 2071          "SCIC PHY 0x%x resetting state machine received unexpected event_code %x\n",
 2072          this_phy, event_code
 2073       ));
 2074 
 2075       result = SCI_FAILURE_INVALID_STATE;
 2076       break;
 2077    }
 2078 
 2079    return result;
 2080 }
 2081 
 2082 // ---------------------------------------------------------------------------
 2083 
 2084 SCIC_SDS_PHY_STATE_HANDLER_T
 2085    scic_sds_phy_state_handler_table[SCI_BASE_PHY_MAX_STATES] =
 2086 {
 2087    // SCI_BASE_PHY_STATE_INITIAL
 2088    {
 2089       {
 2090          scic_sds_phy_default_start_handler,
 2091          scic_sds_phy_default_stop_handler,
 2092          scic_sds_phy_default_reset_handler,
 2093          scic_sds_phy_default_destroy_handler
 2094       },
 2095       scic_sds_phy_default_frame_handler,
 2096       scic_sds_phy_default_event_handler,
 2097       scic_sds_phy_default_consume_power_handler
 2098    },
 2099    // SCI_BASE_PHY_STATE_STOPPED
 2100    {
 2101       {
 2102          scic_sds_phy_stopped_state_start_handler,
 2103          scic_sds_phy_default_stop_handler,
 2104          scic_sds_phy_default_reset_handler,
 2105          scic_sds_phy_stopped_state_destroy_handler
 2106       },
 2107       scic_sds_phy_default_frame_handler,
 2108       scic_sds_phy_default_event_handler,
 2109       scic_sds_phy_default_consume_power_handler
 2110    },
 2111    // SCI_BASE_PHY_STATE_STARTING
 2112    {
 2113       {
 2114          scic_sds_phy_default_start_handler,
 2115          scic_sds_phy_default_stop_handler,
 2116          scic_sds_phy_default_reset_handler,
 2117          scic_sds_phy_default_destroy_handler
 2118       },
 2119       scic_sds_phy_default_frame_handler,
 2120       scic_sds_phy_default_event_handler,
 2121       scic_sds_phy_default_consume_power_handler
 2122    },
 2123    // SCI_BASE_PHY_STATE_READY
 2124    {
 2125       {
 2126          scic_sds_phy_default_start_handler,
 2127          scic_sds_phy_ready_state_stop_handler,
 2128          scic_sds_phy_ready_state_reset_handler,
 2129          scic_sds_phy_default_destroy_handler
 2130       },
 2131       scic_sds_phy_default_frame_handler,
 2132       scic_sds_phy_ready_state_event_handler,
 2133       scic_sds_phy_default_consume_power_handler
 2134    },
 2135    // SCI_BASE_PHY_STATE_RESETTING
 2136    {
 2137       {
 2138          scic_sds_phy_default_start_handler,
 2139          scic_sds_phy_default_stop_handler,
 2140          scic_sds_phy_default_reset_handler,
 2141          scic_sds_phy_default_destroy_handler
 2142       },
 2143       scic_sds_phy_default_frame_handler,
 2144       scic_sds_phy_resetting_state_event_handler,
 2145       scic_sds_phy_default_consume_power_handler
 2146    },
 2147    // SCI_BASE_PHY_STATE_FINAL
 2148    {
 2149       {
 2150          scic_sds_phy_default_start_handler,
 2151          scic_sds_phy_default_stop_handler,
 2152          scic_sds_phy_default_reset_handler,
 2153          scic_sds_phy_default_destroy_handler
 2154       },
 2155       scic_sds_phy_default_frame_handler,
 2156       scic_sds_phy_default_event_handler,
 2157       scic_sds_phy_default_consume_power_handler
 2158    }
 2159 };
 2160 
 2161 //****************************************************************************
 2162 //*  PHY STATE PRIVATE METHODS
 2163 //****************************************************************************
 2164 
 2165 /**
 2166  * This method will stop the SCIC_SDS_PHY object. This does not reset the
 2167  * protocol engine it just suspends it and places it in a state where it will
 2168  * not cause the end device to power up.
 2169  *
 2170  * @param[in] this_phy This is the SCIC_SDS_PHY object to stop.
 2171  *
 2172  * @return none
 2173  */
 2174 static
 2175 void scu_link_layer_stop_protocol_engine(
 2176    SCIC_SDS_PHY_T *this_phy
 2177 )
 2178 {
 2179    U32 scu_sas_pcfg_value;
 2180    U32 enable_spinup_value;
 2181 
 2182    // Suspend the protocol engine and place it in a sata spinup hold state
 2183    scu_sas_pcfg_value  = SCU_SAS_PCFG_READ(this_phy);
 2184    scu_sas_pcfg_value |= (
 2185                            SCU_SAS_PCFG_GEN_BIT(OOB_RESET)
 2186                          | SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE)
 2187                          | SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD)
 2188                          );
 2189    SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
 2190 
 2191    // Disable the notify enable spinup primitives
 2192    enable_spinup_value = SCU_SAS_ENSPINUP_READ(this_phy);
 2193    enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE);
 2194    SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup_value);
 2195 }
 2196 
 2197 /**
 2198  * This method will start the OOB/SN state machine for this SCIC_SDS_PHY
 2199  * object.
 2200  *
 2201  * @param[in] this_phy This is the SCIC_SDS_PHY object on which to start the
 2202  *       OOB/SN state machine.
 2203  */
 2204 static
 2205 void scu_link_layer_start_oob(
 2206    SCIC_SDS_PHY_T *this_phy
 2207 )
 2208 {
 2209    U32 scu_sas_pcfg_value;
 2210 
 2211    /* Reset OOB sequence - start */
 2212    scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
 2213    scu_sas_pcfg_value &=
 2214       ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
 2215    SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
 2216    SCU_SAS_PCFG_READ(this_phy);
 2217    /* Reset OOB sequence - end */
 2218 
 2219    /* Start OOB sequence - start */
 2220    scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
 2221    scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
 2222    SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
 2223    SCU_SAS_PCFG_READ(this_phy);
 2224    /* Start OOB sequence - end */
 2225 }
 2226 
 2227 /**
 2228  * This method will transmit a hard reset request on the specified phy. The
 2229  * SCU hardware requires that we reset the OOB state machine and set the hard
 2230  * reset bit in the phy configuration register.
 2231  * We then must start OOB over with the hard reset bit set.
 2232  *
 2233  * @param[in] this_phy
 2234  */
 2235 static
 2236 void scu_link_layer_tx_hard_reset(
 2237    SCIC_SDS_PHY_T *this_phy
 2238 )
 2239 {
 2240    U32 phy_configuration_value;
 2241 
 2242    // SAS Phys must wait for the HARD_RESET_TX event notification to transition
 2243    // to the starting state.
 2244    phy_configuration_value = SCU_SAS_PCFG_READ(this_phy);
 2245    phy_configuration_value |=
 2246       (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | SCU_SAS_PCFG_GEN_BIT(OOB_RESET));
 2247    SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value);
 2248 
 2249    // Now take the OOB state machine out of reset
 2250    phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
 2251    phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
 2252    SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value);
 2253 }
 2254 
 2255 //****************************************************************************
 2256 //*  PHY BASE STATE METHODS
 2257 //****************************************************************************
 2258 
 2259 /**
 2260  * This method will perform the actions required by the SCIC_SDS_PHY on
 2261  * entering the SCI_BASE_PHY_STATE_INITIAL.
 2262  *    - This function sets the state handlers for the phy object base state
 2263  * machine initial state.
 2264  *
 2265  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 2266  *       SCIC_SDS_PHY object.
 2267  *
 2268  * @return none
 2269  */
 2270 static
 2271 void scic_sds_phy_initial_state_enter(
 2272    SCI_BASE_OBJECT_T *object
 2273 )
 2274 {
 2275    SCIC_SDS_PHY_T *this_phy;
 2276    this_phy = (SCIC_SDS_PHY_T *)object;
 2277 
 2278    scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_INITIAL);
 2279 }
 2280 
 2281 /**
 2282  * This method will perform the actions required by the SCIC_SDS_PHY on
 2283  * entering the SCI_BASE_PHY_STATE_INITIAL.
 2284  *    - This function sets the state handlers for the phy object base state
 2285  * machine initial state.
 2286  *    - The SCU hardware is requested to stop the protocol engine.
 2287  *
 2288  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 2289  *       SCIC_SDS_PHY object.
 2290  *
 2291  * @return none
 2292  */
 2293 static
 2294 void scic_sds_phy_stopped_state_enter(
 2295    SCI_BASE_OBJECT_T *object
 2296 )
 2297 {
 2298    SCIC_SDS_PHY_T *this_phy;
 2299    this_phy = (SCIC_SDS_PHY_T *)object;
 2300 
 2301    /// @todo We need to get to the controller to place this PE in a reset state
 2302    scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED);
 2303 
 2304    if (this_phy->sata_timeout_timer != NULL)
 2305    {
 2306       scic_cb_timer_destroy(
 2307          scic_sds_phy_get_controller(this_phy),
 2308          this_phy->sata_timeout_timer
 2309       );
 2310 
 2311       this_phy->sata_timeout_timer = NULL;
 2312    }
 2313 
 2314    scu_link_layer_stop_protocol_engine(this_phy);
 2315 }
 2316 
 2317 /**
 2318  * This method will perform the actions required by the SCIC_SDS_PHY on
 2319  * entering the SCI_BASE_PHY_STATE_STARTING.
 2320  *    - This function sets the state handlers for the phy object base state
 2321  * machine starting state.
 2322  *    - The SCU hardware is requested to start OOB/SN on this protocol engine.
 2323  *    - The phy starting substate machine is started.
 2324  *    - If the previous state was the ready state then the
 2325  *      SCIC_SDS_CONTROLLER is informed that the phy has gone link down.
 2326  *
 2327  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 2328  *       SCIC_SDS_PHY object.
 2329  *
 2330  * @return none
 2331  */
 2332 static
 2333 void scic_sds_phy_starting_state_enter(
 2334    SCI_BASE_OBJECT_T *object
 2335 )
 2336 {
 2337    SCIC_SDS_PHY_T *this_phy;
 2338    this_phy = (SCIC_SDS_PHY_T *)object;
 2339 
 2340    scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STARTING);
 2341 
 2342    scu_link_layer_stop_protocol_engine(this_phy);
 2343    scu_link_layer_start_oob(this_phy);
 2344 
 2345    // We don't know what kind of phy we are going to be just yet
 2346    this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
 2347    this_phy->bcn_received_while_port_unassigned = FALSE;
 2348 
 2349    // Change over to the starting substate machine to continue
 2350    sci_base_state_machine_start(&this_phy->starting_substate_machine);
 2351 
 2352    if (this_phy->parent.state_machine.previous_state_id
 2353        == SCI_BASE_PHY_STATE_READY)
 2354    {
 2355       scic_sds_controller_link_down(
 2356          scic_sds_phy_get_controller(this_phy),
 2357          scic_sds_phy_get_port(this_phy),
 2358          this_phy
 2359       );
 2360    }
 2361 }
 2362 
 2363 /**
 2364  * This method will perform the actions required by the SCIC_SDS_PHY on
 2365  * entering the SCI_BASE_PHY_STATE_READY.
 2366  *    - This function sets the state handlers for the phy object base state
 2367  * machine ready state.
 2368  *    - The SCU hardware protocol engine is resumed.
 2369  *    - The SCIC_SDS_CONTROLLER is informed that the phy object has gone link
 2370  *      up.
 2371  *
 2372  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 2373  *       SCIC_SDS_PHY object.
 2374  *
 2375  * @return none
 2376  */
 2377 static
 2378 void scic_sds_phy_ready_state_enter(
 2379    SCI_BASE_OBJECT_T *object
 2380 )
 2381 {
 2382    SCIC_SDS_PHY_T *this_phy;
 2383    this_phy = (SCIC_SDS_PHY_T *)object;
 2384 
 2385    scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_READY);
 2386 
 2387    scic_sds_controller_link_up(
 2388       scic_sds_phy_get_controller(this_phy),
 2389       scic_sds_phy_get_port(this_phy),
 2390       this_phy
 2391    );
 2392 }
 2393 
 2394 /**
 2395  * This method will perform the actions required by the SCIC_SDS_PHY on
 2396  * exiting the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU
 2397  * hardware protocol engine represented by this SCIC_SDS_PHY object.
 2398  *
 2399  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 2400  *       SCIC_SDS_PHY object.
 2401  *
 2402  * @return none
 2403  */
 2404 static
 2405 void scic_sds_phy_ready_state_exit(
 2406    SCI_BASE_OBJECT_T *object
 2407 )
 2408 {
 2409    SCIC_SDS_PHY_T *this_phy;
 2410    this_phy = (SCIC_SDS_PHY_T *)object;
 2411 
 2412    scic_sds_phy_suspend(this_phy);
 2413 }
 2414 
 2415 /**
 2416  * This method will perform the actions required by the SCIC_SDS_PHY on
 2417  * entering the SCI_BASE_PHY_STATE_RESETTING.
 2418  *    - This function sets the state handlers for the phy object base state
 2419  * machine resetting state.
 2420  *
 2421  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 2422  *       SCIC_SDS_PHY object.
 2423  *
 2424  * @return none
 2425  */
 2426 static
 2427 void scic_sds_phy_resetting_state_enter(
 2428    SCI_BASE_OBJECT_T *object
 2429 )
 2430 {
 2431    SCIC_SDS_PHY_T * this_phy;
 2432    this_phy = (SCIC_SDS_PHY_T *)object;
 2433 
 2434    scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_RESETTING);
 2435 
 2436    // The phy is being reset, therefore deactivate it from the port.
 2437    // In the resetting state we don't notify the user regarding
 2438    // link up and link down notifications.
 2439    scic_sds_port_deactivate_phy(this_phy->owning_port, this_phy, FALSE);
 2440 
 2441    if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
 2442    {
 2443       scu_link_layer_tx_hard_reset(this_phy);
 2444    }
 2445    else
 2446    {
 2447       // The SCU does not need to have a descrete reset state so just go back to
 2448       // the starting state.
 2449       sci_base_state_machine_change_state(
 2450          &this_phy->parent.state_machine,
 2451          SCI_BASE_PHY_STATE_STARTING
 2452       );
 2453    }
 2454 }
 2455 
 2456 /**
 2457  * This method will perform the actions required by the SCIC_SDS_PHY on
 2458  * entering the SCI_BASE_PHY_STATE_FINAL.
 2459  *    - This function sets the state handlers for the phy object base state
 2460  * machine final state.
 2461  *
 2462  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 2463  *       SCIC_SDS_PHY object.
 2464  *
 2465  * @return none
 2466  */
 2467 static
 2468 void scic_sds_phy_final_state_enter(
 2469    SCI_BASE_OBJECT_T *object
 2470 )
 2471 {
 2472    SCIC_SDS_PHY_T *this_phy;
 2473    this_phy = (SCIC_SDS_PHY_T *)object;
 2474 
 2475    scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_FINAL);
 2476 
 2477    // Nothing to do here
 2478 }
 2479 
 2480 // ---------------------------------------------------------------------------
 2481 
 2482 SCI_BASE_STATE_T scic_sds_phy_state_table[SCI_BASE_PHY_MAX_STATES] =
 2483 {
 2484    {
 2485       SCI_BASE_PHY_STATE_INITIAL,
 2486       scic_sds_phy_initial_state_enter,
 2487       NULL,
 2488    },
 2489    {
 2490       SCI_BASE_PHY_STATE_STOPPED,
 2491       scic_sds_phy_stopped_state_enter,
 2492       NULL,
 2493    },
 2494    {
 2495       SCI_BASE_PHY_STATE_STARTING,
 2496       scic_sds_phy_starting_state_enter,
 2497       NULL,
 2498    },
 2499    {
 2500       SCI_BASE_PHY_STATE_READY,
 2501       scic_sds_phy_ready_state_enter,
 2502       scic_sds_phy_ready_state_exit,
 2503    },
 2504    {
 2505       SCI_BASE_PHY_STATE_RESETTING,
 2506       scic_sds_phy_resetting_state_enter,
 2507       NULL,
 2508    },
 2509    {
 2510       SCI_BASE_PHY_STATE_FINAL,
 2511       scic_sds_phy_final_state_enter,
 2512       NULL,
 2513    }
 2514 };
 2515 
 2516 //******************************************************************************
 2517 //* PHY STARTING SUB-STATE MACHINE
 2518 //******************************************************************************
 2519 
 2520 //*****************************************************************************
 2521 //* SCIC SDS PHY HELPER FUNCTIONS
 2522 //*****************************************************************************
 2523 
 2524 
 2525 /**
 2526  * This method continues the link training for the phy as if it were a SAS PHY
 2527  * instead of a SATA PHY. This is done because the completion queue had a SAS
 2528  * PHY DETECTED event when the state machine was expecting a SATA PHY event.
 2529  *
 2530  * @param[in] this_phy The phy object that received SAS PHY DETECTED.
 2531  *
 2532  * @return none
 2533  */
 2534 static
 2535 void scic_sds_phy_start_sas_link_training(
 2536    SCIC_SDS_PHY_T * this_phy
 2537 )
 2538 {
 2539    U32 phy_control;
 2540 
 2541    phy_control = SCU_SAS_PCFG_READ(this_phy);
 2542    phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD);
 2543    SCU_SAS_PCFG_WRITE(this_phy, phy_control);
 2544 
 2545    sci_base_state_machine_change_state(
 2546       &this_phy->starting_substate_machine,
 2547       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
 2548    );
 2549 
 2550    this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS;
 2551 }
 2552 
 2553 /**
 2554  * This method continues the link training for the phy as if it were a SATA
 2555  * PHY instead of a SAS PHY.  This is done because the completion queue had a
 2556  * SATA SPINUP HOLD event when the state machine was expecting a SAS PHY
 2557  * event.
 2558  *
 2559  * @param[in] this_phy The phy object that received a SATA SPINUP HOLD event
 2560  *
 2561  * @return none
 2562  */
 2563 static
 2564 void scic_sds_phy_start_sata_link_training(
 2565    SCIC_SDS_PHY_T * this_phy
 2566 )
 2567 {
 2568    sci_base_state_machine_change_state(
 2569       &this_phy->starting_substate_machine,
 2570       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER
 2571    );
 2572 
 2573    this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
 2574 }
 2575 
 2576 /**
 2577  * @brief This method performs processing common to all protocols upon
 2578  *        completion of link training.
 2579  *
 2580  * @param[in,out] this_phy This parameter specifies the phy object for which
 2581  *                link training has completed.
 2582  * @param[in]     max_link_rate This parameter specifies the maximum link
 2583  *                rate to be associated with this phy.
 2584  * @param[in]     next_state This parameter specifies the next state for the
 2585  *                phy's starting sub-state machine.
 2586  *
 2587  * @return none
 2588  */
 2589 static
 2590 void scic_sds_phy_complete_link_training(
 2591    SCIC_SDS_PHY_T *   this_phy,
 2592    SCI_SAS_LINK_RATE  max_link_rate,
 2593    U32                next_state
 2594 )
 2595 {
 2596    this_phy->max_negotiated_speed = max_link_rate;
 2597 
 2598    sci_base_state_machine_change_state(
 2599       scic_sds_phy_get_starting_substate_machine(this_phy), next_state
 2600    );
 2601 }
 2602 
 2603 /**
 2604  * This method restarts the SCIC_SDS_PHY objects base state machine in the
 2605  * starting state from any starting substate.
 2606  *
 2607  * @param[in] this_phy The SCIC_SDS_PHY object to restart.
 2608  *
 2609  * @return none
 2610  */
 2611 void scic_sds_phy_restart_starting_state(
 2612    SCIC_SDS_PHY_T *this_phy
 2613 )
 2614 {
 2615    // Stop the current substate machine
 2616    sci_base_state_machine_stop(
 2617       scic_sds_phy_get_starting_substate_machine(this_phy)
 2618    );
 2619 
 2620    // Re-enter the base state machine starting state
 2621    sci_base_state_machine_change_state(
 2622       scic_sds_phy_get_base_state_machine(this_phy),
 2623       SCI_BASE_PHY_STATE_STARTING
 2624       );
 2625 }
 2626 
 2627 
 2628 //*****************************************************************************
 2629 //* SCIC SDS PHY general handlers
 2630 //*****************************************************************************
 2631 
 2632 static
 2633 SCI_STATUS scic_sds_phy_starting_substate_general_stop_handler(
 2634    SCI_BASE_PHY_T *phy
 2635 )
 2636 {
 2637    SCIC_SDS_PHY_T *this_phy;
 2638    this_phy = (SCIC_SDS_PHY_T *)phy;
 2639 
 2640    sci_base_state_machine_stop(
 2641       &this_phy->starting_substate_machine
 2642    );
 2643 
 2644    sci_base_state_machine_change_state(
 2645       &phy->state_machine,
 2646       SCI_BASE_PHY_STATE_STOPPED
 2647    );
 2648 
 2649    return SCI_SUCCESS;
 2650 }
 2651 
 2652 //*****************************************************************************
 2653 //* SCIC SDS PHY EVENT_HANDLERS
 2654 //*****************************************************************************
 2655 
 2656 /**
 2657  * This method is called when an event notification is received for the phy
 2658  * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN.
 2659  *    - decode the event
 2660  *       - sas phy detected causes a state transition to the wait for speed
 2661  *         event notification.
 2662  *       - any other events log a warning message and set a failure status
 2663  *
 2664  * @param[in] phy This SCIC_SDS_PHY object which has received an event.
 2665  * @param[in] event_code This is the event code which the phy object is to
 2666  *       decode.
 2667  *
 2668  * @return SCI_STATUS
 2669  * @retval SCI_SUCCESS on any valid event notification
 2670  * @retval SCI_FAILURE on any unexpected event notifation
 2671  */
 2672 static
 2673 SCI_STATUS scic_sds_phy_starting_substate_await_ossp_event_handler(
 2674    SCIC_SDS_PHY_T *this_phy,
 2675    U32 event_code
 2676 )
 2677 {
 2678    U32 result = SCI_SUCCESS;
 2679 
 2680    switch (scu_get_event_code(event_code))
 2681    {
 2682    case SCU_EVENT_SAS_PHY_DETECTED:
 2683       scic_sds_phy_start_sas_link_training(this_phy);
 2684       this_phy->is_in_link_training = TRUE;
 2685    break;
 2686 
 2687    case SCU_EVENT_SATA_SPINUP_HOLD:
 2688       scic_sds_phy_start_sata_link_training(this_phy);
 2689       this_phy->is_in_link_training = TRUE;
 2690    break;
 2691 
 2692    default:
 2693       SCIC_LOG_WARNING((
 2694          sci_base_object_get_logger(this_phy),
 2695          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
 2696          "PHY starting substate machine received unexpected event_code %x\n",
 2697          event_code
 2698       ));
 2699 
 2700       result = SCI_FAILURE;
 2701    break;
 2702    }
 2703 
 2704    return result;
 2705 }
 2706 
 2707 /**
 2708  * This method is called when an event notification is received for the phy
 2709  * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN.
 2710  *    - decode the event
 2711  *       - sas phy detected returns us back to this state.
 2712  *       - speed event detected causes a state transition to the wait for iaf.
 2713  *       - identify timeout is an un-expected event and the state machine is
 2714  *         restarted.
 2715  *       - link failure events restart the starting state machine
 2716  *       - any other events log a warning message and set a failure status
 2717  *
 2718  * @param[in] phy This SCIC_SDS_PHY object which has received an event.
 2719  * @param[in] event_code This is the event code which the phy object is to
 2720  *       decode.
 2721  *
 2722  * @return SCI_STATUS
 2723  * @retval SCI_SUCCESS on any valid event notification
 2724  * @retval SCI_FAILURE on any unexpected event notifation
 2725  */
 2726 static
 2727 SCI_STATUS scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler(
 2728    SCIC_SDS_PHY_T *this_phy,
 2729    U32 event_code
 2730 )
 2731 {
 2732    U32 result = SCI_SUCCESS;
 2733 
 2734    switch (scu_get_event_code(event_code))
 2735    {
 2736    case SCU_EVENT_SAS_PHY_DETECTED:
 2737       // Why is this being reported again by the controller?
 2738       // We would re-enter this state so just stay here
 2739    break;
 2740 
 2741    case SCU_EVENT_SAS_15:
 2742    case SCU_EVENT_SAS_15_SSC:
 2743       scic_sds_phy_complete_link_training(
 2744          this_phy, SCI_SAS_150_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
 2745       );
 2746    break;
 2747 
 2748    case SCU_EVENT_SAS_30:
 2749    case SCU_EVENT_SAS_30_SSC:
 2750       scic_sds_phy_complete_link_training(
 2751          this_phy, SCI_SAS_300_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
 2752       );
 2753    break;
 2754 
 2755    case SCU_EVENT_SAS_60:
 2756    case SCU_EVENT_SAS_60_SSC:
 2757       scic_sds_phy_complete_link_training(
 2758          this_phy, SCI_SAS_600_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
 2759       );
 2760    break;
 2761 
 2762    case SCU_EVENT_SATA_SPINUP_HOLD:
 2763       // We were doing SAS PHY link training and received a SATA PHY event
 2764       // continue OOB/SN as if this were a SATA PHY
 2765       scic_sds_phy_start_sata_link_training(this_phy);
 2766    break;
 2767 
 2768    case SCU_EVENT_LINK_FAILURE:
 2769       // Link failure change state back to the starting state
 2770       scic_sds_phy_restart_starting_state(this_phy);
 2771    break;
 2772 
 2773    default:
 2774       SCIC_LOG_WARNING((
 2775          sci_base_object_get_logger(this_phy),
 2776          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
 2777          "PHY starting substate machine received unexpected event_code %x\n",
 2778          event_code
 2779       ));
 2780 
 2781       result = SCI_FAILURE;
 2782    break;
 2783    }
 2784 
 2785    return result;
 2786 }
 2787 
 2788 /**
 2789  * This method is called when an event notification is received for the phy
 2790  * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF.
 2791  *    - decode the event
 2792  *       - sas phy detected event backs up the state machine to the await
 2793  *         speed notification.
 2794  *       - identify timeout is an un-expected event and the state machine is
 2795  *         restarted.
 2796  *       - link failure events restart the starting state machine
 2797  *       - any other events log a warning message and set a failure status
 2798  *
 2799  * @param[in] phy This SCIC_SDS_PHY object which has received an event.
 2800  * @param[in] event_code This is the event code which the phy object is to
 2801  *       decode.
 2802  *
 2803  * @return SCI_STATUS
 2804  * @retval SCI_SUCCESS on any valid event notification
 2805  * @retval SCI_FAILURE on any unexpected event notifation
 2806  */
 2807 static
 2808 SCI_STATUS scic_sds_phy_starting_substate_await_iaf_uf_event_handler(
 2809    SCIC_SDS_PHY_T *this_phy,
 2810    U32 event_code
 2811 )
 2812 {
 2813    U32 result = SCI_SUCCESS;
 2814 
 2815    switch (scu_get_event_code(event_code))
 2816    {
 2817    case SCU_EVENT_SAS_PHY_DETECTED:
 2818       // Backup the state machine
 2819       scic_sds_phy_start_sas_link_training(this_phy);
 2820       break;
 2821 
 2822    case SCU_EVENT_SATA_SPINUP_HOLD:
 2823       // We were doing SAS PHY link training and received a SATA PHY event
 2824       // continue OOB/SN as if this were a SATA PHY
 2825       scic_sds_phy_start_sata_link_training(this_phy);
 2826    break;
 2827 
 2828    case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
 2829    case SCU_EVENT_LINK_FAILURE:
 2830    case SCU_EVENT_HARD_RESET_RECEIVED:
 2831       // Start the oob/sn state machine over again
 2832       scic_sds_phy_restart_starting_state(this_phy);
 2833       break;
 2834 
 2835    default:
 2836       SCIC_LOG_WARNING((
 2837          sci_base_object_get_logger(this_phy),
 2838          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
 2839          "PHY starting substate machine received unexpected event_code %x\n",
 2840          event_code
 2841       ));
 2842 
 2843       result = SCI_FAILURE;
 2844       break;
 2845    }
 2846 
 2847    return result;
 2848 }
 2849 
 2850 /**
 2851  * This method is called when an event notification is received for the phy
 2852  * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_POWER.
 2853  *    - decode the event
 2854  *       - link failure events restart the starting state machine
 2855  *       - any other events log a warning message and set a failure status
 2856  *
 2857  * @param[in] phy This SCIC_SDS_PHY object which has received an event.
 2858  * @param[in] event_code This is the event code which the phy object is to
 2859  *       decode.
 2860  *
 2861  * @return SCI_STATUS
 2862  * @retval SCI_SUCCESS on a link failure event
 2863  * @retval SCI_FAILURE on any unexpected event notifation
 2864  */
 2865 static
 2866 SCI_STATUS scic_sds_phy_starting_substate_await_sas_power_event_handler(
 2867    SCIC_SDS_PHY_T *this_phy,
 2868    U32 event_code
 2869 )
 2870 {
 2871    U32 result = SCI_SUCCESS;
 2872 
 2873    switch (scu_get_event_code(event_code))
 2874    {
 2875    case SCU_EVENT_LINK_FAILURE:
 2876       // Link failure change state back to the starting state
 2877       scic_sds_phy_restart_starting_state(this_phy);
 2878       break;
 2879 
 2880    default:
 2881       SCIC_LOG_WARNING((
 2882          sci_base_object_get_logger(this_phy),
 2883          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
 2884          "PHY starting substate machine received unexpected event_code %x\n",
 2885          event_code
 2886       ));
 2887 
 2888       result = SCI_FAILURE;
 2889       break;
 2890    }
 2891 
 2892    return result;
 2893 }
 2894 
 2895 /**
 2896  * This method is called when an event notification is received for the phy
 2897  * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER.
 2898  *    - decode the event
 2899  *       - link failure events restart the starting state machine
 2900  *       - sata spinup hold events are ignored since they are expected
 2901  *       - any other events log a warning message and set a failure status
 2902  *
 2903  * @param[in] phy This SCIC_SDS_PHY object which has received an event.
 2904  * @param[in] event_code This is the event code which the phy object is to
 2905  *       decode.
 2906  *
 2907  * @return SCI_STATUS
 2908  * @retval SCI_SUCCESS on a link failure event
 2909  * @retval SCI_FAILURE on any unexpected event notifation
 2910  */
 2911 static
 2912 SCI_STATUS scic_sds_phy_starting_substate_await_sata_power_event_handler(
 2913    SCIC_SDS_PHY_T *this_phy,
 2914    U32 event_code
 2915 )
 2916 {
 2917    U32 result = SCI_SUCCESS;
 2918 
 2919    switch (scu_get_event_code(event_code))
 2920    {
 2921    case SCU_EVENT_LINK_FAILURE:
 2922       // Link failure change state back to the starting state
 2923       scic_sds_phy_restart_starting_state(this_phy);
 2924       break;
 2925 
 2926    case SCU_EVENT_SATA_SPINUP_HOLD:
 2927       // These events are received every 10ms and are expected while in this state
 2928       break;
 2929 
 2930    case SCU_EVENT_SAS_PHY_DETECTED:
 2931       // There has been a change in the phy type before OOB/SN for the
 2932       // SATA finished start down the SAS link traning path.
 2933       scic_sds_phy_start_sas_link_training(this_phy);
 2934    break;
 2935 
 2936    default:
 2937       SCIC_LOG_WARNING((
 2938          sci_base_object_get_logger(this_phy),
 2939          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
 2940          "PHY starting substate machine received unexpected event_code %x\n",
 2941          event_code
 2942       ));
 2943 
 2944       result = SCI_FAILURE;
 2945       break;
 2946    }
 2947 
 2948    return result;
 2949 }
 2950 
 2951 /**
 2952  * This method is called when an event notification is received for the phy
 2953  * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN.
 2954  *    - decode the event
 2955  *       - link failure events restart the starting state machine
 2956  *       - sata spinup hold events are ignored since they are expected
 2957  *       - sata phy detected event change to the wait speed event
 2958  *       - any other events log a warning message and set a failure status
 2959  *
 2960  * @param[in] phy This SCIC_SDS_PHY object which has received an event.
 2961  * @param[in] event_code This is the event code which the phy object is to
 2962  *       decode.
 2963  *
 2964  * @return SCI_STATUS
 2965  * @retval SCI_SUCCESS on a link failure event
 2966  * @retval SCI_FAILURE on any unexpected event notifation
 2967  */
 2968 static
 2969 SCI_STATUS scic_sds_phy_starting_substate_await_sata_phy_event_handler(
 2970    SCIC_SDS_PHY_T *this_phy,
 2971    U32 event_code
 2972 )
 2973 {
 2974    U32 result = SCI_SUCCESS;
 2975 
 2976    switch (scu_get_event_code(event_code))
 2977    {
 2978    case SCU_EVENT_LINK_FAILURE:
 2979       // Link failure change state back to the starting state
 2980       scic_sds_phy_restart_starting_state(this_phy);
 2981       break;
 2982 
 2983    case SCU_EVENT_SATA_SPINUP_HOLD:
 2984       // These events might be received since we dont know how many may be in
 2985       // the completion queue while waiting for power
 2986       break;
 2987 
 2988    case SCU_EVENT_SATA_PHY_DETECTED:
 2989       this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
 2990 
 2991       // We have received the SATA PHY notification change state
 2992       sci_base_state_machine_change_state(
 2993          scic_sds_phy_get_starting_substate_machine(this_phy),
 2994          SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
 2995          );
 2996       break;
 2997 
 2998    case SCU_EVENT_SAS_PHY_DETECTED:
 2999       // There has been a change in the phy type before OOB/SN for the
 3000       // SATA finished start down the SAS link traning path.
 3001       scic_sds_phy_start_sas_link_training(this_phy);
 3002    break;
 3003 
 3004    default:
 3005       SCIC_LOG_WARNING((
 3006          sci_base_object_get_logger(this_phy),
 3007          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
 3008          "PHY starting substate machine received unexpected event_code %x\n",
 3009          event_code
 3010       ));
 3011 
 3012       result = SCI_FAILURE;
 3013       break;
 3014    }
 3015 
 3016    return result;
 3017 }
 3018 
 3019 /**
 3020  * This method is called when an event notification is received for the phy
 3021  * object when in the state
 3022  * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
 3023  *    - decode the event
 3024  *       - sata phy detected returns us back to this state.
 3025  *       - speed event detected causes a state transition to the wait for
 3026  *         signature.
 3027  *       - link failure events restart the starting state machine
 3028  *       - any other events log a warning message and set a failure status
 3029  *
 3030  * @param[in] phy This SCIC_SDS_PHY object which has received an event.
 3031  * @param[in] event_code This is the event code which the phy object is to
 3032  *       decode.
 3033  *
 3034  * @return SCI_STATUS
 3035  * @retval SCI_SUCCESS on any valid event notification
 3036  * @retval SCI_FAILURE on any unexpected event notifation
 3037  */
 3038 static
 3039 SCI_STATUS scic_sds_phy_starting_substate_await_sata_speed_event_handler(
 3040    SCIC_SDS_PHY_T *this_phy,
 3041    U32 event_code
 3042 )
 3043 {
 3044    U32 result = SCI_SUCCESS;
 3045 
 3046    switch (scu_get_event_code(event_code))
 3047    {
 3048    case SCU_EVENT_SATA_PHY_DETECTED:
 3049       // The hardware reports multiple SATA PHY detected events
 3050       // ignore the extras
 3051    break;
 3052 
 3053    case SCU_EVENT_SATA_15:
 3054    case SCU_EVENT_SATA_15_SSC:
 3055       scic_sds_phy_complete_link_training(
 3056          this_phy,
 3057          SCI_SAS_150_GB,
 3058          SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
 3059       );
 3060    break;
 3061 
 3062    case SCU_EVENT_SATA_30:
 3063    case SCU_EVENT_SATA_30_SSC:
 3064       scic_sds_phy_complete_link_training(
 3065          this_phy,
 3066          SCI_SAS_300_GB,
 3067          SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
 3068       );
 3069    break;
 3070 
 3071    case SCU_EVENT_SATA_60:
 3072    case SCU_EVENT_SATA_60_SSC:
 3073       scic_sds_phy_complete_link_training(
 3074          this_phy,
 3075          SCI_SAS_600_GB,
 3076          SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
 3077       );
 3078    break;
 3079 
 3080    case SCU_EVENT_LINK_FAILURE:
 3081       // Link failure change state back to the starting state
 3082       scic_sds_phy_restart_starting_state(this_phy);
 3083    break;
 3084 
 3085    case SCU_EVENT_SAS_PHY_DETECTED:
 3086       // There has been a change in the phy type before OOB/SN for the
 3087       // SATA finished start down the SAS link traning path.
 3088       scic_sds_phy_start_sas_link_training(this_phy);
 3089    break;
 3090 
 3091    default:
 3092       SCIC_LOG_WARNING((
 3093          sci_base_object_get_logger(this_phy),
 3094          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
 3095          "PHY starting substate machine received unexpected event_code %x\n",
 3096          event_code
 3097       ));
 3098 
 3099       result = SCI_FAILURE;
 3100    break;
 3101    }
 3102 
 3103    return result;
 3104 }
 3105 
 3106 /**
 3107  * This method is called when an event notification is received for the phy
 3108  * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
 3109  *    - decode the event
 3110  *       - sas phy detected event backs up the state machine to the await
 3111  *         speed notification.
 3112  *       - identify timeout is an un-expected event and the state machine is
 3113  *         restarted.
 3114  *       - link failure events restart the starting state machine
 3115  *       - any other events log a warning message and set a failure status
 3116  *
 3117  * @param[in] phy This SCIC_SDS_PHY object which has received an event.
 3118  * @param[in] event_code This is the event code which the phy object is to
 3119  *       decode.
 3120  *
 3121  * @return SCI_STATUS
 3122  * @retval SCI_SUCCESS on any valid event notification
 3123  * @retval SCI_FAILURE on any unexpected event notifation
 3124  */
 3125 static
 3126 SCI_STATUS scic_sds_phy_starting_substate_await_sig_fis_event_handler(
 3127    SCIC_SDS_PHY_T *this_phy,
 3128    U32 event_code
 3129 )
 3130 {
 3131    U32 result = SCI_SUCCESS;
 3132 
 3133    switch (scu_get_event_code(event_code))
 3134    {
 3135    case SCU_EVENT_SATA_PHY_DETECTED:
 3136       // Backup the state machine
 3137       sci_base_state_machine_change_state(
 3138          scic_sds_phy_get_starting_substate_machine(this_phy),
 3139          SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
 3140          );
 3141       break;
 3142 
 3143    case SCU_EVENT_LINK_FAILURE:
 3144       // Link failure change state back to the starting state
 3145       scic_sds_phy_restart_starting_state(this_phy);
 3146       break;
 3147 
 3148    default:
 3149       SCIC_LOG_WARNING((
 3150          sci_base_object_get_logger(this_phy),
 3151          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
 3152          "PHY starting substate machine received unexpected event_code %x\n",
 3153          event_code
 3154       ));
 3155 
 3156       result = SCI_FAILURE;
 3157       break;
 3158    }
 3159 
 3160    return result;
 3161 }
 3162 
 3163 
 3164 //*****************************************************************************
 3165 //*  SCIC SDS PHY FRAME_HANDLERS
 3166 //*****************************************************************************
 3167 
 3168 /**
 3169  * This method decodes the unsolicited frame when the SCIC_SDS_PHY is in the
 3170  * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF.
 3171  *    - Get the UF Header
 3172  *    - If the UF is an IAF
 3173  *       - Copy IAF data to local phy object IAF data buffer.
 3174  *       - Change starting substate to wait power.
 3175  *    - else
 3176  *       - log warning message of unexpected unsolicted frame
 3177  *    - release frame buffer
 3178  *
 3179  * @param[in] phy This is SCIC_SDS_PHY object which is being requested to
 3180  *       decode the frame data.
 3181  * @param[in] frame_index This is the index of the unsolicited frame which was
 3182  *       received for this phy.
 3183  *
 3184  * @return SCI_STATUS
 3185  * @retval SCI_SUCCESS
 3186  */
 3187 static
 3188 SCI_STATUS scic_sds_phy_starting_substate_await_iaf_uf_frame_handler(
 3189    SCIC_SDS_PHY_T *this_phy,
 3190    U32            frame_index
 3191 )
 3192 {
 3193    SCI_STATUS                        result;
 3194    U32                              *frame_words;
 3195    SCI_SAS_IDENTIFY_ADDRESS_FRAME_T *identify_frame;
 3196 
 3197    result = scic_sds_unsolicited_frame_control_get_header(
 3198                &(scic_sds_phy_get_controller(this_phy)->uf_control),
 3199                frame_index,
 3200                (void **)&frame_words);
 3201 
 3202    if (result != SCI_SUCCESS)
 3203    {
 3204       return result;
 3205    }
 3206 
 3207    frame_words[0] = SCIC_SWAP_DWORD(frame_words[0]);
 3208    identify_frame = (SCI_SAS_IDENTIFY_ADDRESS_FRAME_T *)frame_words;
 3209 
 3210    if (identify_frame->address_frame_type == 0)
 3211    {
 3212       // Byte swap the rest of the frame so we can make
 3213       // a copy of the buffer
 3214       frame_words[1] = SCIC_SWAP_DWORD(frame_words[1]);
 3215       frame_words[2] = SCIC_SWAP_DWORD(frame_words[2]);
 3216       frame_words[3] = SCIC_SWAP_DWORD(frame_words[3]);
 3217       frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]);
 3218       frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]);
 3219 
 3220       memcpy(
 3221          &this_phy->phy_type.sas.identify_address_frame_buffer,
 3222          identify_frame,
 3223          sizeof(SCI_SAS_IDENTIFY_ADDRESS_FRAME_T)
 3224       );
 3225 
 3226       if (identify_frame->protocols.u.bits.smp_target)
 3227       {
 3228          // We got the IAF for an expander PHY go to the final state since
 3229          // there are no power requirements for expander phys.
 3230          sci_base_state_machine_change_state(
 3231             scic_sds_phy_get_starting_substate_machine(this_phy),
 3232             SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
 3233          );
 3234       }
 3235       else
 3236       {
 3237          // We got the IAF we can now go to the await spinup semaphore state
 3238          sci_base_state_machine_change_state(
 3239             scic_sds_phy_get_starting_substate_machine(this_phy),
 3240             SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
 3241          );
 3242       }
 3243 
 3244       result = SCI_SUCCESS;
 3245    }
 3246    else
 3247    {
 3248       SCIC_LOG_WARNING((
 3249          sci_base_object_get_logger(this_phy),
 3250          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_UNSOLICITED_FRAMES,
 3251          "PHY starting substate machine received unexpected frame id %x\n",
 3252          frame_index
 3253       ));
 3254    }
 3255 
 3256    // Regardless of the result release this frame since we are done with it
 3257    scic_sds_controller_release_frame(
 3258       scic_sds_phy_get_controller(this_phy), frame_index
 3259       );
 3260 
 3261    return result;
 3262 }
 3263 
 3264 /**
 3265  * This method decodes the unsolicited frame when the SCIC_SDS_PHY is in the
 3266  * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
 3267  *    - Get the UF Header
 3268  *    - If the UF is an SIGNATURE FIS
 3269  *       - Copy IAF data to local phy object SIGNATURE FIS data buffer.
 3270  *    - else
 3271  *       - log warning message of unexpected unsolicted frame
 3272  *    - release frame buffer
 3273  *
 3274  * @param[in] phy This is SCIC_SDS_PHY object which is being requested to
 3275  *       decode the frame data.
 3276  * @param[in] frame_index This is the index of the unsolicited frame which was
 3277  *       received for this phy.
 3278  *
 3279  * @return SCI_STATUS
 3280  * @retval SCI_SUCCESS
 3281  *
 3282  * @todo Must decode the SIGNATURE FIS data
 3283  */
 3284 static
 3285 SCI_STATUS scic_sds_phy_starting_substate_await_sig_fis_frame_handler(
 3286    SCIC_SDS_PHY_T *this_phy,
 3287    U32            frame_index
 3288 )
 3289 {
 3290    SCI_STATUS          result;
 3291    U32               * frame_words;
 3292    SATA_FIS_HEADER_T * fis_frame_header;
 3293    U32               * fis_frame_data;
 3294 
 3295    result = scic_sds_unsolicited_frame_control_get_header(
 3296                &(scic_sds_phy_get_controller(this_phy)->uf_control),
 3297                frame_index,
 3298                (void **)&frame_words);
 3299 
 3300    if (result != SCI_SUCCESS)
 3301    {
 3302       return result;
 3303    }
 3304 
 3305    fis_frame_header = (SATA_FIS_HEADER_T *)frame_words;
 3306 
 3307    if (
 3308          (fis_frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
 3309       && !(fis_frame_header->status & ATA_STATUS_REG_BSY_BIT)
 3310       )
 3311    {
 3312       scic_sds_unsolicited_frame_control_get_buffer(
 3313          &(scic_sds_phy_get_controller(this_phy)->uf_control),
 3314          frame_index,
 3315          (void **)&fis_frame_data
 3316       );
 3317 
 3318       scic_sds_controller_copy_sata_response(
 3319          &this_phy->phy_type.sata.signature_fis_buffer,
 3320          frame_words,
 3321          fis_frame_data
 3322       );
 3323 
 3324       // We got the IAF we can now go to the await spinup semaphore state
 3325       sci_base_state_machine_change_state(
 3326          scic_sds_phy_get_starting_substate_machine(this_phy),
 3327          SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
 3328          );
 3329 
 3330       result = SCI_SUCCESS;
 3331    }
 3332    else
 3333    {
 3334       SCIC_LOG_WARNING((
 3335          sci_base_object_get_logger(this_phy),
 3336          SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_UNSOLICITED_FRAMES,
 3337          "PHY starting substate machine received unexpected frame id %x\n",
 3338          frame_index
 3339       ));
 3340    }
 3341 
 3342    // Regardless of the result release this frame since we are done with it
 3343    scic_sds_controller_release_frame(
 3344       scic_sds_phy_get_controller(this_phy), frame_index
 3345       );
 3346 
 3347    return result;
 3348 }
 3349 
 3350 //*****************************************************************************
 3351 //* SCIC SDS PHY POWER_HANDLERS
 3352 //*****************************************************************************
 3353 
 3354 /**
 3355  * This method is called by the SCIC_SDS_CONTROLLER when the phy object is
 3356  * granted power.
 3357  *    - The notify enable spinups are turned on for this phy object
 3358  *    - The phy state machine is transitioned to the
 3359  *    SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL.
 3360  *
 3361  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 3362  *       SCIC_SDS_PHY object.
 3363  *
 3364  * @return SCI_STATUS
 3365  * @retval SCI_SUCCESS
 3366  */
 3367 static
 3368 SCI_STATUS scic_sds_phy_starting_substate_await_sas_power_consume_power_handler(
 3369    SCIC_SDS_PHY_T *this_phy
 3370 )
 3371 {
 3372    U32 enable_spinup;
 3373 
 3374    enable_spinup = SCU_SAS_ENSPINUP_READ(this_phy);
 3375    enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE);
 3376    SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup);
 3377 
 3378    // Change state to the final state this substate machine has run to completion
 3379    sci_base_state_machine_change_state(
 3380       scic_sds_phy_get_starting_substate_machine(this_phy),
 3381       SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
 3382       );
 3383 
 3384    return SCI_SUCCESS;
 3385 }
 3386 
 3387 /**
 3388  * This method is called by the SCIC_SDS_CONTROLLER when the phy object is
 3389  * granted power.
 3390  *    - The phy state machine is transitioned to the
 3391  *    SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN.
 3392  *
 3393  * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
 3394  *       SCIC_SDS_PHY object.
 3395  *
 3396  * @return SCI_STATUS
 3397  * @retval SCI_SUCCESS
 3398  */
 3399 static
 3400 SCI_STATUS scic_sds_phy_starting_substate_await_sata_power_consume_power_handler(
 3401    SCIC_SDS_PHY_T *this_phy
 3402 )
 3403 {
 3404    U32 scu_sas_pcfg_value;
 3405 
 3406    // Release the spinup hold state and reset the OOB state machine
 3407    scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
 3408    scu_sas_pcfg_value &=
 3409       ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE));
 3410    scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
 3411    SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
 3412 
 3413    // Now restart the OOB operation
 3414    scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
 3415    scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
 3416    SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
 3417 
 3418    // Change state to the final state this substate machine has run to completion
 3419    sci_base_state_machine_change_state(
 3420       scic_sds_phy_get_starting_substate_machine(this_phy),
 3421       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN
 3422    );
 3423 
 3424    return SCI_SUCCESS;
 3425 }
 3426 
 3427 // ---------------------------------------------------------------------------
 3428 
 3429 SCIC_SDS_PHY_STATE_HANDLER_T
 3430    scic_sds_phy_starting_substate_handler_table[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] =
 3431 {
 3432    // SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL
 3433    {
 3434       {
 3435          scic_sds_phy_default_start_handler,
 3436          scic_sds_phy_starting_substate_general_stop_handler,
 3437          scic_sds_phy_default_reset_handler,
 3438          scic_sds_phy_default_destroy_handler
 3439       },
 3440       scic_sds_phy_default_frame_handler,
 3441       scic_sds_phy_default_event_handler,
 3442       scic_sds_phy_default_consume_power_handler
 3443    },
 3444    // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
 3445    {
 3446       {
 3447          scic_sds_phy_default_start_handler,
 3448          scic_sds_phy_starting_substate_general_stop_handler,
 3449          scic_sds_phy_default_reset_handler,
 3450          scic_sds_phy_default_destroy_handler
 3451       },
 3452       scic_sds_phy_default_frame_handler,
 3453       scic_sds_phy_starting_substate_await_ossp_event_handler,
 3454       scic_sds_phy_default_consume_power_handler
 3455    },
 3456    // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
 3457    {
 3458       {
 3459          scic_sds_phy_default_start_handler,
 3460          scic_sds_phy_starting_substate_general_stop_handler,
 3461          scic_sds_phy_default_reset_handler,
 3462          scic_sds_phy_default_destroy_handler
 3463       },
 3464       scic_sds_phy_default_frame_handler,
 3465       scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler,
 3466       scic_sds_phy_default_consume_power_handler
 3467    },
 3468    // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
 3469    {
 3470       {
 3471          scic_sds_phy_default_start_handler,
 3472          scic_sds_phy_default_stop_handler,
 3473          scic_sds_phy_default_reset_handler,
 3474          scic_sds_phy_default_destroy_handler
 3475       },
 3476       scic_sds_phy_starting_substate_await_iaf_uf_frame_handler,
 3477       scic_sds_phy_starting_substate_await_iaf_uf_event_handler,
 3478       scic_sds_phy_default_consume_power_handler
 3479    },
 3480    // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
 3481    {
 3482       {
 3483          scic_sds_phy_default_start_handler,
 3484          scic_sds_phy_starting_substate_general_stop_handler,
 3485          scic_sds_phy_default_reset_handler,
 3486          scic_sds_phy_default_destroy_handler
 3487       },
 3488       scic_sds_phy_default_frame_handler,
 3489       scic_sds_phy_starting_substate_await_sas_power_event_handler,
 3490       scic_sds_phy_starting_substate_await_sas_power_consume_power_handler
 3491    },
 3492    // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER,
 3493    {
 3494       {
 3495          scic_sds_phy_default_start_handler,
 3496          scic_sds_phy_starting_substate_general_stop_handler,
 3497          scic_sds_phy_default_reset_handler,
 3498          scic_sds_phy_default_destroy_handler
 3499       },
 3500       scic_sds_phy_default_frame_handler,
 3501       scic_sds_phy_starting_substate_await_sata_power_event_handler,
 3502       scic_sds_phy_starting_substate_await_sata_power_consume_power_handler
 3503    },
 3504    // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN,
 3505    {
 3506       {
 3507          scic_sds_phy_default_start_handler,
 3508          scic_sds_phy_starting_substate_general_stop_handler,
 3509          scic_sds_phy_default_reset_handler,
 3510          scic_sds_phy_default_destroy_handler
 3511       },
 3512       scic_sds_phy_default_frame_handler,
 3513       scic_sds_phy_starting_substate_await_sata_phy_event_handler,
 3514       scic_sds_phy_default_consume_power_handler
 3515    },
 3516    // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN,
 3517    {
 3518       {
 3519          scic_sds_phy_default_start_handler,
 3520          scic_sds_phy_starting_substate_general_stop_handler,
 3521          scic_sds_phy_default_reset_handler,
 3522          scic_sds_phy_default_destroy_handler
 3523       },
 3524       scic_sds_phy_default_frame_handler,
 3525       scic_sds_phy_starting_substate_await_sata_speed_event_handler,
 3526       scic_sds_phy_default_consume_power_handler
 3527    },
 3528    // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF,
 3529    {
 3530       {
 3531          scic_sds_phy_default_start_handler,
 3532          scic_sds_phy_starting_substate_general_stop_handler,
 3533          scic_sds_phy_default_reset_handler,
 3534          scic_sds_phy_default_destroy_handler
 3535       },
 3536       scic_sds_phy_starting_substate_await_sig_fis_frame_handler,
 3537       scic_sds_phy_starting_substate_await_sig_fis_event_handler,
 3538       scic_sds_phy_default_consume_power_handler
 3539    },
 3540    // SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
 3541    {
 3542       {
 3543          scic_sds_phy_default_start_handler,
 3544          scic_sds_phy_starting_substate_general_stop_handler,
 3545          scic_sds_phy_default_reset_handler,
 3546          scic_sds_phy_default_destroy_handler
 3547       },
 3548       scic_sds_phy_default_frame_handler,
 3549       scic_sds_phy_default_event_handler,
 3550       scic_sds_phy_default_consume_power_handler
 3551    }
 3552 };
 3553 
 3554 /**
 3555  * This macro sets the starting substate handlers by state_id
 3556  */
 3557 #define scic_sds_phy_set_starting_substate_handlers(phy, state_id) \
 3558    scic_sds_phy_set_state_handlers( \
 3559       (phy), \
 3560       &scic_sds_phy_starting_substate_handler_table[(state_id)] \
 3561    )
 3562 
 3563 //****************************************************************************
 3564 //*  PHY STARTING SUBSTATE METHODS
 3565 //****************************************************************************
 3566 
 3567 /**
 3568  * This method will perform the actions required by the SCIC_SDS_PHY on
 3569  * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL.
 3570  *    - The initial state handlers are put in place for the SCIC_SDS_PHY
 3571  *      object.
 3572  *    - The state is changed to the wait phy type event notification.
 3573  *
 3574  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3575  *       SCIC_SDS_PHY object.
 3576  *
 3577  * @return none
 3578  */
 3579 static
 3580 void scic_sds_phy_starting_initial_substate_enter(
 3581    SCI_BASE_OBJECT_T *object
 3582 )
 3583 {
 3584    SCIC_SDS_PHY_T *this_phy;
 3585    this_phy = (SCIC_SDS_PHY_T *)object;
 3586 
 3587    scic_sds_phy_set_starting_substate_handlers(
 3588       this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL);
 3589 
 3590    // This is just an temporary state go off to the starting state
 3591    sci_base_state_machine_change_state(
 3592       scic_sds_phy_get_starting_substate_machine(this_phy),
 3593       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
 3594    );
 3595 }
 3596 
 3597 /**
 3598  * This method will perform the actions required by the SCIC_SDS_PHY on
 3599  * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN.
 3600  *    - Set the SCIC_SDS_PHY object state handlers for this state.
 3601  *
 3602  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3603  *       SCIC_SDS_PHY object.
 3604  *
 3605  * @return none
 3606  */
 3607 static
 3608 void scic_sds_phy_starting_await_ossp_en_substate_enter(
 3609    SCI_BASE_OBJECT_T *object
 3610 )
 3611 {
 3612    SCIC_SDS_PHY_T *this_phy;
 3613    this_phy = (SCIC_SDS_PHY_T *)object;
 3614 
 3615    scic_sds_phy_set_starting_substate_handlers(
 3616       this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
 3617       );
 3618 }
 3619 
 3620 /**
 3621  * This method will perform the actions required by the SCIC_SDS_PHY on
 3622  * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN.
 3623  *    - Set the SCIC_SDS_PHY object state handlers for this state.
 3624  *
 3625  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3626  *       SCIC_SDS_PHY object.
 3627  *
 3628  * @return none
 3629  */
 3630 static
 3631 void scic_sds_phy_starting_await_sas_speed_en_substate_enter(
 3632    SCI_BASE_OBJECT_T *object
 3633 )
 3634 {
 3635    SCIC_SDS_PHY_T *this_phy;
 3636    this_phy = (SCIC_SDS_PHY_T *)object;
 3637 
 3638    scic_sds_phy_set_starting_substate_handlers(
 3639       this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
 3640       );
 3641 }
 3642 
 3643 /**
 3644  * This method will perform the actions required by the SCIC_SDS_PHY on
 3645  * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF.
 3646  *    - Set the SCIC_SDS_PHY object state handlers for this state.
 3647  *
 3648  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3649  *       SCIC_SDS_PHY object.
 3650  *
 3651  * @return none
 3652  */
 3653 static
 3654 void scic_sds_phy_starting_await_iaf_uf_substate_enter(
 3655    SCI_BASE_OBJECT_T *object
 3656 )
 3657 {
 3658    SCIC_SDS_PHY_T *this_phy;
 3659    this_phy = (SCIC_SDS_PHY_T *)object;
 3660 
 3661    scic_sds_phy_set_starting_substate_handlers(
 3662       this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
 3663       );
 3664 }
 3665 
 3666 /**
 3667  * This method will perform the actions required by the SCIC_SDS_PHY on
 3668  * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER.
 3669  *    - Set the SCIC_SDS_PHY object state handlers for this state.
 3670  *    - Add this phy object to the power control queue
 3671  *
 3672  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3673  *       SCIC_SDS_PHY object.
 3674  *
 3675  * @return none
 3676  */
 3677 static
 3678 void scic_sds_phy_starting_await_sas_power_substate_enter(
 3679    SCI_BASE_OBJECT_T *object
 3680 )
 3681 {
 3682    SCIC_SDS_PHY_T *this_phy;
 3683    this_phy = (SCIC_SDS_PHY_T *)object;
 3684 
 3685    scic_sds_phy_set_starting_substate_handlers(
 3686       this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
 3687       );
 3688 
 3689    scic_sds_controller_power_control_queue_insert(
 3690       scic_sds_phy_get_controller(this_phy),
 3691       this_phy
 3692       );
 3693 }
 3694 
 3695 /**
 3696  * This method will perform the actions required by the SCIC_SDS_PHY on
 3697  * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER.
 3698  *    - Remove the SCIC_SDS_PHY object from the power control queue.
 3699  *
 3700  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3701  *       SCIC_SDS_PHY object.
 3702  *
 3703  * @return none
 3704  */
 3705 static
 3706 void scic_sds_phy_starting_await_sas_power_substate_exit(
 3707    SCI_BASE_OBJECT_T *object
 3708 )
 3709 {
 3710    SCIC_SDS_PHY_T *this_phy;
 3711    this_phy = (SCIC_SDS_PHY_T *)object;
 3712 
 3713    scic_sds_controller_power_control_queue_remove(
 3714       scic_sds_phy_get_controller(this_phy), this_phy
 3715    );
 3716 }
 3717 
 3718 /**
 3719  * This method will perform the actions required by the SCIC_SDS_PHY on
 3720  * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER.
 3721  *    - Set the SCIC_SDS_PHY object state handlers for this state.
 3722  *    - Add this phy object to the power control queue
 3723  *
 3724  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3725  *       SCIC_SDS_PHY object.
 3726  *
 3727  * @return none
 3728  */
 3729 static
 3730 void scic_sds_phy_starting_await_sata_power_substate_enter(
 3731    SCI_BASE_OBJECT_T *object
 3732 )
 3733 {
 3734    SCIC_SDS_PHY_T *this_phy;
 3735    this_phy = (SCIC_SDS_PHY_T *)object;
 3736 
 3737    scic_sds_phy_set_starting_substate_handlers(
 3738       this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER
 3739       );
 3740 
 3741    scic_sds_controller_power_control_queue_insert(
 3742       scic_sds_phy_get_controller(this_phy),
 3743       this_phy
 3744       );
 3745 }
 3746 
 3747 /**
 3748  * This method will perform the actions required by the SCIC_SDS_PHY on
 3749  * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER.
 3750  *    - Remove the SCIC_SDS_PHY object from the power control queue.
 3751  *
 3752  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3753  *       SCIC_SDS_PHY object.
 3754  *
 3755  * @return none
 3756  */
 3757 static
 3758 void scic_sds_phy_starting_await_sata_power_substate_exit(
 3759    SCI_BASE_OBJECT_T *object
 3760 )
 3761 {
 3762    SCIC_SDS_PHY_T *this_phy;
 3763    this_phy = (SCIC_SDS_PHY_T *)object;
 3764 
 3765    scic_sds_controller_power_control_queue_remove(
 3766       scic_sds_phy_get_controller(this_phy),
 3767       this_phy
 3768       );
 3769 }
 3770 
 3771 /**
 3772  * This method will perform the actions required by the SCIC_SDS_PHY on
 3773  * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN.
 3774  *    - Set the SCIC_SDS_PHY object state handlers for this state.
 3775  *
 3776  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3777  *       SCIC_SDS_PHY object.
 3778  *
 3779  * @return none
 3780  */
 3781 static
 3782 void scic_sds_phy_starting_await_sata_phy_substate_enter(
 3783    SCI_BASE_OBJECT_T *object
 3784 )
 3785 {
 3786    SCIC_SDS_PHY_T *this_phy;
 3787    this_phy = (SCIC_SDS_PHY_T *)object;
 3788 
 3789    scic_sds_phy_set_starting_substate_handlers(
 3790       this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN
 3791       );
 3792 
 3793    scic_cb_timer_start(
 3794       scic_sds_phy_get_controller(this_phy),
 3795       this_phy->sata_timeout_timer,
 3796       SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT
 3797    );
 3798 }
 3799 
 3800 /**
 3801  * This method will perform the actions required by the SCIC_SDS_PHY on
 3802  * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
 3803  *    - stop the timer that was started on entry to await sata phy
 3804  *      event notification
 3805  *
 3806  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3807  *       SCIC_SDS_PHY object.
 3808  *
 3809  * @return none
 3810  */
 3811 static
 3812 void scic_sds_phy_starting_await_sata_phy_substate_exit(
 3813    SCI_BASE_OBJECT_T *object
 3814 )
 3815 {
 3816    SCIC_SDS_PHY_T *this_phy;
 3817    this_phy = (SCIC_SDS_PHY_T *)object;
 3818 
 3819    scic_cb_timer_stop(
 3820       scic_sds_phy_get_controller(this_phy),
 3821       this_phy->sata_timeout_timer
 3822    );
 3823 }
 3824 
 3825 /**
 3826  * This method will perform the actions required by the SCIC_SDS_PHY on
 3827  * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
 3828  *    - Set the SCIC_SDS_PHY object state handlers for this state.
 3829  *
 3830  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3831  *       SCIC_SDS_PHY object.
 3832  *
 3833  * @return none
 3834  */
 3835 static
 3836 void scic_sds_phy_starting_await_sata_speed_substate_enter(
 3837    SCI_BASE_OBJECT_T *object
 3838 )
 3839 {
 3840    SCIC_SDS_PHY_T *this_phy;
 3841    this_phy = (SCIC_SDS_PHY_T *)object;
 3842 
 3843    scic_sds_phy_set_starting_substate_handlers(
 3844       this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
 3845       );
 3846 
 3847    scic_cb_timer_start(
 3848       scic_sds_phy_get_controller(this_phy),
 3849       this_phy->sata_timeout_timer,
 3850       SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT
 3851    );
 3852 }
 3853 
 3854 /**
 3855  * This method will perform the actions required by the SCIC_SDS_PHY on
 3856  * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
 3857  *    - stop the timer that was started on entry to await sata phy
 3858  *      event notification
 3859  *
 3860  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3861  *       SCIC_SDS_PHY object.
 3862  *
 3863  * @return none
 3864  */
 3865 static
 3866 void scic_sds_phy_starting_await_sata_speed_substate_exit(
 3867    SCI_BASE_OBJECT_T *object
 3868 )
 3869 {
 3870    SCIC_SDS_PHY_T *this_phy;
 3871    this_phy = (SCIC_SDS_PHY_T *)object;
 3872 
 3873    scic_cb_timer_stop(
 3874       scic_sds_phy_get_controller(this_phy),
 3875       this_phy->sata_timeout_timer
 3876    );
 3877 }
 3878 
 3879 /**
 3880  * This method will perform the actions required by the SCIC_SDS_PHY on
 3881  * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
 3882  *    - Set the SCIC_SDS_PHY object state handlers for this state.
 3883  *    - Start the SIGNATURE FIS timeout timer
 3884  *
 3885  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3886  *       SCIC_SDS_PHY object.
 3887  *
 3888  * @return none
 3889  */
 3890 static
 3891 void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(
 3892    SCI_BASE_OBJECT_T *object
 3893 )
 3894 {
 3895    BOOL             continue_to_ready_state;
 3896    SCIC_SDS_PHY_T * this_phy;
 3897 
 3898    this_phy = (SCIC_SDS_PHY_T *)object;
 3899 
 3900    scic_sds_phy_set_starting_substate_handlers(
 3901       this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
 3902    );
 3903 
 3904    continue_to_ready_state = scic_sds_port_link_detected(
 3905                                  this_phy->owning_port,
 3906                                  this_phy
 3907                              );
 3908 
 3909    if (continue_to_ready_state)
 3910    {
 3911       // Clear the PE suspend condition so we can actually receive SIG FIS
 3912       // The hardware will not respond to the XRDY until the PE suspend
 3913       // condition is cleared.
 3914       scic_sds_phy_resume(this_phy);
 3915 
 3916       scic_cb_timer_start(
 3917          scic_sds_phy_get_controller(this_phy),
 3918          this_phy->sata_timeout_timer,
 3919          SCIC_SDS_SIGNATURE_FIS_TIMEOUT
 3920       );
 3921    }
 3922    else
 3923    {
 3924       this_phy->is_in_link_training = FALSE;
 3925    }
 3926 }
 3927 
 3928 /**
 3929  * This method will perform the actions required by the SCIC_SDS_PHY on
 3930  * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
 3931  *    - Stop the SIGNATURE FIS timeout timer.
 3932  *
 3933  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3934  *       SCIC_SDS_PHY object.
 3935  *
 3936  * @return none
 3937  */
 3938 static
 3939 void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(
 3940    SCI_BASE_OBJECT_T *object
 3941 )
 3942 {
 3943    SCIC_SDS_PHY_T *this_phy;
 3944    this_phy = (SCIC_SDS_PHY_T *)object;
 3945 
 3946    scic_cb_timer_stop(
 3947       scic_sds_phy_get_controller(this_phy),
 3948       this_phy->sata_timeout_timer
 3949    );
 3950 }
 3951 
 3952 /**
 3953  * This method will perform the actions required by the SCIC_SDS_PHY on
 3954  * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL.
 3955  *    - Set the SCIC_SDS_PHY object state handlers for this state.
 3956  *    - Change base state machine to the ready state.
 3957  *
 3958  * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
 3959  *       SCIC_SDS_PHY object.
 3960  *
 3961  * @return none
 3962  */
 3963 static
 3964 void scic_sds_phy_starting_final_substate_enter(
 3965    SCI_BASE_OBJECT_T *object
 3966 )
 3967 {
 3968    SCIC_SDS_PHY_T *this_phy;
 3969    this_phy = (SCIC_SDS_PHY_T *)object;
 3970 
 3971    scic_sds_phy_set_starting_substate_handlers(
 3972       this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
 3973       );
 3974 
 3975    // State machine has run to completion so exit out and change
 3976    // the base state machine to the ready state
 3977    sci_base_state_machine_change_state(
 3978       scic_sds_phy_get_base_state_machine(this_phy),
 3979       SCI_BASE_PHY_STATE_READY);
 3980 }
 3981 
 3982 // ---------------------------------------------------------------------------
 3983 
 3984 SCI_BASE_STATE_T
 3985    scic_sds_phy_starting_substates[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] =
 3986 {
 3987    {
 3988       SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL,
 3989       scic_sds_phy_starting_initial_substate_enter,
 3990       NULL,
 3991    },
 3992    {
 3993       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN,
 3994       scic_sds_phy_starting_await_ossp_en_substate_enter,
 3995       NULL,
 3996    },
 3997    {
 3998       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN,
 3999       scic_sds_phy_starting_await_sas_speed_en_substate_enter,
 4000       NULL,
 4001    },
 4002    {
 4003       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF,
 4004       scic_sds_phy_starting_await_iaf_uf_substate_enter,
 4005       NULL,
 4006    },
 4007    {
 4008       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER,
 4009       scic_sds_phy_starting_await_sas_power_substate_enter,
 4010       scic_sds_phy_starting_await_sas_power_substate_exit,
 4011    },
 4012    {
 4013       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER,
 4014       scic_sds_phy_starting_await_sata_power_substate_enter,
 4015       scic_sds_phy_starting_await_sata_power_substate_exit
 4016    },
 4017    {
 4018       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN,
 4019       scic_sds_phy_starting_await_sata_phy_substate_enter,
 4020       scic_sds_phy_starting_await_sata_phy_substate_exit
 4021    },
 4022    {
 4023       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN,
 4024       scic_sds_phy_starting_await_sata_speed_substate_enter,
 4025       scic_sds_phy_starting_await_sata_speed_substate_exit
 4026    },
 4027    {
 4028       SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF,
 4029       scic_sds_phy_starting_await_sig_fis_uf_substate_enter,
 4030       scic_sds_phy_starting_await_sig_fis_uf_substate_exit
 4031    },
 4032    {
 4033       SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL,
 4034       scic_sds_phy_starting_final_substate_enter,
 4035       NULL,
 4036    }
 4037 };
 4038 

Cache object: 320e7e5ed63aca3c88abaab8aaf91240


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