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 for the public and protected
60230557Sjimharris *        methods for the SCIC_SDS_PORT object.
61230557Sjimharris */
62230557Sjimharris
63230557Sjimharris#include <dev/isci/scil/scic_phy.h>
64230557Sjimharris#include <dev/isci/scil/scic_port.h>
65230557Sjimharris#include <dev/isci/scil/scic_controller.h>
66230557Sjimharris#include <dev/isci/scil/scic_user_callback.h>
67230557Sjimharris
68230557Sjimharris#include <dev/isci/scil/scic_sds_controller.h>
69230557Sjimharris#include <dev/isci/scil/scic_sds_port.h>
70230557Sjimharris#include <dev/isci/scil/scic_sds_phy.h>
71230557Sjimharris#include <dev/isci/scil/scic_sds_remote_device.h>
72230557Sjimharris#include <dev/isci/scil/scic_sds_request.h>
73230557Sjimharris#include <dev/isci/scil/scic_sds_port_registers.h>
74230557Sjimharris#include <dev/isci/scil/scic_sds_logger.h>
75230557Sjimharris#include <dev/isci/scil/scic_sds_phy_registers.h>
76230557Sjimharris
77230557Sjimharris#include <dev/isci/scil/intel_sas.h>
78230557Sjimharris#include <dev/isci/scil/scic_sds_remote_node_context.h>
79230557Sjimharris#include <dev/isci/scil/sci_util.h>
80230557Sjimharris
81230557Sjimharris#define SCIC_SDS_PORT_MIN_TIMER_COUNT  (SCI_MAX_PORTS)
82230557Sjimharris#define SCIC_SDS_PORT_MAX_TIMER_COUNT  (SCI_MAX_PORTS)
83230557Sjimharris
84230557Sjimharris#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT  (1000)
85230557Sjimharris#define SCU_DUMMY_INDEX    (0xFFFF)
86230557Sjimharris
87230557Sjimharris/**
88230557Sjimharris * This method will return a TRUE value if the specified phy can be assigned
89230557Sjimharris * to this port
90230557Sjimharris *
91230557Sjimharris * The following is a list of phys for each port that are allowed:
92230557Sjimharris * - Port 0 - 3 2 1 0
93230557Sjimharris * - Port 1 -     1
94230557Sjimharris * - Port 2 - 3 2
95230557Sjimharris * - Port 3 - 3
96230557Sjimharris *
97230557Sjimharris * This method doesn't preclude all configurations.  It merely ensures
98230557Sjimharris * that a phy is part of the allowable set of phy identifiers for
99230557Sjimharris * that port.  For example, one could assign phy 3 to port 0 and no other
100230557Sjimharris * phys.  Please refer to scic_sds_port_is_phy_mask_valid() for
101230557Sjimharris * information regarding whether the phy_mask for a port can be supported.
102230557Sjimharris *
103230557Sjimharris * @param[in] this_port This is the port object to which the phy is being
104230557Sjimharris *       assigned.
105230557Sjimharris * @param[in] phy_index This is the phy index that is being assigned to the
106230557Sjimharris *       port.
107230557Sjimharris *
108230557Sjimharris * @return BOOL
109230557Sjimharris * @retval TRUE if this is a valid phy assignment for the port
110230557Sjimharris * @retval FALSE if this is not a valid phy assignment for the port
111230557Sjimharris */
112230557SjimharrisBOOL scic_sds_port_is_valid_phy_assignment(
113230557Sjimharris   SCIC_SDS_PORT_T *this_port,
114230557Sjimharris   U32              phy_index
115230557Sjimharris)
116230557Sjimharris{
117230557Sjimharris   // Initialize to invalid value.
118230557Sjimharris   U32  existing_phy_index = SCI_MAX_PHYS;
119230557Sjimharris   U32  index;
120230557Sjimharris
121230557Sjimharris   if ((this_port->physical_port_index == 1) && (phy_index != 1))
122230557Sjimharris   {
123230557Sjimharris      return FALSE;
124230557Sjimharris   }
125230557Sjimharris
126230557Sjimharris   if (this_port->physical_port_index == 3 && phy_index != 3)
127230557Sjimharris   {
128230557Sjimharris      return FALSE;
129230557Sjimharris   }
130230557Sjimharris
131230557Sjimharris   if (
132230557Sjimharris          (this_port->physical_port_index == 2)
133230557Sjimharris       && ((phy_index == 0) || (phy_index == 1))
134230557Sjimharris      )
135230557Sjimharris   {
136230557Sjimharris      return FALSE;
137230557Sjimharris   }
138230557Sjimharris
139230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
140230557Sjimharris   {
141230557Sjimharris      if (  (this_port->phy_table[index] != NULL)
142230557Sjimharris         && (index != phy_index) )
143230557Sjimharris      {
144230557Sjimharris         existing_phy_index = index;
145230557Sjimharris      }
146230557Sjimharris   }
147230557Sjimharris
148230557Sjimharris   // Ensure that all of the phys in the port are capable of
149230557Sjimharris   // operating at the same maximum link rate.
150230557Sjimharris   if (
151230557Sjimharris         (existing_phy_index < SCI_MAX_PHYS)
152230557Sjimharris      && (this_port->owning_controller->user_parameters.sds1.phys[
153230557Sjimharris             phy_index].max_speed_generation !=
154230557Sjimharris          this_port->owning_controller->user_parameters.sds1.phys[
155230557Sjimharris             existing_phy_index].max_speed_generation)
156230557Sjimharris      )
157230557Sjimharris      return FALSE;
158230557Sjimharris
159230557Sjimharris   return TRUE;
160230557Sjimharris}
161230557Sjimharris
162230557Sjimharris/**
163230557Sjimharris * @brief This method requests a list (mask) of the phys contained in the
164230557Sjimharris *        supplied SAS port.
165230557Sjimharris *
166230557Sjimharris * @param[in]  this_port a handle corresponding to the SAS port for which
167230557Sjimharris *             to return the phy mask.
168230557Sjimharris *
169230557Sjimharris * @return Return a bit mask indicating which phys are a part of this port.
170230557Sjimharris *         Each bit corresponds to a phy identifier (e.g. bit 0 = phy id 0).
171230557Sjimharris */
172230557SjimharrisU32 scic_sds_port_get_phys(
173230557Sjimharris   SCIC_SDS_PORT_T * this_port
174230557Sjimharris)
175230557Sjimharris{
176230557Sjimharris   U32 index;
177230557Sjimharris   U32 mask;
178230557Sjimharris
179230557Sjimharris   SCIC_LOG_TRACE((
180230557Sjimharris      sci_base_object_get_logger(this_port),
181230557Sjimharris      SCIC_LOG_OBJECT_PORT,
182230557Sjimharris      "scic_sds_port_get_phys(0x%x) enter\n",
183230557Sjimharris      this_port
184230557Sjimharris   ));
185230557Sjimharris
186230557Sjimharris   mask = 0;
187230557Sjimharris
188230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
189230557Sjimharris   {
190230557Sjimharris      if (this_port->phy_table[index] != NULL)
191230557Sjimharris      {
192230557Sjimharris         mask |= (1 << index);
193230557Sjimharris      }
194230557Sjimharris   }
195230557Sjimharris
196230557Sjimharris   return mask;
197230557Sjimharris}
198230557Sjimharris
199230557Sjimharris/**
200230557Sjimharris * This method will return a TRUE value if the port's phy mask can be
201230557Sjimharris * supported by the SCU.
202230557Sjimharris *
203230557Sjimharris * The following is a list of valid PHY mask configurations for each
204230557Sjimharris * port:
205230557Sjimharris * - Port 0 - [[3  2] 1] 0
206230557Sjimharris * - Port 1 -        [1]
207230557Sjimharris * - Port 2 - [[3] 2]
208230557Sjimharris * - Port 3 -  [3]
209230557Sjimharris *
210230557Sjimharris * @param[in] this_port This is the port object for which to determine
211230557Sjimharris *       if the phy mask can be supported.
212230557Sjimharris *
213230557Sjimharris * @return This method returns a boolean indication specifying if the
214230557Sjimharris *         phy mask can be supported.
215230557Sjimharris * @retval TRUE if this is a valid phy assignment for the port
216230557Sjimharris * @retval FALSE if this is not a valid phy assignment for the port
217230557Sjimharris */
218230557SjimharrisBOOL scic_sds_port_is_phy_mask_valid(
219230557Sjimharris   SCIC_SDS_PORT_T *this_port,
220230557Sjimharris   U32              phy_mask
221230557Sjimharris)
222230557Sjimharris{
223230557Sjimharris   if (this_port->physical_port_index == 0)
224230557Sjimharris   {
225230557Sjimharris      if (  ((phy_mask & 0x0F) == 0x0F)
226230557Sjimharris         || ((phy_mask & 0x03) == 0x03)
227230557Sjimharris         || ((phy_mask & 0x01) == 0x01)
228230557Sjimharris         || (phy_mask == 0) )
229230557Sjimharris         return TRUE;
230230557Sjimharris   }
231230557Sjimharris   else if (this_port->physical_port_index == 1)
232230557Sjimharris   {
233230557Sjimharris      if (  ((phy_mask & 0x02) == 0x02)
234230557Sjimharris         || (phy_mask == 0) )
235230557Sjimharris         return TRUE;
236230557Sjimharris   }
237230557Sjimharris   else if (this_port->physical_port_index == 2)
238230557Sjimharris   {
239230557Sjimharris      if (  ((phy_mask & 0x0C) == 0x0C)
240230557Sjimharris         || ((phy_mask & 0x04) == 0x04)
241230557Sjimharris         || (phy_mask == 0) )
242230557Sjimharris         return TRUE;
243230557Sjimharris   }
244230557Sjimharris   else if (this_port->physical_port_index == 3)
245230557Sjimharris   {
246230557Sjimharris      if (  ((phy_mask & 0x08) == 0x08)
247230557Sjimharris         || (phy_mask == 0) )
248230557Sjimharris         return TRUE;
249230557Sjimharris   }
250230557Sjimharris
251230557Sjimharris   return FALSE;
252230557Sjimharris}
253230557Sjimharris
254230557Sjimharris/**
255230557Sjimharris * This method retrieves a currently active (i.e. connected) phy
256230557Sjimharris * contained in the port.  Currently, the lowest order phy that is
257230557Sjimharris * connected is returned.
258230557Sjimharris *
259230557Sjimharris * @param[in] this_port This parameter specifies the port from which
260230557Sjimharris *            to return a connected phy.
261230557Sjimharris *
262230557Sjimharris * @return This method returns a pointer to a SCIS_SDS_PHY object.
263230557Sjimharris * @retval NULL This value is returned if there are no currently
264230557Sjimharris *         active (i.e. connected to a remote end point) phys
265230557Sjimharris *         contained in the port.
266230557Sjimharris * @retval All other values specify a SCIC_SDS_PHY object that is
267230557Sjimharris *         active in the port.
268230557Sjimharris */
269230557SjimharrisSCIC_SDS_PHY_T * scic_sds_port_get_a_connected_phy(
270230557Sjimharris   SCIC_SDS_PORT_T *this_port
271230557Sjimharris)
272230557Sjimharris{
273230557Sjimharris   U32             index;
274230557Sjimharris   SCIC_SDS_PHY_T *phy;
275230557Sjimharris
276230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
277230557Sjimharris   {
278230557Sjimharris      // Ensure that the phy is both part of the port and currently
279230557Sjimharris      // connected to the remote end-point.
280230557Sjimharris      phy = this_port->phy_table[index];
281230557Sjimharris      if (
282230557Sjimharris            (phy != NULL)
283230557Sjimharris         && scic_sds_port_active_phy(this_port, phy)
284230557Sjimharris         )
285230557Sjimharris      {
286230557Sjimharris         return phy;
287230557Sjimharris      }
288230557Sjimharris   }
289230557Sjimharris
290230557Sjimharris   return NULL;
291230557Sjimharris}
292230557Sjimharris
293230557Sjimharris/**
294230557Sjimharris * This method attempts to make the assignment of the phy to the port.
295230557Sjimharris * If successful the phy is assigned to the ports phy table.
296230557Sjimharris *
297230557Sjimharris * @param[in, out] port The port object to which the phy assignement
298230557Sjimharris *                 is being made.
299230557Sjimharris * @param[in, out] phy The phy which is being assigned to the port.
300230557Sjimharris *
301230557Sjimharris * @return BOOL
302230557Sjimharris * @retval TRUE if the phy assignment can be made.
303230557Sjimharris * @retval FALSE if the phy assignement can not be made.
304230557Sjimharris *
305230557Sjimharris * @note This is a functional test that only fails if the phy is currently
306230557Sjimharris *       assigned to a different port.
307230557Sjimharris */
308230557SjimharrisSCI_STATUS scic_sds_port_set_phy(
309230557Sjimharris   SCIC_SDS_PORT_T *port,
310230557Sjimharris   SCIC_SDS_PHY_T  *phy
311230557Sjimharris)
312230557Sjimharris{
313230557Sjimharris   // Check to see if we can add this phy to a port
314230557Sjimharris   // that means that the phy is not part of a port and that the port does
315230557Sjimharris   // not already have a phy assinged to the phy index.
316230557Sjimharris   if (
317230557Sjimharris         (port->phy_table[phy->phy_index] == SCI_INVALID_HANDLE)
318230557Sjimharris      && (scic_sds_phy_get_port(phy) == SCI_INVALID_HANDLE)
319230557Sjimharris      && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)
320230557Sjimharris      )
321230557Sjimharris   {
322230557Sjimharris      // Phy is being added in the stopped state so we are in MPC mode
323230557Sjimharris      // make logical port index = physical port index
324230557Sjimharris      port->logical_port_index = port->physical_port_index;
325230557Sjimharris      port->phy_table[phy->phy_index] = phy;
326230557Sjimharris      scic_sds_phy_set_port(phy, port);
327230557Sjimharris
328230557Sjimharris      return SCI_SUCCESS;
329230557Sjimharris   }
330230557Sjimharris
331230557Sjimharris   return SCI_FAILURE;
332230557Sjimharris}
333230557Sjimharris
334230557Sjimharris/**
335230557Sjimharris * This method will clear the phy assigned to this port.  This method fails
336230557Sjimharris * if this phy is not currently assinged to this port.
337230557Sjimharris *
338230557Sjimharris * @param[in, out] port The port from which the phy is being cleared.
339230557Sjimharris * @param[in, out] phy The phy being cleared from the port.
340230557Sjimharris *
341230557Sjimharris * @return BOOL
342230557Sjimharris * @retval TRUE if the phy is removed from the port.
343230557Sjimharris * @retval FALSE if this phy is not assined to this port.
344230557Sjimharris */
345230557SjimharrisSCI_STATUS scic_sds_port_clear_phy(
346230557Sjimharris   SCIC_SDS_PORT_T *port,
347230557Sjimharris   SCIC_SDS_PHY_T  *phy
348230557Sjimharris)
349230557Sjimharris{
350230557Sjimharris   // Make sure that this phy is part of this port
351230557Sjimharris   if (
352230557Sjimharris           (port->phy_table[phy->phy_index] == phy)
353230557Sjimharris        && (scic_sds_phy_get_port(phy) == port)
354230557Sjimharris      )
355230557Sjimharris   {
356230557Sjimharris      // Yep it is assigned to this port so remove it
357230557Sjimharris      scic_sds_phy_set_port(
358230557Sjimharris         phy,
359230557Sjimharris         &scic_sds_port_get_controller(port)->port_table[SCI_MAX_PORTS]
360230557Sjimharris      );
361230557Sjimharris
362230557Sjimharris      port->phy_table[phy->phy_index] = SCI_INVALID_HANDLE;
363230557Sjimharris
364230557Sjimharris      return SCI_SUCCESS;
365230557Sjimharris   }
366230557Sjimharris
367230557Sjimharris   return SCI_FAILURE;
368230557Sjimharris}
369230557Sjimharris
370230557Sjimharris/**
371230557Sjimharris * This method will add a PHY to the selected port.
372230557Sjimharris *
373230557Sjimharris * @param[in] this_port This parameter specifies the port in which the phy will
374230557Sjimharris *            be added.
375230557Sjimharris *
376230557Sjimharris * @param[in] the_phy This parameter is the phy which is to be added to the
377230557Sjimharris *            port.
378230557Sjimharris *
379230557Sjimharris * @return This method returns an SCI_STATUS.
380230557Sjimharris * @retval SCI_SUCCESS the phy has been added to the port.
381230557Sjimharris * @retval Any other status is failre to add the phy to the port.
382230557Sjimharris */
383230557SjimharrisSCI_STATUS scic_sds_port_add_phy(
384230557Sjimharris   SCIC_SDS_PORT_T * this_port,
385230557Sjimharris   SCIC_SDS_PHY_T  * the_phy
386230557Sjimharris)
387230557Sjimharris{
388230557Sjimharris   return this_port->state_handlers->parent.add_phy_handler(
389230557Sjimharris                                          &this_port->parent, &the_phy->parent);
390230557Sjimharris}
391230557Sjimharris
392230557Sjimharris
393230557Sjimharris/**
394230557Sjimharris * This method will remove the PHY from the selected PORT.
395230557Sjimharris *
396230557Sjimharris * @param[in] this_port This parameter specifies the port in which the phy will
397230557Sjimharris *            be added.
398230557Sjimharris *
399230557Sjimharris * @param[in] the_phy This parameter is the phy which is to be added to the
400230557Sjimharris *            port.
401230557Sjimharris *
402230557Sjimharris * @return This method returns an SCI_STATUS.
403230557Sjimharris * @retval SCI_SUCCESS the phy has been removed from the port.
404230557Sjimharris * @retval Any other status is failre to add the phy to the port.
405230557Sjimharris */
406230557SjimharrisSCI_STATUS scic_sds_port_remove_phy(
407230557Sjimharris   SCIC_SDS_PORT_T * this_port,
408230557Sjimharris   SCIC_SDS_PHY_T  * the_phy
409230557Sjimharris)
410230557Sjimharris{
411230557Sjimharris   return this_port->state_handlers->parent.remove_phy_handler(
412230557Sjimharris                                          &this_port->parent, &the_phy->parent);
413230557Sjimharris}
414230557Sjimharris
415230557Sjimharris/**
416230557Sjimharris * @brief This method requests the SAS address for the supplied SAS port
417230557Sjimharris *        from the SCI implementation.
418230557Sjimharris *
419230557Sjimharris * @param[in]  this_port a handle corresponding to the SAS port for which
420230557Sjimharris *             to return the SAS address.
421230557Sjimharris * @param[out] sas_address This parameter specifies a pointer to a SAS
422230557Sjimharris *             address structure into which the core will copy the SAS
423230557Sjimharris *             address for the port.
424230557Sjimharris *
425230557Sjimharris * @return none
426230557Sjimharris */
427230557Sjimharrisvoid scic_sds_port_get_sas_address(
428230557Sjimharris   SCIC_SDS_PORT_T   * this_port,
429230557Sjimharris   SCI_SAS_ADDRESS_T * sas_address
430230557Sjimharris)
431230557Sjimharris{
432230557Sjimharris   U32 index;
433230557Sjimharris
434230557Sjimharris   SCIC_LOG_TRACE((
435230557Sjimharris      sci_base_object_get_logger(this_port),
436230557Sjimharris      SCIC_LOG_OBJECT_PORT,
437230557Sjimharris      "scic_sds_port_get_sas_address(0x%x, 0x%x) enter\n",
438230557Sjimharris      this_port, sas_address
439230557Sjimharris   ));
440230557Sjimharris
441230557Sjimharris   sas_address->high = 0;
442230557Sjimharris   sas_address->low  = 0;
443230557Sjimharris
444230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
445230557Sjimharris   {
446230557Sjimharris      if (this_port->phy_table[index] != NULL)
447230557Sjimharris      {
448230557Sjimharris         scic_sds_phy_get_sas_address(this_port->phy_table[index], sas_address);
449230557Sjimharris      }
450230557Sjimharris   }
451230557Sjimharris}
452230557Sjimharris
453230557Sjimharris/**
454230557Sjimharris * @brief This method will indicate which protocols are supported by this
455230557Sjimharris *        port.
456230557Sjimharris *
457230557Sjimharris * @param[in]  this_port a handle corresponding to the SAS port for which
458230557Sjimharris *             to return the supported protocols.
459230557Sjimharris * @param[out] protocols This parameter specifies a pointer to an IAF
460230557Sjimharris *             protocol field structure into which the core will copy
461230557Sjimharris *             the protocol values for the port.  The values are
462230557Sjimharris *             returned as part of a bit mask in order to allow for
463230557Sjimharris *             multi-protocol support.
464230557Sjimharris *
465230557Sjimharris * @return none
466230557Sjimharris */
467230557Sjimharrisstatic
468230557Sjimharrisvoid scic_sds_port_get_protocols(
469230557Sjimharris   SCIC_SDS_PORT_T                            * this_port,
470230557Sjimharris   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
471230557Sjimharris)
472230557Sjimharris{
473230557Sjimharris   U8 index;
474230557Sjimharris
475230557Sjimharris   SCIC_LOG_TRACE((
476230557Sjimharris      sci_base_object_get_logger(this_port),
477230557Sjimharris      SCIC_LOG_OBJECT_PORT,
478230557Sjimharris      "scic_sds_port_get_protocols(0x%x, 0x%x) enter\n",
479230557Sjimharris      this_port, protocols
480230557Sjimharris   ));
481230557Sjimharris
482230557Sjimharris   protocols->u.all = 0;
483230557Sjimharris
484230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
485230557Sjimharris   {
486230557Sjimharris      if (this_port->phy_table[index] != NULL)
487230557Sjimharris      {
488230557Sjimharris         scic_sds_phy_get_protocols(this_port->phy_table[index], protocols);
489230557Sjimharris      }
490230557Sjimharris   }
491230557Sjimharris}
492230557Sjimharris
493230557Sjimharris/**
494230557Sjimharris * @brief This method requests the SAS address for the device directly
495230557Sjimharris *        attached to this SAS port.
496230557Sjimharris *
497230557Sjimharris * @param[in]  this_port a handle corresponding to the SAS port for which
498230557Sjimharris *             to return the SAS address.
499230557Sjimharris * @param[out] sas_address This parameter specifies a pointer to a SAS
500230557Sjimharris *             address structure into which the core will copy the SAS
501230557Sjimharris *             address for the device directly attached to the port.
502230557Sjimharris *
503230557Sjimharris * @return none
504230557Sjimharris */
505230557Sjimharrisvoid scic_sds_port_get_attached_sas_address(
506230557Sjimharris   SCIC_SDS_PORT_T   * this_port,
507230557Sjimharris   SCI_SAS_ADDRESS_T * sas_address
508230557Sjimharris)
509230557Sjimharris{
510230557Sjimharris   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T protocols;
511230557Sjimharris   SCIC_SDS_PHY_T  *phy;
512230557Sjimharris
513230557Sjimharris   SCIC_LOG_TRACE((
514230557Sjimharris      sci_base_object_get_logger(this_port),
515230557Sjimharris      SCIC_LOG_OBJECT_PORT,
516230557Sjimharris      "scic_sds_port_get_attached_sas_address(0x%x, 0x%x) enter\n",
517230557Sjimharris      this_port, sas_address
518230557Sjimharris   ));
519230557Sjimharris
520230557Sjimharris   // Ensure that the phy is both part of the port and currently
521230557Sjimharris   // connected to the remote end-point.
522230557Sjimharris   phy = scic_sds_port_get_a_connected_phy(this_port);
523230557Sjimharris   if (phy != NULL)
524230557Sjimharris   {
525230557Sjimharris      scic_sds_phy_get_attached_phy_protocols(phy, &protocols);
526230557Sjimharris
527230557Sjimharris      if (!protocols.u.bits.stp_target)
528230557Sjimharris      {
529230557Sjimharris         scic_sds_phy_get_attached_sas_address(phy, sas_address);
530230557Sjimharris      }
531230557Sjimharris      else
532230557Sjimharris      {
533230557Sjimharris         scic_sds_phy_get_sas_address(phy, sas_address);
534230557Sjimharris         sas_address->low += phy->phy_index;
535230557Sjimharris
536230557Sjimharris		 //Need to make up attached STP device's SAS address in
537230557Sjimharris		 //the same order as recorded IAF from SSP device.
538230557Sjimharris		 sas_address->high = SCIC_SWAP_DWORD(sas_address->high);
539230557Sjimharris		 sas_address->low = SCIC_SWAP_DWORD(sas_address->low);
540230557Sjimharris      }
541230557Sjimharris   }
542230557Sjimharris   else
543230557Sjimharris   {
544230557Sjimharris      sas_address->high = 0;
545230557Sjimharris      sas_address->low  = 0;
546230557Sjimharris   }
547230557Sjimharris}
548230557Sjimharris
549230557Sjimharris/**
550230557Sjimharris * @brief This method will indicate which protocols are supported by this
551230557Sjimharris *        remote device.
552230557Sjimharris *
553230557Sjimharris * @param[in]  this_port a handle corresponding to the SAS port for which
554230557Sjimharris *             to return the supported protocols.
555230557Sjimharris * @param[out] protocols This parameter specifies a pointer to an IAF
556230557Sjimharris *             protocol field structure into which the core will copy
557230557Sjimharris *             the protocol values for the port.  The values are
558230557Sjimharris *             returned as part of a bit mask in order to allow for
559230557Sjimharris *             multi-protocol support.
560230557Sjimharris *
561230557Sjimharris * @return none
562230557Sjimharris */
563230557Sjimharrisvoid scic_sds_port_get_attached_protocols(
564230557Sjimharris   SCIC_SDS_PORT_T                            * this_port,
565230557Sjimharris   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
566230557Sjimharris)
567230557Sjimharris{
568230557Sjimharris   SCIC_SDS_PHY_T  *phy;
569230557Sjimharris
570230557Sjimharris   SCIC_LOG_TRACE((
571230557Sjimharris      sci_base_object_get_logger(this_port),
572230557Sjimharris      SCIC_LOG_OBJECT_PORT,
573230557Sjimharris      "scic_sds_port_get_attached_protocols(0x%x, 0x%x) enter\n",
574230557Sjimharris      this_port, protocols
575230557Sjimharris   ));
576230557Sjimharris
577230557Sjimharris   // Ensure that the phy is both part of the port and currently
578230557Sjimharris   // connected to the remote end-point.
579230557Sjimharris   phy = scic_sds_port_get_a_connected_phy(this_port);
580230557Sjimharris   if (phy != NULL)
581230557Sjimharris      scic_sds_phy_get_attached_phy_protocols(phy, protocols);
582230557Sjimharris   else
583230557Sjimharris      protocols->u.all = 0;
584230557Sjimharris}
585230557Sjimharris
586230557Sjimharris/**
587230557Sjimharris * @brief This method returns the amount of memory requred for a port
588230557Sjimharris *        object.
589230557Sjimharris *
590230557Sjimharris * @return U32
591230557Sjimharris */
592230557SjimharrisU32 scic_sds_port_get_object_size(void)
593230557Sjimharris{
594230557Sjimharris   return sizeof(SCIC_SDS_PORT_T);
595230557Sjimharris}
596230557Sjimharris
597230557Sjimharris/**
598230557Sjimharris * @brief This method returns the minimum number of timers required for all
599230557Sjimharris *        port objects.
600230557Sjimharris *
601230557Sjimharris * @return U32
602230557Sjimharris */
603230557SjimharrisU32 scic_sds_port_get_min_timer_count(void)
604230557Sjimharris{
605230557Sjimharris   return SCIC_SDS_PORT_MIN_TIMER_COUNT;
606230557Sjimharris}
607230557Sjimharris
608230557Sjimharris/**
609230557Sjimharris * @brief This method returns the maximum number of timers required for all
610230557Sjimharris *        port objects.
611230557Sjimharris *
612230557Sjimharris * @return U32
613230557Sjimharris */
614230557SjimharrisU32 scic_sds_port_get_max_timer_count(void)
615230557Sjimharris{
616230557Sjimharris   return SCIC_SDS_PORT_MAX_TIMER_COUNT;
617230557Sjimharris}
618230557Sjimharris
619230557Sjimharris#ifdef SCI_LOGGING
620230557Sjimharrisvoid scic_sds_port_initialize_state_logging(
621230557Sjimharris   SCIC_SDS_PORT_T *this_port
622230557Sjimharris)
623230557Sjimharris{
624230557Sjimharris   sci_base_state_machine_logger_initialize(
625230557Sjimharris      &this_port->parent.state_machine_logger,
626230557Sjimharris      &this_port->parent.state_machine,
627230557Sjimharris      &this_port->parent.parent,
628230557Sjimharris      scic_cb_logger_log_states,
629230557Sjimharris      "SCIC_SDS_PORT_T", "base state machine",
630230557Sjimharris      SCIC_LOG_OBJECT_PORT
631230557Sjimharris   );
632230557Sjimharris
633230557Sjimharris   sci_base_state_machine_logger_initialize(
634230557Sjimharris      &this_port->ready_substate_machine_logger,
635230557Sjimharris      &this_port->ready_substate_machine,
636230557Sjimharris      &this_port->parent.parent,
637230557Sjimharris      scic_cb_logger_log_states,
638230557Sjimharris      "SCIC_SDS_PORT_T", "ready substate machine",
639230557Sjimharris      SCIC_LOG_OBJECT_PORT
640230557Sjimharris   );
641230557Sjimharris}
642230557Sjimharris#endif
643230557Sjimharris
644230557Sjimharris/**
645230557Sjimharris * This routine will construct a dummy remote node context data structure
646230557Sjimharris * This structure will be posted to the hardware to work around a scheduler
647230557Sjimharris * error in the hardware.
648230557Sjimharris *
649230557Sjimharris * @param[in] this_port The logical port on which we need to create the
650230557Sjimharris *            remote node context.
651230557Sjimharris * @param[in] rni The remote node index for this remote node context.
652230557Sjimharris *
653230557Sjimharris * @return none
654230557Sjimharris */
655230557Sjimharrisstatic
656230557Sjimharrisvoid scic_sds_port_construct_dummy_rnc(
657230557Sjimharris   SCIC_SDS_PORT_T *this_port,
658230557Sjimharris   U16              rni
659230557Sjimharris)
660230557Sjimharris{
661230557Sjimharris   SCU_REMOTE_NODE_CONTEXT_T * rnc;
662230557Sjimharris
663230557Sjimharris   rnc = &(this_port->owning_controller->remote_node_context_table[rni]);
664230557Sjimharris
665230557Sjimharris   memset(rnc, 0, sizeof(SCU_REMOTE_NODE_CONTEXT_T));
666230557Sjimharris
667230557Sjimharris   rnc->ssp.remote_sas_address_hi = 0;
668230557Sjimharris   rnc->ssp.remote_sas_address_lo = 0;
669230557Sjimharris
670230557Sjimharris   rnc->ssp.remote_node_index = rni;
671230557Sjimharris   rnc->ssp.remote_node_port_width = 1;
672230557Sjimharris   rnc->ssp.logical_port_index = this_port->physical_port_index;
673230557Sjimharris
674230557Sjimharris   rnc->ssp.nexus_loss_timer_enable = FALSE;
675230557Sjimharris   rnc->ssp.check_bit = FALSE;
676230557Sjimharris   rnc->ssp.is_valid = TRUE;
677230557Sjimharris   rnc->ssp.is_remote_node_context = TRUE;
678230557Sjimharris   rnc->ssp.function_number = 0;
679230557Sjimharris   rnc->ssp.arbitration_wait_time = 0;
680230557Sjimharris}
681230557Sjimharris
682230557Sjimharris/**
683230557Sjimharris * This routine will construct a dummy task context data structure.  This
684230557Sjimharris * structure will be posted to the hardwre to work around a scheduler error
685230557Sjimharris * in the hardware.
686230557Sjimharris *
687230557Sjimharris * @param[in] this_port The logical port on which we need to create the
688230557Sjimharris *            remote node context.
689230557Sjimharris *            context.
690230557Sjimharris * @param[in] tci The remote node index for this remote node context.
691230557Sjimharris *
692230557Sjimharris */
693230557Sjimharrisstatic
694230557Sjimharrisvoid scic_sds_port_construct_dummy_task(
695230557Sjimharris   SCIC_SDS_PORT_T *this_port,
696230557Sjimharris   U16              tci
697230557Sjimharris)
698230557Sjimharris{
699230557Sjimharris   SCU_TASK_CONTEXT_T * task_context;
700230557Sjimharris
701230557Sjimharris   task_context = scic_sds_controller_get_task_context_buffer(this_port->owning_controller, tci);
702230557Sjimharris
703230557Sjimharris   memset(task_context, 0, sizeof(SCU_TASK_CONTEXT_T));
704230557Sjimharris
705230557Sjimharris   task_context->abort = 0;
706230557Sjimharris   task_context->priority = 0;
707230557Sjimharris   task_context->initiator_request = 1;
708230557Sjimharris   task_context->connection_rate = 1;
709230557Sjimharris   task_context->protocol_engine_index = 0;
710230557Sjimharris   task_context->logical_port_index = this_port->physical_port_index;
711230557Sjimharris   task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
712230557Sjimharris   task_context->task_index = scic_sds_io_tag_get_index(tci);
713230557Sjimharris   task_context->valid = SCU_TASK_CONTEXT_VALID;
714230557Sjimharris   task_context->context_type = SCU_TASK_CONTEXT_TYPE;
715230557Sjimharris
716230557Sjimharris   task_context->remote_node_index = this_port->reserved_rni;
717230557Sjimharris   task_context->command_code = 0;
718230557Sjimharris
719230557Sjimharris   task_context->link_layer_control = 0;
720230557Sjimharris   task_context->do_not_dma_ssp_good_response = 1;
721230557Sjimharris   task_context->strict_ordering = 0;
722230557Sjimharris   task_context->control_frame = 0;
723230557Sjimharris   task_context->timeout_enable = 0;
724230557Sjimharris   task_context->block_guard_enable = 0;
725230557Sjimharris
726230557Sjimharris   task_context->address_modifier = 0;
727230557Sjimharris
728230557Sjimharris   task_context->task_phase = 0x01;
729230557Sjimharris}
730230557Sjimharris
731230557Sjimharris/**
732230557Sjimharris * This routine will free any allocated dummy resources for this port.
733230557Sjimharris *
734230557Sjimharris * @param[in, out] this_port The port on which the resources are being destroyed.
735230557Sjimharris */
736230557Sjimharrisstatic
737230557Sjimharrisvoid scic_sds_port_destroy_dummy_resources(
738230557Sjimharris   SCIC_SDS_PORT_T * this_port
739230557Sjimharris)
740230557Sjimharris{
741230557Sjimharris   if (this_port->reserved_tci != SCU_DUMMY_INDEX)
742230557Sjimharris   {
743230557Sjimharris      scic_controller_free_io_tag(
744230557Sjimharris         this_port->owning_controller, this_port->reserved_tci
745230557Sjimharris      );
746230557Sjimharris   }
747230557Sjimharris
748230557Sjimharris   if (this_port->reserved_rni != SCU_DUMMY_INDEX)
749230557Sjimharris   {
750230557Sjimharris      scic_sds_remote_node_table_release_remote_node_index(
751230557Sjimharris         &this_port->owning_controller->available_remote_nodes, 1, this_port->reserved_rni
752230557Sjimharris      );
753230557Sjimharris   }
754230557Sjimharris
755230557Sjimharris   this_port->reserved_rni = SCU_DUMMY_INDEX;
756230557Sjimharris   this_port->reserved_tci = SCU_DUMMY_INDEX;
757230557Sjimharris}
758230557Sjimharris
759230557Sjimharris/**
760230557Sjimharris * @brief
761230557Sjimharris *
762230557Sjimharris * @param[in] this_port
763230557Sjimharris * @param[in] port_index
764230557Sjimharris * @param[in] owning_controller
765230557Sjimharris */
766230557Sjimharrisvoid scic_sds_port_construct(
767230557Sjimharris   SCIC_SDS_PORT_T         *this_port,
768230557Sjimharris   U8                      port_index,
769230557Sjimharris   SCIC_SDS_CONTROLLER_T   *owning_controller
770230557Sjimharris)
771230557Sjimharris{
772230557Sjimharris   U32 index;
773230557Sjimharris
774230557Sjimharris   sci_base_port_construct(
775230557Sjimharris      &this_port->parent,
776230557Sjimharris      sci_base_object_get_logger(owning_controller),
777230557Sjimharris      scic_sds_port_state_table
778230557Sjimharris   );
779230557Sjimharris
780230557Sjimharris   sci_base_state_machine_construct(
781230557Sjimharris      scic_sds_port_get_ready_substate_machine(this_port),
782230557Sjimharris      &this_port->parent.parent,
783230557Sjimharris      scic_sds_port_ready_substate_table,
784230557Sjimharris      SCIC_SDS_PORT_READY_SUBSTATE_WAITING
785230557Sjimharris   );
786230557Sjimharris
787230557Sjimharris   scic_sds_port_initialize_state_logging(this_port);
788230557Sjimharris
789230557Sjimharris   this_port->logical_port_index  = SCIC_SDS_DUMMY_PORT;
790230557Sjimharris   this_port->physical_port_index = port_index;
791230557Sjimharris   this_port->active_phy_mask     = 0;
792230557Sjimharris   this_port->enabled_phy_mask    = 0;
793230557Sjimharris   this_port->owning_controller = owning_controller;
794230557Sjimharris
795230557Sjimharris   this_port->started_request_count = 0;
796230557Sjimharris   this_port->assigned_device_count = 0;
797230557Sjimharris
798230557Sjimharris   this_port->reserved_rni = SCU_DUMMY_INDEX;
799230557Sjimharris   this_port->reserved_tci = SCU_DUMMY_INDEX;
800230557Sjimharris
801230557Sjimharris   this_port->timer_handle = SCI_INVALID_HANDLE;
802230557Sjimharris
803230557Sjimharris   this_port->port_task_scheduler_registers = NULL;
804230557Sjimharris
805230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
806230557Sjimharris   {
807230557Sjimharris      this_port->phy_table[index] = NULL;
808230557Sjimharris   }
809230557Sjimharris}
810230557Sjimharris
811230557Sjimharris/**
812230557Sjimharris * @brief This method performs initialization of the supplied port.
813230557Sjimharris *        Initialization includes:
814230557Sjimharris *        - state machine initialization
815230557Sjimharris *        - member variable initialization
816230557Sjimharris *        - configuring the phy_mask
817230557Sjimharris *
818230557Sjimharris * @param[in] this_port
819230557Sjimharris * @param[in] transport_layer_registers
820230557Sjimharris * @param[in] port_task_scheduler_registers
821230557Sjimharris * @param[in] port_configuration_regsiter
822230557Sjimharris *
823230557Sjimharris * @return SCI_STATUS
824230557Sjimharris * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is
825230557Sjimharris *         returned if the phy being added to the port
826230557Sjimharris */
827230557SjimharrisSCI_STATUS scic_sds_port_initialize(
828230557Sjimharris   SCIC_SDS_PORT_T *this_port,
829230557Sjimharris   void            *port_task_scheduler_registers,
830230557Sjimharris   void            *port_configuration_regsiter,
831230557Sjimharris   void            *viit_registers
832230557Sjimharris)
833230557Sjimharris{
834230557Sjimharris   this_port->port_task_scheduler_registers  = port_task_scheduler_registers;
835230557Sjimharris   this_port->port_pe_configuration_register = port_configuration_regsiter;
836230557Sjimharris   this_port->viit_registers                 = viit_registers;
837230557Sjimharris
838230557Sjimharris   return SCI_SUCCESS;
839230557Sjimharris}
840230557Sjimharris
841230557Sjimharris/**
842230557Sjimharris * This method is the a general link up handler for the SCIC_SDS_PORT object.
843230557Sjimharris * This function will determine if this SCIC_SDS_PHY can
844230557Sjimharris * be assigned to this SCIC_SDS_PORT object. If the SCIC_SDS_PHY object can
845230557Sjimharris * is not a valid PHY for this port then the function will notify the SCIC_USER.
846230557Sjimharris * A PHY can only be part of a port if it's attached SAS ADDRESS is the same as
847230557Sjimharris * all other PHYs in the same port.
848230557Sjimharris *
849230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object for which has a phy
850230557Sjimharris *       that has gone link up.
851230557Sjimharris * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link up.
852230557Sjimharris * @param[in] do_notify_user This parameter specifies whether to inform
853230557Sjimharris *            the user (via scic_cb_port_link_up()) as to the fact that
854230557Sjimharris *            a new phy as become ready.
855230557Sjimharris * @param[in] do_resume_phy This parameter specifies whether to resume the phy.
856230557Sjimharris *            If this function is called from MPC mode, it will be always true.
857230557Sjimharris *            for APC, this will be false, so that phys could be resumed later
858230557Sjimharris *
859230557Sjimharris * @return none
860230557Sjimharris */
861230557Sjimharrisvoid scic_sds_port_general_link_up_handler(
862230557Sjimharris   SCIC_SDS_PORT_T * this_port,
863230557Sjimharris   SCIC_SDS_PHY_T  * the_phy,
864230557Sjimharris   BOOL              do_notify_user,
865230557Sjimharris   BOOL              do_resume_phy
866230557Sjimharris)
867230557Sjimharris{
868230557Sjimharris   SCI_SAS_ADDRESS_T  port_sas_address;
869230557Sjimharris   SCI_SAS_ADDRESS_T  phy_sas_address;
870230557Sjimharris
871230557Sjimharris   scic_sds_port_get_attached_sas_address(this_port, &port_sas_address);
872230557Sjimharris   scic_sds_phy_get_attached_sas_address(the_phy, &phy_sas_address);
873230557Sjimharris
874230557Sjimharris   // If the SAS address of the new phy matches the SAS address of
875230557Sjimharris   // other phys in the port OR this is the first phy in the port,
876230557Sjimharris   // then activate the phy and allow it to be used for operations
877230557Sjimharris   // in this port.
878230557Sjimharris   if (
879230557Sjimharris         (
880230557Sjimharris            (phy_sas_address.high == port_sas_address.high)
881230557Sjimharris         && (phy_sas_address.low  == port_sas_address.low )
882230557Sjimharris         )
883230557Sjimharris         || (this_port->active_phy_mask == 0)
884230557Sjimharris      )
885230557Sjimharris   {
886230557Sjimharris      scic_sds_port_activate_phy(this_port, the_phy, do_notify_user, do_resume_phy);
887230557Sjimharris
888230557Sjimharris      if (this_port->parent.state_machine.current_state_id
889230557Sjimharris          == SCI_BASE_PORT_STATE_RESETTING)
890230557Sjimharris      {
891230557Sjimharris         sci_base_state_machine_change_state(
892230557Sjimharris            &this_port->parent.state_machine, SCI_BASE_PORT_STATE_READY
893230557Sjimharris         );
894230557Sjimharris      }
895230557Sjimharris   }
896230557Sjimharris   else
897230557Sjimharris   {
898230557Sjimharris      scic_sds_port_invalid_link_up(this_port, the_phy);
899230557Sjimharris   }
900230557Sjimharris}
901230557Sjimharris
902230557Sjimharris// ---------------------------------------------------------------------------
903230557Sjimharris
904230557SjimharrisSCI_STATUS scic_port_add_phy(
905230557Sjimharris   SCI_PORT_HANDLE_T handle,
906230557Sjimharris   SCI_PHY_HANDLE_T phy
907230557Sjimharris)
908230557Sjimharris{
909230557Sjimharris   #if defined (SCI_LOGGING)
910230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)handle;
911230557Sjimharris   #endif // defined (SCI_LOGGING)
912230557Sjimharris
913230557Sjimharris   SCIC_LOG_TRACE((
914230557Sjimharris      sci_base_object_get_logger(this_port),
915230557Sjimharris      SCIC_LOG_OBJECT_PORT,
916230557Sjimharris      "scic_port_add_phy(0x%x, 0x%x) enter\n",
917230557Sjimharris      handle, phy
918230557Sjimharris   ));
919230557Sjimharris
920230557Sjimharris   SCIC_LOG_ERROR((
921230557Sjimharris      sci_base_object_get_logger(this_port),
922230557Sjimharris      SCIC_LOG_OBJECT_PORT,
923230557Sjimharris      "Interface function scic_port_add_phy() has been deprecated. "
924230557Sjimharris      "PORT configuration is handled through the OEM parameters.\n"
925230557Sjimharris   ));
926230557Sjimharris
927230557Sjimharris   return SCI_FAILURE_ADDING_PHY_UNSUPPORTED;
928230557Sjimharris
929230557Sjimharris}
930230557Sjimharris
931230557Sjimharris// ---------------------------------------------------------------------------
932230557Sjimharris
933230557SjimharrisSCI_STATUS scic_port_remove_phy(
934230557Sjimharris   SCI_PORT_HANDLE_T handle,
935230557Sjimharris   SCI_PHY_HANDLE_T phy
936230557Sjimharris)
937230557Sjimharris{
938230557Sjimharris   #if defined (SCI_LOGGING)
939230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)handle;
940230557Sjimharris   #endif // defined (SCI_LOGGING)
941230557Sjimharris
942230557Sjimharris   SCIC_LOG_TRACE((
943230557Sjimharris      sci_base_object_get_logger(this_port),
944230557Sjimharris      SCIC_LOG_OBJECT_PORT,
945230557Sjimharris      "scic_port_remove_phy(0x%x, 0x%x) enter\n",
946230557Sjimharris      handle, phy
947230557Sjimharris   ));
948230557Sjimharris
949230557Sjimharris   SCIC_LOG_ERROR((
950230557Sjimharris      sci_base_object_get_logger(this_port),
951230557Sjimharris      SCIC_LOG_OBJECT_PORT,
952230557Sjimharris      "Interface function scic_port_remove_phy() has been deprecated. "
953230557Sjimharris      "PORT configuration is handled through the OEM parameters.\n"
954230557Sjimharris   ));
955230557Sjimharris
956230557Sjimharris   return SCI_FAILURE_ADDING_PHY_UNSUPPORTED;
957230557Sjimharris}
958230557Sjimharris
959230557Sjimharris// ---------------------------------------------------------------------------
960230557Sjimharris
961230557SjimharrisSCI_STATUS scic_port_get_properties(
962230557Sjimharris   SCI_PORT_HANDLE_T        port,
963230557Sjimharris   SCIC_PORT_PROPERTIES_T * properties
964230557Sjimharris)
965230557Sjimharris{
966230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
967230557Sjimharris
968230557Sjimharris   SCIC_LOG_TRACE((
969230557Sjimharris      sci_base_object_get_logger(this_port),
970230557Sjimharris      SCIC_LOG_OBJECT_PORT,
971230557Sjimharris      "scic_port_get_properties(0x%x, 0x%x) enter\n",
972230557Sjimharris      port, properties
973230557Sjimharris   ));
974230557Sjimharris
975230557Sjimharris   if (
976230557Sjimharris         (port == SCI_INVALID_HANDLE)
977230557Sjimharris      || (this_port->logical_port_index == SCIC_SDS_DUMMY_PORT)
978230557Sjimharris      )
979230557Sjimharris   {
980230557Sjimharris      return SCI_FAILURE_INVALID_PORT;
981230557Sjimharris   }
982230557Sjimharris
983230557Sjimharris   properties->index    = this_port->logical_port_index;
984230557Sjimharris   properties->phy_mask = scic_sds_port_get_phys(this_port);
985230557Sjimharris   scic_sds_port_get_sas_address(this_port, &properties->local.sas_address);
986230557Sjimharris   scic_sds_port_get_protocols(this_port, &properties->local.protocols);
987230557Sjimharris   scic_sds_port_get_attached_sas_address(this_port, &properties->remote.sas_address);
988230557Sjimharris   scic_sds_port_get_attached_protocols(this_port, &properties->remote.protocols);
989230557Sjimharris
990230557Sjimharris   return SCI_SUCCESS;
991230557Sjimharris}
992230557Sjimharris
993230557Sjimharris// ---------------------------------------------------------------------------
994230557Sjimharris
995230557SjimharrisSCI_STATUS scic_port_hard_reset(
996230557Sjimharris   SCI_PORT_HANDLE_T handle,
997230557Sjimharris   U32               reset_timeout
998230557Sjimharris)
999230557Sjimharris{
1000230557Sjimharris   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)handle;
1001230557Sjimharris
1002230557Sjimharris   SCIC_LOG_TRACE((
1003230557Sjimharris      sci_base_object_get_logger(this_port),
1004230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1005230557Sjimharris      "scic_port_hard_reset(0x%x, 0x%x) enter\n",
1006230557Sjimharris      handle, reset_timeout
1007230557Sjimharris   ));
1008230557Sjimharris
1009230557Sjimharris   return this_port->state_handlers->parent.reset_handler(
1010230557Sjimharris                                       &this_port->parent,
1011230557Sjimharris                                       reset_timeout
1012230557Sjimharris                                     );
1013230557Sjimharris}
1014230557Sjimharris
1015230557Sjimharris/**
1016230557Sjimharris * This method assigns the direct attached device ID for this port.
1017230557Sjimharris *
1018230557Sjimharris * @param[in] this_port The port for which the direct attached device id is to
1019230557Sjimharris *       be assigned.
1020230557Sjimharris * @param[in] device_id The direct attached device ID to assign to the port.
1021230557Sjimharris *       This will be the RNi for the device
1022230557Sjimharris */
1023230557Sjimharrisvoid scic_sds_port_setup_transports(
1024230557Sjimharris   SCIC_SDS_PORT_T * this_port,
1025230557Sjimharris   U32               device_id
1026230557Sjimharris)
1027230557Sjimharris{
1028230557Sjimharris   U8 index;
1029230557Sjimharris
1030230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
1031230557Sjimharris   {
1032230557Sjimharris      if (this_port->active_phy_mask & (1 << index))
1033230557Sjimharris      {
1034230557Sjimharris         scic_sds_phy_setup_transport(this_port->phy_table[index], device_id);
1035230557Sjimharris      }
1036230557Sjimharris   }
1037230557Sjimharris}
1038230557Sjimharris
1039230557Sjimharris/**
1040230557Sjimharris * This method will resume the phy which is already added in the port.
1041230557Sjimharris * Activation includes:
1042230557Sjimharris * - enabling the Protocol Engine in the silicon.
1043230557Sjimharris * - update the reay mask.
1044230557Sjimharris *
1045230557Sjimharris * @param[in] this_port This is the port on which the phy should be enabled.
1046230557Sjimharris * @return none
1047230557Sjimharris */
1048230557Sjimharrisstatic
1049230557Sjimharrisvoid scic_sds_port_resume_phy(
1050230557Sjimharris   SCIC_SDS_PORT_T * this_port,
1051230557Sjimharris   SCIC_SDS_PHY_T  * the_phy
1052230557Sjimharris)
1053230557Sjimharris{
1054230557Sjimharris   scic_sds_phy_resume (the_phy);
1055230557Sjimharris   this_port->enabled_phy_mask |= 1 << the_phy->phy_index;
1056230557Sjimharris}
1057230557Sjimharris/**
1058230557Sjimharris * This method will activate the phy in the port.
1059230557Sjimharris * Activation includes:
1060230557Sjimharris * - adding the phy to the port
1061230557Sjimharris * - enabling the Protocol Engine in the silicon.
1062230557Sjimharris * - notifying the user that the link is up.
1063230557Sjimharris *
1064230557Sjimharris * @param[in] this_port This is the port on which the phy should be enabled.
1065230557Sjimharris * @param[in] the_phy This is the specific phy which to enable.
1066230557Sjimharris * @param[in] do_notify_user This parameter specifies whether to inform
1067230557Sjimharris *            the user (via scic_cb_port_link_up()) as to the fact that
1068230557Sjimharris *            a new phy as become ready.
1069230557Sjimharris * @param[in] do_resume_phy This parameter specifies whether to resume the phy.
1070230557Sjimharris *            If this function is called from MPC mode, it will be always true.
1071230557Sjimharris *            for APC, this will be false, so that phys could be resumed later
1072230557Sjimharris *
1073230557Sjimharris
1074230557Sjimharris * @return none
1075230557Sjimharris */
1076230557Sjimharrisvoid scic_sds_port_activate_phy(
1077230557Sjimharris   SCIC_SDS_PORT_T * this_port,
1078230557Sjimharris   SCIC_SDS_PHY_T  * the_phy,
1079230557Sjimharris   BOOL              do_notify_user,
1080230557Sjimharris   BOOL              do_resume_phy
1081230557Sjimharris)
1082230557Sjimharris{
1083230557Sjimharris   SCIC_SDS_CONTROLLER_T                      * controller;
1084230557Sjimharris   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T   protocols;
1085230557Sjimharris
1086230557Sjimharris   SCIC_LOG_TRACE((
1087230557Sjimharris      sci_base_object_get_logger(this_port),
1088230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1089230557Sjimharris      "scic_sds_port_activate_phy(0x%x,0x%x,0x%x) enter\n",
1090230557Sjimharris      this_port, the_phy, do_notify_user
1091230557Sjimharris   ));
1092230557Sjimharris
1093230557Sjimharris   controller = scic_sds_port_get_controller(this_port);
1094230557Sjimharris   scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols);
1095230557Sjimharris
1096230557Sjimharris   // If this is sata port then the phy has already been resumed
1097230557Sjimharris   if (!protocols.u.bits.stp_target)
1098230557Sjimharris   {
1099230557Sjimharris      if (do_resume_phy == TRUE)
1100230557Sjimharris      {
1101230557Sjimharris         scic_sds_port_resume_phy(this_port, the_phy);
1102230557Sjimharris      }
1103230557Sjimharris   }
1104230557Sjimharris
1105230557Sjimharris   this_port->active_phy_mask |= 1 << the_phy->phy_index;
1106230557Sjimharris
1107230557Sjimharris   scic_sds_controller_clear_invalid_phy(controller, the_phy);
1108230557Sjimharris
1109230557Sjimharris   if (do_notify_user == TRUE)
1110230557Sjimharris      scic_cb_port_link_up(this_port->owning_controller, this_port, the_phy);
1111230557Sjimharris}
1112230557Sjimharris
1113230557Sjimharris/**
1114230557Sjimharris * This method will deactivate the supplied phy in the port.
1115230557Sjimharris *
1116230557Sjimharris * @param[in] this_port This is the port on which the phy should be
1117230557Sjimharris *            deactivated.
1118230557Sjimharris * @param[in] the_phy This is the specific phy that is no longer
1119230557Sjimharris *            active in the port.
1120230557Sjimharris * @param[in] do_notify_user This parameter specifies whether to inform
1121230557Sjimharris *            the user (via scic_cb_port_link_down()) as to the fact that
1122230557Sjimharris *            a new phy as become ready.
1123230557Sjimharris *
1124230557Sjimharris * @return none
1125230557Sjimharris */
1126230557Sjimharrisvoid scic_sds_port_deactivate_phy(
1127230557Sjimharris   SCIC_SDS_PORT_T * this_port,
1128230557Sjimharris   SCIC_SDS_PHY_T  * the_phy,
1129230557Sjimharris   BOOL              do_notify_user
1130230557Sjimharris)
1131230557Sjimharris{
1132230557Sjimharris   SCIC_LOG_TRACE((
1133230557Sjimharris      sci_base_object_get_logger(this_port),
1134230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1135230557Sjimharris      "scic_sds_port_deactivate_phy(0x%x,0x%x,0x%x) enter\n",
1136230557Sjimharris      this_port, the_phy, do_notify_user
1137230557Sjimharris   ));
1138230557Sjimharris
1139230557Sjimharris   this_port->active_phy_mask &= ~(1 << the_phy->phy_index);
1140230557Sjimharris   this_port->enabled_phy_mask  &= ~(1 << the_phy->phy_index);
1141230557Sjimharris
1142230557Sjimharris   the_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE;
1143230557Sjimharris
1144230557Sjimharris   // Re-assign the phy back to the LP as if it were a narrow port for APC mode.
1145230557Sjimharris   // For MPC mode, the phy will remain in the port
1146230557Sjimharris   if (this_port->owning_controller->oem_parameters.sds1.controller.mode_type
1147230557Sjimharris       == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
1148230557Sjimharris   {
1149230557Sjimharris   SCU_PCSPExCR_WRITE(this_port, the_phy->phy_index, the_phy->phy_index);
1150230557Sjimharris   }
1151230557Sjimharris
1152230557Sjimharris   if (do_notify_user == TRUE)
1153230557Sjimharris      scic_cb_port_link_down(this_port->owning_controller, this_port, the_phy);
1154230557Sjimharris}
1155230557Sjimharris
1156230557Sjimharris/**
1157230557Sjimharris * This method will disable the phy and report that the phy is not valid for this
1158230557Sjimharris * port object.
1159230557Sjimharris *
1160230557Sjimharris * @param[in] this_port This is the port on which the phy should be disabled.
1161230557Sjimharris * @param[in] the_phy This is the specific phy which to disabled.
1162230557Sjimharris *
1163230557Sjimharris * @return None
1164230557Sjimharris */
1165230557Sjimharrisvoid scic_sds_port_invalid_link_up(
1166230557Sjimharris   SCIC_SDS_PORT_T * this_port,
1167230557Sjimharris   SCIC_SDS_PHY_T  * the_phy
1168230557Sjimharris)
1169230557Sjimharris{
1170230557Sjimharris   SCIC_SDS_CONTROLLER_T * controller = scic_sds_port_get_controller(this_port);
1171230557Sjimharris
1172230557Sjimharris   // Check to see if we have alreay reported this link as bad and if not go
1173230557Sjimharris   // ahead and tell the SCI_USER that we have discovered an invalid link.
1174230557Sjimharris   if ((controller->invalid_phy_mask & (1 << the_phy->phy_index)) == 0)
1175230557Sjimharris   {
1176230557Sjimharris      scic_sds_controller_set_invalid_phy(controller, the_phy);
1177230557Sjimharris
1178230557Sjimharris      scic_cb_port_invalid_link_up(controller, this_port, the_phy);
1179230557Sjimharris   }
1180230557Sjimharris}
1181230557Sjimharris
1182230557Sjimharris/**
1183230557Sjimharris * @brief This method returns FALSE if the port only has a single phy object
1184230557Sjimharris *        assigned.  If there are no phys or more than one phy then the
1185230557Sjimharris *        method will return TRUE.
1186230557Sjimharris *
1187230557Sjimharris * @param[in] this_port The port for which the wide port condition is to be
1188230557Sjimharris *            checked.
1189230557Sjimharris *
1190230557Sjimharris * @return BOOL
1191230557Sjimharris * @retval TRUE Is returned if this is a wide ported port.
1192230557Sjimharris * @retval FALSE Is returned if this is a narrow port.
1193230557Sjimharris */
1194230557Sjimharrisstatic
1195230557SjimharrisBOOL scic_sds_port_is_wide(
1196230557Sjimharris   SCIC_SDS_PORT_T *this_port
1197230557Sjimharris)
1198230557Sjimharris{
1199230557Sjimharris   U32 index;
1200230557Sjimharris   U32 phy_count = 0;
1201230557Sjimharris
1202230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
1203230557Sjimharris   {
1204230557Sjimharris      if (this_port->phy_table[index] != NULL)
1205230557Sjimharris      {
1206230557Sjimharris         phy_count++;
1207230557Sjimharris      }
1208230557Sjimharris   }
1209230557Sjimharris
1210230557Sjimharris   return (phy_count != 1);
1211230557Sjimharris}
1212230557Sjimharris
1213230557Sjimharris/**
1214230557Sjimharris * @brief This method is called by the PHY object when the link is detected.
1215230557Sjimharris *        if the port wants the PHY to continue on to the link up state then
1216230557Sjimharris *        the port layer must return TRUE.  If the port object returns FALSE
1217230557Sjimharris *        the phy object must halt its attempt to go link up.
1218230557Sjimharris *
1219230557Sjimharris * @param[in] this_port The port associated with the phy object.
1220230557Sjimharris * @param[in] the_phy The phy object that is trying to go link up.
1221230557Sjimharris *
1222230557Sjimharris * @return TRUE if the phy object can continue to the link up condition.
1223230557Sjimharris * @retval TRUE Is returned if this phy can continue to the ready state.
1224230557Sjimharris * @retval FALSE Is returned if can not continue on to the ready state.
1225230557Sjimharris *
1226230557Sjimharris * @note This notification is in place for wide ports and direct attached
1227230557Sjimharris *       phys.  Since there are no wide ported SATA devices this could
1228230557Sjimharris *       become an invalid port configuration.
1229230557Sjimharris */
1230230557SjimharrisBOOL scic_sds_port_link_detected(
1231230557Sjimharris   SCIC_SDS_PORT_T *this_port,
1232230557Sjimharris   SCIC_SDS_PHY_T  *the_phy
1233230557Sjimharris)
1234230557Sjimharris{
1235230557Sjimharris   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T protocols;
1236230557Sjimharris
1237230557Sjimharris   scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols);
1238230557Sjimharris
1239230557Sjimharris   if (
1240230557Sjimharris         (this_port->logical_port_index != SCIC_SDS_DUMMY_PORT)
1241230557Sjimharris      && (protocols.u.bits.stp_target)
1242230557Sjimharris      )
1243230557Sjimharris   {
1244230557Sjimharris      if (scic_sds_port_is_wide(this_port))
1245230557Sjimharris      {
1246230557Sjimharris         //direct attached Sata phy cannot be in wide port.
1247230557Sjimharris         scic_sds_port_invalid_link_up( this_port, the_phy);
1248230557Sjimharris      return FALSE;
1249230557Sjimharris   }
1250230557Sjimharris      else
1251230557Sjimharris      {
1252230557Sjimharris         SCIC_SDS_PORT_T *destination_port = &(this_port->owning_controller->port_table[the_phy->phy_index]);
1253230557Sjimharris
1254230557Sjimharris         //add the phy to the its logical port for direct attached SATA. The phy will be added
1255230557Sjimharris         //to port whose port_index will be the phy_index.
1256230557Sjimharris         SCU_PCSPExCR_WRITE( destination_port, the_phy->phy_index, the_phy->phy_index);
1257230557Sjimharris      }
1258230557Sjimharris   }
1259230557Sjimharris
1260230557Sjimharris   return TRUE;
1261230557Sjimharris}
1262230557Sjimharris
1263230557Sjimharris/**
1264230557Sjimharris * @brief This method is the entry point for the phy to inform
1265230557Sjimharris *        the port that it is now in a ready state
1266230557Sjimharris *
1267230557Sjimharris * @param[in] this_port
1268230557Sjimharris * @param[in] phy
1269230557Sjimharris */
1270230557Sjimharrisvoid scic_sds_port_link_up(
1271230557Sjimharris   SCIC_SDS_PORT_T *this_port,
1272230557Sjimharris   SCIC_SDS_PHY_T  *the_phy
1273230557Sjimharris)
1274230557Sjimharris{
1275230557Sjimharris   the_phy->is_in_link_training = FALSE;
1276230557Sjimharris
1277230557Sjimharris   this_port->state_handlers->link_up_handler(this_port, the_phy);
1278230557Sjimharris}
1279230557Sjimharris
1280230557Sjimharris/**
1281230557Sjimharris * @brief This method is the entry point for the phy to inform
1282230557Sjimharris *        the port that it is no longer in a ready state
1283230557Sjimharris *
1284230557Sjimharris * @param[in] this_port
1285230557Sjimharris * @param[in] phy
1286230557Sjimharris */
1287230557Sjimharrisvoid scic_sds_port_link_down(
1288230557Sjimharris   SCIC_SDS_PORT_T *this_port,
1289230557Sjimharris   SCIC_SDS_PHY_T  *the_phy
1290230557Sjimharris)
1291230557Sjimharris{
1292230557Sjimharris   this_port->state_handlers->link_down_handler(this_port, the_phy);
1293230557Sjimharris}
1294230557Sjimharris
1295230557Sjimharris/**
1296230557Sjimharris * @brief This method is called to start an IO request on this port.
1297230557Sjimharris *
1298230557Sjimharris * @param[in] this_port
1299230557Sjimharris * @param[in] the_device
1300230557Sjimharris * @param[in] the_io_request
1301230557Sjimharris *
1302230557Sjimharris * @return SCI_STATUS
1303230557Sjimharris */
1304230557SjimharrisSCI_STATUS scic_sds_port_start_io(
1305230557Sjimharris   SCIC_SDS_PORT_T          *this_port,
1306230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *the_device,
1307230557Sjimharris   SCIC_SDS_REQUEST_T       *the_io_request
1308230557Sjimharris)
1309230557Sjimharris{
1310230557Sjimharris   return this_port->state_handlers->start_io_handler(
1311230557Sjimharris                                       this_port, the_device, the_io_request);
1312230557Sjimharris}
1313230557Sjimharris
1314230557Sjimharris/**
1315230557Sjimharris * @brief This method is called to complete an IO request to the port.
1316230557Sjimharris *
1317230557Sjimharris * @param[in] this_port
1318230557Sjimharris * @param[in] the_device
1319230557Sjimharris * @param[in] the_io_request
1320230557Sjimharris *
1321230557Sjimharris * @return SCI_STATUS
1322230557Sjimharris */
1323230557SjimharrisSCI_STATUS scic_sds_port_complete_io(
1324230557Sjimharris   SCIC_SDS_PORT_T          *this_port,
1325230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *the_device,
1326230557Sjimharris   SCIC_SDS_REQUEST_T       *the_io_request
1327230557Sjimharris)
1328230557Sjimharris{
1329230557Sjimharris   return this_port->state_handlers->complete_io_handler(
1330230557Sjimharris                                       this_port, the_device, the_io_request);
1331230557Sjimharris}
1332230557Sjimharris
1333230557Sjimharris/**
1334230557Sjimharris * @brief This method is provided to timeout requests for port operations.
1335230557Sjimharris *        Mostly its for the port reset operation.
1336230557Sjimharris *
1337230557Sjimharris * @param[in] port This is the parameter or cookie value that is provided
1338230557Sjimharris *       to the timer construct operation.
1339230557Sjimharris */
1340230557Sjimharrisvoid scic_sds_port_timeout_handler(
1341230557Sjimharris   void *port
1342230557Sjimharris)
1343230557Sjimharris{
1344230557Sjimharris   U32 current_state;
1345230557Sjimharris   SCIC_SDS_PORT_T * this_port;
1346230557Sjimharris
1347230557Sjimharris   this_port = (SCIC_SDS_PORT_T *)port;
1348230557Sjimharris   current_state = sci_base_state_machine_get_state(
1349230557Sjimharris                           &this_port->parent.state_machine);
1350230557Sjimharris
1351230557Sjimharris   if (current_state == SCI_BASE_PORT_STATE_RESETTING)
1352230557Sjimharris   {
1353230557Sjimharris      // if the port is still in the resetting state then the timeout fired
1354230557Sjimharris      // before the reset completed.
1355230557Sjimharris      sci_base_state_machine_change_state(
1356230557Sjimharris         &this_port->parent.state_machine,
1357230557Sjimharris         SCI_BASE_PORT_STATE_FAILED
1358230557Sjimharris      );
1359230557Sjimharris   }
1360230557Sjimharris   else if (current_state == SCI_BASE_PORT_STATE_STOPPED)
1361230557Sjimharris   {
1362230557Sjimharris      // if the port is stopped then the start request failed
1363230557Sjimharris      // In this case stay in the stopped state.
1364230557Sjimharris      SCIC_LOG_ERROR((
1365230557Sjimharris         sci_base_object_get_logger(this_port),
1366230557Sjimharris         SCIC_LOG_OBJECT_PORT,
1367230557Sjimharris         "SCIC Port 0x%x failed to stop before tiemout.\n",
1368230557Sjimharris         this_port
1369230557Sjimharris      ));
1370230557Sjimharris   }
1371230557Sjimharris   else if (current_state == SCI_BASE_PORT_STATE_STOPPING)
1372230557Sjimharris   {
1373230557Sjimharris      // if the port is still stopping then the stop has not completed
1374230557Sjimharris      scic_cb_port_stop_complete(
1375230557Sjimharris         scic_sds_port_get_controller(this_port),
1376230557Sjimharris         port,
1377230557Sjimharris         SCI_FAILURE_TIMEOUT
1378230557Sjimharris      );
1379230557Sjimharris   }
1380230557Sjimharris   else
1381230557Sjimharris   {
1382230557Sjimharris      // The port is in the ready state and we have a timer reporting a timeout
1383230557Sjimharris      // this should not happen.
1384230557Sjimharris      SCIC_LOG_ERROR((
1385230557Sjimharris         sci_base_object_get_logger(this_port),
1386230557Sjimharris         SCIC_LOG_OBJECT_PORT,
1387230557Sjimharris         "SCIC Port 0x%x is processing a timeout operation in state %d.\n",
1388230557Sjimharris         this_port, current_state
1389230557Sjimharris      ));
1390230557Sjimharris   }
1391230557Sjimharris}
1392230557Sjimharris
1393230557Sjimharris// ---------------------------------------------------------------------------
1394230557Sjimharris
1395230557Sjimharris#ifdef SCIC_DEBUG_ENABLED
1396230557Sjimharrisvoid scic_sds_port_decrement_request_count(
1397230557Sjimharris   SCIC_SDS_PORT_T *this_port
1398230557Sjimharris)
1399230557Sjimharris{
1400230557Sjimharris   if (this_port->started_request_count == 0)
1401230557Sjimharris   {
1402230557Sjimharris      SCIC_LOG_WARNING((
1403230557Sjimharris         sci_base_object_get_logger(this_port),
1404230557Sjimharris         SCIC_LOG_OBJECT_PORT,
1405230557Sjimharris         "SCIC Port object requested to decrement started io count past zero.\n"
1406230557Sjimharris      ));
1407230557Sjimharris   }
1408230557Sjimharris   else
1409230557Sjimharris   {
1410230557Sjimharris      this_port->started_request_count--;
1411230557Sjimharris   }
1412230557Sjimharris}
1413230557Sjimharris#endif
1414230557Sjimharris
1415230557Sjimharris/**
1416230557Sjimharris * @brief This function updates the hardwares VIIT entry for this port.
1417230557Sjimharris *
1418230557Sjimharris * @param[in] this_port
1419230557Sjimharris */
1420230557Sjimharrisvoid scic_sds_port_update_viit_entry(
1421230557Sjimharris   SCIC_SDS_PORT_T *this_port
1422230557Sjimharris)
1423230557Sjimharris{
1424230557Sjimharris   SCI_SAS_ADDRESS_T sas_address;
1425230557Sjimharris
1426230557Sjimharris   scic_sds_port_get_sas_address(this_port, &sas_address);
1427230557Sjimharris
1428230557Sjimharris   scu_port_viit_register_write(
1429230557Sjimharris      this_port, initiator_sas_address_hi, sas_address.high);
1430230557Sjimharris
1431230557Sjimharris   scu_port_viit_register_write(
1432230557Sjimharris      this_port, initiator_sas_address_lo, sas_address.low);
1433230557Sjimharris
1434230557Sjimharris   // This value get cleared just in case its not already cleared
1435230557Sjimharris   scu_port_viit_register_write(
1436230557Sjimharris      this_port, reserved, 0);
1437230557Sjimharris
1438230557Sjimharris
1439230557Sjimharris   // We are required to update the status register last
1440230557Sjimharris   scu_port_viit_register_write(
1441230557Sjimharris      this_port, status, (
1442230557Sjimharris           SCU_VIIT_ENTRY_ID_VIIT
1443230557Sjimharris         | SCU_VIIT_IPPT_INITIATOR
1444230557Sjimharris         | ((1UL << this_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT)
1445230557Sjimharris         | SCU_VIIT_STATUS_ALL_VALID
1446230557Sjimharris         )
1447230557Sjimharris   );
1448230557Sjimharris}
1449230557Sjimharris
1450230557Sjimharris/**
1451230557Sjimharris * @brief This method returns the maximum allowed speed for data transfers
1452230557Sjimharris *        on this port.  This maximum allowed speed evaluates to the maximum
1453230557Sjimharris *        speed of the slowest phy in the port.
1454230557Sjimharris *
1455230557Sjimharris * @param[in] this_port This parameter specifies the port for which to
1456230557Sjimharris *            retrieve the maximum allowed speed.
1457230557Sjimharris *
1458230557Sjimharris * @return This method returns the maximum negotiated speed of the slowest
1459230557Sjimharris *         phy in the port.
1460230557Sjimharris */
1461230557SjimharrisSCI_SAS_LINK_RATE scic_sds_port_get_max_allowed_speed(
1462230557Sjimharris   SCIC_SDS_PORT_T * this_port
1463230557Sjimharris)
1464230557Sjimharris{
1465230557Sjimharris   U16                index             = 0;
1466230557Sjimharris   SCI_SAS_LINK_RATE  max_allowed_speed = SCI_SAS_600_GB;
1467230557Sjimharris   SCIC_SDS_PHY_T   * phy               = NULL;
1468230557Sjimharris
1469230557Sjimharris   // Loop through all of the phys in this port and find the phy with the
1470230557Sjimharris   // lowest maximum link rate.
1471230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
1472230557Sjimharris   {
1473230557Sjimharris      phy = this_port->phy_table[index];
1474230557Sjimharris      if (
1475230557Sjimharris            (phy != NULL)
1476230557Sjimharris         && (scic_sds_port_active_phy(this_port, phy) == TRUE)
1477230557Sjimharris         && (phy->max_negotiated_speed < max_allowed_speed)
1478230557Sjimharris         )
1479230557Sjimharris         max_allowed_speed = phy->max_negotiated_speed;
1480230557Sjimharris   }
1481230557Sjimharris
1482230557Sjimharris   return max_allowed_speed;
1483230557Sjimharris}
1484230557Sjimharris
1485230557Sjimharris
1486230557Sjimharris/**
1487230557Sjimharris * @brief This method passes the event to core user.
1488230557Sjimharris * @param[in] this_port The port that a BCN happens.
1489230557Sjimharris * @param[in] this_phy  The phy that receives BCN.
1490230557Sjimharris *
1491230557Sjimharris * @return none
1492230557Sjimharris */
1493230557Sjimharrisvoid scic_sds_port_broadcast_change_received(
1494230557Sjimharris   SCIC_SDS_PORT_T * this_port,
1495230557Sjimharris   SCIC_SDS_PHY_T * this_phy
1496230557Sjimharris)
1497230557Sjimharris{
1498230557Sjimharris   //notify the user.
1499230557Sjimharris   scic_cb_port_bc_change_primitive_recieved(
1500230557Sjimharris      this_port->owning_controller, this_port, this_phy
1501230557Sjimharris   );
1502230557Sjimharris}
1503230557Sjimharris
1504230557Sjimharris
1505230557Sjimharris/**
1506230557Sjimharris * @brief This API methhod enables the broadcast change notification from
1507230557Sjimharris *        underneath hardware.
1508230557Sjimharris * @param[in] this_port The port that a BCN had been disabled from.
1509230557Sjimharris *
1510230557Sjimharris * @return none
1511230557Sjimharris */
1512230557Sjimharrisvoid scic_port_enable_broadcast_change_notification(
1513230557Sjimharris   SCI_PORT_HANDLE_T  port
1514230557Sjimharris)
1515230557Sjimharris{
1516230557Sjimharris   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
1517230557Sjimharris   SCIC_SDS_PHY_T * phy;
1518230557Sjimharris   U32 register_value;
1519230557Sjimharris   U8 index;
1520230557Sjimharris
1521230557Sjimharris   // Loop through all of the phys to enable BCN.
1522230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
1523230557Sjimharris   {
1524230557Sjimharris      phy = this_port->phy_table[index];
1525230557Sjimharris      if ( phy != NULL)
1526230557Sjimharris      {
1527230557Sjimharris         register_value = SCU_SAS_LLCTL_READ(phy);
1528230557Sjimharris
1529230557Sjimharris         // clear the bit by writing 1.
1530230557Sjimharris         SCU_SAS_LLCTL_WRITE(phy, register_value);
1531230557Sjimharris      }
1532230557Sjimharris   }
1533230557Sjimharris}
1534230557Sjimharris
1535230557Sjimharris/**
1536230557Sjimharris * @brief This method release resources in for a scic port.
1537230557Sjimharris *
1538230557Sjimharris * @param[in] controller This parameter specifies the core controller, one of
1539230557Sjimharris *            its phy's resources are to be released.
1540249586Sgabor * @param[in] this_port This parameter specifies the port whose resource is to
1541230557Sjimharris *            be released.
1542230557Sjimharris */
1543230557Sjimharrisvoid scic_sds_port_release_resource(
1544230557Sjimharris   SCIC_SDS_CONTROLLER_T * controller,
1545230557Sjimharris   SCIC_SDS_PORT_T *this_port
1546230557Sjimharris)
1547230557Sjimharris{
1548230557Sjimharris   SCIC_LOG_TRACE((
1549230557Sjimharris      sci_base_object_get_logger(this_port),
1550230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1551230557Sjimharris      "scic_sds_port_release_resource(0x%x, 0x%x)\n",
1552230557Sjimharris      controller, this_port
1553230557Sjimharris   ));
1554230557Sjimharris
1555230557Sjimharris   //Currently, the only resource to be released is a timer.
1556230557Sjimharris   if (this_port->timer_handle != NULL)
1557230557Sjimharris   {
1558230557Sjimharris      scic_cb_timer_destroy(controller, this_port->timer_handle);
1559230557Sjimharris      this_port->timer_handle = NULL;
1560230557Sjimharris   }
1561230557Sjimharris}
1562230557Sjimharris
1563230557Sjimharris
1564230557Sjimharris//******************************************************************************
1565230557Sjimharris//* PORT STATE MACHINE
1566230557Sjimharris//******************************************************************************
1567230557Sjimharris
1568230557Sjimharris//***************************************************************************
1569230557Sjimharris//*  DEFAULT HANDLERS
1570230557Sjimharris//***************************************************************************
1571230557Sjimharris
1572230557Sjimharris/**
1573230557Sjimharris * This is the default method for port a start request.  It will report a
1574230557Sjimharris * warning and exit.
1575230557Sjimharris *
1576230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1577230557Sjimharris *       SCIC_SDS_PORT object.
1578230557Sjimharris *
1579230557Sjimharris * @return SCI_STATUS
1580230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1581230557Sjimharris */
1582230557SjimharrisSCI_STATUS scic_sds_port_default_start_handler(
1583230557Sjimharris   SCI_BASE_PORT_T *port
1584230557Sjimharris)
1585230557Sjimharris{
1586230557Sjimharris   SCIC_LOG_WARNING((
1587230557Sjimharris      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
1588230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1589230557Sjimharris      "SCIC Port 0x%08x requested to start while in invalid state %d\n",
1590230557Sjimharris      port,
1591230557Sjimharris      sci_base_state_machine_get_state(
1592230557Sjimharris         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
1593230557Sjimharris   ));
1594230557Sjimharris
1595230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1596230557Sjimharris}
1597230557Sjimharris
1598230557Sjimharris/**
1599230557Sjimharris * This is the default method for a port stop request.  It will report a
1600230557Sjimharris * warning and exit.
1601230557Sjimharris *
1602230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1603230557Sjimharris *       SCIC_SDS_PORT object.
1604230557Sjimharris *
1605230557Sjimharris * @return SCI_STATUS
1606230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1607230557Sjimharris */
1608230557SjimharrisSCI_STATUS scic_sds_port_default_stop_handler(
1609230557Sjimharris   SCI_BASE_PORT_T *port
1610230557Sjimharris)
1611230557Sjimharris{
1612230557Sjimharris   SCIC_LOG_WARNING((
1613230557Sjimharris      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
1614230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1615230557Sjimharris      "SCIC Port 0x%08x requested to stop while in invalid state %d\n",
1616230557Sjimharris      port,
1617230557Sjimharris      sci_base_state_machine_get_state(
1618230557Sjimharris         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
1619230557Sjimharris   ));
1620230557Sjimharris
1621230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1622230557Sjimharris}
1623230557Sjimharris
1624230557Sjimharris/**
1625230557Sjimharris * This is the default method for a port destruct request.  It will report a
1626230557Sjimharris * warning and exit.
1627230557Sjimharris *
1628230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1629230557Sjimharris *       SCIC_SDS_PORT object.
1630230557Sjimharris *
1631230557Sjimharris * @return SCI_STATUS
1632230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1633230557Sjimharris */
1634230557SjimharrisSCI_STATUS scic_sds_port_default_destruct_handler(
1635230557Sjimharris   SCI_BASE_PORT_T *port
1636230557Sjimharris)
1637230557Sjimharris{
1638230557Sjimharris   SCIC_LOG_WARNING((
1639230557Sjimharris      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
1640230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1641230557Sjimharris      "SCIC Port 0x%08x requested to destruct while in invalid state %d\n",
1642230557Sjimharris      port,
1643230557Sjimharris      sci_base_state_machine_get_state(
1644230557Sjimharris         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
1645230557Sjimharris   ));
1646230557Sjimharris
1647230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1648230557Sjimharris}
1649230557Sjimharris
1650230557Sjimharris/**
1651230557Sjimharris * This is the default method for a port reset request.  It will report a
1652230557Sjimharris * warning and exit.
1653230557Sjimharris *
1654230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1655230557Sjimharris *       SCIC_SDS_PORT object.
1656230557Sjimharris * @param[in] timeout This is the timeout for the reset request to complete.
1657230557Sjimharris *
1658230557Sjimharris * @return SCI_STATUS
1659230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1660230557Sjimharris */
1661230557SjimharrisSCI_STATUS scic_sds_port_default_reset_handler(
1662230557Sjimharris   SCI_BASE_PORT_T * port,
1663230557Sjimharris   U32               timeout
1664230557Sjimharris)
1665230557Sjimharris{
1666230557Sjimharris   SCIC_LOG_WARNING((
1667230557Sjimharris      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
1668230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1669230557Sjimharris      "SCIC Port 0x%08x requested to reset while in invalid state %d\n",
1670230557Sjimharris      port,
1671230557Sjimharris      sci_base_state_machine_get_state(
1672230557Sjimharris         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
1673230557Sjimharris   ));
1674230557Sjimharris
1675230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1676230557Sjimharris}
1677230557Sjimharris
1678230557Sjimharris/**
1679230557Sjimharris * This is the default method for a port add phy request.  It will report a
1680230557Sjimharris * warning and exit.
1681230557Sjimharris *
1682230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1683230557Sjimharris *       SCIC_SDS_PORT object.
1684230557Sjimharris *
1685230557Sjimharris * @return SCI_STATUS
1686230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1687230557Sjimharris */
1688230557SjimharrisSCI_STATUS scic_sds_port_default_add_phy_handler(
1689230557Sjimharris   SCI_BASE_PORT_T *port,
1690230557Sjimharris   SCI_BASE_PHY_T  *phy
1691230557Sjimharris)
1692230557Sjimharris{
1693230557Sjimharris   SCIC_LOG_WARNING((
1694230557Sjimharris      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
1695230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1696230557Sjimharris      "SCIC Port 0x%08x requested to add phy 0x%08x while in invalid state %d\n",
1697230557Sjimharris      port, phy,
1698230557Sjimharris      sci_base_state_machine_get_state(
1699230557Sjimharris         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
1700230557Sjimharris   ));
1701230557Sjimharris
1702230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1703230557Sjimharris}
1704230557Sjimharris
1705230557Sjimharris/**
1706230557Sjimharris * This is the default method for a port remove phy request.  It will report a
1707230557Sjimharris * warning and exit.
1708230557Sjimharris *
1709230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1710230557Sjimharris *       SCIC_SDS_PORT object.
1711230557Sjimharris *
1712230557Sjimharris * @return SCI_STATUS
1713230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1714230557Sjimharris */
1715230557SjimharrisSCI_STATUS scic_sds_port_default_remove_phy_handler(
1716230557Sjimharris   SCI_BASE_PORT_T *port,
1717230557Sjimharris   SCI_BASE_PHY_T  *phy
1718230557Sjimharris)
1719230557Sjimharris{
1720230557Sjimharris   SCIC_LOG_WARNING((
1721230557Sjimharris      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
1722230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1723230557Sjimharris      "SCIC Port 0x%08x requested to remove phy 0x%08x while in invalid state %d\n",
1724230557Sjimharris      port, phy,
1725230557Sjimharris      sci_base_state_machine_get_state(
1726230557Sjimharris         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
1727230557Sjimharris   ));
1728230557Sjimharris
1729230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1730230557Sjimharris}
1731230557Sjimharris
1732230557Sjimharris/**
1733230557Sjimharris * This is the default method for a port unsolicited frame request.  It will
1734230557Sjimharris * report a warning and exit.
1735230557Sjimharris *
1736230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1737230557Sjimharris *       SCIC_SDS_PORT object.
1738230557Sjimharris *
1739230557Sjimharris * @return SCI_STATUS
1740230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1741230557Sjimharris *
1742230557Sjimharris * @todo Is it even possible to receive an unsolicited frame directed to a
1743230557Sjimharris *       port object?  It seems possible if we implementing virtual functions
1744230557Sjimharris *       but until then?
1745230557Sjimharris */
1746230557SjimharrisSCI_STATUS scic_sds_port_default_frame_handler(
1747230557Sjimharris   SCIC_SDS_PORT_T * port,
1748230557Sjimharris   U32               frame_index
1749230557Sjimharris)
1750230557Sjimharris{
1751230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
1752230557Sjimharris
1753230557Sjimharris   SCIC_LOG_WARNING((
1754230557Sjimharris      sci_base_object_get_logger(this_port),
1755230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1756230557Sjimharris      "SCIC Port 0x%08x requested to process frame %d while in invalid state %d\n",
1757230557Sjimharris      port, frame_index,
1758230557Sjimharris      sci_base_state_machine_get_state(
1759230557Sjimharris         scic_sds_port_get_base_state_machine(this_port))
1760230557Sjimharris   ));
1761230557Sjimharris
1762230557Sjimharris   scic_sds_controller_release_frame(
1763230557Sjimharris      scic_sds_port_get_controller(this_port), frame_index
1764230557Sjimharris   );
1765230557Sjimharris
1766230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1767230557Sjimharris}
1768230557Sjimharris
1769230557Sjimharris/**
1770230557Sjimharris * This is the default method for a port event request.  It will report a
1771230557Sjimharris * warning and exit.
1772230557Sjimharris *
1773230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1774230557Sjimharris *       SCIC_SDS_PORT object.
1775230557Sjimharris *
1776230557Sjimharris * @return SCI_STATUS
1777230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1778230557Sjimharris */
1779230557SjimharrisSCI_STATUS scic_sds_port_default_event_handler(
1780230557Sjimharris   SCIC_SDS_PORT_T * port,
1781230557Sjimharris   U32               event_code
1782230557Sjimharris)
1783230557Sjimharris{
1784230557Sjimharris   SCIC_LOG_WARNING((
1785230557Sjimharris      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
1786230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1787230557Sjimharris      "SCIC Port 0x%08x requested to process event 0x%08x while in invalid state %d\n",
1788230557Sjimharris      port, event_code,
1789230557Sjimharris      sci_base_state_machine_get_state(
1790230557Sjimharris         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
1791230557Sjimharris   ));
1792230557Sjimharris
1793230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1794230557Sjimharris}
1795230557Sjimharris
1796230557Sjimharris/**
1797230557Sjimharris * This is the default method for a port link up notification.  It will report
1798230557Sjimharris * a warning and exit.
1799230557Sjimharris *
1800230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1801230557Sjimharris *       SCIC_SDS_PORT object.
1802230557Sjimharris *
1803230557Sjimharris * @return SCI_STATUS
1804230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1805230557Sjimharris */
1806230557Sjimharrisvoid scic_sds_port_default_link_up_handler(
1807230557Sjimharris   SCIC_SDS_PORT_T *this_port,
1808230557Sjimharris   SCIC_SDS_PHY_T  *phy
1809230557Sjimharris)
1810230557Sjimharris{
1811230557Sjimharris   SCIC_LOG_WARNING((
1812230557Sjimharris      sci_base_object_get_logger(this_port),
1813230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1814230557Sjimharris      "SCIC Port 0x%08x received link_up notification from phy 0x%08x while in invalid state %d\n",
1815230557Sjimharris      this_port, phy,
1816230557Sjimharris      sci_base_state_machine_get_state(
1817230557Sjimharris         scic_sds_port_get_base_state_machine(this_port))
1818230557Sjimharris   ));
1819230557Sjimharris}
1820230557Sjimharris
1821230557Sjimharris/**
1822230557Sjimharris * This is the default method for a port link down notification.  It will
1823230557Sjimharris * report a warning and exit.
1824230557Sjimharris *
1825230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1826230557Sjimharris *       SCIC_SDS_PORT object.
1827230557Sjimharris *
1828230557Sjimharris * @return SCI_STATUS
1829230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1830230557Sjimharris */
1831230557Sjimharrisvoid scic_sds_port_default_link_down_handler(
1832230557Sjimharris   SCIC_SDS_PORT_T *this_port,
1833230557Sjimharris   SCIC_SDS_PHY_T  *phy
1834230557Sjimharris)
1835230557Sjimharris{
1836230557Sjimharris   SCIC_LOG_WARNING((
1837230557Sjimharris      sci_base_object_get_logger(this_port),
1838230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1839230557Sjimharris      "SCIC Port 0x%08x received link down notification from phy 0x%08x while in invalid state %d\n",
1840230557Sjimharris      this_port, phy,
1841230557Sjimharris      sci_base_state_machine_get_state(
1842230557Sjimharris         scic_sds_port_get_base_state_machine(this_port))
1843230557Sjimharris   ));
1844230557Sjimharris}
1845230557Sjimharris
1846230557Sjimharris/**
1847230557Sjimharris * This is the default method for a port start io request.  It will report a
1848230557Sjimharris * warning and exit.
1849230557Sjimharris *
1850230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1851230557Sjimharris *       SCIC_SDS_PORT object.
1852230557Sjimharris *
1853230557Sjimharris * @return SCI_STATUS
1854230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1855230557Sjimharris */
1856230557SjimharrisSCI_STATUS scic_sds_port_default_start_io_handler(
1857230557Sjimharris   SCIC_SDS_PORT_T          *this_port,
1858230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *device,
1859230557Sjimharris   SCIC_SDS_REQUEST_T       *io_request
1860230557Sjimharris)
1861230557Sjimharris{
1862230557Sjimharris   SCIC_LOG_WARNING((
1863230557Sjimharris      sci_base_object_get_logger(this_port),
1864230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1865230557Sjimharris      "SCIC Port 0x%08x requested to start io request 0x%08x while in invalid state %d\n",
1866230557Sjimharris      this_port, io_request,
1867230557Sjimharris      sci_base_state_machine_get_state(
1868230557Sjimharris         scic_sds_port_get_base_state_machine(this_port))
1869230557Sjimharris   ));
1870230557Sjimharris
1871230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1872230557Sjimharris}
1873230557Sjimharris
1874230557Sjimharris/**
1875230557Sjimharris * This is the default method for a port complete io request.  It will report
1876230557Sjimharris * a warning and exit.
1877230557Sjimharris *
1878230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1879230557Sjimharris *       SCIC_SDS_PORT object.
1880230557Sjimharris *
1881230557Sjimharris * @return SCI_STATUS
1882230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
1883230557Sjimharris */
1884230557SjimharrisSCI_STATUS scic_sds_port_default_complete_io_handler(
1885230557Sjimharris   SCIC_SDS_PORT_T          *this_port,
1886230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *device,
1887230557Sjimharris   SCIC_SDS_REQUEST_T       *io_request
1888230557Sjimharris)
1889230557Sjimharris{
1890230557Sjimharris   SCIC_LOG_WARNING((
1891230557Sjimharris      sci_base_object_get_logger(this_port),
1892230557Sjimharris      SCIC_LOG_OBJECT_PORT,
1893230557Sjimharris      "SCIC Port 0x%08x requested to complete io request 0x%08x while in invalid state %d\n",
1894230557Sjimharris      this_port, io_request,
1895230557Sjimharris      sci_base_state_machine_get_state(
1896230557Sjimharris         scic_sds_port_get_base_state_machine(this_port))
1897230557Sjimharris   ));
1898230557Sjimharris
1899230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
1900230557Sjimharris}
1901230557Sjimharris
1902230557Sjimharris//****************************************************************************
1903230557Sjimharris//* GENERAL STATE HANDLERS
1904230557Sjimharris//****************************************************************************
1905230557Sjimharris
1906230557Sjimharris/**
1907230557Sjimharris * This is a general complete io request handler for the SCIC_SDS_PORT object.
1908230557Sjimharris *
1909230557Sjimharris * @param[in] port This is the SCIC_SDS_PORT object on which the io request
1910230557Sjimharris *       count will be decremented.
1911230557Sjimharris * @param[in] device This is the SCIC_SDS_REMOTE_DEVICE object to which the io
1912230557Sjimharris *       request is being directed.  This parameter is not required to
1913230557Sjimharris *       complete this operation.
1914230557Sjimharris * @param[in] io_request This is the request that is being completed on this
1915230557Sjimharris *       port object.  This parameter is not required to complete this
1916230557Sjimharris *       operation.
1917230557Sjimharris *
1918230557Sjimharris * @return SCI_STATUS
1919230557Sjimharris * @retval SCI_SUCCESS
1920230557Sjimharris */
1921230557Sjimharrisstatic
1922230557SjimharrisSCI_STATUS scic_sds_port_general_complete_io_handler(
1923230557Sjimharris   SCIC_SDS_PORT_T          *port,
1924230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *device,
1925230557Sjimharris   SCIC_SDS_REQUEST_T       *io_request
1926230557Sjimharris)
1927230557Sjimharris{
1928230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
1929230557Sjimharris
1930230557Sjimharris   scic_sds_port_decrement_request_count(this_port);
1931230557Sjimharris
1932230557Sjimharris   return SCI_SUCCESS;
1933230557Sjimharris}
1934230557Sjimharris
1935230557Sjimharris//****************************************************************************
1936230557Sjimharris//* STOPPED STATE HANDLERS
1937230557Sjimharris//****************************************************************************
1938230557Sjimharrisstatic
1939230557SjimharrisBOOL scic_sds_port_requires_scheduler_workaround(
1940230557Sjimharris   SCIC_SDS_PORT_T * this_port
1941230557Sjimharris)
1942230557Sjimharris{
1943230557Sjimharris   if (
1944230557Sjimharris         (
1945230557Sjimharris           this_port->owning_controller->logical_port_entries
1946230557Sjimharris         < this_port->owning_controller->task_context_entries
1947230557Sjimharris         )
1948230557Sjimharris      && (
1949230557Sjimharris           this_port->owning_controller->logical_port_entries
1950230557Sjimharris         < this_port->owning_controller->remote_node_entries
1951230557Sjimharris         )
1952230557Sjimharris      )
1953230557Sjimharris   {
1954230557Sjimharris      return TRUE;
1955230557Sjimharris   }
1956230557Sjimharris
1957230557Sjimharris   return FALSE;
1958230557Sjimharris}
1959230557Sjimharris
1960230557Sjimharris
1961230557Sjimharris/**
1962230557Sjimharris * This method takes the SCIC_SDS_PORT from a stopped state and attempts to
1963230557Sjimharris * start it.  To start a port it must have no assiged devices and it must have
1964230557Sjimharris * at least one phy assigned to it.  If those conditions are met then the port
1965230557Sjimharris * can transition to the ready state.
1966230557Sjimharris *
1967230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
1968230557Sjimharris *       SCIC_SDS_PORT object.
1969230557Sjimharris *
1970230557Sjimharris * @return SCI_STATUS
1971230557Sjimharris * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This SCIC_SDS_PORT
1972230557Sjimharris *         object could not be started because the port configuration is not
1973230557Sjimharris *         valid.
1974230557Sjimharris * @retval SCI_SUCCESS the start request is successful and the SCIC_SDS_PORT
1975230557Sjimharris *         object has transitioned to the SCI_BASE_PORT_STATE_READY.
1976230557Sjimharris */
1977230557Sjimharrisstatic
1978230557SjimharrisSCI_STATUS scic_sds_port_stopped_state_start_handler(
1979230557Sjimharris   SCI_BASE_PORT_T *port
1980230557Sjimharris)
1981230557Sjimharris{
1982230557Sjimharris   U32 phy_mask;
1983230557Sjimharris   SCI_STATUS status = SCI_SUCCESS;
1984230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
1985230557Sjimharris
1986230557Sjimharris   if (this_port->assigned_device_count > 0)
1987230557Sjimharris   {
1988230557Sjimharris      /// @todo This is a start failure operation because there are still
1989230557Sjimharris      ///       devices assigned to this port.  There must be no devices
1990230557Sjimharris      ///       assigned to a port on a start operation.
1991230557Sjimharris      return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
1992230557Sjimharris   }
1993230557Sjimharris
1994230557Sjimharris   this_port->timer_handle = scic_cb_timer_create(
1995230557Sjimharris      scic_sds_port_get_controller(this_port),
1996230557Sjimharris      scic_sds_port_timeout_handler,
1997230557Sjimharris      this_port
1998230557Sjimharris   );
1999230557Sjimharris
2000230557Sjimharris   if (this_port->timer_handle == SCI_INVALID_HANDLE)
2001230557Sjimharris   {
2002230557Sjimharris      return SCI_FAILURE_INSUFFICIENT_RESOURCES;
2003230557Sjimharris   }
2004230557Sjimharris
2005230557Sjimharris   if (scic_sds_port_requires_scheduler_workaround(this_port))
2006230557Sjimharris   {
2007230557Sjimharris   if (this_port->reserved_rni == SCU_DUMMY_INDEX)
2008230557Sjimharris   {
2009230557Sjimharris      this_port->reserved_rni =
2010230557Sjimharris         scic_sds_remote_node_table_allocate_remote_node(
2011230557Sjimharris            &this_port->owning_controller->available_remote_nodes, 1
2012230557Sjimharris         );
2013230557Sjimharris
2014230557Sjimharris      if (this_port->reserved_rni != SCU_DUMMY_INDEX)
2015230557Sjimharris      {
2016230557Sjimharris         scic_sds_port_construct_dummy_rnc(
2017230557Sjimharris            this_port,
2018230557Sjimharris            this_port->reserved_rni
2019230557Sjimharris         );
2020230557Sjimharris      }
2021230557Sjimharris      else
2022230557Sjimharris      {
2023230557Sjimharris         status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
2024230557Sjimharris      }
2025230557Sjimharris   }
2026230557Sjimharris
2027230557Sjimharris   if (this_port->reserved_tci == SCU_DUMMY_INDEX)
2028230557Sjimharris   {
2029230557Sjimharris      // Allocate a TCI and remove the sequence nibble
2030230557Sjimharris      this_port->reserved_tci =
2031230557Sjimharris         scic_controller_allocate_io_tag(this_port->owning_controller);
2032230557Sjimharris
2033230557Sjimharris      if (this_port->reserved_tci != SCU_DUMMY_INDEX)
2034230557Sjimharris      {
2035230557Sjimharris         scic_sds_port_construct_dummy_task(this_port, this_port->reserved_tci);
2036230557Sjimharris      }
2037230557Sjimharris      else
2038230557Sjimharris      {
2039230557Sjimharris         status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
2040230557Sjimharris      }
2041230557Sjimharris   }
2042230557Sjimharris   }
2043230557Sjimharris
2044230557Sjimharris   if (status == SCI_SUCCESS)
2045230557Sjimharris   {
2046230557Sjimharris      phy_mask = scic_sds_port_get_phys(this_port);
2047230557Sjimharris
2048230557Sjimharris      // There are one or more phys assigned to this port.  Make sure
2049230557Sjimharris      // the port's phy mask is in fact legal and supported by the
2050230557Sjimharris      // silicon.
2051230557Sjimharris      if (scic_sds_port_is_phy_mask_valid(this_port, phy_mask) == TRUE)
2052230557Sjimharris      {
2053230557Sjimharris         sci_base_state_machine_change_state(
2054230557Sjimharris            scic_sds_port_get_base_state_machine(this_port),
2055230557Sjimharris            SCI_BASE_PORT_STATE_READY
2056230557Sjimharris         );
2057230557Sjimharris      }
2058230557Sjimharris      else
2059230557Sjimharris      {
2060230557Sjimharris         status = SCI_FAILURE;
2061230557Sjimharris      }
2062230557Sjimharris   }
2063230557Sjimharris
2064230557Sjimharris   if (status != SCI_SUCCESS)
2065230557Sjimharris   {
2066230557Sjimharris      scic_sds_port_destroy_dummy_resources(this_port);
2067230557Sjimharris   }
2068230557Sjimharris
2069230557Sjimharris   return status;
2070230557Sjimharris}
2071230557Sjimharris
2072230557Sjimharris/**
2073230557Sjimharris * This method takes the SCIC_SDS_PORT that is in a stopped state and handles
2074230557Sjimharris * a stop request.  This function takes no action.
2075230557Sjimharris *
2076230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
2077230557Sjimharris *       SCIC_SDS_PORT object.
2078230557Sjimharris *
2079230557Sjimharris * @return SCI_STATUS
2080230557Sjimharris * @retval SCI_SUCCESS the stop request is successful as the SCIC_SDS_PORT
2081230557Sjimharris *         object is already stopped.
2082230557Sjimharris */
2083230557Sjimharrisstatic
2084230557SjimharrisSCI_STATUS scic_sds_port_stopped_state_stop_handler(
2085230557Sjimharris   SCI_BASE_PORT_T *port
2086230557Sjimharris)
2087230557Sjimharris{
2088230557Sjimharris   // We are already stopped so there is nothing to do here
2089230557Sjimharris   return SCI_SUCCESS;
2090230557Sjimharris}
2091230557Sjimharris
2092230557Sjimharris/**
2093230557Sjimharris * This method takes the SCIC_SDS_PORT that is in a stopped state and handles
2094230557Sjimharris * the destruct request.  The stopped state is the only state in which the
2095230557Sjimharris * SCIC_SDS_PORT can be destroyed.  This function causes the port object to
2096230557Sjimharris * transition to the SCI_BASE_PORT_STATE_FINAL.
2097230557Sjimharris *
2098230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
2099230557Sjimharris *       SCIC_SDS_PORT object.
2100230557Sjimharris *
2101230557Sjimharris * @return SCI_STATUS
2102230557Sjimharris * @retval SCI_SUCCESS
2103230557Sjimharris */
2104230557Sjimharrisstatic
2105230557SjimharrisSCI_STATUS scic_sds_port_stopped_state_destruct_handler(
2106230557Sjimharris   SCI_BASE_PORT_T *port
2107230557Sjimharris)
2108230557Sjimharris{
2109230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
2110230557Sjimharris
2111230557Sjimharris   sci_base_state_machine_stop(&this_port->parent.state_machine);
2112230557Sjimharris
2113230557Sjimharris   return SCI_SUCCESS;
2114230557Sjimharris}
2115230557Sjimharris
2116230557Sjimharris/**
2117230557Sjimharris * This method takes the SCIC_SDS_PORT that is in a stopped state and handles
2118230557Sjimharris * the add phy request.  In MPC mode the only time a phy can be added to a
2119230557Sjimharris * port is in the SCI_BASE_PORT_STATE_STOPPED.
2120230557Sjimharris *
2121230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
2122230557Sjimharris *       SCIC_SDS_PORT object.
2123230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
2124230557Sjimharris *       SCIC_SDS_PHY object.
2125230557Sjimharris *
2126230557Sjimharris * @return SCI_STATUS
2127230557Sjimharris * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy
2128230557Sjimharris *         can not be added to the port.
2129230557Sjimharris * @retval SCI_SUCCESS if the phy is added to the port.
2130230557Sjimharris */
2131230557Sjimharrisstatic
2132230557SjimharrisSCI_STATUS scic_sds_port_stopped_state_add_phy_handler(
2133230557Sjimharris   SCI_BASE_PORT_T *port,
2134230557Sjimharris   SCI_BASE_PHY_T  *phy
2135230557Sjimharris)
2136230557Sjimharris{
2137230557Sjimharris   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
2138230557Sjimharris   SCIC_SDS_PHY_T  * this_phy  = (SCIC_SDS_PHY_T  *)phy;
2139230557Sjimharris   SCI_SAS_ADDRESS_T port_sas_address;
2140230557Sjimharris
2141230557Sjimharris   // Read the port assigned SAS Address if there is one
2142230557Sjimharris   scic_sds_port_get_sas_address(this_port, &port_sas_address);
2143230557Sjimharris
2144230557Sjimharris   if (port_sas_address.high != 0 && port_sas_address.low != 0)
2145230557Sjimharris   {
2146230557Sjimharris      SCI_SAS_ADDRESS_T phy_sas_address;
2147230557Sjimharris
2148230557Sjimharris      // Make sure that the PHY SAS Address matches the SAS Address
2149230557Sjimharris      // for this port.
2150230557Sjimharris      scic_sds_phy_get_sas_address(this_phy, &phy_sas_address);
2151230557Sjimharris
2152230557Sjimharris      if (
2153230557Sjimharris            (port_sas_address.high != phy_sas_address.high)
2154230557Sjimharris         || (port_sas_address.low  != phy_sas_address.low)
2155230557Sjimharris         )
2156230557Sjimharris      {
2157230557Sjimharris         return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
2158230557Sjimharris      }
2159230557Sjimharris   }
2160230557Sjimharris
2161230557Sjimharris   return scic_sds_port_set_phy(this_port, this_phy);
2162230557Sjimharris}
2163230557Sjimharris
2164230557Sjimharris
2165230557Sjimharris/**
2166230557Sjimharris * This method takes the SCIC_SDS_PORT that is in a stopped state and handles
2167230557Sjimharris * the remove phy request.  In MPC mode the only time a phy can be removed
2168230557Sjimharris * from a port is in the SCI_BASE_PORT_STATE_STOPPED.
2169230557Sjimharris *
2170230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
2171230557Sjimharris *       SCIC_SDS_PORT object.
2172230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
2173230557Sjimharris *       SCIC_SDS_PHY object.
2174230557Sjimharris *
2175230557Sjimharris * @return SCI_STATUS
2176230557Sjimharris * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy
2177230557Sjimharris *         can not be added to the port.
2178230557Sjimharris * @retval SCI_SUCCESS if the phy is added to the port.
2179230557Sjimharris */
2180230557Sjimharrisstatic
2181230557SjimharrisSCI_STATUS scic_sds_port_stopped_state_remove_phy_handler(
2182230557Sjimharris   SCI_BASE_PORT_T *port,
2183230557Sjimharris   SCI_BASE_PHY_T  *phy
2184230557Sjimharris)
2185230557Sjimharris{
2186230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
2187230557Sjimharris   SCIC_SDS_PHY_T  *this_phy  = (SCIC_SDS_PHY_T  *)phy;
2188230557Sjimharris
2189230557Sjimharris   return scic_sds_port_clear_phy(this_port, this_phy);
2190230557Sjimharris}
2191230557Sjimharris
2192230557Sjimharris//****************************************************************************
2193230557Sjimharris//*  READY STATE HANDLERS
2194230557Sjimharris//****************************************************************************
2195230557Sjimharris
2196230557Sjimharris//****************************************************************************
2197230557Sjimharris//*  RESETTING STATE HANDLERS
2198230557Sjimharris//****************************************************************************
2199230557Sjimharris
2200230557Sjimharris//****************************************************************************
2201230557Sjimharris//*  STOPPING STATE HANDLERS
2202230557Sjimharris//****************************************************************************
2203230557Sjimharris
2204230557Sjimharris/**
2205230557Sjimharris * This method takes the SCIC_SDS_PORT that is in a stopping state and handles
2206230557Sjimharris * the complete io request. Should the request count reach 0 then the port
2207230557Sjimharris * object will transition to the stopped state.
2208230557Sjimharris *
2209230557Sjimharris * @param[in] port This is the SCIC_SDS_PORT object on which the io request
2210230557Sjimharris *       count will be decremented.
2211230557Sjimharris * @param[in] device This is the SCIC_SDS_REMOTE_DEVICE object to which the io
2212230557Sjimharris *       request is being directed.  This parameter is not required to
2213230557Sjimharris *       complete this operation.
2214230557Sjimharris * @param[in] io_request This is the request that is being completed on this
2215230557Sjimharris *       port object.  This parameter is not required to complete this
2216230557Sjimharris *       operation.
2217230557Sjimharris *
2218230557Sjimharris * @return SCI_STATUS
2219230557Sjimharris * @retval SCI_SUCCESS
2220230557Sjimharris */
2221230557Sjimharrisstatic
2222230557SjimharrisSCI_STATUS scic_sds_port_stopping_state_complete_io_handler(
2223230557Sjimharris   SCIC_SDS_PORT_T          *port,
2224230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *device,
2225230557Sjimharris   SCIC_SDS_REQUEST_T       *io_request
2226230557Sjimharris)
2227230557Sjimharris{
2228230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
2229230557Sjimharris
2230230557Sjimharris   scic_sds_port_decrement_request_count(this_port);
2231230557Sjimharris
2232230557Sjimharris   if (this_port->started_request_count == 0)
2233230557Sjimharris   {
2234230557Sjimharris      sci_base_state_machine_change_state(
2235230557Sjimharris         scic_sds_port_get_base_state_machine(this_port),
2236230557Sjimharris         SCI_BASE_PORT_STATE_STOPPED
2237230557Sjimharris      );
2238230557Sjimharris   }
2239230557Sjimharris
2240230557Sjimharris   return SCI_SUCCESS;
2241230557Sjimharris}
2242230557Sjimharris
2243230557Sjimharris//****************************************************************************
2244230557Sjimharris//*  RESETTING STATE HANDLERS
2245230557Sjimharris//****************************************************************************
2246230557Sjimharris
2247230557Sjimharris/**
2248230557Sjimharris * This method will stop a failed port.  This causes a transition to the
2249230557Sjimharris * stopping state.
2250230557Sjimharris *
2251230557Sjimharris * @param[in] port This is the port object which is being requested to stop.
2252230557Sjimharris *
2253230557Sjimharris * @return SCI_STATUS
2254230557Sjimharris * @retval SCI_SUCCESS
2255230557Sjimharris */
2256230557Sjimharrisstatic
2257230557SjimharrisSCI_STATUS scic_sds_port_reset_state_stop_handler(
2258230557Sjimharris   SCI_BASE_PORT_T *port
2259230557Sjimharris)
2260230557Sjimharris{
2261230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
2262230557Sjimharris
2263230557Sjimharris   sci_base_state_machine_change_state(
2264230557Sjimharris      &this_port->parent.state_machine,
2265230557Sjimharris      SCI_BASE_PORT_STATE_STOPPING
2266230557Sjimharris   );
2267230557Sjimharris
2268230557Sjimharris   return SCI_SUCCESS;
2269230557Sjimharris}
2270230557Sjimharris
2271230557Sjimharris/**
2272230557Sjimharris * This method will transition a failed port to its ready state.  The port
2273230557Sjimharris * failed because a hard reset request timed out but at some time later one or
2274230557Sjimharris * more phys in the port became ready.
2275230557Sjimharris *
2276230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
2277230557Sjimharris *       SCIC_SDS_PORT object.
2278230557Sjimharris *
2279230557Sjimharris * @return SCI_STATUS
2280230557Sjimharris * @retval SCI_SUCCESS
2281230557Sjimharris */
2282230557Sjimharrisstatic
2283230557Sjimharrisvoid scic_sds_port_reset_state_link_up_handler(
2284230557Sjimharris   SCIC_SDS_PORT_T *this_port,
2285230557Sjimharris   SCIC_SDS_PHY_T  *phy
2286230557Sjimharris)
2287230557Sjimharris{
2288230557Sjimharris   /// @todo We should make sure that the phy that has gone link up is the same
2289230557Sjimharris   ///       one on which we sent the reset.  It is possible that the phy on
2290230557Sjimharris   ///       which we sent the reset is not the one that has gone link up and we
2291230557Sjimharris   ///       want to make sure that phy being reset comes back.  Consider the
2292230557Sjimharris   ///       case where a reset is sent but before the hardware processes the
2293230557Sjimharris   ///       reset it get a link up on the port because of a hot plug event.
2294230557Sjimharris   ///       because of the reset request this phy will go link down almost
2295230557Sjimharris   ///       immediately.
2296230557Sjimharris
2297230557Sjimharris   // In the resetting state we don't notify the user regarding
2298230557Sjimharris   // link up and link down notifications.
2299230557Sjimharris   scic_sds_port_general_link_up_handler(this_port, phy, FALSE, TRUE);
2300230557Sjimharris}
2301230557Sjimharris
2302230557Sjimharris/**
2303230557Sjimharris * This method process link down notifications that occur during a
2304230557Sjimharris * port reset operation. Link downs can occur during the reset operation.
2305230557Sjimharris *
2306230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
2307230557Sjimharris *       SCIC_SDS_PORT object.
2308230557Sjimharris *
2309230557Sjimharris * @return SCI_STATUS
2310230557Sjimharris * @retval SCI_SUCCESS
2311230557Sjimharris */
2312230557Sjimharrisstatic
2313230557Sjimharrisvoid scic_sds_port_reset_state_link_down_handler(
2314230557Sjimharris   SCIC_SDS_PORT_T *this_port,
2315230557Sjimharris   SCIC_SDS_PHY_T  *phy
2316230557Sjimharris)
2317230557Sjimharris{
2318230557Sjimharris   // In the resetting state we don't notify the user regarding
2319230557Sjimharris   // link up and link down notifications.
2320230557Sjimharris   scic_sds_port_deactivate_phy(this_port, phy, FALSE);
2321230557Sjimharris}
2322230557Sjimharris
2323230557Sjimharris// ---------------------------------------------------------------------------
2324230557Sjimharris
2325230557SjimharrisSCIC_SDS_PORT_STATE_HANDLER_T
2326230557Sjimharris   scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] =
2327230557Sjimharris{
2328230557Sjimharris   // SCI_BASE_PORT_STATE_STOPPED
2329230557Sjimharris   {
2330230557Sjimharris      {
2331230557Sjimharris         scic_sds_port_stopped_state_start_handler,
2332230557Sjimharris         scic_sds_port_stopped_state_stop_handler,
2333230557Sjimharris         scic_sds_port_stopped_state_destruct_handler,
2334230557Sjimharris         scic_sds_port_default_reset_handler,
2335230557Sjimharris         scic_sds_port_stopped_state_add_phy_handler,
2336230557Sjimharris         scic_sds_port_stopped_state_remove_phy_handler
2337230557Sjimharris      },
2338230557Sjimharris      scic_sds_port_default_frame_handler,
2339230557Sjimharris      scic_sds_port_default_event_handler,
2340230557Sjimharris      scic_sds_port_default_link_up_handler,
2341230557Sjimharris      scic_sds_port_default_link_down_handler,
2342230557Sjimharris      scic_sds_port_default_start_io_handler,
2343230557Sjimharris      scic_sds_port_default_complete_io_handler
2344230557Sjimharris   },
2345230557Sjimharris   // SCI_BASE_PORT_STATE_STOPPING
2346230557Sjimharris   {
2347230557Sjimharris      {
2348230557Sjimharris         scic_sds_port_default_start_handler,
2349230557Sjimharris         scic_sds_port_default_stop_handler,
2350230557Sjimharris         scic_sds_port_default_destruct_handler,
2351230557Sjimharris         scic_sds_port_default_reset_handler,
2352230557Sjimharris         scic_sds_port_default_add_phy_handler,
2353230557Sjimharris         scic_sds_port_default_remove_phy_handler
2354230557Sjimharris      },
2355230557Sjimharris      scic_sds_port_default_frame_handler,
2356230557Sjimharris      scic_sds_port_default_event_handler,
2357230557Sjimharris      scic_sds_port_default_link_up_handler,
2358230557Sjimharris      scic_sds_port_default_link_down_handler,
2359230557Sjimharris      scic_sds_port_default_start_io_handler,
2360230557Sjimharris      scic_sds_port_stopping_state_complete_io_handler
2361230557Sjimharris   },
2362230557Sjimharris   // SCI_BASE_PORT_STATE_READY
2363230557Sjimharris   {
2364230557Sjimharris      {
2365230557Sjimharris         scic_sds_port_default_start_handler,
2366230557Sjimharris         scic_sds_port_default_stop_handler,
2367230557Sjimharris         scic_sds_port_default_destruct_handler,
2368230557Sjimharris         scic_sds_port_default_reset_handler,
2369230557Sjimharris         scic_sds_port_default_add_phy_handler,
2370230557Sjimharris         scic_sds_port_default_remove_phy_handler
2371230557Sjimharris      },
2372230557Sjimharris      scic_sds_port_default_frame_handler,
2373230557Sjimharris      scic_sds_port_default_event_handler,
2374230557Sjimharris      scic_sds_port_default_link_up_handler,
2375230557Sjimharris      scic_sds_port_default_link_down_handler,
2376230557Sjimharris      scic_sds_port_default_start_io_handler,
2377230557Sjimharris      scic_sds_port_general_complete_io_handler
2378230557Sjimharris   },
2379230557Sjimharris   // SCI_BASE_PORT_STATE_RESETTING
2380230557Sjimharris   {
2381230557Sjimharris      {
2382230557Sjimharris         scic_sds_port_default_start_handler,
2383230557Sjimharris         scic_sds_port_reset_state_stop_handler,
2384230557Sjimharris         scic_sds_port_default_destruct_handler,
2385230557Sjimharris         scic_sds_port_default_reset_handler,
2386230557Sjimharris         scic_sds_port_default_add_phy_handler,
2387230557Sjimharris         scic_sds_port_default_remove_phy_handler
2388230557Sjimharris      },
2389230557Sjimharris      scic_sds_port_default_frame_handler,
2390230557Sjimharris      scic_sds_port_default_event_handler,
2391230557Sjimharris      scic_sds_port_reset_state_link_up_handler,
2392230557Sjimharris      scic_sds_port_reset_state_link_down_handler,
2393230557Sjimharris      scic_sds_port_default_start_io_handler,
2394230557Sjimharris      scic_sds_port_general_complete_io_handler
2395230557Sjimharris   },
2396230557Sjimharris   // SCI_BASE_PORT_STATE_FAILED
2397230557Sjimharris   {
2398230557Sjimharris      {
2399230557Sjimharris         scic_sds_port_default_start_handler,
2400230557Sjimharris         scic_sds_port_default_stop_handler,
2401230557Sjimharris         scic_sds_port_default_destruct_handler,
2402230557Sjimharris         scic_sds_port_default_reset_handler,
2403230557Sjimharris         scic_sds_port_default_add_phy_handler,
2404230557Sjimharris         scic_sds_port_default_remove_phy_handler
2405230557Sjimharris      },
2406230557Sjimharris      scic_sds_port_default_frame_handler,
2407230557Sjimharris      scic_sds_port_default_event_handler,
2408230557Sjimharris      scic_sds_port_default_link_up_handler,
2409230557Sjimharris      scic_sds_port_default_link_down_handler,
2410230557Sjimharris      scic_sds_port_default_start_io_handler,
2411230557Sjimharris      scic_sds_port_general_complete_io_handler
2412230557Sjimharris   }
2413230557Sjimharris};
2414230557Sjimharris
2415230557Sjimharris//******************************************************************************
2416230557Sjimharris//*  PORT STATE PRIVATE METHODS
2417230557Sjimharris//******************************************************************************
2418230557Sjimharris
2419230557Sjimharris/**
2420230557Sjimharris * This method will enable the SCU Port Task Scheduler for this port object
2421230557Sjimharris * but will leave the port task scheduler in a suspended state.
2422230557Sjimharris *
2423230557Sjimharris * @param[in] this_port This is the port object which to suspend.
2424230557Sjimharris *
2425230557Sjimharris * @return none
2426230557Sjimharris */
2427230557Sjimharrisstatic
2428230557Sjimharrisvoid scic_sds_port_enable_port_task_scheduler(
2429230557Sjimharris   SCIC_SDS_PORT_T *this_port
2430230557Sjimharris)
2431230557Sjimharris{
2432230557Sjimharris   U32 pts_control_value;
2433230557Sjimharris
2434230557Sjimharris   pts_control_value = scu_port_task_scheduler_read(this_port, control);
2435230557Sjimharris
2436230557Sjimharris   pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND);
2437230557Sjimharris
2438230557Sjimharris   scu_port_task_scheduler_write(this_port, control, pts_control_value);
2439230557Sjimharris}
2440230557Sjimharris
2441230557Sjimharris/**
2442230557Sjimharris * This method will disable the SCU port task scheduler for this port
2443230557Sjimharris * object.
2444230557Sjimharris *
2445230557Sjimharris * @param[in] this_port This is the port object which to resume.
2446230557Sjimharris *
2447230557Sjimharris * @return none
2448230557Sjimharris */
2449230557Sjimharrisstatic
2450230557Sjimharrisvoid scic_sds_port_disable_port_task_scheduler(
2451230557Sjimharris   SCIC_SDS_PORT_T *this_port
2452230557Sjimharris)
2453230557Sjimharris{
2454230557Sjimharris   U32 pts_control_value;
2455230557Sjimharris
2456230557Sjimharris   pts_control_value = scu_port_task_scheduler_read(this_port, control);
2457230557Sjimharris
2458230557Sjimharris   pts_control_value &= ~(   SCU_PTSxCR_GEN_BIT(ENABLE)
2459230557Sjimharris                           | SCU_PTSxCR_GEN_BIT(SUSPEND) );
2460230557Sjimharris
2461230557Sjimharris   scu_port_task_scheduler_write(this_port, control, pts_control_value);
2462230557Sjimharris}
2463230557Sjimharris
2464230557Sjimharris/**
2465230557Sjimharris *
2466230557Sjimharris */
2467230557Sjimharrisstatic
2468230557Sjimharrisvoid scic_sds_port_post_dummy_remote_node(
2469230557Sjimharris      SCIC_SDS_PORT_T *this_port
2470230557Sjimharris)
2471230557Sjimharris{
2472230557Sjimharris   U32 command;
2473230557Sjimharris   SCU_REMOTE_NODE_CONTEXT_T * rnc;
2474230557Sjimharris
2475230557Sjimharris   if (this_port->reserved_rni != SCU_DUMMY_INDEX)
2476230557Sjimharris   {
2477230557Sjimharris   rnc = &(this_port->owning_controller->remote_node_context_table[this_port->reserved_rni]);
2478230557Sjimharris
2479230557Sjimharris   rnc->ssp.is_valid = TRUE;
2480230557Sjimharris
2481230557Sjimharris   command = (
2482230557Sjimharris       (SCU_CONTEXT_COMMAND_POST_RNC_32)
2483230557Sjimharris     | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)
2484230557Sjimharris     | (this_port->reserved_rni)
2485230557Sjimharris   );
2486230557Sjimharris
2487230557Sjimharris   scic_sds_controller_post_request(this_port->owning_controller, command);
2488230557Sjimharris
2489230557Sjimharris   scic_cb_stall_execution(10);
2490230557Sjimharris
2491230557Sjimharris   command = (
2492230557Sjimharris       (SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX)
2493230557Sjimharris     | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)
2494230557Sjimharris     | (this_port->reserved_rni)
2495230557Sjimharris   );
2496230557Sjimharris
2497230557Sjimharris   scic_sds_controller_post_request(this_port->owning_controller, command);
2498230557Sjimharris}
2499230557Sjimharris}
2500230557Sjimharris
2501230557Sjimharris/**
2502230557Sjimharris *
2503230557Sjimharris */
2504230557Sjimharrisstatic
2505230557Sjimharrisvoid scic_sds_port_invalidate_dummy_remote_node(
2506230557Sjimharris   SCIC_SDS_PORT_T *this_port
2507230557Sjimharris)
2508230557Sjimharris{
2509230557Sjimharris   U32 command;
2510230557Sjimharris   SCU_REMOTE_NODE_CONTEXT_T * rnc;
2511230557Sjimharris
2512230557Sjimharris   if (this_port->reserved_rni != SCU_DUMMY_INDEX)
2513230557Sjimharris   {
2514230557Sjimharris   rnc = &(this_port->owning_controller->remote_node_context_table[this_port->reserved_rni]);
2515230557Sjimharris
2516230557Sjimharris   rnc->ssp.is_valid = FALSE;
2517230557Sjimharris
2518230557Sjimharris   scic_cb_stall_execution(10);
2519230557Sjimharris
2520230557Sjimharris   command = (
2521230557Sjimharris       (SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE)
2522230557Sjimharris     | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)
2523230557Sjimharris     | (this_port->reserved_rni)
2524230557Sjimharris   );
2525230557Sjimharris
2526230557Sjimharris   scic_sds_controller_post_request(this_port->owning_controller, command);
2527230557Sjimharris}
2528230557Sjimharris}
2529230557Sjimharris
2530230557Sjimharris//******************************************************************************
2531230557Sjimharris//*  PORT STATE METHODS
2532230557Sjimharris//******************************************************************************
2533230557Sjimharris
2534230557Sjimharris/**
2535230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
2536230557Sjimharris * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped
2537230557Sjimharris * state handlers for the SCIC_SDS_PORT object and disables the port task
2538230557Sjimharris * scheduler in the hardware.
2539230557Sjimharris *
2540230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2541230557Sjimharris *       SCIC_SDS_PORT object.
2542230557Sjimharris *
2543230557Sjimharris * @return none
2544230557Sjimharris */
2545230557Sjimharrisstatic
2546230557Sjimharrisvoid scic_sds_port_stopped_state_enter(
2547230557Sjimharris   SCI_BASE_OBJECT_T *object
2548230557Sjimharris)
2549230557Sjimharris{
2550230557Sjimharris   SCIC_SDS_PORT_T *this_port;
2551230557Sjimharris   this_port = (SCIC_SDS_PORT_T *)object;
2552230557Sjimharris
2553230557Sjimharris   scic_sds_port_set_base_state_handlers(
2554230557Sjimharris      this_port, SCI_BASE_PORT_STATE_STOPPED
2555230557Sjimharris   );
2556230557Sjimharris
2557230557Sjimharris   if (
2558230557Sjimharris         SCI_BASE_PORT_STATE_STOPPING
2559230557Sjimharris      == this_port->parent.state_machine.previous_state_id
2560230557Sjimharris      )
2561230557Sjimharris   {
2562230557Sjimharris      // If we enter this state becasuse of a request to stop
2563230557Sjimharris      // the port then we want to disable the hardwares port
2564230557Sjimharris      // task scheduler.
2565230557Sjimharris      scic_sds_port_disable_port_task_scheduler(this_port);
2566230557Sjimharris   }
2567230557Sjimharris}
2568230557Sjimharris
2569230557Sjimharris/**
2570230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
2571230557Sjimharris * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware
2572230557Sjimharris * port task scheduler.
2573230557Sjimharris *
2574230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2575230557Sjimharris *       SCIC_SDS_PORT object.
2576230557Sjimharris *
2577230557Sjimharris * @return none
2578230557Sjimharris */
2579230557Sjimharrisstatic
2580230557Sjimharrisvoid scic_sds_port_stopped_state_exit(
2581230557Sjimharris   SCI_BASE_OBJECT_T *object
2582230557Sjimharris)
2583230557Sjimharris{
2584230557Sjimharris   SCIC_SDS_PORT_T *this_port;
2585230557Sjimharris   this_port = (SCIC_SDS_PORT_T *)object;
2586230557Sjimharris
2587230557Sjimharris   // Enable and suspend the port task scheduler
2588230557Sjimharris   scic_sds_port_enable_port_task_scheduler(this_port);
2589230557Sjimharris}
2590230557Sjimharris
2591230557Sjimharris/**
2592230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
2593230557Sjimharris * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state
2594230557Sjimharris * handlers for the SCIC_SDS_PORT object, reports the port object as not ready
2595230557Sjimharris * and starts the ready substate machine.
2596230557Sjimharris *
2597230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2598230557Sjimharris *       SCIC_SDS_PORT object.
2599230557Sjimharris *
2600230557Sjimharris * @return none
2601230557Sjimharris */
2602230557Sjimharrisstatic
2603230557Sjimharrisvoid scic_sds_port_ready_state_enter(
2604230557Sjimharris   SCI_BASE_OBJECT_T *object
2605230557Sjimharris)
2606230557Sjimharris{
2607230557Sjimharris   SCIC_SDS_PORT_T *this_port;
2608230557Sjimharris   this_port = (SCIC_SDS_PORT_T *)object;
2609230557Sjimharris
2610230557Sjimharris   // Put the ready state handlers in place though they will not be there long
2611230557Sjimharris   scic_sds_port_set_base_state_handlers(
2612230557Sjimharris      this_port, SCI_BASE_PORT_STATE_READY
2613230557Sjimharris   );
2614230557Sjimharris
2615230557Sjimharris   if (
2616230557Sjimharris          SCI_BASE_PORT_STATE_RESETTING
2617230557Sjimharris      == this_port->parent.state_machine.previous_state_id
2618230557Sjimharris      )
2619230557Sjimharris   {
2620230557Sjimharris      scic_cb_port_hard_reset_complete(
2621230557Sjimharris         scic_sds_port_get_controller(this_port),
2622230557Sjimharris         this_port,
2623230557Sjimharris         SCI_SUCCESS
2624230557Sjimharris      );
2625230557Sjimharris   }
2626230557Sjimharris   else
2627230557Sjimharris   {
2628230557Sjimharris      // Notify the caller that the port is not yet ready
2629230557Sjimharris      scic_cb_port_not_ready(
2630230557Sjimharris         scic_sds_port_get_controller(this_port),
2631230557Sjimharris         this_port,
2632230557Sjimharris         SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS
2633230557Sjimharris      );
2634230557Sjimharris   }
2635230557Sjimharris
2636230557Sjimharris   // Post and suspend the dummy remote node context for this
2637230557Sjimharris   // port.
2638230557Sjimharris   scic_sds_port_post_dummy_remote_node(this_port);
2639230557Sjimharris
2640230557Sjimharris   // Start the ready substate machine
2641230557Sjimharris   sci_base_state_machine_start(
2642230557Sjimharris      scic_sds_port_get_ready_substate_machine(this_port)
2643230557Sjimharris   );
2644230557Sjimharris}
2645230557Sjimharris
2646230557Sjimharris/**
2647230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
2648230557Sjimharris * exiting the SCI_BASE_STATE_READY. This function does nothing.
2649230557Sjimharris *
2650230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2651230557Sjimharris *       SCIC_SDS_PORT object.
2652230557Sjimharris *
2653230557Sjimharris * @return none
2654230557Sjimharris */
2655230557Sjimharrisstatic
2656230557Sjimharrisvoid scic_sds_port_ready_state_exit(
2657230557Sjimharris   SCI_BASE_OBJECT_T *object
2658230557Sjimharris)
2659230557Sjimharris{
2660230557Sjimharris   SCIC_SDS_PORT_T *this_port;
2661230557Sjimharris   this_port = (SCIC_SDS_PORT_T *)object;
2662230557Sjimharris
2663230557Sjimharris   sci_base_state_machine_stop(&this_port->ready_substate_machine);
2664230557Sjimharris
2665230557Sjimharris   scic_cb_stall_execution(10);
2666230557Sjimharris   scic_sds_port_invalidate_dummy_remote_node(this_port);
2667230557Sjimharris}
2668230557Sjimharris
2669230557Sjimharris/**
2670230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
2671230557Sjimharris * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the
2672230557Sjimharris * resetting state handlers for the SCIC_SDS_PORT object.
2673230557Sjimharris *
2674230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2675230557Sjimharris *       SCIC_SDS_PORT object.
2676230557Sjimharris *
2677230557Sjimharris * @return none
2678230557Sjimharris */
2679230557Sjimharrisstatic
2680230557Sjimharrisvoid scic_sds_port_resetting_state_enter(
2681230557Sjimharris   SCI_BASE_OBJECT_T *object
2682230557Sjimharris)
2683230557Sjimharris{
2684230557Sjimharris   SCIC_SDS_PORT_T *this_port;
2685230557Sjimharris   this_port = (SCIC_SDS_PORT_T *)object;
2686230557Sjimharris
2687230557Sjimharris   scic_sds_port_set_base_state_handlers(
2688230557Sjimharris      this_port, SCI_BASE_PORT_STATE_RESETTING
2689230557Sjimharris   );
2690230557Sjimharris}
2691230557Sjimharris
2692230557Sjimharris/**
2693230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
2694230557Sjimharris * exiting the SCI_BASE_STATE_RESETTING. This function does nothing.
2695230557Sjimharris *
2696230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2697230557Sjimharris *       SCIC_SDS_PORT object.
2698230557Sjimharris *
2699230557Sjimharris * @return none
2700230557Sjimharris */
2701230557Sjimharrisstatic
2702230557Sjimharrisvoid scic_sds_port_resetting_state_exit(
2703230557Sjimharris   SCI_BASE_OBJECT_T *object
2704230557Sjimharris)
2705230557Sjimharris{
2706230557Sjimharris   SCIC_SDS_PORT_T *this_port;
2707230557Sjimharris   this_port = (SCIC_SDS_PORT_T *)object;
2708230557Sjimharris
2709230557Sjimharris   scic_cb_timer_stop(
2710230557Sjimharris      scic_sds_port_get_controller(this_port),
2711230557Sjimharris      this_port->timer_handle
2712230557Sjimharris   );
2713230557Sjimharris}
2714230557Sjimharris
2715230557Sjimharris/**
2716230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
2717230557Sjimharris * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping
2718230557Sjimharris * state handlers for the SCIC_SDS_PORT object.
2719230557Sjimharris *
2720230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2721230557Sjimharris *       SCIC_SDS_PORT object.
2722230557Sjimharris *
2723230557Sjimharris * @return none
2724230557Sjimharris */
2725230557Sjimharrisstatic
2726230557Sjimharrisvoid scic_sds_port_stopping_state_enter(
2727230557Sjimharris   SCI_BASE_OBJECT_T *object
2728230557Sjimharris)
2729230557Sjimharris{
2730230557Sjimharris   SCIC_SDS_PORT_T *this_port;
2731230557Sjimharris   this_port = (SCIC_SDS_PORT_T *)object;
2732230557Sjimharris
2733230557Sjimharris   scic_sds_port_set_base_state_handlers(
2734230557Sjimharris      this_port, SCI_BASE_PORT_STATE_STOPPING
2735230557Sjimharris   );
2736230557Sjimharris
2737230557Sjimharris   if (this_port->started_request_count == 0)
2738230557Sjimharris   {
2739230557Sjimharris      sci_base_state_machine_change_state(
2740230557Sjimharris         &this_port->parent.state_machine,
2741230557Sjimharris         SCI_BASE_PORT_STATE_STOPPED
2742230557Sjimharris      );
2743230557Sjimharris   }
2744230557Sjimharris}
2745230557Sjimharris
2746230557Sjimharris/**
2747230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
2748230557Sjimharris * exiting the SCI_BASE_STATE_STOPPING. This function does nothing.
2749230557Sjimharris *
2750230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2751230557Sjimharris *       SCIC_SDS_PORT object.
2752230557Sjimharris *
2753230557Sjimharris * @return none
2754230557Sjimharris */
2755230557Sjimharrisstatic
2756230557Sjimharrisvoid scic_sds_port_stopping_state_exit(
2757230557Sjimharris   SCI_BASE_OBJECT_T *object
2758230557Sjimharris)
2759230557Sjimharris{
2760230557Sjimharris   SCIC_SDS_PORT_T *this_port;
2761230557Sjimharris   this_port = (SCIC_SDS_PORT_T *)object;
2762230557Sjimharris
2763230557Sjimharris   scic_cb_timer_stop(
2764230557Sjimharris      scic_sds_port_get_controller(this_port),
2765230557Sjimharris      this_port->timer_handle
2766230557Sjimharris   );
2767230557Sjimharris
2768230557Sjimharris   scic_cb_timer_destroy(
2769230557Sjimharris      scic_sds_port_get_controller(this_port),
2770230557Sjimharris      this_port->timer_handle
2771230557Sjimharris   );
2772230557Sjimharris   this_port->timer_handle = NULL;
2773230557Sjimharris
2774230557Sjimharris   scic_sds_port_destroy_dummy_resources(this_port);
2775230557Sjimharris}
2776230557Sjimharris
2777230557Sjimharris/**
2778230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
2779230557Sjimharris * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping
2780230557Sjimharris * state handlers for the SCIC_SDS_PORT object.
2781230557Sjimharris *
2782230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
2783230557Sjimharris *       SCIC_SDS_PORT object.
2784230557Sjimharris *
2785230557Sjimharris * @return none
2786230557Sjimharris */
2787230557Sjimharrisstatic
2788230557Sjimharrisvoid scic_sds_port_failed_state_enter(
2789230557Sjimharris   SCI_BASE_OBJECT_T *object
2790230557Sjimharris)
2791230557Sjimharris{
2792230557Sjimharris   SCIC_SDS_PORT_T *this_port;
2793230557Sjimharris   this_port = (SCIC_SDS_PORT_T *)object;
2794230557Sjimharris
2795230557Sjimharris   scic_sds_port_set_base_state_handlers(
2796230557Sjimharris      this_port,
2797230557Sjimharris      SCI_BASE_PORT_STATE_FAILED
2798230557Sjimharris   );
2799230557Sjimharris
2800230557Sjimharris   scic_cb_port_hard_reset_complete(
2801230557Sjimharris      scic_sds_port_get_controller(this_port),
2802230557Sjimharris      this_port,
2803230557Sjimharris      SCI_FAILURE_TIMEOUT
2804230557Sjimharris   );
2805230557Sjimharris}
2806230557Sjimharris
2807230557Sjimharris// ---------------------------------------------------------------------------
2808230557Sjimharris
2809230557SjimharrisSCI_BASE_STATE_T scic_sds_port_state_table[SCI_BASE_PORT_MAX_STATES] =
2810230557Sjimharris{
2811230557Sjimharris   {
2812230557Sjimharris      SCI_BASE_PORT_STATE_STOPPED,
2813230557Sjimharris      scic_sds_port_stopped_state_enter,
2814230557Sjimharris      scic_sds_port_stopped_state_exit
2815230557Sjimharris   },
2816230557Sjimharris   {
2817230557Sjimharris      SCI_BASE_PORT_STATE_STOPPING,
2818230557Sjimharris      scic_sds_port_stopping_state_enter,
2819230557Sjimharris      scic_sds_port_stopping_state_exit
2820230557Sjimharris   },
2821230557Sjimharris   {
2822230557Sjimharris      SCI_BASE_PORT_STATE_READY,
2823230557Sjimharris      scic_sds_port_ready_state_enter,
2824230557Sjimharris      scic_sds_port_ready_state_exit
2825230557Sjimharris   },
2826230557Sjimharris   {
2827230557Sjimharris      SCI_BASE_PORT_STATE_RESETTING,
2828230557Sjimharris      scic_sds_port_resetting_state_enter,
2829230557Sjimharris      scic_sds_port_resetting_state_exit
2830230557Sjimharris   },
2831230557Sjimharris   {
2832230557Sjimharris      SCI_BASE_PORT_STATE_FAILED,
2833230557Sjimharris      scic_sds_port_failed_state_enter,
2834230557Sjimharris      NULL
2835230557Sjimharris   }
2836230557Sjimharris};
2837230557Sjimharris
2838230557Sjimharris//******************************************************************************
2839230557Sjimharris//* PORT READY SUB-STATE MACHINE
2840230557Sjimharris//******************************************************************************
2841230557Sjimharris
2842230557Sjimharris//****************************************************************************
2843230557Sjimharris//*  READY SUBSTATE HANDLERS
2844230557Sjimharris//****************************************************************************
2845230557Sjimharris
2846230557Sjimharris/**
2847230557Sjimharris * This method is the general ready state stop handler for the SCIC_SDS_PORT
2848230557Sjimharris * object.  This function will transition the ready substate machine to its
2849230557Sjimharris * final state.
2850230557Sjimharris *
2851230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
2852230557Sjimharris *       SCIC_SDS_PORT object.
2853230557Sjimharris *
2854230557Sjimharris * @return SCI_STATUS
2855230557Sjimharris * @retval SCI_SUCCESS
2856230557Sjimharris */
2857230557Sjimharrisstatic
2858230557SjimharrisSCI_STATUS scic_sds_port_ready_substate_stop_handler(
2859230557Sjimharris   SCI_BASE_PORT_T *port
2860230557Sjimharris)
2861230557Sjimharris{
2862230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
2863230557Sjimharris
2864230557Sjimharris   sci_base_state_machine_change_state(
2865230557Sjimharris      &this_port->parent.state_machine,
2866230557Sjimharris      SCI_BASE_PORT_STATE_STOPPING
2867230557Sjimharris   );
2868230557Sjimharris
2869230557Sjimharris   return SCI_SUCCESS;
2870230557Sjimharris}
2871230557Sjimharris
2872230557Sjimharris/**
2873230557Sjimharris * This method is the general ready substate complete io handler for the
2874230557Sjimharris * SCIC_SDS_PORT object.  This function decrments the outstanding request
2875230557Sjimharris * count for this port object.
2876230557Sjimharris *
2877230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
2878230557Sjimharris *       SCIC_SDS_PORT object.
2879230557Sjimharris * @param[in] device This is the SCI_BASE_REMOTE_DEVICE object which is not
2880230557Sjimharris *       used in this function.
2881230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST object which is not used
2882230557Sjimharris *       in this function.
2883230557Sjimharris *
2884230557Sjimharris * @return SCI_STATUS
2885230557Sjimharris * @retval SCI_SUCCESS
2886230557Sjimharris */
2887230557Sjimharrisstatic
2888230557SjimharrisSCI_STATUS scic_sds_port_ready_substate_complete_io_handler(
2889230557Sjimharris   SCIC_SDS_PORT_T               *port,
2890230557Sjimharris   struct SCIC_SDS_REMOTE_DEVICE *device,
2891230557Sjimharris   struct SCIC_SDS_REQUEST       *io_request
2892230557Sjimharris)
2893230557Sjimharris{
2894230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
2895230557Sjimharris
2896230557Sjimharris   scic_sds_port_decrement_request_count(this_port);
2897230557Sjimharris
2898230557Sjimharris   return SCI_SUCCESS;
2899230557Sjimharris}
2900230557Sjimharris
2901230557Sjimharrisstatic
2902230557SjimharrisSCI_STATUS scic_sds_port_ready_substate_add_phy_handler(
2903230557Sjimharris   SCI_BASE_PORT_T *port,
2904230557Sjimharris   SCI_BASE_PHY_T  *phy
2905230557Sjimharris)
2906230557Sjimharris{
2907230557Sjimharris   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
2908230557Sjimharris   SCIC_SDS_PHY_T  * this_phy  = (SCIC_SDS_PHY_T  *)phy;
2909230557Sjimharris   SCI_STATUS        status;
2910230557Sjimharris
2911230557Sjimharris   status = scic_sds_port_set_phy(this_port, this_phy);
2912230557Sjimharris
2913230557Sjimharris   if (status == SCI_SUCCESS)
2914230557Sjimharris   {
2915230557Sjimharris      scic_sds_port_general_link_up_handler(this_port, this_phy, TRUE, FALSE);
2916230557Sjimharris
2917230557Sjimharris      this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
2918230557Sjimharris
2919230557Sjimharris      sci_base_state_machine_change_state(
2920230557Sjimharris         &this_port->ready_substate_machine,
2921230557Sjimharris         SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
2922230557Sjimharris      );
2923230557Sjimharris   }
2924230557Sjimharris
2925230557Sjimharris   return status;
2926230557Sjimharris}
2927230557Sjimharris
2928230557Sjimharrisstatic
2929230557SjimharrisSCI_STATUS scic_sds_port_ready_substate_remove_phy_handler(
2930230557Sjimharris   SCI_BASE_PORT_T *port,
2931230557Sjimharris   SCI_BASE_PHY_T  *phy
2932230557Sjimharris)
2933230557Sjimharris{
2934230557Sjimharris   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
2935230557Sjimharris   SCIC_SDS_PHY_T  * this_phy  = (SCIC_SDS_PHY_T  *)phy;
2936230557Sjimharris   SCI_STATUS        status;
2937230557Sjimharris
2938230557Sjimharris   status = scic_sds_port_clear_phy(this_port, this_phy);
2939230557Sjimharris
2940230557Sjimharris   if (status == SCI_SUCCESS)
2941230557Sjimharris   {
2942230557Sjimharris      scic_sds_port_deactivate_phy(this_port, this_phy, TRUE);
2943230557Sjimharris
2944230557Sjimharris      this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
2945230557Sjimharris
2946230557Sjimharris      sci_base_state_machine_change_state(
2947230557Sjimharris         &this_port->ready_substate_machine,
2948230557Sjimharris         SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
2949230557Sjimharris      );
2950230557Sjimharris   }
2951230557Sjimharris
2952230557Sjimharris   return status;
2953230557Sjimharris}
2954230557Sjimharris
2955230557Sjimharris//****************************************************************************
2956230557Sjimharris//*  READY SUBSTATE WAITING HANDLERS
2957230557Sjimharris//****************************************************************************
2958230557Sjimharris
2959230557Sjimharris/**
2960230557Sjimharris * This method is the ready waiting substate link up handler for the
2961230557Sjimharris * SCIC_SDS_PORT object.  This methos will report the link up condition for
2962230557Sjimharris * this port and will transition to the ready operational substate.
2963230557Sjimharris *
2964230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object that which has a phy
2965230557Sjimharris *       that has gone link up.
2966230557Sjimharris * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link up.
2967230557Sjimharris *
2968230557Sjimharris * @return none
2969230557Sjimharris */
2970230557Sjimharrisstatic
2971230557Sjimharrisvoid scic_sds_port_ready_waiting_substate_link_up_handler(
2972230557Sjimharris   SCIC_SDS_PORT_T *this_port,
2973230557Sjimharris   SCIC_SDS_PHY_T  *the_phy
2974230557Sjimharris)
2975230557Sjimharris{
2976230557Sjimharris   // Since this is the first phy going link up for the port we can just enable
2977230557Sjimharris   // it and continue.
2978230557Sjimharris   scic_sds_port_activate_phy(this_port, the_phy, TRUE, TRUE);
2979230557Sjimharris
2980230557Sjimharris   sci_base_state_machine_change_state(
2981230557Sjimharris      &this_port->ready_substate_machine,
2982230557Sjimharris      SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
2983230557Sjimharris   );
2984230557Sjimharris}
2985230557Sjimharris
2986230557Sjimharris/**
2987230557Sjimharris * This method is the ready waiting substate start io handler for the
2988230557Sjimharris * SCIC_SDS_PORT object. The port object can not accept new requests so the
2989230557Sjimharris * request is failed.
2990230557Sjimharris *
2991230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
2992230557Sjimharris *       SCIC_SDS_PORT object.
2993230557Sjimharris * @param[in] device This is the SCI_BASE_REMOTE_DEVICE object which is not
2994230557Sjimharris *       used in this request.
2995230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST object which is not used
2996230557Sjimharris *       in this function.
2997230557Sjimharris *
2998230557Sjimharris * @return SCI_STATUS
2999230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
3000230557Sjimharris */
3001230557Sjimharrisstatic
3002230557SjimharrisSCI_STATUS scic_sds_port_ready_waiting_substate_start_io_handler(
3003230557Sjimharris   SCIC_SDS_PORT_T          *port,
3004230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *device,
3005230557Sjimharris   SCIC_SDS_REQUEST_T       *io_request
3006230557Sjimharris)
3007230557Sjimharris{
3008230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
3009230557Sjimharris}
3010230557Sjimharris
3011230557Sjimharris//****************************************************************************
3012230557Sjimharris//*  READY SUBSTATE OPERATIONAL HANDLERS
3013230557Sjimharris//****************************************************************************
3014230557Sjimharris
3015230557Sjimharris/**
3016230557Sjimharris * This method will casue the port to reset.
3017230557Sjimharris *
3018230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
3019230557Sjimharris *       SCIC_SDS_PORT object.
3020230557Sjimharris * @param[in] timeout This is the timeout for the reset request to complete.
3021230557Sjimharris *
3022230557Sjimharris * @return SCI_STATUS
3023230557Sjimharris * @retval SCI_SUCCESS
3024230557Sjimharris */
3025230557Sjimharrisstatic
3026230557SjimharrisSCI_STATUS scic_sds_port_ready_operational_substate_reset_handler(
3027230557Sjimharris   SCI_BASE_PORT_T * port,
3028230557Sjimharris   U32               timeout
3029230557Sjimharris)
3030230557Sjimharris{
3031230557Sjimharris   SCI_STATUS        status = SCI_FAILURE_INVALID_PHY;
3032230557Sjimharris   U32               phy_index;
3033230557Sjimharris   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
3034230557Sjimharris   SCIC_SDS_PHY_T  * selected_phy = SCI_INVALID_HANDLE;
3035230557Sjimharris
3036230557Sjimharris
3037230557Sjimharris   // Select a phy on which we can send the hard reset request.
3038230557Sjimharris   for (
3039230557Sjimharris         phy_index = 0;
3040230557Sjimharris            (phy_index < SCI_MAX_PHYS)
3041230557Sjimharris         && (selected_phy == SCI_INVALID_HANDLE);
3042230557Sjimharris         phy_index++
3043230557Sjimharris       )
3044230557Sjimharris   {
3045230557Sjimharris      selected_phy = this_port->phy_table[phy_index];
3046230557Sjimharris
3047230557Sjimharris      if (
3048230557Sjimharris            (selected_phy != SCI_INVALID_HANDLE)
3049230557Sjimharris         && !scic_sds_port_active_phy(this_port, selected_phy)
3050230557Sjimharris         )
3051230557Sjimharris      {
3052230557Sjimharris         // We found a phy but it is not ready select different phy
3053230557Sjimharris         selected_phy = SCI_INVALID_HANDLE;
3054230557Sjimharris      }
3055230557Sjimharris   }
3056230557Sjimharris
3057230557Sjimharris   // If we have a phy then go ahead and start the reset procedure
3058230557Sjimharris   if (selected_phy != SCI_INVALID_HANDLE)
3059230557Sjimharris   {
3060230557Sjimharris      status = scic_sds_phy_reset(selected_phy);
3061230557Sjimharris
3062230557Sjimharris      if (status == SCI_SUCCESS)
3063230557Sjimharris      {
3064230557Sjimharris         scic_cb_timer_start(
3065230557Sjimharris            scic_sds_port_get_controller(this_port),
3066230557Sjimharris            this_port->timer_handle,
3067230557Sjimharris            timeout
3068230557Sjimharris         );
3069230557Sjimharris
3070230557Sjimharris         this_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED;
3071230557Sjimharris
3072230557Sjimharris         sci_base_state_machine_change_state(
3073230557Sjimharris            &this_port->parent.state_machine,
3074230557Sjimharris            SCI_BASE_PORT_STATE_RESETTING
3075230557Sjimharris         );
3076230557Sjimharris      }
3077230557Sjimharris   }
3078230557Sjimharris
3079230557Sjimharris   return status;
3080230557Sjimharris}
3081230557Sjimharris
3082230557Sjimharris/**
3083230557Sjimharris * This method is the ready operational substate link up handler for the
3084230557Sjimharris * SCIC_SDS_PORT object. This function notifies the SCI User that the phy has
3085230557Sjimharris * gone link up.
3086230557Sjimharris *
3087230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object that which has a phy
3088230557Sjimharris *       that has gone link up.
3089230557Sjimharris * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link up.
3090230557Sjimharris *
3091230557Sjimharris * @return none
3092230557Sjimharris */
3093230557Sjimharrisstatic
3094230557Sjimharrisvoid scic_sds_port_ready_operational_substate_link_up_handler(
3095230557Sjimharris   SCIC_SDS_PORT_T *this_port,
3096230557Sjimharris   SCIC_SDS_PHY_T  *the_phy
3097230557Sjimharris)
3098230557Sjimharris{
3099230557Sjimharris   scic_sds_port_general_link_up_handler(this_port, the_phy, TRUE, TRUE);
3100230557Sjimharris}
3101230557Sjimharris
3102230557Sjimharris/**
3103230557Sjimharris * This method is the ready operational substate link down handler for the
3104230557Sjimharris * SCIC_SDS_PORT object. This function notifies the SCI User that the phy has
3105230557Sjimharris * gone link down and if this is the last phy in the port the port will change
3106230557Sjimharris * state to the ready waiting substate.
3107230557Sjimharris *
3108230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object that which has a phy
3109230557Sjimharris *       that has gone link down.
3110230557Sjimharris * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link down.
3111230557Sjimharris *
3112230557Sjimharris * @return none
3113230557Sjimharris */
3114230557Sjimharrisstatic
3115230557Sjimharrisvoid scic_sds_port_ready_operational_substate_link_down_handler(
3116230557Sjimharris   SCIC_SDS_PORT_T *this_port,
3117230557Sjimharris   SCIC_SDS_PHY_T  *the_phy
3118230557Sjimharris)
3119230557Sjimharris{
3120230557Sjimharris   scic_sds_port_deactivate_phy(this_port, the_phy, TRUE);
3121230557Sjimharris
3122230557Sjimharris   // If there are no active phys left in the port, then transition
3123230557Sjimharris   // the port to the WAITING state until such time as a phy goes
3124230557Sjimharris   // link up.
3125230557Sjimharris   if (this_port->active_phy_mask == 0)
3126230557Sjimharris   {
3127230557Sjimharris      sci_base_state_machine_change_state(
3128230557Sjimharris         scic_sds_port_get_ready_substate_machine(this_port),
3129230557Sjimharris         SCIC_SDS_PORT_READY_SUBSTATE_WAITING
3130230557Sjimharris      );
3131230557Sjimharris   }
3132230557Sjimharris}
3133230557Sjimharris
3134230557Sjimharris/**
3135230557Sjimharris * This method is the ready operational substate start io handler for the
3136230557Sjimharris * SCIC_SDS_PORT object.  This function incremetns the outstanding request
3137230557Sjimharris * count for this port object.
3138230557Sjimharris *
3139230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
3140230557Sjimharris *       SCIC_SDS_PORT object.
3141230557Sjimharris * @param[in] device This is the SCI_BASE_REMOTE_DEVICE object which is not
3142230557Sjimharris *       used in this function.
3143230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST object which is not used
3144230557Sjimharris *       in this function.
3145230557Sjimharris *
3146230557Sjimharris * @return SCI_STATUS
3147230557Sjimharris * @retval SCI_SUCCESS
3148230557Sjimharris */
3149230557Sjimharrisstatic
3150230557SjimharrisSCI_STATUS scic_sds_port_ready_operational_substate_start_io_handler(
3151230557Sjimharris   SCIC_SDS_PORT_T          *port,
3152230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *device,
3153230557Sjimharris   SCIC_SDS_REQUEST_T       *io_request
3154230557Sjimharris)
3155230557Sjimharris{
3156230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
3157230557Sjimharris
3158230557Sjimharris   scic_sds_port_increment_request_count(this_port);
3159230557Sjimharris
3160230557Sjimharris   return SCI_SUCCESS;
3161230557Sjimharris}
3162230557Sjimharris
3163230557Sjimharris//****************************************************************************
3164230557Sjimharris//*  READY SUBSTATE OPERATIONAL HANDLERS
3165230557Sjimharris//****************************************************************************
3166230557Sjimharris
3167230557Sjimharris/**
3168230557Sjimharris * This is the default method for a port add phy request.  It will report a
3169230557Sjimharris * warning and exit.
3170230557Sjimharris *
3171230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
3172230557Sjimharris *       SCIC_SDS_PORT object.
3173230557Sjimharris *
3174230557Sjimharris * @return SCI_STATUS
3175230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
3176230557Sjimharris */
3177230557Sjimharrisstatic
3178230557SjimharrisSCI_STATUS scic_sds_port_ready_configuring_substate_add_phy_handler(
3179230557Sjimharris   SCI_BASE_PORT_T *port,
3180230557Sjimharris   SCI_BASE_PHY_T  *phy
3181230557Sjimharris)
3182230557Sjimharris{
3183230557Sjimharris   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
3184230557Sjimharris   SCIC_SDS_PHY_T  * this_phy  = (SCIC_SDS_PHY_T  *)phy;
3185230557Sjimharris   SCI_STATUS        status;
3186230557Sjimharris
3187230557Sjimharris   status = scic_sds_port_set_phy(this_port, this_phy);
3188230557Sjimharris
3189230557Sjimharris   if (status == SCI_SUCCESS)
3190230557Sjimharris   {
3191230557Sjimharris      scic_sds_port_general_link_up_handler(this_port, this_phy, TRUE, FALSE);
3192230557Sjimharris
3193230557Sjimharris      // Re-enter the configuring state since this may be the last phy in
3194230557Sjimharris      // the port.
3195230557Sjimharris      sci_base_state_machine_change_state(
3196230557Sjimharris         &this_port->ready_substate_machine,
3197230557Sjimharris         SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
3198230557Sjimharris      );
3199230557Sjimharris   }
3200230557Sjimharris
3201230557Sjimharris   return status;
3202230557Sjimharris}
3203230557Sjimharris
3204230557Sjimharris/**
3205230557Sjimharris * This is the default method for a port remove phy request.  It will report a
3206230557Sjimharris * warning and exit.
3207230557Sjimharris *
3208230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a
3209230557Sjimharris *       SCIC_SDS_PORT object.
3210230557Sjimharris *
3211230557Sjimharris * @return SCI_STATUS
3212230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
3213230557Sjimharris */
3214230557Sjimharrisstatic
3215230557SjimharrisSCI_STATUS scic_sds_port_ready_configuring_substate_remove_phy_handler(
3216230557Sjimharris   SCI_BASE_PORT_T *port,
3217230557Sjimharris   SCI_BASE_PHY_T  *phy
3218230557Sjimharris)
3219230557Sjimharris{
3220230557Sjimharris   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
3221230557Sjimharris   SCIC_SDS_PHY_T  * this_phy  = (SCIC_SDS_PHY_T  *)phy;
3222230557Sjimharris   SCI_STATUS        status;
3223230557Sjimharris
3224230557Sjimharris   status = scic_sds_port_clear_phy(this_port, this_phy);
3225230557Sjimharris
3226230557Sjimharris   if (status == SCI_SUCCESS)
3227230557Sjimharris   {
3228230557Sjimharris      scic_sds_port_deactivate_phy(this_port, this_phy, TRUE);
3229230557Sjimharris
3230230557Sjimharris      // Re-enter the configuring state since this may be the last phy in
3231230557Sjimharris      // the port.
3232230557Sjimharris      sci_base_state_machine_change_state(
3233230557Sjimharris         &this_port->ready_substate_machine,
3234230557Sjimharris         SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
3235230557Sjimharris      );
3236230557Sjimharris   }
3237230557Sjimharris
3238230557Sjimharris   return status;
3239230557Sjimharris}
3240230557Sjimharris
3241230557Sjimharris/**
3242230557Sjimharris * This method will decrement the outstanding request count for this port.
3243230557Sjimharris * If the request count goes to 0 then the port can be reprogrammed with
3244230557Sjimharris * its new phy data.
3245230557Sjimharris *
3246230557Sjimharris * @param[in] port This is the port that is being requested to complete
3247230557Sjimharris *            the io request.
3248230557Sjimharris * @param[in] device This is the device on which the io is completing.
3249230557Sjimharris * @param[in] io_request This is the io request that is completing.
3250230557Sjimharris */
3251230557Sjimharrisstatic
3252230557SjimharrisSCI_STATUS scic_sds_port_ready_configuring_substate_complete_io_handler(
3253230557Sjimharris   SCIC_SDS_PORT_T          *port,
3254230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *device,
3255230557Sjimharris   SCIC_SDS_REQUEST_T       *io_request
3256230557Sjimharris)
3257230557Sjimharris{
3258230557Sjimharris   scic_sds_port_decrement_request_count(port);
3259230557Sjimharris
3260230557Sjimharris   if (port->started_request_count == 0)
3261230557Sjimharris   {
3262230557Sjimharris      sci_base_state_machine_change_state(
3263230557Sjimharris         &port->ready_substate_machine,
3264230557Sjimharris         SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
3265230557Sjimharris      );
3266230557Sjimharris   }
3267230557Sjimharris
3268230557Sjimharris   return SCI_SUCCESS;
3269230557Sjimharris}
3270230557Sjimharris
3271230557Sjimharris// ---------------------------------------------------------------------------
3272230557Sjimharris
3273230557SjimharrisSCIC_SDS_PORT_STATE_HANDLER_T
3274230557Sjimharris   scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] =
3275230557Sjimharris{
3276230557Sjimharris   // SCIC_SDS_PORT_READY_SUBSTATE_WAITING
3277230557Sjimharris   {
3278230557Sjimharris      {
3279230557Sjimharris         scic_sds_port_default_start_handler,
3280230557Sjimharris         scic_sds_port_ready_substate_stop_handler,
3281230557Sjimharris         scic_sds_port_default_destruct_handler,
3282230557Sjimharris         scic_sds_port_default_reset_handler,
3283230557Sjimharris         scic_sds_port_ready_substate_add_phy_handler,
3284230557Sjimharris         scic_sds_port_default_remove_phy_handler
3285230557Sjimharris      },
3286230557Sjimharris      scic_sds_port_default_frame_handler,
3287230557Sjimharris      scic_sds_port_default_event_handler,
3288230557Sjimharris      scic_sds_port_ready_waiting_substate_link_up_handler,
3289230557Sjimharris      scic_sds_port_default_link_down_handler,
3290230557Sjimharris      scic_sds_port_ready_waiting_substate_start_io_handler,
3291230557Sjimharris      scic_sds_port_ready_substate_complete_io_handler,
3292230557Sjimharris   },
3293230557Sjimharris   // SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
3294230557Sjimharris   {
3295230557Sjimharris      {
3296230557Sjimharris         scic_sds_port_default_start_handler,
3297230557Sjimharris         scic_sds_port_ready_substate_stop_handler,
3298230557Sjimharris         scic_sds_port_default_destruct_handler,
3299230557Sjimharris         scic_sds_port_ready_operational_substate_reset_handler,
3300230557Sjimharris         scic_sds_port_ready_substate_add_phy_handler,
3301230557Sjimharris         scic_sds_port_ready_substate_remove_phy_handler
3302230557Sjimharris      },
3303230557Sjimharris      scic_sds_port_default_frame_handler,
3304230557Sjimharris      scic_sds_port_default_event_handler,
3305230557Sjimharris      scic_sds_port_ready_operational_substate_link_up_handler,
3306230557Sjimharris      scic_sds_port_ready_operational_substate_link_down_handler,
3307230557Sjimharris      scic_sds_port_ready_operational_substate_start_io_handler,
3308230557Sjimharris      scic_sds_port_ready_substate_complete_io_handler
3309230557Sjimharris   },
3310230557Sjimharris   // SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
3311230557Sjimharris   {
3312230557Sjimharris      {
3313230557Sjimharris         scic_sds_port_default_start_handler,
3314230557Sjimharris         scic_sds_port_ready_substate_stop_handler,
3315230557Sjimharris         scic_sds_port_default_destruct_handler,
3316230557Sjimharris         scic_sds_port_default_reset_handler,
3317230557Sjimharris         scic_sds_port_ready_configuring_substate_add_phy_handler,
3318230557Sjimharris         scic_sds_port_ready_configuring_substate_remove_phy_handler
3319230557Sjimharris      },
3320230557Sjimharris      scic_sds_port_default_frame_handler,
3321230557Sjimharris      scic_sds_port_default_event_handler,
3322230557Sjimharris      scic_sds_port_default_link_up_handler,
3323230557Sjimharris      scic_sds_port_default_link_down_handler,
3324230557Sjimharris      scic_sds_port_default_start_io_handler,
3325230557Sjimharris      scic_sds_port_ready_configuring_substate_complete_io_handler
3326230557Sjimharris   }
3327230557Sjimharris};
3328230557Sjimharris
3329230557Sjimharris/**
3330230557Sjimharris * This macro sets the port ready substate handlers.
3331230557Sjimharris */
3332230557Sjimharris#define scic_sds_port_set_ready_state_handlers(port, state_id) \
3333230557Sjimharris   scic_sds_port_set_state_handlers( \
3334230557Sjimharris      port, &scic_sds_port_ready_substate_handler_table[(state_id)] \
3335230557Sjimharris   )
3336230557Sjimharris
3337230557Sjimharris//******************************************************************************
3338230557Sjimharris//*  PORT STATE PRIVATE METHODS
3339230557Sjimharris//******************************************************************************
3340230557Sjimharris
3341230557Sjimharris/**
3342230557Sjimharris * This method will susped the port task scheduler for this port object.
3343230557Sjimharris *
3344230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object to suspend.
3345230557Sjimharris *
3346230557Sjimharris * @return none
3347230557Sjimharris */
3348230557Sjimharrisvoid scic_sds_port_suspend_port_task_scheduler(
3349230557Sjimharris   SCIC_SDS_PORT_T *this_port
3350230557Sjimharris)
3351230557Sjimharris{
3352230557Sjimharris   U32 pts_control_value;
3353230557Sjimharris
3354230557Sjimharris   pts_control_value = scu_port_task_scheduler_read(this_port, control);
3355230557Sjimharris   pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND);
3356230557Sjimharris   scu_port_task_scheduler_write(this_port, control, pts_control_value);
3357230557Sjimharris}
3358230557Sjimharris
3359230557Sjimharris/**
3360230557Sjimharris * This method will resume the port task scheduler for this port object.
3361230557Sjimharris *
3362230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object to resume.
3363230557Sjimharris *
3364230557Sjimharris * @return none
3365230557Sjimharris */
3366230557Sjimharrisvoid scic_sds_port_resume_port_task_scheduler(
3367230557Sjimharris   SCIC_SDS_PORT_T *this_port
3368230557Sjimharris)
3369230557Sjimharris{
3370230557Sjimharris   U32 pts_control_value;
3371230557Sjimharris
3372230557Sjimharris   pts_control_value = scu_port_task_scheduler_read(this_port, control);
3373230557Sjimharris
3374230557Sjimharris   pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND);
3375230557Sjimharris
3376230557Sjimharris   scu_port_task_scheduler_write(this_port, control, pts_control_value);
3377230557Sjimharris}
3378230557Sjimharris
3379230557Sjimharris/**
3380230557Sjimharris * This routine will post the dummy request.  This will prevent the hardware
3381230557Sjimharris * scheduler from posting new requests to the front of the scheduler queue
3382230557Sjimharris * causing a starvation problem for currently ongoing requests.
3383230557Sjimharris *
3384230557Sjimharris * @parm[in] this_port The port on which the task must be posted.
3385230557Sjimharris *
3386230557Sjimharris * @return none
3387230557Sjimharris */
3388230557Sjimharrisstatic
3389230557Sjimharrisvoid scic_sds_port_post_dummy_request(
3390230557Sjimharris   SCIC_SDS_PORT_T *this_port
3391230557Sjimharris)
3392230557Sjimharris{
3393230557Sjimharris   U32 command;
3394230557Sjimharris   SCU_TASK_CONTEXT_T * task_context;
3395230557Sjimharris
3396230557Sjimharris   if (this_port->reserved_tci != SCU_DUMMY_INDEX)
3397230557Sjimharris   {
3398230557Sjimharris   task_context = scic_sds_controller_get_task_context_buffer(
3399230557Sjimharris                     this_port->owning_controller,
3400230557Sjimharris                     this_port->reserved_tci
3401230557Sjimharris                  );
3402230557Sjimharris
3403230557Sjimharris   task_context->abort = 0;
3404230557Sjimharris
3405230557Sjimharris   command = (
3406230557Sjimharris         (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC)
3407230557Sjimharris      | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)
3408230557Sjimharris      | (this_port->reserved_tci)
3409230557Sjimharris   );
3410230557Sjimharris
3411230557Sjimharris   scic_sds_controller_post_request(this_port->owning_controller, command);
3412230557Sjimharris}
3413230557Sjimharris}
3414230557Sjimharris
3415230557Sjimharris/**
3416230557Sjimharris * This routine will abort the dummy request.  This will alow the hardware to
3417230557Sjimharris * power down parts of the silicon to save power.
3418230557Sjimharris *
3419230557Sjimharris * @parm[in] this_port The port on which the task must be aborted.
3420230557Sjimharris *
3421230557Sjimharris * @return none
3422230557Sjimharris */
3423230557Sjimharrisstatic
3424230557Sjimharrisvoid scic_sds_port_abort_dummy_request(
3425230557Sjimharris   SCIC_SDS_PORT_T *this_port
3426230557Sjimharris)
3427230557Sjimharris{
3428230557Sjimharris   U32 command;
3429230557Sjimharris   SCU_TASK_CONTEXT_T * task_context;
3430230557Sjimharris
3431230557Sjimharris   if (this_port->reserved_tci != SCU_DUMMY_INDEX)
3432230557Sjimharris   {
3433230557Sjimharris   task_context = scic_sds_controller_get_task_context_buffer(
3434230557Sjimharris                     this_port->owning_controller,
3435230557Sjimharris                     this_port->reserved_tci
3436230557Sjimharris                  );
3437230557Sjimharris
3438230557Sjimharris   task_context->abort = 1;
3439230557Sjimharris
3440230557Sjimharris   command = (
3441230557Sjimharris        (SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT)
3442230557Sjimharris      | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)
3443230557Sjimharris      | (this_port->reserved_tci)
3444230557Sjimharris   );
3445230557Sjimharris
3446230557Sjimharris   scic_sds_controller_post_request(this_port->owning_controller, command);
3447230557Sjimharris}
3448230557Sjimharris}
3449230557Sjimharris
3450230557Sjimharris//******************************************************************************
3451230557Sjimharris//*  PORT READY SUBSTATE METHODS
3452230557Sjimharris//******************************************************************************
3453230557Sjimharris
3454230557Sjimharris/**
3455230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
3456230557Sjimharris * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the
3457230557Sjimharris * port for any ready phys.  If there is at least one phy in a ready state
3458230557Sjimharris * then the port transitions to the ready operational substate.
3459230557Sjimharris *
3460230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3461230557Sjimharris *       SCIC_SDS_PORT object.
3462230557Sjimharris *
3463230557Sjimharris * @return none
3464230557Sjimharris */
3465230557Sjimharrisstatic
3466230557Sjimharrisvoid scic_sds_port_ready_substate_waiting_enter(
3467230557Sjimharris   SCI_BASE_OBJECT_T *object
3468230557Sjimharris)
3469230557Sjimharris{
3470230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object;
3471230557Sjimharris
3472230557Sjimharris   scic_sds_port_set_ready_state_handlers(
3473230557Sjimharris      this_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING
3474230557Sjimharris   );
3475230557Sjimharris
3476230557Sjimharris   scic_sds_port_suspend_port_task_scheduler(this_port);
3477230557Sjimharris
3478230557Sjimharris
3479230557Sjimharris   this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS;
3480230557Sjimharris
3481230557Sjimharris   if (this_port->active_phy_mask != 0)
3482230557Sjimharris   {
3483230557Sjimharris      // At least one of the phys on the port is ready
3484230557Sjimharris      sci_base_state_machine_change_state(
3485230557Sjimharris         &this_port->ready_substate_machine,
3486230557Sjimharris         SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
3487230557Sjimharris      );
3488230557Sjimharris   }
3489230557Sjimharris}
3490230557Sjimharris
3491230557Sjimharris/**
3492230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
3493230557Sjimharris * exiting the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function resume the
3494230557Sjimharris * PTSG that was suspended at the entry of this state.
3495230557Sjimharris *
3496230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3497230557Sjimharris *       SCIC_SDS_PORT object.
3498230557Sjimharris *
3499230557Sjimharris * @return none
3500230557Sjimharris */
3501230557Sjimharrisstatic
3502230557Sjimharrisvoid scic_sds_port_ready_substate_waiting_exit(
3503230557Sjimharris   SCI_BASE_OBJECT_T *object
3504230557Sjimharris)
3505230557Sjimharris{
3506230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object;
3507230557Sjimharris   scic_sds_port_resume_port_task_scheduler(this_port);
3508230557Sjimharris}
3509230557Sjimharris
3510230557Sjimharris/**
3511230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
3512230557Sjimharris * entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets
3513230557Sjimharris * the state handlers for the port object, notifies the SCI User that the port
3514230557Sjimharris * is ready, and resumes port operations.
3515230557Sjimharris *
3516230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3517230557Sjimharris *       SCIC_SDS_PORT object.
3518230557Sjimharris *
3519230557Sjimharris * @return none
3520230557Sjimharris */
3521230557Sjimharrisstatic
3522230557Sjimharrisvoid scic_sds_port_ready_substate_operational_enter(
3523230557Sjimharris   SCI_BASE_OBJECT_T *object
3524230557Sjimharris)
3525230557Sjimharris{
3526230557Sjimharris   U32 index;
3527230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object;
3528230557Sjimharris
3529230557Sjimharris   scic_sds_port_set_ready_state_handlers(
3530230557Sjimharris      this_port, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
3531230557Sjimharris   );
3532230557Sjimharris
3533230557Sjimharris   scic_cb_port_ready(
3534230557Sjimharris      scic_sds_port_get_controller(this_port), this_port
3535230557Sjimharris   );
3536230557Sjimharris
3537230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
3538230557Sjimharris   {
3539230557Sjimharris      if (this_port->phy_table[index] != NULL)
3540230557Sjimharris      {
3541230557Sjimharris         scic_sds_port_write_phy_assignment(
3542230557Sjimharris            this_port, this_port->phy_table[index]
3543230557Sjimharris         );
3544230557Sjimharris
3545230557Sjimharris         //if the bit at the index location for active phy mask is set and
3546230557Sjimharris         //enabled_phy_mask is not set then resume the phy
3547230557Sjimharris         if ( ( (this_port->active_phy_mask ^ this_port->enabled_phy_mask) & (1 << index) ) != 0)
3548230557Sjimharris         {
3549230557Sjimharris            scic_sds_port_resume_phy (
3550230557Sjimharris               this_port,
3551230557Sjimharris               this_port->phy_table[index]
3552230557Sjimharris            );
3553230557Sjimharris         }
3554230557Sjimharris      }
3555230557Sjimharris   }
3556230557Sjimharris
3557230557Sjimharris   scic_sds_port_update_viit_entry(this_port);
3558230557Sjimharris
3559230557Sjimharris   // Post the dummy task for the port so the hardware can schedule
3560230557Sjimharris   // io correctly
3561230557Sjimharris   scic_sds_port_post_dummy_request(this_port);
3562230557Sjimharris}
3563230557Sjimharris
3564230557Sjimharris/**
3565230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
3566230557Sjimharris * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports
3567230557Sjimharris * the port not ready and suspends the port task scheduler.
3568230557Sjimharris *
3569230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3570230557Sjimharris *       SCIC_SDS_PORT object.
3571230557Sjimharris *
3572230557Sjimharris * @return none
3573230557Sjimharris */
3574230557Sjimharrisstatic
3575230557Sjimharrisvoid scic_sds_port_ready_substate_operational_exit(
3576230557Sjimharris   SCI_BASE_OBJECT_T *object
3577230557Sjimharris)
3578230557Sjimharris{
3579230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object;
3580230557Sjimharris
3581230557Sjimharris   // Kill the dummy task for this port if it has not yet posted
3582230557Sjimharris   // the hardware will treat this as a NOP and just return abort
3583230557Sjimharris   // complete.
3584230557Sjimharris   scic_sds_port_abort_dummy_request(this_port);
3585230557Sjimharris
3586230557Sjimharris   scic_cb_port_not_ready(
3587230557Sjimharris      scic_sds_port_get_controller(this_port),
3588230557Sjimharris      this_port,
3589230557Sjimharris      this_port->not_ready_reason
3590230557Sjimharris   );
3591230557Sjimharris}
3592230557Sjimharris
3593230557Sjimharris//******************************************************************************
3594230557Sjimharris//*  PORT READY CONFIGURING METHODS
3595230557Sjimharris//******************************************************************************
3596230557Sjimharris
3597230557Sjimharris/**
3598230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on
3599230557Sjimharris * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports
3600230557Sjimharris * the port not ready and suspends the port task scheduler.
3601230557Sjimharris *
3602230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
3603230557Sjimharris *       SCIC_SDS_PORT object.
3604230557Sjimharris *
3605230557Sjimharris * @return none
3606230557Sjimharris */
3607230557Sjimharrisstatic
3608230557Sjimharrisvoid scic_sds_port_ready_substate_configuring_enter(
3609230557Sjimharris   SCI_BASE_OBJECT_T *object
3610230557Sjimharris)
3611230557Sjimharris{
3612230557Sjimharris   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object;
3613230557Sjimharris
3614230557Sjimharris   scic_sds_port_set_ready_state_handlers(
3615230557Sjimharris      this_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
3616230557Sjimharris   );
3617230557Sjimharris
3618230557Sjimharris   if (this_port->active_phy_mask == 0)
3619230557Sjimharris   {
3620230557Sjimharris      scic_cb_port_not_ready(
3621230557Sjimharris         scic_sds_port_get_controller(this_port),
3622230557Sjimharris         this_port,
3623230557Sjimharris         SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS
3624230557Sjimharris      );
3625230557Sjimharris
3626230557Sjimharris      sci_base_state_machine_change_state(
3627230557Sjimharris         &this_port->ready_substate_machine,
3628230557Sjimharris         SCIC_SDS_PORT_READY_SUBSTATE_WAITING
3629230557Sjimharris      );
3630230557Sjimharris   }
3631230557Sjimharris   //do not wait for IO to go to 0 in this state.
3632230557Sjimharris   else
3633230557Sjimharris   {
3634230557Sjimharris      sci_base_state_machine_change_state(
3635230557Sjimharris         &this_port->ready_substate_machine,
3636230557Sjimharris         SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
3637230557Sjimharris      );
3638230557Sjimharris   }
3639230557Sjimharris}
3640230557Sjimharris
3641230557Sjimharris// ---------------------------------------------------------------------------
3642230557Sjimharris
3643230557SjimharrisSCI_BASE_STATE_T
3644230557Sjimharris   scic_sds_port_ready_substate_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] =
3645230557Sjimharris{
3646230557Sjimharris   {
3647230557Sjimharris      SCIC_SDS_PORT_READY_SUBSTATE_WAITING,
3648230557Sjimharris      scic_sds_port_ready_substate_waiting_enter,
3649230557Sjimharris      scic_sds_port_ready_substate_waiting_exit
3650230557Sjimharris   },
3651230557Sjimharris   {
3652230557Sjimharris      SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL,
3653230557Sjimharris      scic_sds_port_ready_substate_operational_enter,
3654230557Sjimharris      scic_sds_port_ready_substate_operational_exit
3655230557Sjimharris   },
3656230557Sjimharris   {
3657230557Sjimharris      SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING,
3658230557Sjimharris      scic_sds_port_ready_substate_configuring_enter,
3659230557Sjimharris      NULL
3660230557Sjimharris   }
3661230557Sjimharris};
3662230557Sjimharris
3663