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