1230557Sjimharris/*-
2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license.  When using or
3230557Sjimharris * redistributing this file, you may do so under either license.
4230557Sjimharris *
5230557Sjimharris * GPL LICENSE SUMMARY
6230557Sjimharris *
7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8230557Sjimharris *
9230557Sjimharris * This program is free software; you can redistribute it and/or modify
10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as
11230557Sjimharris * published by the Free Software Foundation.
12230557Sjimharris *
13230557Sjimharris * This program is distributed in the hope that it will be useful, but
14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of
15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16230557Sjimharris * General Public License for more details.
17230557Sjimharris *
18230557Sjimharris * You should have received a copy of the GNU General Public License
19230557Sjimharris * along with this program; if not, write to the Free Software
20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21230557Sjimharris * The full GNU General Public License is included in this distribution
22230557Sjimharris * in the file called LICENSE.GPL.
23230557Sjimharris *
24230557Sjimharris * BSD LICENSE
25230557Sjimharris *
26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27230557Sjimharris * All rights reserved.
28230557Sjimharris *
29230557Sjimharris * Redistribution and use in source and binary forms, with or without
30230557Sjimharris * modification, are permitted provided that the following conditions
31230557Sjimharris * are met:
32230557Sjimharris *
33230557Sjimharris *   * Redistributions of source code must retain the above copyright
34230557Sjimharris *     notice, this list of conditions and the following disclaimer.
35230557Sjimharris *   * Redistributions in binary form must reproduce the above copyright
36230557Sjimharris *     notice, this list of conditions and the following disclaimer in
37230557Sjimharris *     the documentation and/or other materials provided with the
38230557Sjimharris *     distribution.
39230557Sjimharris *
40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51230557Sjimharris */
52230557Sjimharris
53230557Sjimharris#include <sys/cdefs.h>
54230557Sjimharris__FBSDID("$FreeBSD$");
55230557Sjimharris
56230557Sjimharris/**
57230557Sjimharris * @file
58230557Sjimharris *
59230557Sjimharris * @brief This file contains the implementation of the SCIC_SDS_CONTROLLER
60230557Sjimharris *        public, protected, and private methods.
61230557Sjimharris */
62230557Sjimharris
63230557Sjimharris#include <dev/isci/types.h>
64230557Sjimharris#include <dev/isci/scil/sci_util.h>
65230557Sjimharris#include <dev/isci/scil/scic_controller.h>
66230557Sjimharris#include <dev/isci/scil/scic_port.h>
67230557Sjimharris#include <dev/isci/scil/scic_phy.h>
68230557Sjimharris#include <dev/isci/scil/scic_remote_device.h>
69230557Sjimharris#include <dev/isci/scil/scic_user_callback.h>
70230557Sjimharris#include <dev/isci/scil/scic_sds_pci.h>
71230557Sjimharris#include <dev/isci/scil/scic_sds_library.h>
72230557Sjimharris#include <dev/isci/scil/scic_sds_controller.h>
73230557Sjimharris#include <dev/isci/scil/scic_sds_controller_registers.h>
74230557Sjimharris#include <dev/isci/scil/scic_sds_port.h>
75230557Sjimharris#include <dev/isci/scil/scic_sds_phy.h>
76230557Sjimharris#include <dev/isci/scil/scic_sds_remote_device.h>
77230557Sjimharris#include <dev/isci/scil/scic_sds_request.h>
78230557Sjimharris#include <dev/isci/scil/scic_sds_logger.h>
79230557Sjimharris#include <dev/isci/scil/scic_sds_port_configuration_agent.h>
80230557Sjimharris#include <dev/isci/scil/scu_constants.h>
81230557Sjimharris#include <dev/isci/scil/scu_event_codes.h>
82230557Sjimharris#include <dev/isci/scil/scu_completion_codes.h>
83230557Sjimharris#include <dev/isci/scil/scu_task_context.h>
84230557Sjimharris#include <dev/isci/scil/scu_remote_node_context.h>
85230557Sjimharris#include <dev/isci/scil/scu_unsolicited_frame.h>
86230557Sjimharris#include <dev/isci/scil/intel_pci.h>
87230557Sjimharris#include <dev/isci/scil/scic_sgpio.h>
88230557Sjimharris#include <dev/isci/scil/scic_sds_phy_registers.h>
89230557Sjimharris
90230557Sjimharris#define SCU_CONTEXT_RAM_INIT_STALL_TIME      200
91230557Sjimharris#define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT  3
92230557Sjimharris#define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT  3
93230557Sjimharris
94230557Sjimharris#define SCU_MAX_ZPT_DWORD_INDEX              131
95230557Sjimharris
96230557Sjimharris/**
97230557Sjimharris * The number of milliseconds to wait for a phy to start.
98230557Sjimharris */
99230557Sjimharris#define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT      100
100230557Sjimharris
101230557Sjimharris/**
102230557Sjimharris * The number of milliseconds to wait while a given phy is consuming
103230557Sjimharris * power before allowing another set of phys to consume power.
104230557Sjimharris * Ultimately, this will be specified by OEM parameter.
105230557Sjimharris */
106230557Sjimharris#define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500
107230557Sjimharris
108230557Sjimharris/**
109230557Sjimharris * This macro will return the cycle bit of the completion queue entry
110230557Sjimharris */
111230557Sjimharris#define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000)
112230557Sjimharris
113230557Sjimharris/**
114230557Sjimharris * This macro will normalize the completion queue get pointer so its value
115230557Sjimharris * can be used as an index into an array
116230557Sjimharris */
117230557Sjimharris#define NORMALIZE_GET_POINTER(x) \
118230557Sjimharris   ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK)
119230557Sjimharris
120230557Sjimharris/**
121230557Sjimharris *  This macro will normalize the completion queue put pointer so its value
122230557Sjimharris *  can be used as an array inde
123230557Sjimharris */
124230557Sjimharris#define NORMALIZE_PUT_POINTER(x) \
125230557Sjimharris   ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK)
126230557Sjimharris
127230557Sjimharris
128230557Sjimharris/**
129230557Sjimharris * This macro will normalize the completion queue cycle pointer so it
130230557Sjimharris * matches the completion queue cycle bit
131230557Sjimharris */
132230557Sjimharris#define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \
133230557Sjimharris   (((U32)(SMU_CQGR_CYCLE_BIT & (x))) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT))
134230557Sjimharris
135230557Sjimharris/**
136230557Sjimharris * This macro will normalize the completion queue event entry so its value
137230557Sjimharris * can be used as an index.
138230557Sjimharris */
139230557Sjimharris#define NORMALIZE_EVENT_POINTER(x) \
140230557Sjimharris   ( \
141230557Sjimharris        ((U32)((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK)) \
142230557Sjimharris     >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \
143230557Sjimharris   )
144230557Sjimharris
145230557Sjimharris/**
146230557Sjimharris * This macro will increment the controllers completion queue index value
147230557Sjimharris * and possibly toggle the cycle bit if the completion queue index wraps
148230557Sjimharris * back to 0.
149230557Sjimharris */
150230557Sjimharris#define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \
151230557Sjimharris   INCREMENT_QUEUE_GET( \
152230557Sjimharris      (index), \
153230557Sjimharris      (cycle), \
154230557Sjimharris      (controller)->completion_queue_entries, \
155230557Sjimharris      SMU_CQGR_CYCLE_BIT \
156230557Sjimharris   )
157230557Sjimharris
158230557Sjimharris/**
159230557Sjimharris * This macro will increment the controllers event queue index value and
160230557Sjimharris * possibly toggle the event cycle bit if the event queue index wraps back
161230557Sjimharris * to 0.
162230557Sjimharris */
163230557Sjimharris#define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \
164230557Sjimharris   INCREMENT_QUEUE_GET( \
165230557Sjimharris      (index), \
166230557Sjimharris      (cycle), \
167230557Sjimharris      (controller)->completion_event_entries, \
168230557Sjimharris      SMU_CQGR_EVENT_CYCLE_BIT \
169230557Sjimharris   )
170230557Sjimharris
171230557Sjimharris//****************************************************************************-
172230557Sjimharris//* SCIC SDS Controller Initialization Methods
173230557Sjimharris//****************************************************************************-
174230557Sjimharris
175230557Sjimharris/**
176230557Sjimharris * @brief This timer is used to start another phy after we have given up on
177230557Sjimharris *        the previous phy to transition to the ready state.
178230557Sjimharris *
179230557Sjimharris * @param[in] controller
180230557Sjimharris */
181230557Sjimharrisstatic
182230557Sjimharrisvoid scic_sds_controller_phy_startup_timeout_handler(
183230557Sjimharris   void *controller
184230557Sjimharris)
185230557Sjimharris{
186230557Sjimharris   SCI_STATUS status;
187230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
188230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
189230557Sjimharris
190230557Sjimharris   this_controller->phy_startup_timer_pending = FALSE;
191230557Sjimharris
192230557Sjimharris   status = SCI_FAILURE;
193230557Sjimharris
194230557Sjimharris   while (status != SCI_SUCCESS)
195230557Sjimharris   {
196230557Sjimharris      status = scic_sds_controller_start_next_phy(this_controller);
197230557Sjimharris   }
198230557Sjimharris}
199230557Sjimharris
200230557Sjimharris/**
201230557Sjimharris * This method initializes the phy startup operations for controller start.
202230557Sjimharris *
203230557Sjimharris * @param this_controller
204230557Sjimharris */
205230557Sjimharrisstatic
206230557SjimharrisSCI_STATUS scic_sds_controller_initialize_phy_startup(
207230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
208230557Sjimharris)
209230557Sjimharris{
210230557Sjimharris   this_controller->phy_startup_timer = scic_cb_timer_create(
211230557Sjimharris      this_controller,
212230557Sjimharris      scic_sds_controller_phy_startup_timeout_handler,
213230557Sjimharris      this_controller
214230557Sjimharris   );
215230557Sjimharris
216230557Sjimharris   if (this_controller->phy_startup_timer == NULL)
217230557Sjimharris   {
218230557Sjimharris      return SCI_FAILURE_INSUFFICIENT_RESOURCES;
219230557Sjimharris   }
220230557Sjimharris   else
221230557Sjimharris   {
222230557Sjimharris      this_controller->next_phy_to_start = 0;
223230557Sjimharris      this_controller->phy_startup_timer_pending = FALSE;
224230557Sjimharris   }
225230557Sjimharris
226230557Sjimharris   return SCI_SUCCESS;
227230557Sjimharris}
228230557Sjimharris
229230557Sjimharris/**
230230557Sjimharris * This method initializes the power control operations for the controller
231230557Sjimharris * object.
232230557Sjimharris *
233230557Sjimharris * @param this_controller
234230557Sjimharris */
235230557Sjimharrisvoid scic_sds_controller_initialize_power_control(
236230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
237230557Sjimharris)
238230557Sjimharris{
239230557Sjimharris   this_controller->power_control.timer = scic_cb_timer_create(
240230557Sjimharris      this_controller,
241230557Sjimharris      scic_sds_controller_power_control_timer_handler,
242230557Sjimharris      this_controller
243230557Sjimharris   );
244230557Sjimharris
245230557Sjimharris   memset(
246230557Sjimharris      this_controller->power_control.requesters,
247230557Sjimharris      0,
248230557Sjimharris      sizeof(this_controller->power_control.requesters)
249230557Sjimharris   );
250230557Sjimharris
251230557Sjimharris   this_controller->power_control.phys_waiting = 0;
252230557Sjimharris   this_controller->power_control.remote_devices_granted_power = 0;
253230557Sjimharris}
254230557Sjimharris
255230557Sjimharris// ---------------------------------------------------------------------------
256230557Sjimharris
257230557Sjimharris#define SCU_REMOTE_NODE_CONTEXT_ALIGNMENT       (32)
258230557Sjimharris#define SCU_TASK_CONTEXT_ALIGNMENT              (256)
259230557Sjimharris#define SCU_UNSOLICITED_FRAME_ADDRESS_ALIGNMENT (64)
260230557Sjimharris#define SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT  (1024)
261230557Sjimharris#define SCU_UNSOLICITED_FRAME_HEADER_ALIGNMENT  (64)
262230557Sjimharris
263230557Sjimharris// ---------------------------------------------------------------------------
264230557Sjimharris
265230557Sjimharris/**
266230557Sjimharris * @brief This method builds the memory descriptor table for this
267230557Sjimharris *        controller.
268230557Sjimharris *
269230557Sjimharris * @param[in] this_controller This parameter specifies the controller
270230557Sjimharris *            object for which to build the memory table.
271230557Sjimharris *
272230557Sjimharris * @return none
273230557Sjimharris */
274230557Sjimharrisvoid scic_sds_controller_build_memory_descriptor_table(
275230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
276230557Sjimharris)
277230557Sjimharris{
278230557Sjimharris   sci_base_mde_construct(
279230557Sjimharris      &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
280230557Sjimharris      SCU_COMPLETION_RAM_ALIGNMENT,
281230557Sjimharris      (sizeof(U32) * this_controller->completion_queue_entries),
282230557Sjimharris      (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
283230557Sjimharris   );
284230557Sjimharris
285230557Sjimharris   sci_base_mde_construct(
286230557Sjimharris      &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
287230557Sjimharris      SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
288230557Sjimharris      this_controller->remote_node_entries * sizeof(SCU_REMOTE_NODE_CONTEXT_T),
289230557Sjimharris      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
290230557Sjimharris   );
291230557Sjimharris
292230557Sjimharris   sci_base_mde_construct(
293230557Sjimharris      &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
294230557Sjimharris      SCU_TASK_CONTEXT_ALIGNMENT,
295230557Sjimharris      this_controller->task_context_entries * sizeof(SCU_TASK_CONTEXT_T),
296230557Sjimharris      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
297230557Sjimharris   );
298230557Sjimharris
299230557Sjimharris   // The UF buffer address table size must be programmed to a power
300230557Sjimharris   // of 2.  Find the first power of 2 that is equal to or greater then
301230557Sjimharris   // the number of unsolicited frame buffers to be utilized.
302230557Sjimharris   scic_sds_unsolicited_frame_control_set_address_table_count(
303230557Sjimharris      &this_controller->uf_control
304230557Sjimharris   );
305230557Sjimharris
306230557Sjimharris   sci_base_mde_construct(
307230557Sjimharris      &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
308230557Sjimharris      SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
309230557Sjimharris      scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
310230557Sjimharris      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
311230557Sjimharris   );
312230557Sjimharris}
313230557Sjimharris
314230557Sjimharris/**
315230557Sjimharris * @brief This method validates the driver supplied memory descriptor
316230557Sjimharris *        table.
317230557Sjimharris *
318230557Sjimharris * @param[in] this_controller
319230557Sjimharris *
320230557Sjimharris * @return SCI_STATUS
321230557Sjimharris */
322230557SjimharrisSCI_STATUS scic_sds_controller_validate_memory_descriptor_table(
323230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
324230557Sjimharris)
325230557Sjimharris{
326230557Sjimharris   BOOL mde_list_valid;
327230557Sjimharris
328230557Sjimharris   mde_list_valid = sci_base_mde_is_valid(
329230557Sjimharris      &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
330230557Sjimharris      SCU_COMPLETION_RAM_ALIGNMENT,
331230557Sjimharris      (sizeof(U32) * this_controller->completion_queue_entries),
332230557Sjimharris      (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
333230557Sjimharris   );
334230557Sjimharris
335230557Sjimharris   if (mde_list_valid == FALSE)
336230557Sjimharris      return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
337230557Sjimharris
338230557Sjimharris   mde_list_valid = sci_base_mde_is_valid(
339230557Sjimharris      &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
340230557Sjimharris      SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
341230557Sjimharris      this_controller->remote_node_entries * sizeof(SCU_REMOTE_NODE_CONTEXT_T),
342230557Sjimharris      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
343230557Sjimharris   );
344230557Sjimharris
345230557Sjimharris   if (mde_list_valid == FALSE)
346230557Sjimharris      return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
347230557Sjimharris
348230557Sjimharris   mde_list_valid = sci_base_mde_is_valid(
349230557Sjimharris      &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
350230557Sjimharris      SCU_TASK_CONTEXT_ALIGNMENT,
351230557Sjimharris      this_controller->task_context_entries * sizeof(SCU_TASK_CONTEXT_T),
352230557Sjimharris      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
353230557Sjimharris   );
354230557Sjimharris
355230557Sjimharris   if (mde_list_valid == FALSE)
356230557Sjimharris      return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
357230557Sjimharris
358230557Sjimharris   mde_list_valid = sci_base_mde_is_valid(
359230557Sjimharris      &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
360230557Sjimharris      SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
361230557Sjimharris      scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
362230557Sjimharris      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
363230557Sjimharris   );
364230557Sjimharris
365230557Sjimharris   if (mde_list_valid == FALSE)
366230557Sjimharris      return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
367230557Sjimharris
368230557Sjimharris   return SCI_SUCCESS;
369230557Sjimharris}
370230557Sjimharris
371230557Sjimharris/**
372230557Sjimharris * @brief This method initializes the controller with the physical memory
373230557Sjimharris *        addresses that are used to communicate with the driver.
374230557Sjimharris *
375230557Sjimharris * @param[in] this_controller
376230557Sjimharris *
377230557Sjimharris * @return none
378230557Sjimharris */
379230557Sjimharrisvoid scic_sds_controller_ram_initialization(
380230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
381230557Sjimharris)
382230557Sjimharris{
383230557Sjimharris   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde;
384230557Sjimharris
385230557Sjimharris   // The completion queue is actually placed in cacheable memory
386230557Sjimharris   // Therefore it no longer comes out of memory in the MDL.
387230557Sjimharris   mde = &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE];
388230557Sjimharris   this_controller->completion_queue = (U32*) mde->virtual_address;
389230557Sjimharris   SMU_CQBAR_WRITE(this_controller, mde->physical_address);
390230557Sjimharris
391230557Sjimharris   // Program the location of the Remote Node Context table
392230557Sjimharris   // into the SCU.
393230557Sjimharris   mde = &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT];
394230557Sjimharris   this_controller->remote_node_context_table = (SCU_REMOTE_NODE_CONTEXT_T *)
395230557Sjimharris                                                mde->virtual_address;
396230557Sjimharris   SMU_RNCBAR_WRITE(this_controller, mde->physical_address);
397230557Sjimharris
398230557Sjimharris   // Program the location of the Task Context table into the SCU.
399230557Sjimharris   mde = &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT];
400230557Sjimharris   this_controller->task_context_table = (SCU_TASK_CONTEXT_T *)
401230557Sjimharris                                         mde->virtual_address;
402230557Sjimharris   SMU_HTTBAR_WRITE(this_controller, mde->physical_address);
403230557Sjimharris
404230557Sjimharris   mde = &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER];
405230557Sjimharris   scic_sds_unsolicited_frame_control_construct(
406230557Sjimharris      &this_controller->uf_control, mde, this_controller
407230557Sjimharris   );
408230557Sjimharris
409230557Sjimharris   // Inform the silicon as to the location of the UF headers and
410230557Sjimharris   // address table.
411230557Sjimharris   SCU_UFHBAR_WRITE(
412230557Sjimharris      this_controller,
413230557Sjimharris      this_controller->uf_control.headers.physical_address);
414230557Sjimharris   SCU_PUFATHAR_WRITE(
415230557Sjimharris      this_controller,
416230557Sjimharris      this_controller->uf_control.address_table.physical_address);
417230557Sjimharris
418230557Sjimharris   //enable the ECC correction and detection.
419230557Sjimharris   SCU_SECR0_WRITE(
420230557Sjimharris      this_controller,
421230557Sjimharris      (SIGNLE_BIT_ERROR_CORRECTION_ENABLE
422230557Sjimharris       | MULTI_BIT_ERROR_REPORTING_ENABLE
423230557Sjimharris       | SINGLE_BIT_ERROR_REPORTING_ENABLE) );
424230557Sjimharris   SCU_SECR1_WRITE(
425230557Sjimharris      this_controller,
426230557Sjimharris      (SIGNLE_BIT_ERROR_CORRECTION_ENABLE
427230557Sjimharris       | MULTI_BIT_ERROR_REPORTING_ENABLE
428230557Sjimharris       | SINGLE_BIT_ERROR_REPORTING_ENABLE) );
429230557Sjimharris}
430230557Sjimharris
431230557Sjimharris/**
432230557Sjimharris * @brief This method initializes the task context data for the controller.
433230557Sjimharris *
434230557Sjimharris * @param[in] this_controller
435230557Sjimharris *
436230557Sjimharris * @return none
437230557Sjimharris */
438230557Sjimharrisvoid scic_sds_controller_assign_task_entries(
439230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
440230557Sjimharris)
441230557Sjimharris{
442230557Sjimharris   U32 task_assignment;
443230557Sjimharris
444230557Sjimharris   // Assign all the TCs to function 0
445230557Sjimharris   // TODO: Do we actually need to read this register to write it back?
446230557Sjimharris   task_assignment = SMU_TCA_READ(this_controller, 0);
447230557Sjimharris
448230557Sjimharris   task_assignment =
449230557Sjimharris      (
450230557Sjimharris          task_assignment
451230557Sjimharris        | (SMU_TCA_GEN_VAL(STARTING, 0))
452230557Sjimharris        | (SMU_TCA_GEN_VAL(ENDING,  this_controller->task_context_entries - 1))
453230557Sjimharris        | (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE))
454230557Sjimharris      );
455230557Sjimharris
456230557Sjimharris   SMU_TCA_WRITE(this_controller, 0, task_assignment);
457230557Sjimharris}
458230557Sjimharris
459230557Sjimharris/**
460230557Sjimharris * @brief This method initializes the hardware completion queue.
461230557Sjimharris *
462230557Sjimharris * @param[in] this_controller
463230557Sjimharris */
464230557Sjimharrisvoid scic_sds_controller_initialize_completion_queue(
465230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
466230557Sjimharris)
467230557Sjimharris{
468230557Sjimharris   U32 index;
469230557Sjimharris   U32 completion_queue_control_value;
470230557Sjimharris   U32 completion_queue_get_value;
471230557Sjimharris   U32 completion_queue_put_value;
472230557Sjimharris
473230557Sjimharris   this_controller->completion_queue_get = 0;
474230557Sjimharris
475230557Sjimharris   completion_queue_control_value = (
476230557Sjimharris        SMU_CQC_QUEUE_LIMIT_SET(this_controller->completion_queue_entries - 1)
477230557Sjimharris      | SMU_CQC_EVENT_LIMIT_SET(this_controller->completion_event_entries - 1)
478230557Sjimharris   );
479230557Sjimharris
480230557Sjimharris   SMU_CQC_WRITE(this_controller, completion_queue_control_value);
481230557Sjimharris
482230557Sjimharris   // Set the completion queue get pointer and enable the queue
483230557Sjimharris   completion_queue_get_value = (
484230557Sjimharris        (SMU_CQGR_GEN_VAL(POINTER, 0))
485230557Sjimharris      | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0))
486230557Sjimharris      | (SMU_CQGR_GEN_BIT(ENABLE))
487230557Sjimharris      | (SMU_CQGR_GEN_BIT(EVENT_ENABLE))
488230557Sjimharris   );
489230557Sjimharris
490230557Sjimharris   SMU_CQGR_WRITE(this_controller, completion_queue_get_value);
491230557Sjimharris
492230557Sjimharris   this_controller->completion_queue_get = completion_queue_get_value;
493230557Sjimharris
494230557Sjimharris   // Set the completion queue put pointer
495230557Sjimharris   completion_queue_put_value = (
496230557Sjimharris        (SMU_CQPR_GEN_VAL(POINTER, 0))
497230557Sjimharris      | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0))
498230557Sjimharris   );
499230557Sjimharris
500230557Sjimharris   SMU_CQPR_WRITE(this_controller, completion_queue_put_value);
501230557Sjimharris
502230557Sjimharris   // Initialize the cycle bit of the completion queue entries
503230557Sjimharris   for (index = 0; index < this_controller->completion_queue_entries; index++)
504230557Sjimharris   {
505230557Sjimharris      // If get.cycle_bit != completion_queue.cycle_bit
506230557Sjimharris      // its not a valid completion queue entry
507230557Sjimharris      // so at system start all entries are invalid
508230557Sjimharris      this_controller->completion_queue[index] = 0x80000000;
509230557Sjimharris   }
510230557Sjimharris}
511230557Sjimharris
512230557Sjimharris/**
513230557Sjimharris * @brief This method initializes the hardware unsolicited frame queue.
514230557Sjimharris *
515230557Sjimharris * @param[in] this_controller
516230557Sjimharris */
517230557Sjimharrisvoid scic_sds_controller_initialize_unsolicited_frame_queue(
518230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
519230557Sjimharris)
520230557Sjimharris{
521230557Sjimharris   U32 frame_queue_control_value;
522230557Sjimharris   U32 frame_queue_get_value;
523230557Sjimharris   U32 frame_queue_put_value;
524230557Sjimharris
525230557Sjimharris   // Write the queue size
526230557Sjimharris   frame_queue_control_value =
527230557Sjimharris      SCU_UFQC_GEN_VAL(QUEUE_SIZE, this_controller->uf_control.address_table.count);
528230557Sjimharris
529230557Sjimharris   SCU_UFQC_WRITE(this_controller, frame_queue_control_value);
530230557Sjimharris
531230557Sjimharris   // Setup the get pointer for the unsolicited frame queue
532230557Sjimharris   frame_queue_get_value = (
533230557Sjimharris         SCU_UFQGP_GEN_VAL(POINTER, 0)
534230557Sjimharris      |  SCU_UFQGP_GEN_BIT(ENABLE_BIT)
535230557Sjimharris      );
536230557Sjimharris
537230557Sjimharris   SCU_UFQGP_WRITE(this_controller, frame_queue_get_value);
538230557Sjimharris
539230557Sjimharris   // Setup the put pointer for the unsolicited frame queue
540230557Sjimharris   frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0);
541230557Sjimharris
542230557Sjimharris   SCU_UFQPP_WRITE(this_controller, frame_queue_put_value);
543230557Sjimharris}
544230557Sjimharris
545230557Sjimharris/**
546230557Sjimharris * @brief This method enables the hardware port task scheduler.
547230557Sjimharris *
548230557Sjimharris * @param[in] this_controller
549230557Sjimharris */
550230557Sjimharrisvoid scic_sds_controller_enable_port_task_scheduler(
551230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
552230557Sjimharris)
553230557Sjimharris{
554230557Sjimharris   U32 port_task_scheduler_value;
555230557Sjimharris
556230557Sjimharris   port_task_scheduler_value = SCU_PTSGCR_READ(this_controller);
557230557Sjimharris
558230557Sjimharris   port_task_scheduler_value |=
559230557Sjimharris      (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE));
560230557Sjimharris
561230557Sjimharris   SCU_PTSGCR_WRITE(this_controller, port_task_scheduler_value);
562230557Sjimharris}
563230557Sjimharris
564230557Sjimharris// ---------------------------------------------------------------------------
565230557Sjimharris
566230557Sjimharris#ifdef ARLINGTON_BUILD
567230557Sjimharris/**
568230557Sjimharris * This method will read from the lexington status register.  This is required
569230557Sjimharris * as a read fence to the lexington register writes.
570230557Sjimharris *
571230557Sjimharris * @param this_controller
572230557Sjimharris */
573230557Sjimharrisvoid scic_sds_controller_lex_status_read_fence(
574230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
575230557Sjimharris)
576230557Sjimharris{
577230557Sjimharris   U32 lex_status;
578230557Sjimharris
579230557Sjimharris   // Read Fence
580230557Sjimharris   lex_status = lex_register_read(
581230557Sjimharris                  this_controller, this_controller->lex_registers + 0xC4);
582230557Sjimharris
583230557Sjimharris   SCIC_LOG_TRACE((
584230557Sjimharris      sci_base_object_get_logger(this_controller),
585230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
586230557Sjimharris      "Controller 0x%x lex_status = 0x%08x\n",
587230557Sjimharris      this_controller, lex_status
588230557Sjimharris   ));
589230557Sjimharris}
590230557Sjimharris
591230557Sjimharris/**
592230557Sjimharris * This method will initialize the arlington through the LEX_BAR.
593230557Sjimharris *
594230557Sjimharris * @param this_controller
595230557Sjimharris */
596230557Sjimharrisvoid scic_sds_controller_lex_atux_initialization(
597230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
598230557Sjimharris)
599230557Sjimharris{
600230557Sjimharris   // 1. Reset all SCU PHY
601230557Sjimharris   lex_register_write(
602230557Sjimharris      this_controller, this_controller->lex_registers + 0x28, 0x0020FFFF) ;
603230557Sjimharris
604230557Sjimharris   // 2. Write to LEX_CTRL
605230557Sjimharris   lex_register_write(
606230557Sjimharris      this_controller, this_controller->lex_registers + 0xC0, 0x00000700);
607230557Sjimharris
608230557Sjimharris   scic_sds_controller_lex_status_read_fence(this_controller);
609230557Sjimharris
610230557Sjimharris   // 3. Enable PCI Master
611230557Sjimharris   lex_register_write(
612230557Sjimharris      this_controller, this_controller->lex_registers + 0x70, 0x00000002);
613230557Sjimharris
614230557Sjimharris   // 4. Enable SCU Register Clock Domain
615230557Sjimharris   lex_register_write(
616230557Sjimharris      this_controller, this_controller->lex_registers + 0xC0, 0x00000300);
617230557Sjimharris
618230557Sjimharris   scic_sds_controller_lex_status_read_fence(this_controller);
619230557Sjimharris
620230557Sjimharris   // 5.1 Release PHY-A Reg Reset
621230557Sjimharris   lex_register_write(
622230557Sjimharris      this_controller, this_controller->lex_registers + 0x28, 0x0000FFFF);
623230557Sjimharris
624230557Sjimharris   // 5.2 Initialize the AFE for PHY-A
625230557Sjimharris   scic_sds_controller_afe_initialization(this_controller);
626230557Sjimharris
627230557Sjimharris   scic_sds_controller_lex_status_read_fence(this_controller);
628230557Sjimharris
629230557Sjimharris#if 0
630230557Sjimharris   // 5.3 Release PHY Reg Reset
631230557Sjimharris   lex_register_write(
632230557Sjimharris      this_controller, this_controller->lex_registers + 0x28, 0x0000FFFF);
633230557Sjimharris#endif
634230557Sjimharris
635230557Sjimharris   // 6.1 Release PHY-B Reg Reset
636230557Sjimharris   lex_register_write(
637230557Sjimharris      this_controller, this_controller->lex_registers + 0x28, 0x0040FFFF) ;
638230557Sjimharris
639230557Sjimharris   // 6.2 Initialize the AFE for PHY-B
640230557Sjimharris   scic_sds_controller_afe_initialization(this_controller);
641230557Sjimharris
642230557Sjimharris   scic_sds_controller_lex_status_read_fence(this_controller);
643230557Sjimharris
644230557Sjimharris#if 0
645230557Sjimharris   // 6.3 Release PHY-B Reg Reset
646230557Sjimharris   lex_register_write(
647230557Sjimharris      this_controller, this_controller->lex_registers + 0x28, 0x0040FFFF) ;
648230557Sjimharris#endif
649230557Sjimharris
650230557Sjimharris   // 7. Enable SCU clock domaion
651230557Sjimharris   lex_register_write(
652230557Sjimharris      this_controller, this_controller->lex_registers + 0xC0, 0x00000100);
653230557Sjimharris
654230557Sjimharris   scic_sds_controller_lex_status_read_fence(this_controller);
655230557Sjimharris
656230557Sjimharris   // 8. Release LEX SCU Reset
657230557Sjimharris   lex_register_write(
658230557Sjimharris      this_controller, this_controller->lex_registers + 0xC0, 0x00000000);
659230557Sjimharris
660230557Sjimharris   scic_sds_controller_lex_status_read_fence(this_controller);
661230557Sjimharris
662230557Sjimharris#if !defined(DISABLE_INTERRUPTS)
663230557Sjimharris   // 8a. Set legacy interrupts (SCU INTx to PCI-x INTA)
664230557Sjimharris   lex_register_write(
665230557Sjimharris      this_controller, this_controller->lex_registers + 0xC0, 0x00000800);
666230557Sjimharris
667230557Sjimharris   scic_sds_controller_lex_status_read_fence(this_controller);
668230557Sjimharris#endif
669230557Sjimharris
670230557Sjimharris#if 0
671230557Sjimharris   // 9. Override TXOLVL
672230557Sjimharris   //write to lex_ctrl
673230557Sjimharris   lex_register_write(
674230557Sjimharris      this_controller, this_controller->lex_registers + 0xC0, 0x27800000);
675230557Sjimharris#endif
676230557Sjimharris
677230557Sjimharris   // 10. Release PHY-A & PHY-B Resets
678230557Sjimharris   lex_register_write(
679230557Sjimharris      this_controller, this_controller->lex_registers + 0x28, 0x0000FF77);
680230557Sjimharris
681230557Sjimharris   lex_register_write(
682230557Sjimharris      this_controller, this_controller->lex_registers + 0x28, 0x0000FF55);
683230557Sjimharris
684230557Sjimharris   lex_register_write(
685230557Sjimharris      this_controller, this_controller->lex_registers + 0x28, 0x0000FF11);
686230557Sjimharris
687230557Sjimharris   lex_register_write(
688230557Sjimharris      this_controller, this_controller->lex_registers + 0x28, 0x0000FF00);
689230557Sjimharris
690230557Sjimharris   lex_register_write(
691230557Sjimharris      this_controller, this_controller->lex_registers + 0x28, 0x0003FF00);
692230557Sjimharris}
693230557Sjimharris#endif // ARLINGTON_BUILD
694230557Sjimharris
695230557Sjimharris// ---------------------------------------------------------------------------
696230557Sjimharris
697230557Sjimharris#ifdef ARLINGTON_BUILD
698230557Sjimharris/**
699230557Sjimharris * This method enables chipwatch on the arlington board
700230557Sjimharris *
701230557Sjimharris * @param[in] this_controller
702230557Sjimharris */
703230557Sjimharrisvoid scic_sds_controller_enable_chipwatch(
704230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
705230557Sjimharris)
706230557Sjimharris{
707230557Sjimharris   lex_register_write(
708230557Sjimharris      this_controller, this_controller->lex_registers + 0x88, 0x09090909);
709230557Sjimharris
710230557Sjimharris   lex_register_write(
711230557Sjimharris      this_controller, this_controller->lex_registers + 0x8C, 0xcac9c862);
712230557Sjimharris}
713230557Sjimharris#endif
714230557Sjimharris
715230557Sjimharris/**
716230557Sjimharris * This macro is used to delay between writes to the AFE registers
717230557Sjimharris * during AFE initialization.
718230557Sjimharris */
719230557Sjimharris#define AFE_REGISTER_WRITE_DELAY 10
720230557Sjimharris
721230557Sjimharris/**
722230557Sjimharris * Initialize the AFE for this phy index.
723230557Sjimharris *
724230557Sjimharris * @todo We need to read the AFE setup from the OEM parameters
725230557Sjimharris *
726230557Sjimharris * @param[in] this_controller
727230557Sjimharris *
728230557Sjimharris * @return none
729230557Sjimharris */
730230557Sjimharris#if defined(ARLINGTON_BUILD)
731230557Sjimharrisvoid scic_sds_controller_afe_initialization(
732230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
733230557Sjimharris)
734230557Sjimharris{
735230557Sjimharris   // 1. Establish Power
736230557Sjimharris   //       Hold Bias, PLL, and RX TX in reset and powerdown
737230557Sjimharris   //       pe_afe0_rst_n = 0
738230557Sjimharris   //       pe_afe0_txpdn0,1,2,3 = 1
739230557Sjimharris   //       pe_afe0_rxpdn0,1,2,3 = 1
740230557Sjimharris   //       pe_afe0_txrst0,1,2,3_n = 0
741230557Sjimharris   //       pe_afe0_rxrst0,1,2,3_n = 0
742230557Sjimharris   //       wait 1us
743230557Sjimharris   //       pe_afe0_rst_n = 1
744230557Sjimharris   //       wait 1us
745230557Sjimharris   scu_afe_register_write(
746230557Sjimharris      this_controller, afe_pll_control, 0x00247506);
747230557Sjimharris
748230557Sjimharris   // 2. Write 0x00000000 to AFE XCVR Ctrl2
749230557Sjimharris   scu_afe_register_write(
750230557Sjimharris      this_controller, afe_dfx_transceiver_status_clear, 0x00000000);
751230557Sjimharris
752230557Sjimharris   // 3. afe0_override_en = 0
753230557Sjimharris   //    afe0_pll_dis_override = 0
754230557Sjimharris   //    afe0_tx_rst_override = 0
755230557Sjimharris   //    afe0_pll_dis = 1
756230557Sjimharris   //    pe_afe0_txrate = 01
757230557Sjimharris   //    pe_afe0_rxrate = 01
758230557Sjimharris   //    pe_afe0_txdis = 11
759230557Sjimharris   //    pe_afe0_txoob = 1
760230557Sjimharris   //    pe_afe0_txovlv = 9'b001110000
761230557Sjimharris   scu_afe_register_write(
762230557Sjimharris      this_controller, afe_transceiver_control0[0], 0x0700141e);
763230557Sjimharris
764230557Sjimharris   // 4. Configure PLL Unit
765230557Sjimharris   //    Write 0x00200506 to AFE PLL Ctrl Register 0
766230557Sjimharris   scu_afe_register_write(this_controller, afe_pll_control,     0x00200506);
767230557Sjimharris   scu_afe_register_write(this_controller, afe_pll_dfx_control, 0x10000080);
768230557Sjimharris
769230557Sjimharris   // 5. Configure Bias Unit
770230557Sjimharris   scu_afe_register_write(this_controller, afe_bias_control[0], 0x00124814);
771230557Sjimharris   scu_afe_register_write(this_controller, afe_bias_control[1], 0x24900000);
772230557Sjimharris
773230557Sjimharris   // 6. Configure Transceiver Units
774230557Sjimharris   scu_afe_register_write(
775230557Sjimharris      this_controller, afe_transceiver_control0[0], 0x0702941e);
776230557Sjimharris
777230557Sjimharris   scu_afe_register_write(
778230557Sjimharris      this_controller, afe_transceiver_control1[0], 0x0000000a);
779230557Sjimharris
780230557Sjimharris   // 7. Configure RX Units
781230557Sjimharris   scu_afe_register_write(
782230557Sjimharris      this_controller, afe_transceiver_equalization_control[0], 0x00ba2223);
783230557Sjimharris
784230557Sjimharris   scu_afe_register_write(
785230557Sjimharris      this_controller, reserved_0028_003c[2], 0x00000000);
786230557Sjimharris
787230557Sjimharris   // 8. Configure TX Units
788230557Sjimharris   scu_afe_register_write(
789230557Sjimharris      this_controller, afe_dfx_transmit_control_register[0], 0x03815428);
790230557Sjimharris
791230557Sjimharris   // 9. Transfer control to PE signals
792230557Sjimharris   scu_afe_register_write(
793230557Sjimharris      this_controller, afe_dfx_transceiver_status_clear, 0x00000010);
794230557Sjimharris
795230557Sjimharris   // 10. Release PLL Powerdown
796230557Sjimharris   scu_afe_register_write(this_controller, afe_pll_control, 0x00200504);
797230557Sjimharris
798230557Sjimharris   // 11. Release PLL Reset
799230557Sjimharris   scu_afe_register_write(this_controller, afe_pll_control, 0x00200505);
800230557Sjimharris
801230557Sjimharris   // 12. Wait for PLL to Lock
802230557Sjimharris   // (afe0_comm_sta [1:0] should go to 1'b11, and
803230557Sjimharris   //                [5:2] is 0x5, 0x6, 0x7, 0x8, or 0x9
804230557Sjimharris   scu_afe_register_write(this_controller, afe_pll_control, 0x00200501);
805230557Sjimharris
806230557Sjimharris   while ((scu_afe_register_read(this_controller, afe_common_status) & 0x03) != 0x03)
807230557Sjimharris   {
808230557Sjimharris      // Give time for the PLLs to lock
809230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
810230557Sjimharris   }
811230557Sjimharris
812230557Sjimharris   // 13. pe_afe0_rxpdn0 = 0
813230557Sjimharris   //     pe_afe0_rxrst0 = 1
814230557Sjimharris   //     pe_afe0_txrst0_n = 1
815230557Sjimharris   //     pe_afe_txoob0_n = 0
816230557Sjimharris   scu_afe_register_write(
817230557Sjimharris      this_controller, afe_transceiver_control0[0], 0x07028c11);
818230557Sjimharris}
819230557Sjimharris
820230557Sjimharris#elif defined(PLEASANT_RIDGE_BUILD)
821230557Sjimharris
822230557Sjimharrisvoid scic_sds_controller_afe_initialization(
823230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
824230557Sjimharris)
825230557Sjimharris{
826230557Sjimharris   U32 afe_status;
827230557Sjimharris   U32 phy_id;
828230557Sjimharris
829230557Sjimharris#if defined(SPREADSHEET_AFE_SETTINGS)
830230557Sjimharris   // Clear DFX Status registers
831230557Sjimharris   scu_afe_register_write(
832230557Sjimharris      this_controller, afe_dfx_master_control0, 0x0000000f);
833230557Sjimharris   // Configure bias currents to normal
834230557Sjimharris   scu_afe_register_write(
835230557Sjimharris      this_controller, afe_bias_control, 0x0000aa00);
836230557Sjimharris   // Enable PLL
837230557Sjimharris   scu_afe_register_write(
838230557Sjimharris      this_controller, afe_pll_control0, 0x80000908);
839230557Sjimharris
840230557Sjimharris   // Wait for the PLL to lock
841230557Sjimharris   do
842230557Sjimharris   {
843230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
844230557Sjimharris      afe_status = scu_afe_register_read(
845230557Sjimharris                     this_controller, afe_common_block_status);
846230557Sjimharris   }
847230557Sjimharris   while((afe_status & 0x00001000) == 0);
848230557Sjimharris
849230557Sjimharris   for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
850230557Sjimharris   {
851230557Sjimharris      // Initialize transceiver channels
852230557Sjimharris      scu_afe_register_write(
853230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000157);
854230557Sjimharris      // Configure transceiver modes
855230557Sjimharris      scu_afe_register_write(
856230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016d1a);
857230557Sjimharris      // Configure receiver parameters
858230557Sjimharris      scu_afe_register_write(
859230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01501014);
860230557Sjimharris      // Configure transmitter parameters
861230557Sjimharris      scu_afe_register_write(
862230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00000000);
863230557Sjimharris      // Configure transmitter equalization
864230557Sjimharris      scu_afe_register_write(
865230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0, 0x000bdd08);
866230557Sjimharris      scu_afe_register_write(
867230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1, 0x000ffc00);
868230557Sjimharris      scu_afe_register_write(
869230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2, 0x000b7c09);
870230557Sjimharris      scu_afe_register_write(
871230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3, 0x000afc6e);
872230557Sjimharris      // Configure transmitter SSC parameters
873230557Sjimharris      scu_afe_register_write(
874230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00000000);
875230557Sjimharris      // Configure receiver parameters
876230557Sjimharris      scu_afe_register_write(
877230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x3208903f);
878230557Sjimharris
879230557Sjimharris      // Start power on sequence
880230557Sjimharris      // Enable bias currents to transceivers and wait 200ns
881230557Sjimharris      scu_afe_register_write(
882230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000154);
883230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
884230557Sjimharris      // Take receiver out of power down and wait 200ns
885230557Sjimharris      scu_afe_register_write(
886230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x3801611a);
887230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
888230557Sjimharris      // Take receiver out of reset and wait 200ns
889230557Sjimharris      scu_afe_register_write(
890230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x3801631a);
891230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
892230557Sjimharris      // Take transmitter out of power down and wait 200ns
893230557Sjimharris      scu_afe_register_write(
894230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016318);
895230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
896230557Sjimharris      // Take transmitter out of reset and wait 200ns
897230557Sjimharris      scu_afe_register_write(
898230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016319);
899230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
900230557Sjimharris      // Take transmitter out of DC idle
901230557Sjimharris      scu_afe_register_write(
902230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016319);
903230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
904230557Sjimharris   }
905230557Sjimharris
906230557Sjimharris   // Transfer control to the PEs
907230557Sjimharris   scu_afe_register_write(
908230557Sjimharris      this_controller, afe_dfx_master_control0, 0x00010f00);
909230557Sjimharris#else // !defined(SPREADSHEET_AFE_SETTINGS)
910230557Sjimharris   // These are the AFEE settings used by the SV group
911230557Sjimharris   // Clear DFX Status registers
912230557Sjimharris   scu_afe_register_write(
913230557Sjimharris      this_controller, afe_dfx_master_control0, 0x0081000f);
914230557Sjimharris   // Configure bias currents to normal
915230557Sjimharris   scu_afe_register_write(
916230557Sjimharris      this_controller, afe_bias_control, 0x0000aa00);
917230557Sjimharris   // Enable PLL
918230557Sjimharris   scu_afe_register_write(
919230557Sjimharris      this_controller, afe_pll_control0, 0x80000908);
920230557Sjimharris
921230557Sjimharris   // Wait for the PLL to lock
922230557Sjimharris   // Note: this is done later in the SV shell script however this looks
923230557Sjimharris   //       like the location to do this since we have enabled the PLL.
924230557Sjimharris   do
925230557Sjimharris   {
926230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
927230557Sjimharris      afe_status = scu_afe_register_read(
928230557Sjimharris                     this_controller, afe_common_block_status);
929230557Sjimharris   }
930230557Sjimharris   while((afe_status & 0x00001000) == 0);
931230557Sjimharris
932230557Sjimharris   // Make sure BIST is disabled
933230557Sjimharris   scu_afe_register_write(
934230557Sjimharris      this_controller, afe_dfx_master_control1, 0x00000000);
935230557Sjimharris   // Shorten SAS SNW lock time
936230557Sjimharris   scu_afe_register_write(
937230557Sjimharris      this_controller, afe_pmsn_master_control0, 0x7bd316ad);
938230557Sjimharris
939230557Sjimharris   for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
940230557Sjimharris   {
941230557Sjimharris      // Initialize transceiver channels
942230557Sjimharris      scu_afe_register_write(
943230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000174);
944230557Sjimharris      // Configure SSC control
945230557Sjimharris      scu_afe_register_write(
946230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00030000);
947230557Sjimharris      // Configure transceiver modes
948230557Sjimharris      scu_afe_register_write(
949230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0000651a);
950230557Sjimharris      // Power up TX RX and RX OOB
951230557Sjimharris      scu_afe_register_write(
952230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006518);
953230557Sjimharris      // Enable RX OOB Detect
954230557Sjimharris      scu_afe_register_write(
955230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006518);
956230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
957230557Sjimharris      #if 0
958230557Sjimharris      // Configure transmitter parameters
959230557Sjimharris      scu_afe_register_write(
960230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00000000);
961230557Sjimharris      // Configure transmitter equalization
962230557Sjimharris      scu_afe_register_write(
963230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0, 0x000bdd08);
964230557Sjimharris      scu_afe_register_write(
965230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1, 0x000ffc00);
966230557Sjimharris      scu_afe_register_write(
967230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2, 0x000b7c09);
968230557Sjimharris      scu_afe_register_write(
969230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3, 0x000afc6e);
970230557Sjimharris      // Configure transmitter SSC parameters
971230557Sjimharris      // Power up TX RX
972230557Sjimharris
973230557Sjimharris      scu_afe_register_write(
974230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000154);
975230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
976230557Sjimharris
977230557Sjimharris      // FFE = Max
978230557Sjimharris      scu_afe_register_write(
979230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x00000080);
980230557Sjimharris      // DFE1-5 = small
981230557Sjimharris      scu_afe_register_write(
982230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x01041042);
983230557Sjimharris      // Enable DFE/FFE and freeze
984230557Sjimharris      scu_afe_register_write(
985230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x320891bf);
986230557Sjimharris      #endif
987230557Sjimharris      // Take receiver out of power down and wait 200ns
988230557Sjimharris      scu_afe_register_write(
989230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006118);
990230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
991230557Sjimharris      // TX Electrical Idle
992230557Sjimharris      scu_afe_register_write(
993230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006108);
994230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
995230557Sjimharris
996230557Sjimharris      // Leave DFE/FFE on
997230557Sjimharris      scu_afe_register_write(
998230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x0317108f);
999230557Sjimharris
1000230557Sjimharris      // Configure receiver parameters
1001230557Sjimharris      scu_afe_register_write(
1002230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01e00021);
1003230557Sjimharris
1004230557Sjimharris      // Bring RX out of reset
1005230557Sjimharris      scu_afe_register_write(
1006230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006109);
1007230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1008230557Sjimharris
1009230557Sjimharris      scu_afe_register_write(
1010230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006009);
1011230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1012230557Sjimharris
1013230557Sjimharris      scu_afe_register_write(
1014230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006209);
1015230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1016230557Sjimharris   }
1017230557Sjimharris
1018230557Sjimharris   // Transfer control to the PEs
1019230557Sjimharris   scu_afe_register_write(
1020230557Sjimharris      this_controller, afe_dfx_master_control0, 0x00010f00);
1021230557Sjimharris#endif
1022230557Sjimharris}
1023230557Sjimharris
1024230557Sjimharris#elif defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
1025230557Sjimharris
1026230557Sjimharrisvoid scic_sds_controller_afe_initialization(
1027230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1028230557Sjimharris)
1029230557Sjimharris{
1030230557Sjimharris   U32  afe_status;
1031230557Sjimharris   U32  phy_id;
1032230557Sjimharris   U8   cable_selection_mask;
1033230557Sjimharris
1034230557Sjimharris   if (
1035230557Sjimharris         (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_A0)
1036230557Sjimharris      && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_A2)
1037230557Sjimharris      && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_B0)
1038230557Sjimharris      && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_C0)
1039230557Sjimharris      && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_C1)
1040230557Sjimharris      )
1041230557Sjimharris   {
1042230557Sjimharris      // A programming bug has occurred if we are attempting to
1043230557Sjimharris      // support a PCI revision other than those listed.  Default
1044230557Sjimharris      // to B0, and attempt to limp along if it isn't B0.
1045230557Sjimharris      ASSERT(FALSE);
1046230557Sjimharris      this_controller->pci_revision = SCIC_SDS_PCI_REVISION_C1;
1047230557Sjimharris   }
1048230557Sjimharris
1049230557Sjimharris   cable_selection_mask =
1050230557Sjimharris      this_controller->oem_parameters.sds1.controller.cable_selection_mask;
1051230557Sjimharris
1052230557Sjimharris   // These are the AFEE settings used by the SV group
1053230557Sjimharris   // Clear DFX Status registers
1054230557Sjimharris   scu_afe_register_write(
1055230557Sjimharris      this_controller, afe_dfx_master_control0, 0x0081000f);
1056230557Sjimharris   scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1057230557Sjimharris
1058230557Sjimharris   if (
1059230557Sjimharris         (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1060230557Sjimharris      || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1061230557Sjimharris      || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1062230557Sjimharris      )
1063230557Sjimharris   {
1064230557Sjimharris      // PM Rx Equalization Save, PM SPhy Rx Acknowledgement Timer, PM Stagger Timer
1065230557Sjimharris      scu_afe_register_write(
1066230557Sjimharris         this_controller, afe_pmsn_master_control2, 0x0007FFFF);
1067230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1068230557Sjimharris   }
1069230557Sjimharris
1070230557Sjimharris   // Configure bias currents to normal
1071230557Sjimharris   if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1072230557Sjimharris      scu_afe_register_write(this_controller, afe_bias_control, 0x00005500);
1073230557Sjimharris   else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1074230557Sjimharris      scu_afe_register_write(this_controller, afe_bias_control, 0x00005A00);
1075230557Sjimharris   else if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1076230557Sjimharris           || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) )
1077230557Sjimharris      scu_afe_register_write(this_controller, afe_bias_control, 0x00005F00);
1078230557Sjimharris   else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1079230557Sjimharris      scu_afe_register_write(this_controller, afe_bias_control, 0x00005500);
1080230557Sjimharris   // For C0 the AFE BIAS Controll is unchanged
1081230557Sjimharris
1082230557Sjimharris   scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1083230557Sjimharris
1084230557Sjimharris      // Enable PLL
1085230557Sjimharris   if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1086230557Sjimharris      || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1087230557Sjimharris   {
1088230557Sjimharris      scu_afe_register_write(this_controller, afe_pll_control0, 0x80040908);
1089230557Sjimharris   }
1090230557Sjimharris   else if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1091230557Sjimharris           || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) )
1092230557Sjimharris   {
1093230557Sjimharris      scu_afe_register_write(this_controller, afe_pll_control0, 0x80040A08);
1094230557Sjimharris   }
1095230557Sjimharris   else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1096230557Sjimharris   {
1097230557Sjimharris      scu_afe_register_write(this_controller, afe_pll_control0, 0x80000b08);
1098230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1099230557Sjimharris      scu_afe_register_write(this_controller, afe_pll_control0, 0x00000b08);
1100230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1101230557Sjimharris      scu_afe_register_write(this_controller, afe_pll_control0, 0x80000b08);
1102230557Sjimharris   }
1103230557Sjimharris
1104230557Sjimharris   scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1105230557Sjimharris
1106230557Sjimharris   // Wait for the PLL to lock
1107230557Sjimharris   // Note: this is done later in the SV shell script however this looks
1108230557Sjimharris   //       like the location to do this since we have enabled the PLL.
1109230557Sjimharris   do
1110230557Sjimharris   {
1111230557Sjimharris      afe_status = scu_afe_register_read(
1112230557Sjimharris                      this_controller, afe_common_block_status);
1113230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1114230557Sjimharris   }
1115230557Sjimharris   while((afe_status & 0x00001000) == 0);
1116230557Sjimharris
1117230557Sjimharris   if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1118230557Sjimharris      || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1119230557Sjimharris   {
1120230557Sjimharris      // Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us)
1121230557Sjimharris      scu_afe_register_write(
1122230557Sjimharris         this_controller, afe_pmsn_master_control0, 0x7bcc96ad);
1123230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1124230557Sjimharris   }
1125230557Sjimharris
1126230557Sjimharris   for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
1127230557Sjimharris   {
1128230557Sjimharris      U8 cable_length_long   = (cable_selection_mask >> phy_id) & 1;
1129230557Sjimharris      U8 cable_length_medium = (cable_selection_mask >> (phy_id + 4)) & 1;
1130230557Sjimharris
1131230557Sjimharris      if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1132230557Sjimharris         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1133230557Sjimharris      {
1134230557Sjimharris         // All defaults, except the Receive Word Alignament/Comma Detect
1135230557Sjimharris         // Enable....(0xe800)
1136230557Sjimharris         scu_afe_register_write(
1137230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00004512
1138230557Sjimharris         );
1139230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1140230557Sjimharris
1141230557Sjimharris         scu_afe_register_write(
1142230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x0050100F
1143230557Sjimharris         );
1144230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1145230557Sjimharris      }
1146230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1147230557Sjimharris      {
1148230557Sjimharris         // Configure transmitter SSC parameters
1149230557Sjimharris         scu_afe_register_write(
1150230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00030000
1151230557Sjimharris         );
1152230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1153230557Sjimharris      }
1154230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1155230557Sjimharris      {
1156230557Sjimharris         // Configure transmitter SSC parameters
1157230557Sjimharris         scu_afe_register_write(
1158230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00010202
1159230557Sjimharris         );
1160230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1161230557Sjimharris
1162230557Sjimharris         // All defaults, except the Receive Word Alignament/Comma Detect
1163230557Sjimharris         // Enable....(0xe800)
1164230557Sjimharris         scu_afe_register_write(
1165230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00014500
1166230557Sjimharris         );
1167230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1168230557Sjimharris      }
1169230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1170230557Sjimharris      {
1171230557Sjimharris         // Configure transmitter SSC parameters
1172230557Sjimharris         scu_afe_register_write(
1173230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00010202
1174230557Sjimharris         );
1175230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1176230557Sjimharris
1177230557Sjimharris         // All defaults, except the Receive Word Alignament/Comma Detect
1178230557Sjimharris         // Enable....(0xe800)
1179230557Sjimharris         scu_afe_register_write(
1180230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0001C500
1181230557Sjimharris         );
1182230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1183230557Sjimharris      }
1184230557Sjimharris      // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1185230557Sjimharris      // & increase TX int & ext bias 20%....(0xe85c)
1186230557Sjimharris      if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1187230557Sjimharris      {
1188230557Sjimharris         scu_afe_register_write(
1189230557Sjimharris            this_controller,
1190230557Sjimharris            scu_afe_xcvr[phy_id].afe_channel_control,
1191230557Sjimharris            0x000003D4
1192230557Sjimharris         );
1193230557Sjimharris      }
1194230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1195230557Sjimharris      {
1196230557Sjimharris         scu_afe_register_write(
1197230557Sjimharris            this_controller,
1198230557Sjimharris            scu_afe_xcvr[phy_id].afe_channel_control,
1199230557Sjimharris            0x000003F0
1200230557Sjimharris         );
1201230557Sjimharris      }
1202230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1203230557Sjimharris      {
1204230557Sjimharris         // Power down TX and RX (PWRDNTX and PWRDNRX)
1205230557Sjimharris         scu_afe_register_write(
1206230557Sjimharris            this_controller,
1207230557Sjimharris            scu_afe_xcvr[phy_id].afe_channel_control,
1208230557Sjimharris            0x000003d7
1209230557Sjimharris         );
1210230557Sjimharris
1211230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1212230557Sjimharris
1213230557Sjimharris         // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1214230557Sjimharris         // & increase TX int & ext bias 20%....(0xe85c)
1215230557Sjimharris         scu_afe_register_write(
1216230557Sjimharris            this_controller,
1217230557Sjimharris            scu_afe_xcvr[phy_id].afe_channel_control,
1218230557Sjimharris            0x000003d4
1219230557Sjimharris         );
1220230557Sjimharris      }
1221230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1222230557Sjimharris      {
1223230557Sjimharris         scu_afe_register_write(
1224230557Sjimharris            this_controller,
1225230557Sjimharris            scu_afe_xcvr[phy_id].afe_channel_control,
1226230557Sjimharris            0x000001e7
1227230557Sjimharris         );
1228230557Sjimharris
1229230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1230230557Sjimharris
1231230557Sjimharris         // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1232230557Sjimharris         // & increase TX int & ext bias 20%....(0xe85c)
1233230557Sjimharris         scu_afe_register_write(
1234230557Sjimharris            this_controller,
1235230557Sjimharris            scu_afe_xcvr[phy_id].afe_channel_control,
1236230557Sjimharris            0x000001e4
1237230557Sjimharris         );
1238230557Sjimharris      }
1239230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1240230557Sjimharris      {
1241230557Sjimharris         scu_afe_register_write(
1242230557Sjimharris            this_controller,
1243230557Sjimharris            scu_afe_xcvr[phy_id].afe_channel_control,
1244230557Sjimharris            cable_length_long   ? 0x000002F7 :
1245230557Sjimharris            cable_length_medium ? 0x000001F7 : 0x000001F7
1246230557Sjimharris         );
1247230557Sjimharris
1248230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1249230557Sjimharris
1250230557Sjimharris         // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1251230557Sjimharris         // & increase TX int & ext bias 20%....(0xe85c)
1252230557Sjimharris         scu_afe_register_write(
1253230557Sjimharris            this_controller,
1254230557Sjimharris            scu_afe_xcvr[phy_id].afe_channel_control,
1255230557Sjimharris            cable_length_long   ? 0x000002F4 :
1256230557Sjimharris            cable_length_medium ? 0x000001F4 : 0x000001F4
1257230557Sjimharris         );
1258230557Sjimharris      }
1259230557Sjimharris
1260230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1261230557Sjimharris
1262230557Sjimharris      if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1263230557Sjimharris         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1264230557Sjimharris      {
1265230557Sjimharris         // Enable TX equalization (0xe824)
1266230557Sjimharris         scu_afe_register_write(
1267230557Sjimharris            this_controller,
1268230557Sjimharris            scu_afe_xcvr[phy_id].afe_tx_control,
1269230557Sjimharris            0x00040000
1270230557Sjimharris         );
1271230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1272230557Sjimharris      }
1273230557Sjimharris
1274230557Sjimharris      if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1275230557Sjimharris         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1276230557Sjimharris         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0) )
1277230557Sjimharris      {
1278230557Sjimharris         // RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
1279230557Sjimharris         // RDD=0x0(RX Detect Enabled) ....(0xe800)
1280230557Sjimharris         scu_afe_register_write(
1281230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00004100);
1282230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1283230557Sjimharris      }
1284230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1285230557Sjimharris      {
1286230557Sjimharris         scu_afe_register_write(
1287230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00014100);
1288230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1289230557Sjimharris      }
1290230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1291230557Sjimharris      {
1292230557Sjimharris         scu_afe_register_write(
1293230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0001c100);
1294230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1295230557Sjimharris      }
1296230557Sjimharris
1297230557Sjimharris      // Leave DFE/FFE on
1298230557Sjimharris      if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1299230557Sjimharris      {
1300230557Sjimharris         scu_afe_register_write(
1301230557Sjimharris            this_controller,
1302230557Sjimharris            scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1303230557Sjimharris            0x3F09983F
1304230557Sjimharris         );
1305230557Sjimharris      }
1306230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1307230557Sjimharris      {
1308230557Sjimharris         scu_afe_register_write(
1309230557Sjimharris            this_controller,
1310230557Sjimharris            scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1311230557Sjimharris            0x3F11103F
1312230557Sjimharris         );
1313230557Sjimharris      }
1314230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1315230557Sjimharris      {
1316230557Sjimharris         scu_afe_register_write(
1317230557Sjimharris            this_controller,
1318230557Sjimharris            scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1319230557Sjimharris            0x3F11103F
1320230557Sjimharris         );
1321230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1322230557Sjimharris
1323230557Sjimharris         // Enable TX equalization (0xe824)
1324230557Sjimharris         scu_afe_register_write(
1325230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
1326230557Sjimharris      }
1327230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1328230557Sjimharris      {
1329230557Sjimharris         scu_afe_register_write(
1330230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01400c0f);
1331230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1332230557Sjimharris
1333230557Sjimharris         scu_afe_register_write(
1334230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x3f6f103f);
1335230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1336230557Sjimharris
1337230557Sjimharris         // Enable TX equalization (0xe824)
1338230557Sjimharris         scu_afe_register_write(
1339230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
1340230557Sjimharris      }
1341230557Sjimharris      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1342230557Sjimharris      {
1343230557Sjimharris         scu_afe_register_write(
1344230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1,
1345230557Sjimharris            cable_length_long   ? 0x01500C0C :
1346230557Sjimharris            cable_length_medium ? 0x01400C0D : 0x02400C0D
1347230557Sjimharris         );
1348230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1349230557Sjimharris
1350230557Sjimharris         scu_afe_register_write(
1351230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x000003e0);
1352230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1353230557Sjimharris
1354230557Sjimharris         scu_afe_register_write(
1355230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1356230557Sjimharris            cable_length_long   ? 0x33091C1F :
1357230557Sjimharris            cable_length_medium ? 0x3315181F : 0x2B17161F
1358230557Sjimharris         );
1359230557Sjimharris         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1360230557Sjimharris
1361230557Sjimharris         // Enable TX equalization (0xe824)
1362230557Sjimharris         scu_afe_register_write(
1363230557Sjimharris            this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
1364230557Sjimharris      }
1365230557Sjimharris
1366230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1367230557Sjimharris
1368230557Sjimharris      scu_afe_register_write(
1369230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0,
1370230557Sjimharris         this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control0
1371230557Sjimharris      );
1372230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1373230557Sjimharris
1374230557Sjimharris      scu_afe_register_write(
1375230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1,
1376230557Sjimharris         this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control1
1377230557Sjimharris      );
1378230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1379230557Sjimharris
1380230557Sjimharris      scu_afe_register_write(
1381230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2,
1382230557Sjimharris         this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control2
1383230557Sjimharris      );
1384230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1385230557Sjimharris
1386230557Sjimharris      scu_afe_register_write(
1387230557Sjimharris         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3,
1388230557Sjimharris         this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control3
1389230557Sjimharris      );
1390230557Sjimharris      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1391230557Sjimharris   }
1392230557Sjimharris
1393230557Sjimharris   // Transfer control to the PEs
1394230557Sjimharris   scu_afe_register_write(
1395230557Sjimharris      this_controller, afe_dfx_master_control0, 0x00010f00);
1396230557Sjimharris   scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1397230557Sjimharris}
1398230557Sjimharris#else
1399230557Sjimharris   #error "Unsupported board type"
1400230557Sjimharris#endif
1401230557Sjimharris
1402230557Sjimharris//****************************************************************************-
1403230557Sjimharris//* SCIC SDS Controller Internal Start/Stop Routines
1404230557Sjimharris//****************************************************************************-
1405230557Sjimharris
1406230557Sjimharris
1407230557Sjimharris/**
1408230557Sjimharris * @brief This method will attempt to transition into the ready state
1409230557Sjimharris *        for the controller and indicate that the controller start
1410230557Sjimharris *        operation has completed if all criteria are met.
1411230557Sjimharris *
1412230557Sjimharris * @param[in,out] this_controller This parameter indicates the controller
1413230557Sjimharris *                object for which to transition to ready.
1414230557Sjimharris * @param[in]     status This parameter indicates the status value to be
1415230557Sjimharris *                pass into the call to scic_cb_controller_start_complete().
1416230557Sjimharris *
1417230557Sjimharris * @return none.
1418230557Sjimharris */
1419230557Sjimharrisstatic
1420230557Sjimharrisvoid scic_sds_controller_transition_to_ready(
1421230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
1422230557Sjimharris   SCI_STATUS             status
1423230557Sjimharris)
1424230557Sjimharris{
1425230557Sjimharris   SCIC_LOG_TRACE((
1426230557Sjimharris      sci_base_object_get_logger(this_controller),
1427230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
1428230557Sjimharris      "scic_sds_controller_transition_to_ready(0x%x, 0x%x) enter\n",
1429230557Sjimharris      this_controller, status
1430230557Sjimharris   ));
1431230557Sjimharris
1432230557Sjimharris   if (this_controller->parent.state_machine.current_state_id
1433230557Sjimharris       == SCI_BASE_CONTROLLER_STATE_STARTING)
1434230557Sjimharris   {
1435230557Sjimharris      // We move into the ready state, because some of the phys/ports
1436230557Sjimharris      // may be up and operational.
1437230557Sjimharris      sci_base_state_machine_change_state(
1438230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller),
1439230557Sjimharris         SCI_BASE_CONTROLLER_STATE_READY
1440230557Sjimharris      );
1441230557Sjimharris
1442230557Sjimharris      scic_cb_controller_start_complete(this_controller, status);
1443230557Sjimharris   }
1444230557Sjimharris}
1445230557Sjimharris
1446230557Sjimharris/**
1447230557Sjimharris * @brief This method is the general timeout handler for the controller.
1448230557Sjimharris *        It will take the correct timetout action based on the current
1449230557Sjimharris *        controller state
1450230557Sjimharris *
1451230557Sjimharris * @param[in] controller This parameter indicates the controller on which
1452230557Sjimharris *            a timeout occurred.
1453230557Sjimharris *
1454230557Sjimharris * @return none
1455230557Sjimharris */
1456230557Sjimharrisvoid scic_sds_controller_timeout_handler(
1457230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
1458230557Sjimharris)
1459230557Sjimharris{
1460230557Sjimharris   SCI_BASE_CONTROLLER_STATES current_state;
1461230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
1462230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
1463230557Sjimharris
1464230557Sjimharris   current_state = sci_base_state_machine_get_state(
1465230557Sjimharris                      scic_sds_controller_get_base_state_machine(this_controller)
1466230557Sjimharris                   );
1467230557Sjimharris
1468230557Sjimharris   if (current_state == SCI_BASE_CONTROLLER_STATE_STARTING)
1469230557Sjimharris   {
1470230557Sjimharris      scic_sds_controller_transition_to_ready(
1471230557Sjimharris         this_controller, SCI_FAILURE_TIMEOUT
1472230557Sjimharris      );
1473230557Sjimharris   }
1474230557Sjimharris   else if (current_state == SCI_BASE_CONTROLLER_STATE_STOPPING)
1475230557Sjimharris   {
1476230557Sjimharris      sci_base_state_machine_change_state(
1477230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller),
1478230557Sjimharris         SCI_BASE_CONTROLLER_STATE_FAILED
1479230557Sjimharris      );
1480230557Sjimharris
1481230557Sjimharris      scic_cb_controller_stop_complete(controller, SCI_FAILURE_TIMEOUT);
1482230557Sjimharris   }
1483230557Sjimharris   else
1484230557Sjimharris   {
1485230557Sjimharris      /// @todo Now what do we want to do in this case?
1486230557Sjimharris      SCIC_LOG_ERROR((
1487230557Sjimharris         sci_base_object_get_logger(this_controller),
1488230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
1489230557Sjimharris         "Controller timer fired when controller was not in a state being timed.\n"
1490230557Sjimharris      ));
1491230557Sjimharris   }
1492230557Sjimharris}
1493230557Sjimharris
1494230557Sjimharris/**
1495230557Sjimharris * @brief
1496230557Sjimharris *
1497230557Sjimharris * @param[in] this_controller
1498230557Sjimharris *
1499230557Sjimharris * @return SCI_STATUS
1500230557Sjimharris */
1501230557SjimharrisSCI_STATUS scic_sds_controller_stop_ports(
1502230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1503230557Sjimharris)
1504230557Sjimharris{
1505230557Sjimharris   U32        index;
1506230557Sjimharris   SCI_STATUS status;
1507230557Sjimharris   SCI_STATUS port_status;
1508230557Sjimharris
1509230557Sjimharris   status = SCI_SUCCESS;
1510230557Sjimharris
1511230557Sjimharris   for (index = 0; index < this_controller->logical_port_entries; index++)
1512230557Sjimharris   {
1513230557Sjimharris      port_status = this_controller->port_table[index].
1514230557Sjimharris         state_handlers->parent.stop_handler(&this_controller->port_table[index].parent);
1515230557Sjimharris      if (
1516230557Sjimharris            (port_status != SCI_SUCCESS)
1517230557Sjimharris         && (port_status != SCI_FAILURE_INVALID_STATE)
1518230557Sjimharris         )
1519230557Sjimharris      {
1520230557Sjimharris         status = SCI_FAILURE;
1521230557Sjimharris
1522230557Sjimharris         SCIC_LOG_WARNING((
1523230557Sjimharris            sci_base_object_get_logger(this_controller),
1524230557Sjimharris            SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
1525230557Sjimharris            "Controller stop operation failed to stop port %d because of status %d.\n",
1526230557Sjimharris            this_controller->port_table[index].logical_port_index, port_status
1527230557Sjimharris         ));
1528230557Sjimharris      }
1529230557Sjimharris   }
1530230557Sjimharris
1531230557Sjimharris   return status;
1532230557Sjimharris}
1533230557Sjimharris
1534230557Sjimharris/**
1535230557Sjimharris * @brief
1536230557Sjimharris *
1537230557Sjimharris * @param[in] this_controller
1538230557Sjimharris */
1539230557Sjimharrisstatic
1540230557Sjimharrisvoid scic_sds_controller_phy_timer_start(
1541230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1542230557Sjimharris)
1543230557Sjimharris{
1544230557Sjimharris   scic_cb_timer_start(
1545230557Sjimharris      this_controller,
1546230557Sjimharris      this_controller->phy_startup_timer,
1547230557Sjimharris      SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
1548230557Sjimharris   );
1549230557Sjimharris
1550230557Sjimharris   this_controller->phy_startup_timer_pending = TRUE;
1551230557Sjimharris}
1552230557Sjimharris
1553230557Sjimharris/**
1554230557Sjimharris * @brief
1555230557Sjimharris *
1556230557Sjimharris * @param[in] this_controller
1557230557Sjimharris */
1558230557Sjimharrisvoid scic_sds_controller_phy_timer_stop(
1559230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1560230557Sjimharris)
1561230557Sjimharris{
1562230557Sjimharris   scic_cb_timer_stop(
1563230557Sjimharris      this_controller,
1564230557Sjimharris      this_controller->phy_startup_timer
1565230557Sjimharris   );
1566230557Sjimharris
1567230557Sjimharris   this_controller->phy_startup_timer_pending = FALSE;
1568230557Sjimharris}
1569230557Sjimharris
1570230557Sjimharris/**
1571230557Sjimharris * @brief This method is called internally to determine whether the
1572230557Sjimharris *        controller start process is complete.  This is only true when:
1573230557Sjimharris *          - all links have been given an opportunity to start
1574230557Sjimharris *          - have no indication of a connected device
1575230557Sjimharris *          - have an indication of a connected device and it has
1576230557Sjimharris *             finished the link training process.
1577230557Sjimharris *
1578230557Sjimharris * @param[in] this_controller This parameter specifies the controller
1579230557Sjimharris *            object for which to start the next phy.
1580230557Sjimharris *
1581230557Sjimharris * @return BOOL
1582230557Sjimharris */
1583230557SjimharrisBOOL scic_sds_controller_is_start_complete(
1584230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1585230557Sjimharris)
1586230557Sjimharris{
1587230557Sjimharris   U8 index;
1588230557Sjimharris
1589230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
1590230557Sjimharris   {
1591230557Sjimharris      SCIC_SDS_PHY_T *the_phy = & this_controller->phy_table[index];
1592230557Sjimharris
1593230557Sjimharris      if (
1594230557Sjimharris            (
1595230557Sjimharris                  this_controller->oem_parameters.sds1.controller.mode_type
1596230557Sjimharris               == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
1597230557Sjimharris            )
1598230557Sjimharris         || (
1599230557Sjimharris               (
1600230557Sjimharris                  this_controller->oem_parameters.sds1.controller.mode_type
1601230557Sjimharris               == SCIC_PORT_MANUAL_CONFIGURATION_MODE
1602230557Sjimharris               )
1603230557Sjimharris            && (scic_sds_phy_get_port(the_phy) != SCI_INVALID_HANDLE)
1604230557Sjimharris            )
1605230557Sjimharris         )
1606230557Sjimharris      {
1607230557Sjimharris         /**
1608230557Sjimharris          * The controller start operation is complete if and only
1609230557Sjimharris          * if:
1610230557Sjimharris          * - all links have been given an opportunity to start
1611230557Sjimharris          * - have no indication of a connected device
1612230557Sjimharris          * - have an indication of a connected device and it has
1613230557Sjimharris          *   finished the link training process.
1614230557Sjimharris          */
1615230557Sjimharris        if (
1616230557Sjimharris               (
1617230557Sjimharris                  (the_phy->is_in_link_training == FALSE)
1618230557Sjimharris               && (the_phy->parent.state_machine.current_state_id
1619230557Sjimharris                   == SCI_BASE_PHY_STATE_INITIAL)
1620230557Sjimharris               )
1621230557Sjimharris            || (
1622230557Sjimharris                  (the_phy->is_in_link_training == FALSE)
1623230557Sjimharris               && (the_phy->parent.state_machine.current_state_id
1624230557Sjimharris                   == SCI_BASE_PHY_STATE_STOPPED)
1625230557Sjimharris               )
1626230557Sjimharris            || (
1627230557Sjimharris                  (the_phy->is_in_link_training == TRUE)
1628230557Sjimharris               && (the_phy->parent.state_machine.current_state_id
1629230557Sjimharris                   == SCI_BASE_PHY_STATE_STARTING)
1630230557Sjimharris               )
1631230557Sjimharris            || (
1632230557Sjimharris                  this_controller->port_agent.phy_ready_mask
1633230557Sjimharris                  != this_controller->port_agent.phy_configured_mask
1634230557Sjimharris               )
1635230557Sjimharris            )
1636230557Sjimharris         {
1637230557Sjimharris            return FALSE;
1638230557Sjimharris         }
1639230557Sjimharris      }
1640230557Sjimharris   }
1641230557Sjimharris
1642230557Sjimharris   return TRUE;
1643230557Sjimharris}
1644230557Sjimharris
1645230557Sjimharris/**
1646230557Sjimharris * @brief This method is called internally by the controller object to
1647230557Sjimharris *        start the next phy on the controller.  If all the phys have
1648230557Sjimharris *        been starte, then this method will attempt to transition the
1649230557Sjimharris *        controller to the READY state and inform the user
1650230557Sjimharris *        (scic_cb_controller_start_complete()).
1651230557Sjimharris *
1652230557Sjimharris * @param[in] this_controller This parameter specifies the controller
1653230557Sjimharris *            object for which to start the next phy.
1654230557Sjimharris *
1655230557Sjimharris * @return SCI_STATUS
1656230557Sjimharris */
1657230557SjimharrisSCI_STATUS scic_sds_controller_start_next_phy(
1658230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1659230557Sjimharris)
1660230557Sjimharris{
1661230557Sjimharris   SCI_STATUS status;
1662230557Sjimharris
1663230557Sjimharris   status = SCI_SUCCESS;
1664230557Sjimharris
1665230557Sjimharris   if (this_controller->phy_startup_timer_pending == FALSE)
1666230557Sjimharris   {
1667230557Sjimharris      if (this_controller->next_phy_to_start == SCI_MAX_PHYS)
1668230557Sjimharris      {
1669230557Sjimharris         // The controller has successfully finished the start process.
1670230557Sjimharris         // Inform the SCI Core user and transition to the READY state.
1671230557Sjimharris         if (scic_sds_controller_is_start_complete(this_controller) == TRUE)
1672230557Sjimharris         {
1673230557Sjimharris            scic_sds_controller_transition_to_ready(
1674230557Sjimharris               this_controller, SCI_SUCCESS
1675230557Sjimharris            );
1676230557Sjimharris         }
1677230557Sjimharris      }
1678230557Sjimharris      else
1679230557Sjimharris      {
1680230557Sjimharris         SCIC_SDS_PHY_T * the_phy;
1681230557Sjimharris
1682230557Sjimharris         the_phy = &this_controller->phy_table[this_controller->next_phy_to_start];
1683230557Sjimharris
1684230557Sjimharris         if (
1685230557Sjimharris               this_controller->oem_parameters.sds1.controller.mode_type
1686230557Sjimharris            == SCIC_PORT_MANUAL_CONFIGURATION_MODE
1687230557Sjimharris            )
1688230557Sjimharris         {
1689230557Sjimharris            if (scic_sds_phy_get_port(the_phy) == SCI_INVALID_HANDLE)
1690230557Sjimharris            {
1691230557Sjimharris               this_controller->next_phy_to_start++;
1692230557Sjimharris
1693230557Sjimharris               // Caution recursion ahead be forwarned
1694230557Sjimharris               //
1695230557Sjimharris               // The PHY was never added to a PORT in MPC mode so start the next phy in sequence
1696230557Sjimharris               // This phy will never go link up and will not draw power the OEM parameters either
1697230557Sjimharris               // configured the phy incorrectly for the PORT or it was never assigned to a PORT
1698230557Sjimharris               return scic_sds_controller_start_next_phy(this_controller);
1699230557Sjimharris            }
1700230557Sjimharris         }
1701230557Sjimharris
1702230557Sjimharris         status = scic_phy_start(the_phy);
1703230557Sjimharris
1704230557Sjimharris         if (status == SCI_SUCCESS)
1705230557Sjimharris         {
1706230557Sjimharris            scic_sds_controller_phy_timer_start(this_controller);
1707230557Sjimharris         }
1708230557Sjimharris         else
1709230557Sjimharris         {
1710230557Sjimharris            SCIC_LOG_WARNING((
1711230557Sjimharris               sci_base_object_get_logger(this_controller),
1712230557Sjimharris               SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PHY,
1713230557Sjimharris               "Controller stop operation failed to stop phy %d because of status %d.\n",
1714230557Sjimharris               this_controller->phy_table[this_controller->next_phy_to_start].phy_index,
1715230557Sjimharris               status
1716230557Sjimharris            ));
1717230557Sjimharris         }
1718230557Sjimharris
1719230557Sjimharris         this_controller->next_phy_to_start++;
1720230557Sjimharris      }
1721230557Sjimharris   }
1722230557Sjimharris
1723230557Sjimharris   return status;
1724230557Sjimharris}
1725230557Sjimharris
1726230557Sjimharris/**
1727230557Sjimharris * @brief
1728230557Sjimharris *
1729230557Sjimharris * @param[in] this_controller
1730230557Sjimharris *
1731230557Sjimharris * @return SCI_STATUS
1732230557Sjimharris */
1733230557SjimharrisSCI_STATUS scic_sds_controller_stop_phys(
1734230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1735230557Sjimharris)
1736230557Sjimharris{
1737230557Sjimharris   U32        index;
1738230557Sjimharris   SCI_STATUS status;
1739230557Sjimharris   SCI_STATUS phy_status;
1740230557Sjimharris
1741230557Sjimharris   status = SCI_SUCCESS;
1742230557Sjimharris
1743230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
1744230557Sjimharris   {
1745230557Sjimharris      phy_status = scic_phy_stop(&this_controller->phy_table[index]);
1746230557Sjimharris
1747230557Sjimharris      if (
1748230557Sjimharris              (phy_status != SCI_SUCCESS)
1749230557Sjimharris           && (phy_status != SCI_FAILURE_INVALID_STATE)
1750230557Sjimharris         )
1751230557Sjimharris      {
1752230557Sjimharris         status = SCI_FAILURE;
1753230557Sjimharris
1754230557Sjimharris         SCIC_LOG_WARNING((
1755230557Sjimharris            sci_base_object_get_logger(this_controller),
1756230557Sjimharris            SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PHY,
1757230557Sjimharris            "Controller stop operation failed to stop phy %d because of status %d.\n",
1758230557Sjimharris            this_controller->phy_table[index].phy_index, phy_status
1759230557Sjimharris         ));
1760230557Sjimharris      }
1761230557Sjimharris   }
1762230557Sjimharris
1763230557Sjimharris   return status;
1764230557Sjimharris}
1765230557Sjimharris
1766230557Sjimharris/**
1767230557Sjimharris * @brief
1768230557Sjimharris *
1769230557Sjimharris * @param[in] this_controller
1770230557Sjimharris *
1771230557Sjimharris * @return SCI_STATUS
1772230557Sjimharris */
1773230557SjimharrisSCI_STATUS scic_sds_controller_stop_devices(
1774230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1775230557Sjimharris)
1776230557Sjimharris{
1777230557Sjimharris   U32        index;
1778230557Sjimharris   SCI_STATUS status;
1779230557Sjimharris   SCI_STATUS device_status;
1780230557Sjimharris
1781230557Sjimharris   status = SCI_SUCCESS;
1782230557Sjimharris
1783230557Sjimharris   for (index = 0; index < this_controller->remote_node_entries; index++)
1784230557Sjimharris   {
1785230557Sjimharris      if (this_controller->device_table[index] != SCI_INVALID_HANDLE)
1786230557Sjimharris      {
1787230557Sjimharris         /// @todo What timeout value do we want to provide to this request?
1788230557Sjimharris         device_status = scic_remote_device_stop(this_controller->device_table[index], 0);
1789230557Sjimharris
1790230557Sjimharris         if (
1791230557Sjimharris                 (device_status != SCI_SUCCESS)
1792230557Sjimharris              && (device_status != SCI_FAILURE_INVALID_STATE)
1793230557Sjimharris            )
1794230557Sjimharris         {
1795230557Sjimharris            SCIC_LOG_WARNING((
1796230557Sjimharris               sci_base_object_get_logger(this_controller),
1797230557Sjimharris               SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_SSP_REMOTE_TARGET,
1798230557Sjimharris               "Controller stop operation failed to stop device 0x%x because of status %d.\n",
1799230557Sjimharris               this_controller->device_table[index], device_status
1800230557Sjimharris            ));
1801230557Sjimharris         }
1802230557Sjimharris      }
1803230557Sjimharris   }
1804230557Sjimharris
1805230557Sjimharris   return status;
1806230557Sjimharris}
1807230557Sjimharris
1808230557Sjimharris//****************************************************************************-
1809230557Sjimharris//* SCIC SDS Controller Power Control (Staggered Spinup)
1810230557Sjimharris//****************************************************************************-
1811230557Sjimharris
1812230557Sjimharris/**
1813230557Sjimharris * This method starts the power control timer for this controller object.
1814230557Sjimharris *
1815230557Sjimharris * @param this_controller
1816230557Sjimharris */
1817230557Sjimharrisstatic
1818230557Sjimharrisvoid scic_sds_controller_power_control_timer_start(
1819230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1820230557Sjimharris)
1821230557Sjimharris{
1822230557Sjimharris   scic_cb_timer_start(
1823230557Sjimharris      this_controller, this_controller->power_control.timer,
1824230557Sjimharris      SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL
1825230557Sjimharris   );
1826230557Sjimharris
1827230557Sjimharris   this_controller->power_control.timer_started = TRUE;
1828230557Sjimharris}
1829230557Sjimharris
1830230557Sjimharris/**
1831230557Sjimharris * This method stops the power control timer for this controller object.
1832230557Sjimharris *
1833230557Sjimharris * @param this_controller
1834230557Sjimharris */
1835230557Sjimharrisstatic
1836230557Sjimharrisvoid scic_sds_controller_power_control_timer_stop(
1837230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1838230557Sjimharris)
1839230557Sjimharris{
1840230557Sjimharris   if (this_controller->power_control.timer_started)
1841230557Sjimharris   {
1842230557Sjimharris      scic_cb_timer_stop(
1843230557Sjimharris         this_controller, this_controller->power_control.timer
1844230557Sjimharris      );
1845230557Sjimharris
1846230557Sjimharris      this_controller->power_control.timer_started = FALSE;
1847230557Sjimharris   }
1848230557Sjimharris}
1849230557Sjimharris
1850230557Sjimharris/**
1851230557Sjimharris * This method stops and starts the power control timer for this controller object.
1852230557Sjimharris *
1853230557Sjimharris * @param this_controller
1854230557Sjimharris */
1855230557Sjimharrisstatic
1856230557Sjimharrisvoid scic_sds_controller_power_control_timer_restart(
1857230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
1858230557Sjimharris)
1859230557Sjimharris{
1860230557Sjimharris   scic_sds_controller_power_control_timer_stop(this_controller);
1861230557Sjimharris   scic_sds_controller_power_control_timer_start(this_controller);
1862230557Sjimharris}
1863230557Sjimharris
1864230557Sjimharris
1865230557Sjimharris/**
1866230557Sjimharris * @brief
1867230557Sjimharris *
1868230557Sjimharris * @param[in] controller
1869230557Sjimharris */
1870230557Sjimharrisvoid scic_sds_controller_power_control_timer_handler(
1871230557Sjimharris   void *controller
1872230557Sjimharris)
1873230557Sjimharris{
1874230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
1875230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
1876230557Sjimharris
1877230557Sjimharris   this_controller->power_control.remote_devices_granted_power = 0;
1878230557Sjimharris
1879230557Sjimharris   if (this_controller->power_control.phys_waiting == 0)
1880230557Sjimharris   {
1881230557Sjimharris      this_controller->power_control.timer_started = FALSE;
1882230557Sjimharris   }
1883230557Sjimharris   else
1884230557Sjimharris   {
1885230557Sjimharris      SCIC_SDS_PHY_T *the_phy = NULL;
1886230557Sjimharris      U8 i;
1887230557Sjimharris
1888230557Sjimharris      for (i=0;
1889230557Sjimharris              (i < SCI_MAX_PHYS)
1890230557Sjimharris           && (this_controller->power_control.phys_waiting != 0);
1891230557Sjimharris           i++)
1892230557Sjimharris      {
1893230557Sjimharris         if (this_controller->power_control.requesters[i] != NULL)
1894230557Sjimharris         {
1895230557Sjimharris            if ( this_controller->power_control.remote_devices_granted_power <
1896230557Sjimharris                 this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up
1897230557Sjimharris               )
1898230557Sjimharris            {
1899230557Sjimharris               the_phy = this_controller->power_control.requesters[i];
1900230557Sjimharris               this_controller->power_control.requesters[i] = NULL;
1901230557Sjimharris               this_controller->power_control.phys_waiting--;
1902230557Sjimharris               this_controller->power_control.remote_devices_granted_power ++;
1903230557Sjimharris               scic_sds_phy_consume_power_handler(the_phy);
1904230557Sjimharris
1905230557Sjimharris               if (the_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
1906230557Sjimharris               {
1907230557Sjimharris                  U8 j;
1908230557Sjimharris                  SCIC_SDS_PHY_T * current_requester_phy;
1909230557Sjimharris
1910230557Sjimharris                  for (j = 0; j < SCI_MAX_PHYS; j++)
1911230557Sjimharris                  {
1912230557Sjimharris                     current_requester_phy = this_controller->power_control.requesters[j];
1913230557Sjimharris
1914230557Sjimharris                     //Search the power_control queue to see if there are other phys attached to
1915230557Sjimharris                     //the same remote device. If found, take all of them out of await_sas_power state.
1916230557Sjimharris                     if (current_requester_phy != NULL &&
1917230557Sjimharris                         current_requester_phy != the_phy &&
1918230557Sjimharris                         current_requester_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high
1919230557Sjimharris                            == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high &&
1920230557Sjimharris                         current_requester_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low
1921230557Sjimharris                            == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low)
1922230557Sjimharris                     {
1923230557Sjimharris                        this_controller->power_control.requesters[j] = NULL;
1924230557Sjimharris                        this_controller->power_control.phys_waiting--;
1925230557Sjimharris                        scic_sds_phy_consume_power_handler(current_requester_phy);
1926230557Sjimharris                     }
1927230557Sjimharris                  }
1928230557Sjimharris               }
1929230557Sjimharris            }
1930230557Sjimharris            else
1931230557Sjimharris            {
1932230557Sjimharris               break;
1933230557Sjimharris            }
1934230557Sjimharris         }
1935230557Sjimharris      }
1936230557Sjimharris
1937230557Sjimharris      // It doesn't matter if the power list is empty, we need to start the
1938230557Sjimharris      // timer in case another phy becomes ready.
1939230557Sjimharris      scic_sds_controller_power_control_timer_start(this_controller);
1940230557Sjimharris   }
1941230557Sjimharris}
1942230557Sjimharris
1943230557Sjimharris/**
1944230557Sjimharris * @brief This method inserts the phy in the stagger spinup control queue.
1945230557Sjimharris *
1946230557Sjimharris * @param[in] this_controller
1947230557Sjimharris * @param[in] the_phy
1948230557Sjimharris */
1949230557Sjimharrisvoid scic_sds_controller_power_control_queue_insert(
1950230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
1951230557Sjimharris   SCIC_SDS_PHY_T        *the_phy
1952230557Sjimharris)
1953230557Sjimharris{
1954230557Sjimharris   ASSERT (the_phy != NULL);
1955230557Sjimharris
1956230557Sjimharris   if( this_controller->power_control.remote_devices_granted_power <
1957230557Sjimharris       this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up
1958230557Sjimharris     )
1959230557Sjimharris   {
1960230557Sjimharris      this_controller->power_control.remote_devices_granted_power ++;
1961230557Sjimharris      scic_sds_phy_consume_power_handler(the_phy);
1962230557Sjimharris
1963230557Sjimharris      //stop and start the power_control timer. When the timer fires, the
1964230557Sjimharris      //no_of_devices_granted_power will be set to 0
1965230557Sjimharris      scic_sds_controller_power_control_timer_restart (this_controller);
1966230557Sjimharris   }
1967230557Sjimharris   else
1968230557Sjimharris   {
1969230557Sjimharris      //there are phys, attached to the same sas address as this phy, are already
1970230557Sjimharris      //in READY state, this phy don't need wait.
1971230557Sjimharris      U8 i;
1972230557Sjimharris      SCIC_SDS_PHY_T * current_phy;
1973230557Sjimharris      for(i = 0; i < SCI_MAX_PHYS; i++)
1974230557Sjimharris      {
1975230557Sjimharris         current_phy = &this_controller->phy_table[i];
1976230557Sjimharris
1977230557Sjimharris         if (current_phy->parent.state_machine.current_state_id == SCI_BASE_PHY_STATE_READY &&
1978230557Sjimharris             current_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS &&
1979230557Sjimharris             current_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high
1980230557Sjimharris                == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high &&
1981230557Sjimharris             current_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low
1982230557Sjimharris                == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low)
1983230557Sjimharris         {
1984230557Sjimharris            scic_sds_phy_consume_power_handler(the_phy);
1985230557Sjimharris            break;
1986230557Sjimharris         }
1987230557Sjimharris      }
1988230557Sjimharris
1989230557Sjimharris      if (i == SCI_MAX_PHYS)
1990230557Sjimharris      {
1991230557Sjimharris         //Add the phy in the waiting list
1992230557Sjimharris         this_controller->power_control.requesters[the_phy->phy_index] = the_phy;
1993230557Sjimharris         this_controller->power_control.phys_waiting++;
1994230557Sjimharris      }
1995230557Sjimharris   }
1996230557Sjimharris}
1997230557Sjimharris
1998230557Sjimharris/**
1999230557Sjimharris * @brief This method removes the phy from the stagger spinup control
2000230557Sjimharris *        queue.
2001230557Sjimharris *
2002230557Sjimharris * @param[in] this_controller
2003230557Sjimharris * @param[in] the_phy
2004230557Sjimharris */
2005230557Sjimharrisvoid scic_sds_controller_power_control_queue_remove(
2006230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
2007230557Sjimharris   SCIC_SDS_PHY_T        *the_phy
2008230557Sjimharris)
2009230557Sjimharris{
2010230557Sjimharris   ASSERT (the_phy != NULL);
2011230557Sjimharris
2012230557Sjimharris   if (this_controller->power_control.requesters[the_phy->phy_index] != NULL)
2013230557Sjimharris   {
2014230557Sjimharris      this_controller->power_control.phys_waiting--;
2015230557Sjimharris   }
2016230557Sjimharris
2017230557Sjimharris   this_controller->power_control.requesters[the_phy->phy_index] = NULL;
2018230557Sjimharris}
2019230557Sjimharris
2020230557Sjimharris//****************************************************************************-
2021230557Sjimharris//* SCIC SDS Controller Completion Routines
2022230557Sjimharris//****************************************************************************-
2023230557Sjimharris
2024230557Sjimharris/**
2025230557Sjimharris * @brief This method returns a TRUE value if the completion queue has
2026230557Sjimharris *        entries that can be processed
2027230557Sjimharris *
2028230557Sjimharris * @param[in] this_controller
2029230557Sjimharris *
2030230557Sjimharris * @return BOOL
2031230557Sjimharris * @retval TRUE if the completion queue has entries to process
2032230557Sjimharris *         FALSE if the completion queue has no entries to process
2033230557Sjimharris */
2034230557Sjimharrisstatic
2035230557SjimharrisBOOL scic_sds_controller_completion_queue_has_entries(
2036230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
2037230557Sjimharris)
2038230557Sjimharris{
2039230557Sjimharris   U32 get_value = this_controller->completion_queue_get;
2040230557Sjimharris   U32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK;
2041230557Sjimharris   if (
2042230557Sjimharris           NORMALIZE_GET_POINTER_CYCLE_BIT(get_value)
2043230557Sjimharris        == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
2044230557Sjimharris      )
2045230557Sjimharris   {
2046230557Sjimharris      return TRUE;
2047230557Sjimharris   }
2048230557Sjimharris
2049230557Sjimharris   return FALSE;
2050230557Sjimharris}
2051230557Sjimharris
2052230557Sjimharris// ---------------------------------------------------------------------------
2053230557Sjimharris
2054230557Sjimharris/**
2055230557Sjimharris * @brief This method processes a task completion notification.  This is
2056230557Sjimharris *        called from within the controller completion handler.
2057230557Sjimharris *
2058230557Sjimharris * @param[in] this_controller
2059230557Sjimharris * @param[in] completion_entry
2060230557Sjimharris *
2061230557Sjimharris * @return none
2062230557Sjimharris */
2063230557Sjimharrisstatic
2064230557Sjimharrisvoid scic_sds_controller_task_completion(
2065230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
2066230557Sjimharris   U32                   completion_entry
2067230557Sjimharris)
2068230557Sjimharris{
2069230557Sjimharris   U32 index;
2070230557Sjimharris   SCIC_SDS_REQUEST_T *io_request;
2071230557Sjimharris
2072230557Sjimharris   index = SCU_GET_COMPLETION_INDEX(completion_entry);
2073230557Sjimharris   io_request = this_controller->io_request_table[index];
2074230557Sjimharris
2075230557Sjimharris   // Make sure that we really want to process this IO request
2076230557Sjimharris   if (
2077230557Sjimharris           (io_request != SCI_INVALID_HANDLE)
2078230557Sjimharris        && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)
2079230557Sjimharris        && (
2080230557Sjimharris                scic_sds_io_tag_get_sequence(io_request->io_tag)
2081230557Sjimharris             == this_controller->io_request_sequence[index]
2082230557Sjimharris           )
2083230557Sjimharris      )
2084230557Sjimharris   {
2085230557Sjimharris      // Yep this is a valid io request pass it along to the io request handler
2086230557Sjimharris      scic_sds_io_request_tc_completion(io_request, completion_entry);
2087230557Sjimharris   }
2088230557Sjimharris}
2089230557Sjimharris
2090230557Sjimharris/**
2091230557Sjimharris * @brief This method processes an SDMA completion event.  This is called
2092230557Sjimharris *        from within the controller completion handler.
2093230557Sjimharris *
2094230557Sjimharris * @param[in] this_controller
2095230557Sjimharris * @param[in] completion_entry
2096230557Sjimharris *
2097230557Sjimharris * @return none
2098230557Sjimharris */
2099230557Sjimharrisstatic
2100230557Sjimharrisvoid scic_sds_controller_sdma_completion(
2101230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
2102230557Sjimharris   U32                   completion_entry
2103230557Sjimharris)
2104230557Sjimharris{
2105230557Sjimharris   U32 index;
2106230557Sjimharris   SCIC_SDS_REQUEST_T       *io_request;
2107230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *device;
2108230557Sjimharris
2109230557Sjimharris   index = SCU_GET_COMPLETION_INDEX(completion_entry);
2110230557Sjimharris
2111230557Sjimharris   switch (scu_get_command_request_type(completion_entry))
2112230557Sjimharris   {
2113230557Sjimharris   case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC:
2114230557Sjimharris   case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC:
2115230557Sjimharris      io_request = this_controller->io_request_table[index];
2116230557Sjimharris      SCIC_LOG_ERROR((
2117230557Sjimharris         sci_base_object_get_logger(this_controller),
2118230557Sjimharris           SCIC_LOG_OBJECT_CONTROLLER
2119230557Sjimharris         | SCIC_LOG_OBJECT_SMP_IO_REQUEST
2120230557Sjimharris         | SCIC_LOG_OBJECT_SSP_IO_REQUEST
2121230557Sjimharris         | SCIC_LOG_OBJECT_STP_IO_REQUEST,
2122230557Sjimharris         "SCIC SDS Completion type SDMA %x for io request %x\n",
2123230557Sjimharris         completion_entry,
2124230557Sjimharris         io_request
2125230557Sjimharris      ));
2126230557Sjimharris      /// @todo For a post TC operation we need to fail the IO request
2127230557Sjimharris      break;
2128230557Sjimharris
2129230557Sjimharris   case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC:
2130230557Sjimharris   case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC:
2131230557Sjimharris   case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC:
2132230557Sjimharris      device = this_controller->device_table[index];
2133230557Sjimharris      SCIC_LOG_ERROR((
2134230557Sjimharris         sci_base_object_get_logger(this_controller),
2135230557Sjimharris           SCIC_LOG_OBJECT_CONTROLLER
2136230557Sjimharris         | SCIC_LOG_OBJECT_SSP_REMOTE_TARGET
2137230557Sjimharris         | SCIC_LOG_OBJECT_SMP_REMOTE_TARGET
2138230557Sjimharris         | SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
2139230557Sjimharris         "SCIC SDS Completion type SDMA %x for remote device %x\n",
2140230557Sjimharris         completion_entry,
2141230557Sjimharris         device
2142230557Sjimharris      ));
2143230557Sjimharris      /// @todo For a port RNC operation we need to fail the device
2144230557Sjimharris      break;
2145230557Sjimharris
2146230557Sjimharris   default:
2147230557Sjimharris      SCIC_LOG_ERROR((
2148230557Sjimharris         sci_base_object_get_logger(this_controller),
2149230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
2150230557Sjimharris         "SCIC SDS Completion unknown SDMA completion type %x\n",
2151230557Sjimharris         completion_entry
2152230557Sjimharris      ));
2153230557Sjimharris      break;
2154230557Sjimharris   }
2155230557Sjimharris
2156230557Sjimharris   /// This is an unexpected completion type and is un-recoverable
2157230557Sjimharris   /// Transition to the failed state and wait for a controller reset
2158230557Sjimharris   sci_base_state_machine_change_state(
2159230557Sjimharris      scic_sds_controller_get_base_state_machine(this_controller),
2160230557Sjimharris      SCI_BASE_CONTROLLER_STATE_FAILED
2161230557Sjimharris   );
2162230557Sjimharris}
2163230557Sjimharris
2164230557Sjimharris/**
2165230557Sjimharris * This method processes an unsolicited frame message.  This is called from
2166230557Sjimharris * within the controller completion handler.
2167230557Sjimharris *
2168230557Sjimharris * @param[in] this_controller
2169230557Sjimharris * @param[in] completion_entry
2170230557Sjimharris *
2171230557Sjimharris * @return none
2172230557Sjimharris */
2173230557Sjimharrisstatic
2174230557Sjimharrisvoid scic_sds_controller_unsolicited_frame(
2175230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
2176230557Sjimharris   U32                   completion_entry
2177230557Sjimharris)
2178230557Sjimharris{
2179230557Sjimharris   U32 index;
2180230557Sjimharris   U32 frame_index;
2181230557Sjimharris
2182230557Sjimharris   SCU_UNSOLICITED_FRAME_HEADER_T * frame_header;
2183230557Sjimharris   SCIC_SDS_PHY_T                 * phy;
2184230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T       * device;
2185230557Sjimharris
2186230557Sjimharris   SCI_STATUS result = SCI_FAILURE;
2187230557Sjimharris
2188230557Sjimharris   frame_index = SCU_GET_FRAME_INDEX(completion_entry);
2189230557Sjimharris
2190230557Sjimharris   frame_header
2191230557Sjimharris      = this_controller->uf_control.buffers.array[frame_index].header;
2192230557Sjimharris   this_controller->uf_control.buffers.array[frame_index].state
2193230557Sjimharris      = UNSOLICITED_FRAME_IN_USE;
2194230557Sjimharris
2195230557Sjimharris   if (SCU_GET_FRAME_ERROR(completion_entry))
2196230557Sjimharris   {
2197230557Sjimharris      /// @todo If the IAF frame or SIGNATURE FIS frame has an error will
2198230557Sjimharris      ///       this cause a problem? We expect the phy initialization will
2199230557Sjimharris      ///       fail if there is an error in the frame.
2200230557Sjimharris      scic_sds_controller_release_frame(this_controller, frame_index);
2201230557Sjimharris      return;
2202230557Sjimharris   }
2203230557Sjimharris
2204230557Sjimharris   if (frame_header->is_address_frame)
2205230557Sjimharris   {
2206230557Sjimharris      index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
2207230557Sjimharris      phy = &this_controller->phy_table[index];
2208230557Sjimharris      if (phy != NULL)
2209230557Sjimharris      {
2210230557Sjimharris         result = scic_sds_phy_frame_handler(phy, frame_index);
2211230557Sjimharris      }
2212230557Sjimharris   }
2213230557Sjimharris   else
2214230557Sjimharris   {
2215230557Sjimharris
2216230557Sjimharris      index = SCU_GET_COMPLETION_INDEX(completion_entry);
2217230557Sjimharris
2218230557Sjimharris      if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
2219230557Sjimharris      {
2220230557Sjimharris         // This is a signature fis or a frame from a direct attached SATA
2221230557Sjimharris         // device that has not yet been created.  In either case forwared
2222230557Sjimharris         // the frame to the PE and let it take care of the frame data.
2223230557Sjimharris         index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
2224230557Sjimharris         phy = &this_controller->phy_table[index];
2225230557Sjimharris         result = scic_sds_phy_frame_handler(phy, frame_index);
2226230557Sjimharris      }
2227230557Sjimharris      else
2228230557Sjimharris      {
2229230557Sjimharris         if (index < this_controller->remote_node_entries)
2230230557Sjimharris            device = this_controller->device_table[index];
2231230557Sjimharris         else
2232230557Sjimharris            device = NULL;
2233230557Sjimharris
2234230557Sjimharris         if (device != NULL)
2235230557Sjimharris            result = scic_sds_remote_device_frame_handler(device, frame_index);
2236230557Sjimharris         else
2237230557Sjimharris            scic_sds_controller_release_frame(this_controller, frame_index);
2238230557Sjimharris      }
2239230557Sjimharris   }
2240230557Sjimharris
2241230557Sjimharris   if (result != SCI_SUCCESS)
2242230557Sjimharris   {
2243230557Sjimharris      /// @todo Is there any reason to report some additional error message
2244230557Sjimharris      ///       when we get this failure notifiction?
2245230557Sjimharris   }
2246230557Sjimharris}
2247230557Sjimharris
2248230557Sjimharris/**
2249230557Sjimharris * @brief This method processes an event completion entry.  This is called
2250230557Sjimharris *        from within the controller completion handler.
2251230557Sjimharris *
2252230557Sjimharris * @param[in] this_controller
2253230557Sjimharris * @param[in] completion_entry
2254230557Sjimharris *
2255230557Sjimharris * @return none
2256230557Sjimharris */
2257230557Sjimharrisstatic
2258230557Sjimharrisvoid scic_sds_controller_event_completion(
2259230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
2260230557Sjimharris   U32                   completion_entry
2261230557Sjimharris)
2262230557Sjimharris{
2263230557Sjimharris   U32 index;
2264230557Sjimharris   SCIC_SDS_REQUEST_T       *io_request;
2265230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *device;
2266230557Sjimharris   SCIC_SDS_PHY_T           *phy;
2267230557Sjimharris
2268230557Sjimharris   index = SCU_GET_COMPLETION_INDEX(completion_entry);
2269230557Sjimharris
2270230557Sjimharris   switch (scu_get_event_type(completion_entry))
2271230557Sjimharris   {
2272230557Sjimharris   case SCU_EVENT_TYPE_SMU_COMMAND_ERROR:
2273230557Sjimharris      /// @todo The driver did something wrong and we need to fix the condtion.
2274230557Sjimharris      SCIC_LOG_ERROR((
2275230557Sjimharris         sci_base_object_get_logger(this_controller),
2276230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
2277230557Sjimharris         "SCIC Controller 0x%x received SMU command error 0x%x\n",
2278230557Sjimharris         this_controller, completion_entry
2279230557Sjimharris      ));
2280230557Sjimharris      break;
2281230557Sjimharris
2282230557Sjimharris   case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR:
2283230557Sjimharris       // report fatal memory error
2284230557Sjimharris       this_controller->parent.error = SCI_CONTROLLER_FATAL_MEMORY_ERROR;
2285230557Sjimharris
2286230557Sjimharris       sci_base_state_machine_change_state(
2287230557Sjimharris          scic_sds_controller_get_base_state_machine(this_controller),
2288230557Sjimharris          SCI_BASE_CONTROLLER_STATE_FAILED
2289230557Sjimharris       );
2290230557Sjimharris
2291230557Sjimharris       //continue as in following events
2292230557Sjimharris   case SCU_EVENT_TYPE_SMU_PCQ_ERROR:
2293230557Sjimharris   case SCU_EVENT_TYPE_SMU_ERROR:
2294230557Sjimharris      SCIC_LOG_ERROR((
2295230557Sjimharris         sci_base_object_get_logger(this_controller),
2296230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
2297230557Sjimharris         "SCIC Controller 0x%x received fatal controller event 0x%x\n",
2298230557Sjimharris         this_controller, completion_entry
2299230557Sjimharris      ));
2300230557Sjimharris      break;
2301230557Sjimharris
2302230557Sjimharris   case SCU_EVENT_TYPE_TRANSPORT_ERROR:
2303230557Sjimharris      io_request = this_controller->io_request_table[index];
2304230557Sjimharris      scic_sds_io_request_event_handler(io_request, completion_entry);
2305230557Sjimharris      break;
2306230557Sjimharris
2307230557Sjimharris   case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
2308230557Sjimharris      switch (scu_get_event_specifier(completion_entry))
2309230557Sjimharris      {
2310230557Sjimharris      case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE:
2311230557Sjimharris      case SCU_EVENT_SPECIFIC_TASK_TIMEOUT:
2312230557Sjimharris         io_request = this_controller->io_request_table[index];
2313230557Sjimharris         if (io_request != SCI_INVALID_HANDLE)
2314230557Sjimharris         {
2315230557Sjimharris            scic_sds_io_request_event_handler(io_request, completion_entry);
2316230557Sjimharris         }
2317230557Sjimharris         else
2318230557Sjimharris         {
2319230557Sjimharris            SCIC_LOG_WARNING((
2320230557Sjimharris               sci_base_object_get_logger(this_controller),
2321230557Sjimharris               SCIC_LOG_OBJECT_CONTROLLER |
2322230557Sjimharris               SCIC_LOG_OBJECT_SMP_IO_REQUEST |
2323230557Sjimharris               SCIC_LOG_OBJECT_SSP_IO_REQUEST |
2324230557Sjimharris               SCIC_LOG_OBJECT_STP_IO_REQUEST,
2325230557Sjimharris               "SCIC Controller 0x%x received event 0x%x for io request object that doesnt exist.\n",
2326230557Sjimharris               this_controller, completion_entry
2327230557Sjimharris            ));
2328230557Sjimharris         }
2329230557Sjimharris         break;
2330230557Sjimharris
2331230557Sjimharris      case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT:
2332230557Sjimharris         device = this_controller->device_table[index];
2333230557Sjimharris         if (device != SCI_INVALID_HANDLE)
2334230557Sjimharris         {
2335230557Sjimharris            scic_sds_remote_device_event_handler(device, completion_entry);
2336230557Sjimharris         }
2337230557Sjimharris         else
2338230557Sjimharris         {
2339230557Sjimharris            SCIC_LOG_WARNING((
2340230557Sjimharris               sci_base_object_get_logger(this_controller),
2341230557Sjimharris               SCIC_LOG_OBJECT_CONTROLLER |
2342230557Sjimharris               SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
2343230557Sjimharris               SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
2344230557Sjimharris               SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
2345230557Sjimharris               "SCIC Controller 0x%x received event 0x%x for remote device object that doesnt exist.\n",
2346230557Sjimharris               this_controller, completion_entry
2347230557Sjimharris            ));
2348230557Sjimharris         }
2349230557Sjimharris         break;
2350230557Sjimharris      }
2351230557Sjimharris      break;
2352230557Sjimharris
2353230557Sjimharris   case SCU_EVENT_TYPE_BROADCAST_CHANGE:
2354230557Sjimharris      // direct the broadcast change event to the phy first and then let
2355230557Sjimharris      // the phy redirect the broadcast change to the port object
2356230557Sjimharris   case SCU_EVENT_TYPE_ERR_CNT_EVENT:
2357230557Sjimharris      // direct error counter event to the phy object since that is where
2358230557Sjimharris      // we get the event notification.  This is a type 4 event.
2359230557Sjimharris   case SCU_EVENT_TYPE_OSSP_EVENT:
2360230557Sjimharris      index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
2361230557Sjimharris      phy = &this_controller->phy_table[index];
2362230557Sjimharris      scic_sds_phy_event_handler(phy, completion_entry);
2363230557Sjimharris      break;
2364230557Sjimharris
2365230557Sjimharris   case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
2366230557Sjimharris   case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
2367230557Sjimharris   case SCU_EVENT_TYPE_RNC_OPS_MISC:
2368230557Sjimharris      if (index < this_controller->remote_node_entries)
2369230557Sjimharris      {
2370230557Sjimharris         device = this_controller->device_table[index];
2371230557Sjimharris
2372230557Sjimharris         if (device != NULL)
2373230557Sjimharris         {
2374230557Sjimharris            scic_sds_remote_device_event_handler(device, completion_entry);
2375230557Sjimharris         }
2376230557Sjimharris      }
2377230557Sjimharris      else
2378230557Sjimharris      {
2379230557Sjimharris         SCIC_LOG_ERROR((
2380230557Sjimharris            sci_base_object_get_logger(this_controller),
2381230557Sjimharris            SCIC_LOG_OBJECT_CONTROLLER |
2382230557Sjimharris            SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
2383230557Sjimharris            SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
2384230557Sjimharris            SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
2385230557Sjimharris            "SCIC Controller 0x%x received event 0x%x for remote device object 0x%0x that doesnt exist.\n",
2386230557Sjimharris            this_controller, completion_entry, index
2387230557Sjimharris         ));
2388230557Sjimharris      }
2389230557Sjimharris      break;
2390230557Sjimharris
2391230557Sjimharris   default:
2392230557Sjimharris      SCIC_LOG_WARNING((
2393230557Sjimharris         sci_base_object_get_logger(this_controller),
2394230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
2395230557Sjimharris         "SCIC Controller received unknown event code %x\n",
2396230557Sjimharris         completion_entry
2397230557Sjimharris      ));
2398230557Sjimharris      break;
2399230557Sjimharris   }
2400230557Sjimharris}
2401230557Sjimharris
2402230557Sjimharris/**
2403230557Sjimharris * @brief This method is a private routine for processing the completion
2404230557Sjimharris *        queue entries.
2405230557Sjimharris *
2406230557Sjimharris * @param[in] this_controller
2407230557Sjimharris *
2408230557Sjimharris * @return none
2409230557Sjimharris */
2410230557Sjimharrisstatic
2411230557Sjimharrisvoid scic_sds_controller_process_completions(
2412230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
2413230557Sjimharris)
2414230557Sjimharris{
2415230557Sjimharris   U32 completion_count = 0;
2416230557Sjimharris   U32 completion_entry;
2417230557Sjimharris   U32 get_index;
2418230557Sjimharris   U32 get_cycle;
2419230557Sjimharris   U32 event_index;
2420230557Sjimharris   U32 event_cycle;
2421230557Sjimharris
2422230557Sjimharris   SCIC_LOG_TRACE((
2423230557Sjimharris      sci_base_object_get_logger(this_controller),
2424230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
2425230557Sjimharris      "scic_sds_controller_process_completions(0x%x) enter\n",
2426230557Sjimharris      this_controller
2427230557Sjimharris   ));
2428230557Sjimharris
2429230557Sjimharris   SCIC_LOG_TRACE((
2430230557Sjimharris      sci_base_object_get_logger(this_controller),
2431230557Sjimharris      SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2432230557Sjimharris      "completion queue begining get : 0x%08x\n",
2433230557Sjimharris      this_controller->completion_queue_get
2434230557Sjimharris   ));
2435230557Sjimharris
2436230557Sjimharris   // Get the component parts of the completion queue
2437230557Sjimharris   get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
2438230557Sjimharris   get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
2439230557Sjimharris
2440230557Sjimharris   event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
2441230557Sjimharris   event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
2442230557Sjimharris
2443230557Sjimharris   while (
2444230557Sjimharris               NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
2445230557Sjimharris            == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
2446230557Sjimharris         )
2447230557Sjimharris   {
2448230557Sjimharris      completion_count++;
2449230557Sjimharris
2450230557Sjimharris      completion_entry = this_controller->completion_queue[get_index];
2451230557Sjimharris      INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
2452230557Sjimharris
2453230557Sjimharris      SCIC_LOG_TRACE((
2454230557Sjimharris         sci_base_object_get_logger(this_controller),
2455230557Sjimharris         SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2456230557Sjimharris         "completion queue entry : 0x%08x\n",
2457230557Sjimharris         completion_entry
2458230557Sjimharris      ));
2459230557Sjimharris
2460230557Sjimharris      switch (SCU_GET_COMPLETION_TYPE(completion_entry))
2461230557Sjimharris      {
2462230557Sjimharris      case SCU_COMPLETION_TYPE_TASK:
2463230557Sjimharris         scic_sds_controller_task_completion(this_controller, completion_entry);
2464230557Sjimharris         break;
2465230557Sjimharris
2466230557Sjimharris      case SCU_COMPLETION_TYPE_SDMA:
2467230557Sjimharris         scic_sds_controller_sdma_completion(this_controller, completion_entry);
2468230557Sjimharris         break;
2469230557Sjimharris
2470230557Sjimharris      case SCU_COMPLETION_TYPE_UFI:
2471230557Sjimharris         scic_sds_controller_unsolicited_frame(this_controller, completion_entry);
2472230557Sjimharris         break;
2473230557Sjimharris
2474230557Sjimharris      case SCU_COMPLETION_TYPE_EVENT:
2475230557Sjimharris         scic_sds_controller_event_completion(this_controller, completion_entry);
2476230557Sjimharris         break;
2477230557Sjimharris
2478230557Sjimharris      case SCU_COMPLETION_TYPE_NOTIFY:
2479230557Sjimharris         // Presently we do the same thing with a notify event that we do with the
2480230557Sjimharris         // other event codes.
2481230557Sjimharris         INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
2482230557Sjimharris         scic_sds_controller_event_completion(this_controller, completion_entry);
2483230557Sjimharris         break;
2484230557Sjimharris
2485230557Sjimharris      default:
2486230557Sjimharris         SCIC_LOG_WARNING((
2487230557Sjimharris            sci_base_object_get_logger(this_controller),
2488230557Sjimharris            SCIC_LOG_OBJECT_CONTROLLER,
2489230557Sjimharris            "SCIC Controller received unknown completion type %x\n",
2490230557Sjimharris            completion_entry
2491230557Sjimharris         ));
2492230557Sjimharris         break;
2493230557Sjimharris      }
2494230557Sjimharris   }
2495230557Sjimharris
2496230557Sjimharris   // Update the get register if we completed one or more entries
2497230557Sjimharris   if (completion_count > 0)
2498230557Sjimharris   {
2499230557Sjimharris      this_controller->completion_queue_get =
2500230557Sjimharris           SMU_CQGR_GEN_BIT(ENABLE)
2501230557Sjimharris         | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
2502230557Sjimharris         | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
2503230557Sjimharris         | get_cycle   | SMU_CQGR_GEN_VAL(POINTER, get_index)  ;
2504230557Sjimharris
2505230557Sjimharris      SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
2506230557Sjimharris   }
2507230557Sjimharris
2508230557Sjimharris   SCIC_LOG_TRACE((
2509230557Sjimharris      sci_base_object_get_logger(this_controller),
2510230557Sjimharris      SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2511230557Sjimharris      "completion queue ending get : 0x%08x\n",
2512230557Sjimharris      this_controller->completion_queue_get
2513230557Sjimharris   ));
2514230557Sjimharris
2515230557Sjimharris}
2516230557Sjimharris
2517230557Sjimharris/**
2518230557Sjimharris * @brief This method is a private routine for processing the completion
2519230557Sjimharris *        queue entries.
2520230557Sjimharris *
2521230557Sjimharris * @param[in] this_controller
2522230557Sjimharris *
2523230557Sjimharris * @return none
2524230557Sjimharris */
2525230557Sjimharrisstatic
2526230557Sjimharrisvoid scic_sds_controller_transitioned_process_completions(
2527230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller
2528230557Sjimharris)
2529230557Sjimharris{
2530230557Sjimharris   U32 completion_count = 0;
2531230557Sjimharris   U32 completion_entry;
2532230557Sjimharris   U32 get_index;
2533230557Sjimharris   U32 get_cycle;
2534230557Sjimharris   U32 event_index;
2535230557Sjimharris   U32 event_cycle;
2536230557Sjimharris
2537230557Sjimharris   SCIC_LOG_TRACE((
2538230557Sjimharris      sci_base_object_get_logger(this_controller),
2539230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
2540230557Sjimharris      "scic_sds_controller_transitioned_process_completions(0x%x) enter\n",
2541230557Sjimharris      this_controller
2542230557Sjimharris   ));
2543230557Sjimharris
2544230557Sjimharris   SCIC_LOG_TRACE((
2545230557Sjimharris      sci_base_object_get_logger(this_controller),
2546230557Sjimharris      SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2547230557Sjimharris      "completion queue begining get : 0x%08x\n",
2548230557Sjimharris      this_controller->completion_queue_get
2549230557Sjimharris   ));
2550230557Sjimharris
2551230557Sjimharris   // Get the component parts of the completion queue
2552230557Sjimharris   get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
2553230557Sjimharris   get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
2554230557Sjimharris
2555230557Sjimharris   event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
2556230557Sjimharris   event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
2557230557Sjimharris
2558230557Sjimharris   while (
2559230557Sjimharris               NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
2560230557Sjimharris            == COMPLETION_QUEUE_CYCLE_BIT(
2561230557Sjimharris                  this_controller->completion_queue[get_index])
2562230557Sjimharris         )
2563230557Sjimharris   {
2564230557Sjimharris      completion_count++;
2565230557Sjimharris
2566230557Sjimharris      completion_entry = this_controller->completion_queue[get_index];
2567230557Sjimharris      INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
2568230557Sjimharris
2569230557Sjimharris      SCIC_LOG_TRACE((
2570230557Sjimharris         sci_base_object_get_logger(this_controller),
2571230557Sjimharris         SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2572230557Sjimharris         "completion queue entry : 0x%08x\n",
2573230557Sjimharris         completion_entry
2574230557Sjimharris      ));
2575230557Sjimharris
2576230557Sjimharris      switch (SCU_GET_COMPLETION_TYPE(completion_entry))
2577230557Sjimharris      {
2578230557Sjimharris      case SCU_COMPLETION_TYPE_TASK:
2579230557Sjimharris         scic_sds_controller_task_completion(this_controller, completion_entry);
2580230557Sjimharris      break;
2581230557Sjimharris
2582230557Sjimharris      case SCU_COMPLETION_TYPE_NOTIFY:
2583230557Sjimharris         INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
2584230557Sjimharris         // Fall-through
2585230557Sjimharris
2586230557Sjimharris      case SCU_COMPLETION_TYPE_EVENT:
2587230557Sjimharris      case SCU_COMPLETION_TYPE_SDMA:
2588230557Sjimharris      case SCU_COMPLETION_TYPE_UFI:
2589230557Sjimharris      default:
2590230557Sjimharris         SCIC_LOG_WARNING((
2591230557Sjimharris            sci_base_object_get_logger(this_controller),
2592230557Sjimharris            SCIC_LOG_OBJECT_CONTROLLER,
2593230557Sjimharris            "SCIC Controller ignoring completion type %x\n",
2594230557Sjimharris            completion_entry
2595230557Sjimharris         ));
2596230557Sjimharris      break;
2597230557Sjimharris      }
2598230557Sjimharris   }
2599230557Sjimharris
2600230557Sjimharris   // Update the get register if we completed one or more entries
2601230557Sjimharris   if (completion_count > 0)
2602230557Sjimharris   {
2603230557Sjimharris      this_controller->completion_queue_get =
2604230557Sjimharris           SMU_CQGR_GEN_BIT(ENABLE)
2605230557Sjimharris         | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
2606230557Sjimharris         | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
2607230557Sjimharris         | get_cycle   | SMU_CQGR_GEN_VAL(POINTER, get_index)  ;
2608230557Sjimharris
2609230557Sjimharris      SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
2610230557Sjimharris   }
2611230557Sjimharris
2612230557Sjimharris   SCIC_LOG_TRACE((
2613230557Sjimharris      sci_base_object_get_logger(this_controller),
2614230557Sjimharris      SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2615230557Sjimharris      "completion queue ending get : 0x%08x\n",
2616230557Sjimharris      this_controller->completion_queue_get
2617230557Sjimharris   ));
2618230557Sjimharris}
2619230557Sjimharris
2620230557Sjimharris//****************************************************************************-
2621230557Sjimharris//* SCIC SDS Controller Interrupt and Completion functions
2622230557Sjimharris//****************************************************************************-
2623230557Sjimharris
2624230557Sjimharris/**
2625230557Sjimharris * @brief This method provides standard (common) processing of interrupts
2626230557Sjimharris *        for polling and legacy based interrupts.
2627230557Sjimharris *
2628230557Sjimharris * @param[in] controller
2629230557Sjimharris * @param[in] interrupt_status
2630230557Sjimharris *
2631230557Sjimharris * @return This method returns a boolean (BOOL) indication as to
2632230557Sjimharris *         whether an completions are pending to be processed.
2633230557Sjimharris * @retval TRUE if an interrupt is to be processed
2634230557Sjimharris * @retval FALSE if no interrupt was pending
2635230557Sjimharris */
2636230557Sjimharrisstatic
2637230557SjimharrisBOOL scic_sds_controller_standard_interrupt_handler(
2638230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
2639230557Sjimharris   U32                    interrupt_status
2640230557Sjimharris)
2641230557Sjimharris{
2642230557Sjimharris   BOOL  is_completion_needed = FALSE;
2643230557Sjimharris
2644230557Sjimharris   SCIC_LOG_TRACE((
2645230557Sjimharris      sci_base_object_get_logger(this_controller),
2646230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
2647230557Sjimharris      "scic_sds_controller_standard_interrupt_handler(0x%d,0x%d) enter\n",
2648230557Sjimharris      this_controller, interrupt_status
2649230557Sjimharris   ));
2650230557Sjimharris
2651230557Sjimharris   if (
2652230557Sjimharris         (interrupt_status & SMU_ISR_QUEUE_ERROR)
2653230557Sjimharris      || (
2654230557Sjimharris            (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
2655230557Sjimharris         && (!scic_sds_controller_completion_queue_has_entries(this_controller))
2656230557Sjimharris         )
2657230557Sjimharris      )
2658230557Sjimharris   {
2659230557Sjimharris      // We have a fatal error on the read of the completion queue bar
2660230557Sjimharris      // OR
2661230557Sjimharris      // We have a fatal error there is nothing in the completion queue
2662230557Sjimharris      // but we have a report from the hardware that the queue is full
2663230557Sjimharris      /// @todo how do we request the a controller reset
2664230557Sjimharris      is_completion_needed = TRUE;
2665230557Sjimharris      this_controller->encountered_fatal_error = TRUE;
2666230557Sjimharris   }
2667230557Sjimharris
2668230557Sjimharris   if (scic_sds_controller_completion_queue_has_entries(this_controller))
2669230557Sjimharris   {
2670230557Sjimharris      is_completion_needed = TRUE;
2671230557Sjimharris   }
2672230557Sjimharris
2673230557Sjimharris   return is_completion_needed;
2674230557Sjimharris}
2675230557Sjimharris
2676230557Sjimharris/**
2677230557Sjimharris * @brief This is the method provided to handle polling for interrupts
2678230557Sjimharris *        for the controller object.
2679230557Sjimharris *
2680230557Sjimharris * @param[in] controller
2681230557Sjimharris *
2682230557Sjimharris * @return BOOL
2683230557Sjimharris * @retval TRUE if an interrupt is to be processed
2684230557Sjimharris * @retval FALSE if no interrupt was pending
2685230557Sjimharris */
2686230557Sjimharrisstatic
2687230557SjimharrisBOOL scic_sds_controller_polling_interrupt_handler(
2688230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
2689230557Sjimharris)
2690230557Sjimharris{
2691230557Sjimharris   U32                    interrupt_status;
2692230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
2693230557Sjimharris
2694230557Sjimharris   SCIC_LOG_TRACE((
2695230557Sjimharris      sci_base_object_get_logger(controller),
2696230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
2697230557Sjimharris      "scic_sds_controller_polling_interrupt_handler(0x%d) enter\n",
2698230557Sjimharris      controller
2699230557Sjimharris   ));
2700230557Sjimharris
2701230557Sjimharris   /*
2702230557Sjimharris    * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the hardware
2703230557Sjimharris    * indicates nothing is pending. Since we are not being called from a real
2704230557Sjimharris    * interrupt, we don't want to confuse the hardware by servicing the
2705230557Sjimharris    * completion queue before the hardware indicates it is ready. We'll
2706230557Sjimharris    * simply wait for another polling interval and check again.
2707230557Sjimharris    */
2708230557Sjimharris   interrupt_status = SMU_ISR_READ(this_controller);
2709230557Sjimharris   if ((interrupt_status &
2710230557Sjimharris         (SMU_ISR_COMPLETION |
2711230557Sjimharris          SMU_ISR_QUEUE_ERROR |
2712230557Sjimharris          SMU_ISR_QUEUE_SUSPEND)) == 0)
2713230557Sjimharris   {
2714230557Sjimharris      return FALSE;
2715230557Sjimharris   }
2716230557Sjimharris
2717230557Sjimharris   return scic_sds_controller_standard_interrupt_handler(
2718230557Sjimharris             controller, interrupt_status
2719230557Sjimharris          );
2720230557Sjimharris}
2721230557Sjimharris
2722230557Sjimharris/**
2723230557Sjimharris * @brief This is the method provided to handle completions when interrupt
2724230557Sjimharris *        polling is in use.
2725230557Sjimharris *
2726230557Sjimharris * @param[in] controller
2727230557Sjimharris *
2728230557Sjimharris * @return none
2729230557Sjimharris */
2730230557Sjimharrisstatic
2731230557Sjimharrisvoid scic_sds_controller_polling_completion_handler(
2732230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
2733230557Sjimharris)
2734230557Sjimharris{
2735230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2736230557Sjimharris
2737230557Sjimharris   SCIC_LOG_TRACE((
2738230557Sjimharris      sci_base_object_get_logger(controller),
2739230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
2740230557Sjimharris      "scic_sds_controller_polling_completion_handler(0x%d) enter\n",
2741230557Sjimharris      controller
2742230557Sjimharris   ));
2743230557Sjimharris
2744230557Sjimharris   if (this_controller->encountered_fatal_error == TRUE)
2745230557Sjimharris   {
2746230557Sjimharris      SCIC_LOG_ERROR((
2747230557Sjimharris         sci_base_object_get_logger(this_controller),
2748230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
2749230557Sjimharris         "SCIC Controller has encountered a fatal error.\n"
2750230557Sjimharris      ));
2751230557Sjimharris
2752230557Sjimharris      sci_base_state_machine_change_state(
2753230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller),
2754230557Sjimharris         SCI_BASE_CONTROLLER_STATE_FAILED
2755230557Sjimharris      );
2756230557Sjimharris   }
2757230557Sjimharris   else if (scic_sds_controller_completion_queue_has_entries(this_controller))
2758230557Sjimharris   {
2759230557Sjimharris      if (this_controller->restrict_completions == FALSE)
2760230557Sjimharris         scic_sds_controller_process_completions(this_controller);
2761230557Sjimharris      else
2762230557Sjimharris         scic_sds_controller_transitioned_process_completions(this_controller);
2763230557Sjimharris   }
2764230557Sjimharris
2765230557Sjimharris   /*
2766230557Sjimharris    * The interrupt handler does not adjust the CQ's
2767230557Sjimharris    * get pointer.  So, SCU's INTx pin stays asserted during the
2768230557Sjimharris    * interrupt handler even though it tries to clear the interrupt
2769230557Sjimharris    * source.  Therefore, the completion handler must ensure that the
2770230557Sjimharris    * interrupt source is cleared.  Otherwise, we get a spurious
2771230557Sjimharris    * interrupt for which the interrupt handler will not issue a
2772230557Sjimharris    * corresponding completion event. Also, we unmask interrupts.
2773230557Sjimharris    */
2774230557Sjimharris   SMU_ISR_WRITE(
2775230557Sjimharris      this_controller,
2776230557Sjimharris      (U32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)
2777230557Sjimharris   );
2778230557Sjimharris}
2779230557Sjimharris
2780230557Sjimharris#if !defined(DISABLE_INTERRUPTS)
2781230557Sjimharris/**
2782230557Sjimharris * @brief This is the method provided to handle legacy interrupts for the
2783230557Sjimharris *        controller object.
2784230557Sjimharris *
2785230557Sjimharris * @param[in] controller
2786230557Sjimharris *
2787230557Sjimharris * @return BOOL
2788230557Sjimharris * @retval TRUE if an interrupt is processed
2789230557Sjimharris *         FALSE if no interrupt was processed
2790230557Sjimharris */
2791230557Sjimharrisstatic
2792230557SjimharrisBOOL scic_sds_controller_legacy_interrupt_handler(
2793230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
2794230557Sjimharris)
2795230557Sjimharris{
2796230557Sjimharris   U32                    interrupt_status;
2797230557Sjimharris   BOOL                   is_completion_needed;
2798230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
2799230557Sjimharris
2800230557Sjimharris   interrupt_status     = SMU_ISR_READ(this_controller);
2801230557Sjimharris   is_completion_needed = scic_sds_controller_standard_interrupt_handler(
2802230557Sjimharris                             this_controller, interrupt_status
2803230557Sjimharris                          );
2804230557Sjimharris
2805230557Sjimharris   return is_completion_needed;
2806230557Sjimharris}
2807230557Sjimharris
2808230557Sjimharris
2809230557Sjimharris/**
2810230557Sjimharris * @brief This is the method provided to handle legacy completions it is
2811230557Sjimharris *        expected that the SCI User will call this completion handler
2812230557Sjimharris *        anytime the interrupt handler reports that it has handled an
2813230557Sjimharris *        interrupt.
2814230557Sjimharris *
2815230557Sjimharris * @param[in] controller
2816230557Sjimharris *
2817230557Sjimharris * @return none
2818230557Sjimharris */
2819230557Sjimharrisstatic
2820230557Sjimharrisvoid scic_sds_controller_legacy_completion_handler(
2821230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
2822230557Sjimharris)
2823230557Sjimharris{
2824230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2825230557Sjimharris
2826230557Sjimharris   SCIC_LOG_TRACE((
2827230557Sjimharris      sci_base_object_get_logger(controller),
2828230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
2829230557Sjimharris      "scic_sds_controller_legacy_completion_handler(0x%d) enter\n",
2830230557Sjimharris      controller
2831230557Sjimharris   ));
2832230557Sjimharris
2833230557Sjimharris   scic_sds_controller_polling_completion_handler(controller);
2834230557Sjimharris
2835230557Sjimharris   SMU_IMR_WRITE(this_controller, 0x00000000);
2836230557Sjimharris
2837230557Sjimharris#ifdef IMR_READ_FENCE
2838230557Sjimharris   {
2839230557Sjimharris      volatile U32 int_mask_value = 0;
2840230557Sjimharris      ULONG count = 0;
2841230557Sjimharris
2842230557Sjimharris      /*
2843230557Sjimharris       * Temporary code since we have seen with legacy interrupts
2844230557Sjimharris       * that interrupts are still masked after clearing the mask
2845230557Sjimharris       * above. This may be an Arlington problem or it may be an
2846230557Sjimharris       * old driver problem.  Presently this code is turned off
2847230557Sjimharris       * since we have not seen this problem recently.
2848230557Sjimharris       */
2849230557Sjimharris      do
2850230557Sjimharris      {
2851230557Sjimharris         int_mask_value = SMU_IMR_READ(this_controler);
2852230557Sjimharris
2853230557Sjimharris         if (count++ > 10)
2854230557Sjimharris         {
2855230557Sjimharris            #ifdef ALLOW_ENTER_DEBUGGER
2856230557Sjimharris            __debugbreak();
2857230557Sjimharris            #endif
2858230557Sjimharris            break;
2859230557Sjimharris         }
2860230557Sjimharris      } while (int_mask_value != 0);
2861230557Sjimharris   }
2862230557Sjimharris#endif
2863230557Sjimharris}
2864230557Sjimharris
2865230557Sjimharris/**
2866230557Sjimharris * @brief This is the method provided to handle an MSIX interrupt message
2867230557Sjimharris *        when there is just a single MSIX message being provided by the
2868230557Sjimharris *        hardware.  This mode of operation is single vector mode.
2869230557Sjimharris *
2870230557Sjimharris * @param[in] controller
2871230557Sjimharris *
2872230557Sjimharris * @return BOOL
2873230557Sjimharris * @retval TRUE if an interrupt is processed
2874230557Sjimharris *         FALSE if no interrupt was processed
2875230557Sjimharris */
2876230557Sjimharrisstatic
2877230557SjimharrisBOOL scic_sds_controller_single_vector_interrupt_handler(
2878230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
2879230557Sjimharris)
2880230557Sjimharris{
2881230557Sjimharris   U32 interrupt_status;
2882230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
2883230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2884230557Sjimharris
2885230557Sjimharris   // Mask the interrupts
2886230557Sjimharris   // There is a race in the hardware that could cause us not to be notified
2887230557Sjimharris   // of an interrupt completion if we do not take this step.  We will unmask
2888230557Sjimharris   // the interrupts in the completion routine.
2889230557Sjimharris   SMU_IMR_WRITE(this_controller, 0xFFFFFFFF);
2890230557Sjimharris
2891230557Sjimharris   interrupt_status = SMU_ISR_READ(this_controller);
2892230557Sjimharris   interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
2893230557Sjimharris
2894230557Sjimharris   if (
2895230557Sjimharris           (interrupt_status == 0)
2896230557Sjimharris        && scic_sds_controller_completion_queue_has_entries(this_controller)
2897230557Sjimharris      )
2898230557Sjimharris   {
2899230557Sjimharris      // There is at least one completion queue entry to process so we can
2900230557Sjimharris      // return a success and ignore for now the case of an error interrupt
2901230557Sjimharris      SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
2902230557Sjimharris
2903230557Sjimharris      return TRUE;
2904230557Sjimharris   }
2905230557Sjimharris
2906230557Sjimharris
2907230557Sjimharris   if (interrupt_status != 0)
2908230557Sjimharris   {
2909230557Sjimharris      // There is an error interrupt pending so let it through and handle
2910230557Sjimharris      // in the callback
2911230557Sjimharris      return TRUE;
2912230557Sjimharris   }
2913230557Sjimharris
2914230557Sjimharris   // Clear any offending interrupts since we could not find any to handle
2915230557Sjimharris   // and unmask them all
2916230557Sjimharris   SMU_ISR_WRITE(this_controller, 0x00000000);
2917230557Sjimharris   SMU_IMR_WRITE(this_controller, 0x00000000);
2918230557Sjimharris
2919230557Sjimharris   return FALSE;
2920230557Sjimharris}
2921230557Sjimharris
2922230557Sjimharris/**
2923230557Sjimharris * @brief This is the method provided to handle completions for a single
2924230557Sjimharris *        MSIX message.
2925230557Sjimharris *
2926230557Sjimharris * @param[in] controller
2927230557Sjimharris */
2928230557Sjimharrisstatic
2929230557Sjimharrisvoid scic_sds_controller_single_vector_completion_handler(
2930230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
2931230557Sjimharris)
2932230557Sjimharris{
2933230557Sjimharris   U32 interrupt_status;
2934230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
2935230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2936230557Sjimharris
2937230557Sjimharris   SCIC_LOG_TRACE((
2938230557Sjimharris      sci_base_object_get_logger(controller),
2939230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
2940230557Sjimharris      "scic_sds_controller_single_vector_completion_handler(0x%d) enter\n",
2941230557Sjimharris      controller
2942230557Sjimharris   ));
2943230557Sjimharris
2944230557Sjimharris   interrupt_status = SMU_ISR_READ(this_controller);
2945230557Sjimharris   interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
2946230557Sjimharris
2947230557Sjimharris   if (interrupt_status & SMU_ISR_QUEUE_ERROR)
2948230557Sjimharris   {
2949230557Sjimharris      SCIC_LOG_ERROR((
2950230557Sjimharris         sci_base_object_get_logger(this_controller),
2951230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
2952230557Sjimharris         "SCIC Controller has encountered a fatal error.\n"
2953230557Sjimharris      ));
2954230557Sjimharris
2955230557Sjimharris      // We have a fatal condition and must reset the controller
2956230557Sjimharris      // Leave the interrupt mask in place and get the controller reset
2957230557Sjimharris      sci_base_state_machine_change_state(
2958230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller),
2959230557Sjimharris         SCI_BASE_CONTROLLER_STATE_FAILED
2960230557Sjimharris      );
2961230557Sjimharris      return;
2962230557Sjimharris   }
2963230557Sjimharris
2964230557Sjimharris   if (
2965230557Sjimharris           (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
2966230557Sjimharris        && !scic_sds_controller_completion_queue_has_entries(this_controller)
2967230557Sjimharris      )
2968230557Sjimharris   {
2969230557Sjimharris      SCIC_LOG_ERROR((
2970230557Sjimharris         sci_base_object_get_logger(this_controller),
2971230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
2972230557Sjimharris         "SCIC Controller has encountered a fatal error.\n"
2973230557Sjimharris      ));
2974230557Sjimharris
2975230557Sjimharris      // We have a fatal condtion and must reset the controller
2976230557Sjimharris      // Leave the interrupt mask in place and get the controller reset
2977230557Sjimharris      sci_base_state_machine_change_state(
2978230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller),
2979230557Sjimharris         SCI_BASE_CONTROLLER_STATE_FAILED
2980230557Sjimharris      );
2981230557Sjimharris      return;
2982230557Sjimharris   }
2983230557Sjimharris
2984230557Sjimharris   if (scic_sds_controller_completion_queue_has_entries(this_controller))
2985230557Sjimharris   {
2986230557Sjimharris      scic_sds_controller_process_completions(this_controller);
2987230557Sjimharris
2988230557Sjimharris      // We dont care which interrupt got us to processing the completion queu
2989230557Sjimharris      // so clear them both.
2990230557Sjimharris      SMU_ISR_WRITE(
2991230557Sjimharris         this_controller,
2992230557Sjimharris         (SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND)
2993230557Sjimharris      );
2994230557Sjimharris   }
2995230557Sjimharris
2996230557Sjimharris   SMU_IMR_WRITE(this_controller, 0x00000000);
2997230557Sjimharris}
2998230557Sjimharris
2999230557Sjimharris/**
3000230557Sjimharris * @brief This is the method provided to handle a MSIX message for a normal
3001230557Sjimharris *        completion.
3002230557Sjimharris *
3003230557Sjimharris * @param[in] controller
3004230557Sjimharris *
3005230557Sjimharris * @return BOOL
3006230557Sjimharris * @retval TRUE if an interrupt is processed
3007230557Sjimharris *         FALSE if no interrupt was processed
3008230557Sjimharris */
3009230557Sjimharrisstatic
3010230557SjimharrisBOOL scic_sds_controller_normal_vector_interrupt_handler(
3011230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
3012230557Sjimharris)
3013230557Sjimharris{
3014230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
3015230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3016230557Sjimharris
3017230557Sjimharris   if (scic_sds_controller_completion_queue_has_entries(this_controller))
3018230557Sjimharris   {
3019230557Sjimharris      return TRUE;
3020230557Sjimharris   }
3021230557Sjimharris   else
3022230557Sjimharris   {
3023230557Sjimharris      // we have a spurious interrupt it could be that we have already
3024230557Sjimharris      // emptied the completion queue from a previous interrupt
3025230557Sjimharris      SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
3026230557Sjimharris
3027230557Sjimharris      // There is a race in the hardware that could cause us not to be notified
3028230557Sjimharris      // of an interrupt completion if we do not take this step.  We will mask
3029230557Sjimharris      // then unmask the interrupts so if there is another interrupt pending
3030230557Sjimharris      // the clearing of the interrupt source we get the next interrupt message.
3031230557Sjimharris      SMU_IMR_WRITE(this_controller, 0xFF000000);
3032230557Sjimharris      SMU_IMR_WRITE(this_controller, 0x00000000);
3033230557Sjimharris   }
3034230557Sjimharris
3035230557Sjimharris   return FALSE;
3036230557Sjimharris}
3037230557Sjimharris
3038230557Sjimharris/**
3039230557Sjimharris * @brief This is the method provided to handle the completions for a
3040230557Sjimharris *        normal MSIX message.
3041230557Sjimharris *
3042230557Sjimharris * @param[in] controller
3043230557Sjimharris */
3044230557Sjimharrisstatic
3045230557Sjimharrisvoid scic_sds_controller_normal_vector_completion_handler(
3046230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
3047230557Sjimharris)
3048230557Sjimharris{
3049230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
3050230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3051230557Sjimharris
3052230557Sjimharris   SCIC_LOG_TRACE((
3053230557Sjimharris      sci_base_object_get_logger(controller),
3054230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
3055230557Sjimharris      "scic_sds_controller_normal_vector_completion_handler(0x%d) enter\n",
3056230557Sjimharris      controller
3057230557Sjimharris   ));
3058230557Sjimharris
3059230557Sjimharris   // Empty out the completion queue
3060230557Sjimharris   if (scic_sds_controller_completion_queue_has_entries(this_controller))
3061230557Sjimharris   {
3062230557Sjimharris      scic_sds_controller_process_completions(this_controller);
3063230557Sjimharris   }
3064230557Sjimharris
3065230557Sjimharris   // Clear the interrupt and enable all interrupts again
3066230557Sjimharris   SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
3067230557Sjimharris   // Could we write the value of SMU_ISR_COMPLETION?
3068230557Sjimharris   SMU_IMR_WRITE(this_controller, 0xFF000000);
3069230557Sjimharris   SMU_IMR_WRITE(this_controller, 0x00000000);
3070230557Sjimharris}
3071230557Sjimharris
3072230557Sjimharris/**
3073230557Sjimharris * @brief This is the method provided to handle the error MSIX message
3074230557Sjimharris *        interrupt.  This is the normal operating mode for the hardware if
3075230557Sjimharris *        MSIX is enabled.
3076230557Sjimharris *
3077230557Sjimharris * @param[in] controller
3078230557Sjimharris *
3079230557Sjimharris * @return BOOL
3080230557Sjimharris * @retval TRUE if an interrupt is processed
3081230557Sjimharris *         FALSE if no interrupt was processed
3082230557Sjimharris */
3083230557Sjimharrisstatic
3084230557SjimharrisBOOL scic_sds_controller_error_vector_interrupt_handler(
3085230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
3086230557Sjimharris)
3087230557Sjimharris{
3088230557Sjimharris   U32 interrupt_status;
3089230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
3090230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3091230557Sjimharris
3092230557Sjimharris
3093230557Sjimharris   interrupt_status = SMU_ISR_READ(this_controller);
3094230557Sjimharris   interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
3095230557Sjimharris
3096230557Sjimharris   if (interrupt_status != 0)
3097230557Sjimharris   {
3098230557Sjimharris      // There is an error interrupt pending so let it through and handle
3099230557Sjimharris      // in the callback
3100230557Sjimharris      return TRUE;
3101230557Sjimharris   }
3102230557Sjimharris
3103230557Sjimharris   // There is a race in the hardware that could cause us not to be notified
3104230557Sjimharris   // of an interrupt completion if we do not take this step.  We will mask
3105230557Sjimharris   // then unmask the error interrupts so if there was another interrupt
3106230557Sjimharris   // pending we will be notified.
3107230557Sjimharris   // Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)?
3108230557Sjimharris   SMU_IMR_WRITE(this_controller, 0x000000FF);
3109230557Sjimharris   SMU_IMR_WRITE(this_controller, 0x00000000);
3110230557Sjimharris
3111230557Sjimharris   return FALSE;
3112230557Sjimharris}
3113230557Sjimharris
3114230557Sjimharris/**
3115230557Sjimharris * @brief This is the method provided to handle the error completions when
3116230557Sjimharris *        the hardware is using two MSIX messages.
3117230557Sjimharris *
3118230557Sjimharris * @param[in] controller
3119230557Sjimharris */
3120230557Sjimharrisstatic
3121230557Sjimharrisvoid scic_sds_controller_error_vector_completion_handler(
3122230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
3123230557Sjimharris)
3124230557Sjimharris{
3125230557Sjimharris   U32 interrupt_status;
3126230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
3127230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3128230557Sjimharris
3129230557Sjimharris   SCIC_LOG_TRACE((
3130230557Sjimharris      sci_base_object_get_logger(controller),
3131230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
3132230557Sjimharris      "scic_sds_controller_error_vector_completion_handler(0x%d) enter\n",
3133230557Sjimharris      controller
3134230557Sjimharris   ));
3135230557Sjimharris
3136230557Sjimharris   interrupt_status = SMU_ISR_READ(this_controller);
3137230557Sjimharris
3138230557Sjimharris   if (
3139230557Sjimharris            (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
3140230557Sjimharris         && scic_sds_controller_completion_queue_has_entries(this_controller)
3141230557Sjimharris      )
3142230557Sjimharris   {
3143230557Sjimharris      scic_sds_controller_process_completions(this_controller);
3144230557Sjimharris
3145230557Sjimharris      SMU_ISR_WRITE(this_controller, SMU_ISR_QUEUE_SUSPEND);
3146230557Sjimharris   }
3147230557Sjimharris   else
3148230557Sjimharris   {
3149230557Sjimharris      SCIC_LOG_ERROR((
3150230557Sjimharris         sci_base_object_get_logger(this_controller),
3151230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
3152230557Sjimharris         "SCIC Controller reports CRC error on completion ISR %x\n",
3153230557Sjimharris         interrupt_status
3154230557Sjimharris      ));
3155230557Sjimharris
3156230557Sjimharris      sci_base_state_machine_change_state(
3157230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller),
3158230557Sjimharris         SCI_BASE_CONTROLLER_STATE_FAILED
3159230557Sjimharris      );
3160230557Sjimharris
3161230557Sjimharris      return;
3162230557Sjimharris   }
3163230557Sjimharris
3164230557Sjimharris   // If we dont process any completions I am not sure that we want to do this.
3165230557Sjimharris   // We are in the middle of a hardware fault and should probably be reset.
3166230557Sjimharris   SMU_IMR_WRITE(this_controller, 0x00000000);
3167230557Sjimharris}
3168230557Sjimharris
3169230557Sjimharris#endif // !defined(DISABLE_INTERRUPTS)
3170230557Sjimharris
3171230557Sjimharris//****************************************************************************-
3172230557Sjimharris//* SCIC SDS Controller External Methods
3173230557Sjimharris//****************************************************************************-
3174230557Sjimharris
3175230557Sjimharris/**
3176230557Sjimharris * @brief This method returns the sizeof the SCIC SDS Controller Object
3177230557Sjimharris *
3178230557Sjimharris * @return U32
3179230557Sjimharris */
3180230557SjimharrisU32 scic_sds_controller_get_object_size(void)
3181230557Sjimharris{
3182230557Sjimharris   return sizeof(SCIC_SDS_CONTROLLER_T);
3183230557Sjimharris}
3184230557Sjimharris
3185230557Sjimharris/**
3186230557Sjimharris * This method returns the minimum number of timers that are required by the
3187230557Sjimharris * controller object.  This will include required timers for phys and ports.
3188230557Sjimharris *
3189230557Sjimharris * @return U32
3190230557Sjimharris * @retval The minimum number of timers that are required to make this
3191230557Sjimharris *         controller operational.
3192230557Sjimharris */
3193230557SjimharrisU32 scic_sds_controller_get_min_timer_count(void)
3194230557Sjimharris{
3195230557Sjimharris   return   SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT
3196230557Sjimharris          + scic_sds_port_get_min_timer_count()
3197230557Sjimharris          + scic_sds_phy_get_min_timer_count();
3198230557Sjimharris}
3199230557Sjimharris
3200230557Sjimharris/**
3201230557Sjimharris * This method returns the maximum number of timers that are required by the
3202230557Sjimharris * controller object.  This will include required timers for phys and ports.
3203230557Sjimharris *
3204230557Sjimharris * @return U32
3205230557Sjimharris * @retval The maximum number of timers that will be used by the controller
3206230557Sjimharris *         object
3207230557Sjimharris */
3208230557SjimharrisU32 scic_sds_controller_get_max_timer_count(void)
3209230557Sjimharris{
3210230557Sjimharris   return   SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT
3211230557Sjimharris          + scic_sds_port_get_max_timer_count()
3212230557Sjimharris          + scic_sds_phy_get_max_timer_count();
3213230557Sjimharris}
3214230557Sjimharris
3215230557Sjimharris/**
3216230557Sjimharris * @brief
3217230557Sjimharris *
3218230557Sjimharris * @param[in] this_controller
3219230557Sjimharris * @param[in] the_port
3220230557Sjimharris * @param[in] the_phy
3221230557Sjimharris *
3222230557Sjimharris * @return none
3223230557Sjimharris */
3224230557Sjimharrisvoid scic_sds_controller_link_up(
3225230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
3226230557Sjimharris   SCIC_SDS_PORT_T       *the_port,
3227230557Sjimharris   SCIC_SDS_PHY_T        *the_phy
3228230557Sjimharris)
3229230557Sjimharris{
3230230557Sjimharris   if (this_controller->state_handlers->link_up_handler != NULL)
3231230557Sjimharris   {
3232230557Sjimharris      this_controller->state_handlers->link_up_handler(
3233230557Sjimharris         this_controller, the_port, the_phy);
3234230557Sjimharris   }
3235230557Sjimharris   else
3236230557Sjimharris   {
3237230557Sjimharris      SCIC_LOG_INFO((
3238230557Sjimharris         sci_base_object_get_logger(this_controller),
3239230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
3240230557Sjimharris         "SCIC Controller linkup event from phy %d in unexpected state %d\n",
3241230557Sjimharris         the_phy->phy_index,
3242230557Sjimharris         sci_base_state_machine_get_state(
3243230557Sjimharris            scic_sds_controller_get_base_state_machine(this_controller))
3244230557Sjimharris      ));
3245230557Sjimharris   }
3246230557Sjimharris}
3247230557Sjimharris
3248230557Sjimharris/**
3249230557Sjimharris * @brief
3250230557Sjimharris *
3251230557Sjimharris * @param[in] this_controller
3252230557Sjimharris * @param[in] the_port
3253230557Sjimharris * @param[in] the_phy
3254230557Sjimharris */
3255230557Sjimharrisvoid scic_sds_controller_link_down(
3256230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
3257230557Sjimharris   SCIC_SDS_PORT_T       *the_port,
3258230557Sjimharris   SCIC_SDS_PHY_T        *the_phy
3259230557Sjimharris)
3260230557Sjimharris{
3261230557Sjimharris   if (this_controller->state_handlers->link_down_handler != NULL)
3262230557Sjimharris   {
3263230557Sjimharris      this_controller->state_handlers->link_down_handler(
3264230557Sjimharris         this_controller, the_port, the_phy);
3265230557Sjimharris   }
3266230557Sjimharris   else
3267230557Sjimharris   {
3268230557Sjimharris      SCIC_LOG_INFO((
3269230557Sjimharris         sci_base_object_get_logger(this_controller),
3270230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
3271230557Sjimharris         "SCIC Controller linkdown event from phy %d in unexpected state %d\n",
3272230557Sjimharris         the_phy->phy_index,
3273230557Sjimharris         sci_base_state_machine_get_state(
3274230557Sjimharris            scic_sds_controller_get_base_state_machine(this_controller))
3275230557Sjimharris      ));
3276230557Sjimharris   }
3277230557Sjimharris}
3278230557Sjimharris
3279230557Sjimharris/**
3280230557Sjimharris * @brief This method is called by the remote device to inform the controller
3281230557Sjimharris *        that this remote device has started.
3282230557Sjimharris *
3283230557Sjimharris * @param[in] this_controller
3284230557Sjimharris * @param[in] the_device
3285230557Sjimharris */
3286230557Sjimharrisvoid scic_sds_controller_remote_device_started(
3287230557Sjimharris   SCIC_SDS_CONTROLLER_T    * this_controller,
3288230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T * the_device
3289230557Sjimharris)
3290230557Sjimharris{
3291230557Sjimharris   if (this_controller->state_handlers->remote_device_started_handler != NULL)
3292230557Sjimharris   {
3293230557Sjimharris      this_controller->state_handlers->remote_device_started_handler(
3294230557Sjimharris         this_controller, the_device
3295230557Sjimharris      );
3296230557Sjimharris   }
3297230557Sjimharris   else
3298230557Sjimharris   {
3299230557Sjimharris      SCIC_LOG_INFO((
3300230557Sjimharris         sci_base_object_get_logger(this_controller),
3301230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
3302230557Sjimharris         "SCIC Controller 0x%x remote device started event from device 0x%x in unexpected state %d\n",
3303230557Sjimharris         this_controller,
3304230557Sjimharris         the_device,
3305230557Sjimharris         sci_base_state_machine_get_state(
3306230557Sjimharris            scic_sds_controller_get_base_state_machine(this_controller))
3307230557Sjimharris      ));
3308230557Sjimharris   }
3309230557Sjimharris}
3310230557Sjimharris
3311230557Sjimharris/**
3312230557Sjimharris * @brief This is a helper method to determine if any remote devices on this
3313230557Sjimharris *        controller are still in the stopping state.
3314230557Sjimharris *
3315230557Sjimharris * @param[in] this_controller
3316230557Sjimharris */
3317230557SjimharrisBOOL scic_sds_controller_has_remote_devices_stopping(
3318230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller
3319230557Sjimharris)
3320230557Sjimharris{
3321230557Sjimharris   U32 index;
3322230557Sjimharris
3323230557Sjimharris   for (index = 0; index < this_controller->remote_node_entries; index++)
3324230557Sjimharris   {
3325230557Sjimharris      if (
3326230557Sjimharris            (this_controller->device_table[index] != NULL)
3327230557Sjimharris         && (
3328230557Sjimharris               this_controller->device_table[index]->parent.state_machine.current_state_id
3329230557Sjimharris            == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
3330230557Sjimharris            )
3331230557Sjimharris         )
3332230557Sjimharris      {
3333230557Sjimharris         return TRUE;
3334230557Sjimharris      }
3335230557Sjimharris   }
3336230557Sjimharris
3337230557Sjimharris   return FALSE;
3338230557Sjimharris}
3339230557Sjimharris
3340230557Sjimharris/**
3341230557Sjimharris * @brief This method is called by the remote device to inform the controller
3342230557Sjimharris *        object that the remote device has stopped.
3343230557Sjimharris *
3344230557Sjimharris * @param[in] this_controller
3345230557Sjimharris * @param[in] the_device
3346230557Sjimharris */
3347230557Sjimharrisvoid scic_sds_controller_remote_device_stopped(
3348230557Sjimharris   SCIC_SDS_CONTROLLER_T    * this_controller,
3349230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T * the_device
3350230557Sjimharris)
3351230557Sjimharris{
3352230557Sjimharris   if (this_controller->state_handlers->remote_device_stopped_handler != NULL)
3353230557Sjimharris   {
3354230557Sjimharris      this_controller->state_handlers->remote_device_stopped_handler(
3355230557Sjimharris         this_controller, the_device
3356230557Sjimharris      );
3357230557Sjimharris   }
3358230557Sjimharris   else
3359230557Sjimharris   {
3360230557Sjimharris      SCIC_LOG_INFO((
3361230557Sjimharris         sci_base_object_get_logger(this_controller),
3362230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
3363230557Sjimharris         "SCIC Controller 0x%x remote device stopped event from device 0x%x in unexpected state %d\n",
3364230557Sjimharris         this_controller,
3365230557Sjimharris         the_device,
3366230557Sjimharris         sci_base_state_machine_get_state(
3367230557Sjimharris            scic_sds_controller_get_base_state_machine(this_controller))
3368230557Sjimharris      ));
3369230557Sjimharris   }
3370230557Sjimharris}
3371230557Sjimharris
3372230557Sjimharris/**
3373230557Sjimharris * @brief This method will write to the SCU PCP register the request value.
3374230557Sjimharris *        The method is used to suspend/resume ports, devices, and phys.
3375230557Sjimharris *
3376230557Sjimharris * @param[in] this_controller
3377230557Sjimharris * @param[in] request
3378230557Sjimharris */
3379230557Sjimharrisvoid scic_sds_controller_post_request(
3380230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
3381230557Sjimharris   U32                    request
3382230557Sjimharris)
3383230557Sjimharris{
3384230557Sjimharris   SCIC_LOG_INFO((
3385230557Sjimharris      sci_base_object_get_logger(this_controller),
3386230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_COMPLETION_QUEUE,
3387230557Sjimharris      "SCIC Controller 0x%08x post request 0x%08x\n",
3388230557Sjimharris      this_controller, request
3389230557Sjimharris   ));
3390230557Sjimharris
3391230557Sjimharris   SMU_PCP_WRITE(this_controller, request);
3392230557Sjimharris}
3393230557Sjimharris
3394230557Sjimharris/**
3395230557Sjimharris * @brief This method will copy the soft copy of the task context into
3396230557Sjimharris *        the physical memory accessible by the controller.
3397230557Sjimharris *
3398230557Sjimharris * @note After this call is made the SCIC_SDS_IO_REQUEST object will
3399230557Sjimharris *       always point to the physical memory version of the task context.
3400230557Sjimharris *       Thus, all subsequent updates to the task context are performed in
3401230557Sjimharris *       the TC table (i.e. DMAable memory).
3402230557Sjimharris *
3403230557Sjimharris * @param[in]  this_controller This parameter specifies the controller for
3404230557Sjimharris *             which to copy the task context.
3405230557Sjimharris * @param[in]  this_request This parameter specifies the request for which
3406230557Sjimharris *             the task context is being copied.
3407230557Sjimharris *
3408230557Sjimharris * @return none
3409230557Sjimharris */
3410230557Sjimharrisvoid scic_sds_controller_copy_task_context(
3411230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
3412230557Sjimharris   SCIC_SDS_REQUEST_T    *this_request
3413230557Sjimharris)
3414230557Sjimharris{
3415230557Sjimharris   SCU_TASK_CONTEXT_T *task_context_buffer;
3416230557Sjimharris
3417230557Sjimharris   task_context_buffer = scic_sds_controller_get_task_context_buffer(
3418230557Sjimharris                            this_controller, this_request->io_tag
3419230557Sjimharris                         );
3420230557Sjimharris
3421230557Sjimharris   memcpy(
3422230557Sjimharris      task_context_buffer,
3423230557Sjimharris      this_request->task_context_buffer,
3424230557Sjimharris      SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, sgl_snapshot_ac)
3425230557Sjimharris   );
3426230557Sjimharris
3427230557Sjimharris   // Now that the soft copy of the TC has been copied into the TC
3428230557Sjimharris   // table accessible by the silicon.  Thus, any further changes to
3429230557Sjimharris   // the TC (e.g. TC termination) occur in the appropriate location.
3430230557Sjimharris   this_request->task_context_buffer = task_context_buffer;
3431230557Sjimharris}
3432230557Sjimharris
3433230557Sjimharris/**
3434230557Sjimharris * @brief This method returns the task context buffer for the given io tag.
3435230557Sjimharris *
3436230557Sjimharris * @param[in] this_controller
3437230557Sjimharris * @param[in] io_tag
3438230557Sjimharris *
3439230557Sjimharris * @return struct SCU_TASK_CONTEXT*
3440230557Sjimharris */
3441230557SjimharrisSCU_TASK_CONTEXT_T * scic_sds_controller_get_task_context_buffer(
3442230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller,
3443230557Sjimharris   U16                     io_tag
3444230557Sjimharris)
3445230557Sjimharris{
3446230557Sjimharris   U16 task_index = scic_sds_io_tag_get_index(io_tag);
3447230557Sjimharris
3448230557Sjimharris   if (task_index < this_controller->task_context_entries)
3449230557Sjimharris   {
3450230557Sjimharris      return &this_controller->task_context_table[task_index];
3451230557Sjimharris   }
3452230557Sjimharris
3453230557Sjimharris   return NULL;
3454230557Sjimharris}
3455230557Sjimharris
3456230557Sjimharris/**
3457230557Sjimharris * @brief This method returnst the sequence value from the io tag value
3458230557Sjimharris *
3459230557Sjimharris * @param[in] this_controller
3460230557Sjimharris * @param[in] io_tag
3461230557Sjimharris *
3462230557Sjimharris * @return U16
3463230557Sjimharris */
3464230557SjimharrisU16 scic_sds_controller_get_io_sequence_from_tag(
3465230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
3466230557Sjimharris   U16                    io_tag
3467230557Sjimharris)
3468230557Sjimharris{
3469230557Sjimharris   return scic_sds_io_tag_get_sequence(io_tag);
3470230557Sjimharris}
3471230557Sjimharris
3472230557Sjimharris/**
3473230557Sjimharris * @brief This method returns the IO request associated with the tag value
3474230557Sjimharris *
3475230557Sjimharris * @param[in] this_controller
3476230557Sjimharris * @param[in] io_tag
3477230557Sjimharris *
3478230557Sjimharris * @return SCIC_SDS_IO_REQUEST_T*
3479230557Sjimharris * @retval NULL if there is no valid IO request at the tag value
3480230557Sjimharris */
3481230557SjimharrisSCIC_SDS_REQUEST_T *scic_sds_controller_get_io_request_from_tag(
3482230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
3483230557Sjimharris   U16                    io_tag
3484230557Sjimharris)
3485230557Sjimharris{
3486230557Sjimharris   U16 task_index;
3487230557Sjimharris   U16 task_sequence;
3488230557Sjimharris
3489230557Sjimharris   task_index = scic_sds_io_tag_get_index(io_tag);
3490230557Sjimharris
3491230557Sjimharris   if (task_index  < this_controller->task_context_entries)
3492230557Sjimharris   {
3493230557Sjimharris      if (this_controller->io_request_table[task_index] != SCI_INVALID_HANDLE)
3494230557Sjimharris      {
3495230557Sjimharris         task_sequence = scic_sds_io_tag_get_sequence(io_tag);
3496230557Sjimharris
3497230557Sjimharris         if (task_sequence == this_controller->io_request_sequence[task_index])
3498230557Sjimharris         {
3499230557Sjimharris            return this_controller->io_request_table[task_index];
3500230557Sjimharris         }
3501230557Sjimharris      }
3502230557Sjimharris   }
3503230557Sjimharris
3504230557Sjimharris   return SCI_INVALID_HANDLE;
3505230557Sjimharris}
3506230557Sjimharris
3507230557Sjimharris/**
3508230557Sjimharris * @brief This method allocates remote node index and the reserves the
3509230557Sjimharris *        remote node context space for use. This method can fail if there
3510230557Sjimharris *        are no more remote node index available.
3511230557Sjimharris *
3512230557Sjimharris * @param[in] this_controller This is the controller object which contains
3513230557Sjimharris *            the set of free remote node ids
3514230557Sjimharris * @param[in] the_devce This is the device object which is requesting the a
3515230557Sjimharris *            remote node id
3516230557Sjimharris * @param[out] node_id This is the remote node id that is assinged to the
3517230557Sjimharris *             device if one is available
3518230557Sjimharris *
3519230557Sjimharris * @return SCI_STATUS
3520230557Sjimharris * @retval SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote
3521230557Sjimharris *         node index available.
3522230557Sjimharris */
3523230557SjimharrisSCI_STATUS scic_sds_controller_allocate_remote_node_context(
3524230557Sjimharris   SCIC_SDS_CONTROLLER_T    * this_controller,
3525230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T * the_device,
3526230557Sjimharris   U16                      * node_id
3527230557Sjimharris)
3528230557Sjimharris{
3529230557Sjimharris   U16 node_index;
3530230557Sjimharris   U32 remote_node_count = scic_sds_remote_device_node_count(the_device);
3531230557Sjimharris
3532230557Sjimharris   node_index = scic_sds_remote_node_table_allocate_remote_node(
3533230557Sjimharris                  &this_controller->available_remote_nodes, remote_node_count
3534230557Sjimharris              );
3535230557Sjimharris
3536230557Sjimharris   if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
3537230557Sjimharris   {
3538230557Sjimharris      this_controller->device_table[node_index] = the_device;
3539230557Sjimharris
3540230557Sjimharris      *node_id = node_index;
3541230557Sjimharris
3542230557Sjimharris      return SCI_SUCCESS;
3543230557Sjimharris   }
3544230557Sjimharris
3545230557Sjimharris   return SCI_FAILURE_INSUFFICIENT_RESOURCES;
3546230557Sjimharris}
3547230557Sjimharris
3548230557Sjimharris/**
3549230557Sjimharris * @brief This method frees the remote node index back to the available
3550230557Sjimharris *        pool.  Once this is done the remote node context buffer is no
3551230557Sjimharris *        longer valid and can not be used.
3552230557Sjimharris *
3553230557Sjimharris * @param[in] this_controller
3554230557Sjimharris * @param[in] the_device
3555230557Sjimharris * @param[in] node_id
3556230557Sjimharris *
3557230557Sjimharris * @return none
3558230557Sjimharris */
3559230557Sjimharrisvoid scic_sds_controller_free_remote_node_context(
3560230557Sjimharris   SCIC_SDS_CONTROLLER_T    * this_controller,
3561230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T * the_device,
3562230557Sjimharris   U16                        node_id
3563230557Sjimharris)
3564230557Sjimharris{
3565230557Sjimharris   U32 remote_node_count = scic_sds_remote_device_node_count(the_device);
3566230557Sjimharris
3567230557Sjimharris   if (this_controller->device_table[node_id] == the_device)
3568230557Sjimharris   {
3569230557Sjimharris      this_controller->device_table[node_id] = SCI_INVALID_HANDLE;
3570230557Sjimharris
3571230557Sjimharris      scic_sds_remote_node_table_release_remote_node_index(
3572230557Sjimharris         &this_controller->available_remote_nodes, remote_node_count, node_id
3573230557Sjimharris      );
3574230557Sjimharris   }
3575230557Sjimharris}
3576230557Sjimharris
3577230557Sjimharris/**
3578230557Sjimharris * @brief This method returns the SCU_REMOTE_NODE_CONTEXT for the specified
3579230557Sjimharris *        remote node id.
3580230557Sjimharris *
3581230557Sjimharris * @param[in] this_controller
3582230557Sjimharris * @param[in] node_id
3583230557Sjimharris *
3584230557Sjimharris * @return SCU_REMOTE_NODE_CONTEXT_T*
3585230557Sjimharris */
3586230557SjimharrisSCU_REMOTE_NODE_CONTEXT_T *scic_sds_controller_get_remote_node_context_buffer(
3587230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
3588230557Sjimharris   U16                    node_id
3589230557Sjimharris)
3590230557Sjimharris{
3591230557Sjimharris   if (
3592230557Sjimharris           (node_id < this_controller->remote_node_entries)
3593230557Sjimharris        && (this_controller->device_table[node_id] != SCI_INVALID_HANDLE)
3594230557Sjimharris      )
3595230557Sjimharris   {
3596230557Sjimharris      return &this_controller->remote_node_context_table[node_id];
3597230557Sjimharris   }
3598230557Sjimharris
3599230557Sjimharris   return NULL;
3600230557Sjimharris}
3601230557Sjimharris
3602230557Sjimharris/**
3603230557Sjimharris * This method will combind the frame header and frame buffer to create
3604230557Sjimharris * a SATA D2H register FIS
3605230557Sjimharris *
3606230557Sjimharris * @param[out] resposne_buffer This is the buffer into which the D2H register
3607230557Sjimharris *             FIS will be constructed.
3608230557Sjimharris * @param[in]  frame_header This is the frame header returned by the hardware.
3609230557Sjimharris * @param[in]  frame_buffer This is the frame buffer returned by the hardware.
3610230557Sjimharris *
3611230557Sjimharris * @erturn none
3612230557Sjimharris */
3613230557Sjimharrisvoid scic_sds_controller_copy_sata_response(
3614230557Sjimharris   void * response_buffer,
3615230557Sjimharris   void * frame_header,
3616230557Sjimharris   void * frame_buffer
3617230557Sjimharris)
3618230557Sjimharris{
3619230557Sjimharris   memcpy(
3620230557Sjimharris      response_buffer,
3621230557Sjimharris      frame_header,
3622230557Sjimharris      sizeof(U32)
3623230557Sjimharris   );
3624230557Sjimharris
3625230557Sjimharris   memcpy(
3626230557Sjimharris      (char *)((char *)response_buffer + sizeof(U32)),
3627230557Sjimharris      frame_buffer,
3628230557Sjimharris      sizeof(SATA_FIS_REG_D2H_T) - sizeof(U32)
3629230557Sjimharris   );
3630230557Sjimharris}
3631230557Sjimharris
3632230557Sjimharris/**
3633230557Sjimharris * @brief This method releases the frame once this is done the frame is
3634230557Sjimharris *        available for re-use by the hardware.  The data contained in the
3635230557Sjimharris *        frame header and frame buffer is no longer valid.
3636230557Sjimharris *        The UF queue get pointer is only updated if UF control indicates
3637230557Sjimharris *        this is appropriate.
3638230557Sjimharris *
3639230557Sjimharris * @param[in] this_controller
3640230557Sjimharris * @param[in] frame_index
3641230557Sjimharris *
3642230557Sjimharris * @return none
3643230557Sjimharris */
3644230557Sjimharrisvoid scic_sds_controller_release_frame(
3645230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
3646230557Sjimharris   U32                    frame_index
3647230557Sjimharris)
3648230557Sjimharris{
3649230557Sjimharris   if (scic_sds_unsolicited_frame_control_release_frame(
3650230557Sjimharris          &this_controller->uf_control, frame_index) == TRUE)
3651230557Sjimharris      SCU_UFQGP_WRITE(this_controller, this_controller->uf_control.get);
3652230557Sjimharris}
3653230557Sjimharris
3654230557Sjimharris#ifdef SCI_LOGGING
3655230557Sjimharrisvoid scic_sds_controller_initialize_state_logging(
3656230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
3657230557Sjimharris)
3658230557Sjimharris{
3659230557Sjimharris   sci_base_state_machine_logger_initialize(
3660230557Sjimharris      &this_controller->parent.state_machine_logger,
3661230557Sjimharris      &this_controller->parent.state_machine,
3662230557Sjimharris      &this_controller->parent.parent,
3663230557Sjimharris      scic_cb_logger_log_states,
3664230557Sjimharris      "SCIC_SDS_CONTROLLER_T", "base state machine",
3665230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER
3666230557Sjimharris   );
3667230557Sjimharris}
3668230557Sjimharris
3669230557Sjimharrisvoid scic_sds_controller_deinitialize_state_logging(
3670230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
3671230557Sjimharris)
3672230557Sjimharris{
3673230557Sjimharris   sci_base_state_machine_logger_deinitialize(
3674230557Sjimharris      &this_controller->parent.state_machine_logger,
3675230557Sjimharris      &this_controller->parent.state_machine
3676230557Sjimharris   );
3677230557Sjimharris}
3678230557Sjimharris#endif
3679230557Sjimharris
3680230557Sjimharris/**
3681230557Sjimharris * @brief This method sets user parameters and OEM parameters to
3682230557Sjimharris *        default values.  Users can override these values utilizing
3683230557Sjimharris *        the scic_user_parameters_set() and scic_oem_parameters_set()
3684230557Sjimharris *        methods.
3685230557Sjimharris *
3686230557Sjimharris * @param[in] controller This parameter specifies the controller for
3687230557Sjimharris *            which to set the configuration parameters to their
3688230557Sjimharris *            default values.
3689230557Sjimharris *
3690230557Sjimharris * @return none
3691230557Sjimharris */
3692230557Sjimharrisstatic
3693230557Sjimharrisvoid scic_sds_controller_set_default_config_parameters(
3694230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller
3695230557Sjimharris)
3696230557Sjimharris{
3697230557Sjimharris   U16 index;
3698230557Sjimharris
3699230557Sjimharris   // Default to APC mode.
3700230557Sjimharris   this_controller->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
3701230557Sjimharris
3702230557Sjimharris   // Default to 1
3703230557Sjimharris   this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up = 1;
3704230557Sjimharris
3705230557Sjimharris   // Default to no SSC operation.
3706230557Sjimharris   this_controller->oem_parameters.sds1.controller.ssc_sata_tx_spread_level = 0;
3707230557Sjimharris   this_controller->oem_parameters.sds1.controller.ssc_sas_tx_spread_level  = 0;
3708230557Sjimharris   this_controller->oem_parameters.sds1.controller.ssc_sas_tx_type          = 0;
3709230557Sjimharris
3710230557Sjimharris   // Default to all phys to using short cables
3711230557Sjimharris   this_controller->oem_parameters.sds1.controller.cable_selection_mask = 0;
3712230557Sjimharris
3713230557Sjimharris   // Initialize all of the port parameter information to narrow ports.
3714230557Sjimharris   for (index = 0; index < SCI_MAX_PORTS; index++)
3715230557Sjimharris   {
3716230557Sjimharris      this_controller->oem_parameters.sds1.ports[index].phy_mask = 0;
3717230557Sjimharris   }
3718230557Sjimharris
3719230557Sjimharris   // Initialize all of the phy parameter information.
3720230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
3721230557Sjimharris   {
3722230557Sjimharris      // Default to 6G (i.e. Gen 3) for now.  User can override if
3723230557Sjimharris      // they choose.
3724230557Sjimharris      this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2;
3725230557Sjimharris
3726230557Sjimharris      //the frequencies cannot be 0
3727230557Sjimharris      this_controller->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f;
3728230557Sjimharris      this_controller->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff;
3729230557Sjimharris      this_controller->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33;
3730230557Sjimharris
3731230557Sjimharris      // Previous Vitesse based expanders had a arbitration issue that
3732230557Sjimharris      // is worked around by having the upper 32-bits of SAS address
3733230557Sjimharris      // with a value greater then the Vitesse company identifier.
3734230557Sjimharris      // Hence, usage of 0x5FCFFFFF.
3735230557Sjimharris      this_controller->oem_parameters.sds1.phys[index].sas_address.sci_format.high
3736230557Sjimharris         = 0x5FCFFFFF;
3737230557Sjimharris
3738230557Sjimharris      // Add in controller index to ensure each controller will have unique SAS addresses by default.
3739230557Sjimharris      this_controller->oem_parameters.sds1.phys[index].sas_address.sci_format.low
3740230557Sjimharris         = 0x00000001 + this_controller->controller_index;
3741230557Sjimharris
3742230557Sjimharris      if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
3743230557Sjimharris         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
3744230557Sjimharris         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0) )
3745230557Sjimharris      {
3746230557Sjimharris         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control0 = 0x000E7C03;
3747230557Sjimharris         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control1 = 0x000E7C03;
3748230557Sjimharris         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control2 = 0x000E7C03;
3749230557Sjimharris         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control3 = 0x000E7C03;
3750230557Sjimharris      }
3751230557Sjimharris      else // This must be SCIC_SDS_PCI_REVISION_C0
3752230557Sjimharris      {
3753230557Sjimharris         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control0 = 0x000BDD08;
3754230557Sjimharris         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control1 = 0x000B7069;
3755230557Sjimharris         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control2 = 0x000B7C09;
3756230557Sjimharris         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control3 = 0x000AFC6E;
3757230557Sjimharris      }
3758230557Sjimharris   }
3759230557Sjimharris
3760230557Sjimharris   this_controller->user_parameters.sds1.stp_inactivity_timeout = 5;
3761230557Sjimharris   this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5;
3762230557Sjimharris   this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5;
3763230557Sjimharris   this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20;
3764230557Sjimharris   this_controller->user_parameters.sds1.no_outbound_task_timeout = 20;
3765230557Sjimharris
3766230557Sjimharris}
3767230557Sjimharris
3768230557Sjimharris
3769230557Sjimharris/**
3770230557Sjimharris * @brief This method release resources in SCI controller.
3771230557Sjimharris *
3772230557Sjimharris * @param[in] this_controller This parameter specifies the core
3773230557Sjimharris *            controller and associated objects whose resources are to be
3774230557Sjimharris *            released.
3775230557Sjimharris *
3776230557Sjimharris * @return This method returns a value indicating if the operation succeeded.
3777230557Sjimharris * @retval SCI_SUCCESS This value indicates that all the timers are destroyed.
3778230557Sjimharris * @retval SCI_FAILURE This value indicates certain failure during the process
3779230557Sjimharris *            of cleaning timer resource.
3780230557Sjimharris */
3781230557Sjimharrisstatic
3782230557SjimharrisSCI_STATUS scic_sds_controller_release_resource(
3783230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller
3784230557Sjimharris)
3785230557Sjimharris{
3786230557Sjimharris   SCIC_SDS_PORT_T * port;
3787230557Sjimharris   SCIC_SDS_PHY_T * phy;
3788230557Sjimharris   U8 index;
3789230557Sjimharris
3790230557Sjimharris   SCIC_LOG_TRACE((
3791230557Sjimharris      sci_base_object_get_logger(this_controller),
3792230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
3793230557Sjimharris      "scic_sds_controller_release_resource(0x%x) enter\n",
3794230557Sjimharris      this_controller
3795230557Sjimharris   ));
3796230557Sjimharris
3797230557Sjimharris   if(this_controller->phy_startup_timer != NULL)
3798230557Sjimharris   {
3799230557Sjimharris      scic_cb_timer_destroy(this_controller, this_controller->phy_startup_timer);
3800230557Sjimharris      this_controller->phy_startup_timer = NULL;
3801230557Sjimharris   }
3802230557Sjimharris
3803230557Sjimharris   if(this_controller->power_control.timer != NULL)
3804230557Sjimharris   {
3805230557Sjimharris      scic_cb_timer_destroy(this_controller, this_controller->power_control.timer);
3806230557Sjimharris      this_controller->power_control.timer = NULL;
3807230557Sjimharris   }
3808230557Sjimharris
3809230557Sjimharris   if(this_controller->timeout_timer != NULL)
3810230557Sjimharris   {
3811230557Sjimharris      scic_cb_timer_destroy(this_controller, this_controller->timeout_timer);
3812230557Sjimharris      this_controller->timeout_timer = NULL;
3813230557Sjimharris   }
3814230557Sjimharris
3815230557Sjimharris   scic_sds_port_configuration_agent_release_resource(
3816230557Sjimharris      this_controller,
3817230557Sjimharris      &this_controller->port_agent);
3818230557Sjimharris
3819230557Sjimharris   for(index = 0; index < SCI_MAX_PORTS+1; index++)
3820230557Sjimharris   {
3821230557Sjimharris      port = &this_controller->port_table[index];
3822230557Sjimharris      scic_sds_port_release_resource(this_controller, port);
3823230557Sjimharris   }
3824230557Sjimharris
3825230557Sjimharris   for(index = 0; index < SCI_MAX_PHYS; index++)
3826230557Sjimharris   {
3827230557Sjimharris      phy = &this_controller->phy_table[index];
3828230557Sjimharris      scic_sds_phy_release_resource(this_controller, phy);
3829230557Sjimharris   }
3830230557Sjimharris
3831230557Sjimharris   return SCI_SUCCESS;
3832230557Sjimharris}
3833230557Sjimharris
3834230557Sjimharris
3835230557Sjimharris/**
3836230557Sjimharris * @brief This method process the ports configured message from port configuration
3837230557Sjimharris *           agent.
3838230557Sjimharris *
3839230557Sjimharris * @param[in] this_controller This parameter specifies the core
3840230557Sjimharris *            controller that its ports are configured.
3841230557Sjimharris *
3842230557Sjimharris * @return None.
3843230557Sjimharris */
3844230557Sjimharrisvoid scic_sds_controller_port_agent_configured_ports(
3845230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller
3846230557Sjimharris)
3847230557Sjimharris{
3848230557Sjimharris   //simply transit to ready. The function below checks the controller state
3849230557Sjimharris   scic_sds_controller_transition_to_ready(
3850230557Sjimharris      this_controller, SCI_SUCCESS
3851230557Sjimharris   );
3852230557Sjimharris}
3853230557Sjimharris
3854230557Sjimharris
3855230557Sjimharris//****************************************************************************-
3856230557Sjimharris//* SCIC Controller Public Methods
3857230557Sjimharris//****************************************************************************-
3858230557Sjimharris
3859230557SjimharrisSCI_STATUS scic_controller_construct(
3860230557Sjimharris   SCI_LIBRARY_HANDLE_T    library,
3861230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller,
3862230557Sjimharris   void *                  user_object
3863230557Sjimharris)
3864230557Sjimharris{
3865230557Sjimharris   SCIC_SDS_LIBRARY_T    *my_library;
3866230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
3867230557Sjimharris
3868230557Sjimharris   my_library = (SCIC_SDS_LIBRARY_T *)library;
3869230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3870230557Sjimharris
3871230557Sjimharris   SCIC_LOG_TRACE((
3872230557Sjimharris      sci_base_object_get_logger(library),
3873230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
3874230557Sjimharris      "scic_controller_construct(0x%x, 0x%x) enter\n",
3875230557Sjimharris      library, controller
3876230557Sjimharris   ));
3877230557Sjimharris
3878230557Sjimharris   // Just clear out the memory of the structure to be safe.
3879230557Sjimharris   memset(this_controller, 0, sizeof(SCIC_SDS_CONTROLLER_T));
3880230557Sjimharris
3881230557Sjimharris   // Make sure that the static data is assigned before moving onto the
3882230557Sjimharris   // base constroller construct as this will cause the controller to
3883230557Sjimharris   // enter its initial state and the controller_index and pci_revision
3884230557Sjimharris   // will be required to complete those operations correctly
3885230557Sjimharris   this_controller->controller_index =
3886230557Sjimharris      scic_sds_library_get_controller_index(my_library, this_controller);
3887230557Sjimharris
3888230557Sjimharris   this_controller->pci_revision = my_library->pci_revision;
3889230557Sjimharris
3890230557Sjimharris   sci_base_controller_construct(
3891230557Sjimharris      &this_controller->parent,
3892230557Sjimharris      sci_base_object_get_logger(my_library),
3893230557Sjimharris      scic_sds_controller_state_table,
3894230557Sjimharris      this_controller->memory_descriptors,
3895230557Sjimharris      ARRAY_SIZE(this_controller->memory_descriptors),
3896230557Sjimharris      NULL
3897230557Sjimharris   );
3898230557Sjimharris
3899230557Sjimharris   sci_object_set_association(controller, user_object);
3900230557Sjimharris
3901230557Sjimharris   scic_sds_controller_initialize_state_logging(this_controller);
3902230557Sjimharris
3903230557Sjimharris   scic_sds_pci_bar_initialization(this_controller);
3904230557Sjimharris
3905230557Sjimharris   return SCI_SUCCESS;
3906230557Sjimharris}
3907230557Sjimharris
3908230557Sjimharris// ---------------------------------------------------------------------------
3909230557Sjimharris
3910230557SjimharrisSCI_STATUS scic_controller_initialize(
3911230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller
3912230557Sjimharris)
3913230557Sjimharris{
3914230557Sjimharris   SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
3915230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
3916230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3917230557Sjimharris
3918230557Sjimharris   SCIC_LOG_TRACE((
3919230557Sjimharris      sci_base_object_get_logger(controller),
3920230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
3921230557Sjimharris      "scic_controller_initialize(0x%x, 0x%d) enter\n",
3922230557Sjimharris      controller
3923230557Sjimharris   ));
3924230557Sjimharris
3925230557Sjimharris   if (this_controller->state_handlers->parent.initialize_handler != NULL)
3926230557Sjimharris   {
3927230557Sjimharris      status = this_controller->state_handlers->parent.initialize_handler(
3928230557Sjimharris                  (SCI_BASE_CONTROLLER_T *)controller
3929230557Sjimharris               );
3930230557Sjimharris   }
3931230557Sjimharris   else
3932230557Sjimharris   {
3933230557Sjimharris      SCIC_LOG_WARNING((
3934230557Sjimharris         sci_base_object_get_logger(this_controller),
3935230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
3936230557Sjimharris         "SCIC Controller initialize operation requested in invalid state %d\n",
3937230557Sjimharris         sci_base_state_machine_get_state(
3938230557Sjimharris            scic_sds_controller_get_base_state_machine(this_controller))
3939230557Sjimharris      ));
3940230557Sjimharris   }
3941230557Sjimharris
3942230557Sjimharris   return status;
3943230557Sjimharris}
3944230557Sjimharris
3945230557Sjimharris// ---------------------------------------------------------------------------
3946230557Sjimharris
3947230557SjimharrisU32 scic_controller_get_suggested_start_timeout(
3948230557Sjimharris   SCI_CONTROLLER_HANDLE_T  controller
3949230557Sjimharris)
3950230557Sjimharris{
3951230557Sjimharris   // Validate the user supplied parameters.
3952230557Sjimharris   if (controller == SCI_INVALID_HANDLE)
3953230557Sjimharris      return 0;
3954230557Sjimharris
3955230557Sjimharris   // The suggested minimum timeout value for a controller start operation:
3956230557Sjimharris   //
3957230557Sjimharris   //     Signature FIS Timeout
3958230557Sjimharris   //   + Phy Start Timeout
3959230557Sjimharris   //   + Number of Phy Spin Up Intervals
3960230557Sjimharris   //   ---------------------------------
3961230557Sjimharris   //   Number of milliseconds for the controller start operation.
3962230557Sjimharris   //
3963230557Sjimharris   // NOTE: The number of phy spin up intervals will be equivalent
3964230557Sjimharris   //       to the number of phys divided by the number phys allowed
3965230557Sjimharris   //       per interval - 1 (once OEM parameters are supported).
3966230557Sjimharris   //       Currently we assume only 1 phy per interval.
3967230557Sjimharris
3968230557Sjimharris   return (SCIC_SDS_SIGNATURE_FIS_TIMEOUT
3969230557Sjimharris           + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
3970230557Sjimharris           + ((SCI_MAX_PHYS-1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL));
3971230557Sjimharris}
3972230557Sjimharris
3973230557Sjimharris// ---------------------------------------------------------------------------
3974230557Sjimharris
3975230557SjimharrisSCI_STATUS scic_controller_start(
3976230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller,
3977230557Sjimharris   U32 timeout
3978230557Sjimharris)
3979230557Sjimharris{
3980230557Sjimharris   SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
3981230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
3982230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3983230557Sjimharris
3984230557Sjimharris   SCIC_LOG_TRACE((
3985230557Sjimharris      sci_base_object_get_logger(controller),
3986230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
3987230557Sjimharris      "scic_controller_start(0x%x, 0x%d) enter\n",
3988230557Sjimharris      controller, timeout
3989230557Sjimharris   ));
3990230557Sjimharris
3991230557Sjimharris   if (this_controller->state_handlers->parent.start_handler != NULL)
3992230557Sjimharris   {
3993230557Sjimharris      status = this_controller->state_handlers->parent.start_handler(
3994230557Sjimharris                  (SCI_BASE_CONTROLLER_T *)controller, timeout
3995230557Sjimharris               );
3996230557Sjimharris   }
3997230557Sjimharris   else
3998230557Sjimharris   {
3999230557Sjimharris      SCIC_LOG_WARNING((
4000230557Sjimharris         sci_base_object_get_logger(this_controller),
4001230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
4002230557Sjimharris         "SCIC Controller start operation requested in invalid state %d\n",
4003230557Sjimharris         sci_base_state_machine_get_state(
4004230557Sjimharris            scic_sds_controller_get_base_state_machine(this_controller))
4005230557Sjimharris      ));
4006230557Sjimharris   }
4007230557Sjimharris
4008230557Sjimharris   return status;
4009230557Sjimharris}
4010230557Sjimharris
4011230557Sjimharris// ---------------------------------------------------------------------------
4012230557Sjimharris
4013230557SjimharrisSCI_STATUS scic_controller_stop(
4014230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller,
4015230557Sjimharris   U32 timeout
4016230557Sjimharris)
4017230557Sjimharris{
4018230557Sjimharris   SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4019230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4020230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4021230557Sjimharris
4022230557Sjimharris   SCIC_LOG_TRACE((
4023230557Sjimharris      sci_base_object_get_logger(controller),
4024230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4025230557Sjimharris      "scic_controller_stop(0x%x, 0x%d) enter\n",
4026230557Sjimharris      controller, timeout
4027230557Sjimharris   ));
4028230557Sjimharris
4029230557Sjimharris   if (this_controller->state_handlers->parent.stop_handler != NULL)
4030230557Sjimharris   {
4031230557Sjimharris      status = this_controller->state_handlers->parent.stop_handler(
4032230557Sjimharris                  (SCI_BASE_CONTROLLER_T *)controller, timeout
4033230557Sjimharris               );
4034230557Sjimharris   }
4035230557Sjimharris   else
4036230557Sjimharris   {
4037230557Sjimharris      SCIC_LOG_WARNING((
4038230557Sjimharris         sci_base_object_get_logger(this_controller),
4039230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
4040230557Sjimharris         "SCIC Controller stop operation requested in invalid state %d\n",
4041230557Sjimharris         sci_base_state_machine_get_state(
4042230557Sjimharris            scic_sds_controller_get_base_state_machine(this_controller))
4043230557Sjimharris      ));
4044230557Sjimharris   }
4045230557Sjimharris
4046230557Sjimharris   return status;
4047230557Sjimharris}
4048230557Sjimharris
4049230557Sjimharris// ---------------------------------------------------------------------------
4050230557Sjimharris
4051230557SjimharrisSCI_STATUS scic_controller_reset(
4052230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
4053230557Sjimharris)
4054230557Sjimharris{
4055230557Sjimharris   SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4056230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4057230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4058230557Sjimharris
4059230557Sjimharris   SCIC_LOG_TRACE((
4060230557Sjimharris      sci_base_object_get_logger(controller),
4061230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4062230557Sjimharris      "scic_controller_reset(0x%x) enter\n",
4063230557Sjimharris      controller
4064230557Sjimharris   ));
4065230557Sjimharris
4066230557Sjimharris   if (this_controller->state_handlers->parent.reset_handler != NULL)
4067230557Sjimharris   {
4068230557Sjimharris      status = this_controller->state_handlers->parent.reset_handler(
4069230557Sjimharris                  (SCI_BASE_CONTROLLER_T *)controller
4070230557Sjimharris               );
4071230557Sjimharris   }
4072230557Sjimharris   else
4073230557Sjimharris   {
4074230557Sjimharris      SCIC_LOG_WARNING((
4075230557Sjimharris         sci_base_object_get_logger(this_controller),
4076230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
4077230557Sjimharris         "SCIC Controller reset operation requested in invalid state %d\n",
4078230557Sjimharris         sci_base_state_machine_get_state(
4079230557Sjimharris            scic_sds_controller_get_base_state_machine(this_controller))
4080230557Sjimharris      ));
4081230557Sjimharris   }
4082230557Sjimharris
4083230557Sjimharris   return status;
4084230557Sjimharris}
4085230557Sjimharris
4086230557Sjimharris// ---------------------------------------------------------------------------
4087230557Sjimharris
4088230557SjimharrisSCI_STATUS scic_controller_get_handler_methods(
4089230557Sjimharris   SCIC_INTERRUPT_TYPE                interrupt_type,
4090230557Sjimharris   U16                                message_count,
4091230557Sjimharris   SCIC_CONTROLLER_HANDLER_METHODS_T *handler_methods
4092230557Sjimharris)
4093230557Sjimharris{
4094230557Sjimharris   SCI_STATUS status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT;
4095230557Sjimharris
4096230557Sjimharris   switch (interrupt_type)
4097230557Sjimharris   {
4098230557Sjimharris#if !defined(DISABLE_INTERRUPTS)
4099230557Sjimharris   case SCIC_LEGACY_LINE_INTERRUPT_TYPE:
4100230557Sjimharris      if (message_count == 0)
4101230557Sjimharris      {
4102230557Sjimharris         handler_methods[0].interrupt_handler
4103230557Sjimharris            = scic_sds_controller_legacy_interrupt_handler;
4104230557Sjimharris         handler_methods[0].completion_handler
4105230557Sjimharris            = scic_sds_controller_legacy_completion_handler;
4106230557Sjimharris
4107230557Sjimharris         status = SCI_SUCCESS;
4108230557Sjimharris      }
4109230557Sjimharris      break;
4110230557Sjimharris
4111230557Sjimharris   case SCIC_MSIX_INTERRUPT_TYPE:
4112230557Sjimharris      if (message_count == 1)
4113230557Sjimharris      {
4114230557Sjimharris         handler_methods[0].interrupt_handler
4115230557Sjimharris            = scic_sds_controller_single_vector_interrupt_handler;
4116230557Sjimharris         handler_methods[0].completion_handler
4117230557Sjimharris            = scic_sds_controller_single_vector_completion_handler;
4118230557Sjimharris
4119230557Sjimharris         status = SCI_SUCCESS;
4120230557Sjimharris      }
4121230557Sjimharris      else if (message_count == 2)
4122230557Sjimharris      {
4123230557Sjimharris         handler_methods[0].interrupt_handler
4124230557Sjimharris            = scic_sds_controller_normal_vector_interrupt_handler;
4125230557Sjimharris         handler_methods[0].completion_handler
4126230557Sjimharris            = scic_sds_controller_normal_vector_completion_handler;
4127230557Sjimharris
4128230557Sjimharris         handler_methods[1].interrupt_handler
4129230557Sjimharris            = scic_sds_controller_error_vector_interrupt_handler;
4130230557Sjimharris         handler_methods[1].completion_handler
4131230557Sjimharris            = scic_sds_controller_error_vector_completion_handler;
4132230557Sjimharris
4133230557Sjimharris         status = SCI_SUCCESS;
4134230557Sjimharris      }
4135230557Sjimharris      break;
4136230557Sjimharris#endif // !defined(DISABLE_INTERRUPTS)
4137230557Sjimharris
4138230557Sjimharris   case SCIC_NO_INTERRUPTS:
4139230557Sjimharris      if (message_count == 0)
4140230557Sjimharris      {
4141230557Sjimharris
4142230557Sjimharris         handler_methods[0].interrupt_handler
4143230557Sjimharris            = scic_sds_controller_polling_interrupt_handler;
4144230557Sjimharris         handler_methods[0].completion_handler
4145230557Sjimharris            = scic_sds_controller_polling_completion_handler;
4146230557Sjimharris
4147230557Sjimharris         status = SCI_SUCCESS;
4148230557Sjimharris      }
4149230557Sjimharris      break;
4150230557Sjimharris
4151230557Sjimharris   default:
4152230557Sjimharris      status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
4153230557Sjimharris      break;
4154230557Sjimharris   }
4155230557Sjimharris
4156230557Sjimharris   return status;
4157230557Sjimharris}
4158230557Sjimharris
4159230557Sjimharris// ---------------------------------------------------------------------------
4160230557Sjimharris
4161230557SjimharrisSCI_IO_STATUS scic_controller_start_io(
4162230557Sjimharris   SCI_CONTROLLER_HANDLE_T    controller,
4163230557Sjimharris   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4164230557Sjimharris   SCI_IO_REQUEST_HANDLE_T    io_request,
4165230557Sjimharris   U16                        io_tag
4166230557Sjimharris)
4167230557Sjimharris{
4168231296Sjimharris   SCI_STATUS          status;
4169230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4170230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4171230557Sjimharris
4172230557Sjimharris   SCIC_LOG_TRACE((
4173230557Sjimharris      sci_base_object_get_logger(controller),
4174230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4175230557Sjimharris      "scic_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
4176230557Sjimharris      controller, remote_device, io_request, io_tag
4177230557Sjimharris   ));
4178230557Sjimharris
4179230557Sjimharris   status = this_controller->state_handlers->parent.start_io_handler(
4180230557Sjimharris               &this_controller->parent,
4181230557Sjimharris               (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4182230557Sjimharris               (SCI_BASE_REQUEST_T *)io_request,
4183230557Sjimharris               io_tag
4184230557Sjimharris            );
4185230557Sjimharris
4186231296Sjimharris   return (SCI_IO_STATUS)status;
4187230557Sjimharris}
4188230557Sjimharris
4189230557Sjimharris// ---------------------------------------------------------------------------
4190230557Sjimharris
4191230557SjimharrisSCI_STATUS scic_controller_terminate_request(
4192230557Sjimharris   SCI_CONTROLLER_HANDLE_T    controller,
4193230557Sjimharris   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4194230557Sjimharris   SCI_IO_REQUEST_HANDLE_T    request
4195230557Sjimharris)
4196230557Sjimharris{
4197230557Sjimharris   SCI_STATUS status;
4198230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4199230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4200230557Sjimharris
4201230557Sjimharris   SCIC_LOG_TRACE((
4202230557Sjimharris      sci_base_object_get_logger(controller),
4203230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4204230557Sjimharris      "scic_controller_terminate_request(0x%x, 0x%x, 0x%x) enter\n",
4205230557Sjimharris      controller, remote_device, request
4206230557Sjimharris   ));
4207230557Sjimharris
4208230557Sjimharris   status = this_controller->state_handlers->terminate_request_handler(
4209230557Sjimharris      &this_controller->parent,
4210230557Sjimharris      (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4211230557Sjimharris      (SCI_BASE_REQUEST_T *)request
4212230557Sjimharris   );
4213230557Sjimharris
4214230557Sjimharris   return status;
4215230557Sjimharris}
4216230557Sjimharris
4217230557Sjimharris// ---------------------------------------------------------------------------
4218230557Sjimharris
4219230557SjimharrisSCI_STATUS scic_controller_complete_io(
4220230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller,
4221230557Sjimharris   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4222230557Sjimharris   SCI_IO_REQUEST_HANDLE_T io_request
4223230557Sjimharris)
4224230557Sjimharris{
4225230557Sjimharris   SCI_STATUS status;
4226230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4227230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4228230557Sjimharris
4229230557Sjimharris   SCIC_LOG_TRACE((
4230230557Sjimharris      sci_base_object_get_logger(controller),
4231230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4232230557Sjimharris      "scic_controller_complete_io(0x%x, 0x%x, 0x%x) enter\n",
4233230557Sjimharris      controller, remote_device, io_request
4234230557Sjimharris   ));
4235230557Sjimharris
4236230557Sjimharris   status = this_controller->state_handlers->parent.complete_io_handler(
4237230557Sjimharris      &this_controller->parent,
4238230557Sjimharris      (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4239230557Sjimharris      (SCI_BASE_REQUEST_T *)io_request
4240230557Sjimharris   );
4241230557Sjimharris
4242230557Sjimharris   return status;
4243230557Sjimharris}
4244230557Sjimharris
4245230557Sjimharris// ---------------------------------------------------------------------------
4246230557Sjimharris
4247230557Sjimharris#if !defined(DISABLE_TASK_MANAGEMENT)
4248230557Sjimharris
4249230557SjimharrisSCI_TASK_STATUS scic_controller_start_task(
4250230557Sjimharris   SCI_CONTROLLER_HANDLE_T    controller,
4251230557Sjimharris   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4252230557Sjimharris   SCI_TASK_REQUEST_HANDLE_T  task_request,
4253230557Sjimharris   U16                        task_tag
4254230557Sjimharris)
4255230557Sjimharris{
4256231296Sjimharris   SCI_STATUS             status = SCI_FAILURE_INVALID_STATE;
4257230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4258230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4259230557Sjimharris
4260230557Sjimharris   SCIC_LOG_TRACE((
4261230557Sjimharris      sci_base_object_get_logger(controller),
4262230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4263230557Sjimharris      "scic_controller_start_task(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
4264230557Sjimharris      controller, remote_device, task_request, task_tag
4265230557Sjimharris   ));
4266230557Sjimharris
4267230557Sjimharris   if (this_controller->state_handlers->parent.start_task_handler != NULL)
4268230557Sjimharris   {
4269230557Sjimharris      status = this_controller->state_handlers->parent.start_task_handler(
4270230557Sjimharris                  &this_controller->parent,
4271230557Sjimharris                  (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4272230557Sjimharris                  (SCI_BASE_REQUEST_T *)task_request,
4273230557Sjimharris                  task_tag
4274230557Sjimharris               );
4275230557Sjimharris   }
4276230557Sjimharris   else
4277230557Sjimharris   {
4278230557Sjimharris      SCIC_LOG_INFO((
4279230557Sjimharris         sci_base_object_get_logger(controller),
4280230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
4281230557Sjimharris         "SCIC Controller starting task from invalid state\n"
4282230557Sjimharris      ));
4283230557Sjimharris   }
4284230557Sjimharris
4285231296Sjimharris   return (SCI_TASK_STATUS)status;
4286230557Sjimharris}
4287230557Sjimharris
4288230557Sjimharris// ---------------------------------------------------------------------------
4289230557Sjimharris
4290230557SjimharrisSCI_STATUS scic_controller_complete_task(
4291230557Sjimharris   SCI_CONTROLLER_HANDLE_T    controller,
4292230557Sjimharris   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4293230557Sjimharris   SCI_TASK_REQUEST_HANDLE_T  task_request
4294230557Sjimharris)
4295230557Sjimharris{
4296230557Sjimharris   SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4297230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4298230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4299230557Sjimharris
4300230557Sjimharris   SCIC_LOG_TRACE((
4301230557Sjimharris      sci_base_object_get_logger(controller),
4302230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4303230557Sjimharris      "scic_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n",
4304230557Sjimharris      controller, remote_device, task_request
4305230557Sjimharris   ));
4306230557Sjimharris
4307230557Sjimharris   if (this_controller->state_handlers->parent.complete_task_handler != NULL)
4308230557Sjimharris   {
4309230557Sjimharris      status = this_controller->state_handlers->parent.complete_task_handler(
4310230557Sjimharris                  &this_controller->parent,
4311230557Sjimharris                  (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4312230557Sjimharris                  (SCI_BASE_REQUEST_T *)task_request
4313230557Sjimharris               );
4314230557Sjimharris   }
4315230557Sjimharris   else
4316230557Sjimharris   {
4317230557Sjimharris      SCIC_LOG_INFO((
4318230557Sjimharris         sci_base_object_get_logger(controller),
4319230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER,
4320230557Sjimharris         "SCIC Controller completing task from invalid state\n"
4321230557Sjimharris      ));
4322230557Sjimharris   }
4323230557Sjimharris
4324230557Sjimharris   return status;
4325230557Sjimharris}
4326230557Sjimharris
4327230557Sjimharris#endif // !defined(DISABLE_TASK_MANAGEMENT)
4328230557Sjimharris
4329230557Sjimharris// ---------------------------------------------------------------------------
4330230557Sjimharris
4331230557SjimharrisSCI_STATUS scic_controller_get_port_handle(
4332230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller,
4333230557Sjimharris   U8                      port_index,
4334230557Sjimharris   SCI_PORT_HANDLE_T *     port_handle
4335230557Sjimharris)
4336230557Sjimharris{
4337230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4338230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4339230557Sjimharris
4340230557Sjimharris   SCIC_LOG_TRACE((
4341230557Sjimharris      sci_base_object_get_logger(controller),
4342230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4343230557Sjimharris      "scic_controller_get_port_handle(0x%x, 0x%x, 0x%x) enter\n",
4344230557Sjimharris      controller, port_index, port_handle
4345230557Sjimharris   ));
4346230557Sjimharris
4347230557Sjimharris   if (port_index < this_controller->logical_port_entries)
4348230557Sjimharris   {
4349230557Sjimharris      *port_handle = &this_controller->port_table[port_index];
4350230557Sjimharris
4351230557Sjimharris      return SCI_SUCCESS;
4352230557Sjimharris   }
4353230557Sjimharris
4354230557Sjimharris   return SCI_FAILURE_INVALID_PORT;
4355230557Sjimharris}
4356230557Sjimharris
4357230557Sjimharris// ---------------------------------------------------------------------------
4358230557Sjimharris
4359230557SjimharrisSCI_STATUS scic_controller_get_phy_handle(
4360230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller,
4361230557Sjimharris   U8                      phy_index,
4362230557Sjimharris   SCI_PHY_HANDLE_T *      phy_handle
4363230557Sjimharris)
4364230557Sjimharris{
4365230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4366230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4367230557Sjimharris
4368230557Sjimharris   SCIC_LOG_TRACE((
4369230557Sjimharris      sci_base_object_get_logger(controller),
4370230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4371230557Sjimharris      "scic_controller_get_phy_handle(0x%x, 0x%x, 0x%x) enter\n",
4372230557Sjimharris      controller, phy_index, phy_handle
4373230557Sjimharris   ));
4374230557Sjimharris
4375230557Sjimharris   if (phy_index < ARRAY_SIZE(this_controller->phy_table))
4376230557Sjimharris   {
4377230557Sjimharris      *phy_handle = &this_controller->phy_table[phy_index];
4378230557Sjimharris
4379230557Sjimharris      return SCI_SUCCESS;
4380230557Sjimharris   }
4381230557Sjimharris
4382230557Sjimharris   SCIC_LOG_ERROR((
4383230557Sjimharris      sci_base_object_get_logger(this_controller),
4384230557Sjimharris      SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_CONTROLLER,
4385230557Sjimharris      "Controller:0x%x PhyId:0x%x invalid phy index\n",
4386230557Sjimharris      this_controller, phy_index
4387230557Sjimharris   ));
4388230557Sjimharris
4389230557Sjimharris   return SCI_FAILURE_INVALID_PHY;
4390230557Sjimharris}
4391230557Sjimharris
4392230557Sjimharris// ---------------------------------------------------------------------------
4393230557Sjimharris
4394230557SjimharrisU16 scic_controller_allocate_io_tag(
4395230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
4396230557Sjimharris)
4397230557Sjimharris{
4398230557Sjimharris   U16 task_context;
4399230557Sjimharris   U16 sequence_count;
4400230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4401230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4402230557Sjimharris
4403230557Sjimharris   SCIC_LOG_TRACE((
4404230557Sjimharris      sci_base_object_get_logger(controller),
4405230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4406230557Sjimharris      "scic_controller_allocate_io_tag(0x%x) enter\n",
4407230557Sjimharris      controller
4408230557Sjimharris   ));
4409230557Sjimharris
4410230557Sjimharris   if (!sci_pool_empty(this_controller->tci_pool))
4411230557Sjimharris   {
4412230557Sjimharris      sci_pool_get(this_controller->tci_pool, task_context);
4413230557Sjimharris
4414230557Sjimharris      sequence_count = this_controller->io_request_sequence[task_context];
4415230557Sjimharris
4416230557Sjimharris      return scic_sds_io_tag_construct(sequence_count, task_context);
4417230557Sjimharris   }
4418230557Sjimharris
4419230557Sjimharris   return SCI_CONTROLLER_INVALID_IO_TAG;
4420230557Sjimharris}
4421230557Sjimharris
4422230557Sjimharris// ---------------------------------------------------------------------------
4423230557Sjimharris
4424230557SjimharrisSCI_STATUS scic_controller_free_io_tag(
4425230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller,
4426230557Sjimharris   U16                     io_tag
4427230557Sjimharris)
4428230557Sjimharris{
4429230557Sjimharris   U16 sequence;
4430230557Sjimharris   U16 index;
4431230557Sjimharris
4432230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4433230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4434230557Sjimharris
4435230557Sjimharris   ASSERT(io_tag != SCI_CONTROLLER_INVALID_IO_TAG);
4436230557Sjimharris
4437230557Sjimharris   SCIC_LOG_TRACE((
4438230557Sjimharris      sci_base_object_get_logger(controller),
4439230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4440230557Sjimharris      "scic_controller_free_io_tag(0x%x, 0x%x) enter\n",
4441230557Sjimharris      controller, io_tag
4442230557Sjimharris   ));
4443230557Sjimharris
4444230557Sjimharris   sequence = scic_sds_io_tag_get_sequence(io_tag);
4445230557Sjimharris   index    = scic_sds_io_tag_get_index(io_tag);
4446230557Sjimharris
4447230557Sjimharris   if (!sci_pool_full(this_controller->tci_pool))
4448230557Sjimharris   {
4449230557Sjimharris      if (sequence == this_controller->io_request_sequence[index])
4450230557Sjimharris      {
4451230557Sjimharris         scic_sds_io_sequence_increment(
4452230557Sjimharris            this_controller->io_request_sequence[index]);
4453230557Sjimharris
4454230557Sjimharris         sci_pool_put(this_controller->tci_pool, index);
4455230557Sjimharris
4456230557Sjimharris         return SCI_SUCCESS;
4457230557Sjimharris      }
4458230557Sjimharris   }
4459230557Sjimharris
4460230557Sjimharris   return SCI_FAILURE_INVALID_IO_TAG;
4461230557Sjimharris}
4462230557Sjimharris
4463230557Sjimharris// ---------------------------------------------------------------------------
4464230557Sjimharris
4465230557Sjimharrisvoid scic_controller_enable_interrupts(
4466230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
4467230557Sjimharris)
4468230557Sjimharris{
4469230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4470230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4471230557Sjimharris
4472230557Sjimharris   ASSERT(this_controller->smu_registers != NULL);
4473230557Sjimharris
4474230557Sjimharris   SMU_IMR_WRITE(this_controller, 0x00000000);
4475230557Sjimharris}
4476230557Sjimharris
4477230557Sjimharris// ---------------------------------------------------------------------------
4478230557Sjimharris
4479230557Sjimharrisvoid scic_controller_disable_interrupts(
4480230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller
4481230557Sjimharris)
4482230557Sjimharris{
4483230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
4484230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4485230557Sjimharris
4486230557Sjimharris   ASSERT(this_controller->smu_registers != NULL);
4487230557Sjimharris
4488230557Sjimharris   SMU_IMR_WRITE(this_controller, 0xffffffff);
4489230557Sjimharris}
4490230557Sjimharris
4491230557Sjimharris// ---------------------------------------------------------------------------
4492230557Sjimharris
4493230557SjimharrisSCI_STATUS scic_controller_set_mode(
4494230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
4495230557Sjimharris   SCI_CONTROLLER_MODE       operating_mode
4496230557Sjimharris)
4497230557Sjimharris{
4498230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4499230557Sjimharris   SCI_STATUS             status          = SCI_SUCCESS;
4500230557Sjimharris
4501230557Sjimharris   SCIC_LOG_TRACE((
4502230557Sjimharris      sci_base_object_get_logger(controller),
4503230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
4504230557Sjimharris      "scic_controller_set_mode(0x%x, 0x%x) enter\n",
4505230557Sjimharris      controller, operating_mode
4506230557Sjimharris   ));
4507230557Sjimharris
4508230557Sjimharris   if (
4509230557Sjimharris         (this_controller->parent.state_machine.current_state_id
4510230557Sjimharris          == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
4511230557Sjimharris      || (this_controller->parent.state_machine.current_state_id
4512230557Sjimharris          == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
4513230557Sjimharris      )
4514230557Sjimharris   {
4515230557Sjimharris      switch (operating_mode)
4516230557Sjimharris      {
4517230557Sjimharris      case SCI_MODE_SPEED:
4518230557Sjimharris         this_controller->remote_node_entries =
4519230557Sjimharris            MIN(this_controller->remote_node_entries, SCI_MAX_REMOTE_DEVICES);
4520230557Sjimharris         this_controller->task_context_entries =
4521230557Sjimharris            MIN(this_controller->task_context_entries, SCU_IO_REQUEST_COUNT);
4522230557Sjimharris         this_controller->uf_control.buffers.count =
4523230557Sjimharris            MIN(this_controller->uf_control.buffers.count, SCU_UNSOLICITED_FRAME_COUNT);
4524230557Sjimharris         this_controller->completion_event_entries =
4525230557Sjimharris            MIN(this_controller->completion_event_entries, SCU_EVENT_COUNT);
4526230557Sjimharris         this_controller->completion_queue_entries =
4527230557Sjimharris            MIN(this_controller->completion_queue_entries, SCU_COMPLETION_QUEUE_COUNT);
4528230557Sjimharris
4529230557Sjimharris         scic_sds_controller_build_memory_descriptor_table(this_controller);
4530230557Sjimharris      break;
4531230557Sjimharris
4532230557Sjimharris      case SCI_MODE_SIZE:
4533230557Sjimharris         this_controller->remote_node_entries =
4534230557Sjimharris            MIN(this_controller->remote_node_entries, SCI_MIN_REMOTE_DEVICES);
4535230557Sjimharris         this_controller->task_context_entries =
4536230557Sjimharris            MIN(this_controller->task_context_entries, SCI_MIN_IO_REQUESTS);
4537230557Sjimharris         this_controller->uf_control.buffers.count =
4538230557Sjimharris            MIN(this_controller->uf_control.buffers.count, SCU_MIN_UNSOLICITED_FRAMES);
4539230557Sjimharris         this_controller->completion_event_entries =
4540230557Sjimharris            MIN(this_controller->completion_event_entries, SCU_MIN_EVENTS);
4541230557Sjimharris         this_controller->completion_queue_entries =
4542230557Sjimharris            MIN(this_controller->completion_queue_entries, SCU_MIN_COMPLETION_QUEUE_ENTRIES);
4543230557Sjimharris
4544230557Sjimharris         scic_sds_controller_build_memory_descriptor_table(this_controller);
4545230557Sjimharris      break;
4546230557Sjimharris
4547230557Sjimharris      default:
4548230557Sjimharris         status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
4549230557Sjimharris      break;
4550230557Sjimharris      }
4551230557Sjimharris   }
4552230557Sjimharris   else
4553230557Sjimharris      status = SCI_FAILURE_INVALID_STATE;
4554230557Sjimharris
4555230557Sjimharris   return status;
4556230557Sjimharris}
4557230557Sjimharris
4558230557Sjimharris/**
4559230557Sjimharris * This method will reset the controller hardware.
4560230557Sjimharris *
4561230557Sjimharris * @param[in] this_controller The controller that is to be reset.
4562230557Sjimharris */
4563230557Sjimharrisvoid scic_sds_controller_reset_hardware(
4564230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller
4565230557Sjimharris)
4566230557Sjimharris{
4567230557Sjimharris   // Disable interrupts so we dont take any spurious interrupts
4568230557Sjimharris   scic_controller_disable_interrupts(this_controller);
4569230557Sjimharris
4570230557Sjimharris   // Reset the SCU
4571230557Sjimharris   SMU_SMUSRCR_WRITE(this_controller, 0xFFFFFFFF);
4572230557Sjimharris
4573230557Sjimharris   // Delay for 1ms to before clearing the CQP and UFQPR.
4574230557Sjimharris   scic_cb_stall_execution(1000);
4575230557Sjimharris
4576230557Sjimharris   // The write to the CQGR clears the CQP
4577230557Sjimharris   SMU_CQGR_WRITE(this_controller, 0x00000000);
4578230557Sjimharris
4579230557Sjimharris   // The write to the UFQGP clears the UFQPR
4580230557Sjimharris   SCU_UFQGP_WRITE(this_controller, 0x00000000);
4581230557Sjimharris}
4582230557Sjimharris
4583230557Sjimharris// ---------------------------------------------------------------------------
4584230557Sjimharris
4585230557SjimharrisSCI_STATUS scic_user_parameters_set(
4586230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
4587230557Sjimharris   SCIC_USER_PARAMETERS_T  * scic_parms
4588230557Sjimharris)
4589230557Sjimharris{
4590230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4591230557Sjimharris
4592230557Sjimharris   if (
4593230557Sjimharris         (this_controller->parent.state_machine.current_state_id
4594230557Sjimharris          == SCI_BASE_CONTROLLER_STATE_RESET)
4595230557Sjimharris      || (this_controller->parent.state_machine.current_state_id
4596230557Sjimharris          == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
4597230557Sjimharris      || (this_controller->parent.state_machine.current_state_id
4598230557Sjimharris          == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
4599230557Sjimharris      )
4600230557Sjimharris   {
4601230557Sjimharris      U16  index;
4602230557Sjimharris
4603230557Sjimharris      // Validate the user parameters.  If they are not legal, then
4604230557Sjimharris      // return a failure.
4605230557Sjimharris      for (index = 0; index < SCI_MAX_PHYS; index++)
4606230557Sjimharris      {
4607230557Sjimharris         if (!
4608230557Sjimharris               (  scic_parms->sds1.phys[index].max_speed_generation
4609230557Sjimharris                  <= SCIC_SDS_PARM_MAX_SPEED
4610230557Sjimharris               && scic_parms->sds1.phys[index].max_speed_generation
4611230557Sjimharris                  > SCIC_SDS_PARM_NO_SPEED
4612230557Sjimharris               )
4613230557Sjimharris            )
4614230557Sjimharris            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4615230557Sjimharris
4616230557Sjimharris         if (
4617230557Sjimharris               (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) ||
4618230557Sjimharris               (scic_parms->sds1.phys[index].align_insertion_frequency == 0) ||
4619230557Sjimharris               (scic_parms->sds1.phys[index].notify_enable_spin_up_insertion_frequency == 0)
4620230557Sjimharris            )
4621230557Sjimharris         {
4622230557Sjimharris            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4623230557Sjimharris         }
4624230557Sjimharris      }
4625230557Sjimharris
4626230557Sjimharris      if (
4627230557Sjimharris            (scic_parms->sds1.stp_inactivity_timeout == 0) ||
4628230557Sjimharris            (scic_parms->sds1.ssp_inactivity_timeout == 0) ||
4629230557Sjimharris            (scic_parms->sds1.stp_max_occupancy_timeout == 0) ||
4630230557Sjimharris            (scic_parms->sds1.ssp_max_occupancy_timeout == 0) ||
4631230557Sjimharris            (scic_parms->sds1.no_outbound_task_timeout == 0)
4632230557Sjimharris         )
4633230557Sjimharris      {
4634230557Sjimharris         return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4635230557Sjimharris      }
4636230557Sjimharris
4637230557Sjimharris      memcpy(
4638230557Sjimharris         (&this_controller->user_parameters), scic_parms, sizeof(*scic_parms));
4639230557Sjimharris
4640230557Sjimharris      return SCI_SUCCESS;
4641230557Sjimharris   }
4642230557Sjimharris
4643230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
4644230557Sjimharris}
4645230557Sjimharris
4646230557Sjimharris// ---------------------------------------------------------------------------
4647230557Sjimharris
4648230557Sjimharrisvoid scic_user_parameters_get(
4649230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
4650230557Sjimharris   SCIC_USER_PARAMETERS_T   * scic_parms
4651230557Sjimharris)
4652230557Sjimharris{
4653230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4654230557Sjimharris
4655230557Sjimharris   memcpy(scic_parms, (&this_controller->user_parameters), sizeof(*scic_parms));
4656230557Sjimharris}
4657230557Sjimharris
4658230557Sjimharris// ---------------------------------------------------------------------------
4659230557SjimharrisSCI_STATUS scic_oem_parameters_set(
4660230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
4661230557Sjimharris   SCIC_OEM_PARAMETERS_T   * scic_parms,
4662230557Sjimharris   U8 scic_parms_version
4663230557Sjimharris)
4664230557Sjimharris{
4665230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4666230557Sjimharris   SCI_BIOS_OEM_PARAM_ELEMENT_T *old_oem_params =
4667230557Sjimharris                (SCI_BIOS_OEM_PARAM_ELEMENT_T *)(&(scic_parms->sds1));
4668230557Sjimharris
4669230557Sjimharris
4670230557Sjimharris   if (
4671230557Sjimharris         (this_controller->parent.state_machine.current_state_id
4672230557Sjimharris          == SCI_BASE_CONTROLLER_STATE_RESET)
4673230557Sjimharris      || (this_controller->parent.state_machine.current_state_id
4674230557Sjimharris          == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
4675230557Sjimharris      || (this_controller->parent.state_machine.current_state_id
4676230557Sjimharris          == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
4677230557Sjimharris      )
4678230557Sjimharris   {
4679230557Sjimharris      U16  index;
4680230557Sjimharris      U8   combined_phy_mask = 0;
4681230557Sjimharris
4682230557Sjimharris      /*
4683230557Sjimharris       * Set the OEM parameter version for the controller. This comes
4684230557Sjimharris       * from the OEM parameter block header or the registry depending
4685230557Sjimharris       * on what WCDL is set to retrieve.
4686230557Sjimharris       */
4687230557Sjimharris      this_controller->oem_parameters_version = scic_parms_version;
4688230557Sjimharris
4689230557Sjimharris      // Validate the oem parameters.  If they are not legal, then
4690230557Sjimharris      // return a failure.
4691230557Sjimharris      for(index=0; index<SCI_MAX_PORTS; index++)
4692230557Sjimharris      {
4693230557Sjimharris         if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX)
4694230557Sjimharris         {
4695230557Sjimharris            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4696230557Sjimharris         }
4697230557Sjimharris      }
4698230557Sjimharris
4699230557Sjimharris      for(index=0; index<SCI_MAX_PHYS; index++)
4700230557Sjimharris      {
4701230557Sjimharris         if (
4702230557Sjimharris             scic_parms->sds1.phys[index].sas_address.sci_format.high == 0
4703230557Sjimharris                 && scic_parms->sds1.phys[index].sas_address.sci_format.low  == 0
4704230557Sjimharris        )
4705230557Sjimharris        {
4706230557Sjimharris            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4707230557Sjimharris        }
4708230557Sjimharris
4709230557Sjimharris#if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
4710230557Sjimharris        if (
4711230557Sjimharris              (scic_parms->sds1.phys[index].afe_tx_amp_control0 == 0) ||
4712230557Sjimharris              (scic_parms->sds1.phys[index].afe_tx_amp_control1 == 0) ||
4713230557Sjimharris              (scic_parms->sds1.phys[index].afe_tx_amp_control2 == 0) ||
4714230557Sjimharris              (scic_parms->sds1.phys[index].afe_tx_amp_control3 == 0)
4715230557Sjimharris              )
4716230557Sjimharris        {
4717230557Sjimharris           return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4718230557Sjimharris        }
4719230557Sjimharris#endif
4720230557Sjimharris      }
4721230557Sjimharris
4722230557Sjimharris      if (scic_parms->sds1.controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
4723230557Sjimharris      {
4724230557Sjimharris         for(index=0; index<SCI_MAX_PHYS; index++)
4725230557Sjimharris         {
4726230557Sjimharris            if (scic_parms->sds1.ports[index].phy_mask != 0)
4727230557Sjimharris            {
4728230557Sjimharris               return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4729230557Sjimharris            }
4730230557Sjimharris         }
4731230557Sjimharris      }
4732230557Sjimharris      else if (scic_parms->sds1.controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE)
4733230557Sjimharris      {
4734230557Sjimharris         for(index=0; index<SCI_MAX_PHYS; index++)
4735230557Sjimharris         {
4736230557Sjimharris            combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask;
4737230557Sjimharris         }
4738230557Sjimharris
4739230557Sjimharris         if (combined_phy_mask == 0)
4740230557Sjimharris         {
4741230557Sjimharris            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4742230557Sjimharris         }
4743230557Sjimharris      }
4744230557Sjimharris      else
4745230557Sjimharris      {
4746230557Sjimharris         return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4747230557Sjimharris      }
4748230557Sjimharris
4749230557Sjimharris      if (scic_parms->sds1.controller.max_number_concurrent_device_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
4750230557Sjimharris      {
4751230557Sjimharris         return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4752230557Sjimharris      }
4753230557Sjimharris
4754230557Sjimharris      if (old_oem_params->controller.do_enable_ssc != 0)
4755230557Sjimharris      {
4756230557Sjimharris         if (  (scic_parms_version == SCI_OEM_PARAM_VER_1_0)
4757230557Sjimharris            && (old_oem_params->controller.do_enable_ssc != 0x01))
4758230557Sjimharris             return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4759230557Sjimharris
4760230557Sjimharris         if (scic_parms_version >= SCI_OEM_PARAM_VER_1_1)
4761230557Sjimharris         {
4762230557Sjimharris            SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T *oem_params =
4763230557Sjimharris                (SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T*)(&(scic_parms->sds1));
4764230557Sjimharris
4765230557Sjimharris            U8 test = oem_params->controller.ssc_sata_tx_spread_level;
4766230557Sjimharris            if ( !((test == 0x0) || (test == 0x2) || (test == 0x3) ||
4767230557Sjimharris                 (test == 0x6) || (test == 0x7)) )
4768230557Sjimharris                return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4769230557Sjimharris
4770230557Sjimharris            test = oem_params->controller.ssc_sas_tx_spread_level;
4771230557Sjimharris            if (oem_params->controller.ssc_sas_tx_type == 0)
4772230557Sjimharris            {
4773230557Sjimharris                if ( !((test == 0x0) || (test == 0x2) || (test == 0x3)) )
4774230557Sjimharris                    return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4775230557Sjimharris            }
4776230557Sjimharris            else
4777230557Sjimharris            if (oem_params->controller.ssc_sas_tx_type == 1)
4778230557Sjimharris            {
4779230557Sjimharris                if ( !((test == 0x0) || (test == 0x3) || (test == 0x6)) )
4780230557Sjimharris                    return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4781230557Sjimharris            }
4782230557Sjimharris         }
4783230557Sjimharris      }
4784230557Sjimharris
4785230557Sjimharris      memcpy(
4786230557Sjimharris         (&this_controller->oem_parameters), scic_parms, sizeof(*scic_parms));
4787230557Sjimharris      return SCI_SUCCESS;
4788230557Sjimharris   }
4789230557Sjimharris
4790230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
4791230557Sjimharris}
4792230557Sjimharris
4793230557Sjimharris// ---------------------------------------------------------------------------
4794230557Sjimharris
4795230557Sjimharrisvoid scic_oem_parameters_get(
4796230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
4797230557Sjimharris   SCIC_OEM_PARAMETERS_T   * scic_parms
4798230557Sjimharris)
4799230557Sjimharris{
4800230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4801230557Sjimharris
4802230557Sjimharris   memcpy(scic_parms, (&this_controller->oem_parameters), sizeof(*scic_parms));
4803230557Sjimharris}
4804230557Sjimharris
4805230557Sjimharris// ---------------------------------------------------------------------------
4806230557Sjimharris
4807230557Sjimharris#if !defined(DISABLE_INTERRUPTS)
4808230557Sjimharris
4809230557Sjimharris#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853
4810230557Sjimharris#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280
4811230557Sjimharris#define INTERRUPT_COALESCE_TIMEOUT_MAX_US                    2700000
4812230557Sjimharris#define INTERRUPT_COALESCE_NUMBER_MAX                        256
4813230557Sjimharris#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN                7
4814230557Sjimharris#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX                28
4815230557Sjimharris
4816230557SjimharrisSCI_STATUS scic_controller_set_interrupt_coalescence(
4817230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller,
4818230557Sjimharris   U32                     coalesce_number,
4819230557Sjimharris   U32                     coalesce_timeout
4820230557Sjimharris)
4821230557Sjimharris{
4822230557Sjimharris   SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4823230557Sjimharris   U8 timeout_encode = 0;
4824230557Sjimharris   U32 min = 0;
4825230557Sjimharris   U32 max = 0;
4826230557Sjimharris
4827230557Sjimharris   //Check if the input parameters fall in the range.
4828230557Sjimharris   if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX)
4829230557Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4830230557Sjimharris
4831230557Sjimharris   //  Defined encoding for interrupt coalescing timeout:
4832230557Sjimharris   //              Value   Min      Max     Units
4833230557Sjimharris   //              -----   ---      ---     -----
4834230557Sjimharris   //              0       -        -       Disabled
4835230557Sjimharris   //              1       13.3     20.0    ns
4836230557Sjimharris   //              2       26.7     40.0
4837230557Sjimharris   //              3       53.3     80.0
4838230557Sjimharris   //              4       106.7    160.0
4839230557Sjimharris   //              5       213.3    320.0
4840230557Sjimharris   //              6       426.7    640.0
4841230557Sjimharris   //              7       853.3    1280.0
4842230557Sjimharris   //              8       1.7      2.6     us
4843230557Sjimharris   //              9       3.4      5.1
4844230557Sjimharris   //              10      6.8      10.2
4845230557Sjimharris   //              11      13.7     20.5
4846230557Sjimharris   //              12      27.3     41.0
4847230557Sjimharris   //              13      54.6     81.9
4848230557Sjimharris   //              14      109.2    163.8
4849230557Sjimharris   //              15      218.5    327.7
4850230557Sjimharris   //              16      436.9    655.4
4851230557Sjimharris   //              17      873.8    1310.7
4852230557Sjimharris   //              18      1.7      2.6     ms
4853230557Sjimharris   //              19      3.5      5.2
4854230557Sjimharris   //              20      7.0      10.5
4855230557Sjimharris   //              21      14.0     21.0
4856230557Sjimharris   //              22      28.0     41.9
4857230557Sjimharris   //              23      55.9     83.9
4858230557Sjimharris   //              24      111.8    167.8
4859230557Sjimharris   //              25      223.7    335.5
4860230557Sjimharris   //              26      447.4    671.1
4861230557Sjimharris   //              27      894.8    1342.2
4862230557Sjimharris   //              28      1.8      2.7     s
4863230557Sjimharris   //              Others Undefined
4864230557Sjimharris
4865230557Sjimharris   //Use the table above to decide the encode of interrupt coalescing timeout
4866230557Sjimharris   //value for register writing.
4867230557Sjimharris   if (coalesce_timeout == 0)
4868230557Sjimharris      timeout_encode = 0;
4869230557Sjimharris   else
4870230557Sjimharris   {
4871230557Sjimharris      //make the timeout value in unit of (10 ns).
4872230557Sjimharris      coalesce_timeout = coalesce_timeout * 100;
4873230557Sjimharris      min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10;
4874230557Sjimharris      max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10;
4875230557Sjimharris
4876230557Sjimharris      //get the encode of timeout for register writing.
4877230557Sjimharris      for ( timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN;
4878230557Sjimharris            timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX;
4879230557Sjimharris            timeout_encode++ )
4880230557Sjimharris      {
4881230557Sjimharris         if (min <= coalesce_timeout &&  max > coalesce_timeout)
4882230557Sjimharris            break;
4883230557Sjimharris         else if (coalesce_timeout >= max && coalesce_timeout < min*2
4884230557Sjimharris            && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US*100)
4885230557Sjimharris         {
4886230557Sjimharris            if ( (coalesce_timeout-max) < (2*min - coalesce_timeout) )
4887230557Sjimharris               break;
4888230557Sjimharris            else
4889230557Sjimharris            {
4890230557Sjimharris               timeout_encode++;
4891230557Sjimharris               break;
4892230557Sjimharris            }
4893230557Sjimharris         }
4894230557Sjimharris         else
4895230557Sjimharris         {
4896230557Sjimharris            max = max*2;
4897230557Sjimharris            min = min*2;
4898230557Sjimharris         }
4899230557Sjimharris      }
4900230557Sjimharris
4901230557Sjimharris      if ( timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX+1 )
4902230557Sjimharris         //the value is out of range.
4903230557Sjimharris         return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4904230557Sjimharris   }
4905230557Sjimharris
4906230557Sjimharris   SMU_ICC_WRITE(
4907230557Sjimharris      scic_controller,
4908230557Sjimharris      (SMU_ICC_GEN_VAL(NUMBER, coalesce_number)|
4909230557Sjimharris       SMU_ICC_GEN_VAL(TIMER, timeout_encode))
4910230557Sjimharris   );
4911230557Sjimharris
4912230557Sjimharris   scic_controller->interrupt_coalesce_number = (U16)coalesce_number;
4913230557Sjimharris   scic_controller->interrupt_coalesce_timeout = coalesce_timeout/100;
4914230557Sjimharris
4915230557Sjimharris   return SCI_SUCCESS;
4916230557Sjimharris}
4917230557Sjimharris
4918230557Sjimharris// ---------------------------------------------------------------------------
4919230557Sjimharris
4920230557Sjimharrisvoid scic_controller_get_interrupt_coalescence(
4921230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
4922230557Sjimharris   U32                     * coalesce_number,
4923230557Sjimharris   U32                     * coalesce_timeout
4924230557Sjimharris)
4925230557Sjimharris{
4926230557Sjimharris   SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4927230557Sjimharris   *coalesce_number = scic_controller->interrupt_coalesce_number;
4928230557Sjimharris   *coalesce_timeout = scic_controller->interrupt_coalesce_timeout;
4929230557Sjimharris}
4930230557Sjimharris
4931230557Sjimharris#endif // !defined(DISABLE_INTERRUPTS)
4932230557Sjimharris
4933230557Sjimharris// ---------------------------------------------------------------------------
4934230557Sjimharris
4935230557SjimharrisU32 scic_controller_get_scratch_ram_size(
4936230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller
4937230557Sjimharris)
4938230557Sjimharris{
4939230557Sjimharris   return SCU_SCRATCH_RAM_SIZE_IN_DWORDS;
4940230557Sjimharris}
4941230557Sjimharris
4942230557Sjimharris// ---------------------------------------------------------------------------
4943230557Sjimharris
4944230557SjimharrisSCI_STATUS scic_controller_read_scratch_ram_dword(
4945230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
4946230557Sjimharris   U32                       offset,
4947230557Sjimharris   U32                     * value
4948230557Sjimharris)
4949230557Sjimharris{
4950230557Sjimharris   U32 zpt_index;
4951230557Sjimharris   SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4952230557Sjimharris   U32 status = SMU_SMUCSR_READ(scic_controller);
4953230557Sjimharris
4954230557Sjimharris   //Check if the SCU Scratch RAM been initialized, if not return zeros
4955230557Sjimharris   if ((status & SCU_RAM_INIT_COMPLETED) != SCU_RAM_INIT_COMPLETED)
4956230557Sjimharris   {
4957230557Sjimharris      *value = 0x00000000;
4958230557Sjimharris      return SCI_SUCCESS;
4959230557Sjimharris   }
4960230557Sjimharris
4961230557Sjimharris   if (offset < scic_controller_get_scratch_ram_size(controller))
4962230557Sjimharris   {
4963230557Sjimharris      if(offset <= SCU_MAX_ZPT_DWORD_INDEX)
4964230557Sjimharris      {
4965230557Sjimharris         zpt_index = offset + (offset - (offset % 4)) + 4;
4966230557Sjimharris
4967230557Sjimharris         *value = scu_controller_scratch_ram_register_read(scic_controller,zpt_index);
4968230557Sjimharris      }
4969230557Sjimharris      else //offset > SCU_MAX_ZPT_DWORD_INDEX
4970230557Sjimharris      {
4971230557Sjimharris         offset = offset - 132;
4972230557Sjimharris
4973230557Sjimharris         zpt_index = offset + (offset - (offset % 4)) + 4;
4974230557Sjimharris
4975230557Sjimharris         *value = scu_controller_scratch_ram_register_read_ext(scic_controller,zpt_index);
4976230557Sjimharris      }
4977230557Sjimharris
4978230557Sjimharris      return SCI_SUCCESS;
4979230557Sjimharris   }
4980230557Sjimharris   else
4981230557Sjimharris   {
4982230557Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4983230557Sjimharris   }
4984230557Sjimharris}
4985230557Sjimharris
4986230557Sjimharris// ---------------------------------------------------------------------------
4987230557Sjimharris
4988230557SjimharrisSCI_STATUS scic_controller_write_scratch_ram_dword(
4989230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
4990230557Sjimharris   U32                       offset,
4991230557Sjimharris   U32                       value
4992230557Sjimharris)
4993230557Sjimharris{
4994230557Sjimharris   U32 zpt_index;
4995230557Sjimharris
4996230557Sjimharris   if (offset < scic_controller_get_scratch_ram_size(controller))
4997230557Sjimharris   {
4998230557Sjimharris      SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4999230557Sjimharris
5000230557Sjimharris      if(offset <= SCU_MAX_ZPT_DWORD_INDEX)
5001230557Sjimharris      {
5002230557Sjimharris         zpt_index = offset + (offset - (offset % 4)) + 4;
5003230557Sjimharris
5004230557Sjimharris         scu_controller_scratch_ram_register_write(scic_controller,zpt_index,value);
5005230557Sjimharris      }
5006230557Sjimharris      else //offset > SCU_MAX_ZPT_DWORD_INDEX
5007230557Sjimharris      {
5008230557Sjimharris         offset = offset - 132;
5009230557Sjimharris
5010230557Sjimharris         zpt_index = offset + (offset - (offset % 4)) + 4;
5011230557Sjimharris
5012230557Sjimharris         scu_controller_scratch_ram_register_write_ext(scic_controller,zpt_index,value);
5013230557Sjimharris
5014230557Sjimharris      }
5015230557Sjimharris
5016230557Sjimharris      return SCI_SUCCESS;
5017230557Sjimharris   }
5018230557Sjimharris   else
5019230557Sjimharris   {
5020230557Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
5021230557Sjimharris   }
5022230557Sjimharris}
5023230557Sjimharris
5024230557Sjimharris// ---------------------------------------------------------------------------
5025230557Sjimharris
5026230557SjimharrisSCI_STATUS scic_controller_suspend(
5027230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller
5028230557Sjimharris)
5029230557Sjimharris{
5030230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
5031230557Sjimharris   U8 index;
5032230557Sjimharris
5033230557Sjimharris   // As a precaution, disable interrupts.  The user is required
5034230557Sjimharris   // to re-enable interrupts if so desired after the call.
5035230557Sjimharris   scic_controller_disable_interrupts(controller);
5036230557Sjimharris
5037230557Sjimharris   // Stop all the timers
5038230557Sjimharris   // Maybe change the states of the objects to avoid processing stuff.
5039230557Sjimharris
5040230557Sjimharris
5041230557Sjimharris   // Suspend the Ports in order to ensure no unexpected
5042230557Sjimharris   // frame reception occurs on the links from the target
5043230557Sjimharris   for (index = 0; index < SCI_MAX_PORTS; index++)
5044230557Sjimharris      scic_sds_port_suspend_port_task_scheduler(
5045230557Sjimharris         &(this_controller->port_table[index]));
5046230557Sjimharris
5047230557Sjimharris   // Disable/Reset the completion queue and unsolicited frame
5048230557Sjimharris   // queue.
5049230557Sjimharris   SMU_CQGR_WRITE(this_controller, 0x00000000);
5050230557Sjimharris   SCU_UFQGP_WRITE(this_controller, 0x00000000);
5051230557Sjimharris
5052230557Sjimharris   // Clear any interrupts that may be pending or may have been generated
5053230557Sjimharris   // by setting CQGR and CQPR back to 0
5054230557Sjimharris   SMU_ISR_WRITE(this_controller, 0xFFFFFFFF);
5055230557Sjimharris
5056230557Sjimharris   //reset the software get pointer to completion queue.
5057230557Sjimharris   this_controller->completion_queue_get = 0;
5058230557Sjimharris
5059230557Sjimharris   return SCI_SUCCESS;
5060230557Sjimharris}
5061230557Sjimharris
5062230557Sjimharris// ---------------------------------------------------------------------------
5063230557Sjimharris
5064230557SjimharrisSCI_STATUS scic_controller_resume(
5065230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller
5066230557Sjimharris)
5067230557Sjimharris{
5068230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
5069230557Sjimharris   U8 index;
5070230557Sjimharris
5071230557Sjimharris   // Initialize the completion queue and unsolicited frame queue.
5072230557Sjimharris   scic_sds_controller_initialize_completion_queue(this_controller);
5073230557Sjimharris   scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
5074230557Sjimharris
5075230557Sjimharris   this_controller->restrict_completions = FALSE;
5076230557Sjimharris
5077230557Sjimharris   // Release the port suspensions to allow for further successful
5078230557Sjimharris   // operation.
5079230557Sjimharris   for (index = 0; index < SCI_MAX_PORTS; index++)
5080230557Sjimharris      scic_sds_port_resume_port_task_scheduler(
5081230557Sjimharris         &(this_controller->port_table[index]));
5082230557Sjimharris
5083230557Sjimharris   //check the link layer status register DWORD sync acquired bit to detect
5084230557Sjimharris   //link down event. If there is any link down event happened during controller
5085230557Sjimharris   //suspension, restart phy state machine.
5086230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index ++)
5087230557Sjimharris   {
5088230557Sjimharris      SCIC_SDS_PHY_T * curr_phy = &this_controller->phy_table[index];
5089230557Sjimharris      U32 link_layer_status = SCU_SAS_LLSTA_READ(curr_phy);
5090230557Sjimharris
5091230557Sjimharris      if ((link_layer_status & SCU_SAS_LLSTA_DWORD_SYNCA_BIT) == 0)
5092230557Sjimharris      {
5093230557Sjimharris         //Need to put the phy back to start OOB. Then an appropriate link event
5094230557Sjimharris         //message will be send to scic user.
5095230557Sjimharris         scic_sds_phy_restart_starting_state(curr_phy);
5096230557Sjimharris      }
5097230557Sjimharris   }
5098230557Sjimharris
5099230557Sjimharris   return SCI_SUCCESS;
5100230557Sjimharris}
5101230557Sjimharris
5102230557Sjimharris// ---------------------------------------------------------------------------
5103230557Sjimharris
5104230557SjimharrisSCI_STATUS scic_controller_transition(
5105230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
5106230557Sjimharris   BOOL                      restrict_completions
5107230557Sjimharris)
5108230557Sjimharris{
5109230557Sjimharris   SCI_STATUS              result = SCI_FAILURE_INVALID_STATE;
5110230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
5111230557Sjimharris   U8                      index;
5112230557Sjimharris
5113230557Sjimharris   SCIC_LOG_TRACE((
5114230557Sjimharris      sci_base_object_get_logger(controller),
5115230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
5116230557Sjimharris      "scic_controller_transition(0x%x) enter\n",
5117230557Sjimharris      controller
5118230557Sjimharris   ));
5119230557Sjimharris
5120230557Sjimharris   if (this_controller->parent.state_machine.current_state_id
5121230557Sjimharris       == SCI_BASE_CONTROLLER_STATE_READY)
5122230557Sjimharris   {
5123230557Sjimharris      // Ensure that there are no outstanding IO operations at this
5124230557Sjimharris      // time.
5125230557Sjimharris      for (index = 0; index < SCI_MAX_PORTS; index++)
5126230557Sjimharris      {
5127230557Sjimharris         if (this_controller->port_table[index].started_request_count != 0)
5128230557Sjimharris            return result;
5129230557Sjimharris      }
5130230557Sjimharris
5131230557Sjimharris      scic_controller_suspend(controller);
5132230557Sjimharris
5133230557Sjimharris      // Loop through the memory descriptor list and reprogram
5134230557Sjimharris      // the silicon memory registers accordingly.
5135230557Sjimharris      result = scic_sds_controller_validate_memory_descriptor_table(
5136230557Sjimharris                  this_controller);
5137230557Sjimharris      if (result == SCI_SUCCESS)
5138230557Sjimharris      {
5139230557Sjimharris         scic_sds_controller_ram_initialization(this_controller);
5140230557Sjimharris         this_controller->restrict_completions = restrict_completions;
5141230557Sjimharris      }
5142230557Sjimharris
5143230557Sjimharris      scic_controller_resume(controller);
5144230557Sjimharris   }
5145230557Sjimharris
5146230557Sjimharris   return result;
5147230557Sjimharris}
5148230557Sjimharris
5149230557Sjimharris// ---------------------------------------------------------------------------
5150230557Sjimharris
5151230557SjimharrisSCI_STATUS scic_controller_get_max_ports(
5152230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
5153230557Sjimharris   U8                      * count
5154230557Sjimharris)
5155230557Sjimharris{
5156230557Sjimharris   *count = SCI_MAX_PORTS;
5157230557Sjimharris   return SCI_SUCCESS;
5158230557Sjimharris}
5159230557Sjimharris
5160230557Sjimharris// ---------------------------------------------------------------------------
5161230557Sjimharris
5162230557SjimharrisSCI_STATUS scic_controller_get_max_phys(
5163230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
5164230557Sjimharris   U8                      * count
5165230557Sjimharris)
5166230557Sjimharris{
5167230557Sjimharris   *count = SCI_MAX_PHYS;
5168230557Sjimharris   return SCI_SUCCESS;
5169230557Sjimharris}
5170230557Sjimharris
5171230557Sjimharris
5172230557Sjimharris//******************************************************************************
5173230557Sjimharris//* CONTROLLER STATE MACHINE
5174230557Sjimharris//******************************************************************************
5175230557Sjimharris
5176230557Sjimharris/**
5177230557Sjimharris * This macro returns the maximum number of logical ports supported by the
5178230557Sjimharris * hardware. The caller passes in the value read from the device context
5179230557Sjimharris * capacity register and this macro will mash and shift the value
5180230557Sjimharris * appropriately.
5181230557Sjimharris */
5182230557Sjimharris#define smu_dcc_get_max_ports(dcc_value) \
5183230557Sjimharris   ( \
5184230557Sjimharris     (    ((U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK)) \
5185230557Sjimharris       >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT ) + 1\
5186230557Sjimharris   )
5187230557Sjimharris
5188230557Sjimharris/**
5189230557Sjimharris * This macro returns the maximum number of task contexts supported by the
5190230557Sjimharris * hardware. The caller passes in the value read from the device context
5191230557Sjimharris * capacity register and this macro will mash and shift the value
5192230557Sjimharris * appropriately.
5193230557Sjimharris */
5194230557Sjimharris#define smu_dcc_get_max_task_context(dcc_value) \
5195230557Sjimharris   ( \
5196230557Sjimharris     (   ((U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK)) \
5197230557Sjimharris       >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT ) + 1\
5198230557Sjimharris   )
5199230557Sjimharris
5200230557Sjimharris/**
5201230557Sjimharris * This macro returns the maximum number of remote node contexts supported
5202230557Sjimharris * by the hardware. The caller passes in the value read from the device
5203230557Sjimharris * context capacity register and this macro will mash and shift the value
5204230557Sjimharris * appropriately.
5205230557Sjimharris */
5206230557Sjimharris#define smu_dcc_get_max_remote_node_context(dcc_value) \
5207230557Sjimharris   ( \
5208230557Sjimharris     (  ( (U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) )\
5209230557Sjimharris       >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT ) + 1\
5210230557Sjimharris   )
5211230557Sjimharris
5212230557Sjimharris//*****************************************************************************
5213230557Sjimharris//* DEFAULT STATE HANDLERS
5214230557Sjimharris//*****************************************************************************
5215230557Sjimharris
5216230557Sjimharris/**
5217230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER default start
5218230557Sjimharris * io/task handler is in place.
5219230557Sjimharris *    - Issue a warning message
5220230557Sjimharris *
5221230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5222230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
5223230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
5224230557Sjimharris *       used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
5225230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
5226230557Sjimharris *       would be cast to a SCIC_SDS_IO_REQUEST.
5227230557Sjimharris * @param[in] io_tag This is the IO tag to be assigned to the IO request or
5228230557Sjimharris *       SCI_CONTROLLER_INVALID_IO_TAG.
5229230557Sjimharris *
5230230557Sjimharris * @return SCI_STATUS
5231230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
5232230557Sjimharris */
5233230557Sjimharrisstatic
5234230557SjimharrisSCI_STATUS scic_sds_controller_default_start_operation_handler(
5235230557Sjimharris   SCI_BASE_CONTROLLER_T    *controller,
5236230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T *remote_device,
5237230557Sjimharris   SCI_BASE_REQUEST_T       *io_request,
5238230557Sjimharris   U16                       io_tag
5239230557Sjimharris)
5240230557Sjimharris{
5241230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
5242230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5243230557Sjimharris
5244230557Sjimharris   SCIC_LOG_WARNING((
5245230557Sjimharris      sci_base_object_get_logger(this_controller),
5246230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
5247230557Sjimharris      "SCIC Controller requested to start an io/task from invalid state %d\n",
5248230557Sjimharris      sci_base_state_machine_get_state(
5249230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller))
5250230557Sjimharris   ));
5251230557Sjimharris
5252230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
5253230557Sjimharris}
5254230557Sjimharris
5255230557Sjimharris/**
5256230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER default
5257230557Sjimharris * request handler is in place.
5258230557Sjimharris *    - Issue a warning message
5259230557Sjimharris *
5260230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5261230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
5262230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
5263230557Sjimharris *       used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
5264230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
5265230557Sjimharris *       would be cast to a SCIC_SDS_IO_REQUEST.
5266230557Sjimharris *
5267230557Sjimharris * @return SCI_STATUS
5268230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE
5269230557Sjimharris */
5270230557Sjimharrisstatic
5271230557SjimharrisSCI_STATUS scic_sds_controller_default_request_handler(
5272230557Sjimharris   SCI_BASE_CONTROLLER_T    *controller,
5273230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T *remote_device,
5274230557Sjimharris   SCI_BASE_REQUEST_T       *io_request
5275230557Sjimharris)
5276230557Sjimharris{
5277230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
5278230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5279230557Sjimharris
5280230557Sjimharris   SCIC_LOG_WARNING((
5281230557Sjimharris      sci_base_object_get_logger(this_controller),
5282230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
5283230557Sjimharris      "SCIC Controller request operation from invalid state %d\n",
5284230557Sjimharris      sci_base_state_machine_get_state(
5285230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller))
5286230557Sjimharris   ));
5287230557Sjimharris
5288230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
5289230557Sjimharris}
5290230557Sjimharris
5291230557Sjimharris//*****************************************************************************
5292230557Sjimharris//* GENERAL (COMMON) STATE HANDLERS
5293230557Sjimharris//*****************************************************************************
5294230557Sjimharris
5295230557Sjimharris/**
5296230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5297230557Sjimharris * reset handler is in place.
5298230557Sjimharris *    - Transition to SCI_BASE_CONTROLLER_STATE_RESETTING
5299230557Sjimharris *
5300230557Sjimharris * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
5301230557Sjimharris *       SCIC_SDS_CONTROLLER object.
5302230557Sjimharris *
5303230557Sjimharris * @return SCI_STATUS
5304230557Sjimharris * @retval SCI_SUCCESS
5305230557Sjimharris */
5306230557Sjimharrisstatic
5307230557SjimharrisSCI_STATUS scic_sds_controller_general_reset_handler(
5308230557Sjimharris   SCI_BASE_CONTROLLER_T *controller
5309230557Sjimharris)
5310230557Sjimharris{
5311230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
5312230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5313230557Sjimharris
5314230557Sjimharris   SCIC_LOG_TRACE((
5315230557Sjimharris      sci_base_object_get_logger(controller),
5316230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
5317230557Sjimharris      "scic_sds_controller_resetting_state_enter(0x%x) enter\n",
5318230557Sjimharris      controller
5319230557Sjimharris   ));
5320230557Sjimharris
5321230557Sjimharris   //Release resource. So far only resource to be released are timers.
5322230557Sjimharris   scic_sds_controller_release_resource(this_controller);
5323230557Sjimharris
5324230557Sjimharris   // The reset operation is not a graceful cleanup just perform the state
5325230557Sjimharris   // transition.
5326230557Sjimharris   sci_base_state_machine_change_state(
5327230557Sjimharris      scic_sds_controller_get_base_state_machine(this_controller),
5328230557Sjimharris      SCI_BASE_CONTROLLER_STATE_RESETTING
5329230557Sjimharris   );
5330230557Sjimharris
5331230557Sjimharris   return SCI_SUCCESS;
5332230557Sjimharris}
5333230557Sjimharris
5334230557Sjimharris//*****************************************************************************
5335230557Sjimharris//* RESET STATE HANDLERS
5336230557Sjimharris//*****************************************************************************
5337230557Sjimharris
5338230557Sjimharris/**
5339230557Sjimharris * This method is the SCIC_SDS_CONTROLLER initialize handler for the reset
5340230557Sjimharris * state.
5341230557Sjimharris *    - Currently this function does nothing
5342230557Sjimharris *
5343230557Sjimharris * @param[in] controller This is the SCI_BASE_CONTROLLER object which is cast
5344230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
5345230557Sjimharris *
5346230557Sjimharris * @return SCI_STATUS
5347230557Sjimharris * @retval SCI_FAILURE
5348230557Sjimharris *
5349230557Sjimharris * @todo This function is not yet implemented and is a valid request from the
5350230557Sjimharris *       reset state.
5351230557Sjimharris */
5352230557Sjimharrisstatic
5353230557SjimharrisSCI_STATUS scic_sds_controller_reset_state_initialize_handler(
5354230557Sjimharris   SCI_BASE_CONTROLLER_T *controller
5355230557Sjimharris)
5356230557Sjimharris{
5357230557Sjimharris   U32 index;
5358230557Sjimharris   SCI_STATUS result = SCI_SUCCESS;
5359230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
5360230557Sjimharris
5361230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5362230557Sjimharris
5363230557Sjimharris   SCIC_LOG_TRACE((
5364230557Sjimharris      sci_base_object_get_logger(controller),
5365230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
5366230557Sjimharris      "scic_sds_controller_reset_state_initialize_handler(0x%x) enter\n",
5367230557Sjimharris      controller
5368230557Sjimharris   ));
5369230557Sjimharris
5370230557Sjimharris   sci_base_state_machine_change_state(
5371230557Sjimharris      scic_sds_controller_get_base_state_machine(this_controller),
5372230557Sjimharris      SCI_BASE_CONTROLLER_STATE_INITIALIZING
5373230557Sjimharris   );
5374230557Sjimharris
5375230557Sjimharris   this_controller->timeout_timer = scic_cb_timer_create(
5376230557Sjimharris      controller,
5377230557Sjimharris      scic_sds_controller_timeout_handler,
5378230557Sjimharris      controller
5379230557Sjimharris   );
5380230557Sjimharris
5381230557Sjimharris   scic_sds_controller_initialize_power_control(this_controller);
5382230557Sjimharris
5383230557Sjimharris   /// todo: This should really be done in the reset state enter but
5384230557Sjimharris   ///       the controller has not yet been initialized before getting
5385230557Sjimharris   ///       to the reset enter state so the PCI BAR is not yet assigned
5386230557Sjimharris   scic_sds_controller_reset_hardware(this_controller);
5387230557Sjimharris
5388230557Sjimharris#if defined(ARLINGTON_BUILD)
5389230557Sjimharris   scic_sds_controller_lex_atux_initialization(this_controller);
5390230557Sjimharris#elif    defined(PLEASANT_RIDGE_BUILD) \
5391230557Sjimharris      || defined(PBG_HBA_A0_BUILD) \
5392230557Sjimharris      || defined(PBG_HBA_A2_BUILD)
5393230557Sjimharris   scic_sds_controller_afe_initialization(this_controller);
5394230557Sjimharris#elif defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
5395230557Sjimharris   // There is nothing to do here for B0 since we do not have to
5396230557Sjimharris   // program the AFE registers.
5397230557Sjimharris   /// @todo The AFE settings are supposed to be correct for the B0 but
5398230557Sjimharris   ///       presently they seem to be wrong.
5399230557Sjimharris   scic_sds_controller_afe_initialization(this_controller);
5400230557Sjimharris#else  // !defined(ARLINGTON_BUILD) && !defined(PLEASANT_RIDGE_BUILD)
5401230557Sjimharris   // What other systems do we want to add here?
5402230557Sjimharris#endif // !defined(ARLINGTON_BUILD) && !defined(PLEASANT_RIDGE_BUILD)
5403230557Sjimharris
5404230557Sjimharris   if (SCI_SUCCESS == result)
5405230557Sjimharris   {
5406230557Sjimharris      U32 status;
5407230557Sjimharris      U32 terminate_loop;
5408230557Sjimharris
5409230557Sjimharris      // Take the hardware out of reset
5410230557Sjimharris      SMU_SMUSRCR_WRITE(this_controller, 0x00000000);
5411230557Sjimharris
5412230557Sjimharris      /// @todo Provide meaningfull error code for hardware failure
5413230557Sjimharris      //result = SCI_FAILURE_CONTROLLER_HARDWARE;
5414230557Sjimharris      result = SCI_FAILURE;
5415230557Sjimharris      terminate_loop = 100;
5416230557Sjimharris
5417230557Sjimharris      while (terminate_loop-- && (result != SCI_SUCCESS))
5418230557Sjimharris      {
5419230557Sjimharris         // Loop until the hardware reports success
5420230557Sjimharris         scic_cb_stall_execution(SCU_CONTEXT_RAM_INIT_STALL_TIME);
5421230557Sjimharris         status = SMU_SMUCSR_READ(this_controller);
5422230557Sjimharris
5423230557Sjimharris         if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED)
5424230557Sjimharris         {
5425230557Sjimharris            result = SCI_SUCCESS;
5426230557Sjimharris         }
5427230557Sjimharris      }
5428230557Sjimharris   }
5429230557Sjimharris
5430230557Sjimharris#ifdef ARLINGTON_BUILD
5431230557Sjimharris   scic_sds_controller_enable_chipwatch(this_controller);
5432230557Sjimharris#endif
5433230557Sjimharris
5434230557Sjimharris   if (result == SCI_SUCCESS)
5435230557Sjimharris   {
5436230557Sjimharris      U32 max_supported_ports;
5437230557Sjimharris      U32 max_supported_devices;
5438230557Sjimharris      U32 max_supported_io_requests;
5439230557Sjimharris      U32 device_context_capacity;
5440230557Sjimharris
5441230557Sjimharris      // Determine what are the actaul device capacities that the
5442230557Sjimharris      // hardware will support
5443230557Sjimharris      device_context_capacity = SMU_DCC_READ(this_controller);
5444230557Sjimharris
5445230557Sjimharris      max_supported_ports =
5446230557Sjimharris         smu_dcc_get_max_ports(device_context_capacity);
5447230557Sjimharris      max_supported_devices =
5448230557Sjimharris         smu_dcc_get_max_remote_node_context(device_context_capacity);
5449230557Sjimharris      max_supported_io_requests =
5450230557Sjimharris         smu_dcc_get_max_task_context(device_context_capacity);
5451230557Sjimharris
5452230557Sjimharris      // Make all PEs that are unassigned match up with the logical ports
5453230557Sjimharris      for (index = 0; index < max_supported_ports; index++)
5454230557Sjimharris      {
5455230557Sjimharris         scu_register_write(
5456230557Sjimharris            this_controller,
5457230557Sjimharris            this_controller->scu_registers->peg0.ptsg.protocol_engine[index],
5458230557Sjimharris            index
5459230557Sjimharris         );
5460230557Sjimharris      }
5461230557Sjimharris
5462230557Sjimharris      // Now that we have the correct hardware reported minimum values
5463230557Sjimharris      // build the MDL for the controller.  Default to a performance
5464230557Sjimharris      // configuration.
5465230557Sjimharris      scic_controller_set_mode(this_controller, SCI_MODE_SPEED);
5466230557Sjimharris
5467230557Sjimharris      // Record the smaller of the two capacity values
5468230557Sjimharris      this_controller->logical_port_entries =
5469230557Sjimharris         MIN(max_supported_ports, this_controller->logical_port_entries);
5470230557Sjimharris
5471230557Sjimharris      this_controller->task_context_entries =
5472230557Sjimharris         MIN(max_supported_io_requests, this_controller->task_context_entries);
5473230557Sjimharris
5474230557Sjimharris      this_controller->remote_node_entries =
5475230557Sjimharris         MIN(max_supported_devices, this_controller->remote_node_entries);
5476230557Sjimharris   }
5477230557Sjimharris
5478230557Sjimharris   // Initialize hardware PCI Relaxed ordering in DMA engines
5479230557Sjimharris   if (result == SCI_SUCCESS)
5480230557Sjimharris   {
5481230557Sjimharris      U32 dma_configuration;
5482230557Sjimharris
5483230557Sjimharris      // Configure the payload DMA
5484230557Sjimharris      dma_configuration = SCU_PDMACR_READ(this_controller);
5485230557Sjimharris      dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
5486230557Sjimharris      SCU_PDMACR_WRITE(this_controller, dma_configuration);
5487230557Sjimharris
5488230557Sjimharris      // Configure the control DMA
5489230557Sjimharris      dma_configuration = SCU_CDMACR_READ(this_controller);
5490230557Sjimharris      dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
5491230557Sjimharris      SCU_CDMACR_WRITE(this_controller, dma_configuration);
5492230557Sjimharris   }
5493230557Sjimharris
5494230557Sjimharris   // Initialize the PHYs before the PORTs because the PHY registers
5495230557Sjimharris   // are accessed during the port initialization.
5496230557Sjimharris   if (result == SCI_SUCCESS)
5497230557Sjimharris   {
5498230557Sjimharris      // Initialize the phys
5499230557Sjimharris      for (index = 0;
5500230557Sjimharris           (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS);
5501230557Sjimharris           index++)
5502230557Sjimharris      {
5503230557Sjimharris         result = scic_sds_phy_initialize(
5504230557Sjimharris            &this_controller->phy_table[index],
5505230557Sjimharris            &this_controller->scu_registers->peg0.pe[index].tl,
5506230557Sjimharris            &this_controller->scu_registers->peg0.pe[index].ll
5507230557Sjimharris         );
5508230557Sjimharris      }
5509230557Sjimharris   }
5510230557Sjimharris
5511230557Sjimharris   //Initialize the SGPIO Unit for HARDWARE controlled SGPIO
5512230557Sjimharris   if(result == SCI_SUCCESS)
5513230557Sjimharris   {
5514230557Sjimharris      scic_sgpio_hardware_initialize(this_controller);
5515230557Sjimharris   }
5516230557Sjimharris
5517230557Sjimharris   if (result == SCI_SUCCESS)
5518230557Sjimharris   {
5519230557Sjimharris      // Initialize the logical ports
5520230557Sjimharris      for (index = 0;
5521230557Sjimharris              (index < this_controller->logical_port_entries)
5522230557Sjimharris           && (result == SCI_SUCCESS);
5523230557Sjimharris           index++)
5524230557Sjimharris      {
5525230557Sjimharris         result = scic_sds_port_initialize(
5526230557Sjimharris            &this_controller->port_table[index],
5527230557Sjimharris            &this_controller->scu_registers->peg0.ptsg.port[index],
5528230557Sjimharris            &this_controller->scu_registers->peg0.ptsg.protocol_engine,
5529230557Sjimharris            &this_controller->scu_registers->peg0.viit[index]
5530230557Sjimharris         );
5531230557Sjimharris      }
5532230557Sjimharris   }
5533230557Sjimharris
5534230557Sjimharris   if (SCI_SUCCESS == result)
5535230557Sjimharris   {
5536230557Sjimharris      result = scic_sds_port_configuration_agent_initialize(
5537230557Sjimharris                  this_controller,
5538230557Sjimharris                  &this_controller->port_agent
5539230557Sjimharris               );
5540230557Sjimharris   }
5541230557Sjimharris
5542230557Sjimharris   // Advance the controller state machine
5543230557Sjimharris   if (result == SCI_SUCCESS)
5544230557Sjimharris   {
5545230557Sjimharris      sci_base_state_machine_change_state(
5546230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller),
5547230557Sjimharris         SCI_BASE_CONTROLLER_STATE_INITIALIZED
5548230557Sjimharris      );
5549230557Sjimharris   }
5550230557Sjimharris   else
5551230557Sjimharris   {
5552230557Sjimharris      //stay in the same state and release the resource
5553230557Sjimharris      scic_sds_controller_release_resource(this_controller);
5554230557Sjimharris
5555230557Sjimharris      SCIC_LOG_TRACE((
5556230557Sjimharris         sci_base_object_get_logger(controller),
5557230557Sjimharris         SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
5558230557Sjimharris         "Invalid Port Configuration from scic_sds_controller_reset_state_initialize_handler(0x%x) \n",
5559230557Sjimharris         controller
5560230557Sjimharris      ));
5561230557Sjimharris
5562230557Sjimharris   }
5563230557Sjimharris
5564230557Sjimharris   return result;
5565230557Sjimharris}
5566230557Sjimharris
5567230557Sjimharris//*****************************************************************************
5568230557Sjimharris//* INITIALIZED STATE HANDLERS
5569230557Sjimharris//*****************************************************************************
5570230557Sjimharris
5571230557Sjimharris/**
5572230557Sjimharris * This method is the SCIC_SDS_CONTROLLER start handler for the initialized
5573230557Sjimharris * state.
5574230557Sjimharris *    - Validate we have a good memory descriptor table
5575230557Sjimharris *    - Initialze the physical memory before programming the hardware
5576230557Sjimharris *    - Program the SCU hardware with the physical memory addresses passed in
5577230557Sjimharris *      the memory descriptor table.
5578230557Sjimharris *    - Initialzie the TCi pool
5579230557Sjimharris *    - Initialize the RNi pool
5580230557Sjimharris *    - Initialize the completion queue
5581230557Sjimharris *    - Initialize the unsolicited frame data
5582230557Sjimharris *    - Take the SCU port task scheduler out of reset
5583230557Sjimharris *    - Start the first phy object.
5584230557Sjimharris *    - Transition to SCI_BASE_CONTROLLER_STATE_STARTING.
5585230557Sjimharris *
5586230557Sjimharris * @param[in] controller This is the SCI_BASE_CONTROLLER object which is cast
5587230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
5588230557Sjimharris * @param[in] timeout This is the allowed time for the controller object to
5589230557Sjimharris *       reach the started state.
5590230557Sjimharris *
5591230557Sjimharris * @return SCI_STATUS
5592230557Sjimharris * @retval SCI_SUCCESS if all of the controller start operations complete
5593230557Sjimharris * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD if one or more of the
5594230557Sjimharris *         memory descriptor fields is invalid.
5595230557Sjimharris */
5596230557Sjimharrisstatic
5597230557SjimharrisSCI_STATUS scic_sds_controller_initialized_state_start_handler(
5598230557Sjimharris   SCI_BASE_CONTROLLER_T * controller,
5599230557Sjimharris   U32                     timeout
5600230557Sjimharris)
5601230557Sjimharris{
5602230557Sjimharris   U16                     index;
5603230557Sjimharris   SCI_STATUS              result;
5604230557Sjimharris   SCIC_SDS_CONTROLLER_T * this_controller;
5605230557Sjimharris
5606230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5607230557Sjimharris
5608230557Sjimharris   // Make sure that the SCI User filled in the memory descriptor table correctly
5609230557Sjimharris   result = scic_sds_controller_validate_memory_descriptor_table(this_controller);
5610230557Sjimharris
5611230557Sjimharris   if (result == SCI_SUCCESS)
5612230557Sjimharris   {
5613230557Sjimharris      // The memory descriptor list looks good so program the hardware
5614230557Sjimharris      scic_sds_controller_ram_initialization(this_controller);
5615230557Sjimharris   }
5616230557Sjimharris
5617230557Sjimharris   if (SCI_SUCCESS == result)
5618230557Sjimharris   {
5619230557Sjimharris      // Build the TCi free pool
5620230557Sjimharris      sci_pool_initialize(this_controller->tci_pool);
5621230557Sjimharris      for (index = 0; index < this_controller->task_context_entries; index++)
5622230557Sjimharris      {
5623230557Sjimharris         sci_pool_put(this_controller->tci_pool, index);
5624230557Sjimharris      }
5625230557Sjimharris
5626230557Sjimharris      // Build the RNi free pool
5627230557Sjimharris      scic_sds_remote_node_table_initialize(
5628230557Sjimharris         &this_controller->available_remote_nodes,
5629230557Sjimharris         this_controller->remote_node_entries
5630230557Sjimharris      );
5631230557Sjimharris   }
5632230557Sjimharris
5633230557Sjimharris   if (SCI_SUCCESS == result)
5634230557Sjimharris   {
5635230557Sjimharris      // Before anything else lets make sure we will not be interrupted
5636230557Sjimharris      // by the hardware.
5637230557Sjimharris      scic_controller_disable_interrupts(controller);
5638230557Sjimharris
5639230557Sjimharris      // Enable the port task scheduler
5640230557Sjimharris      scic_sds_controller_enable_port_task_scheduler(this_controller);
5641230557Sjimharris
5642230557Sjimharris      // Assign all the task entries to this controller physical function
5643230557Sjimharris      scic_sds_controller_assign_task_entries(this_controller);
5644230557Sjimharris
5645230557Sjimharris      // Now initialze the completion queue
5646230557Sjimharris      scic_sds_controller_initialize_completion_queue(this_controller);
5647230557Sjimharris
5648230557Sjimharris      // Initialize the unsolicited frame queue for use
5649230557Sjimharris      scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
5650230557Sjimharris
5651230557Sjimharris      // Setup the phy start timer
5652230557Sjimharris      result = scic_sds_controller_initialize_phy_startup(this_controller);
5653230557Sjimharris   }
5654230557Sjimharris
5655230557Sjimharris   // Start all of the ports on this controller
5656230557Sjimharris   for (
5657230557Sjimharris          index = 0;
5658230557Sjimharris          (index < this_controller->logical_port_entries) && (result == SCI_SUCCESS);
5659230557Sjimharris          index++
5660230557Sjimharris       )
5661230557Sjimharris   {
5662230557Sjimharris      result = this_controller->port_table[index].
5663230557Sjimharris         state_handlers->parent.start_handler(&this_controller->port_table[index].parent);
5664230557Sjimharris   }
5665230557Sjimharris
5666230557Sjimharris   if (SCI_SUCCESS == result)
5667230557Sjimharris   {
5668230557Sjimharris      scic_sds_controller_start_next_phy(this_controller);
5669230557Sjimharris
5670230557Sjimharris      // See if the user requested to timeout this operation.
5671230557Sjimharris      if (timeout != 0)
5672230557Sjimharris         scic_cb_timer_start(controller, this_controller->timeout_timer, timeout);
5673230557Sjimharris
5674230557Sjimharris      sci_base_state_machine_change_state(
5675230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller),
5676230557Sjimharris         SCI_BASE_CONTROLLER_STATE_STARTING
5677230557Sjimharris      );
5678230557Sjimharris   }
5679230557Sjimharris
5680230557Sjimharris   return result;
5681230557Sjimharris}
5682230557Sjimharris
5683230557Sjimharris//*****************************************************************************
5684230557Sjimharris//* STARTING STATE HANDLERS
5685230557Sjimharris//*****************************************************************************
5686230557Sjimharris
5687230557Sjimharris/**
5688230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
5689230557Sjimharris * link up handler is called.  This method will perform the following:
5690230557Sjimharris *    - Stop the phy timer
5691230557Sjimharris *    - Start the next phy
5692230557Sjimharris *    - Report the link up condition to the port object
5693230557Sjimharris *
5694230557Sjimharris * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the link up
5695230557Sjimharris *       notification.
5696230557Sjimharris * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
5697230557Sjimharris * @param[in] phy This is the SCIC_SDS_PHY which has gone link up.
5698230557Sjimharris *
5699230557Sjimharris * @return none
5700230557Sjimharris */
5701230557Sjimharrisstatic
5702230557Sjimharrisvoid scic_sds_controller_starting_state_link_up_handler(
5703230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
5704230557Sjimharris   SCIC_SDS_PORT_T       *port,
5705230557Sjimharris   SCIC_SDS_PHY_T        *phy
5706230557Sjimharris)
5707230557Sjimharris{
5708230557Sjimharris   scic_sds_controller_phy_timer_stop(this_controller);
5709230557Sjimharris
5710230557Sjimharris   this_controller->port_agent.link_up_handler(
5711230557Sjimharris      this_controller, &this_controller->port_agent, port, phy
5712230557Sjimharris   );
5713230557Sjimharris   //scic_sds_port_link_up(port, phy);
5714230557Sjimharris
5715230557Sjimharris   scic_sds_controller_start_next_phy(this_controller);
5716230557Sjimharris}
5717230557Sjimharris
5718230557Sjimharris/**
5719230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
5720230557Sjimharris * link down handler is called.
5721230557Sjimharris *    - Report the link down condition to the port object
5722230557Sjimharris *
5723230557Sjimharris * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the
5724230557Sjimharris *       link down notification.
5725230557Sjimharris * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
5726230557Sjimharris * @param[in] phy This is the SCIC_SDS_PHY which has gone link down.
5727230557Sjimharris *
5728230557Sjimharris * @return none
5729230557Sjimharris */
5730230557Sjimharrisstatic
5731230557Sjimharrisvoid scic_sds_controller_starting_state_link_down_handler(
5732230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
5733230557Sjimharris   SCIC_SDS_PORT_T       *port,
5734230557Sjimharris   SCIC_SDS_PHY_T        *phy
5735230557Sjimharris)
5736230557Sjimharris{
5737230557Sjimharris   this_controller->port_agent.link_down_handler(
5738230557Sjimharris      this_controller, &this_controller->port_agent, port, phy
5739230557Sjimharris   );
5740230557Sjimharris   //scic_sds_port_link_down(port, phy);
5741230557Sjimharris}
5742230557Sjimharris
5743230557Sjimharris//*****************************************************************************
5744230557Sjimharris//* READY STATE HANDLERS
5745230557Sjimharris//*****************************************************************************
5746230557Sjimharris
5747230557Sjimharris/**
5748230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5749230557Sjimharris * stop handler is called.
5750230557Sjimharris *    - Start the timeout timer
5751230557Sjimharris *    - Transition to SCI_BASE_CONTROLLER_STATE_STOPPING.
5752230557Sjimharris *
5753230557Sjimharris * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
5754230557Sjimharris *       SCIC_SDS_CONTROLLER object.
5755230557Sjimharris * @param[in] timeout The timeout for when the stop operation should report a
5756230557Sjimharris *       failure.
5757230557Sjimharris *
5758230557Sjimharris * @return SCI_STATUS
5759230557Sjimharris * @retval SCI_SUCCESS
5760230557Sjimharris */
5761230557Sjimharrisstatic
5762230557SjimharrisSCI_STATUS scic_sds_controller_ready_state_stop_handler(
5763230557Sjimharris   SCI_BASE_CONTROLLER_T *controller,
5764230557Sjimharris   U32                   timeout
5765230557Sjimharris)
5766230557Sjimharris{
5767230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
5768230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5769230557Sjimharris
5770230557Sjimharris   // See if the user requested to timeout this operation
5771230557Sjimharris   if (timeout != 0)
5772230557Sjimharris      scic_cb_timer_start(controller, this_controller->timeout_timer, timeout);
5773230557Sjimharris
5774230557Sjimharris   sci_base_state_machine_change_state(
5775230557Sjimharris      scic_sds_controller_get_base_state_machine(this_controller),
5776230557Sjimharris      SCI_BASE_CONTROLLER_STATE_STOPPING
5777230557Sjimharris   );
5778230557Sjimharris
5779230557Sjimharris   return SCI_SUCCESS;
5780230557Sjimharris}
5781230557Sjimharris
5782230557Sjimharris/**
5783230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5784230557Sjimharris * and the start io handler is called.
5785230557Sjimharris *    - Start the io request on the remote device
5786230557Sjimharris *    - if successful
5787230557Sjimharris *       - assign the io_request to the io_request_table
5788230557Sjimharris *       - post the request to the hardware
5789230557Sjimharris *
5790230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5791230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
5792230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5793230557Sjimharris *       SCIC_SDS_REMOTE_DEVICE object.
5794230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5795230557Sjimharris *       SCIC_SDS_IO_REQUEST object.
5796230557Sjimharris * @param[in] io_tag This is the IO tag to be assigned to the IO request or
5797230557Sjimharris *       SCI_CONTROLLER_INVALID_IO_TAG.
5798230557Sjimharris *
5799230557Sjimharris * @return SCI_STATUS
5800230557Sjimharris * @retval SCI_SUCCESS if the start io operation succeeds
5801230557Sjimharris * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
5802230557Sjimharris *         allocated for the io request.
5803230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
5804230557Sjimharris *         state to accept io requests.
5805230557Sjimharris *
5806230557Sjimharris * @todo How does the io_tag parameter get assigned to the io request?
5807230557Sjimharris */
5808230557Sjimharrisstatic
5809230557SjimharrisSCI_STATUS scic_sds_controller_ready_state_start_io_handler(
5810230557Sjimharris   SCI_BASE_CONTROLLER_T    *controller,
5811230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T *remote_device,
5812230557Sjimharris   SCI_BASE_REQUEST_T       *io_request,
5813230557Sjimharris   U16                       io_tag
5814230557Sjimharris)
5815230557Sjimharris{
5816230557Sjimharris   SCI_STATUS status;
5817230557Sjimharris
5818230557Sjimharris   SCIC_SDS_CONTROLLER_T    *this_controller;
5819230557Sjimharris   SCIC_SDS_REQUEST_T       *the_request;
5820230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *the_device;
5821230557Sjimharris
5822230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5823230557Sjimharris   the_request = (SCIC_SDS_REQUEST_T *)io_request;
5824230557Sjimharris   the_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
5825230557Sjimharris
5826230557Sjimharris   status = scic_sds_remote_device_start_io(this_controller, the_device, the_request);
5827230557Sjimharris
5828230557Sjimharris   if (status == SCI_SUCCESS)
5829230557Sjimharris   {
5830230557Sjimharris      this_controller->io_request_table[
5831230557Sjimharris            scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5832230557Sjimharris
5833230557Sjimharris      scic_sds_controller_post_request(
5834230557Sjimharris         this_controller,
5835230557Sjimharris         scic_sds_request_get_post_context(the_request)
5836230557Sjimharris      );
5837230557Sjimharris   }
5838230557Sjimharris
5839230557Sjimharris   return status;
5840230557Sjimharris}
5841230557Sjimharris
5842230557Sjimharris/**
5843230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5844230557Sjimharris * and the complete io handler is called.
5845230557Sjimharris *    - Complete the io request on the remote device
5846230557Sjimharris *    - if successful
5847230557Sjimharris *       - remove the io_request to the io_request_table
5848230557Sjimharris *
5849230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5850230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
5851230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5852230557Sjimharris *       SCIC_SDS_REMOTE_DEVICE object.
5853230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5854230557Sjimharris *       SCIC_SDS_IO_REQUEST object.
5855230557Sjimharris *
5856230557Sjimharris * @return SCI_STATUS
5857230557Sjimharris * @retval SCI_SUCCESS if the start io operation succeeds
5858230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
5859230557Sjimharris *         state to accept io requests.
5860230557Sjimharris */
5861230557Sjimharrisstatic
5862230557SjimharrisSCI_STATUS scic_sds_controller_ready_state_complete_io_handler(
5863230557Sjimharris   SCI_BASE_CONTROLLER_T    *controller,
5864230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T *remote_device,
5865230557Sjimharris   SCI_BASE_REQUEST_T       *io_request
5866230557Sjimharris)
5867230557Sjimharris{
5868230557Sjimharris   U16        index;
5869230557Sjimharris   SCI_STATUS status;
5870230557Sjimharris   SCIC_SDS_CONTROLLER_T    *this_controller;
5871230557Sjimharris   SCIC_SDS_REQUEST_T       *the_request;
5872230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *the_device;
5873230557Sjimharris
5874230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5875230557Sjimharris   the_request = (SCIC_SDS_REQUEST_T *)io_request;
5876230557Sjimharris   the_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
5877230557Sjimharris
5878230557Sjimharris   status = scic_sds_remote_device_complete_io(
5879230557Sjimharris                  this_controller, the_device, the_request);
5880230557Sjimharris
5881230557Sjimharris   if (status == SCI_SUCCESS)
5882230557Sjimharris   {
5883230557Sjimharris      index = scic_sds_io_tag_get_index(the_request->io_tag);
5884230557Sjimharris      this_controller->io_request_table[index] = SCI_INVALID_HANDLE;
5885230557Sjimharris   }
5886230557Sjimharris
5887230557Sjimharris   return status;
5888230557Sjimharris}
5889230557Sjimharris
5890230557Sjimharris/**
5891230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5892230557Sjimharris * and the continue io handler is called.
5893230557Sjimharris *
5894230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5895230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
5896230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5897230557Sjimharris *       SCIC_SDS_REMOTE_DEVICE object.
5898230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5899230557Sjimharris *       SCIC_SDS_IO_REQUEST object.
5900230557Sjimharris *
5901230557Sjimharris * @return SCI_STATUS
5902230557Sjimharris */
5903230557Sjimharrisstatic
5904230557SjimharrisSCI_STATUS scic_sds_controller_ready_state_continue_io_handler(
5905230557Sjimharris   SCI_BASE_CONTROLLER_T    *controller,
5906230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T *remote_device,
5907230557Sjimharris   SCI_BASE_REQUEST_T       *io_request
5908230557Sjimharris)
5909230557Sjimharris{
5910230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
5911230557Sjimharris   SCIC_SDS_REQUEST_T    *the_request;
5912230557Sjimharris
5913230557Sjimharris   the_request     = (SCIC_SDS_REQUEST_T *)io_request;
5914230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5915230557Sjimharris
5916230557Sjimharris   this_controller->io_request_table[
5917230557Sjimharris      scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5918230557Sjimharris
5919230557Sjimharris   scic_sds_controller_post_request(
5920230557Sjimharris      this_controller,
5921230557Sjimharris      scic_sds_request_get_post_context(the_request)
5922230557Sjimharris   );
5923230557Sjimharris
5924230557Sjimharris   return SCI_SUCCESS;
5925230557Sjimharris}
5926230557Sjimharris
5927230557Sjimharris/**
5928230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5929230557Sjimharris * and the start task handler is called.
5930230557Sjimharris *    - The remote device is requested to start the task request
5931230557Sjimharris *    - if successful
5932230557Sjimharris *       - assign the task to the io_request_table
5933230557Sjimharris *       - post the request to the SCU hardware
5934230557Sjimharris *
5935230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5936230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
5937230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5938230557Sjimharris *       SCIC_SDS_REMOTE_DEVICE object.
5939230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5940230557Sjimharris *       SCIC_SDS_IO_REQUEST object.
5941230557Sjimharris * @param[in] task_tag This is the task tag to be assigned to the task request
5942230557Sjimharris *       or SCI_CONTROLLER_INVALID_IO_TAG.
5943230557Sjimharris *
5944230557Sjimharris * @return SCI_STATUS
5945230557Sjimharris * @retval SCI_SUCCESS if the start io operation succeeds
5946230557Sjimharris * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
5947230557Sjimharris *         allocated for the io request.
5948230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
5949230557Sjimharris *         state to accept io requests.
5950230557Sjimharris *
5951230557Sjimharris * @todo How does the io tag get assigned in this code path?
5952230557Sjimharris */
5953230557Sjimharrisstatic
5954230557SjimharrisSCI_STATUS scic_sds_controller_ready_state_start_task_handler(
5955230557Sjimharris   SCI_BASE_CONTROLLER_T    *controller,
5956230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T *remote_device,
5957230557Sjimharris   SCI_BASE_REQUEST_T       *io_request,
5958230557Sjimharris   U16                       task_tag
5959230557Sjimharris)
5960230557Sjimharris{
5961230557Sjimharris   SCIC_SDS_CONTROLLER_T    *this_controller = (SCIC_SDS_CONTROLLER_T *)
5962230557Sjimharris                                               controller;
5963230557Sjimharris   SCIC_SDS_REQUEST_T       *the_request     = (SCIC_SDS_REQUEST_T *)
5964230557Sjimharris                                               io_request;
5965230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *the_device      = (SCIC_SDS_REMOTE_DEVICE_T *)
5966230557Sjimharris                                               remote_device;
5967230557Sjimharris   SCI_STATUS                status;
5968230557Sjimharris
5969230557Sjimharris   status = scic_sds_remote_device_start_task(
5970230557Sjimharris               this_controller, the_device, the_request
5971230557Sjimharris            );
5972230557Sjimharris
5973230557Sjimharris   if (status == SCI_SUCCESS)
5974230557Sjimharris   {
5975230557Sjimharris      this_controller->io_request_table[
5976230557Sjimharris         scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5977230557Sjimharris
5978230557Sjimharris      scic_sds_controller_post_request(
5979230557Sjimharris         this_controller,
5980230557Sjimharris         scic_sds_request_get_post_context(the_request)
5981230557Sjimharris      );
5982230557Sjimharris   }
5983230557Sjimharris   else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS)
5984230557Sjimharris   {
5985230557Sjimharris      this_controller->io_request_table[
5986230557Sjimharris         scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5987230557Sjimharris
5988230557Sjimharris      //We will let framework know this task request started successfully,
5989230557Sjimharris      //although core is still woring on starting the request (to post tc when
5990230557Sjimharris      //RNC is resumed.)
5991230557Sjimharris      status = SCI_SUCCESS;
5992230557Sjimharris   }
5993230557Sjimharris   return status;
5994230557Sjimharris}
5995230557Sjimharris
5996230557Sjimharris/**
5997230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5998230557Sjimharris * and the terminate request handler is called.
5999230557Sjimharris *    - call the io request terminate function
6000230557Sjimharris *    - if successful
6001230557Sjimharris *       - post the terminate request to the SCU hardware
6002230557Sjimharris *
6003230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6004230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
6005230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6006230557Sjimharris *       SCIC_SDS_REMOTE_DEVICE object.
6007230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
6008230557Sjimharris *       SCIC_SDS_IO_REQUEST object.
6009230557Sjimharris *
6010230557Sjimharris * @return SCI_STATUS
6011230557Sjimharris * @retval SCI_SUCCESS if the start io operation succeeds
6012230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
6013230557Sjimharris *         state to accept io requests.
6014230557Sjimharris */
6015230557Sjimharrisstatic
6016230557SjimharrisSCI_STATUS scic_sds_controller_ready_state_terminate_request_handler(
6017230557Sjimharris   SCI_BASE_CONTROLLER_T    *controller,
6018230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T *remote_device,
6019230557Sjimharris   SCI_BASE_REQUEST_T       *io_request
6020230557Sjimharris)
6021230557Sjimharris{
6022230557Sjimharris   SCIC_SDS_CONTROLLER_T    *this_controller = (SCIC_SDS_CONTROLLER_T *)
6023230557Sjimharris                                               controller;
6024230557Sjimharris   SCIC_SDS_REQUEST_T       *the_request     = (SCIC_SDS_REQUEST_T *)
6025230557Sjimharris                                               io_request;
6026230557Sjimharris   SCI_STATUS                status;
6027230557Sjimharris
6028230557Sjimharris   status = scic_sds_io_request_terminate(the_request);
6029230557Sjimharris   if (status == SCI_SUCCESS)
6030230557Sjimharris   {
6031230557Sjimharris      // Utilize the original post context command and or in the POST_TC_ABORT
6032230557Sjimharris      // request sub-type.
6033230557Sjimharris      scic_sds_controller_post_request(
6034230557Sjimharris         this_controller,
6035230557Sjimharris         scic_sds_request_get_post_context(the_request)
6036230557Sjimharris         | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT
6037230557Sjimharris      );
6038230557Sjimharris   }
6039230557Sjimharris
6040230557Sjimharris   return status;
6041230557Sjimharris}
6042230557Sjimharris
6043230557Sjimharris/**
6044230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
6045230557Sjimharris * link up handler is called.  This method will perform the following:
6046230557Sjimharris *    - Stop the phy timer
6047230557Sjimharris *    - Start the next phy
6048230557Sjimharris *    - Report the link up condition to the port object
6049230557Sjimharris *
6050230557Sjimharris * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the link up
6051230557Sjimharris *       notification.
6052230557Sjimharris * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
6053230557Sjimharris * @param[in] phy This is the SCIC_SDS_PHY which has gone link up.
6054230557Sjimharris *
6055230557Sjimharris * @return none
6056230557Sjimharris */
6057230557Sjimharrisstatic
6058230557Sjimharrisvoid scic_sds_controller_ready_state_link_up_handler(
6059230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
6060230557Sjimharris   SCIC_SDS_PORT_T       *port,
6061230557Sjimharris   SCIC_SDS_PHY_T        *phy
6062230557Sjimharris)
6063230557Sjimharris{
6064230557Sjimharris   this_controller->port_agent.link_up_handler(
6065230557Sjimharris      this_controller, &this_controller->port_agent, port, phy
6066230557Sjimharris   );
6067230557Sjimharris}
6068230557Sjimharris
6069230557Sjimharris/**
6070230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
6071230557Sjimharris * link down handler is called.
6072230557Sjimharris *    - Report the link down condition to the port object
6073230557Sjimharris *
6074230557Sjimharris * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the
6075230557Sjimharris *       link down notification.
6076230557Sjimharris * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
6077230557Sjimharris * @param[in] phy This is the SCIC_SDS_PHY which has gone link down.
6078230557Sjimharris *
6079230557Sjimharris * @return none
6080230557Sjimharris */
6081230557Sjimharrisstatic
6082230557Sjimharrisvoid scic_sds_controller_ready_state_link_down_handler(
6083230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller,
6084230557Sjimharris   SCIC_SDS_PORT_T       *port,
6085230557Sjimharris   SCIC_SDS_PHY_T        *phy
6086230557Sjimharris)
6087230557Sjimharris{
6088230557Sjimharris   this_controller->port_agent.link_down_handler(
6089230557Sjimharris      this_controller, &this_controller->port_agent, port, phy
6090230557Sjimharris   );
6091230557Sjimharris}
6092230557Sjimharris
6093230557Sjimharris//*****************************************************************************
6094230557Sjimharris//* STOPPING STATE HANDLERS
6095230557Sjimharris//*****************************************************************************
6096230557Sjimharris
6097230557Sjimharris/**
6098230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in a stopping state
6099230557Sjimharris * and the complete io handler is called.
6100230557Sjimharris *    - This function is not yet implemented
6101230557Sjimharris *
6102230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6103230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
6104230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6105230557Sjimharris *       SCIC_SDS_REMOTE_DEVICE object.
6106230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
6107230557Sjimharris *       SCIC_SDS_IO_REQUEST object.
6108230557Sjimharris *
6109230557Sjimharris * @return SCI_STATUS
6110230557Sjimharris * @retval SCI_FAILURE
6111230557Sjimharris */
6112230557Sjimharrisstatic
6113230557SjimharrisSCI_STATUS scic_sds_controller_stopping_state_complete_io_handler(
6114230557Sjimharris   SCI_BASE_CONTROLLER_T    *controller,
6115230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T *remote_device,
6116230557Sjimharris   SCI_BASE_REQUEST_T       *io_request
6117230557Sjimharris)
6118230557Sjimharris{
6119230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6120230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
6121230557Sjimharris
6122230557Sjimharris   /// @todo Implement this function
6123230557Sjimharris   return SCI_FAILURE;
6124230557Sjimharris}
6125230557Sjimharris
6126230557Sjimharris/**
6127230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in a stopping state
6128230557Sjimharris * and the a remote device has stopped.
6129230557Sjimharris *
6130230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6131230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
6132230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6133230557Sjimharris *       SCIC_SDS_REMOTE_DEVICE object.
6134230557Sjimharris *
6135230557Sjimharris * @return none
6136230557Sjimharris */
6137230557Sjimharrisstatic
6138230557Sjimharrisvoid scic_sds_controller_stopping_state_device_stopped_handler(
6139230557Sjimharris   SCIC_SDS_CONTROLLER_T    * controller,
6140230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T * remote_device
6141230557Sjimharris)
6142230557Sjimharris{
6143230557Sjimharris   if (!scic_sds_controller_has_remote_devices_stopping(controller))
6144230557Sjimharris   {
6145230557Sjimharris      sci_base_state_machine_change_state(
6146230557Sjimharris         &controller->parent.state_machine,
6147230557Sjimharris         SCI_BASE_CONTROLLER_STATE_STOPPED
6148230557Sjimharris      );
6149230557Sjimharris   }
6150230557Sjimharris}
6151230557Sjimharris
6152230557Sjimharris//*****************************************************************************
6153230557Sjimharris//* STOPPED STATE HANDLERS
6154230557Sjimharris//*****************************************************************************
6155230557Sjimharris
6156230557Sjimharris//*****************************************************************************
6157230557Sjimharris//* FAILED STATE HANDLERS
6158230557Sjimharris//*****************************************************************************
6159230557Sjimharris
6160230557Sjimharris/**
6161230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER failed state start
6162230557Sjimharris * io/task handler is in place.
6163230557Sjimharris *    - Issue a warning message
6164230557Sjimharris *
6165230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6166230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
6167230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
6168230557Sjimharris *       used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
6169230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
6170230557Sjimharris *       would be cast to a SCIC_SDS_IO_REQUEST.
6171230557Sjimharris * @param[in] io_tag This is the IO tag to be assigned to the IO request or
6172230557Sjimharris *       SCI_CONTROLLER_INVALID_IO_TAG.
6173230557Sjimharris *
6174230557Sjimharris * @return SCI_FAILURE
6175230557Sjimharris * @retval SCI_FAILURE
6176230557Sjimharris */
6177230557Sjimharrisstatic
6178230557SjimharrisSCI_STATUS scic_sds_controller_failed_state_start_operation_handler(
6179230557Sjimharris   SCI_BASE_CONTROLLER_T    *controller,
6180230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T *remote_device,
6181230557Sjimharris   SCI_BASE_REQUEST_T       *io_request,
6182230557Sjimharris   U16                       io_tag
6183230557Sjimharris)
6184230557Sjimharris{
6185230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6186230557Sjimharris   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
6187230557Sjimharris
6188230557Sjimharris   SCIC_LOG_WARNING((
6189230557Sjimharris      sci_base_object_get_logger(this_controller),
6190230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
6191230557Sjimharris      "SCIC Controller requested to start an io/task from failed state %d\n",
6192230557Sjimharris      sci_base_state_machine_get_state(
6193230557Sjimharris         scic_sds_controller_get_base_state_machine(this_controller))
6194230557Sjimharris   ));
6195230557Sjimharris
6196230557Sjimharris   return SCI_FAILURE;
6197230557Sjimharris}
6198230557Sjimharris
6199230557Sjimharris/**
6200230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the failed state
6201230557Sjimharris * reset handler is in place.
6202230557Sjimharris *    - Transition to SCI_BASE_CONTROLLER_STATE_RESETTING
6203230557Sjimharris *
6204230557Sjimharris * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
6205230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6206230557Sjimharris *
6207230557Sjimharris * @return SCI_STATUS
6208230557Sjimharris * @retval SCI_FAILURE if fatal memory error occurred
6209230557Sjimharris */
6210230557Sjimharrisstatic
6211230557SjimharrisSCI_STATUS scic_sds_controller_failed_state_reset_handler(
6212230557Sjimharris   SCI_BASE_CONTROLLER_T *controller
6213230557Sjimharris)
6214230557Sjimharris{
6215230557Sjimharris    SCIC_SDS_CONTROLLER_T *this_controller;
6216230557Sjimharris    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
6217230557Sjimharris
6218230557Sjimharris    if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR) {
6219230557Sjimharris        SCIC_LOG_TRACE((
6220230557Sjimharris           sci_base_object_get_logger(controller),
6221230557Sjimharris           SCIC_LOG_OBJECT_CONTROLLER,
6222230557Sjimharris           "scic_sds_controller_resetting_state_enter(0x%x) enter\n not allowed with fatal memory error",
6223230557Sjimharris           controller
6224230557Sjimharris        ));
6225230557Sjimharris
6226230557Sjimharris        return SCI_FAILURE;
6227230557Sjimharris    } else {
6228230557Sjimharris        return scic_sds_controller_general_reset_handler(controller);
6229230557Sjimharris    }
6230230557Sjimharris}
6231230557Sjimharris
6232230557Sjimharris/**
6233230557Sjimharris * This method is called when the SCIC_SDS_CONTROLLER is in the failed state
6234230557Sjimharris * and the terminate request handler is called.
6235230557Sjimharris *    - call the io request terminate function
6236230557Sjimharris *    - if successful
6237230557Sjimharris *       - post the terminate request to the SCU hardware
6238230557Sjimharris *
6239230557Sjimharris * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6240230557Sjimharris *       into a SCIC_SDS_CONTROLLER object.
6241230557Sjimharris * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6242230557Sjimharris *       SCIC_SDS_REMOTE_DEVICE object.
6243230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
6244230557Sjimharris *       SCIC_SDS_IO_REQUEST object.
6245230557Sjimharris *
6246230557Sjimharris * @return SCI_STATUS
6247230557Sjimharris * @retval SCI_SUCCESS if the start io operation succeeds
6248230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
6249230557Sjimharris *         state to accept io requests.
6250230557Sjimharris */
6251230557Sjimharrisstatic
6252230557SjimharrisSCI_STATUS scic_sds_controller_failed_state_terminate_request_handler(
6253230557Sjimharris   SCI_BASE_CONTROLLER_T    *controller,
6254230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T *remote_device,
6255230557Sjimharris   SCI_BASE_REQUEST_T       *io_request
6256230557Sjimharris)
6257230557Sjimharris{
6258230557Sjimharris   SCIC_SDS_REQUEST_T       *the_request     = (SCIC_SDS_REQUEST_T *)
6259230557Sjimharris                                               io_request;
6260230557Sjimharris
6261230557Sjimharris   return scic_sds_io_request_terminate(the_request);
6262230557Sjimharris}
6263230557Sjimharris
6264230557SjimharrisSCIC_SDS_CONTROLLER_STATE_HANDLER_T
6265230557Sjimharris   scic_sds_controller_state_handler_table[SCI_BASE_CONTROLLER_MAX_STATES] =
6266230557Sjimharris{
6267230557Sjimharris   // SCI_BASE_CONTROLLER_STATE_INITIAL
6268230557Sjimharris   {
6269230557Sjimharris      {
6270230557Sjimharris         NULL,
6271230557Sjimharris         NULL,
6272230557Sjimharris         NULL,
6273230557Sjimharris         NULL,
6274230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6275230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6276230557Sjimharris         scic_sds_controller_default_request_handler,
6277230557Sjimharris         scic_sds_controller_default_request_handler,
6278230557Sjimharris         scic_sds_controller_default_request_handler,
6279230557Sjimharris         NULL,
6280230557Sjimharris         NULL
6281230557Sjimharris      },
6282230557Sjimharris      scic_sds_controller_default_request_handler,
6283230557Sjimharris      NULL,
6284230557Sjimharris      NULL,
6285230557Sjimharris      NULL,
6286230557Sjimharris      NULL
6287230557Sjimharris   },
6288230557Sjimharris   // SCI_BASE_CONTROLLER_STATE_RESET
6289230557Sjimharris   {
6290230557Sjimharris      {
6291230557Sjimharris         NULL,
6292230557Sjimharris         NULL,
6293230557Sjimharris         NULL,
6294230557Sjimharris         scic_sds_controller_reset_state_initialize_handler,
6295230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6296230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6297230557Sjimharris         scic_sds_controller_default_request_handler,
6298230557Sjimharris         scic_sds_controller_default_request_handler,
6299230557Sjimharris         scic_sds_controller_default_request_handler,
6300230557Sjimharris         NULL,
6301230557Sjimharris         NULL
6302230557Sjimharris      },
6303230557Sjimharris      scic_sds_controller_default_request_handler,
6304230557Sjimharris      NULL,
6305230557Sjimharris      NULL,
6306230557Sjimharris      NULL,
6307230557Sjimharris      NULL
6308230557Sjimharris   },
6309230557Sjimharris   // SCI_BASE_CONTROLLER_STATE_INITIALIZING
6310230557Sjimharris   {
6311230557Sjimharris      {
6312230557Sjimharris         NULL,
6313230557Sjimharris         NULL,
6314230557Sjimharris         NULL,
6315230557Sjimharris         NULL,
6316230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6317230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6318230557Sjimharris         scic_sds_controller_default_request_handler,
6319230557Sjimharris         scic_sds_controller_default_request_handler,
6320230557Sjimharris         scic_sds_controller_default_request_handler,
6321230557Sjimharris         NULL,
6322230557Sjimharris         NULL
6323230557Sjimharris      },
6324230557Sjimharris      scic_sds_controller_default_request_handler,
6325230557Sjimharris      NULL,
6326230557Sjimharris      NULL,
6327230557Sjimharris      NULL,
6328230557Sjimharris      NULL
6329230557Sjimharris   },
6330230557Sjimharris   // SCI_BASE_CONTROLLER_STATE_INITIALIZED
6331230557Sjimharris   {
6332230557Sjimharris      {
6333230557Sjimharris         scic_sds_controller_initialized_state_start_handler,
6334230557Sjimharris         NULL,
6335230557Sjimharris         NULL,
6336230557Sjimharris         NULL,
6337230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6338230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6339230557Sjimharris         scic_sds_controller_default_request_handler,
6340230557Sjimharris         scic_sds_controller_default_request_handler,
6341230557Sjimharris         scic_sds_controller_default_request_handler,
6342230557Sjimharris         NULL,
6343230557Sjimharris         NULL
6344230557Sjimharris      },
6345230557Sjimharris      scic_sds_controller_default_request_handler,
6346230557Sjimharris      NULL,
6347230557Sjimharris      NULL,
6348230557Sjimharris      NULL,
6349230557Sjimharris      NULL
6350230557Sjimharris   },
6351230557Sjimharris   // SCI_BASE_CONTROLLER_STATE_STARTING
6352230557Sjimharris   {
6353230557Sjimharris      {
6354230557Sjimharris         NULL,
6355230557Sjimharris         NULL,
6356230557Sjimharris         NULL,
6357230557Sjimharris         NULL,
6358230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6359230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6360230557Sjimharris         scic_sds_controller_default_request_handler,
6361230557Sjimharris         scic_sds_controller_default_request_handler,
6362230557Sjimharris         scic_sds_controller_default_request_handler,
6363230557Sjimharris         NULL,
6364230557Sjimharris         NULL
6365230557Sjimharris      },
6366230557Sjimharris      scic_sds_controller_default_request_handler,
6367230557Sjimharris      scic_sds_controller_starting_state_link_up_handler,
6368230557Sjimharris      scic_sds_controller_starting_state_link_down_handler,
6369230557Sjimharris      NULL,
6370230557Sjimharris      NULL
6371230557Sjimharris   },
6372230557Sjimharris   // SCI_BASE_CONTROLLER_STATE_READY
6373230557Sjimharris   {
6374230557Sjimharris      {
6375230557Sjimharris         NULL,
6376230557Sjimharris         scic_sds_controller_ready_state_stop_handler,
6377230557Sjimharris         scic_sds_controller_general_reset_handler,
6378230557Sjimharris         NULL,
6379230557Sjimharris         scic_sds_controller_ready_state_start_io_handler,
6380230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6381230557Sjimharris         scic_sds_controller_ready_state_complete_io_handler,
6382230557Sjimharris         scic_sds_controller_default_request_handler,
6383230557Sjimharris         scic_sds_controller_ready_state_continue_io_handler,
6384230557Sjimharris         scic_sds_controller_ready_state_start_task_handler,
6385230557Sjimharris         scic_sds_controller_ready_state_complete_io_handler
6386230557Sjimharris      },
6387230557Sjimharris      scic_sds_controller_ready_state_terminate_request_handler,
6388230557Sjimharris      scic_sds_controller_ready_state_link_up_handler,
6389230557Sjimharris      scic_sds_controller_ready_state_link_down_handler,
6390230557Sjimharris      NULL,
6391230557Sjimharris      NULL
6392230557Sjimharris   },
6393230557Sjimharris   // SCI_BASE_CONTROLLER_STATE_RESETTING
6394230557Sjimharris   {
6395230557Sjimharris      {
6396230557Sjimharris         NULL,
6397230557Sjimharris         NULL,
6398230557Sjimharris         NULL,
6399230557Sjimharris         NULL,
6400230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6401230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6402230557Sjimharris         scic_sds_controller_default_request_handler,
6403230557Sjimharris         scic_sds_controller_default_request_handler,
6404230557Sjimharris         scic_sds_controller_default_request_handler,
6405230557Sjimharris         NULL,
6406230557Sjimharris         NULL
6407230557Sjimharris      },
6408230557Sjimharris      scic_sds_controller_default_request_handler,
6409230557Sjimharris      NULL,
6410230557Sjimharris      NULL,
6411230557Sjimharris      NULL,
6412230557Sjimharris      NULL
6413230557Sjimharris   },
6414230557Sjimharris   // SCI_BASE_CONTROLLER_STATE_STOPPING
6415230557Sjimharris   {
6416230557Sjimharris      {
6417230557Sjimharris         NULL,
6418230557Sjimharris         NULL,
6419230557Sjimharris         NULL,
6420230557Sjimharris         NULL,
6421230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6422230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6423230557Sjimharris         scic_sds_controller_stopping_state_complete_io_handler,
6424230557Sjimharris         scic_sds_controller_default_request_handler,
6425230557Sjimharris         scic_sds_controller_default_request_handler,
6426230557Sjimharris         NULL,
6427230557Sjimharris         NULL
6428230557Sjimharris      },
6429230557Sjimharris      scic_sds_controller_default_request_handler,
6430230557Sjimharris      NULL,
6431230557Sjimharris      NULL,
6432230557Sjimharris      NULL,
6433230557Sjimharris      scic_sds_controller_stopping_state_device_stopped_handler
6434230557Sjimharris   },
6435230557Sjimharris   // SCI_BASE_CONTROLLER_STATE_STOPPED
6436230557Sjimharris   {
6437230557Sjimharris      {
6438230557Sjimharris         NULL,
6439230557Sjimharris         NULL,
6440230557Sjimharris         scic_sds_controller_failed_state_reset_handler,
6441230557Sjimharris         NULL,
6442230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6443230557Sjimharris         scic_sds_controller_default_start_operation_handler,
6444230557Sjimharris         scic_sds_controller_default_request_handler,
6445230557Sjimharris         scic_sds_controller_default_request_handler,
6446230557Sjimharris         scic_sds_controller_default_request_handler,
6447230557Sjimharris         NULL,
6448230557Sjimharris         NULL
6449230557Sjimharris      },
6450230557Sjimharris      scic_sds_controller_default_request_handler,
6451230557Sjimharris      NULL,
6452230557Sjimharris      NULL,
6453230557Sjimharris      NULL,
6454230557Sjimharris      NULL
6455230557Sjimharris   },
6456230557Sjimharris   // SCI_BASE_CONTROLLER_STATE_FAILED
6457230557Sjimharris   {
6458230557Sjimharris      {
6459230557Sjimharris         NULL,
6460230557Sjimharris         NULL,
6461230557Sjimharris         scic_sds_controller_general_reset_handler,
6462230557Sjimharris         NULL,
6463230557Sjimharris         scic_sds_controller_failed_state_start_operation_handler,
6464230557Sjimharris         scic_sds_controller_failed_state_start_operation_handler,
6465230557Sjimharris         scic_sds_controller_default_request_handler,
6466230557Sjimharris         scic_sds_controller_default_request_handler,
6467230557Sjimharris         scic_sds_controller_default_request_handler,
6468230557Sjimharris         NULL,
6469230557Sjimharris         NULL
6470230557Sjimharris      },
6471230557Sjimharris      scic_sds_controller_failed_state_terminate_request_handler,
6472230557Sjimharris      NULL,
6473230557Sjimharris      NULL,
6474230557Sjimharris      NULL
6475230557Sjimharris   }
6476230557Sjimharris};
6477230557Sjimharris
6478230557Sjimharris/**
6479230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6480230557Sjimharris * entry to the SCI_BASE_CONTROLLER_STATE_INITIAL.
6481230557Sjimharris *    - Set the state handlers to the controllers initial state.
6482230557Sjimharris *
6483230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6484230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6485230557Sjimharris *
6486230557Sjimharris * @return none
6487230557Sjimharris *
6488230557Sjimharris * @todo This function should initialze the controller object.
6489230557Sjimharris */
6490230557Sjimharrisstatic
6491230557Sjimharrisvoid scic_sds_controller_initial_state_enter(
6492230557Sjimharris   SCI_BASE_OBJECT_T *object
6493230557Sjimharris)
6494230557Sjimharris{
6495230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6496230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6497230557Sjimharris
6498230557Sjimharris   scic_sds_controller_set_base_state_handlers(
6499230557Sjimharris      this_controller, SCI_BASE_CONTROLLER_STATE_INITIAL);
6500230557Sjimharris
6501230557Sjimharris   sci_base_state_machine_change_state(
6502230557Sjimharris      &this_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_RESET);
6503230557Sjimharris}
6504230557Sjimharris
6505230557Sjimharris/**
6506230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6507230557Sjimharris * entry to the SCI_BASE_CONTROLLER_STATE_RESET.
6508230557Sjimharris *    - Set the state handlers to the controllers reset state.
6509230557Sjimharris *
6510230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6511230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6512230557Sjimharris *
6513230557Sjimharris * @return none
6514230557Sjimharris */
6515230557Sjimharrisstatic
6516230557Sjimharrisvoid scic_sds_controller_reset_state_enter(
6517230557Sjimharris   SCI_BASE_OBJECT_T *object
6518230557Sjimharris)
6519230557Sjimharris{
6520230557Sjimharris   U8 index;
6521230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6522230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6523230557Sjimharris
6524230557Sjimharris   scic_sds_controller_set_base_state_handlers(
6525230557Sjimharris      this_controller, SCI_BASE_CONTROLLER_STATE_RESET);
6526230557Sjimharris
6527230557Sjimharris   scic_sds_port_configuration_agent_construct(&this_controller->port_agent);
6528230557Sjimharris
6529230557Sjimharris   // Construct the ports for this controller
6530230557Sjimharris   for (index = 0; index < (SCI_MAX_PORTS + 1); index++)
6531230557Sjimharris   {
6532230557Sjimharris      scic_sds_port_construct(
6533230557Sjimharris         &this_controller->port_table[index],
6534230557Sjimharris         (index == SCI_MAX_PORTS) ? SCIC_SDS_DUMMY_PORT : index,
6535230557Sjimharris         this_controller
6536230557Sjimharris      );
6537230557Sjimharris   }
6538230557Sjimharris
6539230557Sjimharris   // Construct the phys for this controller
6540230557Sjimharris   for (index = 0; index < SCI_MAX_PHYS; index++)
6541230557Sjimharris   {
6542230557Sjimharris      // Add all the PHYs to the dummy port
6543230557Sjimharris      scic_sds_phy_construct(
6544230557Sjimharris         &this_controller->phy_table[index],
6545230557Sjimharris         &this_controller->port_table[SCI_MAX_PORTS],
6546230557Sjimharris         index
6547230557Sjimharris      );
6548230557Sjimharris   }
6549230557Sjimharris
6550230557Sjimharris   this_controller->invalid_phy_mask = 0;
6551230557Sjimharris
6552230557Sjimharris   // Set the default maximum values
6553230557Sjimharris   this_controller->completion_event_entries      = SCU_EVENT_COUNT;
6554230557Sjimharris   this_controller->completion_queue_entries      = SCU_COMPLETION_QUEUE_COUNT;
6555230557Sjimharris   this_controller->remote_node_entries           = SCI_MAX_REMOTE_DEVICES;
6556230557Sjimharris   this_controller->logical_port_entries          = SCI_MAX_PORTS;
6557230557Sjimharris   this_controller->task_context_entries          = SCU_IO_REQUEST_COUNT;
6558230557Sjimharris   this_controller->uf_control.buffers.count      = SCU_UNSOLICITED_FRAME_COUNT;
6559230557Sjimharris   this_controller->uf_control.address_table.count= SCU_UNSOLICITED_FRAME_COUNT;
6560230557Sjimharris
6561230557Sjimharris   // Initialize the User and OEM parameters to default values.
6562230557Sjimharris   scic_sds_controller_set_default_config_parameters(this_controller);
6563230557Sjimharris}
6564230557Sjimharris
6565230557Sjimharris/**
6566230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6567230557Sjimharris * entry to the SCI_BASE_CONTROLLER_STATE_INITIALIZING.
6568230557Sjimharris *    - Set the state handlers to the controllers initializing state.
6569230557Sjimharris *
6570230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6571230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6572230557Sjimharris *
6573230557Sjimharris * @return none
6574230557Sjimharris */
6575230557Sjimharrisstatic
6576230557Sjimharrisvoid scic_sds_controller_initializing_state_enter(
6577230557Sjimharris   SCI_BASE_OBJECT_T *object
6578230557Sjimharris)
6579230557Sjimharris{
6580230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6581230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6582230557Sjimharris
6583230557Sjimharris   scic_sds_controller_set_base_state_handlers(
6584230557Sjimharris      this_controller, SCI_BASE_CONTROLLER_STATE_INITIALIZING);
6585230557Sjimharris}
6586230557Sjimharris
6587230557Sjimharris/**
6588230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6589230557Sjimharris * entry to the SCI_BASE_CONTROLLER_STATE_INITIALIZED.
6590230557Sjimharris *    - Set the state handlers to the controllers initialized state.
6591230557Sjimharris *
6592230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6593230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6594230557Sjimharris *
6595230557Sjimharris * @return none
6596230557Sjimharris */
6597230557Sjimharrisstatic
6598230557Sjimharrisvoid scic_sds_controller_initialized_state_enter(
6599230557Sjimharris   SCI_BASE_OBJECT_T *object
6600230557Sjimharris)
6601230557Sjimharris{
6602230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6603230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6604230557Sjimharris
6605230557Sjimharris   scic_sds_controller_set_base_state_handlers(
6606230557Sjimharris      this_controller, SCI_BASE_CONTROLLER_STATE_INITIALIZED);
6607230557Sjimharris}
6608230557Sjimharris
6609230557Sjimharris/**
6610230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6611230557Sjimharris * entry to the SCI_BASE_CONTROLLER_STATE_STARTING.
6612230557Sjimharris *    - Set the state handlers to the controllers starting state.
6613230557Sjimharris *
6614230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6615230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6616230557Sjimharris *
6617230557Sjimharris * @return none
6618230557Sjimharris */
6619230557Sjimharrisstatic
6620230557Sjimharrisvoid scic_sds_controller_starting_state_enter(
6621230557Sjimharris   SCI_BASE_OBJECT_T *object
6622230557Sjimharris)
6623230557Sjimharris{
6624230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6625230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6626230557Sjimharris
6627230557Sjimharris   scic_sds_controller_set_base_state_handlers(
6628230557Sjimharris      this_controller, SCI_BASE_CONTROLLER_STATE_STARTING);
6629230557Sjimharris
6630230557Sjimharris}
6631230557Sjimharris
6632230557Sjimharris/**
6633230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
6634230557Sjimharris * from the SCI_BASE_CONTROLLER_STATE_STARTING.
6635230557Sjimharris *    - This function stops the controller starting timeout timer.
6636230557Sjimharris *
6637230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6638230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6639230557Sjimharris *
6640230557Sjimharris * @return none
6641230557Sjimharris */
6642230557Sjimharrisstatic
6643230557Sjimharrisvoid scic_sds_controller_starting_state_exit(
6644230557Sjimharris   SCI_BASE_OBJECT_T *object
6645230557Sjimharris)
6646230557Sjimharris{
6647230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6648230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6649230557Sjimharris
6650230557Sjimharris   scic_cb_timer_stop(object, this_controller->timeout_timer);
6651230557Sjimharris
6652230557Sjimharris   // We are done with this timer since we are exiting the starting
6653230557Sjimharris   // state so remove it
6654230557Sjimharris   scic_cb_timer_destroy(
6655230557Sjimharris      this_controller,
6656230557Sjimharris      this_controller->phy_startup_timer
6657230557Sjimharris   );
6658230557Sjimharris
6659230557Sjimharris   this_controller->phy_startup_timer = NULL;
6660230557Sjimharris}
6661230557Sjimharris
6662230557Sjimharris/**
6663230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6664230557Sjimharris * entry to the SCI_BASE_CONTROLLER_STATE_READY.
6665230557Sjimharris *    - Set the state handlers to the controllers ready state.
6666230557Sjimharris *
6667230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6668230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6669230557Sjimharris *
6670230557Sjimharris * @return none
6671230557Sjimharris */
6672230557Sjimharrisstatic
6673230557Sjimharrisvoid scic_sds_controller_ready_state_enter(
6674230557Sjimharris   SCI_BASE_OBJECT_T *object
6675230557Sjimharris)
6676230557Sjimharris{
6677230557Sjimharris   U32 clock_gating_unit_value;
6678230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6679230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6680230557Sjimharris
6681230557Sjimharris   scic_sds_controller_set_base_state_handlers(
6682230557Sjimharris      this_controller, SCI_BASE_CONTROLLER_STATE_READY);
6683230557Sjimharris
6684230557Sjimharris   /**
6685230557Sjimharris    * enable clock gating for power control of the scu unit
6686230557Sjimharris    */
6687230557Sjimharris   clock_gating_unit_value = SMU_CGUCR_READ(this_controller);
6688230557Sjimharris
6689230557Sjimharris   clock_gating_unit_value &= ~( SMU_CGUCR_GEN_BIT(REGCLK_ENABLE)
6690230557Sjimharris                               | SMU_CGUCR_GEN_BIT(TXCLK_ENABLE)
6691230557Sjimharris                               | SMU_CGUCR_GEN_BIT(XCLK_ENABLE) );
6692230557Sjimharris   clock_gating_unit_value |= SMU_CGUCR_GEN_BIT(IDLE_ENABLE);
6693230557Sjimharris
6694230557Sjimharris   SMU_CGUCR_WRITE(this_controller, clock_gating_unit_value);
6695230557Sjimharris
6696230557Sjimharris   //set the default interrupt coalescence number and timeout value.
6697230557Sjimharris   scic_controller_set_interrupt_coalescence(
6698230557Sjimharris      this_controller, 0x10, 250);
6699230557Sjimharris}
6700230557Sjimharris
6701230557Sjimharris/**
6702230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
6703230557Sjimharris * from the SCI_BASE_CONTROLLER_STATE_READY.
6704230557Sjimharris *    - This function does nothing.
6705230557Sjimharris *
6706230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6707230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6708230557Sjimharris *
6709230557Sjimharris * @return none
6710230557Sjimharris */
6711230557Sjimharrisstatic
6712230557Sjimharrisvoid scic_sds_controller_ready_state_exit(
6713230557Sjimharris   SCI_BASE_OBJECT_T *object
6714230557Sjimharris)
6715230557Sjimharris{
6716230557Sjimharris   U32 clock_gating_unit_value;
6717230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6718230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6719230557Sjimharris
6720230557Sjimharris   /**
6721230557Sjimharris    * restore clock gating for power control of the scu unit
6722230557Sjimharris    */
6723230557Sjimharris   clock_gating_unit_value = SMU_CGUCR_READ(this_controller);
6724230557Sjimharris
6725230557Sjimharris   clock_gating_unit_value &= ~SMU_CGUCR_GEN_BIT(IDLE_ENABLE);
6726230557Sjimharris   clock_gating_unit_value |= ( SMU_CGUCR_GEN_BIT(REGCLK_ENABLE)
6727230557Sjimharris                              | SMU_CGUCR_GEN_BIT(TXCLK_ENABLE)
6728230557Sjimharris                              | SMU_CGUCR_GEN_BIT(XCLK_ENABLE) );
6729230557Sjimharris
6730230557Sjimharris   SMU_CGUCR_WRITE(this_controller, clock_gating_unit_value);
6731230557Sjimharris
6732230557Sjimharris   //disable interrupt coalescence.
6733230557Sjimharris   scic_controller_set_interrupt_coalescence(this_controller, 0, 0);
6734230557Sjimharris}
6735230557Sjimharris
6736230557Sjimharris/**
6737230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6738230557Sjimharris * entry to the SCI_BASE_CONTROLLER_STATE_READY.
6739230557Sjimharris *    - Set the state handlers to the controllers ready state.
6740230557Sjimharris *    - Stop all of the remote devices on this controller
6741230557Sjimharris *    - Stop the ports on this controller
6742230557Sjimharris *    - Stop the phys on this controller
6743230557Sjimharris *
6744230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6745230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6746230557Sjimharris *
6747230557Sjimharris * @return none
6748230557Sjimharris */
6749230557Sjimharrisstatic
6750230557Sjimharrisvoid scic_sds_controller_stopping_state_enter(
6751230557Sjimharris   SCI_BASE_OBJECT_T *object
6752230557Sjimharris)
6753230557Sjimharris{
6754230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6755230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6756230557Sjimharris
6757230557Sjimharris   scic_sds_controller_set_base_state_handlers(
6758230557Sjimharris      this_controller, SCI_BASE_CONTROLLER_STATE_STOPPING);
6759230557Sjimharris
6760230557Sjimharris   // Stop all of the components for this controller in the reverse order
6761230557Sjimharris   // from which they are initialized.
6762230557Sjimharris   scic_sds_controller_stop_devices(this_controller);
6763230557Sjimharris   scic_sds_controller_stop_ports(this_controller);
6764230557Sjimharris
6765230557Sjimharris   if (!scic_sds_controller_has_remote_devices_stopping(this_controller))
6766230557Sjimharris   {
6767230557Sjimharris      sci_base_state_machine_change_state(
6768230557Sjimharris         &this_controller->parent.state_machine,
6769230557Sjimharris         SCI_BASE_CONTROLLER_STATE_STOPPED
6770230557Sjimharris      );
6771230557Sjimharris   }
6772230557Sjimharris}
6773230557Sjimharris
6774230557Sjimharris/**
6775230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
6776230557Sjimharris * from the SCI_BASE_CONTROLLER_STATE_STOPPING.
6777230557Sjimharris *    - This function stops the controller stopping timeout timer.
6778230557Sjimharris *
6779230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6780230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6781230557Sjimharris *
6782230557Sjimharris * @return none
6783230557Sjimharris */
6784230557Sjimharrisstatic
6785230557Sjimharrisvoid scic_sds_controller_stopping_state_exit(
6786230557Sjimharris   SCI_BASE_OBJECT_T *object
6787230557Sjimharris)
6788230557Sjimharris{
6789230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6790230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6791230557Sjimharris
6792230557Sjimharris   scic_cb_timer_stop(this_controller, this_controller->timeout_timer);
6793230557Sjimharris}
6794230557Sjimharris
6795230557Sjimharris/**
6796230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6797230557Sjimharris * entry to the SCI_BASE_CONTROLLER_STATE_STOPPED.
6798230557Sjimharris *    - Set the state handlers to the controllers stopped state.
6799230557Sjimharris *
6800230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6801230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6802230557Sjimharris *
6803230557Sjimharris * @return none
6804230557Sjimharris */
6805230557Sjimharrisstatic
6806230557Sjimharrisvoid scic_sds_controller_stopped_state_enter(
6807230557Sjimharris   SCI_BASE_OBJECT_T *object
6808230557Sjimharris)
6809230557Sjimharris{
6810230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6811230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6812230557Sjimharris
6813230557Sjimharris   scic_sds_controller_set_base_state_handlers(
6814230557Sjimharris      this_controller, SCI_BASE_CONTROLLER_STATE_STOPPED);
6815230557Sjimharris
6816230557Sjimharris   // We are done with this timer until the next timer we initialize
6817230557Sjimharris   scic_cb_timer_destroy(
6818230557Sjimharris      this_controller,
6819230557Sjimharris      this_controller->timeout_timer
6820230557Sjimharris   );
6821230557Sjimharris   this_controller->timeout_timer = NULL;
6822230557Sjimharris
6823230557Sjimharris   // Controller has stopped so disable all the phys on this controller
6824230557Sjimharris   scic_sds_controller_stop_phys(this_controller);
6825230557Sjimharris
6826230557Sjimharris   scic_sds_port_configuration_agent_destroy(
6827230557Sjimharris      this_controller,
6828230557Sjimharris      &this_controller->port_agent
6829230557Sjimharris   );
6830230557Sjimharris
6831230557Sjimharris   scic_cb_controller_stop_complete(this_controller, SCI_SUCCESS);
6832230557Sjimharris}
6833230557Sjimharris
6834230557Sjimharris/**
6835230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6836230557Sjimharris * entry to the SCI_BASE_CONTROLLER_STATE_RESETTING.
6837230557Sjimharris *    - Set the state handlers to the controllers resetting state.
6838230557Sjimharris *    - Write to the SCU hardware reset register to force a reset
6839230557Sjimharris *    - Transition to the SCI_BASE_CONTROLLER_STATE_RESET
6840230557Sjimharris *
6841230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6842230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6843230557Sjimharris *
6844230557Sjimharris * @return none
6845230557Sjimharris */
6846230557Sjimharrisstatic
6847230557Sjimharrisvoid scic_sds_controller_resetting_state_enter(
6848230557Sjimharris   SCI_BASE_OBJECT_T *object
6849230557Sjimharris)
6850230557Sjimharris{
6851230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6852230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6853230557Sjimharris
6854230557Sjimharris   SCIC_LOG_TRACE((
6855230557Sjimharris      sci_base_object_get_logger(this_controller),
6856230557Sjimharris      SCIC_LOG_OBJECT_CONTROLLER,
6857230557Sjimharris      "scic_sds_controller_resetting_state_enter(0x%x) enter\n",
6858230557Sjimharris      this_controller
6859230557Sjimharris   ));
6860230557Sjimharris
6861230557Sjimharris   scic_sds_controller_set_base_state_handlers(
6862230557Sjimharris      this_controller, SCI_BASE_CONTROLLER_STATE_RESETTING);
6863230557Sjimharris
6864230557Sjimharris   scic_sds_controller_reset_hardware(this_controller);
6865230557Sjimharris
6866230557Sjimharris   sci_base_state_machine_change_state(
6867230557Sjimharris      scic_sds_controller_get_base_state_machine(this_controller),
6868230557Sjimharris      SCI_BASE_CONTROLLER_STATE_RESET
6869230557Sjimharris   );
6870230557Sjimharris}
6871230557Sjimharris
6872230557Sjimharrisstatic
6873230557SjimharrisSCI_STATUS scic_sds_abort_reqests(
6874230557Sjimharris        SCIC_SDS_CONTROLLER_T * controller,
6875230557Sjimharris        SCIC_SDS_REMOTE_DEVICE_T * remote_device,
6876230557Sjimharris        SCIC_SDS_PORT_T * port
6877230557Sjimharris)
6878230557Sjimharris{
6879230557Sjimharris    SCI_STATUS          status           = SCI_SUCCESS;
6880230557Sjimharris    SCI_STATUS          terminate_status = SCI_SUCCESS;
6881230557Sjimharris    SCIC_SDS_REQUEST_T *the_request;
6882230557Sjimharris    U32                 index;
6883230557Sjimharris    U32                 request_count;
6884230557Sjimharris
6885230557Sjimharris    if (remote_device != NULL)
6886230557Sjimharris        request_count = remote_device->started_request_count;
6887230557Sjimharris    else if (port != NULL)
6888230557Sjimharris        request_count = port->started_request_count;
6889230557Sjimharris    else
6890230557Sjimharris        request_count = SCI_MAX_IO_REQUESTS;
6891230557Sjimharris
6892230557Sjimharris
6893230557Sjimharris    for (index = 0;
6894230557Sjimharris         (index < SCI_MAX_IO_REQUESTS) && (request_count > 0);
6895230557Sjimharris         index++)
6896230557Sjimharris    {
6897230557Sjimharris       the_request = controller->io_request_table[index];
6898230557Sjimharris
6899230557Sjimharris       if (the_request != NULL)
6900230557Sjimharris       {
6901230557Sjimharris           if (the_request->target_device == remote_device
6902230557Sjimharris                   || the_request->target_device->owning_port == port
6903230557Sjimharris                   || (remote_device == NULL && port == NULL))
6904230557Sjimharris           {
6905230557Sjimharris               terminate_status = scic_controller_terminate_request(
6906230557Sjimharris                                     controller,
6907230557Sjimharris                                     the_request->target_device,
6908230557Sjimharris                                     the_request
6909230557Sjimharris                                  );
6910230557Sjimharris
6911230557Sjimharris               if (terminate_status != SCI_SUCCESS)
6912230557Sjimharris                  status = terminate_status;
6913230557Sjimharris
6914230557Sjimharris               request_count--;
6915230557Sjimharris           }
6916230557Sjimharris       }
6917230557Sjimharris    }
6918230557Sjimharris
6919230557Sjimharris    return status;
6920230557Sjimharris}
6921230557Sjimharris
6922230557SjimharrisSCI_STATUS scic_sds_terminate_reqests(
6923230557Sjimharris        SCIC_SDS_CONTROLLER_T *this_controller,
6924230557Sjimharris        SCIC_SDS_REMOTE_DEVICE_T *this_remote_device,
6925230557Sjimharris        SCIC_SDS_PORT_T *this_port
6926230557Sjimharris)
6927230557Sjimharris{
6928230557Sjimharris    SCI_STATUS status = SCI_SUCCESS;
6929230557Sjimharris    SCI_STATUS abort_status = SCI_SUCCESS;
6930230557Sjimharris
6931230557Sjimharris    // move all request to abort state
6932230557Sjimharris    abort_status = scic_sds_abort_reqests(this_controller, this_remote_device, this_port);
6933230557Sjimharris
6934230557Sjimharris    if (abort_status != SCI_SUCCESS)
6935230557Sjimharris        status = abort_status;
6936230557Sjimharris
6937230557Sjimharris    //move all request to complete state
6938230557Sjimharris    if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR)
6939230557Sjimharris        abort_status = scic_sds_abort_reqests(this_controller, this_remote_device, this_port);
6940230557Sjimharris
6941230557Sjimharris    if (abort_status != SCI_SUCCESS)
6942230557Sjimharris        status = abort_status;
6943230557Sjimharris
6944230557Sjimharris    return status;
6945230557Sjimharris}
6946230557Sjimharris
6947230557Sjimharrisstatic
6948230557SjimharrisSCI_STATUS scic_sds_terminate_all_requests(
6949230557Sjimharris        SCIC_SDS_CONTROLLER_T * controller
6950230557Sjimharris)
6951230557Sjimharris{
6952230557Sjimharris    return scic_sds_terminate_reqests(controller, NULL, NULL);
6953230557Sjimharris}
6954230557Sjimharris
6955230557Sjimharris/**
6956230557Sjimharris * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6957230557Sjimharris * entry to the SCI_BASE_CONTROLLER_STATE_FAILED.
6958230557Sjimharris *    - Set the state handlers to the controllers failed state.
6959230557Sjimharris *
6960230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6961230557Sjimharris *       SCIC_SDS_CONTROLLER object.
6962230557Sjimharris *
6963230557Sjimharris * @return none
6964230557Sjimharris */
6965230557Sjimharrisstatic
6966230557Sjimharrisvoid scic_sds_controller_failed_state_enter(
6967230557Sjimharris   SCI_BASE_OBJECT_T *object
6968230557Sjimharris)
6969230557Sjimharris{
6970230557Sjimharris   SCIC_SDS_CONTROLLER_T *this_controller;
6971230557Sjimharris   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6972230557Sjimharris
6973230557Sjimharris   scic_sds_controller_set_base_state_handlers(
6974230557Sjimharris      this_controller, SCI_BASE_CONTROLLER_STATE_FAILED);
6975230557Sjimharris
6976230557Sjimharris   if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR)
6977230557Sjimharris   scic_sds_terminate_all_requests(this_controller);
6978230557Sjimharris   else
6979230557Sjimharris       scic_sds_controller_release_resource(this_controller);
6980230557Sjimharris
6981230557Sjimharris   //notify framework the controller failed.
6982230557Sjimharris   scic_cb_controller_error(this_controller,
6983230557Sjimharris           this_controller->parent.error);
6984230557Sjimharris}
6985230557Sjimharris
6986230557Sjimharris// ---------------------------------------------------------------------------
6987230557Sjimharris
6988230557SjimharrisSCI_BASE_STATE_T
6989230557Sjimharris   scic_sds_controller_state_table[SCI_BASE_CONTROLLER_MAX_STATES] =
6990230557Sjimharris{
6991230557Sjimharris   {
6992230557Sjimharris      SCI_BASE_CONTROLLER_STATE_INITIAL,
6993230557Sjimharris      scic_sds_controller_initial_state_enter,
6994230557Sjimharris      NULL,
6995230557Sjimharris   },
6996230557Sjimharris   {
6997230557Sjimharris      SCI_BASE_CONTROLLER_STATE_RESET,
6998230557Sjimharris      scic_sds_controller_reset_state_enter,
6999230557Sjimharris      NULL,
7000230557Sjimharris   },
7001230557Sjimharris   {
7002230557Sjimharris      SCI_BASE_CONTROLLER_STATE_INITIALIZING,
7003230557Sjimharris      scic_sds_controller_initializing_state_enter,
7004230557Sjimharris      NULL,
7005230557Sjimharris   },
7006230557Sjimharris   {
7007230557Sjimharris      SCI_BASE_CONTROLLER_STATE_INITIALIZED,
7008230557Sjimharris      scic_sds_controller_initialized_state_enter,
7009230557Sjimharris      NULL,
7010230557Sjimharris   },
7011230557Sjimharris   {
7012230557Sjimharris      SCI_BASE_CONTROLLER_STATE_STARTING,
7013230557Sjimharris      scic_sds_controller_starting_state_enter,
7014230557Sjimharris      scic_sds_controller_starting_state_exit,
7015230557Sjimharris   },
7016230557Sjimharris   {
7017230557Sjimharris      SCI_BASE_CONTROLLER_STATE_READY,
7018230557Sjimharris      scic_sds_controller_ready_state_enter,
7019230557Sjimharris      scic_sds_controller_ready_state_exit,
7020230557Sjimharris   },
7021230557Sjimharris   {
7022230557Sjimharris      SCI_BASE_CONTROLLER_STATE_RESETTING,
7023230557Sjimharris      scic_sds_controller_resetting_state_enter,
7024230557Sjimharris      NULL,
7025230557Sjimharris   },
7026230557Sjimharris   {
7027230557Sjimharris      SCI_BASE_CONTROLLER_STATE_STOPPING,
7028230557Sjimharris      scic_sds_controller_stopping_state_enter,
7029230557Sjimharris      scic_sds_controller_stopping_state_exit,
7030230557Sjimharris   },
7031230557Sjimharris   {
7032230557Sjimharris      SCI_BASE_CONTROLLER_STATE_STOPPED,
7033230557Sjimharris      scic_sds_controller_stopped_state_enter,
7034230557Sjimharris      NULL,
7035230557Sjimharris   },
7036230557Sjimharris   {
7037230557Sjimharris      SCI_BASE_CONTROLLER_STATE_FAILED,
7038230557Sjimharris      scic_sds_controller_failed_state_enter,
7039230557Sjimharris      NULL,
7040230557Sjimharris   }
7041230557Sjimharris};
7042230557Sjimharris
7043