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