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