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