1230557Sjimharris/*-
2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license.  When using or
3230557Sjimharris * redistributing this file, you may do so under either license.
4230557Sjimharris *
5230557Sjimharris * GPL LICENSE SUMMARY
6230557Sjimharris *
7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8230557Sjimharris *
9230557Sjimharris * This program is free software; you can redistribute it and/or modify
10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as
11230557Sjimharris * published by the Free Software Foundation.
12230557Sjimharris *
13230557Sjimharris * This program is distributed in the hope that it will be useful, but
14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of
15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16230557Sjimharris * General Public License for more details.
17230557Sjimharris *
18230557Sjimharris * You should have received a copy of the GNU General Public License
19230557Sjimharris * along with this program; if not, write to the Free Software
20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21230557Sjimharris * The full GNU General Public License is included in this distribution
22230557Sjimharris * in the file called LICENSE.GPL.
23230557Sjimharris *
24230557Sjimharris * BSD LICENSE
25230557Sjimharris *
26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27230557Sjimharris * All rights reserved.
28230557Sjimharris *
29230557Sjimharris * Redistribution and use in source and binary forms, with or without
30230557Sjimharris * modification, are permitted provided that the following conditions
31230557Sjimharris * are met:
32230557Sjimharris *
33230557Sjimharris *   * Redistributions of source code must retain the above copyright
34230557Sjimharris *     notice, this list of conditions and the following disclaimer.
35230557Sjimharris *   * Redistributions in binary form must reproduce the above copyright
36230557Sjimharris *     notice, this list of conditions and the following disclaimer in
37230557Sjimharris *     the documentation and/or other materials provided with the
38230557Sjimharris *     distribution.
39230557Sjimharris *
40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51230557Sjimharris */
52230557Sjimharris
53230557Sjimharris#include <sys/cdefs.h>
54230557Sjimharris__FBSDID("$FreeBSD$");
55230557Sjimharris
56230557Sjimharris/**
57230557Sjimharris * @file
58230557Sjimharris *
59230557Sjimharris * @brief This file contains the implementation of the SCIC_SDS_PHY public and
60230557Sjimharris *        protected methods.
61230557Sjimharris */
62230557Sjimharris
63230557Sjimharris#include <dev/isci/scil/scic_user_callback.h>
64230557Sjimharris#include <dev/isci/scil/scic_phy.h>
65230557Sjimharris#include <dev/isci/scil/scic_sds_phy.h>
66230557Sjimharris#include <dev/isci/scil/scic_sds_port.h>
67230557Sjimharris#include <dev/isci/scil/scic_sds_controller_registers.h>
68230557Sjimharris#include <dev/isci/scil/scic_sds_phy_registers.h>
69230557Sjimharris#include <dev/isci/scil/scic_sds_logger.h>
70230557Sjimharris#include <dev/isci/scil/scic_sds_remote_node_context.h>
71230557Sjimharris#include <dev/isci/scil/sci_util.h>
72230557Sjimharris#include <dev/isci/scil/scic_sds_controller.h>
73230557Sjimharris#include <dev/isci/scil/scu_event_codes.h>
74230557Sjimharris#include <dev/isci/scil/sci_base_state.h>
75230557Sjimharris#include <dev/isci/scil/intel_ata.h>
76230557Sjimharris#include <dev/isci/scil/intel_sata.h>
77230557Sjimharris#include <dev/isci/scil/sci_base_state_machine.h>
78230557Sjimharris#include <dev/isci/scil/scic_sds_port_registers.h>
79230557Sjimharris
80230557Sjimharris#define SCIC_SDS_PHY_MIN_TIMER_COUNT  (SCI_MAX_PHYS)
81230557Sjimharris#define SCIC_SDS_PHY_MAX_TIMER_COUNT  (SCI_MAX_PHYS)
82230557Sjimharris
83230557Sjimharris// Maximum arbitration wait time in micro-seconds
84230557Sjimharris#define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME  (700)
85230557Sjimharris
86230557Sjimharris#define AFE_REGISTER_WRITE_DELAY 10
87230557Sjimharris
88230557Sjimharris//*****************************************************************************
89230557Sjimharris//* SCIC SDS PHY Internal Methods
90230557Sjimharris//*****************************************************************************
91230557Sjimharris
92230557Sjimharris/**
93230557Sjimharris * @brief This method will initialize the phy transport layer registers
94230557Sjimharris *
95230557Sjimharris * @param[in] this_phy
96230557Sjimharris * @param[in] transport_layer_registers
97230557Sjimharris *
98230557Sjimharris * @return SCI_STATUS
99230557Sjimharris */
100230557Sjimharrisstatic
101230557SjimharrisSCI_STATUS scic_sds_phy_transport_layer_initialization(
102230557Sjimharris   SCIC_SDS_PHY_T                  *this_phy,
103230557Sjimharris   SCU_TRANSPORT_LAYER_REGISTERS_T *transport_layer_registers
104230557Sjimharris)
105230557Sjimharris{
106230557Sjimharris   U32 tl_control;
107230557Sjimharris
108230557Sjimharris   SCIC_LOG_TRACE((
109230557Sjimharris      sci_base_object_get_logger(this_phy),
110230557Sjimharris      SCIC_LOG_OBJECT_PHY,
111230557Sjimharris      "scic_sds_phy_link_layer_initialization(this_phy:0x%x, link_layer_registers:0x%x)\n",
112230557Sjimharris      this_phy, transport_layer_registers
113230557Sjimharris   ));
114230557Sjimharris
115230557Sjimharris   this_phy->transport_layer_registers = transport_layer_registers;
116230557Sjimharris
117230557Sjimharris   SCU_STPTLDARNI_WRITE(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);
118230557Sjimharris
119230557Sjimharris   // Hardware team recommends that we enable the STP prefetch for all transports
120230557Sjimharris   tl_control = SCU_TLCR_READ(this_phy);
121230557Sjimharris   tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH);
122230557Sjimharris   SCU_TLCR_WRITE(this_phy, tl_control);
123230557Sjimharris
124230557Sjimharris   return SCI_SUCCESS;
125230557Sjimharris}
126230557Sjimharris
127230557Sjimharris/**
128230557Sjimharris * @brief This method will initialize the phy link layer registers
129230557Sjimharris *
130230557Sjimharris * @param[in] this_phy
131230557Sjimharris * @param[in] link_layer_registers
132230557Sjimharris *
133230557Sjimharris * @return SCI_STATUS
134230557Sjimharris */
135230557Sjimharrisstatic
136230557SjimharrisSCI_STATUS scic_sds_phy_link_layer_initialization(
137230557Sjimharris   SCIC_SDS_PHY_T             *this_phy,
138230557Sjimharris   SCU_LINK_LAYER_REGISTERS_T *link_layer_registers
139230557Sjimharris)
140230557Sjimharris{
141230557Sjimharris   U32                phy_configuration;
142230557Sjimharris   SAS_CAPABILITIES_T phy_capabilities;
143230557Sjimharris   U32                parity_check = 0;
144230557Sjimharris   U32                parity_count = 0;
145230557Sjimharris   U32                link_layer_control;
146230557Sjimharris   U32                phy_timer_timeout_values;
147230557Sjimharris   U32                clksm_value = 0;
148230557Sjimharris
149230557Sjimharris   SCIC_LOG_TRACE((
150230557Sjimharris      sci_base_object_get_logger(this_phy),
151230557Sjimharris      SCIC_LOG_OBJECT_PHY,
152230557Sjimharris      "scic_sds_phy_link_layer_initialization(this_phy:0x%x, link_layer_registers:0x%x)\n",
153230557Sjimharris      this_phy, link_layer_registers
154230557Sjimharris   ));
155230557Sjimharris
156230557Sjimharris   this_phy->link_layer_registers = link_layer_registers;
157230557Sjimharris
158230557Sjimharris   // Set our IDENTIFY frame data
159230557Sjimharris   #define SCI_END_DEVICE 0x01
160230557Sjimharris
161230557Sjimharris   SCU_SAS_TIID_WRITE(
162230557Sjimharris      this_phy,
163230557Sjimharris      (   SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR)
164230557Sjimharris        | SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR)
165230557Sjimharris        | SCU_SAS_TIID_GEN_BIT(STP_INITIATOR)
166230557Sjimharris        | SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST)
167230557Sjimharris        | SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE) )
168230557Sjimharris      );
169230557Sjimharris
170230557Sjimharris   // Write the device SAS Address
171230557Sjimharris   SCU_SAS_TIDNH_WRITE(this_phy, 0xFEDCBA98);
172230557Sjimharris   SCU_SAS_TIDNL_WRITE(this_phy, this_phy->phy_index);
173230557Sjimharris
174230557Sjimharris   // Write the source SAS Address
175230557Sjimharris   SCU_SAS_TISSAH_WRITE(
176230557Sjimharris      this_phy,
177230557Sjimharris      this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[
178230557Sjimharris          this_phy->phy_index].sas_address.sci_format.high
179230557Sjimharris   );
180230557Sjimharris   SCU_SAS_TISSAL_WRITE(
181230557Sjimharris      this_phy,
182230557Sjimharris      this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[
183230557Sjimharris          this_phy->phy_index].sas_address.sci_format.low
184230557Sjimharris   );
185230557Sjimharris
186230557Sjimharris   // Clear and Set the PHY Identifier
187230557Sjimharris   SCU_SAS_TIPID_WRITE(this_phy, 0x00000000);
188230557Sjimharris   SCU_SAS_TIPID_WRITE(this_phy, SCU_SAS_TIPID_GEN_VALUE(ID, this_phy->phy_index));
189230557Sjimharris
190230557Sjimharris   // Change the initial state of the phy configuration register
191230557Sjimharris   phy_configuration = SCU_SAS_PCFG_READ(this_phy);
192230557Sjimharris
193230557Sjimharris   // Hold OOB state machine in reset
194230557Sjimharris   phy_configuration |=  SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
195230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, phy_configuration);
196230557Sjimharris
197230557Sjimharris   // Configure the SNW capabilities
198230557Sjimharris   phy_capabilities.u.all = 0;
199230557Sjimharris   phy_capabilities.u.bits.start                      = 1;
200230557Sjimharris   phy_capabilities.u.bits.gen3_without_ssc_supported = 1;
201230557Sjimharris   phy_capabilities.u.bits.gen2_without_ssc_supported = 1;
202230557Sjimharris   phy_capabilities.u.bits.gen1_without_ssc_supported = 1;
203230557Sjimharris
204230557Sjimharris   /*
205230557Sjimharris    * Set up SSC settings according to version of OEM Parameters.
206230557Sjimharris    */
207230557Sjimharris   {
208230557Sjimharris       U8 header_version, enable_sata, enable_sas,
209230557Sjimharris          sata_spread, sas_type, sas_spread;
210230557Sjimharris       OEM_SSC_PARAMETERS_T ssc;
211230557Sjimharris
212230557Sjimharris       header_version = this_phy->owning_port->owning_controller->
213230557Sjimharris                        oem_parameters_version;
214230557Sjimharris
215230557Sjimharris       ssc.bf.ssc_sata_tx_spread_level =
216230557Sjimharris          this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sata_tx_spread_level;
217230557Sjimharris       ssc.bf.ssc_sas_tx_spread_level =
218230557Sjimharris          this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sas_tx_spread_level;
219230557Sjimharris       ssc.bf.ssc_sas_tx_type =
220230557Sjimharris          this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sas_tx_type;
221230557Sjimharris       enable_sata = enable_sas = sata_spread = sas_type = sas_spread = 0;
222230557Sjimharris
223230557Sjimharris       if (header_version == SCI_OEM_PARAM_VER_1_0)
224230557Sjimharris       {
225230557Sjimharris           /*
226230557Sjimharris            * Version 1.0 is merely turning SSC on to default values.;
227230557Sjimharris            */
228230557Sjimharris           if (ssc.do_enable_ssc != 0)
229230557Sjimharris           {
230230557Sjimharris               enable_sas = enable_sata = TRUE;
231230557Sjimharris               sas_type = 0x0;      // Downspreading
232230557Sjimharris               sata_spread = 0x2;   // +0 to -1419 PPM
233230557Sjimharris               sas_spread = 0x2;    // +0 to -1419 PPM
234230557Sjimharris           }
235230557Sjimharris       }
236230557Sjimharris       else // header_version >= SCI_OEM_PARAM_VER_1_1
237230557Sjimharris       {
238230557Sjimharris          /*
239230557Sjimharris           * Version 1.1 can turn on SAS and SATA independently and
240230557Sjimharris           * specify spread levels. Also can specify spread type for SAS.
241230557Sjimharris           */
242230557Sjimharris          if ((sata_spread = ssc.bf.ssc_sata_tx_spread_level) != 0)
243230557Sjimharris             enable_sata = TRUE;  // Downspreading only
244230557Sjimharris          if ((sas_spread = ssc.bf.ssc_sas_tx_spread_level) != 0)
245230557Sjimharris          {
246230557Sjimharris             enable_sas = TRUE;
247230557Sjimharris             sas_type = ssc.bf.ssc_sas_tx_type;
248230557Sjimharris          }
249230557Sjimharris       }
250230557Sjimharris
251230557Sjimharris       if (enable_sas == TRUE)
252230557Sjimharris       {
253230557Sjimharris           U32 reg_val = scu_afe_register_read(
254230557Sjimharris                             this_phy->owning_port->owning_controller,
255230557Sjimharris                             scu_afe_xcvr[this_phy->phy_index].
256230557Sjimharris                             afe_xcvr_control0);
257230557Sjimharris           reg_val |= (0x00100000 | (((U32)sas_type) << 19));
258230557Sjimharris           scu_afe_register_write(
259230557Sjimharris               this_phy->owning_port->owning_controller,
260230557Sjimharris               scu_afe_xcvr[this_phy->phy_index].afe_xcvr_control0,
261230557Sjimharris               reg_val);
262230557Sjimharris
263230557Sjimharris           reg_val = scu_afe_register_read(
264230557Sjimharris                             this_phy->owning_port->owning_controller,
265230557Sjimharris                             scu_afe_xcvr[this_phy->phy_index].
266230557Sjimharris                             afe_tx_ssc_control);
267230557Sjimharris           reg_val |= (((U32)(sas_spread)) << 8);
268230557Sjimharris           scu_afe_register_write(
269230557Sjimharris               this_phy->owning_port->owning_controller,
270230557Sjimharris               scu_afe_xcvr[this_phy->phy_index].afe_tx_ssc_control,
271230557Sjimharris               reg_val);
272230557Sjimharris      phy_capabilities.u.bits.gen3_with_ssc_supported = 1;
273230557Sjimharris      phy_capabilities.u.bits.gen2_with_ssc_supported = 1;
274230557Sjimharris      phy_capabilities.u.bits.gen1_with_ssc_supported = 1;
275230557Sjimharris   }
276230557Sjimharris
277230557Sjimharris       if (enable_sata == TRUE)
278230557Sjimharris       {
279230557Sjimharris           U32 reg_val = scu_afe_register_read(
280230557Sjimharris                         this_phy->owning_port->owning_controller,
281230557Sjimharris                         scu_afe_xcvr[this_phy->phy_index].
282230557Sjimharris                         afe_tx_ssc_control);
283230557Sjimharris           reg_val |= (U32)sata_spread;
284230557Sjimharris           scu_afe_register_write(
285230557Sjimharris               this_phy->owning_port->owning_controller,
286230557Sjimharris               scu_afe_xcvr[this_phy->phy_index].afe_tx_ssc_control,
287230557Sjimharris               reg_val);
288230557Sjimharris
289230557Sjimharris           reg_val = scu_link_layer_register_read(
290230557Sjimharris                         this_phy,
291230557Sjimharris                         stp_control);
292230557Sjimharris           reg_val |= (U32)(1 << 12);
293230557Sjimharris           scu_link_layer_register_write(
294230557Sjimharris               this_phy,
295230557Sjimharris               stp_control,
296230557Sjimharris               reg_val);
297230557Sjimharris       }
298230557Sjimharris   }
299230557Sjimharris
300230557Sjimharris   // The SAS specification indicates that the phy_capabilities that
301230557Sjimharris   // are transmitted shall have an even parity.  Calculate the parity.
302230557Sjimharris   parity_check = phy_capabilities.u.all;
303230557Sjimharris   while (parity_check != 0)
304230557Sjimharris   {
305230557Sjimharris      if (parity_check & 0x1)
306230557Sjimharris         parity_count++;
307230557Sjimharris      parity_check >>= 1;
308230557Sjimharris   }
309230557Sjimharris
310230557Sjimharris   // If parity indicates there are an odd number of bits set, then
311230557Sjimharris   // set the parity bit to 1 in the phy capabilities.
312230557Sjimharris   if ((parity_count % 2) != 0)
313230557Sjimharris      phy_capabilities.u.bits.parity = 1;
314230557Sjimharris
315230557Sjimharris   SCU_SAS_PHYCAP_WRITE(this_phy, phy_capabilities.u.all);
316230557Sjimharris
317230557Sjimharris   // Set the enable spinup period but disable the ability to send notify enable spinup
318230557Sjimharris   SCU_SAS_ENSPINUP_WRITE(
319230557Sjimharris     this_phy,
320230557Sjimharris     SCU_ENSPINUP_GEN_VAL(
321230557Sjimharris        COUNT,
322230557Sjimharris        this_phy->owning_port->owning_controller->user_parameters.sds1.
323230557Sjimharris           phys[this_phy->phy_index].notify_enable_spin_up_insertion_frequency
324230557Sjimharris     )
325230557Sjimharris   );
326230557Sjimharris
327230557Sjimharris   // Write the ALIGN Insertion Ferequency for connected phy and inpendent of connected state
328230557Sjimharris   clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL (
329230557Sjimharris                     CONNECTED,
330230557Sjimharris                     this_phy->owning_port->owning_controller->user_parameters.sds1.
331230557Sjimharris                        phys[this_phy->phy_index].in_connection_align_insertion_frequency
332230557Sjimharris                 );
333230557Sjimharris
334230557Sjimharris   clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL (
335230557Sjimharris                     GENERAL,
336230557Sjimharris                     this_phy->owning_port->owning_controller->user_parameters.sds1.
337230557Sjimharris                        phys[this_phy->phy_index].align_insertion_frequency
338230557Sjimharris                  );
339230557Sjimharris
340230557Sjimharris   SCU_SAS_CLKSM_WRITE ( this_phy, clksm_value);
341230557Sjimharris
342230557Sjimharris
343230557Sjimharris#if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD)
344230557Sjimharris   /// @todo Provide a way to write this register correctly
345230557Sjimharris   scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421);
346230557Sjimharris#elif defined(PBG_BUILD)
347230557Sjimharris   if (
348230557Sjimharris         (this_phy->owning_port->owning_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
349230557Sjimharris      || (this_phy->owning_port->owning_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
350230557Sjimharris      )
351230557Sjimharris   {
352230557Sjimharris      scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x04210400);
353230557Sjimharris      scu_link_layer_register_write(this_phy, sas_primitive_timeout, 0x20A7C05);
354230557Sjimharris   }
355230557Sjimharris   else
356230557Sjimharris   {
357230557Sjimharris      scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421);
358230557Sjimharris   }
359230557Sjimharris#else
360230557Sjimharris   /// @todo Provide a way to write this register correctly
361230557Sjimharris   scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x0e739ce7);
362230557Sjimharris#endif
363230557Sjimharris
364230557Sjimharris   link_layer_control = SCU_SAS_LLCTL_GEN_VAL(
365230557Sjimharris                           NO_OUTBOUND_TASK_TIMEOUT,
366230557Sjimharris                           (U8) this_phy->owning_port->owning_controller->
367230557Sjimharris                           user_parameters.sds1.no_outbound_task_timeout
368230557Sjimharris                        );
369230557Sjimharris
370230557Sjimharris#if PHY_MAX_LINK_SPEED_GENERATION == SCIC_SDS_PARM_GEN1_SPEED
371230557Sjimharris#define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1
372230557Sjimharris#elif PHY_MAX_LINK_SPEED_GENERATION == SCIC_SDS_PARM_GEN2_SPEED
373230557Sjimharris#define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2
374230557Sjimharris#else
375230557Sjimharris#define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3
376230557Sjimharris#endif // PHY_MAX_LINK_SPEED_GENERATION
377230557Sjimharris
378230557Sjimharris   if (this_phy->owning_port->owning_controller->user_parameters.sds1.
379230557Sjimharris       phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED)
380230557Sjimharris   {
381230557Sjimharris      link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
382230557Sjimharris                               MAX_LINK_RATE, COMPILED_MAX_LINK_RATE
383230557Sjimharris                            );
384230557Sjimharris   }
385230557Sjimharris   else if (this_phy->owning_port->owning_controller->user_parameters.sds1.
386230557Sjimharris       phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED)
387230557Sjimharris   {
388230557Sjimharris      link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
389230557Sjimharris                               MAX_LINK_RATE,
390230557Sjimharris                               MIN(
391230557Sjimharris                                  SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2,
392230557Sjimharris                                  COMPILED_MAX_LINK_RATE)
393230557Sjimharris                            );
394230557Sjimharris   }
395230557Sjimharris   else
396230557Sjimharris   {
397230557Sjimharris      link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
398230557Sjimharris                               MAX_LINK_RATE,
399230557Sjimharris                               MIN(
400230557Sjimharris                                  SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1,
401230557Sjimharris                                  COMPILED_MAX_LINK_RATE)
402230557Sjimharris                            );
403230557Sjimharris   }
404230557Sjimharris
405230557Sjimharris   scu_link_layer_register_write(
406230557Sjimharris      this_phy, link_layer_control, link_layer_control
407230557Sjimharris   );
408230557Sjimharris
409230557Sjimharris   phy_timer_timeout_values = scu_link_layer_register_read(
410230557Sjimharris                                 this_phy,
411230557Sjimharris                                 phy_timer_timeout_values
412230557Sjimharris                              );
413230557Sjimharris
414230557Sjimharris   // Clear the default 0x36 (54us) RATE_CHANGE timeout value.
415230557Sjimharris   phy_timer_timeout_values &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF);
416230557Sjimharris
417230557Sjimharris   // Set RATE_CHANGE timeout value to 0x3B (59us).  This ensures SCU can
418230557Sjimharris   //  lock with 3Gb drive when SCU max rate is set to 1.5Gb.
419230557Sjimharris   phy_timer_timeout_values |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B);
420230557Sjimharris
421230557Sjimharris   scu_link_layer_register_write(
422230557Sjimharris      this_phy, phy_timer_timeout_values, phy_timer_timeout_values
423230557Sjimharris   );
424230557Sjimharris
425230557Sjimharris   // Program the max ARB time for the PHY to 700us so we inter-operate with
426230557Sjimharris   // the PMC expander which shuts down PHYs if the expander PHY generates too
427230557Sjimharris   // many breaks.  This time value will guarantee that the initiator PHY will
428230557Sjimharris   // generate the break.
429230557Sjimharris#if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD)
430230557Sjimharris   scu_link_layer_register_write(
431230557Sjimharris      this_phy,
432230557Sjimharris      maximum_arbitration_wait_timer_timeout,
433230557Sjimharris      SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME
434230557Sjimharris   );
435230557Sjimharris#endif // defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD)
436230557Sjimharris
437230557Sjimharris   // Disable the link layer hang detection timer
438230557Sjimharris   scu_link_layer_register_write(
439230557Sjimharris      this_phy, link_layer_hang_detection_timeout, 0x00000000
440230557Sjimharris   );
441230557Sjimharris
442230557Sjimharris   // We can exit the initial state to the stopped state
443230557Sjimharris   sci_base_state_machine_change_state(
444230557Sjimharris      scic_sds_phy_get_base_state_machine(this_phy),
445230557Sjimharris      SCI_BASE_PHY_STATE_STOPPED
446230557Sjimharris   );
447230557Sjimharris
448230557Sjimharris   return SCI_SUCCESS;
449230557Sjimharris}
450230557Sjimharris
451230557Sjimharris/**
452230557Sjimharris * This function will handle the sata SIGNATURE FIS timeout condition.  It
453230557Sjimharris * will restart the starting substate machine since we dont know what has
454230557Sjimharris * actually happening.
455230557Sjimharris *
456230557Sjimharris * @param[in] cookie This object is cast to the SCIC_SDS_PHY_T object.
457230557Sjimharris *
458230557Sjimharris * @return none
459230557Sjimharris */
460230557Sjimharrisvoid scic_sds_phy_sata_timeout( SCI_OBJECT_HANDLE_T cookie)
461230557Sjimharris{
462230557Sjimharris   SCIC_SDS_PHY_T * this_phy = (SCIC_SDS_PHY_T *)cookie;
463230557Sjimharris
464230557Sjimharris   SCIC_LOG_INFO((
465230557Sjimharris      sci_base_object_get_logger(this_phy),
466230557Sjimharris      SCIC_LOG_OBJECT_PHY,
467230557Sjimharris      "SCIC SDS Phy 0x%x did not receive signature fis before timeout.\n",
468230557Sjimharris      this_phy
469230557Sjimharris   ));
470230557Sjimharris
471230557Sjimharris   sci_base_state_machine_stop(
472230557Sjimharris      scic_sds_phy_get_starting_substate_machine(this_phy));
473230557Sjimharris
474230557Sjimharris   sci_base_state_machine_change_state(
475230557Sjimharris      scic_sds_phy_get_base_state_machine(this_phy),
476230557Sjimharris      SCI_BASE_PHY_STATE_STARTING
477230557Sjimharris   );
478230557Sjimharris}
479230557Sjimharris
480230557Sjimharris//*****************************************************************************
481230557Sjimharris//* SCIC SDS PHY External Methods
482230557Sjimharris//*****************************************************************************
483230557Sjimharris
484230557Sjimharris/**
485230557Sjimharris * @brief This method returns the object size for a phy object.
486230557Sjimharris *
487230557Sjimharris * @return U32
488230557Sjimharris */
489230557SjimharrisU32 scic_sds_phy_get_object_size(void)
490230557Sjimharris{
491230557Sjimharris   return sizeof(SCIC_SDS_PHY_T);
492230557Sjimharris}
493230557Sjimharris
494230557Sjimharris/**
495230557Sjimharris * @brief This method returns the minimum number of timers required for a
496230557Sjimharris *        phy object.
497230557Sjimharris *
498230557Sjimharris * @return U32
499230557Sjimharris */
500230557SjimharrisU32 scic_sds_phy_get_min_timer_count(void)
501230557Sjimharris{
502230557Sjimharris   return SCIC_SDS_PHY_MIN_TIMER_COUNT;
503230557Sjimharris}
504230557Sjimharris
505230557Sjimharris/**
506230557Sjimharris * @brief This method returns the maximum number of timers required for a
507230557Sjimharris *        phy object.
508230557Sjimharris *
509230557Sjimharris * @return U32
510230557Sjimharris */
511230557SjimharrisU32 scic_sds_phy_get_max_timer_count(void)
512230557Sjimharris{
513230557Sjimharris   return SCIC_SDS_PHY_MAX_TIMER_COUNT;
514230557Sjimharris}
515230557Sjimharris
516230557Sjimharris#ifdef SCI_LOGGING
517230557Sjimharrisstatic
518230557Sjimharrisvoid scic_sds_phy_initialize_state_logging(
519230557Sjimharris   SCIC_SDS_PHY_T *this_phy
520230557Sjimharris)
521230557Sjimharris{
522230557Sjimharris   sci_base_state_machine_logger_initialize(
523230557Sjimharris      &this_phy->parent.state_machine_logger,
524230557Sjimharris      &this_phy->parent.state_machine,
525230557Sjimharris      &this_phy->parent.parent,
526230557Sjimharris      scic_cb_logger_log_states,
527230557Sjimharris      "SCIC_SDS_PHY_T", "base state machine",
528230557Sjimharris      SCIC_LOG_OBJECT_PHY
529230557Sjimharris   );
530230557Sjimharris
531230557Sjimharris   sci_base_state_machine_logger_initialize(
532230557Sjimharris      &this_phy->starting_substate_machine_logger,
533230557Sjimharris      &this_phy->starting_substate_machine,
534230557Sjimharris      &this_phy->parent.parent,
535230557Sjimharris      scic_cb_logger_log_states,
536230557Sjimharris      "SCIC_SDS_PHY_T", "starting substate machine",
537230557Sjimharris      SCIC_LOG_OBJECT_PHY
538230557Sjimharris   );
539230557Sjimharris}
540230557Sjimharris#endif // SCI_LOGGING
541230557Sjimharris
542230557Sjimharris#ifdef SCIC_DEBUG_ENABLED
543230557Sjimharris/**
544230557Sjimharris * Debug code to record the state transitions in the phy
545230557Sjimharris *
546230557Sjimharris * @param our_observer
547230557Sjimharris * @param the_state_machine
548230557Sjimharris */
549230557Sjimharrisvoid scic_sds_phy_observe_state_change(
550230557Sjimharris   SCI_BASE_OBSERVER_T * our_observer,
551230557Sjimharris   SCI_BASE_SUBJECT_T  * the_subject
552230557Sjimharris)
553230557Sjimharris{
554230557Sjimharris   SCIC_SDS_PHY_T           *this_phy;
555230557Sjimharris   SCI_BASE_STATE_MACHINE_T *the_state_machine;
556230557Sjimharris
557230557Sjimharris   U8  transition_requestor;
558230557Sjimharris   U32 base_state_id;
559230557Sjimharris   U32 starting_substate_id;
560230557Sjimharris
561230557Sjimharris   the_state_machine = (SCI_BASE_STATE_MACHINE_T *)the_subject;
562230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)the_state_machine->state_machine_owner;
563230557Sjimharris
564230557Sjimharris   if (the_state_machine == &this_phy->parent.state_machine)
565230557Sjimharris   {
566230557Sjimharris      transition_requestor = 0x01;
567230557Sjimharris   }
568230557Sjimharris   else if (the_state_machine == &this_phy->starting_substate_machine)
569230557Sjimharris   {
570230557Sjimharris      transition_requestor = 0x02;
571230557Sjimharris   }
572230557Sjimharris   else
573230557Sjimharris   {
574230557Sjimharris      transition_requestor = 0xFF;
575230557Sjimharris   }
576230557Sjimharris
577230557Sjimharris   base_state_id =
578230557Sjimharris      sci_base_state_machine_get_state(&this_phy->parent.state_machine);
579230557Sjimharris   starting_substate_id =
580230557Sjimharris      sci_base_state_machine_get_state(&this_phy->starting_substate_machine);
581230557Sjimharris
582230557Sjimharris   this_phy->state_record.state_transition_table[
583230557Sjimharris      this_phy->state_record.index++] = ( (transition_requestor << 24)
584230557Sjimharris                                        | ((U8)base_state_id << 8)
585230557Sjimharris                                        | ((U8)starting_substate_id));
586230557Sjimharris
587230557Sjimharris   this_phy->state_record.index =
588230557Sjimharris      this_phy->state_record.index & (MAX_STATE_TRANSITION_RECORD - 1);
589230557Sjimharris
590230557Sjimharris}
591230557Sjimharris#endif // SCIC_DEBUG_ENABLED
592230557Sjimharris
593230557Sjimharris#ifdef SCIC_DEBUG_ENABLED
594230557Sjimharris/**
595230557Sjimharris * This method initializes the state record debug information for the phy
596230557Sjimharris * object.
597230557Sjimharris *
598230557Sjimharris * @pre The state machines for the phy object must be constructed before this
599230557Sjimharris *      function is called.
600230557Sjimharris *
601230557Sjimharris * @param this_phy The phy which is being initialized.
602230557Sjimharris */
603230557Sjimharrisvoid scic_sds_phy_initialize_state_recording(
604230557Sjimharris   SCIC_SDS_PHY_T *this_phy
605230557Sjimharris)
606230557Sjimharris{
607230557Sjimharris   this_phy->state_record.index = 0;
608230557Sjimharris
609230557Sjimharris   sci_base_observer_initialize(
610230557Sjimharris      &this_phy->state_record.base_state_observer,
611230557Sjimharris      scic_sds_phy_observe_state_change,
612230557Sjimharris      &this_phy->parent.state_machine.parent
613230557Sjimharris   );
614230557Sjimharris
615230557Sjimharris   sci_base_observer_initialize(
616230557Sjimharris      &this_phy->state_record.starting_state_observer,
617230557Sjimharris      scic_sds_phy_observe_state_change,
618230557Sjimharris      &this_phy->starting_substate_machine.parent
619230557Sjimharris   );
620230557Sjimharris}
621230557Sjimharris#endif // SCIC_DEBUG_ENABLED
622230557Sjimharris
623230557Sjimharris/**
624230557Sjimharris * @brief This method will construct the SCIC_SDS_PHY object
625230557Sjimharris *
626230557Sjimharris * @param[in] this_phy
627230557Sjimharris * @param[in] owning_port
628230557Sjimharris * @param[in] phy_index
629230557Sjimharris *
630230557Sjimharris * @return none
631230557Sjimharris */
632230557Sjimharrisvoid scic_sds_phy_construct(
633230557Sjimharris   SCIC_SDS_PHY_T  *this_phy,
634230557Sjimharris   SCIC_SDS_PORT_T *owning_port,
635230557Sjimharris   U8              phy_index
636230557Sjimharris)
637230557Sjimharris{
638230557Sjimharris   // Call the base constructor first
639230557Sjimharris   // Copy the logger from the port (this could be the dummy port)
640230557Sjimharris   sci_base_phy_construct(
641230557Sjimharris      &this_phy->parent,
642230557Sjimharris      sci_base_object_get_logger(owning_port),
643230557Sjimharris      scic_sds_phy_state_table
644230557Sjimharris      );
645230557Sjimharris
646230557Sjimharris   // Copy the rest of the input data to our locals
647230557Sjimharris   this_phy->owning_port = owning_port;
648230557Sjimharris   this_phy->phy_index = phy_index;
649230557Sjimharris   this_phy->bcn_received_while_port_unassigned = FALSE;
650230557Sjimharris   this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
651230557Sjimharris   this_phy->link_layer_registers = NULL;
652230557Sjimharris   this_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE;
653230557Sjimharris   this_phy->sata_timeout_timer = NULL;
654230557Sjimharris
655230557Sjimharris   // Clear out the identification buffer data
656230557Sjimharris   memset(&this_phy->phy_type, 0, sizeof(this_phy->phy_type));
657230557Sjimharris
658230557Sjimharris   // Clear out the error counter data
659230557Sjimharris   memset(this_phy->error_counter, 0, sizeof(this_phy->error_counter));
660230557Sjimharris
661240518Seadler   // Initialize the substate machines
662230557Sjimharris   sci_base_state_machine_construct(
663230557Sjimharris      &this_phy->starting_substate_machine,
664230557Sjimharris      &this_phy->parent.parent,
665230557Sjimharris      scic_sds_phy_starting_substates,
666230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL
667230557Sjimharris      );
668230557Sjimharris
669230557Sjimharris   #ifdef SCI_LOGGING
670230557Sjimharris   scic_sds_phy_initialize_state_logging(this_phy);
671230557Sjimharris   #endif // SCI_LOGGING
672230557Sjimharris
673230557Sjimharris   #ifdef SCIC_DEBUG_ENABLED
674230557Sjimharris   scic_sds_phy_initialize_state_recording(this_phy);
675230557Sjimharris   #endif // SCIC_DEBUG_ENABLED
676230557Sjimharris}
677230557Sjimharris
678230557Sjimharris/**
679230557Sjimharris * @brief This method returns the port currently containing this phy.
680230557Sjimharris *        If the phy is currently contained by the dummy port, then
681230557Sjimharris *        the phy is considered to not be part of a port.
682230557Sjimharris *
683230557Sjimharris * @param[in] this_phy This parameter specifies the phy for which to
684230557Sjimharris *            retrieve the containing port.
685230557Sjimharris *
686230557Sjimharris * @return This method returns a handle to a port that contains
687230557Sjimharris *         the supplied phy.
688230557Sjimharris * @retval SCI_INVALID_HANDLE This value is returned if the phy is not
689230557Sjimharris *         part of a real port (i.e. it's contained in the dummy port).
690230557Sjimharris * @retval !SCI_INVALID_HANDLE All other values indicate a handle/pointer
691230557Sjimharris *         to the port containing the phy.
692230557Sjimharris */
693230557SjimharrisSCI_PORT_HANDLE_T scic_sds_phy_get_port(
694230557Sjimharris   SCIC_SDS_PHY_T *this_phy
695230557Sjimharris)
696230557Sjimharris{
697230557Sjimharris   SCIC_LOG_TRACE((
698230557Sjimharris      sci_base_object_get_logger(this_phy),
699230557Sjimharris      SCIC_LOG_OBJECT_PHY,
700230557Sjimharris      "scic_phy_get_port(0x%x) enter\n",
701230557Sjimharris      this_phy
702230557Sjimharris   ));
703230557Sjimharris
704230557Sjimharris   if (scic_sds_port_get_index(this_phy->owning_port) == SCIC_SDS_DUMMY_PORT)
705230557Sjimharris      return SCI_INVALID_HANDLE;
706230557Sjimharris
707230557Sjimharris   return this_phy->owning_port;
708230557Sjimharris}
709230557Sjimharris
710230557Sjimharris/**
711230557Sjimharris * @brief This method will assign a port to the phy object.
712230557Sjimharris *
713230557Sjimharris * @param[in, out] this_phy This parameter specifies the phy for which
714230557Sjimharris *    to assign a port object.
715230557Sjimharris * @param[in] the_port This parameter is the port to assing to the phy.
716230557Sjimharris */
717230557Sjimharrisvoid scic_sds_phy_set_port(
718230557Sjimharris   SCIC_SDS_PHY_T * this_phy,
719230557Sjimharris   SCIC_SDS_PORT_T * the_port
720230557Sjimharris)
721230557Sjimharris{
722230557Sjimharris   this_phy->owning_port = the_port;
723230557Sjimharris
724230557Sjimharris   if (this_phy->bcn_received_while_port_unassigned)
725230557Sjimharris   {
726230557Sjimharris      this_phy->bcn_received_while_port_unassigned = FALSE;
727230557Sjimharris      scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy);
728230557Sjimharris   }
729230557Sjimharris}
730230557Sjimharris
731230557Sjimharris/**
732230557Sjimharris * @brief This method will initialize the constructed phy
733230557Sjimharris *
734230557Sjimharris * @param[in] this_phy
735230557Sjimharris * @param[in] link_layer_registers
736230557Sjimharris *
737230557Sjimharris * @return SCI_STATUS
738230557Sjimharris */
739230557SjimharrisSCI_STATUS scic_sds_phy_initialize(
740230557Sjimharris   SCIC_SDS_PHY_T             *this_phy,
741230557Sjimharris   void                       *transport_layer_registers,
742230557Sjimharris   SCU_LINK_LAYER_REGISTERS_T *link_layer_registers
743230557Sjimharris)
744230557Sjimharris{
745230557Sjimharris   SCIC_LOG_TRACE((
746230557Sjimharris      sci_base_object_get_logger(this_phy),
747230557Sjimharris      SCIC_LOG_OBJECT_PHY,
748230557Sjimharris      "scic_sds_phy_initialize(this_phy:0x%x, link_layer_registers:0x%x)\n",
749230557Sjimharris      this_phy, link_layer_registers
750230557Sjimharris   ));
751230557Sjimharris
752298931Spfg   // Perform the initialization of the TL hardware
753230557Sjimharris   scic_sds_phy_transport_layer_initialization(this_phy, transport_layer_registers);
754230557Sjimharris
755230557Sjimharris   // Perofrm the initialization of the PE hardware
756230557Sjimharris   scic_sds_phy_link_layer_initialization(this_phy, link_layer_registers);
757230557Sjimharris
758230557Sjimharris   // There is nothing that needs to be done in this state just
759230557Sjimharris   // transition to the stopped state.
760230557Sjimharris   sci_base_state_machine_change_state(
761230557Sjimharris      scic_sds_phy_get_base_state_machine(this_phy),
762230557Sjimharris      SCI_BASE_PHY_STATE_STOPPED
763230557Sjimharris   );
764230557Sjimharris
765230557Sjimharris   return SCI_SUCCESS;
766230557Sjimharris}
767230557Sjimharris
768230557Sjimharris/**
769230557Sjimharris * This method assigns the direct attached device ID for this phy.
770230557Sjimharris *
771230557Sjimharris * @param[in] this_phy The phy for which the direct attached device id is to
772230557Sjimharris *       be assigned.
773230557Sjimharris * @param[in] device_id The direct attached device ID to assign to the phy.
774230557Sjimharris *       This will either be the RNi for the device or an invalid RNi if there
775230557Sjimharris *       is no current device assigned to the phy.
776230557Sjimharris */
777230557Sjimharrisvoid scic_sds_phy_setup_transport(
778230557Sjimharris   SCIC_SDS_PHY_T * this_phy,
779230557Sjimharris   U32              device_id
780230557Sjimharris)
781230557Sjimharris{
782230557Sjimharris   U32 tl_control;
783230557Sjimharris
784230557Sjimharris   SCU_STPTLDARNI_WRITE(this_phy, device_id);
785230557Sjimharris
786230557Sjimharris   // The read should guarntee that the first write gets posted
787230557Sjimharris   // before the next write
788230557Sjimharris   tl_control = SCU_TLCR_READ(this_phy);
789230557Sjimharris   tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
790230557Sjimharris   SCU_TLCR_WRITE(this_phy, tl_control);
791230557Sjimharris}
792230557Sjimharris
793230557Sjimharris/**
794230557Sjimharris * This function will perform the register reads/writes to suspend the SCU
795230557Sjimharris * hardware protocol engine.
796230557Sjimharris *
797230557Sjimharris * @param[in,out] this_phy The phy object to be suspended.
798230557Sjimharris *
799230557Sjimharris * @return none
800230557Sjimharris */
801230557Sjimharrisvoid scic_sds_phy_suspend(
802230557Sjimharris   SCIC_SDS_PHY_T * this_phy
803230557Sjimharris)
804230557Sjimharris{
805230557Sjimharris   U32 scu_sas_pcfg_value;
806230557Sjimharris
807230557Sjimharris   scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
808230557Sjimharris   scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
809230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
810230557Sjimharris
811230557Sjimharris   scic_sds_phy_setup_transport(
812230557Sjimharris      this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
813230557Sjimharris   );
814230557Sjimharris}
815230557Sjimharris
816230557Sjimharris/**
817230557Sjimharris * This function will perform the register reads/writes required to resume the
818230557Sjimharris * SCU hardware protocol engine.
819230557Sjimharris *
820230557Sjimharris * @param[in,out] this_phy The phy object to resume.
821230557Sjimharris *
822230557Sjimharris * @return none
823230557Sjimharris */
824230557Sjimharrisvoid scic_sds_phy_resume(
825230557Sjimharris   SCIC_SDS_PHY_T * this_phy
826230557Sjimharris)
827230557Sjimharris{
828230557Sjimharris   U32 scu_sas_pcfg_value;
829230557Sjimharris
830230557Sjimharris   scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
831230557Sjimharris
832230557Sjimharris   scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
833230557Sjimharris
834230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
835230557Sjimharris}
836230557Sjimharris
837230557Sjimharris/**
838230557Sjimharris * @brief This method returns the local sas address assigned to this phy.
839230557Sjimharris *
840230557Sjimharris * @param[in] this_phy This parameter specifies the phy for which
841230557Sjimharris *            to retrieve the local SAS address.
842230557Sjimharris * @param[out] sas_address This parameter specifies the location into
843230557Sjimharris *             which to copy the local SAS address.
844230557Sjimharris *
845230557Sjimharris * @return none
846230557Sjimharris */
847230557Sjimharrisvoid scic_sds_phy_get_sas_address(
848230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
849230557Sjimharris   SCI_SAS_ADDRESS_T *sas_address
850230557Sjimharris)
851230557Sjimharris{
852230557Sjimharris   SCIC_LOG_TRACE((
853230557Sjimharris      sci_base_object_get_logger(this_phy),
854230557Sjimharris      SCIC_LOG_OBJECT_PHY,
855230557Sjimharris      "scic_sds_phy_get_sas_address(this_phy:0x%x, sas_address:0x%x)\n",
856230557Sjimharris      this_phy, sas_address
857230557Sjimharris   ));
858230557Sjimharris
859230557Sjimharris   sas_address->high = SCU_SAS_TISSAH_READ(this_phy);
860230557Sjimharris   sas_address->low  = SCU_SAS_TISSAL_READ(this_phy);
861230557Sjimharris}
862230557Sjimharris
863230557Sjimharris/**
864230557Sjimharris * @brief This method returns the remote end-point (i.e. attached)
865230557Sjimharris *        sas address assigned to this phy.
866230557Sjimharris *
867230557Sjimharris * @param[in] this_phy This parameter specifies the phy for which
868230557Sjimharris *            to retrieve the remote end-point SAS address.
869230557Sjimharris * @param[out] sas_address This parameter specifies the location into
870230557Sjimharris *             which to copy the remote end-point SAS address.
871230557Sjimharris *
872230557Sjimharris * @return none
873230557Sjimharris */
874230557Sjimharrisvoid scic_sds_phy_get_attached_sas_address(
875230557Sjimharris   SCIC_SDS_PHY_T    *this_phy,
876230557Sjimharris   SCI_SAS_ADDRESS_T *sas_address
877230557Sjimharris)
878230557Sjimharris{
879230557Sjimharris   SCIC_LOG_TRACE((
880230557Sjimharris      sci_base_object_get_logger(this_phy),
881230557Sjimharris      SCIC_LOG_OBJECT_PHY,
882230557Sjimharris      "scic_sds_phy_get_attached_sas_address(0x%x, 0x%x) enter\n",
883230557Sjimharris      this_phy, sas_address
884230557Sjimharris   ));
885230557Sjimharris
886230557Sjimharris   sas_address->high
887230557Sjimharris      = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high;
888230557Sjimharris   sas_address->low
889230557Sjimharris      = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low;
890230557Sjimharris}
891230557Sjimharris
892230557Sjimharris/**
893230557Sjimharris * @brief This method returns the supported protocols assigned to
894230557Sjimharris *        this phy
895230557Sjimharris *
896230557Sjimharris * @param[in] this_phy
897230557Sjimharris * @param[out] protocols
898230557Sjimharris */
899230557Sjimharrisvoid scic_sds_phy_get_protocols(
900230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
901230557Sjimharris   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
902230557Sjimharris)
903230557Sjimharris{
904230557Sjimharris   U32 tiid_value = SCU_SAS_TIID_READ(this_phy);
905230557Sjimharris
906230557Sjimharris   //Check each bit of this register. please refer to
907230557Sjimharris   //SAS Transmit Identification Register (SAS_TIID).
908230557Sjimharris   if (tiid_value & 0x2)
909230557Sjimharris      protocols->u.bits.smp_target = 1;
910230557Sjimharris
911230557Sjimharris   if (tiid_value & 0x4)
912230557Sjimharris      protocols->u.bits.stp_target = 1;
913230557Sjimharris
914230557Sjimharris   if (tiid_value & 0x8)
915230557Sjimharris      protocols->u.bits.ssp_target = 1;
916230557Sjimharris
917230557Sjimharris   if (tiid_value & 0x200)
918230557Sjimharris      protocols->u.bits.smp_initiator = 1;
919230557Sjimharris
920230557Sjimharris   if ((tiid_value & 0x400))
921230557Sjimharris      protocols->u.bits.stp_initiator = 1;
922230557Sjimharris
923230557Sjimharris   if (tiid_value & 0x800)
924230557Sjimharris      protocols->u.bits.ssp_initiator = 1;
925230557Sjimharris
926230557Sjimharris   SCIC_LOG_TRACE((
927230557Sjimharris      sci_base_object_get_logger(this_phy),
928230557Sjimharris      SCIC_LOG_OBJECT_PHY,
929230557Sjimharris      "scic_sds_phy_get_protocols(this_phy:0x%x, protocols:0x%x)\n",
930230557Sjimharris      this_phy, protocols->u.all
931230557Sjimharris   ));
932230557Sjimharris}
933230557Sjimharris
934230557Sjimharris/**
935230557Sjimharris * This method returns the supported protocols for the attached phy.  If this
936230557Sjimharris * is a SAS phy the protocols are returned from the identify address frame.
937230557Sjimharris * If this is a SATA phy then protocols are made up and the target phy is an
938230557Sjimharris * STP target phy.
939230557Sjimharris *
940230557Sjimharris * @note The caller will get the entire set of bits for the protocol value.
941230557Sjimharris *
942230557Sjimharris * @param[in] this_phy The parameter is the phy object for which the attached
943230557Sjimharris *       phy protcols are to be returned.
944230557Sjimharris * @param[out] protocols The parameter is the returned protocols for the
945230557Sjimharris *       attached phy.
946230557Sjimharris */
947230557Sjimharrisvoid scic_sds_phy_get_attached_phy_protocols(
948230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
949230557Sjimharris   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
950230557Sjimharris)
951230557Sjimharris{
952230557Sjimharris   SCIC_LOG_TRACE((
953230557Sjimharris      sci_base_object_get_logger(this_phy),
954230557Sjimharris      SCIC_LOG_OBJECT_PHY,
955230557Sjimharris      "scic_sds_phy_get_attached_phy_protocols(this_phy:0x%x, protocols:0x%x[0x%x])\n",
956230557Sjimharris      this_phy, protocols, protocols->u.all
957230557Sjimharris   ));
958230557Sjimharris
959230557Sjimharris   protocols->u.all = 0;
960230557Sjimharris
961230557Sjimharris   if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
962230557Sjimharris   {
963230557Sjimharris      protocols->u.all =
964230557Sjimharris         this_phy->phy_type.sas.identify_address_frame_buffer.protocols.u.all;
965230557Sjimharris   }
966230557Sjimharris   else if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)
967230557Sjimharris   {
968230557Sjimharris      protocols->u.bits.stp_target = 1;
969230557Sjimharris   }
970230557Sjimharris}
971230557Sjimharris
972230557Sjimharris
973230557Sjimharris/**
974230557Sjimharris * @brief This method release resources in for a scic phy.
975230557Sjimharris *
976230557Sjimharris * @param[in] controller This parameter specifies the core controller, one of
977230557Sjimharris *            its phy's resources are to be released.
978249586Sgabor * @param[in] this_phy This parameter specifies the phy whose resource is to
979230557Sjimharris *            be released.
980230557Sjimharris */
981230557Sjimharrisvoid scic_sds_phy_release_resource(
982230557Sjimharris   SCIC_SDS_CONTROLLER_T * controller,
983230557Sjimharris   SCIC_SDS_PHY_T        * this_phy
984230557Sjimharris)
985230557Sjimharris{
986230557Sjimharris   SCIC_LOG_TRACE((
987230557Sjimharris      sci_base_object_get_logger(this_phy),
988230557Sjimharris      SCIC_LOG_OBJECT_PHY,
989230557Sjimharris      "scic_sds_phy_release_resource(0x%x, 0x%x)\n",
990230557Sjimharris      controller, this_phy
991230557Sjimharris   ));
992230557Sjimharris
993230557Sjimharris   //Currently, the only resource to be released is a timer.
994230557Sjimharris   if (this_phy->sata_timeout_timer != NULL)
995230557Sjimharris   {
996230557Sjimharris      scic_cb_timer_destroy(controller, this_phy->sata_timeout_timer);
997230557Sjimharris      this_phy->sata_timeout_timer = NULL;
998230557Sjimharris   }
999230557Sjimharris}
1000230557Sjimharris
1001230557Sjimharris
1002230557Sjimharris//*****************************************************************************
1003230557Sjimharris//* SCIC SDS PHY Handler Redirects
1004230557Sjimharris//*****************************************************************************
1005230557Sjimharris
1006230557Sjimharris/**
1007230557Sjimharris * @brief This method will attempt to reset the phy.  This
1008230557Sjimharris *        request is only valid when the phy is in an ready
1009230557Sjimharris *        state
1010230557Sjimharris *
1011230557Sjimharris * @param[in] this_phy
1012230557Sjimharris *
1013230557Sjimharris * @return SCI_STATUS
1014230557Sjimharris */
1015230557SjimharrisSCI_STATUS scic_sds_phy_reset(
1016230557Sjimharris   SCIC_SDS_PHY_T * this_phy
1017230557Sjimharris)
1018230557Sjimharris{
1019230557Sjimharris   SCIC_LOG_TRACE((
1020230557Sjimharris      sci_base_object_get_logger(this_phy),
1021230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1022230557Sjimharris      "scic_sds_phy_reset(this_phy:0x%08x)\n",
1023230557Sjimharris      this_phy
1024230557Sjimharris   ));
1025230557Sjimharris
1026230557Sjimharris   return this_phy->state_handlers->parent.reset_handler(
1027230557Sjimharris                                             &this_phy->parent
1028230557Sjimharris                                           );
1029230557Sjimharris}
1030230557Sjimharris
1031230557Sjimharris/**
1032298931Spfg * @brief This method will process the event code received.
1033230557Sjimharris *
1034230557Sjimharris * @param[in] this_phy
1035230557Sjimharris * @param[in] event_code
1036230557Sjimharris *
1037230557Sjimharris * @return SCI_STATUS
1038230557Sjimharris */
1039230557SjimharrisSCI_STATUS scic_sds_phy_event_handler(
1040230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
1041230557Sjimharris   U32 event_code
1042230557Sjimharris)
1043230557Sjimharris{
1044230557Sjimharris   SCIC_LOG_TRACE((
1045230557Sjimharris      sci_base_object_get_logger(this_phy),
1046230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1047230557Sjimharris      "scic_sds_phy_event_handler(this_phy:0x%08x, event_code:%x)\n",
1048230557Sjimharris      this_phy, event_code
1049230557Sjimharris   ));
1050230557Sjimharris
1051230557Sjimharris   return this_phy->state_handlers->event_handler(this_phy, event_code);
1052230557Sjimharris}
1053230557Sjimharris
1054230557Sjimharris/**
1055298931Spfg * @brief This method will process the frame index received.
1056230557Sjimharris *
1057230557Sjimharris * @param[in] this_phy
1058230557Sjimharris * @param[in] frame_index
1059230557Sjimharris *
1060230557Sjimharris * @return SCI_STATUS
1061230557Sjimharris */
1062230557SjimharrisSCI_STATUS scic_sds_phy_frame_handler(
1063230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
1064230557Sjimharris   U32 frame_index
1065230557Sjimharris)
1066230557Sjimharris{
1067230557Sjimharris   SCIC_LOG_TRACE((
1068230557Sjimharris      sci_base_object_get_logger(this_phy),
1069230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1070230557Sjimharris      "scic_sds_phy_frame_handler(this_phy:0x%08x, frame_index:%d)\n",
1071230557Sjimharris      this_phy, frame_index
1072230557Sjimharris   ));
1073230557Sjimharris
1074230557Sjimharris   return this_phy->state_handlers->frame_handler(this_phy, frame_index);
1075230557Sjimharris}
1076230557Sjimharris
1077230557Sjimharris/**
1078230557Sjimharris * @brief This method will give the phy permission to consume power
1079230557Sjimharris *
1080230557Sjimharris * @param[in] this_phy
1081230557Sjimharris *
1082230557Sjimharris * @return SCI_STATUS
1083230557Sjimharris */
1084230557SjimharrisSCI_STATUS scic_sds_phy_consume_power_handler(
1085230557Sjimharris   SCIC_SDS_PHY_T *this_phy
1086230557Sjimharris)
1087230557Sjimharris{
1088230557Sjimharris   SCIC_LOG_TRACE((
1089230557Sjimharris      sci_base_object_get_logger(this_phy),
1090230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1091230557Sjimharris      "scic_sds_phy_consume_power_handler(this_phy:0x%08x)\n",
1092230557Sjimharris      this_phy
1093230557Sjimharris   ));
1094230557Sjimharris
1095230557Sjimharris   return this_phy->state_handlers->consume_power_handler(this_phy);
1096230557Sjimharris}
1097230557Sjimharris
1098230557Sjimharris//*****************************************************************************
1099230557Sjimharris//* SCIC PHY Public Methods
1100230557Sjimharris//*****************************************************************************
1101230557Sjimharris
1102230557SjimharrisSCI_STATUS scic_phy_get_properties(
1103230557Sjimharris   SCI_PHY_HANDLE_T        phy,
1104230557Sjimharris   SCIC_PHY_PROPERTIES_T * properties
1105230557Sjimharris)
1106230557Sjimharris{
1107230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1108230557Sjimharris   U8 max_speed_generation;
1109230557Sjimharris
1110230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1111230557Sjimharris
1112230557Sjimharris   SCIC_LOG_TRACE((
1113230557Sjimharris      sci_base_object_get_logger(this_phy),
1114230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1115230557Sjimharris      "scic_phy_get_properties(0x%x, 0x%x) enter\n",
1116230557Sjimharris      this_phy, properties
1117230557Sjimharris   ));
1118230557Sjimharris
1119230557Sjimharris   if (phy == SCI_INVALID_HANDLE)
1120230557Sjimharris   {
1121230557Sjimharris      return SCI_FAILURE_INVALID_PHY;
1122230557Sjimharris   }
1123230557Sjimharris
1124230557Sjimharris   memset(properties, 0, sizeof(SCIC_PHY_PROPERTIES_T));
1125230557Sjimharris
1126230557Sjimharris   //get max link rate of this phy set by user.
1127230557Sjimharris   max_speed_generation =
1128230557Sjimharris      this_phy->owning_port->owning_controller->user_parameters.sds1.
1129230557Sjimharris         phys[this_phy->phy_index].max_speed_generation;
1130230557Sjimharris
1131230557Sjimharris   properties->negotiated_link_rate     = this_phy->max_negotiated_speed;
1132230557Sjimharris
1133230557Sjimharris   if (max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED)
1134230557Sjimharris      properties->max_link_rate            = SCI_SAS_600_GB;
1135230557Sjimharris   else if (max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED)
1136230557Sjimharris      properties->max_link_rate            = SCI_SAS_300_GB;
1137230557Sjimharris   else
1138230557Sjimharris      properties->max_link_rate            = SCI_SAS_150_GB;
1139230557Sjimharris
1140230557Sjimharris   properties->index                    = this_phy->phy_index;
1141230557Sjimharris   properties->owning_port              = scic_sds_phy_get_port(this_phy);
1142230557Sjimharris
1143230557Sjimharris   scic_sds_phy_get_protocols(this_phy, &properties->transmit_iaf.protocols);
1144230557Sjimharris
1145230557Sjimharris   properties->transmit_iaf.sas_address.high =
1146230557Sjimharris      this_phy->owning_port->owning_controller->oem_parameters.sds1.
1147230557Sjimharris         phys[this_phy->phy_index].sas_address.sci_format.high;
1148230557Sjimharris
1149230557Sjimharris   properties->transmit_iaf.sas_address.low =
1150230557Sjimharris      this_phy->owning_port->owning_controller->oem_parameters.sds1.
1151230557Sjimharris         phys[this_phy->phy_index].sas_address.sci_format.low;
1152230557Sjimharris
1153230557Sjimharris   return SCI_SUCCESS;
1154230557Sjimharris}
1155230557Sjimharris
1156230557Sjimharris// ---------------------------------------------------------------------------
1157230557Sjimharris
1158230557SjimharrisSCI_STATUS scic_sas_phy_get_properties(
1159230557Sjimharris   SCI_PHY_HANDLE_T            phy,
1160230557Sjimharris   SCIC_SAS_PHY_PROPERTIES_T * properties
1161230557Sjimharris)
1162230557Sjimharris{
1163230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1164230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1165230557Sjimharris
1166230557Sjimharris   SCIC_LOG_TRACE((
1167230557Sjimharris      sci_base_object_get_logger(this_phy),
1168230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1169230557Sjimharris      "scic_sas_phy_get_properties(0x%x, 0x%x) enter\n",
1170230557Sjimharris      this_phy, properties
1171230557Sjimharris   ));
1172230557Sjimharris
1173230557Sjimharris   if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
1174230557Sjimharris   {
1175230557Sjimharris      memcpy(
1176230557Sjimharris         &properties->received_iaf,
1177230557Sjimharris         &this_phy->phy_type.sas.identify_address_frame_buffer,
1178230557Sjimharris         sizeof(SCI_SAS_IDENTIFY_ADDRESS_FRAME_T)
1179230557Sjimharris      );
1180230557Sjimharris
1181230557Sjimharris      properties->received_capabilities.u.all
1182230557Sjimharris         = SCU_SAS_RECPHYCAP_READ(this_phy);
1183230557Sjimharris
1184230557Sjimharris      return SCI_SUCCESS;
1185230557Sjimharris   }
1186230557Sjimharris
1187230557Sjimharris   return SCI_FAILURE;
1188230557Sjimharris}
1189230557Sjimharris
1190230557Sjimharris// ---------------------------------------------------------------------------
1191230557Sjimharris
1192230557SjimharrisSCI_STATUS scic_sata_phy_get_properties(
1193230557Sjimharris   SCI_PHY_HANDLE_T             phy,
1194230557Sjimharris   SCIC_SATA_PHY_PROPERTIES_T * properties
1195230557Sjimharris)
1196230557Sjimharris{
1197230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1198230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1199230557Sjimharris
1200230557Sjimharris   SCIC_LOG_TRACE((
1201230557Sjimharris      sci_base_object_get_logger(this_phy),
1202230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1203230557Sjimharris      "scic_sata_phy_get_properties(0x%x, 0x%x) enter\n",
1204230557Sjimharris      this_phy, properties
1205230557Sjimharris   ));
1206230557Sjimharris
1207230557Sjimharris   if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)
1208230557Sjimharris   {
1209230557Sjimharris      memcpy(
1210230557Sjimharris         &properties->signature_fis,
1211230557Sjimharris         &this_phy->phy_type.sata.signature_fis_buffer,
1212230557Sjimharris         sizeof(SATA_FIS_REG_D2H_T)
1213230557Sjimharris      );
1214230557Sjimharris
1215230557Sjimharris      /// @todo add support for port selectors.
1216230557Sjimharris      properties->is_port_selector_present = FALSE;
1217230557Sjimharris
1218230557Sjimharris      return SCI_SUCCESS;
1219230557Sjimharris   }
1220230557Sjimharris
1221230557Sjimharris   return SCI_FAILURE;
1222230557Sjimharris}
1223230557Sjimharris
1224230557Sjimharris// ---------------------------------------------------------------------------
1225230557Sjimharris
1226230557Sjimharris#if !defined(DISABLE_PORT_SELECTORS)
1227230557Sjimharris
1228230557SjimharrisSCI_STATUS scic_sata_phy_send_port_selection_signal(
1229230557Sjimharris   SCI_PHY_HANDLE_T  phy
1230230557Sjimharris)
1231230557Sjimharris{
1232230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1233230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1234230557Sjimharris
1235230557Sjimharris   SCIC_LOG_TRACE((
1236230557Sjimharris      sci_base_object_get_logger(this_phy),
1237230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1238230557Sjimharris      "scic_sata_phy_send_port_selection_signals(0x%x) enter\n",
1239230557Sjimharris      this_phy
1240230557Sjimharris   ));
1241230557Sjimharris
1242230557Sjimharris   /// @todo To be implemented
1243230557Sjimharris   ASSERT(FALSE);
1244230557Sjimharris   return SCI_FAILURE;
1245230557Sjimharris}
1246230557Sjimharris
1247230557Sjimharris#endif // !defined(DISABLE_PORT_SELECTORS)
1248230557Sjimharris
1249230557Sjimharris// ---------------------------------------------------------------------------
1250230557Sjimharris
1251230557Sjimharris#if !defined(DISABLE_PHY_COUNTERS)
1252230557Sjimharris
1253230557SjimharrisSCI_STATUS scic_phy_enable_counter(
1254230557Sjimharris   SCI_PHY_HANDLE_T       phy,
1255230557Sjimharris   SCIC_PHY_COUNTER_ID_T  counter_id
1256230557Sjimharris)
1257230557Sjimharris{
1258230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1259230557Sjimharris   SCI_STATUS status = SCI_SUCCESS;
1260230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1261230557Sjimharris
1262230557Sjimharris   SCIC_LOG_TRACE((
1263230557Sjimharris      sci_base_object_get_logger(this_phy),
1264230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1265230557Sjimharris      "scic_phy_enable_counter(0x%x, 0x%x) enter\n",
1266230557Sjimharris      this_phy, counter_id
1267230557Sjimharris   ));
1268230557Sjimharris
1269230557Sjimharris   switch(counter_id)
1270230557Sjimharris   {
1271230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
1272230557Sjimharris         {
1273230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1274230557Sjimharris            control |= (1 << SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX);
1275230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1276230557Sjimharris         }
1277230557Sjimharris         break;
1278230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
1279230557Sjimharris         {
1280230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1281230557Sjimharris            control |= (1 << SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX);
1282230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1283230557Sjimharris         }
1284230557Sjimharris         break;
1285230557Sjimharris      case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
1286230557Sjimharris         {
1287230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1288230557Sjimharris            control |= (1 << SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX);
1289230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1290230557Sjimharris         }
1291230557Sjimharris         break;
1292230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
1293230557Sjimharris         {
1294230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1295230557Sjimharris            control |= (1 << SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX);
1296230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1297230557Sjimharris         }
1298230557Sjimharris         break;
1299230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
1300230557Sjimharris         {
1301230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1302230557Sjimharris            control |= (1 << SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX);
1303230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1304230557Sjimharris         }
1305230557Sjimharris         break;
1306230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
1307230557Sjimharris         {
1308230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1309230557Sjimharris            control |= (1 << SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX);
1310230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1311230557Sjimharris         }
1312230557Sjimharris         break;
1313230557Sjimharris
1314230557Sjimharris         // These error counters are enabled by default, and cannot be
1315230557Sjimharris         //  disabled.  Return SCI_SUCCESS to denote that they are
1316230557Sjimharris         //  enabled, hiding the fact that enabling the counter is
1317230557Sjimharris         //  a no-op.
1318230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME:
1319230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
1320230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
1321230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
1322230557Sjimharris      case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
1323230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
1324230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
1325230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
1326230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
1327230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
1328230557Sjimharris      case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
1329230557Sjimharris         break;
1330230557Sjimharris
1331230557Sjimharris      default:
1332230557Sjimharris         status = SCI_FAILURE;
1333230557Sjimharris         break;
1334230557Sjimharris   }
1335230557Sjimharris   return status;
1336230557Sjimharris}
1337230557Sjimharris
1338230557Sjimharris// ---------------------------------------------------------------------------
1339230557Sjimharris
1340230557SjimharrisSCI_STATUS scic_phy_disable_counter(
1341230557Sjimharris   SCI_PHY_HANDLE_T       phy,
1342230557Sjimharris   SCIC_PHY_COUNTER_ID_T  counter_id
1343230557Sjimharris)
1344230557Sjimharris{
1345230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1346230557Sjimharris   SCI_STATUS status = SCI_SUCCESS;
1347230557Sjimharris
1348230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1349230557Sjimharris
1350230557Sjimharris   SCIC_LOG_TRACE((
1351230557Sjimharris      sci_base_object_get_logger(this_phy),
1352230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1353230557Sjimharris      "scic_phy_disable_counter(0x%x, 0x%x) enter\n",
1354230557Sjimharris      this_phy, counter_id
1355230557Sjimharris   ));
1356230557Sjimharris
1357230557Sjimharris   switch(counter_id)
1358230557Sjimharris   {
1359230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
1360230557Sjimharris         {
1361230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1362230557Sjimharris            control &= ~(1 << SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX);
1363230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1364230557Sjimharris         }
1365230557Sjimharris         break;
1366230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
1367230557Sjimharris         {
1368230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1369230557Sjimharris            control &= ~(1 << SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX);
1370230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1371230557Sjimharris         }
1372230557Sjimharris         break;
1373230557Sjimharris      case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
1374230557Sjimharris         {
1375230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1376230557Sjimharris            control &= ~(1 << SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX);
1377230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1378230557Sjimharris         }
1379230557Sjimharris         break;
1380230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
1381230557Sjimharris         {
1382230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1383230557Sjimharris            control &= ~(1 << SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX);
1384230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1385230557Sjimharris         }
1386230557Sjimharris         break;
1387230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
1388230557Sjimharris         {
1389230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1390230557Sjimharris            control &= ~(1 << SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX);
1391230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1392230557Sjimharris         }
1393230557Sjimharris         break;
1394230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
1395230557Sjimharris         {
1396230557Sjimharris            U32 control = SCU_SAS_ECENCR_READ(this_phy);
1397230557Sjimharris            control &= ~(1 << SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX);
1398230557Sjimharris            SCU_SAS_ECENCR_WRITE(this_phy, control);
1399230557Sjimharris         }
1400230557Sjimharris         break;
1401230557Sjimharris
1402230557Sjimharris         // These error counters cannot be disabled, so return SCI_FAILURE.
1403230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME:
1404230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
1405230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
1406230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
1407230557Sjimharris      case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
1408230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
1409230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
1410230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
1411230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
1412230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
1413230557Sjimharris      case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
1414230557Sjimharris      default:
1415230557Sjimharris         status = SCI_FAILURE;
1416230557Sjimharris         break;
1417230557Sjimharris   }
1418230557Sjimharris   return status;
1419230557Sjimharris}
1420230557Sjimharris
1421230557Sjimharris// ---------------------------------------------------------------------------
1422230557Sjimharris
1423230557SjimharrisSCI_STATUS scic_phy_get_counter(
1424230557Sjimharris   SCI_PHY_HANDLE_T        phy,
1425230557Sjimharris   SCIC_PHY_COUNTER_ID_T   counter_id,
1426230557Sjimharris   U32                   * data
1427230557Sjimharris)
1428230557Sjimharris{
1429230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1430230557Sjimharris   SCI_STATUS status = SCI_SUCCESS;
1431230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1432230557Sjimharris
1433230557Sjimharris   SCIC_LOG_TRACE((
1434230557Sjimharris      sci_base_object_get_logger(this_phy),
1435230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1436230557Sjimharris      "scic_phy_get_counter(0x%x, 0x%x) enter\n",
1437230557Sjimharris      this_phy, counter_id
1438230557Sjimharris   ));
1439230557Sjimharris
1440230557Sjimharris   switch(counter_id)
1441230557Sjimharris   {
1442230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME:
1443230557Sjimharris         *data = scu_link_layer_register_read(this_phy, received_frame_count);
1444230557Sjimharris         break;
1445230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
1446230557Sjimharris         *data = scu_link_layer_register_read(this_phy, transmit_frame_count);
1447230557Sjimharris         break;
1448230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
1449230557Sjimharris         *data = scu_link_layer_register_read(this_phy, received_dword_count);
1450230557Sjimharris         break;
1451230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
1452230557Sjimharris         *data = scu_link_layer_register_read(this_phy, transmit_dword_count);
1453230557Sjimharris         break;
1454230557Sjimharris      case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
1455230557Sjimharris         *data = scu_link_layer_register_read(this_phy, loss_of_sync_error_count);
1456230557Sjimharris         break;
1457230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
1458230557Sjimharris         *data = scu_link_layer_register_read(this_phy, running_disparity_error_count);
1459230557Sjimharris         break;
1460230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
1461230557Sjimharris         *data = scu_link_layer_register_read(this_phy, received_frame_crc_error_count);
1462230557Sjimharris         break;
1463230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
1464230557Sjimharris         *data = this_phy->error_counter[SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX];
1465230557Sjimharris         break;
1466230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
1467230557Sjimharris         *data = this_phy->error_counter[SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX];
1468230557Sjimharris         break;
1469230557Sjimharris      case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
1470230557Sjimharris         *data = this_phy->error_counter[SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX];
1471230557Sjimharris         break;
1472230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
1473230557Sjimharris         *data = this_phy->error_counter[SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX];
1474230557Sjimharris         break;
1475230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
1476230557Sjimharris         *data = this_phy->error_counter[SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX];
1477230557Sjimharris         break;
1478230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
1479230557Sjimharris         *data = this_phy->error_counter[SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX];
1480230557Sjimharris         break;
1481230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
1482230557Sjimharris         *data = scu_link_layer_register_read(this_phy, received_short_frame_count);
1483230557Sjimharris         break;
1484230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
1485230557Sjimharris         *data = scu_link_layer_register_read(this_phy, received_frame_without_credit_count);
1486230557Sjimharris         break;
1487230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
1488230557Sjimharris         *data = scu_link_layer_register_read(this_phy, received_frame_after_done_count);
1489230557Sjimharris         break;
1490230557Sjimharris      case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
1491230557Sjimharris         *data = scu_link_layer_register_read(this_phy, phy_reset_problem_count);
1492230557Sjimharris         break;
1493230557Sjimharris      default:
1494230557Sjimharris         status = SCI_FAILURE;
1495230557Sjimharris         break;
1496230557Sjimharris   }
1497230557Sjimharris
1498230557Sjimharris   return status;
1499230557Sjimharris}
1500230557Sjimharris
1501230557Sjimharris// ---------------------------------------------------------------------------
1502230557Sjimharris
1503230557SjimharrisSCI_STATUS scic_phy_clear_counter(
1504230557Sjimharris   SCI_PHY_HANDLE_T       phy,
1505230557Sjimharris   SCIC_PHY_COUNTER_ID_T  counter_id
1506230557Sjimharris)
1507230557Sjimharris{
1508230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1509230557Sjimharris   SCI_STATUS status = SCI_SUCCESS;
1510230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1511230557Sjimharris
1512230557Sjimharris   SCIC_LOG_TRACE((
1513230557Sjimharris      sci_base_object_get_logger(this_phy),
1514230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1515230557Sjimharris      "scic_phy_clear_counter(0x%x, 0x%x) enter\n",
1516230557Sjimharris      this_phy, counter_id
1517230557Sjimharris   ));
1518230557Sjimharris
1519230557Sjimharris   switch(counter_id)
1520230557Sjimharris   {
1521230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME:
1522230557Sjimharris         scu_link_layer_register_write(this_phy, received_frame_count, 0);
1523230557Sjimharris         break;
1524230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
1525230557Sjimharris         scu_link_layer_register_write(this_phy, transmit_frame_count, 0);
1526230557Sjimharris         break;
1527230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
1528230557Sjimharris         scu_link_layer_register_write(this_phy, received_dword_count, 0);
1529230557Sjimharris         break;
1530230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
1531230557Sjimharris         scu_link_layer_register_write(this_phy, transmit_dword_count, 0);
1532230557Sjimharris         break;
1533230557Sjimharris      case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
1534230557Sjimharris         scu_link_layer_register_write(this_phy, loss_of_sync_error_count, 0);
1535230557Sjimharris         break;
1536230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
1537230557Sjimharris         scu_link_layer_register_write(this_phy, running_disparity_error_count, 0);
1538230557Sjimharris         break;
1539230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
1540230557Sjimharris         scu_link_layer_register_write(this_phy, received_frame_crc_error_count, 0);
1541230557Sjimharris         break;
1542230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
1543230557Sjimharris         this_phy->error_counter[SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX] = 0;
1544230557Sjimharris         break;
1545230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
1546230557Sjimharris         this_phy->error_counter[SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX] = 0;
1547230557Sjimharris         break;
1548230557Sjimharris      case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
1549230557Sjimharris         this_phy->error_counter[SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX] = 0;
1550230557Sjimharris         break;
1551230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
1552230557Sjimharris         this_phy->error_counter[SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX] = 0;
1553230557Sjimharris         break;
1554230557Sjimharris      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
1555230557Sjimharris         this_phy->error_counter[SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX] = 0;
1556230557Sjimharris         break;
1557230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
1558230557Sjimharris         this_phy->error_counter[SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX] = 0;
1559230557Sjimharris         break;
1560230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
1561230557Sjimharris         scu_link_layer_register_write(this_phy, received_short_frame_count, 0);
1562230557Sjimharris         break;
1563230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
1564230557Sjimharris         scu_link_layer_register_write(this_phy, received_frame_without_credit_count, 0);
1565230557Sjimharris         break;
1566230557Sjimharris      case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
1567230557Sjimharris         scu_link_layer_register_write(this_phy, received_frame_after_done_count, 0);
1568230557Sjimharris         break;
1569230557Sjimharris      case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
1570230557Sjimharris         scu_link_layer_register_write(this_phy, phy_reset_problem_count, 0);
1571230557Sjimharris         break;
1572230557Sjimharris      default:
1573230557Sjimharris         status = SCI_FAILURE;
1574230557Sjimharris   }
1575230557Sjimharris
1576230557Sjimharris   return status;
1577230557Sjimharris}
1578230557Sjimharris
1579230557Sjimharris#endif // !defined(DISABLE_PHY_COUNTERS)
1580230557Sjimharris
1581230557SjimharrisSCI_STATUS scic_phy_stop(
1582230557Sjimharris   SCI_PHY_HANDLE_T       phy
1583230557Sjimharris)
1584230557Sjimharris{
1585230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1586230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1587230557Sjimharris
1588230557Sjimharris   SCIC_LOG_TRACE((
1589230557Sjimharris      sci_base_object_get_logger(this_phy),
1590230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1591230557Sjimharris      "scic_phy_stop(this_phy:0x%x)\n",
1592230557Sjimharris      this_phy
1593230557Sjimharris   ));
1594230557Sjimharris
1595230557Sjimharris   return this_phy->state_handlers->parent.stop_handler(&this_phy->parent);
1596230557Sjimharris}
1597230557Sjimharris
1598230557SjimharrisSCI_STATUS scic_phy_start(
1599230557Sjimharris   SCI_PHY_HANDLE_T       phy
1600230557Sjimharris)
1601230557Sjimharris{
1602230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1603230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1604230557Sjimharris
1605230557Sjimharris   SCIC_LOG_TRACE((
1606230557Sjimharris      sci_base_object_get_logger(this_phy),
1607230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1608230557Sjimharris      "scic_phy_start(this_phy:0x%x)\n",
1609230557Sjimharris      this_phy
1610230557Sjimharris   ));
1611230557Sjimharris
1612230557Sjimharris   return this_phy->state_handlers->parent.start_handler(&this_phy->parent);
1613230557Sjimharris}
1614230557Sjimharris
1615230557Sjimharris//******************************************************************************
1616230557Sjimharris//* PHY STATE MACHINE
1617230557Sjimharris//******************************************************************************
1618230557Sjimharris
1619230557Sjimharris//***************************************************************************
1620230557Sjimharris//*  DEFAULT HANDLERS
1621230557Sjimharris//***************************************************************************
1622230557Sjimharris
1623230557Sjimharris/**
1624230557Sjimharris * This is the default method for phy a start request.  It will report a
1625230557Sjimharris * warning and exit.
1626230557Sjimharris *
1627230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1628230557Sjimharris *       SCIC_SDS_PHY object.
1629230557Sjimharris *
1630230557Sjimharris * @return SCI_STATUS
1631230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1632230557Sjimharris */
1633230557SjimharrisSCI_STATUS scic_sds_phy_default_start_handler(
1634230557Sjimharris   SCI_BASE_PHY_T *phy
1635230557Sjimharris)
1636230557Sjimharris{
1637230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1638230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1639230557Sjimharris
1640230557Sjimharris   SCIC_LOG_WARNING((
1641230557Sjimharris      sci_base_object_get_logger(this_phy),
1642230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1643230557Sjimharris      "SCIC Phy 0x%08x requested to start from invalid state %d\n",
1644230557Sjimharris      this_phy,
1645230557Sjimharris      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
1646230557Sjimharris   ));
1647230557Sjimharris
1648230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1649230557Sjimharris
1650230557Sjimharris}
1651230557Sjimharris
1652230557Sjimharris/**
1653230557Sjimharris * This is the default method for phy a stop request.  It will report a
1654230557Sjimharris * warning and exit.
1655230557Sjimharris *
1656230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1657230557Sjimharris *       SCIC_SDS_PHY object.
1658230557Sjimharris *
1659230557Sjimharris * @return SCI_STATUS
1660230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1661230557Sjimharris */
1662230557SjimharrisSCI_STATUS scic_sds_phy_default_stop_handler(
1663230557Sjimharris   SCI_BASE_PHY_T *phy
1664230557Sjimharris)
1665230557Sjimharris{
1666230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1667230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1668230557Sjimharris
1669230557Sjimharris   SCIC_LOG_WARNING((
1670230557Sjimharris      sci_base_object_get_logger(this_phy),
1671230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1672230557Sjimharris      "SCIC Phy 0x%08x requested to stop from invalid state %d\n",
1673230557Sjimharris      this_phy,
1674230557Sjimharris      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
1675230557Sjimharris   ));
1676230557Sjimharris
1677230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1678230557Sjimharris}
1679230557Sjimharris
1680230557Sjimharris/**
1681230557Sjimharris * This is the default method for phy a reset request.  It will report a
1682230557Sjimharris * warning and exit.
1683230557Sjimharris *
1684230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1685230557Sjimharris *       SCIC_SDS_PHY object.
1686230557Sjimharris *
1687230557Sjimharris * @return SCI_STATUS
1688230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1689230557Sjimharris */
1690230557SjimharrisSCI_STATUS scic_sds_phy_default_reset_handler(
1691230557Sjimharris   SCI_BASE_PHY_T * phy
1692230557Sjimharris)
1693230557Sjimharris{
1694230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1695230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1696230557Sjimharris
1697230557Sjimharris   SCIC_LOG_WARNING((
1698230557Sjimharris      sci_base_object_get_logger(this_phy),
1699230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1700230557Sjimharris      "SCIC Phy 0x%08x requested to reset from invalid state %d\n",
1701230557Sjimharris      this_phy,
1702230557Sjimharris      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
1703230557Sjimharris   ));
1704230557Sjimharris
1705230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1706230557Sjimharris}
1707230557Sjimharris
1708230557Sjimharris/**
1709230557Sjimharris * This is the default method for phy a destruct request.  It will report a
1710230557Sjimharris * warning and exit.
1711230557Sjimharris *
1712230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1713230557Sjimharris *       SCIC_SDS_PHY object.
1714230557Sjimharris *
1715230557Sjimharris * @return SCI_STATUS
1716230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1717230557Sjimharris */
1718230557SjimharrisSCI_STATUS scic_sds_phy_default_destroy_handler(
1719230557Sjimharris   SCI_BASE_PHY_T *phy
1720230557Sjimharris)
1721230557Sjimharris{
1722230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1723230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1724230557Sjimharris
1725230557Sjimharris   /// @todo Implement something for the default
1726230557Sjimharris   SCIC_LOG_WARNING((
1727230557Sjimharris      sci_base_object_get_logger(this_phy),
1728230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1729230557Sjimharris      "SCIC Phy 0x%08x requested to destroy from invalid state %d\n",
1730230557Sjimharris      this_phy,
1731230557Sjimharris      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
1732230557Sjimharris   ));
1733230557Sjimharris
1734230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1735230557Sjimharris}
1736230557Sjimharris
1737230557Sjimharris/**
1738230557Sjimharris * This is the default method for a phy frame handling request.  It will
1739230557Sjimharris * report a warning, release the frame and exit.
1740230557Sjimharris *
1741230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1742230557Sjimharris *       SCIC_SDS_PHY object.
1743230557Sjimharris * @param[in] frame_index This is the frame index that was received from the
1744230557Sjimharris *       SCU hardware.
1745230557Sjimharris *
1746230557Sjimharris * @return SCI_STATUS
1747230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1748230557Sjimharris */
1749230557SjimharrisSCI_STATUS scic_sds_phy_default_frame_handler(
1750230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
1751230557Sjimharris   U32            frame_index
1752230557Sjimharris)
1753230557Sjimharris{
1754230557Sjimharris   SCIC_LOG_WARNING((
1755230557Sjimharris      sci_base_object_get_logger(this_phy),
1756230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1757298931Spfg      "SCIC Phy 0x%08x received unexpected frame data %d while in state %d\n",
1758230557Sjimharris      this_phy, frame_index,
1759230557Sjimharris      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
1760230557Sjimharris   ));
1761230557Sjimharris
1762230557Sjimharris   scic_sds_controller_release_frame(
1763230557Sjimharris      scic_sds_phy_get_controller(this_phy), frame_index);
1764230557Sjimharris
1765230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1766230557Sjimharris}
1767230557Sjimharris
1768230557Sjimharris/**
1769230557Sjimharris * This is the default method for a phy event handler.  It will report a
1770230557Sjimharris * warning and exit.
1771230557Sjimharris *
1772230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1773230557Sjimharris *       SCIC_SDS_PHY object.
1774230557Sjimharris * @param[in] event_code This is the event code that was received from the SCU
1775230557Sjimharris *       hardware.
1776230557Sjimharris *
1777230557Sjimharris * @return SCI_STATUS
1778230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1779230557Sjimharris */
1780230557SjimharrisSCI_STATUS scic_sds_phy_default_event_handler(
1781230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
1782230557Sjimharris   U32            event_code
1783230557Sjimharris)
1784230557Sjimharris{
1785230557Sjimharris   SCIC_LOG_WARNING((
1786230557Sjimharris      sci_base_object_get_logger(this_phy),
1787230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1788230557Sjimharris      "SCIC Phy 0x%08x received unexpected event status %x while in state %d\n",
1789230557Sjimharris      this_phy, event_code,
1790230557Sjimharris      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
1791230557Sjimharris   ));
1792230557Sjimharris
1793230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1794230557Sjimharris}
1795230557Sjimharris
1796230557Sjimharris/**
1797230557Sjimharris * This is the default method for a phy consume power handler.  It will report
1798230557Sjimharris * a warning and exit.
1799230557Sjimharris *
1800230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1801230557Sjimharris *       SCIC_SDS_PHY object.
1802230557Sjimharris *
1803230557Sjimharris * @return SCI_STATUS
1804230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1805230557Sjimharris */
1806230557SjimharrisSCI_STATUS scic_sds_phy_default_consume_power_handler(
1807230557Sjimharris   SCIC_SDS_PHY_T *this_phy
1808230557Sjimharris)
1809230557Sjimharris{
1810230557Sjimharris   SCIC_LOG_WARNING((
1811230557Sjimharris      sci_base_object_get_logger(this_phy),
1812230557Sjimharris      SCIC_LOG_OBJECT_PHY,
1813230557Sjimharris      "SCIC Phy 0x%08x given unexpected permission to consume power while in state %d\n",
1814230557Sjimharris      this_phy,
1815230557Sjimharris      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
1816230557Sjimharris   ));
1817230557Sjimharris
1818230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1819230557Sjimharris}
1820230557Sjimharris
1821230557Sjimharris//******************************************************************************
1822230557Sjimharris//* PHY STOPPED STATE HANDLERS
1823230557Sjimharris//******************************************************************************
1824230557Sjimharris
1825230557Sjimharris/**
1826230557Sjimharris * This method takes the SCIC_SDS_PHY from a stopped state and attempts to
1827230557Sjimharris * start it.
1828230557Sjimharris *    - The phy state machine is transitioned to the
1829230557Sjimharris *      SCI_BASE_PHY_STATE_STARTING.
1830230557Sjimharris *
1831230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1832230557Sjimharris *       SCIC_SDS_PHY object.
1833230557Sjimharris *
1834230557Sjimharris * @return SCI_STATUS
1835230557Sjimharris * @retval SCI_SUCCESS
1836230557Sjimharris */
1837230557Sjimharrisstatic
1838230557SjimharrisSCI_STATUS scic_sds_phy_stopped_state_start_handler(
1839230557Sjimharris   SCI_BASE_PHY_T *phy
1840230557Sjimharris)
1841230557Sjimharris{
1842230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1843230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1844230557Sjimharris
1845230557Sjimharris
1846230557Sjimharris
1847230557Sjimharris   // Create the SIGNATURE FIS Timeout timer for this phy
1848230557Sjimharris   this_phy->sata_timeout_timer = scic_cb_timer_create(
1849230557Sjimharris      scic_sds_phy_get_controller(this_phy),
1850230557Sjimharris      scic_sds_phy_sata_timeout,
1851230557Sjimharris      this_phy
1852230557Sjimharris   );
1853230557Sjimharris
1854230557Sjimharris   if (this_phy->sata_timeout_timer != NULL)
1855230557Sjimharris   {
1856230557Sjimharris      sci_base_state_machine_change_state(
1857230557Sjimharris         scic_sds_phy_get_base_state_machine(this_phy),
1858230557Sjimharris         SCI_BASE_PHY_STATE_STARTING
1859230557Sjimharris      );
1860230557Sjimharris   }
1861230557Sjimharris
1862230557Sjimharris   return SCI_SUCCESS;
1863230557Sjimharris}
1864230557Sjimharris
1865230557Sjimharris/**
1866230557Sjimharris * This method takes the SCIC_SDS_PHY from a stopped state and destroys it.
1867230557Sjimharris *    - This function takes no action.
1868230557Sjimharris *
1869298931Spfg * @todo Shouldn't this function transition the SCI_BASE_PHY::state_machine to
1870230557Sjimharris *        the SCI_BASE_PHY_STATE_FINAL?
1871230557Sjimharris *
1872230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1873230557Sjimharris *       SCIC_SDS_PHY object.
1874230557Sjimharris *
1875230557Sjimharris * @return SCI_STATUS
1876230557Sjimharris * @retval SCI_SUCCESS
1877230557Sjimharris */
1878230557Sjimharrisstatic
1879230557SjimharrisSCI_STATUS scic_sds_phy_stopped_state_destroy_handler(
1880230557Sjimharris   SCI_BASE_PHY_T *phy
1881230557Sjimharris)
1882230557Sjimharris{
1883230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1884230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1885230557Sjimharris
1886230557Sjimharris   /// @todo what do we actually need to do here?
1887230557Sjimharris   return SCI_SUCCESS;
1888230557Sjimharris}
1889230557Sjimharris
1890230557Sjimharris//******************************************************************************
1891230557Sjimharris//* PHY STARTING STATE HANDLERS
1892230557Sjimharris//******************************************************************************
1893230557Sjimharris
1894230557Sjimharris// All of these state handlers are mapped to the starting sub-state machine
1895230557Sjimharris
1896230557Sjimharris//******************************************************************************
1897230557Sjimharris//* PHY READY STATE HANDLERS
1898230557Sjimharris//******************************************************************************
1899230557Sjimharris
1900230557Sjimharris/**
1901230557Sjimharris * This method takes the SCIC_SDS_PHY from a ready state and attempts to stop
1902230557Sjimharris * it.
1903230557Sjimharris *    - The phy state machine is transitioned to the SCI_BASE_PHY_STATE_STOPPED.
1904230557Sjimharris *
1905230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1906230557Sjimharris *       SCIC_SDS_PHY object.
1907230557Sjimharris *
1908230557Sjimharris * @return SCI_STATUS
1909230557Sjimharris * @retval SCI_SUCCESS
1910230557Sjimharris */
1911230557Sjimharrisstatic
1912230557SjimharrisSCI_STATUS scic_sds_phy_ready_state_stop_handler(
1913230557Sjimharris   SCI_BASE_PHY_T *phy
1914230557Sjimharris)
1915230557Sjimharris{
1916230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
1917230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1918230557Sjimharris
1919230557Sjimharris   sci_base_state_machine_change_state(
1920230557Sjimharris      scic_sds_phy_get_base_state_machine(this_phy),
1921230557Sjimharris      SCI_BASE_PHY_STATE_STOPPED
1922230557Sjimharris   );
1923230557Sjimharris
1924230557Sjimharris   scic_sds_controller_link_down(
1925230557Sjimharris      scic_sds_phy_get_controller(this_phy),
1926230557Sjimharris      scic_sds_phy_get_port(this_phy),
1927230557Sjimharris      this_phy
1928230557Sjimharris   );
1929230557Sjimharris
1930230557Sjimharris   return SCI_SUCCESS;
1931230557Sjimharris}
1932230557Sjimharris
1933230557Sjimharris/**
1934230557Sjimharris * This method takes the SCIC_SDS_PHY from a ready state and attempts to reset
1935230557Sjimharris * it.
1936230557Sjimharris *    - The phy state machine is transitioned to the SCI_BASE_PHY_STATE_STARTING.
1937230557Sjimharris *
1938230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
1939230557Sjimharris *       SCIC_SDS_PHY object.
1940230557Sjimharris *
1941230557Sjimharris * @return SCI_STATUS
1942230557Sjimharris * @retval SCI_SUCCESS
1943230557Sjimharris */
1944230557Sjimharrisstatic
1945230557SjimharrisSCI_STATUS scic_sds_phy_ready_state_reset_handler(
1946230557Sjimharris   SCI_BASE_PHY_T * phy
1947230557Sjimharris)
1948230557Sjimharris{
1949230557Sjimharris   SCIC_SDS_PHY_T * this_phy;
1950230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
1951230557Sjimharris
1952230557Sjimharris   sci_base_state_machine_change_state(
1953230557Sjimharris      scic_sds_phy_get_base_state_machine(this_phy),
1954230557Sjimharris      SCI_BASE_PHY_STATE_RESETTING
1955230557Sjimharris   );
1956230557Sjimharris
1957230557Sjimharris   return SCI_SUCCESS;
1958230557Sjimharris}
1959230557Sjimharris
1960230557Sjimharris/**
1961230557Sjimharris * This method request the SCIC_SDS_PHY handle the received event.  The only
1962230557Sjimharris * event that we are interested in while in the ready state is the link
1963230557Sjimharris * failure event.
1964230557Sjimharris *    - decoded event is a link failure
1965230557Sjimharris *       - transition the SCIC_SDS_PHY back to the SCI_BASE_PHY_STATE_STARTING
1966230557Sjimharris *         state.
1967298931Spfg *    - any other event received will report a warning message
1968230557Sjimharris *
1969230557Sjimharris * @param[in] phy This is the SCIC_SDS_PHY object which has received the
1970230557Sjimharris *       event.
1971230557Sjimharris *
1972230557Sjimharris * @return SCI_STATUS
1973230557Sjimharris * @retval SCI_SUCCESS if the event received is a link failure
1974230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE for any other event received.
1975230557Sjimharris */
1976230557Sjimharrisstatic
1977230557SjimharrisSCI_STATUS scic_sds_phy_ready_state_event_handler(
1978230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
1979230557Sjimharris   U32            event_code
1980230557Sjimharris)
1981230557Sjimharris{
1982230557Sjimharris   SCI_STATUS result = SCI_FAILURE;
1983230557Sjimharris
1984230557Sjimharris   switch (scu_get_event_code(event_code))
1985230557Sjimharris   {
1986230557Sjimharris   case SCU_EVENT_LINK_FAILURE:
1987230557Sjimharris      // Link failure change state back to the starting state
1988230557Sjimharris      sci_base_state_machine_change_state(
1989230557Sjimharris         scic_sds_phy_get_base_state_machine(this_phy),
1990230557Sjimharris         SCI_BASE_PHY_STATE_STARTING
1991230557Sjimharris         );
1992230557Sjimharris
1993230557Sjimharris      result = SCI_SUCCESS;
1994230557Sjimharris      break;
1995230557Sjimharris
1996230557Sjimharris   case SCU_EVENT_BROADCAST_CHANGE:
1997230557Sjimharris      // Broadcast change received. Notify the port.
1998230557Sjimharris      if (scic_sds_phy_get_port(this_phy) != SCI_INVALID_HANDLE)
1999230557Sjimharris         scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy);
2000230557Sjimharris      else
2001230557Sjimharris         this_phy->bcn_received_while_port_unassigned = TRUE;
2002230557Sjimharris      break;
2003230557Sjimharris
2004230557Sjimharris   case SCU_EVENT_ERR_CNT(RX_CREDIT_BLOCKED_RECEIVED):
2005230557Sjimharris   case SCU_EVENT_ERR_CNT(TX_DONE_CREDIT_TIMEOUT):
2006230557Sjimharris   case SCU_EVENT_ERR_CNT(RX_DONE_CREDIT_TIMEOUT):
2007230557Sjimharris   case SCU_EVENT_ERR_CNT(INACTIVITY_TIMER_EXPIRED):
2008230557Sjimharris   case SCU_EVENT_ERR_CNT(TX_DONE_ACK_NAK_TIMEOUT):
2009230557Sjimharris   case SCU_EVENT_ERR_CNT(RX_DONE_ACK_NAK_TIMEOUT):
2010230557Sjimharris      {
2011230557Sjimharris         U32 error_counter_index =
2012230557Sjimharris                scu_get_event_specifier(event_code) >> SCU_EVENT_SPECIFIC_CODE_SHIFT;
2013230557Sjimharris
2014230557Sjimharris         this_phy->error_counter[error_counter_index]++;
2015230557Sjimharris         result = SCI_SUCCESS;
2016230557Sjimharris      }
2017230557Sjimharris      break;
2018230557Sjimharris
2019230557Sjimharris   default:
2020230557Sjimharris      SCIC_LOG_WARNING((
2021230557Sjimharris         sci_base_object_get_logger(this_phy),
2022230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
2023298931Spfg         "SCIC PHY 0x%x ready state machine received unexpected event_code %x\n",
2024230557Sjimharris         this_phy, event_code
2025230557Sjimharris      ));
2026230557Sjimharris      result = SCI_FAILURE_INVALID_STATE;
2027230557Sjimharris      break;
2028230557Sjimharris   }
2029230557Sjimharris
2030230557Sjimharris   return result;
2031230557Sjimharris}
2032230557Sjimharris
2033230557Sjimharris// ---------------------------------------------------------------------------
2034230557Sjimharris
2035230557Sjimharris/**
2036230557Sjimharris * This is the resetting state event handler.
2037230557Sjimharris *
2038230557Sjimharris * @param[in] this_phy This is the SCIC_SDS_PHY object which is receiving the
2039230557Sjimharris *       event.
2040230557Sjimharris * @param[in] event_code This is the event code to be processed.
2041230557Sjimharris *
2042230557Sjimharris * @return SCI_STATUS
2043230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
2044230557Sjimharris */
2045230557Sjimharrisstatic
2046230557SjimharrisSCI_STATUS scic_sds_phy_resetting_state_event_handler(
2047230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
2048230557Sjimharris   U32            event_code
2049230557Sjimharris)
2050230557Sjimharris{
2051230557Sjimharris   SCI_STATUS result = SCI_FAILURE;
2052230557Sjimharris
2053230557Sjimharris   switch (scu_get_event_code(event_code))
2054230557Sjimharris   {
2055230557Sjimharris   case SCU_EVENT_HARD_RESET_TRANSMITTED:
2056230557Sjimharris      // Link failure change state back to the starting state
2057230557Sjimharris      sci_base_state_machine_change_state(
2058230557Sjimharris         scic_sds_phy_get_base_state_machine(this_phy),
2059230557Sjimharris         SCI_BASE_PHY_STATE_STARTING
2060230557Sjimharris         );
2061230557Sjimharris
2062230557Sjimharris      result = SCI_SUCCESS;
2063230557Sjimharris      break;
2064230557Sjimharris
2065230557Sjimharris   default:
2066230557Sjimharris      SCIC_LOG_WARNING((
2067230557Sjimharris         sci_base_object_get_logger(this_phy),
2068230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
2069298931Spfg         "SCIC PHY 0x%x resetting state machine received unexpected event_code %x\n",
2070230557Sjimharris         this_phy, event_code
2071230557Sjimharris      ));
2072230557Sjimharris
2073230557Sjimharris      result = SCI_FAILURE_INVALID_STATE;
2074230557Sjimharris      break;
2075230557Sjimharris   }
2076230557Sjimharris
2077230557Sjimharris   return result;
2078230557Sjimharris}
2079230557Sjimharris
2080230557Sjimharris// ---------------------------------------------------------------------------
2081230557Sjimharris
2082230557SjimharrisSCIC_SDS_PHY_STATE_HANDLER_T
2083230557Sjimharris   scic_sds_phy_state_handler_table[SCI_BASE_PHY_MAX_STATES] =
2084230557Sjimharris{
2085230557Sjimharris   // SCI_BASE_PHY_STATE_INITIAL
2086230557Sjimharris   {
2087230557Sjimharris      {
2088230557Sjimharris         scic_sds_phy_default_start_handler,
2089230557Sjimharris         scic_sds_phy_default_stop_handler,
2090230557Sjimharris         scic_sds_phy_default_reset_handler,
2091230557Sjimharris         scic_sds_phy_default_destroy_handler
2092230557Sjimharris      },
2093230557Sjimharris      scic_sds_phy_default_frame_handler,
2094230557Sjimharris      scic_sds_phy_default_event_handler,
2095230557Sjimharris      scic_sds_phy_default_consume_power_handler
2096230557Sjimharris   },
2097230557Sjimharris   // SCI_BASE_PHY_STATE_STOPPED
2098230557Sjimharris   {
2099230557Sjimharris      {
2100230557Sjimharris         scic_sds_phy_stopped_state_start_handler,
2101230557Sjimharris         scic_sds_phy_default_stop_handler,
2102230557Sjimharris         scic_sds_phy_default_reset_handler,
2103230557Sjimharris         scic_sds_phy_stopped_state_destroy_handler
2104230557Sjimharris      },
2105230557Sjimharris      scic_sds_phy_default_frame_handler,
2106230557Sjimharris      scic_sds_phy_default_event_handler,
2107230557Sjimharris      scic_sds_phy_default_consume_power_handler
2108230557Sjimharris   },
2109230557Sjimharris   // SCI_BASE_PHY_STATE_STARTING
2110230557Sjimharris   {
2111230557Sjimharris      {
2112230557Sjimharris         scic_sds_phy_default_start_handler,
2113230557Sjimharris         scic_sds_phy_default_stop_handler,
2114230557Sjimharris         scic_sds_phy_default_reset_handler,
2115230557Sjimharris         scic_sds_phy_default_destroy_handler
2116230557Sjimharris      },
2117230557Sjimharris      scic_sds_phy_default_frame_handler,
2118230557Sjimharris      scic_sds_phy_default_event_handler,
2119230557Sjimharris      scic_sds_phy_default_consume_power_handler
2120230557Sjimharris   },
2121230557Sjimharris   // SCI_BASE_PHY_STATE_READY
2122230557Sjimharris   {
2123230557Sjimharris      {
2124230557Sjimharris         scic_sds_phy_default_start_handler,
2125230557Sjimharris         scic_sds_phy_ready_state_stop_handler,
2126230557Sjimharris         scic_sds_phy_ready_state_reset_handler,
2127230557Sjimharris         scic_sds_phy_default_destroy_handler
2128230557Sjimharris      },
2129230557Sjimharris      scic_sds_phy_default_frame_handler,
2130230557Sjimharris      scic_sds_phy_ready_state_event_handler,
2131230557Sjimharris      scic_sds_phy_default_consume_power_handler
2132230557Sjimharris   },
2133230557Sjimharris   // SCI_BASE_PHY_STATE_RESETTING
2134230557Sjimharris   {
2135230557Sjimharris      {
2136230557Sjimharris         scic_sds_phy_default_start_handler,
2137230557Sjimharris         scic_sds_phy_default_stop_handler,
2138230557Sjimharris         scic_sds_phy_default_reset_handler,
2139230557Sjimharris         scic_sds_phy_default_destroy_handler
2140230557Sjimharris      },
2141230557Sjimharris      scic_sds_phy_default_frame_handler,
2142230557Sjimharris      scic_sds_phy_resetting_state_event_handler,
2143230557Sjimharris      scic_sds_phy_default_consume_power_handler
2144230557Sjimharris   },
2145230557Sjimharris   // SCI_BASE_PHY_STATE_FINAL
2146230557Sjimharris   {
2147230557Sjimharris      {
2148230557Sjimharris         scic_sds_phy_default_start_handler,
2149230557Sjimharris         scic_sds_phy_default_stop_handler,
2150230557Sjimharris         scic_sds_phy_default_reset_handler,
2151230557Sjimharris         scic_sds_phy_default_destroy_handler
2152230557Sjimharris      },
2153230557Sjimharris      scic_sds_phy_default_frame_handler,
2154230557Sjimharris      scic_sds_phy_default_event_handler,
2155230557Sjimharris      scic_sds_phy_default_consume_power_handler
2156230557Sjimharris   }
2157230557Sjimharris};
2158230557Sjimharris
2159230557Sjimharris//****************************************************************************
2160230557Sjimharris//*  PHY STATE PRIVATE METHODS
2161230557Sjimharris//****************************************************************************
2162230557Sjimharris
2163230557Sjimharris/**
2164230557Sjimharris * This method will stop the SCIC_SDS_PHY object. This does not reset the
2165230557Sjimharris * protocol engine it just suspends it and places it in a state where it will
2166230557Sjimharris * not cause the end device to power up.
2167230557Sjimharris *
2168230557Sjimharris * @param[in] this_phy This is the SCIC_SDS_PHY object to stop.
2169230557Sjimharris *
2170230557Sjimharris * @return none
2171230557Sjimharris */
2172230557Sjimharrisstatic
2173230557Sjimharrisvoid scu_link_layer_stop_protocol_engine(
2174230557Sjimharris   SCIC_SDS_PHY_T *this_phy
2175230557Sjimharris)
2176230557Sjimharris{
2177230557Sjimharris   U32 scu_sas_pcfg_value;
2178230557Sjimharris   U32 enable_spinup_value;
2179230557Sjimharris
2180230557Sjimharris   // Suspend the protocol engine and place it in a sata spinup hold state
2181230557Sjimharris   scu_sas_pcfg_value  = SCU_SAS_PCFG_READ(this_phy);
2182230557Sjimharris   scu_sas_pcfg_value |= (
2183230557Sjimharris                           SCU_SAS_PCFG_GEN_BIT(OOB_RESET)
2184230557Sjimharris                         | SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE)
2185230557Sjimharris                         | SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD)
2186230557Sjimharris                         );
2187230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
2188230557Sjimharris
2189230557Sjimharris   // Disable the notify enable spinup primitives
2190230557Sjimharris   enable_spinup_value = SCU_SAS_ENSPINUP_READ(this_phy);
2191230557Sjimharris   enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE);
2192230557Sjimharris   SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup_value);
2193230557Sjimharris}
2194230557Sjimharris
2195230557Sjimharris/**
2196230557Sjimharris * This method will start the OOB/SN state machine for this SCIC_SDS_PHY
2197230557Sjimharris * object.
2198230557Sjimharris *
2199230557Sjimharris * @param[in] this_phy This is the SCIC_SDS_PHY object on which to start the
2200230557Sjimharris *       OOB/SN state machine.
2201230557Sjimharris */
2202230557Sjimharrisstatic
2203230557Sjimharrisvoid scu_link_layer_start_oob(
2204230557Sjimharris   SCIC_SDS_PHY_T *this_phy
2205230557Sjimharris)
2206230557Sjimharris{
2207230557Sjimharris   U32 scu_sas_pcfg_value;
2208230557Sjimharris
2209230557Sjimharris   /* Reset OOB sequence - start */
2210230557Sjimharris   scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
2211230557Sjimharris   scu_sas_pcfg_value &=
2212230557Sjimharris      ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
2213230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
2214230557Sjimharris   SCU_SAS_PCFG_READ(this_phy);
2215230557Sjimharris   /* Reset OOB sequence - end */
2216230557Sjimharris
2217230557Sjimharris   /* Start OOB sequence - start */
2218230557Sjimharris   scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
2219230557Sjimharris   scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
2220230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
2221230557Sjimharris   SCU_SAS_PCFG_READ(this_phy);
2222230557Sjimharris   /* Start OOB sequence - end */
2223230557Sjimharris}
2224230557Sjimharris
2225230557Sjimharris/**
2226230557Sjimharris * This method will transmit a hard reset request on the specified phy. The
2227230557Sjimharris * SCU hardware requires that we reset the OOB state machine and set the hard
2228230557Sjimharris * reset bit in the phy configuration register.
2229230557Sjimharris * We then must start OOB over with the hard reset bit set.
2230230557Sjimharris *
2231230557Sjimharris * @param[in] this_phy
2232230557Sjimharris */
2233230557Sjimharrisstatic
2234230557Sjimharrisvoid scu_link_layer_tx_hard_reset(
2235230557Sjimharris   SCIC_SDS_PHY_T *this_phy
2236230557Sjimharris)
2237230557Sjimharris{
2238230557Sjimharris   U32 phy_configuration_value;
2239230557Sjimharris
2240230557Sjimharris   // SAS Phys must wait for the HARD_RESET_TX event notification to transition
2241230557Sjimharris   // to the starting state.
2242230557Sjimharris   phy_configuration_value = SCU_SAS_PCFG_READ(this_phy);
2243230557Sjimharris   phy_configuration_value |=
2244230557Sjimharris      (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | SCU_SAS_PCFG_GEN_BIT(OOB_RESET));
2245230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value);
2246230557Sjimharris
2247230557Sjimharris   // Now take the OOB state machine out of reset
2248230557Sjimharris   phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
2249230557Sjimharris   phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
2250230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value);
2251230557Sjimharris}
2252230557Sjimharris
2253230557Sjimharris//****************************************************************************
2254230557Sjimharris//*  PHY BASE STATE METHODS
2255230557Sjimharris//****************************************************************************
2256230557Sjimharris
2257230557Sjimharris/**
2258230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
2259230557Sjimharris * entering the SCI_BASE_PHY_STATE_INITIAL.
2260230557Sjimharris *    - This function sets the state handlers for the phy object base state
2261230557Sjimharris * machine initial state.
2262230557Sjimharris *
2263230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2264230557Sjimharris *       SCIC_SDS_PHY object.
2265230557Sjimharris *
2266230557Sjimharris * @return none
2267230557Sjimharris */
2268230557Sjimharrisstatic
2269230557Sjimharrisvoid scic_sds_phy_initial_state_enter(
2270230557Sjimharris   SCI_BASE_OBJECT_T *object
2271230557Sjimharris)
2272230557Sjimharris{
2273230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
2274230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
2275230557Sjimharris
2276230557Sjimharris   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_INITIAL);
2277230557Sjimharris}
2278230557Sjimharris
2279230557Sjimharris/**
2280230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
2281230557Sjimharris * entering the SCI_BASE_PHY_STATE_INITIAL.
2282230557Sjimharris *    - This function sets the state handlers for the phy object base state
2283230557Sjimharris * machine initial state.
2284230557Sjimharris *    - The SCU hardware is requested to stop the protocol engine.
2285230557Sjimharris *
2286230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2287230557Sjimharris *       SCIC_SDS_PHY object.
2288230557Sjimharris *
2289230557Sjimharris * @return none
2290230557Sjimharris */
2291230557Sjimharrisstatic
2292230557Sjimharrisvoid scic_sds_phy_stopped_state_enter(
2293230557Sjimharris   SCI_BASE_OBJECT_T *object
2294230557Sjimharris)
2295230557Sjimharris{
2296230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
2297230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
2298230557Sjimharris
2299230557Sjimharris   /// @todo We need to get to the controller to place this PE in a reset state
2300230557Sjimharris   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED);
2301230557Sjimharris
2302230557Sjimharris   if (this_phy->sata_timeout_timer != NULL)
2303230557Sjimharris   {
2304230557Sjimharris      scic_cb_timer_destroy(
2305230557Sjimharris         scic_sds_phy_get_controller(this_phy),
2306230557Sjimharris         this_phy->sata_timeout_timer
2307230557Sjimharris      );
2308230557Sjimharris
2309230557Sjimharris      this_phy->sata_timeout_timer = NULL;
2310230557Sjimharris   }
2311230557Sjimharris
2312230557Sjimharris   scu_link_layer_stop_protocol_engine(this_phy);
2313230557Sjimharris}
2314230557Sjimharris
2315230557Sjimharris/**
2316230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
2317230557Sjimharris * entering the SCI_BASE_PHY_STATE_STARTING.
2318230557Sjimharris *    - This function sets the state handlers for the phy object base state
2319230557Sjimharris * machine starting state.
2320240743Skevlo *    - The SCU hardware is requested to start OOB/SN on this protocol engine.
2321230557Sjimharris *    - The phy starting substate machine is started.
2322230557Sjimharris *    - If the previous state was the ready state then the
2323230557Sjimharris *      SCIC_SDS_CONTROLLER is informed that the phy has gone link down.
2324230557Sjimharris *
2325230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2326230557Sjimharris *       SCIC_SDS_PHY object.
2327230557Sjimharris *
2328230557Sjimharris * @return none
2329230557Sjimharris */
2330230557Sjimharrisstatic
2331230557Sjimharrisvoid scic_sds_phy_starting_state_enter(
2332230557Sjimharris   SCI_BASE_OBJECT_T *object
2333230557Sjimharris)
2334230557Sjimharris{
2335230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
2336230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
2337230557Sjimharris
2338230557Sjimharris   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STARTING);
2339230557Sjimharris
2340230557Sjimharris   scu_link_layer_stop_protocol_engine(this_phy);
2341230557Sjimharris   scu_link_layer_start_oob(this_phy);
2342230557Sjimharris
2343230557Sjimharris   // We don't know what kind of phy we are going to be just yet
2344230557Sjimharris   this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
2345230557Sjimharris   this_phy->bcn_received_while_port_unassigned = FALSE;
2346230557Sjimharris
2347230557Sjimharris   // Change over to the starting substate machine to continue
2348230557Sjimharris   sci_base_state_machine_start(&this_phy->starting_substate_machine);
2349230557Sjimharris
2350230557Sjimharris   if (this_phy->parent.state_machine.previous_state_id
2351230557Sjimharris       == SCI_BASE_PHY_STATE_READY)
2352230557Sjimharris   {
2353230557Sjimharris      scic_sds_controller_link_down(
2354230557Sjimharris         scic_sds_phy_get_controller(this_phy),
2355230557Sjimharris         scic_sds_phy_get_port(this_phy),
2356230557Sjimharris         this_phy
2357230557Sjimharris      );
2358230557Sjimharris   }
2359230557Sjimharris}
2360230557Sjimharris
2361230557Sjimharris/**
2362230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
2363230557Sjimharris * entering the SCI_BASE_PHY_STATE_READY.
2364230557Sjimharris *    - This function sets the state handlers for the phy object base state
2365230557Sjimharris * machine ready state.
2366230557Sjimharris *    - The SCU hardware protocol engine is resumed.
2367230557Sjimharris *    - The SCIC_SDS_CONTROLLER is informed that the phy object has gone link
2368230557Sjimharris *      up.
2369230557Sjimharris *
2370230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2371230557Sjimharris *       SCIC_SDS_PHY object.
2372230557Sjimharris *
2373230557Sjimharris * @return none
2374230557Sjimharris */
2375230557Sjimharrisstatic
2376230557Sjimharrisvoid scic_sds_phy_ready_state_enter(
2377230557Sjimharris   SCI_BASE_OBJECT_T *object
2378230557Sjimharris)
2379230557Sjimharris{
2380230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
2381230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
2382230557Sjimharris
2383230557Sjimharris   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_READY);
2384230557Sjimharris
2385230557Sjimharris   scic_sds_controller_link_up(
2386230557Sjimharris      scic_sds_phy_get_controller(this_phy),
2387230557Sjimharris      scic_sds_phy_get_port(this_phy),
2388230557Sjimharris      this_phy
2389230557Sjimharris   );
2390230557Sjimharris}
2391230557Sjimharris
2392230557Sjimharris/**
2393230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
2394230557Sjimharris * exiting the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU
2395230557Sjimharris * hardware protocol engine represented by this SCIC_SDS_PHY object.
2396230557Sjimharris *
2397230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2398230557Sjimharris *       SCIC_SDS_PHY object.
2399230557Sjimharris *
2400230557Sjimharris * @return none
2401230557Sjimharris */
2402230557Sjimharrisstatic
2403230557Sjimharrisvoid scic_sds_phy_ready_state_exit(
2404230557Sjimharris   SCI_BASE_OBJECT_T *object
2405230557Sjimharris)
2406230557Sjimharris{
2407230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
2408230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
2409230557Sjimharris
2410230557Sjimharris   scic_sds_phy_suspend(this_phy);
2411230557Sjimharris}
2412230557Sjimharris
2413230557Sjimharris/**
2414230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
2415230557Sjimharris * entering the SCI_BASE_PHY_STATE_RESETTING.
2416230557Sjimharris *    - This function sets the state handlers for the phy object base state
2417230557Sjimharris * machine resetting state.
2418230557Sjimharris *
2419230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2420230557Sjimharris *       SCIC_SDS_PHY object.
2421230557Sjimharris *
2422230557Sjimharris * @return none
2423230557Sjimharris */
2424230557Sjimharrisstatic
2425230557Sjimharrisvoid scic_sds_phy_resetting_state_enter(
2426230557Sjimharris   SCI_BASE_OBJECT_T *object
2427230557Sjimharris)
2428230557Sjimharris{
2429230557Sjimharris   SCIC_SDS_PHY_T * this_phy;
2430230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
2431230557Sjimharris
2432230557Sjimharris   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_RESETTING);
2433230557Sjimharris
2434230557Sjimharris   // The phy is being reset, therefore deactivate it from the port.
2435230557Sjimharris   // In the resetting state we don't notify the user regarding
2436230557Sjimharris   // link up and link down notifications.
2437230557Sjimharris   scic_sds_port_deactivate_phy(this_phy->owning_port, this_phy, FALSE);
2438230557Sjimharris
2439230557Sjimharris   if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
2440230557Sjimharris   {
2441230557Sjimharris      scu_link_layer_tx_hard_reset(this_phy);
2442230557Sjimharris   }
2443230557Sjimharris   else
2444230557Sjimharris   {
2445230557Sjimharris      // The SCU does not need to have a descrete reset state so just go back to
2446230557Sjimharris      // the starting state.
2447230557Sjimharris      sci_base_state_machine_change_state(
2448230557Sjimharris         &this_phy->parent.state_machine,
2449230557Sjimharris         SCI_BASE_PHY_STATE_STARTING
2450230557Sjimharris      );
2451230557Sjimharris   }
2452230557Sjimharris}
2453230557Sjimharris
2454230557Sjimharris/**
2455230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
2456230557Sjimharris * entering the SCI_BASE_PHY_STATE_FINAL.
2457230557Sjimharris *    - This function sets the state handlers for the phy object base state
2458230557Sjimharris * machine final state.
2459230557Sjimharris *
2460230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2461230557Sjimharris *       SCIC_SDS_PHY object.
2462230557Sjimharris *
2463230557Sjimharris * @return none
2464230557Sjimharris */
2465230557Sjimharrisstatic
2466230557Sjimharrisvoid scic_sds_phy_final_state_enter(
2467230557Sjimharris   SCI_BASE_OBJECT_T *object
2468230557Sjimharris)
2469230557Sjimharris{
2470230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
2471230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
2472230557Sjimharris
2473230557Sjimharris   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_FINAL);
2474230557Sjimharris
2475230557Sjimharris   // Nothing to do here
2476230557Sjimharris}
2477230557Sjimharris
2478230557Sjimharris// ---------------------------------------------------------------------------
2479230557Sjimharris
2480230557SjimharrisSCI_BASE_STATE_T scic_sds_phy_state_table[SCI_BASE_PHY_MAX_STATES] =
2481230557Sjimharris{
2482230557Sjimharris   {
2483230557Sjimharris      SCI_BASE_PHY_STATE_INITIAL,
2484230557Sjimharris      scic_sds_phy_initial_state_enter,
2485230557Sjimharris      NULL,
2486230557Sjimharris   },
2487230557Sjimharris   {
2488230557Sjimharris      SCI_BASE_PHY_STATE_STOPPED,
2489230557Sjimharris      scic_sds_phy_stopped_state_enter,
2490230557Sjimharris      NULL,
2491230557Sjimharris   },
2492230557Sjimharris   {
2493230557Sjimharris      SCI_BASE_PHY_STATE_STARTING,
2494230557Sjimharris      scic_sds_phy_starting_state_enter,
2495230557Sjimharris      NULL,
2496230557Sjimharris   },
2497230557Sjimharris   {
2498230557Sjimharris      SCI_BASE_PHY_STATE_READY,
2499230557Sjimharris      scic_sds_phy_ready_state_enter,
2500230557Sjimharris      scic_sds_phy_ready_state_exit,
2501230557Sjimharris   },
2502230557Sjimharris   {
2503230557Sjimharris      SCI_BASE_PHY_STATE_RESETTING,
2504230557Sjimharris      scic_sds_phy_resetting_state_enter,
2505230557Sjimharris      NULL,
2506230557Sjimharris   },
2507230557Sjimharris   {
2508230557Sjimharris      SCI_BASE_PHY_STATE_FINAL,
2509230557Sjimharris      scic_sds_phy_final_state_enter,
2510230557Sjimharris      NULL,
2511230557Sjimharris   }
2512230557Sjimharris};
2513230557Sjimharris
2514230557Sjimharris//******************************************************************************
2515230557Sjimharris//* PHY STARTING SUB-STATE MACHINE
2516230557Sjimharris//******************************************************************************
2517230557Sjimharris
2518230557Sjimharris//*****************************************************************************
2519230557Sjimharris//* SCIC SDS PHY HELPER FUNCTIONS
2520230557Sjimharris//*****************************************************************************
2521230557Sjimharris
2522230557Sjimharris
2523230557Sjimharris/**
2524230557Sjimharris * This method continues the link training for the phy as if it were a SAS PHY
2525230557Sjimharris * instead of a SATA PHY. This is done because the completion queue had a SAS
2526230557Sjimharris * PHY DETECTED event when the state machine was expecting a SATA PHY event.
2527230557Sjimharris *
2528230557Sjimharris * @param[in] this_phy The phy object that received SAS PHY DETECTED.
2529230557Sjimharris *
2530230557Sjimharris * @return none
2531230557Sjimharris */
2532230557Sjimharrisstatic
2533230557Sjimharrisvoid scic_sds_phy_start_sas_link_training(
2534230557Sjimharris   SCIC_SDS_PHY_T * this_phy
2535230557Sjimharris)
2536230557Sjimharris{
2537230557Sjimharris   U32 phy_control;
2538230557Sjimharris
2539230557Sjimharris   phy_control = SCU_SAS_PCFG_READ(this_phy);
2540230557Sjimharris   phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD);
2541230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, phy_control);
2542230557Sjimharris
2543230557Sjimharris   sci_base_state_machine_change_state(
2544230557Sjimharris      &this_phy->starting_substate_machine,
2545230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
2546230557Sjimharris   );
2547230557Sjimharris
2548230557Sjimharris   this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS;
2549230557Sjimharris}
2550230557Sjimharris
2551230557Sjimharris/**
2552230557Sjimharris * This method continues the link training for the phy as if it were a SATA
2553230557Sjimharris * PHY instead of a SAS PHY.  This is done because the completion queue had a
2554230557Sjimharris * SATA SPINUP HOLD event when the state machine was expecting a SAS PHY
2555230557Sjimharris * event.
2556230557Sjimharris *
2557230557Sjimharris * @param[in] this_phy The phy object that received a SATA SPINUP HOLD event
2558230557Sjimharris *
2559230557Sjimharris * @return none
2560230557Sjimharris */
2561230557Sjimharrisstatic
2562230557Sjimharrisvoid scic_sds_phy_start_sata_link_training(
2563230557Sjimharris   SCIC_SDS_PHY_T * this_phy
2564230557Sjimharris)
2565230557Sjimharris{
2566230557Sjimharris   sci_base_state_machine_change_state(
2567230557Sjimharris      &this_phy->starting_substate_machine,
2568230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER
2569230557Sjimharris   );
2570230557Sjimharris
2571230557Sjimharris   this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
2572230557Sjimharris}
2573230557Sjimharris
2574230557Sjimharris/**
2575230557Sjimharris * @brief This method performs processing common to all protocols upon
2576230557Sjimharris *        completion of link training.
2577230557Sjimharris *
2578230557Sjimharris * @param[in,out] this_phy This parameter specifies the phy object for which
2579230557Sjimharris *                link training has completed.
2580230557Sjimharris * @param[in]     max_link_rate This parameter specifies the maximum link
2581230557Sjimharris *                rate to be associated with this phy.
2582230557Sjimharris * @param[in]     next_state This parameter specifies the next state for the
2583230557Sjimharris *                phy's starting sub-state machine.
2584230557Sjimharris *
2585230557Sjimharris * @return none
2586230557Sjimharris */
2587230557Sjimharrisstatic
2588230557Sjimharrisvoid scic_sds_phy_complete_link_training(
2589230557Sjimharris   SCIC_SDS_PHY_T *   this_phy,
2590230557Sjimharris   SCI_SAS_LINK_RATE  max_link_rate,
2591230557Sjimharris   U32                next_state
2592230557Sjimharris)
2593230557Sjimharris{
2594230557Sjimharris   this_phy->max_negotiated_speed = max_link_rate;
2595230557Sjimharris
2596230557Sjimharris   sci_base_state_machine_change_state(
2597230557Sjimharris      scic_sds_phy_get_starting_substate_machine(this_phy), next_state
2598230557Sjimharris   );
2599230557Sjimharris}
2600230557Sjimharris
2601230557Sjimharris/**
2602230557Sjimharris * This method restarts the SCIC_SDS_PHY objects base state machine in the
2603230557Sjimharris * starting state from any starting substate.
2604230557Sjimharris *
2605230557Sjimharris * @param[in] this_phy The SCIC_SDS_PHY object to restart.
2606230557Sjimharris *
2607230557Sjimharris * @return none
2608230557Sjimharris */
2609230557Sjimharrisvoid scic_sds_phy_restart_starting_state(
2610230557Sjimharris   SCIC_SDS_PHY_T *this_phy
2611230557Sjimharris)
2612230557Sjimharris{
2613230557Sjimharris   // Stop the current substate machine
2614230557Sjimharris   sci_base_state_machine_stop(
2615230557Sjimharris      scic_sds_phy_get_starting_substate_machine(this_phy)
2616230557Sjimharris   );
2617230557Sjimharris
2618230557Sjimharris   // Re-enter the base state machine starting state
2619230557Sjimharris   sci_base_state_machine_change_state(
2620230557Sjimharris      scic_sds_phy_get_base_state_machine(this_phy),
2621230557Sjimharris      SCI_BASE_PHY_STATE_STARTING
2622230557Sjimharris      );
2623230557Sjimharris}
2624230557Sjimharris
2625230557Sjimharris
2626230557Sjimharris//*****************************************************************************
2627230557Sjimharris//* SCIC SDS PHY general handlers
2628230557Sjimharris//*****************************************************************************
2629230557Sjimharris
2630230557Sjimharrisstatic
2631230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_general_stop_handler(
2632230557Sjimharris   SCI_BASE_PHY_T *phy
2633230557Sjimharris)
2634230557Sjimharris{
2635230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
2636230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)phy;
2637230557Sjimharris
2638230557Sjimharris   sci_base_state_machine_stop(
2639230557Sjimharris      &this_phy->starting_substate_machine
2640230557Sjimharris   );
2641230557Sjimharris
2642230557Sjimharris   sci_base_state_machine_change_state(
2643230557Sjimharris      &phy->state_machine,
2644230557Sjimharris      SCI_BASE_PHY_STATE_STOPPED
2645230557Sjimharris   );
2646230557Sjimharris
2647230557Sjimharris   return SCI_SUCCESS;
2648230557Sjimharris}
2649230557Sjimharris
2650230557Sjimharris//*****************************************************************************
2651230557Sjimharris//* SCIC SDS PHY EVENT_HANDLERS
2652230557Sjimharris//*****************************************************************************
2653230557Sjimharris
2654230557Sjimharris/**
2655230557Sjimharris * This method is called when an event notification is received for the phy
2656230557Sjimharris * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN.
2657230557Sjimharris *    - decode the event
2658230557Sjimharris *       - sas phy detected causes a state transition to the wait for speed
2659230557Sjimharris *         event notification.
2660230557Sjimharris *       - any other events log a warning message and set a failure status
2661230557Sjimharris *
2662230557Sjimharris * @param[in] phy This SCIC_SDS_PHY object which has received an event.
2663230557Sjimharris * @param[in] event_code This is the event code which the phy object is to
2664230557Sjimharris *       decode.
2665230557Sjimharris *
2666230557Sjimharris * @return SCI_STATUS
2667230557Sjimharris * @retval SCI_SUCCESS on any valid event notification
2668230557Sjimharris * @retval SCI_FAILURE on any unexpected event notifation
2669230557Sjimharris */
2670230557Sjimharrisstatic
2671230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_ossp_event_handler(
2672230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
2673230557Sjimharris   U32 event_code
2674230557Sjimharris)
2675230557Sjimharris{
2676230557Sjimharris   U32 result = SCI_SUCCESS;
2677230557Sjimharris
2678230557Sjimharris   switch (scu_get_event_code(event_code))
2679230557Sjimharris   {
2680230557Sjimharris   case SCU_EVENT_SAS_PHY_DETECTED:
2681230557Sjimharris      scic_sds_phy_start_sas_link_training(this_phy);
2682230557Sjimharris      this_phy->is_in_link_training = TRUE;
2683230557Sjimharris   break;
2684230557Sjimharris
2685230557Sjimharris   case SCU_EVENT_SATA_SPINUP_HOLD:
2686230557Sjimharris      scic_sds_phy_start_sata_link_training(this_phy);
2687230557Sjimharris      this_phy->is_in_link_training = TRUE;
2688230557Sjimharris   break;
2689230557Sjimharris
2690230557Sjimharris   default:
2691230557Sjimharris      SCIC_LOG_WARNING((
2692230557Sjimharris         sci_base_object_get_logger(this_phy),
2693230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
2694298931Spfg         "PHY starting substate machine received unexpected event_code %x\n",
2695230557Sjimharris         event_code
2696230557Sjimharris      ));
2697230557Sjimharris
2698230557Sjimharris      result = SCI_FAILURE;
2699230557Sjimharris   break;
2700230557Sjimharris   }
2701230557Sjimharris
2702230557Sjimharris   return result;
2703230557Sjimharris}
2704230557Sjimharris
2705230557Sjimharris/**
2706230557Sjimharris * This method is called when an event notification is received for the phy
2707230557Sjimharris * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN.
2708230557Sjimharris *    - decode the event
2709230557Sjimharris *       - sas phy detected returns us back to this state.
2710230557Sjimharris *       - speed event detected causes a state transition to the wait for iaf.
2711230557Sjimharris *       - identify timeout is an un-expected event and the state machine is
2712230557Sjimharris *         restarted.
2713230557Sjimharris *       - link failure events restart the starting state machine
2714230557Sjimharris *       - any other events log a warning message and set a failure status
2715230557Sjimharris *
2716230557Sjimharris * @param[in] phy This SCIC_SDS_PHY object which has received an event.
2717230557Sjimharris * @param[in] event_code This is the event code which the phy object is to
2718230557Sjimharris *       decode.
2719230557Sjimharris *
2720230557Sjimharris * @return SCI_STATUS
2721230557Sjimharris * @retval SCI_SUCCESS on any valid event notification
2722230557Sjimharris * @retval SCI_FAILURE on any unexpected event notifation
2723230557Sjimharris */
2724230557Sjimharrisstatic
2725230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler(
2726230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
2727230557Sjimharris   U32 event_code
2728230557Sjimharris)
2729230557Sjimharris{
2730230557Sjimharris   U32 result = SCI_SUCCESS;
2731230557Sjimharris
2732230557Sjimharris   switch (scu_get_event_code(event_code))
2733230557Sjimharris   {
2734230557Sjimharris   case SCU_EVENT_SAS_PHY_DETECTED:
2735230557Sjimharris      // Why is this being reported again by the controller?
2736230557Sjimharris      // We would re-enter this state so just stay here
2737230557Sjimharris   break;
2738230557Sjimharris
2739230557Sjimharris   case SCU_EVENT_SAS_15:
2740230557Sjimharris   case SCU_EVENT_SAS_15_SSC:
2741230557Sjimharris      scic_sds_phy_complete_link_training(
2742230557Sjimharris         this_phy, SCI_SAS_150_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
2743230557Sjimharris      );
2744230557Sjimharris   break;
2745230557Sjimharris
2746230557Sjimharris   case SCU_EVENT_SAS_30:
2747230557Sjimharris   case SCU_EVENT_SAS_30_SSC:
2748230557Sjimharris      scic_sds_phy_complete_link_training(
2749230557Sjimharris         this_phy, SCI_SAS_300_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
2750230557Sjimharris      );
2751230557Sjimharris   break;
2752230557Sjimharris
2753230557Sjimharris   case SCU_EVENT_SAS_60:
2754230557Sjimharris   case SCU_EVENT_SAS_60_SSC:
2755230557Sjimharris      scic_sds_phy_complete_link_training(
2756230557Sjimharris         this_phy, SCI_SAS_600_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
2757230557Sjimharris      );
2758230557Sjimharris   break;
2759230557Sjimharris
2760230557Sjimharris   case SCU_EVENT_SATA_SPINUP_HOLD:
2761230557Sjimharris      // We were doing SAS PHY link training and received a SATA PHY event
2762230557Sjimharris      // continue OOB/SN as if this were a SATA PHY
2763230557Sjimharris      scic_sds_phy_start_sata_link_training(this_phy);
2764230557Sjimharris   break;
2765230557Sjimharris
2766230557Sjimharris   case SCU_EVENT_LINK_FAILURE:
2767230557Sjimharris      // Link failure change state back to the starting state
2768230557Sjimharris      scic_sds_phy_restart_starting_state(this_phy);
2769230557Sjimharris   break;
2770230557Sjimharris
2771230557Sjimharris   default:
2772230557Sjimharris      SCIC_LOG_WARNING((
2773230557Sjimharris         sci_base_object_get_logger(this_phy),
2774230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
2775298931Spfg         "PHY starting substate machine received unexpected event_code %x\n",
2776230557Sjimharris         event_code
2777230557Sjimharris      ));
2778230557Sjimharris
2779230557Sjimharris      result = SCI_FAILURE;
2780230557Sjimharris   break;
2781230557Sjimharris   }
2782230557Sjimharris
2783230557Sjimharris   return result;
2784230557Sjimharris}
2785230557Sjimharris
2786230557Sjimharris/**
2787230557Sjimharris * This method is called when an event notification is received for the phy
2788230557Sjimharris * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF.
2789230557Sjimharris *    - decode the event
2790230557Sjimharris *       - sas phy detected event backs up the state machine to the await
2791230557Sjimharris *         speed notification.
2792230557Sjimharris *       - identify timeout is an un-expected event and the state machine is
2793230557Sjimharris *         restarted.
2794230557Sjimharris *       - link failure events restart the starting state machine
2795230557Sjimharris *       - any other events log a warning message and set a failure status
2796230557Sjimharris *
2797230557Sjimharris * @param[in] phy This SCIC_SDS_PHY object which has received an event.
2798230557Sjimharris * @param[in] event_code This is the event code which the phy object is to
2799230557Sjimharris *       decode.
2800230557Sjimharris *
2801230557Sjimharris * @return SCI_STATUS
2802230557Sjimharris * @retval SCI_SUCCESS on any valid event notification
2803230557Sjimharris * @retval SCI_FAILURE on any unexpected event notifation
2804230557Sjimharris */
2805230557Sjimharrisstatic
2806230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_iaf_uf_event_handler(
2807230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
2808230557Sjimharris   U32 event_code
2809230557Sjimharris)
2810230557Sjimharris{
2811230557Sjimharris   U32 result = SCI_SUCCESS;
2812230557Sjimharris
2813230557Sjimharris   switch (scu_get_event_code(event_code))
2814230557Sjimharris   {
2815230557Sjimharris   case SCU_EVENT_SAS_PHY_DETECTED:
2816230557Sjimharris      // Backup the state machine
2817230557Sjimharris      scic_sds_phy_start_sas_link_training(this_phy);
2818230557Sjimharris      break;
2819230557Sjimharris
2820230557Sjimharris   case SCU_EVENT_SATA_SPINUP_HOLD:
2821230557Sjimharris      // We were doing SAS PHY link training and received a SATA PHY event
2822230557Sjimharris      // continue OOB/SN as if this were a SATA PHY
2823230557Sjimharris      scic_sds_phy_start_sata_link_training(this_phy);
2824230557Sjimharris   break;
2825230557Sjimharris
2826230557Sjimharris   case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
2827230557Sjimharris   case SCU_EVENT_LINK_FAILURE:
2828230557Sjimharris   case SCU_EVENT_HARD_RESET_RECEIVED:
2829230557Sjimharris      // Start the oob/sn state machine over again
2830230557Sjimharris      scic_sds_phy_restart_starting_state(this_phy);
2831230557Sjimharris      break;
2832230557Sjimharris
2833230557Sjimharris   default:
2834230557Sjimharris      SCIC_LOG_WARNING((
2835230557Sjimharris         sci_base_object_get_logger(this_phy),
2836230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
2837298931Spfg         "PHY starting substate machine received unexpected event_code %x\n",
2838230557Sjimharris         event_code
2839230557Sjimharris      ));
2840230557Sjimharris
2841230557Sjimharris      result = SCI_FAILURE;
2842230557Sjimharris      break;
2843230557Sjimharris   }
2844230557Sjimharris
2845230557Sjimharris   return result;
2846230557Sjimharris}
2847230557Sjimharris
2848230557Sjimharris/**
2849230557Sjimharris * This method is called when an event notification is received for the phy
2850230557Sjimharris * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_POWER.
2851230557Sjimharris *    - decode the event
2852230557Sjimharris *       - link failure events restart the starting state machine
2853230557Sjimharris *       - any other events log a warning message and set a failure status
2854230557Sjimharris *
2855230557Sjimharris * @param[in] phy This SCIC_SDS_PHY object which has received an event.
2856230557Sjimharris * @param[in] event_code This is the event code which the phy object is to
2857230557Sjimharris *       decode.
2858230557Sjimharris *
2859230557Sjimharris * @return SCI_STATUS
2860230557Sjimharris * @retval SCI_SUCCESS on a link failure event
2861230557Sjimharris * @retval SCI_FAILURE on any unexpected event notifation
2862230557Sjimharris */
2863230557Sjimharrisstatic
2864230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_sas_power_event_handler(
2865230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
2866230557Sjimharris   U32 event_code
2867230557Sjimharris)
2868230557Sjimharris{
2869230557Sjimharris   U32 result = SCI_SUCCESS;
2870230557Sjimharris
2871230557Sjimharris   switch (scu_get_event_code(event_code))
2872230557Sjimharris   {
2873230557Sjimharris   case SCU_EVENT_LINK_FAILURE:
2874230557Sjimharris      // Link failure change state back to the starting state
2875230557Sjimharris      scic_sds_phy_restart_starting_state(this_phy);
2876230557Sjimharris      break;
2877230557Sjimharris
2878230557Sjimharris   default:
2879230557Sjimharris      SCIC_LOG_WARNING((
2880230557Sjimharris         sci_base_object_get_logger(this_phy),
2881230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
2882298931Spfg         "PHY starting substate machine received unexpected event_code %x\n",
2883230557Sjimharris         event_code
2884230557Sjimharris      ));
2885230557Sjimharris
2886230557Sjimharris      result = SCI_FAILURE;
2887230557Sjimharris      break;
2888230557Sjimharris   }
2889230557Sjimharris
2890230557Sjimharris   return result;
2891230557Sjimharris}
2892230557Sjimharris
2893230557Sjimharris/**
2894230557Sjimharris * This method is called when an event notification is received for the phy
2895230557Sjimharris * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER.
2896230557Sjimharris *    - decode the event
2897230557Sjimharris *       - link failure events restart the starting state machine
2898230557Sjimharris *       - sata spinup hold events are ignored since they are expected
2899230557Sjimharris *       - any other events log a warning message and set a failure status
2900230557Sjimharris *
2901230557Sjimharris * @param[in] phy This SCIC_SDS_PHY object which has received an event.
2902230557Sjimharris * @param[in] event_code This is the event code which the phy object is to
2903230557Sjimharris *       decode.
2904230557Sjimharris *
2905230557Sjimharris * @return SCI_STATUS
2906230557Sjimharris * @retval SCI_SUCCESS on a link failure event
2907230557Sjimharris * @retval SCI_FAILURE on any unexpected event notifation
2908230557Sjimharris */
2909230557Sjimharrisstatic
2910230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_sata_power_event_handler(
2911230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
2912230557Sjimharris   U32 event_code
2913230557Sjimharris)
2914230557Sjimharris{
2915230557Sjimharris   U32 result = SCI_SUCCESS;
2916230557Sjimharris
2917230557Sjimharris   switch (scu_get_event_code(event_code))
2918230557Sjimharris   {
2919230557Sjimharris   case SCU_EVENT_LINK_FAILURE:
2920230557Sjimharris      // Link failure change state back to the starting state
2921230557Sjimharris      scic_sds_phy_restart_starting_state(this_phy);
2922230557Sjimharris      break;
2923230557Sjimharris
2924230557Sjimharris   case SCU_EVENT_SATA_SPINUP_HOLD:
2925230557Sjimharris      // These events are received every 10ms and are expected while in this state
2926230557Sjimharris      break;
2927230557Sjimharris
2928230557Sjimharris   case SCU_EVENT_SAS_PHY_DETECTED:
2929230557Sjimharris      // There has been a change in the phy type before OOB/SN for the
2930230557Sjimharris      // SATA finished start down the SAS link traning path.
2931230557Sjimharris      scic_sds_phy_start_sas_link_training(this_phy);
2932230557Sjimharris   break;
2933230557Sjimharris
2934230557Sjimharris   default:
2935230557Sjimharris      SCIC_LOG_WARNING((
2936230557Sjimharris         sci_base_object_get_logger(this_phy),
2937230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
2938298931Spfg         "PHY starting substate machine received unexpected event_code %x\n",
2939230557Sjimharris         event_code
2940230557Sjimharris      ));
2941230557Sjimharris
2942230557Sjimharris      result = SCI_FAILURE;
2943230557Sjimharris      break;
2944230557Sjimharris   }
2945230557Sjimharris
2946230557Sjimharris   return result;
2947230557Sjimharris}
2948230557Sjimharris
2949230557Sjimharris/**
2950230557Sjimharris * This method is called when an event notification is received for the phy
2951230557Sjimharris * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN.
2952230557Sjimharris *    - decode the event
2953230557Sjimharris *       - link failure events restart the starting state machine
2954230557Sjimharris *       - sata spinup hold events are ignored since they are expected
2955230557Sjimharris *       - sata phy detected event change to the wait speed event
2956230557Sjimharris *       - any other events log a warning message and set a failure status
2957230557Sjimharris *
2958230557Sjimharris * @param[in] phy This SCIC_SDS_PHY object which has received an event.
2959230557Sjimharris * @param[in] event_code This is the event code which the phy object is to
2960230557Sjimharris *       decode.
2961230557Sjimharris *
2962230557Sjimharris * @return SCI_STATUS
2963230557Sjimharris * @retval SCI_SUCCESS on a link failure event
2964230557Sjimharris * @retval SCI_FAILURE on any unexpected event notifation
2965230557Sjimharris */
2966230557Sjimharrisstatic
2967230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_sata_phy_event_handler(
2968230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
2969230557Sjimharris   U32 event_code
2970230557Sjimharris)
2971230557Sjimharris{
2972230557Sjimharris   U32 result = SCI_SUCCESS;
2973230557Sjimharris
2974230557Sjimharris   switch (scu_get_event_code(event_code))
2975230557Sjimharris   {
2976230557Sjimharris   case SCU_EVENT_LINK_FAILURE:
2977230557Sjimharris      // Link failure change state back to the starting state
2978230557Sjimharris      scic_sds_phy_restart_starting_state(this_phy);
2979230557Sjimharris      break;
2980230557Sjimharris
2981230557Sjimharris   case SCU_EVENT_SATA_SPINUP_HOLD:
2982230557Sjimharris      // These events might be received since we dont know how many may be in
2983230557Sjimharris      // the completion queue while waiting for power
2984230557Sjimharris      break;
2985230557Sjimharris
2986230557Sjimharris   case SCU_EVENT_SATA_PHY_DETECTED:
2987230557Sjimharris      this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
2988230557Sjimharris
2989230557Sjimharris      // We have received the SATA PHY notification change state
2990230557Sjimharris      sci_base_state_machine_change_state(
2991230557Sjimharris         scic_sds_phy_get_starting_substate_machine(this_phy),
2992230557Sjimharris         SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
2993230557Sjimharris         );
2994230557Sjimharris      break;
2995230557Sjimharris
2996230557Sjimharris   case SCU_EVENT_SAS_PHY_DETECTED:
2997230557Sjimharris      // There has been a change in the phy type before OOB/SN for the
2998230557Sjimharris      // SATA finished start down the SAS link traning path.
2999230557Sjimharris      scic_sds_phy_start_sas_link_training(this_phy);
3000230557Sjimharris   break;
3001230557Sjimharris
3002230557Sjimharris   default:
3003230557Sjimharris      SCIC_LOG_WARNING((
3004230557Sjimharris         sci_base_object_get_logger(this_phy),
3005230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
3006298931Spfg         "PHY starting substate machine received unexpected event_code %x\n",
3007230557Sjimharris         event_code
3008230557Sjimharris      ));
3009230557Sjimharris
3010230557Sjimharris      result = SCI_FAILURE;
3011230557Sjimharris      break;
3012230557Sjimharris   }
3013230557Sjimharris
3014230557Sjimharris   return result;
3015230557Sjimharris}
3016230557Sjimharris
3017230557Sjimharris/**
3018230557Sjimharris * This method is called when an event notification is received for the phy
3019230557Sjimharris * object when in the state
3020230557Sjimharris * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
3021230557Sjimharris *    - decode the event
3022230557Sjimharris *       - sata phy detected returns us back to this state.
3023230557Sjimharris *       - speed event detected causes a state transition to the wait for
3024230557Sjimharris *         signature.
3025230557Sjimharris *       - link failure events restart the starting state machine
3026230557Sjimharris *       - any other events log a warning message and set a failure status
3027230557Sjimharris *
3028230557Sjimharris * @param[in] phy This SCIC_SDS_PHY object which has received an event.
3029230557Sjimharris * @param[in] event_code This is the event code which the phy object is to
3030230557Sjimharris *       decode.
3031230557Sjimharris *
3032230557Sjimharris * @return SCI_STATUS
3033230557Sjimharris * @retval SCI_SUCCESS on any valid event notification
3034230557Sjimharris * @retval SCI_FAILURE on any unexpected event notifation
3035230557Sjimharris */
3036230557Sjimharrisstatic
3037230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_sata_speed_event_handler(
3038230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
3039230557Sjimharris   U32 event_code
3040230557Sjimharris)
3041230557Sjimharris{
3042230557Sjimharris   U32 result = SCI_SUCCESS;
3043230557Sjimharris
3044230557Sjimharris   switch (scu_get_event_code(event_code))
3045230557Sjimharris   {
3046230557Sjimharris   case SCU_EVENT_SATA_PHY_DETECTED:
3047230557Sjimharris      // The hardware reports multiple SATA PHY detected events
3048230557Sjimharris      // ignore the extras
3049230557Sjimharris   break;
3050230557Sjimharris
3051230557Sjimharris   case SCU_EVENT_SATA_15:
3052230557Sjimharris   case SCU_EVENT_SATA_15_SSC:
3053230557Sjimharris      scic_sds_phy_complete_link_training(
3054230557Sjimharris         this_phy,
3055230557Sjimharris         SCI_SAS_150_GB,
3056230557Sjimharris         SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
3057230557Sjimharris      );
3058230557Sjimharris   break;
3059230557Sjimharris
3060230557Sjimharris   case SCU_EVENT_SATA_30:
3061230557Sjimharris   case SCU_EVENT_SATA_30_SSC:
3062230557Sjimharris      scic_sds_phy_complete_link_training(
3063230557Sjimharris         this_phy,
3064230557Sjimharris         SCI_SAS_300_GB,
3065230557Sjimharris         SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
3066230557Sjimharris      );
3067230557Sjimharris   break;
3068230557Sjimharris
3069230557Sjimharris   case SCU_EVENT_SATA_60:
3070230557Sjimharris   case SCU_EVENT_SATA_60_SSC:
3071230557Sjimharris      scic_sds_phy_complete_link_training(
3072230557Sjimharris         this_phy,
3073230557Sjimharris         SCI_SAS_600_GB,
3074230557Sjimharris         SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
3075230557Sjimharris      );
3076230557Sjimharris   break;
3077230557Sjimharris
3078230557Sjimharris   case SCU_EVENT_LINK_FAILURE:
3079230557Sjimharris      // Link failure change state back to the starting state
3080230557Sjimharris      scic_sds_phy_restart_starting_state(this_phy);
3081230557Sjimharris   break;
3082230557Sjimharris
3083230557Sjimharris   case SCU_EVENT_SAS_PHY_DETECTED:
3084230557Sjimharris      // There has been a change in the phy type before OOB/SN for the
3085230557Sjimharris      // SATA finished start down the SAS link traning path.
3086230557Sjimharris      scic_sds_phy_start_sas_link_training(this_phy);
3087230557Sjimharris   break;
3088230557Sjimharris
3089230557Sjimharris   default:
3090230557Sjimharris      SCIC_LOG_WARNING((
3091230557Sjimharris         sci_base_object_get_logger(this_phy),
3092230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
3093298931Spfg         "PHY starting substate machine received unexpected event_code %x\n",
3094230557Sjimharris         event_code
3095230557Sjimharris      ));
3096230557Sjimharris
3097230557Sjimharris      result = SCI_FAILURE;
3098230557Sjimharris   break;
3099230557Sjimharris   }
3100230557Sjimharris
3101230557Sjimharris   return result;
3102230557Sjimharris}
3103230557Sjimharris
3104230557Sjimharris/**
3105230557Sjimharris * This method is called when an event notification is received for the phy
3106230557Sjimharris * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
3107230557Sjimharris *    - decode the event
3108230557Sjimharris *       - sas phy detected event backs up the state machine to the await
3109230557Sjimharris *         speed notification.
3110230557Sjimharris *       - identify timeout is an un-expected event and the state machine is
3111230557Sjimharris *         restarted.
3112230557Sjimharris *       - link failure events restart the starting state machine
3113230557Sjimharris *       - any other events log a warning message and set a failure status
3114230557Sjimharris *
3115230557Sjimharris * @param[in] phy This SCIC_SDS_PHY object which has received an event.
3116230557Sjimharris * @param[in] event_code This is the event code which the phy object is to
3117230557Sjimharris *       decode.
3118230557Sjimharris *
3119230557Sjimharris * @return SCI_STATUS
3120230557Sjimharris * @retval SCI_SUCCESS on any valid event notification
3121230557Sjimharris * @retval SCI_FAILURE on any unexpected event notifation
3122230557Sjimharris */
3123230557Sjimharrisstatic
3124230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_sig_fis_event_handler(
3125230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
3126230557Sjimharris   U32 event_code
3127230557Sjimharris)
3128230557Sjimharris{
3129230557Sjimharris   U32 result = SCI_SUCCESS;
3130230557Sjimharris
3131230557Sjimharris   switch (scu_get_event_code(event_code))
3132230557Sjimharris   {
3133230557Sjimharris   case SCU_EVENT_SATA_PHY_DETECTED:
3134230557Sjimharris      // Backup the state machine
3135230557Sjimharris      sci_base_state_machine_change_state(
3136230557Sjimharris         scic_sds_phy_get_starting_substate_machine(this_phy),
3137230557Sjimharris         SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
3138230557Sjimharris         );
3139230557Sjimharris      break;
3140230557Sjimharris
3141230557Sjimharris   case SCU_EVENT_LINK_FAILURE:
3142230557Sjimharris      // Link failure change state back to the starting state
3143230557Sjimharris      scic_sds_phy_restart_starting_state(this_phy);
3144230557Sjimharris      break;
3145230557Sjimharris
3146230557Sjimharris   default:
3147230557Sjimharris      SCIC_LOG_WARNING((
3148230557Sjimharris         sci_base_object_get_logger(this_phy),
3149230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
3150298931Spfg         "PHY starting substate machine received unexpected event_code %x\n",
3151230557Sjimharris         event_code
3152230557Sjimharris      ));
3153230557Sjimharris
3154230557Sjimharris      result = SCI_FAILURE;
3155230557Sjimharris      break;
3156230557Sjimharris   }
3157230557Sjimharris
3158230557Sjimharris   return result;
3159230557Sjimharris}
3160230557Sjimharris
3161230557Sjimharris
3162230557Sjimharris//*****************************************************************************
3163230557Sjimharris//*  SCIC SDS PHY FRAME_HANDLERS
3164230557Sjimharris//*****************************************************************************
3165230557Sjimharris
3166230557Sjimharris/**
3167230557Sjimharris * This method decodes the unsolicited frame when the SCIC_SDS_PHY is in the
3168230557Sjimharris * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF.
3169230557Sjimharris *    - Get the UF Header
3170230557Sjimharris *    - If the UF is an IAF
3171230557Sjimharris *       - Copy IAF data to local phy object IAF data buffer.
3172230557Sjimharris *       - Change starting substate to wait power.
3173230557Sjimharris *    - else
3174230557Sjimharris *       - log warning message of unexpected unsolicted frame
3175230557Sjimharris *    - release frame buffer
3176230557Sjimharris *
3177230557Sjimharris * @param[in] phy This is SCIC_SDS_PHY object which is being requested to
3178230557Sjimharris *       decode the frame data.
3179230557Sjimharris * @param[in] frame_index This is the index of the unsolicited frame which was
3180230557Sjimharris *       received for this phy.
3181230557Sjimharris *
3182230557Sjimharris * @return SCI_STATUS
3183230557Sjimharris * @retval SCI_SUCCESS
3184230557Sjimharris */
3185230557Sjimharrisstatic
3186230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_iaf_uf_frame_handler(
3187230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
3188230557Sjimharris   U32            frame_index
3189230557Sjimharris)
3190230557Sjimharris{
3191230557Sjimharris   SCI_STATUS                        result;
3192230557Sjimharris   U32                              *frame_words;
3193230557Sjimharris   SCI_SAS_IDENTIFY_ADDRESS_FRAME_T *identify_frame;
3194230557Sjimharris
3195230557Sjimharris   result = scic_sds_unsolicited_frame_control_get_header(
3196230557Sjimharris               &(scic_sds_phy_get_controller(this_phy)->uf_control),
3197230557Sjimharris               frame_index,
3198230557Sjimharris               (void **)&frame_words);
3199230557Sjimharris
3200230557Sjimharris   if (result != SCI_SUCCESS)
3201230557Sjimharris   {
3202230557Sjimharris      return result;
3203230557Sjimharris   }
3204230557Sjimharris
3205230557Sjimharris   frame_words[0] = SCIC_SWAP_DWORD(frame_words[0]);
3206230557Sjimharris   identify_frame = (SCI_SAS_IDENTIFY_ADDRESS_FRAME_T *)frame_words;
3207230557Sjimharris
3208230557Sjimharris   if (identify_frame->address_frame_type == 0)
3209230557Sjimharris   {
3210230557Sjimharris      // Byte swap the rest of the frame so we can make
3211230557Sjimharris      // a copy of the buffer
3212230557Sjimharris      frame_words[1] = SCIC_SWAP_DWORD(frame_words[1]);
3213230557Sjimharris      frame_words[2] = SCIC_SWAP_DWORD(frame_words[2]);
3214230557Sjimharris      frame_words[3] = SCIC_SWAP_DWORD(frame_words[3]);
3215230557Sjimharris      frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]);
3216230557Sjimharris      frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]);
3217230557Sjimharris
3218230557Sjimharris      memcpy(
3219230557Sjimharris         &this_phy->phy_type.sas.identify_address_frame_buffer,
3220230557Sjimharris         identify_frame,
3221230557Sjimharris         sizeof(SCI_SAS_IDENTIFY_ADDRESS_FRAME_T)
3222230557Sjimharris      );
3223230557Sjimharris
3224230557Sjimharris      if (identify_frame->protocols.u.bits.smp_target)
3225230557Sjimharris      {
3226230557Sjimharris         // We got the IAF for an expander PHY go to the final state since
3227230557Sjimharris         // there are no power requirements for expander phys.
3228230557Sjimharris         sci_base_state_machine_change_state(
3229230557Sjimharris            scic_sds_phy_get_starting_substate_machine(this_phy),
3230230557Sjimharris            SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
3231230557Sjimharris         );
3232230557Sjimharris      }
3233230557Sjimharris      else
3234230557Sjimharris      {
3235230557Sjimharris         // We got the IAF we can now go to the await spinup semaphore state
3236230557Sjimharris         sci_base_state_machine_change_state(
3237230557Sjimharris            scic_sds_phy_get_starting_substate_machine(this_phy),
3238230557Sjimharris            SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
3239230557Sjimharris         );
3240230557Sjimharris      }
3241230557Sjimharris
3242230557Sjimharris      result = SCI_SUCCESS;
3243230557Sjimharris   }
3244230557Sjimharris   else
3245230557Sjimharris   {
3246230557Sjimharris      SCIC_LOG_WARNING((
3247230557Sjimharris         sci_base_object_get_logger(this_phy),
3248230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_UNSOLICITED_FRAMES,
3249298931Spfg         "PHY starting substate machine received unexpected frame id %x\n",
3250230557Sjimharris         frame_index
3251230557Sjimharris      ));
3252230557Sjimharris   }
3253230557Sjimharris
3254230557Sjimharris   // Regardless of the result release this frame since we are done with it
3255230557Sjimharris   scic_sds_controller_release_frame(
3256230557Sjimharris      scic_sds_phy_get_controller(this_phy), frame_index
3257230557Sjimharris      );
3258230557Sjimharris
3259230557Sjimharris   return result;
3260230557Sjimharris}
3261230557Sjimharris
3262230557Sjimharris/**
3263230557Sjimharris * This method decodes the unsolicited frame when the SCIC_SDS_PHY is in the
3264230557Sjimharris * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
3265230557Sjimharris *    - Get the UF Header
3266230557Sjimharris *    - If the UF is an SIGNATURE FIS
3267230557Sjimharris *       - Copy IAF data to local phy object SIGNATURE FIS data buffer.
3268230557Sjimharris *    - else
3269230557Sjimharris *       - log warning message of unexpected unsolicted frame
3270230557Sjimharris *    - release frame buffer
3271230557Sjimharris *
3272230557Sjimharris * @param[in] phy This is SCIC_SDS_PHY object which is being requested to
3273230557Sjimharris *       decode the frame data.
3274230557Sjimharris * @param[in] frame_index This is the index of the unsolicited frame which was
3275230557Sjimharris *       received for this phy.
3276230557Sjimharris *
3277230557Sjimharris * @return SCI_STATUS
3278230557Sjimharris * @retval SCI_SUCCESS
3279230557Sjimharris *
3280230557Sjimharris * @todo Must decode the SIGNATURE FIS data
3281230557Sjimharris */
3282230557Sjimharrisstatic
3283230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_sig_fis_frame_handler(
3284230557Sjimharris   SCIC_SDS_PHY_T *this_phy,
3285230557Sjimharris   U32            frame_index
3286230557Sjimharris)
3287230557Sjimharris{
3288230557Sjimharris   SCI_STATUS          result;
3289230557Sjimharris   U32               * frame_words;
3290230557Sjimharris   SATA_FIS_HEADER_T * fis_frame_header;
3291230557Sjimharris   U32               * fis_frame_data;
3292230557Sjimharris
3293230557Sjimharris   result = scic_sds_unsolicited_frame_control_get_header(
3294230557Sjimharris               &(scic_sds_phy_get_controller(this_phy)->uf_control),
3295230557Sjimharris               frame_index,
3296230557Sjimharris               (void **)&frame_words);
3297230557Sjimharris
3298230557Sjimharris   if (result != SCI_SUCCESS)
3299230557Sjimharris   {
3300230557Sjimharris      return result;
3301230557Sjimharris   }
3302230557Sjimharris
3303230557Sjimharris   fis_frame_header = (SATA_FIS_HEADER_T *)frame_words;
3304230557Sjimharris
3305230557Sjimharris   if (
3306230557Sjimharris         (fis_frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
3307230557Sjimharris      && !(fis_frame_header->status & ATA_STATUS_REG_BSY_BIT)
3308230557Sjimharris      )
3309230557Sjimharris   {
3310230557Sjimharris      scic_sds_unsolicited_frame_control_get_buffer(
3311230557Sjimharris         &(scic_sds_phy_get_controller(this_phy)->uf_control),
3312230557Sjimharris         frame_index,
3313230557Sjimharris         (void **)&fis_frame_data
3314230557Sjimharris      );
3315230557Sjimharris
3316230557Sjimharris      scic_sds_controller_copy_sata_response(
3317230557Sjimharris         &this_phy->phy_type.sata.signature_fis_buffer,
3318230557Sjimharris         frame_words,
3319230557Sjimharris         fis_frame_data
3320230557Sjimharris      );
3321230557Sjimharris
3322230557Sjimharris      // We got the IAF we can now go to the await spinup semaphore state
3323230557Sjimharris      sci_base_state_machine_change_state(
3324230557Sjimharris         scic_sds_phy_get_starting_substate_machine(this_phy),
3325230557Sjimharris         SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
3326230557Sjimharris         );
3327230557Sjimharris
3328230557Sjimharris      result = SCI_SUCCESS;
3329230557Sjimharris   }
3330230557Sjimharris   else
3331230557Sjimharris   {
3332230557Sjimharris      SCIC_LOG_WARNING((
3333230557Sjimharris         sci_base_object_get_logger(this_phy),
3334230557Sjimharris         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_UNSOLICITED_FRAMES,
3335298931Spfg         "PHY starting substate machine received unexpected frame id %x\n",
3336230557Sjimharris         frame_index
3337230557Sjimharris      ));
3338230557Sjimharris   }
3339230557Sjimharris
3340230557Sjimharris   // Regardless of the result release this frame since we are done with it
3341230557Sjimharris   scic_sds_controller_release_frame(
3342230557Sjimharris      scic_sds_phy_get_controller(this_phy), frame_index
3343230557Sjimharris      );
3344230557Sjimharris
3345230557Sjimharris   return result;
3346230557Sjimharris}
3347230557Sjimharris
3348230557Sjimharris//*****************************************************************************
3349230557Sjimharris//* SCIC SDS PHY POWER_HANDLERS
3350230557Sjimharris//*****************************************************************************
3351230557Sjimharris
3352230557Sjimharris/**
3353230557Sjimharris * This method is called by the SCIC_SDS_CONTROLLER when the phy object is
3354230557Sjimharris * granted power.
3355230557Sjimharris *    - The notify enable spinups are turned on for this phy object
3356230557Sjimharris *    - The phy state machine is transitioned to the
3357230557Sjimharris *    SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL.
3358230557Sjimharris *
3359230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
3360230557Sjimharris *       SCIC_SDS_PHY object.
3361230557Sjimharris *
3362230557Sjimharris * @return SCI_STATUS
3363230557Sjimharris * @retval SCI_SUCCESS
3364230557Sjimharris */
3365230557Sjimharrisstatic
3366230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_sas_power_consume_power_handler(
3367230557Sjimharris   SCIC_SDS_PHY_T *this_phy
3368230557Sjimharris)
3369230557Sjimharris{
3370230557Sjimharris   U32 enable_spinup;
3371230557Sjimharris
3372230557Sjimharris   enable_spinup = SCU_SAS_ENSPINUP_READ(this_phy);
3373230557Sjimharris   enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE);
3374230557Sjimharris   SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup);
3375230557Sjimharris
3376230557Sjimharris   // Change state to the final state this substate machine has run to completion
3377230557Sjimharris   sci_base_state_machine_change_state(
3378230557Sjimharris      scic_sds_phy_get_starting_substate_machine(this_phy),
3379230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
3380230557Sjimharris      );
3381230557Sjimharris
3382230557Sjimharris   return SCI_SUCCESS;
3383230557Sjimharris}
3384230557Sjimharris
3385230557Sjimharris/**
3386230557Sjimharris * This method is called by the SCIC_SDS_CONTROLLER when the phy object is
3387230557Sjimharris * granted power.
3388230557Sjimharris *    - The phy state machine is transitioned to the
3389230557Sjimharris *    SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN.
3390230557Sjimharris *
3391230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
3392230557Sjimharris *       SCIC_SDS_PHY object.
3393230557Sjimharris *
3394230557Sjimharris * @return SCI_STATUS
3395230557Sjimharris * @retval SCI_SUCCESS
3396230557Sjimharris */
3397230557Sjimharrisstatic
3398230557SjimharrisSCI_STATUS scic_sds_phy_starting_substate_await_sata_power_consume_power_handler(
3399230557Sjimharris   SCIC_SDS_PHY_T *this_phy
3400230557Sjimharris)
3401230557Sjimharris{
3402230557Sjimharris   U32 scu_sas_pcfg_value;
3403230557Sjimharris
3404230557Sjimharris   // Release the spinup hold state and reset the OOB state machine
3405230557Sjimharris   scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
3406230557Sjimharris   scu_sas_pcfg_value &=
3407230557Sjimharris      ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE));
3408230557Sjimharris   scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
3409230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
3410230557Sjimharris
3411230557Sjimharris   // Now restart the OOB operation
3412230557Sjimharris   scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
3413230557Sjimharris   scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
3414230557Sjimharris   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
3415230557Sjimharris
3416230557Sjimharris   // Change state to the final state this substate machine has run to completion
3417230557Sjimharris   sci_base_state_machine_change_state(
3418230557Sjimharris      scic_sds_phy_get_starting_substate_machine(this_phy),
3419230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN
3420230557Sjimharris   );
3421230557Sjimharris
3422230557Sjimharris   return SCI_SUCCESS;
3423230557Sjimharris}
3424230557Sjimharris
3425230557Sjimharris// ---------------------------------------------------------------------------
3426230557Sjimharris
3427230557SjimharrisSCIC_SDS_PHY_STATE_HANDLER_T
3428230557Sjimharris   scic_sds_phy_starting_substate_handler_table[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] =
3429230557Sjimharris{
3430230557Sjimharris   // SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL
3431230557Sjimharris   {
3432230557Sjimharris      {
3433230557Sjimharris         scic_sds_phy_default_start_handler,
3434230557Sjimharris         scic_sds_phy_starting_substate_general_stop_handler,
3435230557Sjimharris         scic_sds_phy_default_reset_handler,
3436230557Sjimharris         scic_sds_phy_default_destroy_handler
3437230557Sjimharris      },
3438230557Sjimharris      scic_sds_phy_default_frame_handler,
3439230557Sjimharris      scic_sds_phy_default_event_handler,
3440230557Sjimharris      scic_sds_phy_default_consume_power_handler
3441230557Sjimharris   },
3442230557Sjimharris   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
3443230557Sjimharris   {
3444230557Sjimharris      {
3445230557Sjimharris         scic_sds_phy_default_start_handler,
3446230557Sjimharris         scic_sds_phy_starting_substate_general_stop_handler,
3447230557Sjimharris         scic_sds_phy_default_reset_handler,
3448230557Sjimharris         scic_sds_phy_default_destroy_handler
3449230557Sjimharris      },
3450230557Sjimharris      scic_sds_phy_default_frame_handler,
3451230557Sjimharris      scic_sds_phy_starting_substate_await_ossp_event_handler,
3452230557Sjimharris      scic_sds_phy_default_consume_power_handler
3453230557Sjimharris   },
3454230557Sjimharris   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
3455230557Sjimharris   {
3456230557Sjimharris      {
3457230557Sjimharris         scic_sds_phy_default_start_handler,
3458230557Sjimharris         scic_sds_phy_starting_substate_general_stop_handler,
3459230557Sjimharris         scic_sds_phy_default_reset_handler,
3460230557Sjimharris         scic_sds_phy_default_destroy_handler
3461230557Sjimharris      },
3462230557Sjimharris      scic_sds_phy_default_frame_handler,
3463230557Sjimharris      scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler,
3464230557Sjimharris      scic_sds_phy_default_consume_power_handler
3465230557Sjimharris   },
3466230557Sjimharris   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
3467230557Sjimharris   {
3468230557Sjimharris      {
3469230557Sjimharris         scic_sds_phy_default_start_handler,
3470230557Sjimharris         scic_sds_phy_default_stop_handler,
3471230557Sjimharris         scic_sds_phy_default_reset_handler,
3472230557Sjimharris         scic_sds_phy_default_destroy_handler
3473230557Sjimharris      },
3474230557Sjimharris      scic_sds_phy_starting_substate_await_iaf_uf_frame_handler,
3475230557Sjimharris      scic_sds_phy_starting_substate_await_iaf_uf_event_handler,
3476230557Sjimharris      scic_sds_phy_default_consume_power_handler
3477230557Sjimharris   },
3478230557Sjimharris   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
3479230557Sjimharris   {
3480230557Sjimharris      {
3481230557Sjimharris         scic_sds_phy_default_start_handler,
3482230557Sjimharris         scic_sds_phy_starting_substate_general_stop_handler,
3483230557Sjimharris         scic_sds_phy_default_reset_handler,
3484230557Sjimharris         scic_sds_phy_default_destroy_handler
3485230557Sjimharris      },
3486230557Sjimharris      scic_sds_phy_default_frame_handler,
3487230557Sjimharris      scic_sds_phy_starting_substate_await_sas_power_event_handler,
3488230557Sjimharris      scic_sds_phy_starting_substate_await_sas_power_consume_power_handler
3489230557Sjimharris   },
3490230557Sjimharris   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER,
3491230557Sjimharris   {
3492230557Sjimharris      {
3493230557Sjimharris         scic_sds_phy_default_start_handler,
3494230557Sjimharris         scic_sds_phy_starting_substate_general_stop_handler,
3495230557Sjimharris         scic_sds_phy_default_reset_handler,
3496230557Sjimharris         scic_sds_phy_default_destroy_handler
3497230557Sjimharris      },
3498230557Sjimharris      scic_sds_phy_default_frame_handler,
3499230557Sjimharris      scic_sds_phy_starting_substate_await_sata_power_event_handler,
3500230557Sjimharris      scic_sds_phy_starting_substate_await_sata_power_consume_power_handler
3501230557Sjimharris   },
3502230557Sjimharris   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN,
3503230557Sjimharris   {
3504230557Sjimharris      {
3505230557Sjimharris         scic_sds_phy_default_start_handler,
3506230557Sjimharris         scic_sds_phy_starting_substate_general_stop_handler,
3507230557Sjimharris         scic_sds_phy_default_reset_handler,
3508230557Sjimharris         scic_sds_phy_default_destroy_handler
3509230557Sjimharris      },
3510230557Sjimharris      scic_sds_phy_default_frame_handler,
3511230557Sjimharris      scic_sds_phy_starting_substate_await_sata_phy_event_handler,
3512230557Sjimharris      scic_sds_phy_default_consume_power_handler
3513230557Sjimharris   },
3514230557Sjimharris   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN,
3515230557Sjimharris   {
3516230557Sjimharris      {
3517230557Sjimharris         scic_sds_phy_default_start_handler,
3518230557Sjimharris         scic_sds_phy_starting_substate_general_stop_handler,
3519230557Sjimharris         scic_sds_phy_default_reset_handler,
3520230557Sjimharris         scic_sds_phy_default_destroy_handler
3521230557Sjimharris      },
3522230557Sjimharris      scic_sds_phy_default_frame_handler,
3523230557Sjimharris      scic_sds_phy_starting_substate_await_sata_speed_event_handler,
3524230557Sjimharris      scic_sds_phy_default_consume_power_handler
3525230557Sjimharris   },
3526230557Sjimharris   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF,
3527230557Sjimharris   {
3528230557Sjimharris      {
3529230557Sjimharris         scic_sds_phy_default_start_handler,
3530230557Sjimharris         scic_sds_phy_starting_substate_general_stop_handler,
3531230557Sjimharris         scic_sds_phy_default_reset_handler,
3532230557Sjimharris         scic_sds_phy_default_destroy_handler
3533230557Sjimharris      },
3534230557Sjimharris      scic_sds_phy_starting_substate_await_sig_fis_frame_handler,
3535230557Sjimharris      scic_sds_phy_starting_substate_await_sig_fis_event_handler,
3536230557Sjimharris      scic_sds_phy_default_consume_power_handler
3537230557Sjimharris   },
3538230557Sjimharris   // SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
3539230557Sjimharris   {
3540230557Sjimharris      {
3541230557Sjimharris         scic_sds_phy_default_start_handler,
3542230557Sjimharris         scic_sds_phy_starting_substate_general_stop_handler,
3543230557Sjimharris         scic_sds_phy_default_reset_handler,
3544230557Sjimharris         scic_sds_phy_default_destroy_handler
3545230557Sjimharris      },
3546230557Sjimharris      scic_sds_phy_default_frame_handler,
3547230557Sjimharris      scic_sds_phy_default_event_handler,
3548230557Sjimharris      scic_sds_phy_default_consume_power_handler
3549230557Sjimharris   }
3550230557Sjimharris};
3551230557Sjimharris
3552230557Sjimharris/**
3553230557Sjimharris * This macro sets the starting substate handlers by state_id
3554230557Sjimharris */
3555230557Sjimharris#define scic_sds_phy_set_starting_substate_handlers(phy, state_id) \
3556230557Sjimharris   scic_sds_phy_set_state_handlers( \
3557230557Sjimharris      (phy), \
3558230557Sjimharris      &scic_sds_phy_starting_substate_handler_table[(state_id)] \
3559230557Sjimharris   )
3560230557Sjimharris
3561230557Sjimharris//****************************************************************************
3562230557Sjimharris//*  PHY STARTING SUBSTATE METHODS
3563230557Sjimharris//****************************************************************************
3564230557Sjimharris
3565230557Sjimharris/**
3566230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3567230557Sjimharris * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL.
3568230557Sjimharris *    - The initial state handlers are put in place for the SCIC_SDS_PHY
3569230557Sjimharris *      object.
3570230557Sjimharris *    - The state is changed to the wait phy type event notification.
3571230557Sjimharris *
3572230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3573230557Sjimharris *       SCIC_SDS_PHY object.
3574230557Sjimharris *
3575230557Sjimharris * @return none
3576230557Sjimharris */
3577230557Sjimharrisstatic
3578230557Sjimharrisvoid scic_sds_phy_starting_initial_substate_enter(
3579230557Sjimharris   SCI_BASE_OBJECT_T *object
3580230557Sjimharris)
3581230557Sjimharris{
3582230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3583230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3584230557Sjimharris
3585230557Sjimharris   scic_sds_phy_set_starting_substate_handlers(
3586230557Sjimharris      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL);
3587230557Sjimharris
3588230557Sjimharris   // This is just an temporary state go off to the starting state
3589230557Sjimharris   sci_base_state_machine_change_state(
3590230557Sjimharris      scic_sds_phy_get_starting_substate_machine(this_phy),
3591230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
3592230557Sjimharris   );
3593230557Sjimharris}
3594230557Sjimharris
3595230557Sjimharris/**
3596230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3597230557Sjimharris * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN.
3598230557Sjimharris *    - Set the SCIC_SDS_PHY object state handlers for this state.
3599230557Sjimharris *
3600230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3601230557Sjimharris *       SCIC_SDS_PHY object.
3602230557Sjimharris *
3603230557Sjimharris * @return none
3604230557Sjimharris */
3605230557Sjimharrisstatic
3606230557Sjimharrisvoid scic_sds_phy_starting_await_ossp_en_substate_enter(
3607230557Sjimharris   SCI_BASE_OBJECT_T *object
3608230557Sjimharris)
3609230557Sjimharris{
3610230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3611230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3612230557Sjimharris
3613230557Sjimharris   scic_sds_phy_set_starting_substate_handlers(
3614230557Sjimharris      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
3615230557Sjimharris      );
3616230557Sjimharris}
3617230557Sjimharris
3618230557Sjimharris/**
3619230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3620230557Sjimharris * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN.
3621230557Sjimharris *    - Set the SCIC_SDS_PHY object state handlers for this state.
3622230557Sjimharris *
3623230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3624230557Sjimharris *       SCIC_SDS_PHY object.
3625230557Sjimharris *
3626230557Sjimharris * @return none
3627230557Sjimharris */
3628230557Sjimharrisstatic
3629230557Sjimharrisvoid scic_sds_phy_starting_await_sas_speed_en_substate_enter(
3630230557Sjimharris   SCI_BASE_OBJECT_T *object
3631230557Sjimharris)
3632230557Sjimharris{
3633230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3634230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3635230557Sjimharris
3636230557Sjimharris   scic_sds_phy_set_starting_substate_handlers(
3637230557Sjimharris      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
3638230557Sjimharris      );
3639230557Sjimharris}
3640230557Sjimharris
3641230557Sjimharris/**
3642230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3643230557Sjimharris * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF.
3644230557Sjimharris *    - Set the SCIC_SDS_PHY object state handlers for this state.
3645230557Sjimharris *
3646230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3647230557Sjimharris *       SCIC_SDS_PHY object.
3648230557Sjimharris *
3649230557Sjimharris * @return none
3650230557Sjimharris */
3651230557Sjimharrisstatic
3652230557Sjimharrisvoid scic_sds_phy_starting_await_iaf_uf_substate_enter(
3653230557Sjimharris   SCI_BASE_OBJECT_T *object
3654230557Sjimharris)
3655230557Sjimharris{
3656230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3657230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3658230557Sjimharris
3659230557Sjimharris   scic_sds_phy_set_starting_substate_handlers(
3660230557Sjimharris      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
3661230557Sjimharris      );
3662230557Sjimharris}
3663230557Sjimharris
3664230557Sjimharris/**
3665230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3666230557Sjimharris * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER.
3667230557Sjimharris *    - Set the SCIC_SDS_PHY object state handlers for this state.
3668230557Sjimharris *    - Add this phy object to the power control queue
3669230557Sjimharris *
3670230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3671230557Sjimharris *       SCIC_SDS_PHY object.
3672230557Sjimharris *
3673230557Sjimharris * @return none
3674230557Sjimharris */
3675230557Sjimharrisstatic
3676230557Sjimharrisvoid scic_sds_phy_starting_await_sas_power_substate_enter(
3677230557Sjimharris   SCI_BASE_OBJECT_T *object
3678230557Sjimharris)
3679230557Sjimharris{
3680230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3681230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3682230557Sjimharris
3683230557Sjimharris   scic_sds_phy_set_starting_substate_handlers(
3684230557Sjimharris      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
3685230557Sjimharris      );
3686230557Sjimharris
3687230557Sjimharris   scic_sds_controller_power_control_queue_insert(
3688230557Sjimharris      scic_sds_phy_get_controller(this_phy),
3689230557Sjimharris      this_phy
3690230557Sjimharris      );
3691230557Sjimharris}
3692230557Sjimharris
3693230557Sjimharris/**
3694230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3695230557Sjimharris * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER.
3696230557Sjimharris *    - Remove the SCIC_SDS_PHY object from the power control queue.
3697230557Sjimharris *
3698230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3699230557Sjimharris *       SCIC_SDS_PHY object.
3700230557Sjimharris *
3701230557Sjimharris * @return none
3702230557Sjimharris */
3703230557Sjimharrisstatic
3704230557Sjimharrisvoid scic_sds_phy_starting_await_sas_power_substate_exit(
3705230557Sjimharris   SCI_BASE_OBJECT_T *object
3706230557Sjimharris)
3707230557Sjimharris{
3708230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3709230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3710230557Sjimharris
3711230557Sjimharris   scic_sds_controller_power_control_queue_remove(
3712230557Sjimharris      scic_sds_phy_get_controller(this_phy), this_phy
3713230557Sjimharris   );
3714230557Sjimharris}
3715230557Sjimharris
3716230557Sjimharris/**
3717230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3718230557Sjimharris * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER.
3719230557Sjimharris *    - Set the SCIC_SDS_PHY object state handlers for this state.
3720230557Sjimharris *    - Add this phy object to the power control queue
3721230557Sjimharris *
3722230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3723230557Sjimharris *       SCIC_SDS_PHY object.
3724230557Sjimharris *
3725230557Sjimharris * @return none
3726230557Sjimharris */
3727230557Sjimharrisstatic
3728230557Sjimharrisvoid scic_sds_phy_starting_await_sata_power_substate_enter(
3729230557Sjimharris   SCI_BASE_OBJECT_T *object
3730230557Sjimharris)
3731230557Sjimharris{
3732230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3733230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3734230557Sjimharris
3735230557Sjimharris   scic_sds_phy_set_starting_substate_handlers(
3736230557Sjimharris      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER
3737230557Sjimharris      );
3738230557Sjimharris
3739230557Sjimharris   scic_sds_controller_power_control_queue_insert(
3740230557Sjimharris      scic_sds_phy_get_controller(this_phy),
3741230557Sjimharris      this_phy
3742230557Sjimharris      );
3743230557Sjimharris}
3744230557Sjimharris
3745230557Sjimharris/**
3746230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3747230557Sjimharris * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER.
3748230557Sjimharris *    - Remove the SCIC_SDS_PHY object from the power control queue.
3749230557Sjimharris *
3750230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3751230557Sjimharris *       SCIC_SDS_PHY object.
3752230557Sjimharris *
3753230557Sjimharris * @return none
3754230557Sjimharris */
3755230557Sjimharrisstatic
3756230557Sjimharrisvoid scic_sds_phy_starting_await_sata_power_substate_exit(
3757230557Sjimharris   SCI_BASE_OBJECT_T *object
3758230557Sjimharris)
3759230557Sjimharris{
3760230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3761230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3762230557Sjimharris
3763230557Sjimharris   scic_sds_controller_power_control_queue_remove(
3764230557Sjimharris      scic_sds_phy_get_controller(this_phy),
3765230557Sjimharris      this_phy
3766230557Sjimharris      );
3767230557Sjimharris}
3768230557Sjimharris
3769230557Sjimharris/**
3770230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3771230557Sjimharris * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN.
3772230557Sjimharris *    - Set the SCIC_SDS_PHY object state handlers for this state.
3773230557Sjimharris *
3774230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3775230557Sjimharris *       SCIC_SDS_PHY object.
3776230557Sjimharris *
3777230557Sjimharris * @return none
3778230557Sjimharris */
3779230557Sjimharrisstatic
3780230557Sjimharrisvoid scic_sds_phy_starting_await_sata_phy_substate_enter(
3781230557Sjimharris   SCI_BASE_OBJECT_T *object
3782230557Sjimharris)
3783230557Sjimharris{
3784230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3785230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3786230557Sjimharris
3787230557Sjimharris   scic_sds_phy_set_starting_substate_handlers(
3788230557Sjimharris      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN
3789230557Sjimharris      );
3790230557Sjimharris
3791230557Sjimharris   scic_cb_timer_start(
3792230557Sjimharris      scic_sds_phy_get_controller(this_phy),
3793230557Sjimharris      this_phy->sata_timeout_timer,
3794230557Sjimharris      SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT
3795230557Sjimharris   );
3796230557Sjimharris}
3797230557Sjimharris
3798230557Sjimharris/**
3799230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3800230557Sjimharris * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
3801230557Sjimharris *    - stop the timer that was started on entry to await sata phy
3802230557Sjimharris *      event notification
3803230557Sjimharris *
3804230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3805230557Sjimharris *       SCIC_SDS_PHY object.
3806230557Sjimharris *
3807230557Sjimharris * @return none
3808230557Sjimharris */
3809230557Sjimharrisstatic
3810230557Sjimharrisvoid scic_sds_phy_starting_await_sata_phy_substate_exit(
3811230557Sjimharris   SCI_BASE_OBJECT_T *object
3812230557Sjimharris)
3813230557Sjimharris{
3814230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3815230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3816230557Sjimharris
3817230557Sjimharris   scic_cb_timer_stop(
3818230557Sjimharris      scic_sds_phy_get_controller(this_phy),
3819230557Sjimharris      this_phy->sata_timeout_timer
3820230557Sjimharris   );
3821230557Sjimharris}
3822230557Sjimharris
3823230557Sjimharris/**
3824230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3825230557Sjimharris * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
3826230557Sjimharris *    - Set the SCIC_SDS_PHY object state handlers for this state.
3827230557Sjimharris *
3828230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3829230557Sjimharris *       SCIC_SDS_PHY object.
3830230557Sjimharris *
3831230557Sjimharris * @return none
3832230557Sjimharris */
3833230557Sjimharrisstatic
3834230557Sjimharrisvoid scic_sds_phy_starting_await_sata_speed_substate_enter(
3835230557Sjimharris   SCI_BASE_OBJECT_T *object
3836230557Sjimharris)
3837230557Sjimharris{
3838230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3839230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3840230557Sjimharris
3841230557Sjimharris   scic_sds_phy_set_starting_substate_handlers(
3842230557Sjimharris      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
3843230557Sjimharris      );
3844230557Sjimharris
3845230557Sjimharris   scic_cb_timer_start(
3846230557Sjimharris      scic_sds_phy_get_controller(this_phy),
3847230557Sjimharris      this_phy->sata_timeout_timer,
3848230557Sjimharris      SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT
3849230557Sjimharris   );
3850230557Sjimharris}
3851230557Sjimharris
3852230557Sjimharris/**
3853230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3854230557Sjimharris * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
3855230557Sjimharris *    - stop the timer that was started on entry to await sata phy
3856230557Sjimharris *      event notification
3857230557Sjimharris *
3858230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3859230557Sjimharris *       SCIC_SDS_PHY object.
3860230557Sjimharris *
3861230557Sjimharris * @return none
3862230557Sjimharris */
3863230557Sjimharrisstatic
3864230557Sjimharrisvoid scic_sds_phy_starting_await_sata_speed_substate_exit(
3865230557Sjimharris   SCI_BASE_OBJECT_T *object
3866230557Sjimharris)
3867230557Sjimharris{
3868230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3869230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3870230557Sjimharris
3871230557Sjimharris   scic_cb_timer_stop(
3872230557Sjimharris      scic_sds_phy_get_controller(this_phy),
3873230557Sjimharris      this_phy->sata_timeout_timer
3874230557Sjimharris   );
3875230557Sjimharris}
3876230557Sjimharris
3877230557Sjimharris/**
3878230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3879230557Sjimharris * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
3880230557Sjimharris *    - Set the SCIC_SDS_PHY object state handlers for this state.
3881230557Sjimharris *    - Start the SIGNATURE FIS timeout timer
3882230557Sjimharris *
3883230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3884230557Sjimharris *       SCIC_SDS_PHY object.
3885230557Sjimharris *
3886230557Sjimharris * @return none
3887230557Sjimharris */
3888230557Sjimharrisstatic
3889230557Sjimharrisvoid scic_sds_phy_starting_await_sig_fis_uf_substate_enter(
3890230557Sjimharris   SCI_BASE_OBJECT_T *object
3891230557Sjimharris)
3892230557Sjimharris{
3893230557Sjimharris   BOOL             continue_to_ready_state;
3894230557Sjimharris   SCIC_SDS_PHY_T * this_phy;
3895230557Sjimharris
3896230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3897230557Sjimharris
3898230557Sjimharris   scic_sds_phy_set_starting_substate_handlers(
3899230557Sjimharris      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
3900230557Sjimharris   );
3901230557Sjimharris
3902230557Sjimharris   continue_to_ready_state = scic_sds_port_link_detected(
3903230557Sjimharris                                 this_phy->owning_port,
3904230557Sjimharris                                 this_phy
3905230557Sjimharris                             );
3906230557Sjimharris
3907230557Sjimharris   if (continue_to_ready_state)
3908230557Sjimharris   {
3909230557Sjimharris      // Clear the PE suspend condition so we can actually receive SIG FIS
3910230557Sjimharris      // The hardware will not respond to the XRDY until the PE suspend
3911230557Sjimharris      // condition is cleared.
3912230557Sjimharris      scic_sds_phy_resume(this_phy);
3913230557Sjimharris
3914230557Sjimharris      scic_cb_timer_start(
3915230557Sjimharris         scic_sds_phy_get_controller(this_phy),
3916230557Sjimharris         this_phy->sata_timeout_timer,
3917230557Sjimharris         SCIC_SDS_SIGNATURE_FIS_TIMEOUT
3918230557Sjimharris      );
3919230557Sjimharris   }
3920230557Sjimharris   else
3921230557Sjimharris   {
3922230557Sjimharris      this_phy->is_in_link_training = FALSE;
3923230557Sjimharris   }
3924230557Sjimharris}
3925230557Sjimharris
3926230557Sjimharris/**
3927230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3928230557Sjimharris * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
3929230557Sjimharris *    - Stop the SIGNATURE FIS timeout timer.
3930230557Sjimharris *
3931230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3932230557Sjimharris *       SCIC_SDS_PHY object.
3933230557Sjimharris *
3934230557Sjimharris * @return none
3935230557Sjimharris */
3936230557Sjimharrisstatic
3937230557Sjimharrisvoid scic_sds_phy_starting_await_sig_fis_uf_substate_exit(
3938230557Sjimharris   SCI_BASE_OBJECT_T *object
3939230557Sjimharris)
3940230557Sjimharris{
3941230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3942230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3943230557Sjimharris
3944230557Sjimharris   scic_cb_timer_stop(
3945230557Sjimharris      scic_sds_phy_get_controller(this_phy),
3946230557Sjimharris      this_phy->sata_timeout_timer
3947230557Sjimharris   );
3948230557Sjimharris}
3949230557Sjimharris
3950230557Sjimharris/**
3951230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PHY on
3952230557Sjimharris * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL.
3953230557Sjimharris *    - Set the SCIC_SDS_PHY object state handlers for this state.
3954230557Sjimharris *    - Change base state machine to the ready state.
3955230557Sjimharris *
3956230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3957230557Sjimharris *       SCIC_SDS_PHY object.
3958230557Sjimharris *
3959230557Sjimharris * @return none
3960230557Sjimharris */
3961230557Sjimharrisstatic
3962230557Sjimharrisvoid scic_sds_phy_starting_final_substate_enter(
3963230557Sjimharris   SCI_BASE_OBJECT_T *object
3964230557Sjimharris)
3965230557Sjimharris{
3966230557Sjimharris   SCIC_SDS_PHY_T *this_phy;
3967230557Sjimharris   this_phy = (SCIC_SDS_PHY_T *)object;
3968230557Sjimharris
3969230557Sjimharris   scic_sds_phy_set_starting_substate_handlers(
3970230557Sjimharris      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
3971230557Sjimharris      );
3972230557Sjimharris
3973230557Sjimharris   // State machine has run to completion so exit out and change
3974230557Sjimharris   // the base state machine to the ready state
3975230557Sjimharris   sci_base_state_machine_change_state(
3976230557Sjimharris      scic_sds_phy_get_base_state_machine(this_phy),
3977230557Sjimharris      SCI_BASE_PHY_STATE_READY);
3978230557Sjimharris}
3979230557Sjimharris
3980230557Sjimharris// ---------------------------------------------------------------------------
3981230557Sjimharris
3982230557SjimharrisSCI_BASE_STATE_T
3983230557Sjimharris   scic_sds_phy_starting_substates[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] =
3984230557Sjimharris{
3985230557Sjimharris   {
3986230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL,
3987230557Sjimharris      scic_sds_phy_starting_initial_substate_enter,
3988230557Sjimharris      NULL,
3989230557Sjimharris   },
3990230557Sjimharris   {
3991230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN,
3992230557Sjimharris      scic_sds_phy_starting_await_ossp_en_substate_enter,
3993230557Sjimharris      NULL,
3994230557Sjimharris   },
3995230557Sjimharris   {
3996230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN,
3997230557Sjimharris      scic_sds_phy_starting_await_sas_speed_en_substate_enter,
3998230557Sjimharris      NULL,
3999230557Sjimharris   },
4000230557Sjimharris   {
4001230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF,
4002230557Sjimharris      scic_sds_phy_starting_await_iaf_uf_substate_enter,
4003230557Sjimharris      NULL,
4004230557Sjimharris   },
4005230557Sjimharris   {
4006230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER,
4007230557Sjimharris      scic_sds_phy_starting_await_sas_power_substate_enter,
4008230557Sjimharris      scic_sds_phy_starting_await_sas_power_substate_exit,
4009230557Sjimharris   },
4010230557Sjimharris   {
4011230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER,
4012230557Sjimharris      scic_sds_phy_starting_await_sata_power_substate_enter,
4013230557Sjimharris      scic_sds_phy_starting_await_sata_power_substate_exit
4014230557Sjimharris   },
4015230557Sjimharris   {
4016230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN,
4017230557Sjimharris      scic_sds_phy_starting_await_sata_phy_substate_enter,
4018230557Sjimharris      scic_sds_phy_starting_await_sata_phy_substate_exit
4019230557Sjimharris   },
4020230557Sjimharris   {
4021230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN,
4022230557Sjimharris      scic_sds_phy_starting_await_sata_speed_substate_enter,
4023230557Sjimharris      scic_sds_phy_starting_await_sata_speed_substate_exit
4024230557Sjimharris   },
4025230557Sjimharris   {
4026230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF,
4027230557Sjimharris      scic_sds_phy_starting_await_sig_fis_uf_substate_enter,
4028230557Sjimharris      scic_sds_phy_starting_await_sig_fis_uf_substate_exit
4029230557Sjimharris   },
4030230557Sjimharris   {
4031230557Sjimharris      SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL,
4032230557Sjimharris      scic_sds_phy_starting_final_substate_enter,
4033230557Sjimharris      NULL,
4034230557Sjimharris   }
4035230557Sjimharris};
4036230557Sjimharris
4037