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