2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
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.
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
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.
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.
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.
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
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
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.
55 #include <sys/cdefs.h>
56 __FBSDID("$FreeBSD$");
61 * @brief This file contains the implementation of the SCIC_SDS_CONTROLLER
62 * public, protected, and private methods.
65 #include <dev/isci/types.h>
66 #include <dev/isci/scil/sci_util.h>
67 #include <dev/isci/scil/scic_controller.h>
68 #include <dev/isci/scil/scic_port.h>
69 #include <dev/isci/scil/scic_phy.h>
70 #include <dev/isci/scil/scic_remote_device.h>
71 #include <dev/isci/scil/scic_user_callback.h>
72 #include <dev/isci/scil/scic_sds_pci.h>
73 #include <dev/isci/scil/scic_sds_library.h>
74 #include <dev/isci/scil/scic_sds_controller.h>
75 #include <dev/isci/scil/scic_sds_controller_registers.h>
76 #include <dev/isci/scil/scic_sds_port.h>
77 #include <dev/isci/scil/scic_sds_phy.h>
78 #include <dev/isci/scil/scic_sds_remote_device.h>
79 #include <dev/isci/scil/scic_sds_request.h>
80 #include <dev/isci/scil/scic_sds_logger.h>
81 #include <dev/isci/scil/scic_sds_port_configuration_agent.h>
82 #include <dev/isci/scil/scu_constants.h>
83 #include <dev/isci/scil/scu_event_codes.h>
84 #include <dev/isci/scil/scu_completion_codes.h>
85 #include <dev/isci/scil/scu_task_context.h>
86 #include <dev/isci/scil/scu_remote_node_context.h>
87 #include <dev/isci/scil/scu_unsolicited_frame.h>
88 #include <dev/isci/scil/intel_pci.h>
89 #include <dev/isci/scil/scic_sgpio.h>
90 #include <dev/isci/scil/scic_sds_phy_registers.h>
92 #define SCU_CONTEXT_RAM_INIT_STALL_TIME 200
93 #define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT 3
94 #define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT 3
96 #define SCU_MAX_ZPT_DWORD_INDEX 131
99 * The number of milliseconds to wait for a phy to start.
101 #define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT 100
104 * The number of milliseconds to wait while a given phy is consuming
105 * power before allowing another set of phys to consume power.
106 * Ultimately, this will be specified by OEM parameter.
108 #define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500
111 * This macro will return the cycle bit of the completion queue entry
113 #define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000)
116 * This macro will normalize the completion queue get pointer so its value
117 * can be used as an index into an array
119 #define NORMALIZE_GET_POINTER(x) \
120 ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK)
123 * This macro will normalize the completion queue put pointer so its value
124 * can be used as an array inde
126 #define NORMALIZE_PUT_POINTER(x) \
127 ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK)
131 * This macro will normalize the completion queue cycle pointer so it
132 * matches the completion queue cycle bit
134 #define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \
135 (((U32)(SMU_CQGR_CYCLE_BIT & (x))) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT))
138 * This macro will normalize the completion queue event entry so its value
139 * can be used as an index.
141 #define NORMALIZE_EVENT_POINTER(x) \
143 ((U32)((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK)) \
144 >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \
148 * This macro will increment the controllers completion queue index value
149 * and possibly toggle the cycle bit if the completion queue index wraps
152 #define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \
153 INCREMENT_QUEUE_GET( \
156 (controller)->completion_queue_entries, \
161 * This macro will increment the controllers event queue index value and
162 * possibly toggle the event cycle bit if the event queue index wraps back
165 #define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \
166 INCREMENT_QUEUE_GET( \
169 (controller)->completion_event_entries, \
170 SMU_CQGR_EVENT_CYCLE_BIT \
173 //****************************************************************************-
174 //* SCIC SDS Controller Initialization Methods
175 //****************************************************************************-
178 * @brief This timer is used to start another phy after we have given up on
179 * the previous phy to transition to the ready state.
181 * @param[in] controller
184 void scic_sds_controller_phy_startup_timeout_handler(
189 SCIC_SDS_CONTROLLER_T *this_controller;
190 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
192 this_controller->phy_startup_timer_pending = FALSE;
194 status = SCI_FAILURE;
196 while (status != SCI_SUCCESS)
198 status = scic_sds_controller_start_next_phy(this_controller);
203 * This method initializes the phy startup operations for controller start.
205 * @param this_controller
208 SCI_STATUS scic_sds_controller_initialize_phy_startup(
209 SCIC_SDS_CONTROLLER_T *this_controller
212 this_controller->phy_startup_timer = scic_cb_timer_create(
214 scic_sds_controller_phy_startup_timeout_handler,
218 if (this_controller->phy_startup_timer == NULL)
220 return SCI_FAILURE_INSUFFICIENT_RESOURCES;
224 this_controller->next_phy_to_start = 0;
225 this_controller->phy_startup_timer_pending = FALSE;
232 * This method initializes the power control operations for the controller
235 * @param this_controller
237 void scic_sds_controller_initialize_power_control(
238 SCIC_SDS_CONTROLLER_T *this_controller
241 this_controller->power_control.timer = scic_cb_timer_create(
243 scic_sds_controller_power_control_timer_handler,
248 this_controller->power_control.requesters,
250 sizeof(this_controller->power_control.requesters)
253 this_controller->power_control.phys_waiting = 0;
254 this_controller->power_control.remote_devices_granted_power = 0;
257 // ---------------------------------------------------------------------------
259 #define SCU_REMOTE_NODE_CONTEXT_ALIGNMENT (32)
260 #define SCU_TASK_CONTEXT_ALIGNMENT (256)
261 #define SCU_UNSOLICITED_FRAME_ADDRESS_ALIGNMENT (64)
262 #define SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT (1024)
263 #define SCU_UNSOLICITED_FRAME_HEADER_ALIGNMENT (64)
265 // ---------------------------------------------------------------------------
268 * @brief This method builds the memory descriptor table for this
271 * @param[in] this_controller This parameter specifies the controller
272 * object for which to build the memory table.
276 void scic_sds_controller_build_memory_descriptor_table(
277 SCIC_SDS_CONTROLLER_T *this_controller
280 sci_base_mde_construct(
281 &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
282 SCU_COMPLETION_RAM_ALIGNMENT,
283 (sizeof(U32) * this_controller->completion_queue_entries),
284 (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
287 sci_base_mde_construct(
288 &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
289 SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
290 this_controller->remote_node_entries * sizeof(SCU_REMOTE_NODE_CONTEXT_T),
291 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
294 sci_base_mde_construct(
295 &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
296 SCU_TASK_CONTEXT_ALIGNMENT,
297 this_controller->task_context_entries * sizeof(SCU_TASK_CONTEXT_T),
298 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
301 // The UF buffer address table size must be programmed to a power
302 // of 2. Find the first power of 2 that is equal to or greater then
303 // the number of unsolicited frame buffers to be utilized.
304 scic_sds_unsolicited_frame_control_set_address_table_count(
305 &this_controller->uf_control
308 sci_base_mde_construct(
309 &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
310 SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
311 scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
312 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
317 * @brief This method validates the driver supplied memory descriptor
320 * @param[in] this_controller
324 SCI_STATUS scic_sds_controller_validate_memory_descriptor_table(
325 SCIC_SDS_CONTROLLER_T *this_controller
330 mde_list_valid = sci_base_mde_is_valid(
331 &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
332 SCU_COMPLETION_RAM_ALIGNMENT,
333 (sizeof(U32) * this_controller->completion_queue_entries),
334 (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
337 if (mde_list_valid == FALSE)
338 return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
340 mde_list_valid = sci_base_mde_is_valid(
341 &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
342 SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
343 this_controller->remote_node_entries * sizeof(SCU_REMOTE_NODE_CONTEXT_T),
344 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
347 if (mde_list_valid == FALSE)
348 return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
350 mde_list_valid = sci_base_mde_is_valid(
351 &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
352 SCU_TASK_CONTEXT_ALIGNMENT,
353 this_controller->task_context_entries * sizeof(SCU_TASK_CONTEXT_T),
354 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
357 if (mde_list_valid == FALSE)
358 return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
360 mde_list_valid = sci_base_mde_is_valid(
361 &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
362 SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
363 scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
364 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
367 if (mde_list_valid == FALSE)
368 return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
374 * @brief This method initializes the controller with the physical memory
375 * addresses that are used to communicate with the driver.
377 * @param[in] this_controller
381 void scic_sds_controller_ram_initialization(
382 SCIC_SDS_CONTROLLER_T *this_controller
385 SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde;
387 // The completion queue is actually placed in cacheable memory
388 // Therefore it no longer comes out of memory in the MDL.
389 mde = &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE];
390 this_controller->completion_queue = (U32*) mde->virtual_address;
391 SMU_CQBAR_WRITE(this_controller, mde->physical_address);
393 // Program the location of the Remote Node Context table
395 mde = &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT];
396 this_controller->remote_node_context_table = (SCU_REMOTE_NODE_CONTEXT_T *)
397 mde->virtual_address;
398 SMU_RNCBAR_WRITE(this_controller, mde->physical_address);
400 // Program the location of the Task Context table into the SCU.
401 mde = &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT];
402 this_controller->task_context_table = (SCU_TASK_CONTEXT_T *)
403 mde->virtual_address;
404 SMU_HTTBAR_WRITE(this_controller, mde->physical_address);
406 mde = &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER];
407 scic_sds_unsolicited_frame_control_construct(
408 &this_controller->uf_control, mde, this_controller
411 // Inform the silicon as to the location of the UF headers and
415 this_controller->uf_control.headers.physical_address);
418 this_controller->uf_control.address_table.physical_address);
420 //enable the ECC correction and detection.
423 (SIGNLE_BIT_ERROR_CORRECTION_ENABLE
424 | MULTI_BIT_ERROR_REPORTING_ENABLE
425 | SINGLE_BIT_ERROR_REPORTING_ENABLE) );
428 (SIGNLE_BIT_ERROR_CORRECTION_ENABLE
429 | MULTI_BIT_ERROR_REPORTING_ENABLE
430 | SINGLE_BIT_ERROR_REPORTING_ENABLE) );
434 * @brief This method initializes the task context data for the controller.
436 * @param[in] this_controller
440 void scic_sds_controller_assign_task_entries(
441 SCIC_SDS_CONTROLLER_T *this_controller
446 // Assign all the TCs to function 0
447 // TODO: Do we actually need to read this register to write it back?
448 task_assignment = SMU_TCA_READ(this_controller, 0);
453 | (SMU_TCA_GEN_VAL(STARTING, 0))
454 | (SMU_TCA_GEN_VAL(ENDING, this_controller->task_context_entries - 1))
455 | (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE))
458 SMU_TCA_WRITE(this_controller, 0, task_assignment);
462 * @brief This method initializes the hardware completion queue.
464 * @param[in] this_controller
466 void scic_sds_controller_initialize_completion_queue(
467 SCIC_SDS_CONTROLLER_T *this_controller
471 U32 completion_queue_control_value;
472 U32 completion_queue_get_value;
473 U32 completion_queue_put_value;
475 this_controller->completion_queue_get = 0;
477 completion_queue_control_value = (
478 SMU_CQC_QUEUE_LIMIT_SET(this_controller->completion_queue_entries - 1)
479 | SMU_CQC_EVENT_LIMIT_SET(this_controller->completion_event_entries - 1)
482 SMU_CQC_WRITE(this_controller, completion_queue_control_value);
484 // Set the completion queue get pointer and enable the queue
485 completion_queue_get_value = (
486 (SMU_CQGR_GEN_VAL(POINTER, 0))
487 | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0))
488 | (SMU_CQGR_GEN_BIT(ENABLE))
489 | (SMU_CQGR_GEN_BIT(EVENT_ENABLE))
492 SMU_CQGR_WRITE(this_controller, completion_queue_get_value);
494 this_controller->completion_queue_get = completion_queue_get_value;
496 // Set the completion queue put pointer
497 completion_queue_put_value = (
498 (SMU_CQPR_GEN_VAL(POINTER, 0))
499 | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0))
502 SMU_CQPR_WRITE(this_controller, completion_queue_put_value);
504 // Initialize the cycle bit of the completion queue entries
505 for (index = 0; index < this_controller->completion_queue_entries; index++)
507 // If get.cycle_bit != completion_queue.cycle_bit
508 // its not a valid completion queue entry
509 // so at system start all entries are invalid
510 this_controller->completion_queue[index] = 0x80000000;
515 * @brief This method initializes the hardware unsolicited frame queue.
517 * @param[in] this_controller
519 void scic_sds_controller_initialize_unsolicited_frame_queue(
520 SCIC_SDS_CONTROLLER_T *this_controller
523 U32 frame_queue_control_value;
524 U32 frame_queue_get_value;
525 U32 frame_queue_put_value;
527 // Write the queue size
528 frame_queue_control_value =
529 SCU_UFQC_GEN_VAL(QUEUE_SIZE, this_controller->uf_control.address_table.count);
531 SCU_UFQC_WRITE(this_controller, frame_queue_control_value);
533 // Setup the get pointer for the unsolicited frame queue
534 frame_queue_get_value = (
535 SCU_UFQGP_GEN_VAL(POINTER, 0)
536 | SCU_UFQGP_GEN_BIT(ENABLE_BIT)
539 SCU_UFQGP_WRITE(this_controller, frame_queue_get_value);
541 // Setup the put pointer for the unsolicited frame queue
542 frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0);
544 SCU_UFQPP_WRITE(this_controller, frame_queue_put_value);
548 * @brief This method enables the hardware port task scheduler.
550 * @param[in] this_controller
552 void scic_sds_controller_enable_port_task_scheduler(
553 SCIC_SDS_CONTROLLER_T *this_controller
556 U32 port_task_scheduler_value;
558 port_task_scheduler_value = SCU_PTSGCR_READ(this_controller);
560 port_task_scheduler_value |=
561 (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE));
563 SCU_PTSGCR_WRITE(this_controller, port_task_scheduler_value);
566 // ---------------------------------------------------------------------------
568 #ifdef ARLINGTON_BUILD
570 * This method will read from the lexington status register. This is required
571 * as a read fence to the lexington register writes.
573 * @param this_controller
575 void scic_sds_controller_lex_status_read_fence(
576 SCIC_SDS_CONTROLLER_T *this_controller
582 lex_status = lex_register_read(
583 this_controller, this_controller->lex_registers + 0xC4);
586 sci_base_object_get_logger(this_controller),
587 SCIC_LOG_OBJECT_CONTROLLER,
588 "Controller 0x%x lex_status = 0x%08x\n",
589 this_controller, lex_status
594 * This method will initialize the arlington through the LEX_BAR.
596 * @param this_controller
598 void scic_sds_controller_lex_atux_initialization(
599 SCIC_SDS_CONTROLLER_T *this_controller
602 // 1. Reset all SCU PHY
604 this_controller, this_controller->lex_registers + 0x28, 0x0020FFFF) ;
606 // 2. Write to LEX_CTRL
608 this_controller, this_controller->lex_registers + 0xC0, 0x00000700);
610 scic_sds_controller_lex_status_read_fence(this_controller);
612 // 3. Enable PCI Master
614 this_controller, this_controller->lex_registers + 0x70, 0x00000002);
616 // 4. Enable SCU Register Clock Domain
618 this_controller, this_controller->lex_registers + 0xC0, 0x00000300);
620 scic_sds_controller_lex_status_read_fence(this_controller);
622 // 5.1 Release PHY-A Reg Reset
624 this_controller, this_controller->lex_registers + 0x28, 0x0000FFFF);
626 // 5.2 Initialize the AFE for PHY-A
627 scic_sds_controller_afe_initialization(this_controller);
629 scic_sds_controller_lex_status_read_fence(this_controller);
632 // 5.3 Release PHY Reg Reset
634 this_controller, this_controller->lex_registers + 0x28, 0x0000FFFF);
637 // 6.1 Release PHY-B Reg Reset
639 this_controller, this_controller->lex_registers + 0x28, 0x0040FFFF) ;
641 // 6.2 Initialize the AFE for PHY-B
642 scic_sds_controller_afe_initialization(this_controller);
644 scic_sds_controller_lex_status_read_fence(this_controller);
647 // 6.3 Release PHY-B Reg Reset
649 this_controller, this_controller->lex_registers + 0x28, 0x0040FFFF) ;
652 // 7. Enable SCU clock domaion
654 this_controller, this_controller->lex_registers + 0xC0, 0x00000100);
656 scic_sds_controller_lex_status_read_fence(this_controller);
658 // 8. Release LEX SCU Reset
660 this_controller, this_controller->lex_registers + 0xC0, 0x00000000);
662 scic_sds_controller_lex_status_read_fence(this_controller);
664 #if !defined(DISABLE_INTERRUPTS)
665 // 8a. Set legacy interrupts (SCU INTx to PCI-x INTA)
667 this_controller, this_controller->lex_registers + 0xC0, 0x00000800);
669 scic_sds_controller_lex_status_read_fence(this_controller);
673 // 9. Override TXOLVL
676 this_controller, this_controller->lex_registers + 0xC0, 0x27800000);
679 // 10. Release PHY-A & PHY-B Resets
681 this_controller, this_controller->lex_registers + 0x28, 0x0000FF77);
684 this_controller, this_controller->lex_registers + 0x28, 0x0000FF55);
687 this_controller, this_controller->lex_registers + 0x28, 0x0000FF11);
690 this_controller, this_controller->lex_registers + 0x28, 0x0000FF00);
693 this_controller, this_controller->lex_registers + 0x28, 0x0003FF00);
695 #endif // ARLINGTON_BUILD
697 // ---------------------------------------------------------------------------
699 #ifdef ARLINGTON_BUILD
701 * This method enables chipwatch on the arlington board
703 * @param[in] this_controller
705 void scic_sds_controller_enable_chipwatch(
706 SCIC_SDS_CONTROLLER_T *this_controller
710 this_controller, this_controller->lex_registers + 0x88, 0x09090909);
713 this_controller, this_controller->lex_registers + 0x8C, 0xcac9c862);
718 * This macro is used to delay between writes to the AFE registers
719 * during AFE initialization.
721 #define AFE_REGISTER_WRITE_DELAY 10
724 * Initialize the AFE for this phy index.
726 * @todo We need to read the AFE setup from the OEM parameters
728 * @param[in] this_controller
732 #if defined(ARLINGTON_BUILD)
733 void scic_sds_controller_afe_initialization(
734 SCIC_SDS_CONTROLLER_T *this_controller
737 // 1. Establish Power
738 // Hold Bias, PLL, and RX TX in reset and powerdown
740 // pe_afe0_txpdn0,1,2,3 = 1
741 // pe_afe0_rxpdn0,1,2,3 = 1
742 // pe_afe0_txrst0,1,2,3_n = 0
743 // pe_afe0_rxrst0,1,2,3_n = 0
747 scu_afe_register_write(
748 this_controller, afe_pll_control, 0x00247506);
750 // 2. Write 0x00000000 to AFE XCVR Ctrl2
751 scu_afe_register_write(
752 this_controller, afe_dfx_transceiver_status_clear, 0x00000000);
754 // 3. afe0_override_en = 0
755 // afe0_pll_dis_override = 0
756 // afe0_tx_rst_override = 0
758 // pe_afe0_txrate = 01
759 // pe_afe0_rxrate = 01
760 // pe_afe0_txdis = 11
762 // pe_afe0_txovlv = 9'b001110000
763 scu_afe_register_write(
764 this_controller, afe_transceiver_control0[0], 0x0700141e);
766 // 4. Configure PLL Unit
767 // Write 0x00200506 to AFE PLL Ctrl Register 0
768 scu_afe_register_write(this_controller, afe_pll_control, 0x00200506);
769 scu_afe_register_write(this_controller, afe_pll_dfx_control, 0x10000080);
771 // 5. Configure Bias Unit
772 scu_afe_register_write(this_controller, afe_bias_control[0], 0x00124814);
773 scu_afe_register_write(this_controller, afe_bias_control[1], 0x24900000);
775 // 6. Configure Transceiver Units
776 scu_afe_register_write(
777 this_controller, afe_transceiver_control0[0], 0x0702941e);
779 scu_afe_register_write(
780 this_controller, afe_transceiver_control1[0], 0x0000000a);
782 // 7. Configure RX Units
783 scu_afe_register_write(
784 this_controller, afe_transceiver_equalization_control[0], 0x00ba2223);
786 scu_afe_register_write(
787 this_controller, reserved_0028_003c[2], 0x00000000);
789 // 8. Configure TX Units
790 scu_afe_register_write(
791 this_controller, afe_dfx_transmit_control_register[0], 0x03815428);
793 // 9. Transfer control to PE signals
794 scu_afe_register_write(
795 this_controller, afe_dfx_transceiver_status_clear, 0x00000010);
797 // 10. Release PLL Powerdown
798 scu_afe_register_write(this_controller, afe_pll_control, 0x00200504);
800 // 11. Release PLL Reset
801 scu_afe_register_write(this_controller, afe_pll_control, 0x00200505);
803 // 12. Wait for PLL to Lock
804 // (afe0_comm_sta [1:0] should go to 1'b11, and
805 // [5:2] is 0x5, 0x6, 0x7, 0x8, or 0x9
806 scu_afe_register_write(this_controller, afe_pll_control, 0x00200501);
808 while ((scu_afe_register_read(this_controller, afe_common_status) & 0x03) != 0x03)
810 // Give time for the PLLs to lock
811 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
814 // 13. pe_afe0_rxpdn0 = 0
815 // pe_afe0_rxrst0 = 1
816 // pe_afe0_txrst0_n = 1
817 // pe_afe_txoob0_n = 0
818 scu_afe_register_write(
819 this_controller, afe_transceiver_control0[0], 0x07028c11);
822 #elif defined(PLEASANT_RIDGE_BUILD)
824 void scic_sds_controller_afe_initialization(
825 SCIC_SDS_CONTROLLER_T *this_controller
831 #if defined(SPREADSHEET_AFE_SETTINGS)
832 // Clear DFX Status registers
833 scu_afe_register_write(
834 this_controller, afe_dfx_master_control0, 0x0000000f);
835 // Configure bias currents to normal
836 scu_afe_register_write(
837 this_controller, afe_bias_control, 0x0000aa00);
839 scu_afe_register_write(
840 this_controller, afe_pll_control0, 0x80000908);
842 // Wait for the PLL to lock
845 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
846 afe_status = scu_afe_register_read(
847 this_controller, afe_common_block_status);
849 while((afe_status & 0x00001000) == 0);
851 for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
853 // Initialize transceiver channels
854 scu_afe_register_write(
855 this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000157);
856 // Configure transceiver modes
857 scu_afe_register_write(
858 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016d1a);
859 // Configure receiver parameters
860 scu_afe_register_write(
861 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01501014);
862 // Configure transmitter parameters
863 scu_afe_register_write(
864 this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00000000);
865 // Configure transmitter equalization
866 scu_afe_register_write(
867 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0, 0x000bdd08);
868 scu_afe_register_write(
869 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1, 0x000ffc00);
870 scu_afe_register_write(
871 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2, 0x000b7c09);
872 scu_afe_register_write(
873 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3, 0x000afc6e);
874 // Configure transmitter SSC parameters
875 scu_afe_register_write(
876 this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00000000);
877 // Configure receiver parameters
878 scu_afe_register_write(
879 this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x3208903f);
881 // Start power on sequence
882 // Enable bias currents to transceivers and wait 200ns
883 scu_afe_register_write(
884 this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000154);
885 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
886 // Take receiver out of power down and wait 200ns
887 scu_afe_register_write(
888 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x3801611a);
889 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
890 // Take receiver out of reset and wait 200ns
891 scu_afe_register_write(
892 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x3801631a);
893 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
894 // Take transmitter out of power down and wait 200ns
895 scu_afe_register_write(
896 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016318);
897 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
898 // Take transmitter out of reset and wait 200ns
899 scu_afe_register_write(
900 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016319);
901 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
902 // Take transmitter out of DC idle
903 scu_afe_register_write(
904 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016319);
905 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
908 // Transfer control to the PEs
909 scu_afe_register_write(
910 this_controller, afe_dfx_master_control0, 0x00010f00);
911 #else // !defined(SPREADSHEET_AFE_SETTINGS)
912 // These are the AFEE settings used by the SV group
913 // Clear DFX Status registers
914 scu_afe_register_write(
915 this_controller, afe_dfx_master_control0, 0x0081000f);
916 // Configure bias currents to normal
917 scu_afe_register_write(
918 this_controller, afe_bias_control, 0x0000aa00);
920 scu_afe_register_write(
921 this_controller, afe_pll_control0, 0x80000908);
923 // Wait for the PLL to lock
924 // Note: this is done later in the SV shell script however this looks
925 // like the location to do this since we have enabled the PLL.
928 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
929 afe_status = scu_afe_register_read(
930 this_controller, afe_common_block_status);
932 while((afe_status & 0x00001000) == 0);
934 // Make sure BIST is disabled
935 scu_afe_register_write(
936 this_controller, afe_dfx_master_control1, 0x00000000);
937 // Shorten SAS SNW lock time
938 scu_afe_register_write(
939 this_controller, afe_pmsn_master_control0, 0x7bd316ad);
941 for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
943 // Initialize transceiver channels
944 scu_afe_register_write(
945 this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000174);
946 // Configure SSC control
947 scu_afe_register_write(
948 this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00030000);
949 // Configure transceiver modes
950 scu_afe_register_write(
951 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0000651a);
952 // Power up TX RX and RX OOB
953 scu_afe_register_write(
954 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006518);
955 // Enable RX OOB Detect
956 scu_afe_register_write(
957 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006518);
958 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
960 // Configure transmitter parameters
961 scu_afe_register_write(
962 this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00000000);
963 // Configure transmitter equalization
964 scu_afe_register_write(
965 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0, 0x000bdd08);
966 scu_afe_register_write(
967 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1, 0x000ffc00);
968 scu_afe_register_write(
969 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2, 0x000b7c09);
970 scu_afe_register_write(
971 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3, 0x000afc6e);
972 // Configure transmitter SSC parameters
975 scu_afe_register_write(
976 this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000154);
977 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
980 scu_afe_register_write(
981 this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x00000080);
983 scu_afe_register_write(
984 this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x01041042);
985 // Enable DFE/FFE and freeze
986 scu_afe_register_write(
987 this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x320891bf);
989 // Take receiver out of power down and wait 200ns
990 scu_afe_register_write(
991 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006118);
992 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
993 // TX Electrical Idle
994 scu_afe_register_write(
995 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006108);
996 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
999 scu_afe_register_write(
1000 this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x0317108f);
1002 // Configure receiver parameters
1003 scu_afe_register_write(
1004 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01e00021);
1006 // Bring RX out of reset
1007 scu_afe_register_write(
1008 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006109);
1009 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1011 scu_afe_register_write(
1012 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006009);
1013 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1015 scu_afe_register_write(
1016 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006209);
1017 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1020 // Transfer control to the PEs
1021 scu_afe_register_write(
1022 this_controller, afe_dfx_master_control0, 0x00010f00);
1026 #elif defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
1028 void scic_sds_controller_afe_initialization(
1029 SCIC_SDS_CONTROLLER_T *this_controller
1034 U8 cable_selection_mask;
1037 (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_A0)
1038 && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_A2)
1039 && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_B0)
1040 && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_C0)
1041 && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_C1)
1044 // A programming bug has occurred if we are attempting to
1045 // support a PCI revision other than those listed. Default
1046 // to B0, and attempt to limp along if it isn't B0.
1048 this_controller->pci_revision = SCIC_SDS_PCI_REVISION_C1;
1051 cable_selection_mask =
1052 this_controller->oem_parameters.sds1.controller.cable_selection_mask;
1054 // These are the AFEE settings used by the SV group
1055 // Clear DFX Status registers
1056 scu_afe_register_write(
1057 this_controller, afe_dfx_master_control0, 0x0081000f);
1058 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1061 (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1062 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1063 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1066 // PM Rx Equalization Save, PM SPhy Rx Acknowledgement Timer, PM Stagger Timer
1067 scu_afe_register_write(
1068 this_controller, afe_pmsn_master_control2, 0x0007FFFF);
1069 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1072 // Configure bias currents to normal
1073 if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1074 scu_afe_register_write(this_controller, afe_bias_control, 0x00005500);
1075 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1076 scu_afe_register_write(this_controller, afe_bias_control, 0x00005A00);
1077 else if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1078 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) )
1079 scu_afe_register_write(this_controller, afe_bias_control, 0x00005F00);
1080 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1081 scu_afe_register_write(this_controller, afe_bias_control, 0x00005500);
1082 // For C0 the AFE BIAS Control is unchanged
1084 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1087 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1088 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1090 scu_afe_register_write(this_controller, afe_pll_control0, 0x80040908);
1092 else if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1093 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) )
1095 scu_afe_register_write(this_controller, afe_pll_control0, 0x80040A08);
1097 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1099 scu_afe_register_write(this_controller, afe_pll_control0, 0x80000b08);
1100 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1101 scu_afe_register_write(this_controller, afe_pll_control0, 0x00000b08);
1102 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1103 scu_afe_register_write(this_controller, afe_pll_control0, 0x80000b08);
1106 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1108 // Wait for the PLL to lock
1109 // Note: this is done later in the SV shell script however this looks
1110 // like the location to do this since we have enabled the PLL.
1113 afe_status = scu_afe_register_read(
1114 this_controller, afe_common_block_status);
1115 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1117 while((afe_status & 0x00001000) == 0);
1119 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1120 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1122 // Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us)
1123 scu_afe_register_write(
1124 this_controller, afe_pmsn_master_control0, 0x7bcc96ad);
1125 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1128 for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
1130 U8 cable_length_long = (cable_selection_mask >> phy_id) & 1;
1131 U8 cable_length_medium = (cable_selection_mask >> (phy_id + 4)) & 1;
1133 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1134 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1136 // All defaults, except the Receive Word Alignament/Comma Detect
1137 // Enable....(0xe800)
1138 scu_afe_register_write(
1139 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00004512
1141 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1143 scu_afe_register_write(
1144 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x0050100F
1146 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1148 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1150 // Configure transmitter SSC parameters
1151 scu_afe_register_write(
1152 this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00030000
1154 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1156 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1158 // Configure transmitter SSC parameters
1159 scu_afe_register_write(
1160 this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00010202
1162 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1164 // All defaults, except the Receive Word Alignament/Comma Detect
1165 // Enable....(0xe800)
1166 scu_afe_register_write(
1167 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00014500
1169 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1171 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1173 // Configure transmitter SSC parameters
1174 scu_afe_register_write(
1175 this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00010202
1177 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1179 // All defaults, except the Receive Word Alignament/Comma Detect
1180 // Enable....(0xe800)
1181 scu_afe_register_write(
1182 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0001C500
1184 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1186 // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1187 // & increase TX int & ext bias 20%....(0xe85c)
1188 if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1190 scu_afe_register_write(
1192 scu_afe_xcvr[phy_id].afe_channel_control,
1196 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1198 scu_afe_register_write(
1200 scu_afe_xcvr[phy_id].afe_channel_control,
1204 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1206 // Power down TX and RX (PWRDNTX and PWRDNRX)
1207 scu_afe_register_write(
1209 scu_afe_xcvr[phy_id].afe_channel_control,
1213 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1215 // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1216 // & increase TX int & ext bias 20%....(0xe85c)
1217 scu_afe_register_write(
1219 scu_afe_xcvr[phy_id].afe_channel_control,
1223 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1225 scu_afe_register_write(
1227 scu_afe_xcvr[phy_id].afe_channel_control,
1231 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1233 // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1234 // & increase TX int & ext bias 20%....(0xe85c)
1235 scu_afe_register_write(
1237 scu_afe_xcvr[phy_id].afe_channel_control,
1241 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1243 scu_afe_register_write(
1245 scu_afe_xcvr[phy_id].afe_channel_control,
1246 cable_length_long ? 0x000002F7 :
1247 cable_length_medium ? 0x000001F7 : 0x000001F7
1250 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1252 // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1253 // & increase TX int & ext bias 20%....(0xe85c)
1254 scu_afe_register_write(
1256 scu_afe_xcvr[phy_id].afe_channel_control,
1257 cable_length_long ? 0x000002F4 :
1258 cable_length_medium ? 0x000001F4 : 0x000001F4
1262 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1264 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1265 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1267 // Enable TX equalization (0xe824)
1268 scu_afe_register_write(
1270 scu_afe_xcvr[phy_id].afe_tx_control,
1273 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1276 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1277 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1278 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0) )
1280 // RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
1281 // RDD=0x0(RX Detect Enabled) ....(0xe800)
1282 scu_afe_register_write(
1283 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00004100);
1284 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1286 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1288 scu_afe_register_write(
1289 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00014100);
1290 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1292 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1294 scu_afe_register_write(
1295 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0001c100);
1296 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1300 if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1302 scu_afe_register_write(
1304 scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1308 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1310 scu_afe_register_write(
1312 scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1316 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1318 scu_afe_register_write(
1320 scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1323 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1325 // Enable TX equalization (0xe824)
1326 scu_afe_register_write(
1327 this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
1329 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1331 scu_afe_register_write(
1332 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01400c0f);
1333 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1335 scu_afe_register_write(
1336 this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x3f6f103f);
1337 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1339 // Enable TX equalization (0xe824)
1340 scu_afe_register_write(
1341 this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
1343 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1345 scu_afe_register_write(
1346 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1,
1347 cable_length_long ? 0x01500C0C :
1348 cable_length_medium ? 0x01400C0D : 0x02400C0D
1350 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1352 scu_afe_register_write(
1353 this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x000003e0);
1354 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1356 scu_afe_register_write(
1357 this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1358 cable_length_long ? 0x33091C1F :
1359 cable_length_medium ? 0x3315181F : 0x2B17161F
1361 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1363 // Enable TX equalization (0xe824)
1364 scu_afe_register_write(
1365 this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
1368 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1370 scu_afe_register_write(
1371 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0,
1372 this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control0
1374 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1376 scu_afe_register_write(
1377 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1,
1378 this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control1
1380 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1382 scu_afe_register_write(
1383 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2,
1384 this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control2
1386 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1388 scu_afe_register_write(
1389 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3,
1390 this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control3
1392 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1395 // Transfer control to the PEs
1396 scu_afe_register_write(
1397 this_controller, afe_dfx_master_control0, 0x00010f00);
1398 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1401 #error "Unsupported board type"
1404 //****************************************************************************-
1405 //* SCIC SDS Controller Internal Start/Stop Routines
1406 //****************************************************************************-
1410 * @brief This method will attempt to transition into the ready state
1411 * for the controller and indicate that the controller start
1412 * operation has completed if all criteria are met.
1414 * @param[in,out] this_controller This parameter indicates the controller
1415 * object for which to transition to ready.
1416 * @param[in] status This parameter indicates the status value to be
1417 * pass into the call to scic_cb_controller_start_complete().
1422 void scic_sds_controller_transition_to_ready(
1423 SCIC_SDS_CONTROLLER_T *this_controller,
1428 sci_base_object_get_logger(this_controller),
1429 SCIC_LOG_OBJECT_CONTROLLER,
1430 "scic_sds_controller_transition_to_ready(0x%x, 0x%x) enter\n",
1431 this_controller, status
1434 if (this_controller->parent.state_machine.current_state_id
1435 == SCI_BASE_CONTROLLER_STATE_STARTING)
1437 // We move into the ready state, because some of the phys/ports
1438 // may be up and operational.
1439 sci_base_state_machine_change_state(
1440 scic_sds_controller_get_base_state_machine(this_controller),
1441 SCI_BASE_CONTROLLER_STATE_READY
1444 scic_cb_controller_start_complete(this_controller, status);
1449 * @brief This method is the general timeout handler for the controller.
1450 * It will take the correct timetout action based on the current
1453 * @param[in] controller This parameter indicates the controller on which
1454 * a timeout occurred.
1458 void scic_sds_controller_timeout_handler(
1459 SCI_CONTROLLER_HANDLE_T controller
1462 SCI_BASE_CONTROLLER_STATES current_state;
1463 SCIC_SDS_CONTROLLER_T *this_controller;
1464 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
1466 current_state = sci_base_state_machine_get_state(
1467 scic_sds_controller_get_base_state_machine(this_controller)
1470 if (current_state == SCI_BASE_CONTROLLER_STATE_STARTING)
1472 scic_sds_controller_transition_to_ready(
1473 this_controller, SCI_FAILURE_TIMEOUT
1476 else if (current_state == SCI_BASE_CONTROLLER_STATE_STOPPING)
1478 sci_base_state_machine_change_state(
1479 scic_sds_controller_get_base_state_machine(this_controller),
1480 SCI_BASE_CONTROLLER_STATE_FAILED
1483 scic_cb_controller_stop_complete(controller, SCI_FAILURE_TIMEOUT);
1487 /// @todo Now what do we want to do in this case?
1489 sci_base_object_get_logger(this_controller),
1490 SCIC_LOG_OBJECT_CONTROLLER,
1491 "Controller timer fired when controller was not in a state being timed.\n"
1499 * @param[in] this_controller
1501 * @return SCI_STATUS
1503 SCI_STATUS scic_sds_controller_stop_ports(
1504 SCIC_SDS_CONTROLLER_T *this_controller
1509 SCI_STATUS port_status;
1511 status = SCI_SUCCESS;
1513 for (index = 0; index < this_controller->logical_port_entries; index++)
1515 port_status = this_controller->port_table[index].
1516 state_handlers->parent.stop_handler(&this_controller->port_table[index].parent);
1518 (port_status != SCI_SUCCESS)
1519 && (port_status != SCI_FAILURE_INVALID_STATE)
1522 status = SCI_FAILURE;
1525 sci_base_object_get_logger(this_controller),
1526 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
1527 "Controller stop operation failed to stop port %d because of status %d.\n",
1528 this_controller->port_table[index].logical_port_index, port_status
1539 * @param[in] this_controller
1542 void scic_sds_controller_phy_timer_start(
1543 SCIC_SDS_CONTROLLER_T *this_controller
1546 scic_cb_timer_start(
1548 this_controller->phy_startup_timer,
1549 SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
1552 this_controller->phy_startup_timer_pending = TRUE;
1558 * @param[in] this_controller
1560 void scic_sds_controller_phy_timer_stop(
1561 SCIC_SDS_CONTROLLER_T *this_controller
1566 this_controller->phy_startup_timer
1569 this_controller->phy_startup_timer_pending = FALSE;
1573 * @brief This method is called internally to determine whether the
1574 * controller start process is complete. This is only true when:
1575 * - all links have been given an opportunity to start
1576 * - have no indication of a connected device
1577 * - have an indication of a connected device and it has
1578 * finished the link training process.
1580 * @param[in] this_controller This parameter specifies the controller
1581 * object for which to start the next phy.
1585 BOOL scic_sds_controller_is_start_complete(
1586 SCIC_SDS_CONTROLLER_T *this_controller
1591 for (index = 0; index < SCI_MAX_PHYS; index++)
1593 SCIC_SDS_PHY_T *the_phy = & this_controller->phy_table[index];
1597 this_controller->oem_parameters.sds1.controller.mode_type
1598 == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
1602 this_controller->oem_parameters.sds1.controller.mode_type
1603 == SCIC_PORT_MANUAL_CONFIGURATION_MODE
1605 && (scic_sds_phy_get_port(the_phy) != SCI_INVALID_HANDLE)
1610 * The controller start operation is complete if and only
1612 * - all links have been given an opportunity to start
1613 * - have no indication of a connected device
1614 * - have an indication of a connected device and it has
1615 * finished the link training process.
1619 (the_phy->is_in_link_training == FALSE)
1620 && (the_phy->parent.state_machine.current_state_id
1621 == SCI_BASE_PHY_STATE_INITIAL)
1624 (the_phy->is_in_link_training == FALSE)
1625 && (the_phy->parent.state_machine.current_state_id
1626 == SCI_BASE_PHY_STATE_STOPPED)
1629 (the_phy->is_in_link_training == TRUE)
1630 && (the_phy->parent.state_machine.current_state_id
1631 == SCI_BASE_PHY_STATE_STARTING)
1634 this_controller->port_agent.phy_ready_mask
1635 != this_controller->port_agent.phy_configured_mask
1648 * @brief This method is called internally by the controller object to
1649 * start the next phy on the controller. If all the phys have
1650 * been starte, then this method will attempt to transition the
1651 * controller to the READY state and inform the user
1652 * (scic_cb_controller_start_complete()).
1654 * @param[in] this_controller This parameter specifies the controller
1655 * object for which to start the next phy.
1657 * @return SCI_STATUS
1659 SCI_STATUS scic_sds_controller_start_next_phy(
1660 SCIC_SDS_CONTROLLER_T *this_controller
1665 status = SCI_SUCCESS;
1667 if (this_controller->phy_startup_timer_pending == FALSE)
1669 if (this_controller->next_phy_to_start == SCI_MAX_PHYS)
1671 // The controller has successfully finished the start process.
1672 // Inform the SCI Core user and transition to the READY state.
1673 if (scic_sds_controller_is_start_complete(this_controller) == TRUE)
1675 scic_sds_controller_transition_to_ready(
1676 this_controller, SCI_SUCCESS
1682 SCIC_SDS_PHY_T * the_phy;
1684 the_phy = &this_controller->phy_table[this_controller->next_phy_to_start];
1687 this_controller->oem_parameters.sds1.controller.mode_type
1688 == SCIC_PORT_MANUAL_CONFIGURATION_MODE
1691 if (scic_sds_phy_get_port(the_phy) == SCI_INVALID_HANDLE)
1693 this_controller->next_phy_to_start++;
1695 // Caution recursion ahead be forwarned
1697 // The PHY was never added to a PORT in MPC mode so start the next phy in sequence
1698 // This phy will never go link up and will not draw power the OEM parameters either
1699 // configured the phy incorrectly for the PORT or it was never assigned to a PORT
1700 return scic_sds_controller_start_next_phy(this_controller);
1704 status = scic_phy_start(the_phy);
1706 if (status == SCI_SUCCESS)
1708 scic_sds_controller_phy_timer_start(this_controller);
1713 sci_base_object_get_logger(this_controller),
1714 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PHY,
1715 "Controller stop operation failed to stop phy %d because of status %d.\n",
1716 this_controller->phy_table[this_controller->next_phy_to_start].phy_index,
1721 this_controller->next_phy_to_start++;
1731 * @param[in] this_controller
1733 * @return SCI_STATUS
1735 SCI_STATUS scic_sds_controller_stop_phys(
1736 SCIC_SDS_CONTROLLER_T *this_controller
1741 SCI_STATUS phy_status;
1743 status = SCI_SUCCESS;
1745 for (index = 0; index < SCI_MAX_PHYS; index++)
1747 phy_status = scic_phy_stop(&this_controller->phy_table[index]);
1750 (phy_status != SCI_SUCCESS)
1751 && (phy_status != SCI_FAILURE_INVALID_STATE)
1754 status = SCI_FAILURE;
1757 sci_base_object_get_logger(this_controller),
1758 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PHY,
1759 "Controller stop operation failed to stop phy %d because of status %d.\n",
1760 this_controller->phy_table[index].phy_index, phy_status
1771 * @param[in] this_controller
1773 * @return SCI_STATUS
1775 SCI_STATUS scic_sds_controller_stop_devices(
1776 SCIC_SDS_CONTROLLER_T *this_controller
1781 SCI_STATUS device_status;
1783 status = SCI_SUCCESS;
1785 for (index = 0; index < this_controller->remote_node_entries; index++)
1787 if (this_controller->device_table[index] != SCI_INVALID_HANDLE)
1789 /// @todo What timeout value do we want to provide to this request?
1790 device_status = scic_remote_device_stop(this_controller->device_table[index], 0);
1793 (device_status != SCI_SUCCESS)
1794 && (device_status != SCI_FAILURE_INVALID_STATE)
1798 sci_base_object_get_logger(this_controller),
1799 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_SSP_REMOTE_TARGET,
1800 "Controller stop operation failed to stop device 0x%x because of status %d.\n",
1801 this_controller->device_table[index], device_status
1810 //****************************************************************************-
1811 //* SCIC SDS Controller Power Control (Staggered Spinup)
1812 //****************************************************************************-
1815 * This method starts the power control timer for this controller object.
1817 * @param this_controller
1820 void scic_sds_controller_power_control_timer_start(
1821 SCIC_SDS_CONTROLLER_T *this_controller
1824 scic_cb_timer_start(
1825 this_controller, this_controller->power_control.timer,
1826 SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL
1829 this_controller->power_control.timer_started = TRUE;
1833 * This method stops the power control timer for this controller object.
1835 * @param this_controller
1838 void scic_sds_controller_power_control_timer_stop(
1839 SCIC_SDS_CONTROLLER_T *this_controller
1842 if (this_controller->power_control.timer_started)
1845 this_controller, this_controller->power_control.timer
1848 this_controller->power_control.timer_started = FALSE;
1853 * This method stops and starts the power control timer for this controller object.
1855 * @param this_controller
1858 void scic_sds_controller_power_control_timer_restart(
1859 SCIC_SDS_CONTROLLER_T *this_controller
1862 scic_sds_controller_power_control_timer_stop(this_controller);
1863 scic_sds_controller_power_control_timer_start(this_controller);
1870 * @param[in] controller
1872 void scic_sds_controller_power_control_timer_handler(
1876 SCIC_SDS_CONTROLLER_T *this_controller;
1877 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
1879 this_controller->power_control.remote_devices_granted_power = 0;
1881 if (this_controller->power_control.phys_waiting == 0)
1883 this_controller->power_control.timer_started = FALSE;
1887 SCIC_SDS_PHY_T *the_phy = NULL;
1892 && (this_controller->power_control.phys_waiting != 0);
1895 if (this_controller->power_control.requesters[i] != NULL)
1897 if ( this_controller->power_control.remote_devices_granted_power <
1898 this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up
1901 the_phy = this_controller->power_control.requesters[i];
1902 this_controller->power_control.requesters[i] = NULL;
1903 this_controller->power_control.phys_waiting--;
1904 this_controller->power_control.remote_devices_granted_power ++;
1905 scic_sds_phy_consume_power_handler(the_phy);
1907 if (the_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
1910 SCIC_SDS_PHY_T * current_requester_phy;
1912 for (j = 0; j < SCI_MAX_PHYS; j++)
1914 current_requester_phy = this_controller->power_control.requesters[j];
1916 //Search the power_control queue to see if there are other phys attached to
1917 //the same remote device. If found, take all of them out of await_sas_power state.
1918 if (current_requester_phy != NULL &&
1919 current_requester_phy != the_phy &&
1920 current_requester_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high
1921 == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high &&
1922 current_requester_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low
1923 == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low)
1925 this_controller->power_control.requesters[j] = NULL;
1926 this_controller->power_control.phys_waiting--;
1927 scic_sds_phy_consume_power_handler(current_requester_phy);
1939 // It doesn't matter if the power list is empty, we need to start the
1940 // timer in case another phy becomes ready.
1941 scic_sds_controller_power_control_timer_start(this_controller);
1946 * @brief This method inserts the phy in the stagger spinup control queue.
1948 * @param[in] this_controller
1949 * @param[in] the_phy
1951 void scic_sds_controller_power_control_queue_insert(
1952 SCIC_SDS_CONTROLLER_T *this_controller,
1953 SCIC_SDS_PHY_T *the_phy
1956 ASSERT (the_phy != NULL);
1958 if( this_controller->power_control.remote_devices_granted_power <
1959 this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up
1962 this_controller->power_control.remote_devices_granted_power ++;
1963 scic_sds_phy_consume_power_handler(the_phy);
1965 //stop and start the power_control timer. When the timer fires, the
1966 //no_of_devices_granted_power will be set to 0
1967 scic_sds_controller_power_control_timer_restart (this_controller);
1971 //there are phys, attached to the same sas address as this phy, are already
1972 //in READY state, this phy don't need wait.
1974 SCIC_SDS_PHY_T * current_phy;
1975 for(i = 0; i < SCI_MAX_PHYS; i++)
1977 current_phy = &this_controller->phy_table[i];
1979 if (current_phy->parent.state_machine.current_state_id == SCI_BASE_PHY_STATE_READY &&
1980 current_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS &&
1981 current_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high
1982 == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high &&
1983 current_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low
1984 == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low)
1986 scic_sds_phy_consume_power_handler(the_phy);
1991 if (i == SCI_MAX_PHYS)
1993 //Add the phy in the waiting list
1994 this_controller->power_control.requesters[the_phy->phy_index] = the_phy;
1995 this_controller->power_control.phys_waiting++;
2001 * @brief This method removes the phy from the stagger spinup control
2004 * @param[in] this_controller
2005 * @param[in] the_phy
2007 void scic_sds_controller_power_control_queue_remove(
2008 SCIC_SDS_CONTROLLER_T *this_controller,
2009 SCIC_SDS_PHY_T *the_phy
2012 ASSERT (the_phy != NULL);
2014 if (this_controller->power_control.requesters[the_phy->phy_index] != NULL)
2016 this_controller->power_control.phys_waiting--;
2019 this_controller->power_control.requesters[the_phy->phy_index] = NULL;
2022 //****************************************************************************-
2023 //* SCIC SDS Controller Completion Routines
2024 //****************************************************************************-
2027 * @brief This method returns a TRUE value if the completion queue has
2028 * entries that can be processed
2030 * @param[in] this_controller
2033 * @retval TRUE if the completion queue has entries to process
2034 * FALSE if the completion queue has no entries to process
2037 BOOL scic_sds_controller_completion_queue_has_entries(
2038 SCIC_SDS_CONTROLLER_T *this_controller
2041 U32 get_value = this_controller->completion_queue_get;
2042 U32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK;
2044 NORMALIZE_GET_POINTER_CYCLE_BIT(get_value)
2045 == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
2054 // ---------------------------------------------------------------------------
2057 * @brief This method processes a task completion notification. This is
2058 * called from within the controller completion handler.
2060 * @param[in] this_controller
2061 * @param[in] completion_entry
2066 void scic_sds_controller_task_completion(
2067 SCIC_SDS_CONTROLLER_T *this_controller,
2068 U32 completion_entry
2072 SCIC_SDS_REQUEST_T *io_request;
2074 index = SCU_GET_COMPLETION_INDEX(completion_entry);
2075 io_request = this_controller->io_request_table[index];
2077 // Make sure that we really want to process this IO request
2079 (io_request != SCI_INVALID_HANDLE)
2080 && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)
2082 scic_sds_io_tag_get_sequence(io_request->io_tag)
2083 == this_controller->io_request_sequence[index]
2087 // Yep this is a valid io request pass it along to the io request handler
2088 scic_sds_io_request_tc_completion(io_request, completion_entry);
2093 * @brief This method processes an SDMA completion event. This is called
2094 * from within the controller completion handler.
2096 * @param[in] this_controller
2097 * @param[in] completion_entry
2102 void scic_sds_controller_sdma_completion(
2103 SCIC_SDS_CONTROLLER_T *this_controller,
2104 U32 completion_entry
2108 SCIC_SDS_REQUEST_T *io_request;
2109 SCIC_SDS_REMOTE_DEVICE_T *device;
2111 index = SCU_GET_COMPLETION_INDEX(completion_entry);
2113 switch (scu_get_command_request_type(completion_entry))
2115 case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC:
2116 case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC:
2117 io_request = this_controller->io_request_table[index];
2119 sci_base_object_get_logger(this_controller),
2120 SCIC_LOG_OBJECT_CONTROLLER
2121 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
2122 | SCIC_LOG_OBJECT_SSP_IO_REQUEST
2123 | SCIC_LOG_OBJECT_STP_IO_REQUEST,
2124 "SCIC SDS Completion type SDMA %x for io request %x\n",
2128 /// @todo For a post TC operation we need to fail the IO request
2131 case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC:
2132 case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC:
2133 case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC:
2134 device = this_controller->device_table[index];
2136 sci_base_object_get_logger(this_controller),
2137 SCIC_LOG_OBJECT_CONTROLLER
2138 | SCIC_LOG_OBJECT_SSP_REMOTE_TARGET
2139 | SCIC_LOG_OBJECT_SMP_REMOTE_TARGET
2140 | SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
2141 "SCIC SDS Completion type SDMA %x for remote device %x\n",
2145 /// @todo For a port RNC operation we need to fail the device
2150 sci_base_object_get_logger(this_controller),
2151 SCIC_LOG_OBJECT_CONTROLLER,
2152 "SCIC SDS Completion unknown SDMA completion type %x\n",
2158 /// This is an unexpected completion type and is un-recoverable
2159 /// Transition to the failed state and wait for a controller reset
2160 sci_base_state_machine_change_state(
2161 scic_sds_controller_get_base_state_machine(this_controller),
2162 SCI_BASE_CONTROLLER_STATE_FAILED
2167 * This method processes an unsolicited frame message. This is called from
2168 * within the controller completion handler.
2170 * @param[in] this_controller
2171 * @param[in] completion_entry
2176 void scic_sds_controller_unsolicited_frame(
2177 SCIC_SDS_CONTROLLER_T *this_controller,
2178 U32 completion_entry
2184 SCU_UNSOLICITED_FRAME_HEADER_T * frame_header;
2185 SCIC_SDS_PHY_T * phy;
2186 SCIC_SDS_REMOTE_DEVICE_T * device;
2188 SCI_STATUS result = SCI_FAILURE;
2190 frame_index = SCU_GET_FRAME_INDEX(completion_entry);
2193 = this_controller->uf_control.buffers.array[frame_index].header;
2194 this_controller->uf_control.buffers.array[frame_index].state
2195 = UNSOLICITED_FRAME_IN_USE;
2197 if (SCU_GET_FRAME_ERROR(completion_entry))
2199 /// @todo If the IAF frame or SIGNATURE FIS frame has an error will
2200 /// this cause a problem? We expect the phy initialization will
2201 /// fail if there is an error in the frame.
2202 scic_sds_controller_release_frame(this_controller, frame_index);
2206 if (frame_header->is_address_frame)
2208 index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
2209 phy = &this_controller->phy_table[index];
2212 result = scic_sds_phy_frame_handler(phy, frame_index);
2218 index = SCU_GET_COMPLETION_INDEX(completion_entry);
2220 if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
2222 // This is a signature fis or a frame from a direct attached SATA
2223 // device that has not yet been created. In either case forwared
2224 // the frame to the PE and let it take care of the frame data.
2225 index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
2226 phy = &this_controller->phy_table[index];
2227 result = scic_sds_phy_frame_handler(phy, frame_index);
2231 if (index < this_controller->remote_node_entries)
2232 device = this_controller->device_table[index];
2237 result = scic_sds_remote_device_frame_handler(device, frame_index);
2239 scic_sds_controller_release_frame(this_controller, frame_index);
2243 if (result != SCI_SUCCESS)
2245 /// @todo Is there any reason to report some additional error message
2246 /// when we get this failure notifiction?
2251 * @brief This method processes an event completion entry. This is called
2252 * from within the controller completion handler.
2254 * @param[in] this_controller
2255 * @param[in] completion_entry
2260 void scic_sds_controller_event_completion(
2261 SCIC_SDS_CONTROLLER_T *this_controller,
2262 U32 completion_entry
2266 SCIC_SDS_REQUEST_T *io_request;
2267 SCIC_SDS_REMOTE_DEVICE_T *device;
2268 SCIC_SDS_PHY_T *phy;
2270 index = SCU_GET_COMPLETION_INDEX(completion_entry);
2272 switch (scu_get_event_type(completion_entry))
2274 case SCU_EVENT_TYPE_SMU_COMMAND_ERROR:
2275 /// @todo The driver did something wrong and we need to fix the condtion.
2277 sci_base_object_get_logger(this_controller),
2278 SCIC_LOG_OBJECT_CONTROLLER,
2279 "SCIC Controller 0x%x received SMU command error 0x%x\n",
2280 this_controller, completion_entry
2284 case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR:
2285 // report fatal memory error
2286 this_controller->parent.error = SCI_CONTROLLER_FATAL_MEMORY_ERROR;
2288 sci_base_state_machine_change_state(
2289 scic_sds_controller_get_base_state_machine(this_controller),
2290 SCI_BASE_CONTROLLER_STATE_FAILED
2293 //continue as in following events
2294 case SCU_EVENT_TYPE_SMU_PCQ_ERROR:
2295 case SCU_EVENT_TYPE_SMU_ERROR:
2297 sci_base_object_get_logger(this_controller),
2298 SCIC_LOG_OBJECT_CONTROLLER,
2299 "SCIC Controller 0x%x received fatal controller event 0x%x\n",
2300 this_controller, completion_entry
2304 case SCU_EVENT_TYPE_TRANSPORT_ERROR:
2305 io_request = this_controller->io_request_table[index];
2306 scic_sds_io_request_event_handler(io_request, completion_entry);
2309 case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
2310 switch (scu_get_event_specifier(completion_entry))
2312 case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE:
2313 case SCU_EVENT_SPECIFIC_TASK_TIMEOUT:
2314 io_request = this_controller->io_request_table[index];
2315 if (io_request != SCI_INVALID_HANDLE)
2317 scic_sds_io_request_event_handler(io_request, completion_entry);
2322 sci_base_object_get_logger(this_controller),
2323 SCIC_LOG_OBJECT_CONTROLLER |
2324 SCIC_LOG_OBJECT_SMP_IO_REQUEST |
2325 SCIC_LOG_OBJECT_SSP_IO_REQUEST |
2326 SCIC_LOG_OBJECT_STP_IO_REQUEST,
2327 "SCIC Controller 0x%x received event 0x%x for io request object that doesnt exist.\n",
2328 this_controller, completion_entry
2333 case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT:
2334 device = this_controller->device_table[index];
2335 if (device != SCI_INVALID_HANDLE)
2337 scic_sds_remote_device_event_handler(device, completion_entry);
2342 sci_base_object_get_logger(this_controller),
2343 SCIC_LOG_OBJECT_CONTROLLER |
2344 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
2345 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
2346 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
2347 "SCIC Controller 0x%x received event 0x%x for remote device object that doesnt exist.\n",
2348 this_controller, completion_entry
2355 case SCU_EVENT_TYPE_BROADCAST_CHANGE:
2356 // direct the broadcast change event to the phy first and then let
2357 // the phy redirect the broadcast change to the port object
2358 case SCU_EVENT_TYPE_ERR_CNT_EVENT:
2359 // direct error counter event to the phy object since that is where
2360 // we get the event notification. This is a type 4 event.
2361 case SCU_EVENT_TYPE_OSSP_EVENT:
2362 index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
2363 phy = &this_controller->phy_table[index];
2364 scic_sds_phy_event_handler(phy, completion_entry);
2367 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
2368 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
2369 case SCU_EVENT_TYPE_RNC_OPS_MISC:
2370 if (index < this_controller->remote_node_entries)
2372 device = this_controller->device_table[index];
2376 scic_sds_remote_device_event_handler(device, completion_entry);
2382 sci_base_object_get_logger(this_controller),
2383 SCIC_LOG_OBJECT_CONTROLLER |
2384 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
2385 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
2386 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
2387 "SCIC Controller 0x%x received event 0x%x for remote device object 0x%0x that doesnt exist.\n",
2388 this_controller, completion_entry, index
2395 sci_base_object_get_logger(this_controller),
2396 SCIC_LOG_OBJECT_CONTROLLER,
2397 "SCIC Controller received unknown event code %x\n",
2405 * @brief This method is a private routine for processing the completion
2408 * @param[in] this_controller
2413 void scic_sds_controller_process_completions(
2414 SCIC_SDS_CONTROLLER_T *this_controller
2417 U32 completion_count = 0;
2418 U32 completion_entry;
2425 sci_base_object_get_logger(this_controller),
2426 SCIC_LOG_OBJECT_CONTROLLER,
2427 "scic_sds_controller_process_completions(0x%x) enter\n",
2432 sci_base_object_get_logger(this_controller),
2433 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2434 "completion queue beginning get : 0x%08x\n",
2435 this_controller->completion_queue_get
2438 // Get the component parts of the completion queue
2439 get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
2440 get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
2442 event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
2443 event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
2446 NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
2447 == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
2452 completion_entry = this_controller->completion_queue[get_index];
2453 INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
2456 sci_base_object_get_logger(this_controller),
2457 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2458 "completion queue entry : 0x%08x\n",
2462 switch (SCU_GET_COMPLETION_TYPE(completion_entry))
2464 case SCU_COMPLETION_TYPE_TASK:
2465 scic_sds_controller_task_completion(this_controller, completion_entry);
2468 case SCU_COMPLETION_TYPE_SDMA:
2469 scic_sds_controller_sdma_completion(this_controller, completion_entry);
2472 case SCU_COMPLETION_TYPE_UFI:
2473 scic_sds_controller_unsolicited_frame(this_controller, completion_entry);
2476 case SCU_COMPLETION_TYPE_EVENT:
2477 scic_sds_controller_event_completion(this_controller, completion_entry);
2480 case SCU_COMPLETION_TYPE_NOTIFY:
2481 // Presently we do the same thing with a notify event that we do with the
2482 // other event codes.
2483 INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
2484 scic_sds_controller_event_completion(this_controller, completion_entry);
2489 sci_base_object_get_logger(this_controller),
2490 SCIC_LOG_OBJECT_CONTROLLER,
2491 "SCIC Controller received unknown completion type %x\n",
2498 // Update the get register if we completed one or more entries
2499 if (completion_count > 0)
2501 this_controller->completion_queue_get =
2502 SMU_CQGR_GEN_BIT(ENABLE)
2503 | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
2504 | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
2505 | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index) ;
2507 SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
2511 sci_base_object_get_logger(this_controller),
2512 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2513 "completion queue ending get : 0x%08x\n",
2514 this_controller->completion_queue_get
2520 * @brief This method is a private routine for processing the completion
2523 * @param[in] this_controller
2528 void scic_sds_controller_transitioned_process_completions(
2529 SCIC_SDS_CONTROLLER_T * this_controller
2532 U32 completion_count = 0;
2533 U32 completion_entry;
2540 sci_base_object_get_logger(this_controller),
2541 SCIC_LOG_OBJECT_CONTROLLER,
2542 "scic_sds_controller_transitioned_process_completions(0x%x) enter\n",
2547 sci_base_object_get_logger(this_controller),
2548 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2549 "completion queue beginning get : 0x%08x\n",
2550 this_controller->completion_queue_get
2553 // Get the component parts of the completion queue
2554 get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
2555 get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
2557 event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
2558 event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
2561 NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
2562 == COMPLETION_QUEUE_CYCLE_BIT(
2563 this_controller->completion_queue[get_index])
2568 completion_entry = this_controller->completion_queue[get_index];
2569 INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
2572 sci_base_object_get_logger(this_controller),
2573 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2574 "completion queue entry : 0x%08x\n",
2578 switch (SCU_GET_COMPLETION_TYPE(completion_entry))
2580 case SCU_COMPLETION_TYPE_TASK:
2581 scic_sds_controller_task_completion(this_controller, completion_entry);
2584 case SCU_COMPLETION_TYPE_NOTIFY:
2585 INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
2588 case SCU_COMPLETION_TYPE_EVENT:
2589 case SCU_COMPLETION_TYPE_SDMA:
2590 case SCU_COMPLETION_TYPE_UFI:
2593 sci_base_object_get_logger(this_controller),
2594 SCIC_LOG_OBJECT_CONTROLLER,
2595 "SCIC Controller ignoring completion type %x\n",
2602 // Update the get register if we completed one or more entries
2603 if (completion_count > 0)
2605 this_controller->completion_queue_get =
2606 SMU_CQGR_GEN_BIT(ENABLE)
2607 | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
2608 | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
2609 | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index) ;
2611 SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
2615 sci_base_object_get_logger(this_controller),
2616 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2617 "completion queue ending get : 0x%08x\n",
2618 this_controller->completion_queue_get
2622 //****************************************************************************-
2623 //* SCIC SDS Controller Interrupt and Completion functions
2624 //****************************************************************************-
2627 * @brief This method provides standard (common) processing of interrupts
2628 * for polling and legacy based interrupts.
2630 * @param[in] controller
2631 * @param[in] interrupt_status
2633 * @return This method returns a boolean (BOOL) indication as to
2634 * whether an completions are pending to be processed.
2635 * @retval TRUE if an interrupt is to be processed
2636 * @retval FALSE if no interrupt was pending
2639 BOOL scic_sds_controller_standard_interrupt_handler(
2640 SCIC_SDS_CONTROLLER_T *this_controller,
2641 U32 interrupt_status
2644 BOOL is_completion_needed = FALSE;
2647 sci_base_object_get_logger(this_controller),
2648 SCIC_LOG_OBJECT_CONTROLLER,
2649 "scic_sds_controller_standard_interrupt_handler(0x%d,0x%d) enter\n",
2650 this_controller, interrupt_status
2654 (interrupt_status & SMU_ISR_QUEUE_ERROR)
2656 (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
2657 && (!scic_sds_controller_completion_queue_has_entries(this_controller))
2661 // We have a fatal error on the read of the completion queue bar
2663 // We have a fatal error there is nothing in the completion queue
2664 // but we have a report from the hardware that the queue is full
2665 /// @todo how do we request the a controller reset
2666 is_completion_needed = TRUE;
2667 this_controller->encountered_fatal_error = TRUE;
2670 if (scic_sds_controller_completion_queue_has_entries(this_controller))
2672 is_completion_needed = TRUE;
2675 return is_completion_needed;
2679 * @brief This is the method provided to handle polling for interrupts
2680 * for the controller object.
2682 * @param[in] controller
2685 * @retval TRUE if an interrupt is to be processed
2686 * @retval FALSE if no interrupt was pending
2689 BOOL scic_sds_controller_polling_interrupt_handler(
2690 SCI_CONTROLLER_HANDLE_T controller
2693 U32 interrupt_status;
2694 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
2697 sci_base_object_get_logger(controller),
2698 SCIC_LOG_OBJECT_CONTROLLER,
2699 "scic_sds_controller_polling_interrupt_handler(0x%d) enter\n",
2704 * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the hardware
2705 * indicates nothing is pending. Since we are not being called from a real
2706 * interrupt, we don't want to confuse the hardware by servicing the
2707 * completion queue before the hardware indicates it is ready. We'll
2708 * simply wait for another polling interval and check again.
2710 interrupt_status = SMU_ISR_READ(this_controller);
2711 if ((interrupt_status &
2712 (SMU_ISR_COMPLETION |
2713 SMU_ISR_QUEUE_ERROR |
2714 SMU_ISR_QUEUE_SUSPEND)) == 0)
2719 return scic_sds_controller_standard_interrupt_handler(
2720 controller, interrupt_status
2725 * @brief This is the method provided to handle completions when interrupt
2726 * polling is in use.
2728 * @param[in] controller
2733 void scic_sds_controller_polling_completion_handler(
2734 SCI_CONTROLLER_HANDLE_T controller
2737 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2740 sci_base_object_get_logger(controller),
2741 SCIC_LOG_OBJECT_CONTROLLER,
2742 "scic_sds_controller_polling_completion_handler(0x%d) enter\n",
2746 if (this_controller->encountered_fatal_error == TRUE)
2749 sci_base_object_get_logger(this_controller),
2750 SCIC_LOG_OBJECT_CONTROLLER,
2751 "SCIC Controller has encountered a fatal error.\n"
2754 sci_base_state_machine_change_state(
2755 scic_sds_controller_get_base_state_machine(this_controller),
2756 SCI_BASE_CONTROLLER_STATE_FAILED
2759 else if (scic_sds_controller_completion_queue_has_entries(this_controller))
2761 if (this_controller->restrict_completions == FALSE)
2762 scic_sds_controller_process_completions(this_controller);
2764 scic_sds_controller_transitioned_process_completions(this_controller);
2768 * The interrupt handler does not adjust the CQ's
2769 * get pointer. So, SCU's INTx pin stays asserted during the
2770 * interrupt handler even though it tries to clear the interrupt
2771 * source. Therefore, the completion handler must ensure that the
2772 * interrupt source is cleared. Otherwise, we get a spurious
2773 * interrupt for which the interrupt handler will not issue a
2774 * corresponding completion event. Also, we unmask interrupts.
2778 (U32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)
2782 #if !defined(DISABLE_INTERRUPTS)
2784 * @brief This is the method provided to handle legacy interrupts for the
2785 * controller object.
2787 * @param[in] controller
2790 * @retval TRUE if an interrupt is processed
2791 * FALSE if no interrupt was processed
2794 BOOL scic_sds_controller_legacy_interrupt_handler(
2795 SCI_CONTROLLER_HANDLE_T controller
2798 U32 interrupt_status;
2799 BOOL is_completion_needed;
2800 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
2802 interrupt_status = SMU_ISR_READ(this_controller);
2803 is_completion_needed = scic_sds_controller_standard_interrupt_handler(
2804 this_controller, interrupt_status
2807 return is_completion_needed;
2812 * @brief This is the method provided to handle legacy completions it is
2813 * expected that the SCI User will call this completion handler
2814 * anytime the interrupt handler reports that it has handled an
2817 * @param[in] controller
2822 void scic_sds_controller_legacy_completion_handler(
2823 SCI_CONTROLLER_HANDLE_T controller
2826 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2829 sci_base_object_get_logger(controller),
2830 SCIC_LOG_OBJECT_CONTROLLER,
2831 "scic_sds_controller_legacy_completion_handler(0x%d) enter\n",
2835 scic_sds_controller_polling_completion_handler(controller);
2837 SMU_IMR_WRITE(this_controller, 0x00000000);
2839 #ifdef IMR_READ_FENCE
2841 volatile U32 int_mask_value = 0;
2845 * Temporary code since we have seen with legacy interrupts
2846 * that interrupts are still masked after clearing the mask
2847 * above. This may be an Arlington problem or it may be an
2848 * old driver problem. Presently this code is turned off
2849 * since we have not seen this problem recently.
2853 int_mask_value = SMU_IMR_READ(this_controler);
2857 #ifdef ALLOW_ENTER_DEBUGGER
2862 } while (int_mask_value != 0);
2868 * @brief This is the method provided to handle an MSIX interrupt message
2869 * when there is just a single MSIX message being provided by the
2870 * hardware. This mode of operation is single vector mode.
2872 * @param[in] controller
2875 * @retval TRUE if an interrupt is processed
2876 * FALSE if no interrupt was processed
2879 BOOL scic_sds_controller_single_vector_interrupt_handler(
2880 SCI_CONTROLLER_HANDLE_T controller
2883 U32 interrupt_status;
2884 SCIC_SDS_CONTROLLER_T *this_controller;
2885 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2887 // Mask the interrupts
2888 // There is a race in the hardware that could cause us not to be notified
2889 // of an interrupt completion if we do not take this step. We will unmask
2890 // the interrupts in the completion routine.
2891 SMU_IMR_WRITE(this_controller, 0xFFFFFFFF);
2893 interrupt_status = SMU_ISR_READ(this_controller);
2894 interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
2897 (interrupt_status == 0)
2898 && scic_sds_controller_completion_queue_has_entries(this_controller)
2901 // There is at least one completion queue entry to process so we can
2902 // return a success and ignore for now the case of an error interrupt
2903 SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
2909 if (interrupt_status != 0)
2911 // There is an error interrupt pending so let it through and handle
2916 // Clear any offending interrupts since we could not find any to handle
2917 // and unmask them all
2918 SMU_ISR_WRITE(this_controller, 0x00000000);
2919 SMU_IMR_WRITE(this_controller, 0x00000000);
2925 * @brief This is the method provided to handle completions for a single
2928 * @param[in] controller
2931 void scic_sds_controller_single_vector_completion_handler(
2932 SCI_CONTROLLER_HANDLE_T controller
2935 U32 interrupt_status;
2936 SCIC_SDS_CONTROLLER_T *this_controller;
2937 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2940 sci_base_object_get_logger(controller),
2941 SCIC_LOG_OBJECT_CONTROLLER,
2942 "scic_sds_controller_single_vector_completion_handler(0x%d) enter\n",
2946 interrupt_status = SMU_ISR_READ(this_controller);
2947 interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
2949 if (interrupt_status & SMU_ISR_QUEUE_ERROR)
2952 sci_base_object_get_logger(this_controller),
2953 SCIC_LOG_OBJECT_CONTROLLER,
2954 "SCIC Controller has encountered a fatal error.\n"
2957 // We have a fatal condition and must reset the controller
2958 // Leave the interrupt mask in place and get the controller reset
2959 sci_base_state_machine_change_state(
2960 scic_sds_controller_get_base_state_machine(this_controller),
2961 SCI_BASE_CONTROLLER_STATE_FAILED
2967 (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
2968 && !scic_sds_controller_completion_queue_has_entries(this_controller)
2972 sci_base_object_get_logger(this_controller),
2973 SCIC_LOG_OBJECT_CONTROLLER,
2974 "SCIC Controller has encountered a fatal error.\n"
2977 // We have a fatal condtion and must reset the controller
2978 // Leave the interrupt mask in place and get the controller reset
2979 sci_base_state_machine_change_state(
2980 scic_sds_controller_get_base_state_machine(this_controller),
2981 SCI_BASE_CONTROLLER_STATE_FAILED
2986 if (scic_sds_controller_completion_queue_has_entries(this_controller))
2988 scic_sds_controller_process_completions(this_controller);
2990 // We dont care which interrupt got us to processing the completion queu
2991 // so clear them both.
2994 (SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND)
2998 SMU_IMR_WRITE(this_controller, 0x00000000);
3002 * @brief This is the method provided to handle a MSIX message for a normal
3005 * @param[in] controller
3008 * @retval TRUE if an interrupt is processed
3009 * FALSE if no interrupt was processed
3012 BOOL scic_sds_controller_normal_vector_interrupt_handler(
3013 SCI_CONTROLLER_HANDLE_T controller
3016 SCIC_SDS_CONTROLLER_T *this_controller;
3017 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3019 if (scic_sds_controller_completion_queue_has_entries(this_controller))
3025 // we have a spurious interrupt it could be that we have already
3026 // emptied the completion queue from a previous interrupt
3027 SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
3029 // There is a race in the hardware that could cause us not to be notified
3030 // of an interrupt completion if we do not take this step. We will mask
3031 // then unmask the interrupts so if there is another interrupt pending
3032 // the clearing of the interrupt source we get the next interrupt message.
3033 SMU_IMR_WRITE(this_controller, 0xFF000000);
3034 SMU_IMR_WRITE(this_controller, 0x00000000);
3041 * @brief This is the method provided to handle the completions for a
3042 * normal MSIX message.
3044 * @param[in] controller
3047 void scic_sds_controller_normal_vector_completion_handler(
3048 SCI_CONTROLLER_HANDLE_T controller
3051 SCIC_SDS_CONTROLLER_T *this_controller;
3052 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3055 sci_base_object_get_logger(controller),
3056 SCIC_LOG_OBJECT_CONTROLLER,
3057 "scic_sds_controller_normal_vector_completion_handler(0x%d) enter\n",
3061 // Empty out the completion queue
3062 if (scic_sds_controller_completion_queue_has_entries(this_controller))
3064 scic_sds_controller_process_completions(this_controller);
3067 // Clear the interrupt and enable all interrupts again
3068 SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
3069 // Could we write the value of SMU_ISR_COMPLETION?
3070 SMU_IMR_WRITE(this_controller, 0xFF000000);
3071 SMU_IMR_WRITE(this_controller, 0x00000000);
3075 * @brief This is the method provided to handle the error MSIX message
3076 * interrupt. This is the normal operating mode for the hardware if
3079 * @param[in] controller
3082 * @retval TRUE if an interrupt is processed
3083 * FALSE if no interrupt was processed
3086 BOOL scic_sds_controller_error_vector_interrupt_handler(
3087 SCI_CONTROLLER_HANDLE_T controller
3090 U32 interrupt_status;
3091 SCIC_SDS_CONTROLLER_T *this_controller;
3092 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3095 interrupt_status = SMU_ISR_READ(this_controller);
3096 interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
3098 if (interrupt_status != 0)
3100 // There is an error interrupt pending so let it through and handle
3105 // There is a race in the hardware that could cause us not to be notified
3106 // of an interrupt completion if we do not take this step. We will mask
3107 // then unmask the error interrupts so if there was another interrupt
3108 // pending we will be notified.
3109 // Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)?
3110 SMU_IMR_WRITE(this_controller, 0x000000FF);
3111 SMU_IMR_WRITE(this_controller, 0x00000000);
3117 * @brief This is the method provided to handle the error completions when
3118 * the hardware is using two MSIX messages.
3120 * @param[in] controller
3123 void scic_sds_controller_error_vector_completion_handler(
3124 SCI_CONTROLLER_HANDLE_T controller
3127 U32 interrupt_status;
3128 SCIC_SDS_CONTROLLER_T *this_controller;
3129 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3132 sci_base_object_get_logger(controller),
3133 SCIC_LOG_OBJECT_CONTROLLER,
3134 "scic_sds_controller_error_vector_completion_handler(0x%d) enter\n",
3138 interrupt_status = SMU_ISR_READ(this_controller);
3141 (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
3142 && scic_sds_controller_completion_queue_has_entries(this_controller)
3145 scic_sds_controller_process_completions(this_controller);
3147 SMU_ISR_WRITE(this_controller, SMU_ISR_QUEUE_SUSPEND);
3152 sci_base_object_get_logger(this_controller),
3153 SCIC_LOG_OBJECT_CONTROLLER,
3154 "SCIC Controller reports CRC error on completion ISR %x\n",
3158 sci_base_state_machine_change_state(
3159 scic_sds_controller_get_base_state_machine(this_controller),
3160 SCI_BASE_CONTROLLER_STATE_FAILED
3166 // If we dont process any completions I am not sure that we want to do this.
3167 // We are in the middle of a hardware fault and should probably be reset.
3168 SMU_IMR_WRITE(this_controller, 0x00000000);
3171 #endif // !defined(DISABLE_INTERRUPTS)
3173 //****************************************************************************-
3174 //* SCIC SDS Controller External Methods
3175 //****************************************************************************-
3178 * @brief This method returns the sizeof the SCIC SDS Controller Object
3182 U32 scic_sds_controller_get_object_size(void)
3184 return sizeof(SCIC_SDS_CONTROLLER_T);
3188 * This method returns the minimum number of timers that are required by the
3189 * controller object. This will include required timers for phys and ports.
3192 * @retval The minimum number of timers that are required to make this
3193 * controller operational.
3195 U32 scic_sds_controller_get_min_timer_count(void)
3197 return SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT
3198 + scic_sds_port_get_min_timer_count()
3199 + scic_sds_phy_get_min_timer_count();
3203 * This method returns the maximum number of timers that are required by the
3204 * controller object. This will include required timers for phys and ports.
3207 * @retval The maximum number of timers that will be used by the controller
3210 U32 scic_sds_controller_get_max_timer_count(void)
3212 return SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT
3213 + scic_sds_port_get_max_timer_count()
3214 + scic_sds_phy_get_max_timer_count();
3220 * @param[in] this_controller
3221 * @param[in] the_port
3222 * @param[in] the_phy
3226 void scic_sds_controller_link_up(
3227 SCIC_SDS_CONTROLLER_T *this_controller,
3228 SCIC_SDS_PORT_T *the_port,
3229 SCIC_SDS_PHY_T *the_phy
3232 if (this_controller->state_handlers->link_up_handler != NULL)
3234 this_controller->state_handlers->link_up_handler(
3235 this_controller, the_port, the_phy);
3240 sci_base_object_get_logger(this_controller),
3241 SCIC_LOG_OBJECT_CONTROLLER,
3242 "SCIC Controller linkup event from phy %d in unexpected state %d\n",
3244 sci_base_state_machine_get_state(
3245 scic_sds_controller_get_base_state_machine(this_controller))
3253 * @param[in] this_controller
3254 * @param[in] the_port
3255 * @param[in] the_phy
3257 void scic_sds_controller_link_down(
3258 SCIC_SDS_CONTROLLER_T *this_controller,
3259 SCIC_SDS_PORT_T *the_port,
3260 SCIC_SDS_PHY_T *the_phy
3263 if (this_controller->state_handlers->link_down_handler != NULL)
3265 this_controller->state_handlers->link_down_handler(
3266 this_controller, the_port, the_phy);
3271 sci_base_object_get_logger(this_controller),
3272 SCIC_LOG_OBJECT_CONTROLLER,
3273 "SCIC Controller linkdown event from phy %d in unexpected state %d\n",
3275 sci_base_state_machine_get_state(
3276 scic_sds_controller_get_base_state_machine(this_controller))
3282 * @brief This method is called by the remote device to inform the controller
3283 * that this remote device has started.
3285 * @param[in] this_controller
3286 * @param[in] the_device
3288 void scic_sds_controller_remote_device_started(
3289 SCIC_SDS_CONTROLLER_T * this_controller,
3290 SCIC_SDS_REMOTE_DEVICE_T * the_device
3293 if (this_controller->state_handlers->remote_device_started_handler != NULL)
3295 this_controller->state_handlers->remote_device_started_handler(
3296 this_controller, the_device
3302 sci_base_object_get_logger(this_controller),
3303 SCIC_LOG_OBJECT_CONTROLLER,
3304 "SCIC Controller 0x%x remote device started event from device 0x%x in unexpected state %d\n",
3307 sci_base_state_machine_get_state(
3308 scic_sds_controller_get_base_state_machine(this_controller))
3314 * @brief This is a helper method to determine if any remote devices on this
3315 * controller are still in the stopping state.
3317 * @param[in] this_controller
3319 BOOL scic_sds_controller_has_remote_devices_stopping(
3320 SCIC_SDS_CONTROLLER_T * this_controller
3325 for (index = 0; index < this_controller->remote_node_entries; index++)
3328 (this_controller->device_table[index] != NULL)
3330 this_controller->device_table[index]->parent.state_machine.current_state_id
3331 == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
3343 * @brief This method is called by the remote device to inform the controller
3344 * object that the remote device has stopped.
3346 * @param[in] this_controller
3347 * @param[in] the_device
3349 void scic_sds_controller_remote_device_stopped(
3350 SCIC_SDS_CONTROLLER_T * this_controller,
3351 SCIC_SDS_REMOTE_DEVICE_T * the_device
3354 if (this_controller->state_handlers->remote_device_stopped_handler != NULL)
3356 this_controller->state_handlers->remote_device_stopped_handler(
3357 this_controller, the_device
3363 sci_base_object_get_logger(this_controller),
3364 SCIC_LOG_OBJECT_CONTROLLER,
3365 "SCIC Controller 0x%x remote device stopped event from device 0x%x in unexpected state %d\n",
3368 sci_base_state_machine_get_state(
3369 scic_sds_controller_get_base_state_machine(this_controller))
3375 * @brief This method will write to the SCU PCP register the request value.
3376 * The method is used to suspend/resume ports, devices, and phys.
3378 * @param[in] this_controller
3379 * @param[in] request
3381 void scic_sds_controller_post_request(
3382 SCIC_SDS_CONTROLLER_T *this_controller,
3387 sci_base_object_get_logger(this_controller),
3388 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_COMPLETION_QUEUE,
3389 "SCIC Controller 0x%08x post request 0x%08x\n",
3390 this_controller, request
3393 SMU_PCP_WRITE(this_controller, request);
3397 * @brief This method will copy the soft copy of the task context into
3398 * the physical memory accessible by the controller.
3400 * @note After this call is made the SCIC_SDS_IO_REQUEST object will
3401 * always point to the physical memory version of the task context.
3402 * Thus, all subsequent updates to the task context are performed in
3403 * the TC table (i.e. DMAable memory).
3405 * @param[in] this_controller This parameter specifies the controller for
3406 * which to copy the task context.
3407 * @param[in] this_request This parameter specifies the request for which
3408 * the task context is being copied.
3412 void scic_sds_controller_copy_task_context(
3413 SCIC_SDS_CONTROLLER_T *this_controller,
3414 SCIC_SDS_REQUEST_T *this_request
3417 SCU_TASK_CONTEXT_T *task_context_buffer;
3419 task_context_buffer = scic_sds_controller_get_task_context_buffer(
3420 this_controller, this_request->io_tag
3424 task_context_buffer,
3425 this_request->task_context_buffer,
3426 SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, sgl_snapshot_ac)
3429 // Now that the soft copy of the TC has been copied into the TC
3430 // table accessible by the silicon. Thus, any further changes to
3431 // the TC (e.g. TC termination) occur in the appropriate location.
3432 this_request->task_context_buffer = task_context_buffer;
3436 * @brief This method returns the task context buffer for the given io tag.
3438 * @param[in] this_controller
3441 * @return struct SCU_TASK_CONTEXT*
3443 SCU_TASK_CONTEXT_T * scic_sds_controller_get_task_context_buffer(
3444 SCIC_SDS_CONTROLLER_T * this_controller,
3448 U16 task_index = scic_sds_io_tag_get_index(io_tag);
3450 if (task_index < this_controller->task_context_entries)
3452 return &this_controller->task_context_table[task_index];
3459 * @brief This method returnst the sequence value from the io tag value
3461 * @param[in] this_controller
3466 U16 scic_sds_controller_get_io_sequence_from_tag(
3467 SCIC_SDS_CONTROLLER_T *this_controller,
3471 return scic_sds_io_tag_get_sequence(io_tag);
3475 * @brief This method returns the IO request associated with the tag value
3477 * @param[in] this_controller
3480 * @return SCIC_SDS_IO_REQUEST_T*
3481 * @retval NULL if there is no valid IO request at the tag value
3483 SCIC_SDS_REQUEST_T *scic_sds_controller_get_io_request_from_tag(
3484 SCIC_SDS_CONTROLLER_T *this_controller,
3491 task_index = scic_sds_io_tag_get_index(io_tag);
3493 if (task_index < this_controller->task_context_entries)
3495 if (this_controller->io_request_table[task_index] != SCI_INVALID_HANDLE)
3497 task_sequence = scic_sds_io_tag_get_sequence(io_tag);
3499 if (task_sequence == this_controller->io_request_sequence[task_index])
3501 return this_controller->io_request_table[task_index];
3506 return SCI_INVALID_HANDLE;
3510 * @brief This method allocates remote node index and the reserves the
3511 * remote node context space for use. This method can fail if there
3512 * are no more remote node index available.
3514 * @param[in] this_controller This is the controller object which contains
3515 * the set of free remote node ids
3516 * @param[in] the_devce This is the device object which is requesting the a
3518 * @param[out] node_id This is the remote node id that is assinged to the
3519 * device if one is available
3521 * @return SCI_STATUS
3522 * @retval SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote
3523 * node index available.
3525 SCI_STATUS scic_sds_controller_allocate_remote_node_context(
3526 SCIC_SDS_CONTROLLER_T * this_controller,
3527 SCIC_SDS_REMOTE_DEVICE_T * the_device,
3532 U32 remote_node_count = scic_sds_remote_device_node_count(the_device);
3534 node_index = scic_sds_remote_node_table_allocate_remote_node(
3535 &this_controller->available_remote_nodes, remote_node_count
3538 if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
3540 this_controller->device_table[node_index] = the_device;
3542 *node_id = node_index;
3547 return SCI_FAILURE_INSUFFICIENT_RESOURCES;
3551 * @brief This method frees the remote node index back to the available
3552 * pool. Once this is done the remote node context buffer is no
3553 * longer valid and can not be used.
3555 * @param[in] this_controller
3556 * @param[in] the_device
3557 * @param[in] node_id
3561 void scic_sds_controller_free_remote_node_context(
3562 SCIC_SDS_CONTROLLER_T * this_controller,
3563 SCIC_SDS_REMOTE_DEVICE_T * the_device,
3567 U32 remote_node_count = scic_sds_remote_device_node_count(the_device);
3569 if (this_controller->device_table[node_id] == the_device)
3571 this_controller->device_table[node_id] = SCI_INVALID_HANDLE;
3573 scic_sds_remote_node_table_release_remote_node_index(
3574 &this_controller->available_remote_nodes, remote_node_count, node_id
3580 * @brief This method returns the SCU_REMOTE_NODE_CONTEXT for the specified
3583 * @param[in] this_controller
3584 * @param[in] node_id
3586 * @return SCU_REMOTE_NODE_CONTEXT_T*
3588 SCU_REMOTE_NODE_CONTEXT_T *scic_sds_controller_get_remote_node_context_buffer(
3589 SCIC_SDS_CONTROLLER_T *this_controller,
3594 (node_id < this_controller->remote_node_entries)
3595 && (this_controller->device_table[node_id] != SCI_INVALID_HANDLE)
3598 return &this_controller->remote_node_context_table[node_id];
3605 * This method will combind the frame header and frame buffer to create
3606 * a SATA D2H register FIS
3608 * @param[out] resposne_buffer This is the buffer into which the D2H register
3609 * FIS will be constructed.
3610 * @param[in] frame_header This is the frame header returned by the hardware.
3611 * @param[in] frame_buffer This is the frame buffer returned by the hardware.
3615 void scic_sds_controller_copy_sata_response(
3616 void * response_buffer,
3617 void * frame_header,
3628 (char *)((char *)response_buffer + sizeof(U32)),
3630 sizeof(SATA_FIS_REG_D2H_T) - sizeof(U32)
3635 * @brief This method releases the frame once this is done the frame is
3636 * available for re-use by the hardware. The data contained in the
3637 * frame header and frame buffer is no longer valid.
3638 * The UF queue get pointer is only updated if UF control indicates
3639 * this is appropriate.
3641 * @param[in] this_controller
3642 * @param[in] frame_index
3646 void scic_sds_controller_release_frame(
3647 SCIC_SDS_CONTROLLER_T *this_controller,
3651 if (scic_sds_unsolicited_frame_control_release_frame(
3652 &this_controller->uf_control, frame_index) == TRUE)
3653 SCU_UFQGP_WRITE(this_controller, this_controller->uf_control.get);
3657 void scic_sds_controller_initialize_state_logging(
3658 SCIC_SDS_CONTROLLER_T *this_controller
3661 sci_base_state_machine_logger_initialize(
3662 &this_controller->parent.state_machine_logger,
3663 &this_controller->parent.state_machine,
3664 &this_controller->parent.parent,
3665 scic_cb_logger_log_states,
3666 "SCIC_SDS_CONTROLLER_T", "base state machine",
3667 SCIC_LOG_OBJECT_CONTROLLER
3671 void scic_sds_controller_deinitialize_state_logging(
3672 SCIC_SDS_CONTROLLER_T *this_controller
3675 sci_base_state_machine_logger_deinitialize(
3676 &this_controller->parent.state_machine_logger,
3677 &this_controller->parent.state_machine
3683 * @brief This method sets user parameters and OEM parameters to
3684 * default values. Users can override these values utilizing
3685 * the scic_user_parameters_set() and scic_oem_parameters_set()
3688 * @param[in] controller This parameter specifies the controller for
3689 * which to set the configuration parameters to their
3695 void scic_sds_controller_set_default_config_parameters(
3696 SCIC_SDS_CONTROLLER_T *this_controller
3701 // Default to APC mode.
3702 this_controller->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
3705 this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up = 1;
3707 // Default to no SSC operation.
3708 this_controller->oem_parameters.sds1.controller.ssc_sata_tx_spread_level = 0;
3709 this_controller->oem_parameters.sds1.controller.ssc_sas_tx_spread_level = 0;
3710 this_controller->oem_parameters.sds1.controller.ssc_sas_tx_type = 0;
3712 // Default to all phys to using short cables
3713 this_controller->oem_parameters.sds1.controller.cable_selection_mask = 0;
3715 // Initialize all of the port parameter information to narrow ports.
3716 for (index = 0; index < SCI_MAX_PORTS; index++)
3718 this_controller->oem_parameters.sds1.ports[index].phy_mask = 0;
3721 // Initialize all of the phy parameter information.
3722 for (index = 0; index < SCI_MAX_PHYS; index++)
3724 // Default to 6G (i.e. Gen 3) for now. User can override if
3726 this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2;
3728 //the frequencies cannot be 0
3729 this_controller->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f;
3730 this_controller->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff;
3731 this_controller->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33;
3733 // Previous Vitesse based expanders had a arbitration issue that
3734 // is worked around by having the upper 32-bits of SAS address
3735 // with a value greater then the Vitesse company identifier.
3736 // Hence, usage of 0x5FCFFFFF.
3737 this_controller->oem_parameters.sds1.phys[index].sas_address.sci_format.high
3740 // Add in controller index to ensure each controller will have unique SAS addresses by default.
3741 this_controller->oem_parameters.sds1.phys[index].sas_address.sci_format.low
3742 = 0x00000001 + this_controller->controller_index;
3744 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
3745 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
3746 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0) )
3748 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control0 = 0x000E7C03;
3749 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control1 = 0x000E7C03;
3750 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control2 = 0x000E7C03;
3751 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control3 = 0x000E7C03;
3753 else // This must be SCIC_SDS_PCI_REVISION_C0
3755 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control0 = 0x000BDD08;
3756 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control1 = 0x000B7069;
3757 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control2 = 0x000B7C09;
3758 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control3 = 0x000AFC6E;
3762 this_controller->user_parameters.sds1.stp_inactivity_timeout = 5;
3763 this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5;
3764 this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5;
3765 this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20;
3766 this_controller->user_parameters.sds1.no_outbound_task_timeout = 20;
3772 * @brief This method release resources in SCI controller.
3774 * @param[in] this_controller This parameter specifies the core
3775 * controller and associated objects whose resources are to be
3778 * @return This method returns a value indicating if the operation succeeded.
3779 * @retval SCI_SUCCESS This value indicates that all the timers are destroyed.
3780 * @retval SCI_FAILURE This value indicates certain failure during the process
3781 * of cleaning timer resource.
3784 SCI_STATUS scic_sds_controller_release_resource(
3785 SCIC_SDS_CONTROLLER_T * this_controller
3788 SCIC_SDS_PORT_T * port;
3789 SCIC_SDS_PHY_T * phy;
3793 sci_base_object_get_logger(this_controller),
3794 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
3795 "scic_sds_controller_release_resource(0x%x) enter\n",
3799 if(this_controller->phy_startup_timer != NULL)
3801 scic_cb_timer_destroy(this_controller, this_controller->phy_startup_timer);
3802 this_controller->phy_startup_timer = NULL;
3805 if(this_controller->power_control.timer != NULL)
3807 scic_cb_timer_destroy(this_controller, this_controller->power_control.timer);
3808 this_controller->power_control.timer = NULL;
3811 if(this_controller->timeout_timer != NULL)
3813 scic_cb_timer_destroy(this_controller, this_controller->timeout_timer);
3814 this_controller->timeout_timer = NULL;
3817 scic_sds_port_configuration_agent_release_resource(
3819 &this_controller->port_agent);
3821 for(index = 0; index < SCI_MAX_PORTS+1; index++)
3823 port = &this_controller->port_table[index];
3824 scic_sds_port_release_resource(this_controller, port);
3827 for(index = 0; index < SCI_MAX_PHYS; index++)
3829 phy = &this_controller->phy_table[index];
3830 scic_sds_phy_release_resource(this_controller, phy);
3838 * @brief This method process the ports configured message from port configuration
3841 * @param[in] this_controller This parameter specifies the core
3842 * controller that its ports are configured.
3846 void scic_sds_controller_port_agent_configured_ports(
3847 SCIC_SDS_CONTROLLER_T * this_controller
3850 //simply transit to ready. The function below checks the controller state
3851 scic_sds_controller_transition_to_ready(
3852 this_controller, SCI_SUCCESS
3857 //****************************************************************************-
3858 //* SCIC Controller Public Methods
3859 //****************************************************************************-
3861 SCI_STATUS scic_controller_construct(
3862 SCI_LIBRARY_HANDLE_T library,
3863 SCI_CONTROLLER_HANDLE_T controller,
3867 SCIC_SDS_LIBRARY_T *my_library;
3868 SCIC_SDS_CONTROLLER_T *this_controller;
3870 my_library = (SCIC_SDS_LIBRARY_T *)library;
3871 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3874 sci_base_object_get_logger(library),
3875 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
3876 "scic_controller_construct(0x%x, 0x%x) enter\n",
3880 // Just clear out the memory of the structure to be safe.
3881 memset(this_controller, 0, sizeof(SCIC_SDS_CONTROLLER_T));
3883 // Make sure that the static data is assigned before moving onto the
3884 // base constroller construct as this will cause the controller to
3885 // enter its initial state and the controller_index and pci_revision
3886 // will be required to complete those operations correctly
3887 this_controller->controller_index =
3888 scic_sds_library_get_controller_index(my_library, this_controller);
3890 this_controller->pci_revision = my_library->pci_revision;
3892 sci_base_controller_construct(
3893 &this_controller->parent,
3894 sci_base_object_get_logger(my_library),
3895 scic_sds_controller_state_table,
3896 this_controller->memory_descriptors,
3897 ARRAY_SIZE(this_controller->memory_descriptors),
3901 sci_object_set_association(controller, user_object);
3903 scic_sds_controller_initialize_state_logging(this_controller);
3905 scic_sds_pci_bar_initialization(this_controller);
3910 // ---------------------------------------------------------------------------
3912 SCI_STATUS scic_controller_initialize(
3913 SCI_CONTROLLER_HANDLE_T controller
3916 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
3917 SCIC_SDS_CONTROLLER_T *this_controller;
3918 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3921 sci_base_object_get_logger(controller),
3922 SCIC_LOG_OBJECT_CONTROLLER,
3923 "scic_controller_initialize(0x%x, 0x%d) enter\n",
3927 if (this_controller->state_handlers->parent.initialize_handler != NULL)
3929 status = this_controller->state_handlers->parent.initialize_handler(
3930 (SCI_BASE_CONTROLLER_T *)controller
3936 sci_base_object_get_logger(this_controller),
3937 SCIC_LOG_OBJECT_CONTROLLER,
3938 "SCIC Controller initialize operation requested in invalid state %d\n",
3939 sci_base_state_machine_get_state(
3940 scic_sds_controller_get_base_state_machine(this_controller))
3947 // ---------------------------------------------------------------------------
3949 U32 scic_controller_get_suggested_start_timeout(
3950 SCI_CONTROLLER_HANDLE_T controller
3953 // Validate the user supplied parameters.
3954 if (controller == SCI_INVALID_HANDLE)
3957 // The suggested minimum timeout value for a controller start operation:
3959 // Signature FIS Timeout
3960 // + Phy Start Timeout
3961 // + Number of Phy Spin Up Intervals
3962 // ---------------------------------
3963 // Number of milliseconds for the controller start operation.
3965 // NOTE: The number of phy spin up intervals will be equivalent
3966 // to the number of phys divided by the number phys allowed
3967 // per interval - 1 (once OEM parameters are supported).
3968 // Currently we assume only 1 phy per interval.
3970 return (SCIC_SDS_SIGNATURE_FIS_TIMEOUT
3971 + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
3972 + ((SCI_MAX_PHYS-1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL));
3975 // ---------------------------------------------------------------------------
3977 SCI_STATUS scic_controller_start(
3978 SCI_CONTROLLER_HANDLE_T controller,
3982 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
3983 SCIC_SDS_CONTROLLER_T *this_controller;
3984 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3987 sci_base_object_get_logger(controller),
3988 SCIC_LOG_OBJECT_CONTROLLER,
3989 "scic_controller_start(0x%x, 0x%d) enter\n",
3993 if (this_controller->state_handlers->parent.start_handler != NULL)
3995 status = this_controller->state_handlers->parent.start_handler(
3996 (SCI_BASE_CONTROLLER_T *)controller, timeout
4002 sci_base_object_get_logger(this_controller),
4003 SCIC_LOG_OBJECT_CONTROLLER,
4004 "SCIC Controller start operation requested in invalid state %d\n",
4005 sci_base_state_machine_get_state(
4006 scic_sds_controller_get_base_state_machine(this_controller))
4013 // ---------------------------------------------------------------------------
4015 SCI_STATUS scic_controller_stop(
4016 SCI_CONTROLLER_HANDLE_T controller,
4020 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4021 SCIC_SDS_CONTROLLER_T *this_controller;
4022 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4025 sci_base_object_get_logger(controller),
4026 SCIC_LOG_OBJECT_CONTROLLER,
4027 "scic_controller_stop(0x%x, 0x%d) enter\n",
4031 if (this_controller->state_handlers->parent.stop_handler != NULL)
4033 status = this_controller->state_handlers->parent.stop_handler(
4034 (SCI_BASE_CONTROLLER_T *)controller, timeout
4040 sci_base_object_get_logger(this_controller),
4041 SCIC_LOG_OBJECT_CONTROLLER,
4042 "SCIC Controller stop operation requested in invalid state %d\n",
4043 sci_base_state_machine_get_state(
4044 scic_sds_controller_get_base_state_machine(this_controller))
4051 // ---------------------------------------------------------------------------
4053 SCI_STATUS scic_controller_reset(
4054 SCI_CONTROLLER_HANDLE_T controller
4057 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4058 SCIC_SDS_CONTROLLER_T *this_controller;
4059 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4062 sci_base_object_get_logger(controller),
4063 SCIC_LOG_OBJECT_CONTROLLER,
4064 "scic_controller_reset(0x%x) enter\n",
4068 if (this_controller->state_handlers->parent.reset_handler != NULL)
4070 status = this_controller->state_handlers->parent.reset_handler(
4071 (SCI_BASE_CONTROLLER_T *)controller
4077 sci_base_object_get_logger(this_controller),
4078 SCIC_LOG_OBJECT_CONTROLLER,
4079 "SCIC Controller reset operation requested in invalid state %d\n",
4080 sci_base_state_machine_get_state(
4081 scic_sds_controller_get_base_state_machine(this_controller))
4088 // ---------------------------------------------------------------------------
4090 SCI_STATUS scic_controller_get_handler_methods(
4091 SCIC_INTERRUPT_TYPE interrupt_type,
4093 SCIC_CONTROLLER_HANDLER_METHODS_T *handler_methods
4096 SCI_STATUS status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT;
4098 switch (interrupt_type)
4100 #if !defined(DISABLE_INTERRUPTS)
4101 case SCIC_LEGACY_LINE_INTERRUPT_TYPE:
4102 if (message_count == 0)
4104 handler_methods[0].interrupt_handler
4105 = scic_sds_controller_legacy_interrupt_handler;
4106 handler_methods[0].completion_handler
4107 = scic_sds_controller_legacy_completion_handler;
4109 status = SCI_SUCCESS;
4113 case SCIC_MSIX_INTERRUPT_TYPE:
4114 if (message_count == 1)
4116 handler_methods[0].interrupt_handler
4117 = scic_sds_controller_single_vector_interrupt_handler;
4118 handler_methods[0].completion_handler
4119 = scic_sds_controller_single_vector_completion_handler;
4121 status = SCI_SUCCESS;
4123 else if (message_count == 2)
4125 handler_methods[0].interrupt_handler
4126 = scic_sds_controller_normal_vector_interrupt_handler;
4127 handler_methods[0].completion_handler
4128 = scic_sds_controller_normal_vector_completion_handler;
4130 handler_methods[1].interrupt_handler
4131 = scic_sds_controller_error_vector_interrupt_handler;
4132 handler_methods[1].completion_handler
4133 = scic_sds_controller_error_vector_completion_handler;
4135 status = SCI_SUCCESS;
4138 #endif // !defined(DISABLE_INTERRUPTS)
4140 case SCIC_NO_INTERRUPTS:
4141 if (message_count == 0)
4144 handler_methods[0].interrupt_handler
4145 = scic_sds_controller_polling_interrupt_handler;
4146 handler_methods[0].completion_handler
4147 = scic_sds_controller_polling_completion_handler;
4149 status = SCI_SUCCESS;
4154 status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
4161 // ---------------------------------------------------------------------------
4163 SCI_IO_STATUS scic_controller_start_io(
4164 SCI_CONTROLLER_HANDLE_T controller,
4165 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4166 SCI_IO_REQUEST_HANDLE_T io_request,
4171 SCIC_SDS_CONTROLLER_T *this_controller;
4172 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4175 sci_base_object_get_logger(controller),
4176 SCIC_LOG_OBJECT_CONTROLLER,
4177 "scic_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
4178 controller, remote_device, io_request, io_tag
4181 status = this_controller->state_handlers->parent.start_io_handler(
4182 &this_controller->parent,
4183 (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4184 (SCI_BASE_REQUEST_T *)io_request,
4188 return (SCI_IO_STATUS)status;
4191 // ---------------------------------------------------------------------------
4193 SCI_STATUS scic_controller_terminate_request(
4194 SCI_CONTROLLER_HANDLE_T controller,
4195 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4196 SCI_IO_REQUEST_HANDLE_T request
4200 SCIC_SDS_CONTROLLER_T *this_controller;
4201 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4204 sci_base_object_get_logger(controller),
4205 SCIC_LOG_OBJECT_CONTROLLER,
4206 "scic_controller_terminate_request(0x%x, 0x%x, 0x%x) enter\n",
4207 controller, remote_device, request
4210 status = this_controller->state_handlers->terminate_request_handler(
4211 &this_controller->parent,
4212 (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4213 (SCI_BASE_REQUEST_T *)request
4219 // ---------------------------------------------------------------------------
4221 SCI_STATUS scic_controller_complete_io(
4222 SCI_CONTROLLER_HANDLE_T controller,
4223 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4224 SCI_IO_REQUEST_HANDLE_T io_request
4228 SCIC_SDS_CONTROLLER_T *this_controller;
4229 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4232 sci_base_object_get_logger(controller),
4233 SCIC_LOG_OBJECT_CONTROLLER,
4234 "scic_controller_complete_io(0x%x, 0x%x, 0x%x) enter\n",
4235 controller, remote_device, io_request
4238 status = this_controller->state_handlers->parent.complete_io_handler(
4239 &this_controller->parent,
4240 (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4241 (SCI_BASE_REQUEST_T *)io_request
4247 // ---------------------------------------------------------------------------
4249 #if !defined(DISABLE_TASK_MANAGEMENT)
4251 SCI_TASK_STATUS scic_controller_start_task(
4252 SCI_CONTROLLER_HANDLE_T controller,
4253 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4254 SCI_TASK_REQUEST_HANDLE_T task_request,
4258 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4259 SCIC_SDS_CONTROLLER_T *this_controller;
4260 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4263 sci_base_object_get_logger(controller),
4264 SCIC_LOG_OBJECT_CONTROLLER,
4265 "scic_controller_start_task(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
4266 controller, remote_device, task_request, task_tag
4269 if (this_controller->state_handlers->parent.start_task_handler != NULL)
4271 status = this_controller->state_handlers->parent.start_task_handler(
4272 &this_controller->parent,
4273 (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4274 (SCI_BASE_REQUEST_T *)task_request,
4281 sci_base_object_get_logger(controller),
4282 SCIC_LOG_OBJECT_CONTROLLER,
4283 "SCIC Controller starting task from invalid state\n"
4287 return (SCI_TASK_STATUS)status;
4290 // ---------------------------------------------------------------------------
4292 SCI_STATUS scic_controller_complete_task(
4293 SCI_CONTROLLER_HANDLE_T controller,
4294 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4295 SCI_TASK_REQUEST_HANDLE_T task_request
4298 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4299 SCIC_SDS_CONTROLLER_T *this_controller;
4300 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4303 sci_base_object_get_logger(controller),
4304 SCIC_LOG_OBJECT_CONTROLLER,
4305 "scic_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n",
4306 controller, remote_device, task_request
4309 if (this_controller->state_handlers->parent.complete_task_handler != NULL)
4311 status = this_controller->state_handlers->parent.complete_task_handler(
4312 &this_controller->parent,
4313 (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4314 (SCI_BASE_REQUEST_T *)task_request
4320 sci_base_object_get_logger(controller),
4321 SCIC_LOG_OBJECT_CONTROLLER,
4322 "SCIC Controller completing task from invalid state\n"
4329 #endif // !defined(DISABLE_TASK_MANAGEMENT)
4331 // ---------------------------------------------------------------------------
4333 SCI_STATUS scic_controller_get_port_handle(
4334 SCI_CONTROLLER_HANDLE_T controller,
4336 SCI_PORT_HANDLE_T * port_handle
4339 SCIC_SDS_CONTROLLER_T *this_controller;
4340 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4343 sci_base_object_get_logger(controller),
4344 SCIC_LOG_OBJECT_CONTROLLER,
4345 "scic_controller_get_port_handle(0x%x, 0x%x, 0x%x) enter\n",
4346 controller, port_index, port_handle
4349 if (port_index < this_controller->logical_port_entries)
4351 *port_handle = &this_controller->port_table[port_index];
4356 return SCI_FAILURE_INVALID_PORT;
4359 // ---------------------------------------------------------------------------
4361 SCI_STATUS scic_controller_get_phy_handle(
4362 SCI_CONTROLLER_HANDLE_T controller,
4364 SCI_PHY_HANDLE_T * phy_handle
4367 SCIC_SDS_CONTROLLER_T *this_controller;
4368 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4371 sci_base_object_get_logger(controller),
4372 SCIC_LOG_OBJECT_CONTROLLER,
4373 "scic_controller_get_phy_handle(0x%x, 0x%x, 0x%x) enter\n",
4374 controller, phy_index, phy_handle
4377 if (phy_index < ARRAY_SIZE(this_controller->phy_table))
4379 *phy_handle = &this_controller->phy_table[phy_index];
4385 sci_base_object_get_logger(this_controller),
4386 SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_CONTROLLER,
4387 "Controller:0x%x PhyId:0x%x invalid phy index\n",
4388 this_controller, phy_index
4391 return SCI_FAILURE_INVALID_PHY;
4394 // ---------------------------------------------------------------------------
4396 U16 scic_controller_allocate_io_tag(
4397 SCI_CONTROLLER_HANDLE_T controller
4402 SCIC_SDS_CONTROLLER_T *this_controller;
4403 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4406 sci_base_object_get_logger(controller),
4407 SCIC_LOG_OBJECT_CONTROLLER,
4408 "scic_controller_allocate_io_tag(0x%x) enter\n",
4412 if (!sci_pool_empty(this_controller->tci_pool))
4414 sci_pool_get(this_controller->tci_pool, task_context);
4416 sequence_count = this_controller->io_request_sequence[task_context];
4418 return scic_sds_io_tag_construct(sequence_count, task_context);
4421 return SCI_CONTROLLER_INVALID_IO_TAG;
4424 // ---------------------------------------------------------------------------
4426 SCI_STATUS scic_controller_free_io_tag(
4427 SCI_CONTROLLER_HANDLE_T controller,
4434 SCIC_SDS_CONTROLLER_T *this_controller;
4435 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4437 ASSERT(io_tag != SCI_CONTROLLER_INVALID_IO_TAG);
4440 sci_base_object_get_logger(controller),
4441 SCIC_LOG_OBJECT_CONTROLLER,
4442 "scic_controller_free_io_tag(0x%x, 0x%x) enter\n",
4446 sequence = scic_sds_io_tag_get_sequence(io_tag);
4447 index = scic_sds_io_tag_get_index(io_tag);
4449 if (!sci_pool_full(this_controller->tci_pool))
4451 if (sequence == this_controller->io_request_sequence[index])
4453 scic_sds_io_sequence_increment(
4454 this_controller->io_request_sequence[index]);
4456 sci_pool_put(this_controller->tci_pool, index);
4462 return SCI_FAILURE_INVALID_IO_TAG;
4465 // ---------------------------------------------------------------------------
4467 void scic_controller_enable_interrupts(
4468 SCI_CONTROLLER_HANDLE_T controller
4471 SCIC_SDS_CONTROLLER_T *this_controller;
4472 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4474 ASSERT(this_controller->smu_registers != NULL);
4476 SMU_IMR_WRITE(this_controller, 0x00000000);
4479 // ---------------------------------------------------------------------------
4481 void scic_controller_disable_interrupts(
4482 SCI_CONTROLLER_HANDLE_T controller
4485 SCIC_SDS_CONTROLLER_T *this_controller;
4486 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4488 ASSERT(this_controller->smu_registers != NULL);
4490 SMU_IMR_WRITE(this_controller, 0xffffffff);
4493 // ---------------------------------------------------------------------------
4495 SCI_STATUS scic_controller_set_mode(
4496 SCI_CONTROLLER_HANDLE_T controller,
4497 SCI_CONTROLLER_MODE operating_mode
4500 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4501 SCI_STATUS status = SCI_SUCCESS;
4504 sci_base_object_get_logger(controller),
4505 SCIC_LOG_OBJECT_CONTROLLER,
4506 "scic_controller_set_mode(0x%x, 0x%x) enter\n",
4507 controller, operating_mode
4511 (this_controller->parent.state_machine.current_state_id
4512 == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
4513 || (this_controller->parent.state_machine.current_state_id
4514 == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
4517 switch (operating_mode)
4519 case SCI_MODE_SPEED:
4520 this_controller->remote_node_entries =
4521 MIN(this_controller->remote_node_entries, SCI_MAX_REMOTE_DEVICES);
4522 this_controller->task_context_entries =
4523 MIN(this_controller->task_context_entries, SCU_IO_REQUEST_COUNT);
4524 this_controller->uf_control.buffers.count =
4525 MIN(this_controller->uf_control.buffers.count, SCU_UNSOLICITED_FRAME_COUNT);
4526 this_controller->completion_event_entries =
4527 MIN(this_controller->completion_event_entries, SCU_EVENT_COUNT);
4528 this_controller->completion_queue_entries =
4529 MIN(this_controller->completion_queue_entries, SCU_COMPLETION_QUEUE_COUNT);
4531 scic_sds_controller_build_memory_descriptor_table(this_controller);
4535 this_controller->remote_node_entries =
4536 MIN(this_controller->remote_node_entries, SCI_MIN_REMOTE_DEVICES);
4537 this_controller->task_context_entries =
4538 MIN(this_controller->task_context_entries, SCI_MIN_IO_REQUESTS);
4539 this_controller->uf_control.buffers.count =
4540 MIN(this_controller->uf_control.buffers.count, SCU_MIN_UNSOLICITED_FRAMES);
4541 this_controller->completion_event_entries =
4542 MIN(this_controller->completion_event_entries, SCU_MIN_EVENTS);
4543 this_controller->completion_queue_entries =
4544 MIN(this_controller->completion_queue_entries, SCU_MIN_COMPLETION_QUEUE_ENTRIES);
4546 scic_sds_controller_build_memory_descriptor_table(this_controller);
4550 status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
4555 status = SCI_FAILURE_INVALID_STATE;
4561 * This method will reset the controller hardware.
4563 * @param[in] this_controller The controller that is to be reset.
4565 void scic_sds_controller_reset_hardware(
4566 SCIC_SDS_CONTROLLER_T * this_controller
4569 // Disable interrupts so we dont take any spurious interrupts
4570 scic_controller_disable_interrupts(this_controller);
4573 SMU_SMUSRCR_WRITE(this_controller, 0xFFFFFFFF);
4575 // Delay for 1ms to before clearing the CQP and UFQPR.
4576 scic_cb_stall_execution(1000);
4578 // The write to the CQGR clears the CQP
4579 SMU_CQGR_WRITE(this_controller, 0x00000000);
4581 // The write to the UFQGP clears the UFQPR
4582 SCU_UFQGP_WRITE(this_controller, 0x00000000);
4585 // ---------------------------------------------------------------------------
4587 SCI_STATUS scic_user_parameters_set(
4588 SCI_CONTROLLER_HANDLE_T controller,
4589 SCIC_USER_PARAMETERS_T * scic_parms
4592 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4595 (this_controller->parent.state_machine.current_state_id
4596 == SCI_BASE_CONTROLLER_STATE_RESET)
4597 || (this_controller->parent.state_machine.current_state_id
4598 == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
4599 || (this_controller->parent.state_machine.current_state_id
4600 == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
4605 // Validate the user parameters. If they are not legal, then
4606 // return a failure.
4607 for (index = 0; index < SCI_MAX_PHYS; index++)
4610 ( scic_parms->sds1.phys[index].max_speed_generation
4611 <= SCIC_SDS_PARM_MAX_SPEED
4612 && scic_parms->sds1.phys[index].max_speed_generation
4613 > SCIC_SDS_PARM_NO_SPEED
4616 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4619 (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) ||
4620 (scic_parms->sds1.phys[index].align_insertion_frequency == 0) ||
4621 (scic_parms->sds1.phys[index].notify_enable_spin_up_insertion_frequency == 0)
4624 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4629 (scic_parms->sds1.stp_inactivity_timeout == 0) ||
4630 (scic_parms->sds1.ssp_inactivity_timeout == 0) ||
4631 (scic_parms->sds1.stp_max_occupancy_timeout == 0) ||
4632 (scic_parms->sds1.ssp_max_occupancy_timeout == 0) ||
4633 (scic_parms->sds1.no_outbound_task_timeout == 0)
4636 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4640 (&this_controller->user_parameters), scic_parms, sizeof(*scic_parms));
4645 return SCI_FAILURE_INVALID_STATE;
4648 // ---------------------------------------------------------------------------
4650 void scic_user_parameters_get(
4651 SCI_CONTROLLER_HANDLE_T controller,
4652 SCIC_USER_PARAMETERS_T * scic_parms
4655 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4657 memcpy(scic_parms, (&this_controller->user_parameters), sizeof(*scic_parms));
4660 // ---------------------------------------------------------------------------
4661 SCI_STATUS scic_oem_parameters_set(
4662 SCI_CONTROLLER_HANDLE_T controller,
4663 SCIC_OEM_PARAMETERS_T * scic_parms,
4664 U8 scic_parms_version
4667 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4668 SCI_BIOS_OEM_PARAM_ELEMENT_T *old_oem_params =
4669 (SCI_BIOS_OEM_PARAM_ELEMENT_T *)(&(scic_parms->sds1));
4673 (this_controller->parent.state_machine.current_state_id
4674 == SCI_BASE_CONTROLLER_STATE_RESET)
4675 || (this_controller->parent.state_machine.current_state_id
4676 == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
4677 || (this_controller->parent.state_machine.current_state_id
4678 == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
4682 U8 combined_phy_mask = 0;
4685 * Set the OEM parameter version for the controller. This comes
4686 * from the OEM parameter block header or the registry depending
4687 * on what WCDL is set to retrieve.
4689 this_controller->oem_parameters_version = scic_parms_version;
4691 // Validate the oem parameters. If they are not legal, then
4692 // return a failure.
4693 for(index=0; index<SCI_MAX_PORTS; index++)
4695 if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX)
4697 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4701 for(index=0; index<SCI_MAX_PHYS; index++)
4704 scic_parms->sds1.phys[index].sas_address.sci_format.high == 0
4705 && scic_parms->sds1.phys[index].sas_address.sci_format.low == 0
4708 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4711 #if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
4713 (scic_parms->sds1.phys[index].afe_tx_amp_control0 == 0) ||
4714 (scic_parms->sds1.phys[index].afe_tx_amp_control1 == 0) ||
4715 (scic_parms->sds1.phys[index].afe_tx_amp_control2 == 0) ||
4716 (scic_parms->sds1.phys[index].afe_tx_amp_control3 == 0)
4719 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4724 if (scic_parms->sds1.controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
4726 for(index=0; index<SCI_MAX_PHYS; index++)
4728 if (scic_parms->sds1.ports[index].phy_mask != 0)
4730 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4734 else if (scic_parms->sds1.controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE)
4736 for(index=0; index<SCI_MAX_PHYS; index++)
4738 combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask;
4741 if (combined_phy_mask == 0)
4743 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4748 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4751 if (scic_parms->sds1.controller.max_number_concurrent_device_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
4753 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4756 if (old_oem_params->controller.do_enable_ssc != 0)
4758 if ( (scic_parms_version == SCI_OEM_PARAM_VER_1_0)
4759 && (old_oem_params->controller.do_enable_ssc != 0x01))
4760 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4762 if (scic_parms_version >= SCI_OEM_PARAM_VER_1_1)
4764 SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T *oem_params =
4765 (SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T*)(&(scic_parms->sds1));
4767 U8 test = oem_params->controller.ssc_sata_tx_spread_level;
4768 if ( !((test == 0x0) || (test == 0x2) || (test == 0x3) ||
4769 (test == 0x6) || (test == 0x7)) )
4770 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4772 test = oem_params->controller.ssc_sas_tx_spread_level;
4773 if (oem_params->controller.ssc_sas_tx_type == 0)
4775 if ( !((test == 0x0) || (test == 0x2) || (test == 0x3)) )
4776 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4779 if (oem_params->controller.ssc_sas_tx_type == 1)
4781 if ( !((test == 0x0) || (test == 0x3) || (test == 0x6)) )
4782 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4788 (&this_controller->oem_parameters), scic_parms, sizeof(*scic_parms));
4792 return SCI_FAILURE_INVALID_STATE;
4795 // ---------------------------------------------------------------------------
4797 void scic_oem_parameters_get(
4798 SCI_CONTROLLER_HANDLE_T controller,
4799 SCIC_OEM_PARAMETERS_T * scic_parms
4802 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4804 memcpy(scic_parms, (&this_controller->oem_parameters), sizeof(*scic_parms));
4807 // ---------------------------------------------------------------------------
4809 #if !defined(DISABLE_INTERRUPTS)
4811 #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853
4812 #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280
4813 #define INTERRUPT_COALESCE_TIMEOUT_MAX_US 2700000
4814 #define INTERRUPT_COALESCE_NUMBER_MAX 256
4815 #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN 7
4816 #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX 28
4818 SCI_STATUS scic_controller_set_interrupt_coalescence(
4819 SCI_CONTROLLER_HANDLE_T controller,
4820 U32 coalesce_number,
4821 U32 coalesce_timeout
4824 SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4825 U8 timeout_encode = 0;
4829 //Check if the input parameters fall in the range.
4830 if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX)
4831 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4833 // Defined encoding for interrupt coalescing timeout:
4834 // Value Min Max Units
4835 // ----- --- --- -----
4867 //Use the table above to decide the encode of interrupt coalescing timeout
4868 //value for register writing.
4869 if (coalesce_timeout == 0)
4873 //make the timeout value in unit of (10 ns).
4874 coalesce_timeout = coalesce_timeout * 100;
4875 min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10;
4876 max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10;
4878 //get the encode of timeout for register writing.
4879 for ( timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN;
4880 timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX;
4883 if (min <= coalesce_timeout && max > coalesce_timeout)
4885 else if (coalesce_timeout >= max && coalesce_timeout < min*2
4886 && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US*100)
4888 if ( (coalesce_timeout-max) < (2*min - coalesce_timeout) )
4903 if ( timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX+1 )
4904 //the value is out of range.
4905 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4910 (SMU_ICC_GEN_VAL(NUMBER, coalesce_number)|
4911 SMU_ICC_GEN_VAL(TIMER, timeout_encode))
4914 scic_controller->interrupt_coalesce_number = (U16)coalesce_number;
4915 scic_controller->interrupt_coalesce_timeout = coalesce_timeout/100;
4920 // ---------------------------------------------------------------------------
4922 void scic_controller_get_interrupt_coalescence(
4923 SCI_CONTROLLER_HANDLE_T controller,
4924 U32 * coalesce_number,
4925 U32 * coalesce_timeout
4928 SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4929 *coalesce_number = scic_controller->interrupt_coalesce_number;
4930 *coalesce_timeout = scic_controller->interrupt_coalesce_timeout;
4933 #endif // !defined(DISABLE_INTERRUPTS)
4935 // ---------------------------------------------------------------------------
4937 U32 scic_controller_get_scratch_ram_size(
4938 SCI_CONTROLLER_HANDLE_T controller
4941 return SCU_SCRATCH_RAM_SIZE_IN_DWORDS;
4944 // ---------------------------------------------------------------------------
4946 SCI_STATUS scic_controller_read_scratch_ram_dword(
4947 SCI_CONTROLLER_HANDLE_T controller,
4953 SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4954 U32 status = SMU_SMUCSR_READ(scic_controller);
4956 //Check if the SCU Scratch RAM been initialized, if not return zeros
4957 if ((status & SCU_RAM_INIT_COMPLETED) != SCU_RAM_INIT_COMPLETED)
4959 *value = 0x00000000;
4963 if (offset < scic_controller_get_scratch_ram_size(controller))
4965 if(offset <= SCU_MAX_ZPT_DWORD_INDEX)
4967 zpt_index = offset + (offset - (offset % 4)) + 4;
4969 *value = scu_controller_scratch_ram_register_read(scic_controller,zpt_index);
4971 else //offset > SCU_MAX_ZPT_DWORD_INDEX
4973 offset = offset - 132;
4975 zpt_index = offset + (offset - (offset % 4)) + 4;
4977 *value = scu_controller_scratch_ram_register_read_ext(scic_controller,zpt_index);
4984 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4988 // ---------------------------------------------------------------------------
4990 SCI_STATUS scic_controller_write_scratch_ram_dword(
4991 SCI_CONTROLLER_HANDLE_T controller,
4998 if (offset < scic_controller_get_scratch_ram_size(controller))
5000 SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5002 if(offset <= SCU_MAX_ZPT_DWORD_INDEX)
5004 zpt_index = offset + (offset - (offset % 4)) + 4;
5006 scu_controller_scratch_ram_register_write(scic_controller,zpt_index,value);
5008 else //offset > SCU_MAX_ZPT_DWORD_INDEX
5010 offset = offset - 132;
5012 zpt_index = offset + (offset - (offset % 4)) + 4;
5014 scu_controller_scratch_ram_register_write_ext(scic_controller,zpt_index,value);
5022 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
5026 // ---------------------------------------------------------------------------
5028 SCI_STATUS scic_controller_suspend(
5029 SCI_CONTROLLER_HANDLE_T controller
5032 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
5035 // As a precaution, disable interrupts. The user is required
5036 // to re-enable interrupts if so desired after the call.
5037 scic_controller_disable_interrupts(controller);
5039 // Stop all the timers
5040 // Maybe change the states of the objects to avoid processing stuff.
5043 // Suspend the Ports in order to ensure no unexpected
5044 // frame reception occurs on the links from the target
5045 for (index = 0; index < SCI_MAX_PORTS; index++)
5046 scic_sds_port_suspend_port_task_scheduler(
5047 &(this_controller->port_table[index]));
5049 // Disable/Reset the completion queue and unsolicited frame
5051 SMU_CQGR_WRITE(this_controller, 0x00000000);
5052 SCU_UFQGP_WRITE(this_controller, 0x00000000);
5054 // Clear any interrupts that may be pending or may have been generated
5055 // by setting CQGR and CQPR back to 0
5056 SMU_ISR_WRITE(this_controller, 0xFFFFFFFF);
5058 //reset the software get pointer to completion queue.
5059 this_controller->completion_queue_get = 0;
5064 // ---------------------------------------------------------------------------
5066 SCI_STATUS scic_controller_resume(
5067 SCI_CONTROLLER_HANDLE_T controller
5070 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
5073 // Initialize the completion queue and unsolicited frame queue.
5074 scic_sds_controller_initialize_completion_queue(this_controller);
5075 scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
5077 this_controller->restrict_completions = FALSE;
5079 // Release the port suspensions to allow for further successful
5081 for (index = 0; index < SCI_MAX_PORTS; index++)
5082 scic_sds_port_resume_port_task_scheduler(
5083 &(this_controller->port_table[index]));
5085 //check the link layer status register DWORD sync acquired bit to detect
5086 //link down event. If there is any link down event happened during controller
5087 //suspension, restart phy state machine.
5088 for (index = 0; index < SCI_MAX_PHYS; index ++)
5090 SCIC_SDS_PHY_T * curr_phy = &this_controller->phy_table[index];
5091 U32 link_layer_status = SCU_SAS_LLSTA_READ(curr_phy);
5093 if ((link_layer_status & SCU_SAS_LLSTA_DWORD_SYNCA_BIT) == 0)
5095 //Need to put the phy back to start OOB. Then an appropriate link event
5096 //message will be send to scic user.
5097 scic_sds_phy_restart_starting_state(curr_phy);
5104 // ---------------------------------------------------------------------------
5106 SCI_STATUS scic_controller_transition(
5107 SCI_CONTROLLER_HANDLE_T controller,
5108 BOOL restrict_completions
5111 SCI_STATUS result = SCI_FAILURE_INVALID_STATE;
5112 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
5116 sci_base_object_get_logger(controller),
5117 SCIC_LOG_OBJECT_CONTROLLER,
5118 "scic_controller_transition(0x%x) enter\n",
5122 if (this_controller->parent.state_machine.current_state_id
5123 == SCI_BASE_CONTROLLER_STATE_READY)
5125 // Ensure that there are no outstanding IO operations at this
5127 for (index = 0; index < SCI_MAX_PORTS; index++)
5129 if (this_controller->port_table[index].started_request_count != 0)
5133 scic_controller_suspend(controller);
5135 // Loop through the memory descriptor list and reprogram
5136 // the silicon memory registers accordingly.
5137 result = scic_sds_controller_validate_memory_descriptor_table(
5139 if (result == SCI_SUCCESS)
5141 scic_sds_controller_ram_initialization(this_controller);
5142 this_controller->restrict_completions = restrict_completions;
5145 scic_controller_resume(controller);
5151 // ---------------------------------------------------------------------------
5153 SCI_STATUS scic_controller_get_max_ports(
5154 SCI_CONTROLLER_HANDLE_T controller,
5158 *count = SCI_MAX_PORTS;
5162 // ---------------------------------------------------------------------------
5164 SCI_STATUS scic_controller_get_max_phys(
5165 SCI_CONTROLLER_HANDLE_T controller,
5169 *count = SCI_MAX_PHYS;
5174 //******************************************************************************
5175 //* CONTROLLER STATE MACHINE
5176 //******************************************************************************
5179 * This macro returns the maximum number of logical ports supported by the
5180 * hardware. The caller passes in the value read from the device context
5181 * capacity register and this macro will mash and shift the value
5184 #define smu_dcc_get_max_ports(dcc_value) \
5186 ( ((U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK)) \
5187 >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT ) + 1\
5191 * This macro returns the maximum number of task contexts supported by the
5192 * hardware. The caller passes in the value read from the device context
5193 * capacity register and this macro will mash and shift the value
5196 #define smu_dcc_get_max_task_context(dcc_value) \
5198 ( ((U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK)) \
5199 >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT ) + 1\
5203 * This macro returns the maximum number of remote node contexts supported
5204 * by the hardware. The caller passes in the value read from the device
5205 * context capacity register and this macro will mash and shift the value
5208 #define smu_dcc_get_max_remote_node_context(dcc_value) \
5210 ( ( (U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) )\
5211 >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT ) + 1\
5214 //*****************************************************************************
5215 //* DEFAULT STATE HANDLERS
5216 //*****************************************************************************
5219 * This method is called when the SCIC_SDS_CONTROLLER default start
5220 * io/task handler is in place.
5221 * - Issue a warning message
5223 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5224 * into a SCIC_SDS_CONTROLLER object.
5225 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
5226 * used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
5227 * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
5228 * would be cast to a SCIC_SDS_IO_REQUEST.
5229 * @param[in] io_tag This is the IO tag to be assigned to the IO request or
5230 * SCI_CONTROLLER_INVALID_IO_TAG.
5232 * @return SCI_STATUS
5233 * @retval SCI_FAILURE_INVALID_STATE
5236 SCI_STATUS scic_sds_controller_default_start_operation_handler(
5237 SCI_BASE_CONTROLLER_T *controller,
5238 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5239 SCI_BASE_REQUEST_T *io_request,
5243 SCIC_SDS_CONTROLLER_T *this_controller;
5244 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5247 sci_base_object_get_logger(this_controller),
5248 SCIC_LOG_OBJECT_CONTROLLER,
5249 "SCIC Controller requested to start an io/task from invalid state %d\n",
5250 sci_base_state_machine_get_state(
5251 scic_sds_controller_get_base_state_machine(this_controller))
5254 return SCI_FAILURE_INVALID_STATE;
5258 * This method is called when the SCIC_SDS_CONTROLLER default
5259 * request handler is in place.
5260 * - Issue a warning message
5262 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5263 * into a SCIC_SDS_CONTROLLER object.
5264 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
5265 * used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
5266 * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
5267 * would be cast to a SCIC_SDS_IO_REQUEST.
5269 * @return SCI_STATUS
5270 * @retval SCI_FAILURE_INVALID_STATE
5273 SCI_STATUS scic_sds_controller_default_request_handler(
5274 SCI_BASE_CONTROLLER_T *controller,
5275 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5276 SCI_BASE_REQUEST_T *io_request
5279 SCIC_SDS_CONTROLLER_T *this_controller;
5280 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5283 sci_base_object_get_logger(this_controller),
5284 SCIC_LOG_OBJECT_CONTROLLER,
5285 "SCIC Controller request operation from invalid state %d\n",
5286 sci_base_state_machine_get_state(
5287 scic_sds_controller_get_base_state_machine(this_controller))
5290 return SCI_FAILURE_INVALID_STATE;
5293 //*****************************************************************************
5294 //* GENERAL (COMMON) STATE HANDLERS
5295 //*****************************************************************************
5298 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5299 * reset handler is in place.
5300 * - Transition to SCI_BASE_CONTROLLER_STATE_RESETTING
5302 * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
5303 * SCIC_SDS_CONTROLLER object.
5305 * @return SCI_STATUS
5306 * @retval SCI_SUCCESS
5309 SCI_STATUS scic_sds_controller_general_reset_handler(
5310 SCI_BASE_CONTROLLER_T *controller
5313 SCIC_SDS_CONTROLLER_T *this_controller;
5314 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5317 sci_base_object_get_logger(controller),
5318 SCIC_LOG_OBJECT_CONTROLLER,
5319 "scic_sds_controller_resetting_state_enter(0x%x) enter\n",
5323 //Release resource. So far only resource to be released are timers.
5324 scic_sds_controller_release_resource(this_controller);
5326 // The reset operation is not a graceful cleanup just perform the state
5328 sci_base_state_machine_change_state(
5329 scic_sds_controller_get_base_state_machine(this_controller),
5330 SCI_BASE_CONTROLLER_STATE_RESETTING
5336 //*****************************************************************************
5337 //* RESET STATE HANDLERS
5338 //*****************************************************************************
5341 * This method is the SCIC_SDS_CONTROLLER initialize handler for the reset
5343 * - Currently this function does nothing
5345 * @param[in] controller This is the SCI_BASE_CONTROLLER object which is cast
5346 * into a SCIC_SDS_CONTROLLER object.
5348 * @return SCI_STATUS
5349 * @retval SCI_FAILURE
5351 * @todo This function is not yet implemented and is a valid request from the
5355 SCI_STATUS scic_sds_controller_reset_state_initialize_handler(
5356 SCI_BASE_CONTROLLER_T *controller
5360 SCI_STATUS result = SCI_SUCCESS;
5361 SCIC_SDS_CONTROLLER_T *this_controller;
5363 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5366 sci_base_object_get_logger(controller),
5367 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
5368 "scic_sds_controller_reset_state_initialize_handler(0x%x) enter\n",
5372 sci_base_state_machine_change_state(
5373 scic_sds_controller_get_base_state_machine(this_controller),
5374 SCI_BASE_CONTROLLER_STATE_INITIALIZING
5377 this_controller->timeout_timer = scic_cb_timer_create(
5379 scic_sds_controller_timeout_handler,
5383 scic_sds_controller_initialize_power_control(this_controller);
5385 /// todo: This should really be done in the reset state enter but
5386 /// the controller has not yet been initialized before getting
5387 /// to the reset enter state so the PCI BAR is not yet assigned
5388 scic_sds_controller_reset_hardware(this_controller);
5390 #if defined(ARLINGTON_BUILD)
5391 scic_sds_controller_lex_atux_initialization(this_controller);
5392 #elif defined(PLEASANT_RIDGE_BUILD) \
5393 || defined(PBG_HBA_A0_BUILD) \
5394 || defined(PBG_HBA_A2_BUILD)
5395 scic_sds_controller_afe_initialization(this_controller);
5396 #elif defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
5397 // There is nothing to do here for B0 since we do not have to
5398 // program the AFE registers.
5399 /// @todo The AFE settings are supposed to be correct for the B0 but
5400 /// presently they seem to be wrong.
5401 scic_sds_controller_afe_initialization(this_controller);
5402 #else // !defined(ARLINGTON_BUILD) && !defined(PLEASANT_RIDGE_BUILD)
5403 // What other systems do we want to add here?
5404 #endif // !defined(ARLINGTON_BUILD) && !defined(PLEASANT_RIDGE_BUILD)
5406 if (SCI_SUCCESS == result)
5411 // Take the hardware out of reset
5412 SMU_SMUSRCR_WRITE(this_controller, 0x00000000);
5414 /// @todo Provide meaningfull error code for hardware failure
5415 //result = SCI_FAILURE_CONTROLLER_HARDWARE;
5416 result = SCI_FAILURE;
5417 terminate_loop = 100;
5419 while (terminate_loop-- && (result != SCI_SUCCESS))
5421 // Loop until the hardware reports success
5422 scic_cb_stall_execution(SCU_CONTEXT_RAM_INIT_STALL_TIME);
5423 status = SMU_SMUCSR_READ(this_controller);
5425 if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED)
5427 result = SCI_SUCCESS;
5432 #ifdef ARLINGTON_BUILD
5433 scic_sds_controller_enable_chipwatch(this_controller);
5436 if (result == SCI_SUCCESS)
5438 U32 max_supported_ports;
5439 U32 max_supported_devices;
5440 U32 max_supported_io_requests;
5441 U32 device_context_capacity;
5443 // Determine what are the actaul device capacities that the
5444 // hardware will support
5445 device_context_capacity = SMU_DCC_READ(this_controller);
5447 max_supported_ports =
5448 smu_dcc_get_max_ports(device_context_capacity);
5449 max_supported_devices =
5450 smu_dcc_get_max_remote_node_context(device_context_capacity);
5451 max_supported_io_requests =
5452 smu_dcc_get_max_task_context(device_context_capacity);
5454 // Make all PEs that are unassigned match up with the logical ports
5455 for (index = 0; index < max_supported_ports; index++)
5459 this_controller->scu_registers->peg0.ptsg.protocol_engine[index],
5464 // Now that we have the correct hardware reported minimum values
5465 // build the MDL for the controller. Default to a performance
5467 scic_controller_set_mode(this_controller, SCI_MODE_SPEED);
5469 // Record the smaller of the two capacity values
5470 this_controller->logical_port_entries =
5471 MIN(max_supported_ports, this_controller->logical_port_entries);
5473 this_controller->task_context_entries =
5474 MIN(max_supported_io_requests, this_controller->task_context_entries);
5476 this_controller->remote_node_entries =
5477 MIN(max_supported_devices, this_controller->remote_node_entries);
5480 // Initialize hardware PCI Relaxed ordering in DMA engines
5481 if (result == SCI_SUCCESS)
5483 U32 dma_configuration;
5485 // Configure the payload DMA
5486 dma_configuration = SCU_PDMACR_READ(this_controller);
5487 dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
5488 SCU_PDMACR_WRITE(this_controller, dma_configuration);
5490 // Configure the control DMA
5491 dma_configuration = SCU_CDMACR_READ(this_controller);
5492 dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
5493 SCU_CDMACR_WRITE(this_controller, dma_configuration);
5496 // Initialize the PHYs before the PORTs because the PHY registers
5497 // are accessed during the port initialization.
5498 if (result == SCI_SUCCESS)
5500 // Initialize the phys
5502 (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS);
5505 result = scic_sds_phy_initialize(
5506 &this_controller->phy_table[index],
5507 &this_controller->scu_registers->peg0.pe[index].tl,
5508 &this_controller->scu_registers->peg0.pe[index].ll
5513 //Initialize the SGPIO Unit for HARDWARE controlled SGPIO
5514 if(result == SCI_SUCCESS)
5516 scic_sgpio_hardware_initialize(this_controller);
5519 if (result == SCI_SUCCESS)
5521 // Initialize the logical ports
5523 (index < this_controller->logical_port_entries)
5524 && (result == SCI_SUCCESS);
5527 result = scic_sds_port_initialize(
5528 &this_controller->port_table[index],
5529 &this_controller->scu_registers->peg0.ptsg.port[index],
5530 &this_controller->scu_registers->peg0.ptsg.protocol_engine,
5531 &this_controller->scu_registers->peg0.viit[index]
5536 if (SCI_SUCCESS == result)
5538 result = scic_sds_port_configuration_agent_initialize(
5540 &this_controller->port_agent
5544 // Advance the controller state machine
5545 if (result == SCI_SUCCESS)
5547 sci_base_state_machine_change_state(
5548 scic_sds_controller_get_base_state_machine(this_controller),
5549 SCI_BASE_CONTROLLER_STATE_INITIALIZED
5554 //stay in the same state and release the resource
5555 scic_sds_controller_release_resource(this_controller);
5558 sci_base_object_get_logger(controller),
5559 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
5560 "Invalid Port Configuration from scic_sds_controller_reset_state_initialize_handler(0x%x) \n",
5569 //*****************************************************************************
5570 //* INITIALIZED STATE HANDLERS
5571 //*****************************************************************************
5574 * This method is the SCIC_SDS_CONTROLLER start handler for the initialized
5576 * - Validate we have a good memory descriptor table
5577 * - Initialze the physical memory before programming the hardware
5578 * - Program the SCU hardware with the physical memory addresses passed in
5579 * the memory descriptor table.
5580 * - Initialzie the TCi pool
5581 * - Initialize the RNi pool
5582 * - Initialize the completion queue
5583 * - Initialize the unsolicited frame data
5584 * - Take the SCU port task scheduler out of reset
5585 * - Start the first phy object.
5586 * - Transition to SCI_BASE_CONTROLLER_STATE_STARTING.
5588 * @param[in] controller This is the SCI_BASE_CONTROLLER object which is cast
5589 * into a SCIC_SDS_CONTROLLER object.
5590 * @param[in] timeout This is the allowed time for the controller object to
5591 * reach the started state.
5593 * @return SCI_STATUS
5594 * @retval SCI_SUCCESS if all of the controller start operations complete
5595 * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD if one or more of the
5596 * memory descriptor fields is invalid.
5599 SCI_STATUS scic_sds_controller_initialized_state_start_handler(
5600 SCI_BASE_CONTROLLER_T * controller,
5606 SCIC_SDS_CONTROLLER_T * this_controller;
5608 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5610 // Make sure that the SCI User filled in the memory descriptor table correctly
5611 result = scic_sds_controller_validate_memory_descriptor_table(this_controller);
5613 if (result == SCI_SUCCESS)
5615 // The memory descriptor list looks good so program the hardware
5616 scic_sds_controller_ram_initialization(this_controller);
5619 if (SCI_SUCCESS == result)
5621 // Build the TCi free pool
5622 sci_pool_initialize(this_controller->tci_pool);
5623 for (index = 0; index < this_controller->task_context_entries; index++)
5625 sci_pool_put(this_controller->tci_pool, index);
5628 // Build the RNi free pool
5629 scic_sds_remote_node_table_initialize(
5630 &this_controller->available_remote_nodes,
5631 this_controller->remote_node_entries
5635 if (SCI_SUCCESS == result)
5637 // Before anything else lets make sure we will not be interrupted
5639 scic_controller_disable_interrupts(controller);
5641 // Enable the port task scheduler
5642 scic_sds_controller_enable_port_task_scheduler(this_controller);
5644 // Assign all the task entries to this controller physical function
5645 scic_sds_controller_assign_task_entries(this_controller);
5647 // Now initialze the completion queue
5648 scic_sds_controller_initialize_completion_queue(this_controller);
5650 // Initialize the unsolicited frame queue for use
5651 scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
5653 // Setup the phy start timer
5654 result = scic_sds_controller_initialize_phy_startup(this_controller);
5657 // Start all of the ports on this controller
5660 (index < this_controller->logical_port_entries) && (result == SCI_SUCCESS);
5664 result = this_controller->port_table[index].
5665 state_handlers->parent.start_handler(&this_controller->port_table[index].parent);
5668 if (SCI_SUCCESS == result)
5670 scic_sds_controller_start_next_phy(this_controller);
5672 // See if the user requested to timeout this operation.
5674 scic_cb_timer_start(controller, this_controller->timeout_timer, timeout);
5676 sci_base_state_machine_change_state(
5677 scic_sds_controller_get_base_state_machine(this_controller),
5678 SCI_BASE_CONTROLLER_STATE_STARTING
5685 //*****************************************************************************
5686 //* STARTING STATE HANDLERS
5687 //*****************************************************************************
5690 * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
5691 * link up handler is called. This method will perform the following:
5692 * - Stop the phy timer
5693 * - Start the next phy
5694 * - Report the link up condition to the port object
5696 * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the link up
5698 * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
5699 * @param[in] phy This is the SCIC_SDS_PHY which has gone link up.
5704 void scic_sds_controller_starting_state_link_up_handler(
5705 SCIC_SDS_CONTROLLER_T *this_controller,
5706 SCIC_SDS_PORT_T *port,
5710 scic_sds_controller_phy_timer_stop(this_controller);
5712 this_controller->port_agent.link_up_handler(
5713 this_controller, &this_controller->port_agent, port, phy
5715 //scic_sds_port_link_up(port, phy);
5717 scic_sds_controller_start_next_phy(this_controller);
5721 * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
5722 * link down handler is called.
5723 * - Report the link down condition to the port object
5725 * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the
5726 * link down notification.
5727 * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
5728 * @param[in] phy This is the SCIC_SDS_PHY which has gone link down.
5733 void scic_sds_controller_starting_state_link_down_handler(
5734 SCIC_SDS_CONTROLLER_T *this_controller,
5735 SCIC_SDS_PORT_T *port,
5739 this_controller->port_agent.link_down_handler(
5740 this_controller, &this_controller->port_agent, port, phy
5742 //scic_sds_port_link_down(port, phy);
5745 //*****************************************************************************
5746 //* READY STATE HANDLERS
5747 //*****************************************************************************
5750 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5751 * stop handler is called.
5752 * - Start the timeout timer
5753 * - Transition to SCI_BASE_CONTROLLER_STATE_STOPPING.
5755 * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
5756 * SCIC_SDS_CONTROLLER object.
5757 * @param[in] timeout The timeout for when the stop operation should report a
5760 * @return SCI_STATUS
5761 * @retval SCI_SUCCESS
5764 SCI_STATUS scic_sds_controller_ready_state_stop_handler(
5765 SCI_BASE_CONTROLLER_T *controller,
5769 SCIC_SDS_CONTROLLER_T *this_controller;
5770 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5772 // See if the user requested to timeout this operation
5774 scic_cb_timer_start(controller, this_controller->timeout_timer, timeout);
5776 sci_base_state_machine_change_state(
5777 scic_sds_controller_get_base_state_machine(this_controller),
5778 SCI_BASE_CONTROLLER_STATE_STOPPING
5785 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5786 * and the start io handler is called.
5787 * - Start the io request on the remote device
5789 * - assign the io_request to the io_request_table
5790 * - post the request to the hardware
5792 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5793 * into a SCIC_SDS_CONTROLLER object.
5794 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5795 * SCIC_SDS_REMOTE_DEVICE object.
5796 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5797 * SCIC_SDS_IO_REQUEST object.
5798 * @param[in] io_tag This is the IO tag to be assigned to the IO request or
5799 * SCI_CONTROLLER_INVALID_IO_TAG.
5801 * @return SCI_STATUS
5802 * @retval SCI_SUCCESS if the start io operation succeeds
5803 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
5804 * allocated for the io request.
5805 * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
5806 * state to accept io requests.
5808 * @todo How does the io_tag parameter get assigned to the io request?
5811 SCI_STATUS scic_sds_controller_ready_state_start_io_handler(
5812 SCI_BASE_CONTROLLER_T *controller,
5813 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5814 SCI_BASE_REQUEST_T *io_request,
5820 SCIC_SDS_CONTROLLER_T *this_controller;
5821 SCIC_SDS_REQUEST_T *the_request;
5822 SCIC_SDS_REMOTE_DEVICE_T *the_device;
5824 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5825 the_request = (SCIC_SDS_REQUEST_T *)io_request;
5826 the_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
5828 status = scic_sds_remote_device_start_io(this_controller, the_device, the_request);
5830 if (status == SCI_SUCCESS)
5832 this_controller->io_request_table[
5833 scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5835 scic_sds_controller_post_request(
5837 scic_sds_request_get_post_context(the_request)
5845 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5846 * and the complete io handler is called.
5847 * - Complete the io request on the remote device
5849 * - remove the io_request to the io_request_table
5851 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5852 * into a SCIC_SDS_CONTROLLER object.
5853 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5854 * SCIC_SDS_REMOTE_DEVICE object.
5855 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5856 * SCIC_SDS_IO_REQUEST object.
5858 * @return SCI_STATUS
5859 * @retval SCI_SUCCESS if the start io operation succeeds
5860 * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
5861 * state to accept io requests.
5864 SCI_STATUS scic_sds_controller_ready_state_complete_io_handler(
5865 SCI_BASE_CONTROLLER_T *controller,
5866 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5867 SCI_BASE_REQUEST_T *io_request
5872 SCIC_SDS_CONTROLLER_T *this_controller;
5873 SCIC_SDS_REQUEST_T *the_request;
5874 SCIC_SDS_REMOTE_DEVICE_T *the_device;
5876 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5877 the_request = (SCIC_SDS_REQUEST_T *)io_request;
5878 the_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
5880 status = scic_sds_remote_device_complete_io(
5881 this_controller, the_device, the_request);
5883 if (status == SCI_SUCCESS)
5885 index = scic_sds_io_tag_get_index(the_request->io_tag);
5886 this_controller->io_request_table[index] = SCI_INVALID_HANDLE;
5893 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5894 * and the continue io handler is called.
5896 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5897 * into a SCIC_SDS_CONTROLLER object.
5898 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5899 * SCIC_SDS_REMOTE_DEVICE object.
5900 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5901 * SCIC_SDS_IO_REQUEST object.
5903 * @return SCI_STATUS
5906 SCI_STATUS scic_sds_controller_ready_state_continue_io_handler(
5907 SCI_BASE_CONTROLLER_T *controller,
5908 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5909 SCI_BASE_REQUEST_T *io_request
5912 SCIC_SDS_CONTROLLER_T *this_controller;
5913 SCIC_SDS_REQUEST_T *the_request;
5915 the_request = (SCIC_SDS_REQUEST_T *)io_request;
5916 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5918 this_controller->io_request_table[
5919 scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5921 scic_sds_controller_post_request(
5923 scic_sds_request_get_post_context(the_request)
5930 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5931 * and the start task handler is called.
5932 * - The remote device is requested to start the task request
5934 * - assign the task to the io_request_table
5935 * - post the request to the SCU hardware
5937 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5938 * into a SCIC_SDS_CONTROLLER object.
5939 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5940 * SCIC_SDS_REMOTE_DEVICE object.
5941 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5942 * SCIC_SDS_IO_REQUEST object.
5943 * @param[in] task_tag This is the task tag to be assigned to the task request
5944 * or SCI_CONTROLLER_INVALID_IO_TAG.
5946 * @return SCI_STATUS
5947 * @retval SCI_SUCCESS if the start io operation succeeds
5948 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
5949 * allocated for the io request.
5950 * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
5951 * state to accept io requests.
5953 * @todo How does the io tag get assigned in this code path?
5956 SCI_STATUS scic_sds_controller_ready_state_start_task_handler(
5957 SCI_BASE_CONTROLLER_T *controller,
5958 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5959 SCI_BASE_REQUEST_T *io_request,
5963 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)
5965 SCIC_SDS_REQUEST_T *the_request = (SCIC_SDS_REQUEST_T *)
5967 SCIC_SDS_REMOTE_DEVICE_T *the_device = (SCIC_SDS_REMOTE_DEVICE_T *)
5971 status = scic_sds_remote_device_start_task(
5972 this_controller, the_device, the_request
5975 if (status == SCI_SUCCESS)
5977 this_controller->io_request_table[
5978 scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5980 scic_sds_controller_post_request(
5982 scic_sds_request_get_post_context(the_request)
5985 else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS)
5987 this_controller->io_request_table[
5988 scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5990 //We will let framework know this task request started successfully,
5991 //although core is still woring on starting the request (to post tc when
5993 status = SCI_SUCCESS;
5999 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
6000 * and the terminate request handler is called.
6001 * - call the io request terminate function
6003 * - post the terminate request to the SCU hardware
6005 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6006 * into a SCIC_SDS_CONTROLLER object.
6007 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6008 * SCIC_SDS_REMOTE_DEVICE object.
6009 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
6010 * SCIC_SDS_IO_REQUEST object.
6012 * @return SCI_STATUS
6013 * @retval SCI_SUCCESS if the start io operation succeeds
6014 * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
6015 * state to accept io requests.
6018 SCI_STATUS scic_sds_controller_ready_state_terminate_request_handler(
6019 SCI_BASE_CONTROLLER_T *controller,
6020 SCI_BASE_REMOTE_DEVICE_T *remote_device,
6021 SCI_BASE_REQUEST_T *io_request
6024 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)
6026 SCIC_SDS_REQUEST_T *the_request = (SCIC_SDS_REQUEST_T *)
6030 status = scic_sds_io_request_terminate(the_request);
6031 if (status == SCI_SUCCESS)
6033 // Utilize the original post context command and or in the POST_TC_ABORT
6034 // request sub-type.
6035 scic_sds_controller_post_request(
6037 scic_sds_request_get_post_context(the_request)
6038 | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT
6046 * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
6047 * link up handler is called. This method will perform the following:
6048 * - Stop the phy timer
6049 * - Start the next phy
6050 * - Report the link up condition to the port object
6052 * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the link up
6054 * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
6055 * @param[in] phy This is the SCIC_SDS_PHY which has gone link up.
6060 void scic_sds_controller_ready_state_link_up_handler(
6061 SCIC_SDS_CONTROLLER_T *this_controller,
6062 SCIC_SDS_PORT_T *port,
6066 this_controller->port_agent.link_up_handler(
6067 this_controller, &this_controller->port_agent, port, phy
6072 * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
6073 * link down handler is called.
6074 * - Report the link down condition to the port object
6076 * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the
6077 * link down notification.
6078 * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
6079 * @param[in] phy This is the SCIC_SDS_PHY which has gone link down.
6084 void scic_sds_controller_ready_state_link_down_handler(
6085 SCIC_SDS_CONTROLLER_T *this_controller,
6086 SCIC_SDS_PORT_T *port,
6090 this_controller->port_agent.link_down_handler(
6091 this_controller, &this_controller->port_agent, port, phy
6095 //*****************************************************************************
6096 //* STOPPING STATE HANDLERS
6097 //*****************************************************************************
6100 * This method is called when the SCIC_SDS_CONTROLLER is in a stopping state
6101 * and the complete io handler is called.
6102 * - This function is not yet implemented
6104 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6105 * into a SCIC_SDS_CONTROLLER object.
6106 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6107 * SCIC_SDS_REMOTE_DEVICE object.
6108 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
6109 * SCIC_SDS_IO_REQUEST object.
6111 * @return SCI_STATUS
6112 * @retval SCI_FAILURE
6115 SCI_STATUS scic_sds_controller_stopping_state_complete_io_handler(
6116 SCI_BASE_CONTROLLER_T *controller,
6117 SCI_BASE_REMOTE_DEVICE_T *remote_device,
6118 SCI_BASE_REQUEST_T *io_request
6121 SCIC_SDS_CONTROLLER_T *this_controller;
6122 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
6124 /// @todo Implement this function
6129 * This method is called when the SCIC_SDS_CONTROLLER is in a stopping state
6130 * and the a remote device has stopped.
6132 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6133 * into a SCIC_SDS_CONTROLLER object.
6134 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6135 * SCIC_SDS_REMOTE_DEVICE object.
6140 void scic_sds_controller_stopping_state_device_stopped_handler(
6141 SCIC_SDS_CONTROLLER_T * controller,
6142 SCIC_SDS_REMOTE_DEVICE_T * remote_device
6145 if (!scic_sds_controller_has_remote_devices_stopping(controller))
6147 sci_base_state_machine_change_state(
6148 &controller->parent.state_machine,
6149 SCI_BASE_CONTROLLER_STATE_STOPPED
6154 //*****************************************************************************
6155 //* STOPPED STATE HANDLERS
6156 //*****************************************************************************
6158 //*****************************************************************************
6159 //* FAILED STATE HANDLERS
6160 //*****************************************************************************
6163 * This method is called when the SCIC_SDS_CONTROLLER failed state start
6164 * io/task handler is in place.
6165 * - Issue a warning message
6167 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6168 * into a SCIC_SDS_CONTROLLER object.
6169 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
6170 * used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
6171 * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
6172 * would be cast to a SCIC_SDS_IO_REQUEST.
6173 * @param[in] io_tag This is the IO tag to be assigned to the IO request or
6174 * SCI_CONTROLLER_INVALID_IO_TAG.
6176 * @return SCI_FAILURE
6177 * @retval SCI_FAILURE
6180 SCI_STATUS scic_sds_controller_failed_state_start_operation_handler(
6181 SCI_BASE_CONTROLLER_T *controller,
6182 SCI_BASE_REMOTE_DEVICE_T *remote_device,
6183 SCI_BASE_REQUEST_T *io_request,
6187 SCIC_SDS_CONTROLLER_T *this_controller;
6188 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
6191 sci_base_object_get_logger(this_controller),
6192 SCIC_LOG_OBJECT_CONTROLLER,
6193 "SCIC Controller requested to start an io/task from failed state %d\n",
6194 sci_base_state_machine_get_state(
6195 scic_sds_controller_get_base_state_machine(this_controller))
6202 * This method is called when the SCIC_SDS_CONTROLLER is in the failed state
6203 * reset handler is in place.
6204 * - Transition to SCI_BASE_CONTROLLER_STATE_RESETTING
6206 * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
6207 * SCIC_SDS_CONTROLLER object.
6209 * @return SCI_STATUS
6210 * @retval SCI_FAILURE if fatal memory error occurred
6213 SCI_STATUS scic_sds_controller_failed_state_reset_handler(
6214 SCI_BASE_CONTROLLER_T *controller
6217 SCIC_SDS_CONTROLLER_T *this_controller;
6218 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
6220 if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR) {
6222 sci_base_object_get_logger(controller),
6223 SCIC_LOG_OBJECT_CONTROLLER,
6224 "scic_sds_controller_resetting_state_enter(0x%x) enter\n not allowed with fatal memory error",
6230 return scic_sds_controller_general_reset_handler(controller);
6235 * This method is called when the SCIC_SDS_CONTROLLER is in the failed state
6236 * and the terminate request handler is called.
6237 * - call the io request terminate function
6239 * - post the terminate request to the SCU hardware
6241 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6242 * into a SCIC_SDS_CONTROLLER object.
6243 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6244 * SCIC_SDS_REMOTE_DEVICE object.
6245 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
6246 * SCIC_SDS_IO_REQUEST object.
6248 * @return SCI_STATUS
6249 * @retval SCI_SUCCESS if the start io operation succeeds
6250 * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
6251 * state to accept io requests.
6254 SCI_STATUS scic_sds_controller_failed_state_terminate_request_handler(
6255 SCI_BASE_CONTROLLER_T *controller,
6256 SCI_BASE_REMOTE_DEVICE_T *remote_device,
6257 SCI_BASE_REQUEST_T *io_request
6260 SCIC_SDS_REQUEST_T *the_request = (SCIC_SDS_REQUEST_T *)
6263 return scic_sds_io_request_terminate(the_request);
6266 SCIC_SDS_CONTROLLER_STATE_HANDLER_T
6267 scic_sds_controller_state_handler_table[SCI_BASE_CONTROLLER_MAX_STATES] =
6269 // SCI_BASE_CONTROLLER_STATE_INITIAL
6276 scic_sds_controller_default_start_operation_handler,
6277 scic_sds_controller_default_start_operation_handler,
6278 scic_sds_controller_default_request_handler,
6279 scic_sds_controller_default_request_handler,
6280 scic_sds_controller_default_request_handler,
6284 scic_sds_controller_default_request_handler,
6290 // SCI_BASE_CONTROLLER_STATE_RESET
6296 scic_sds_controller_reset_state_initialize_handler,
6297 scic_sds_controller_default_start_operation_handler,
6298 scic_sds_controller_default_start_operation_handler,
6299 scic_sds_controller_default_request_handler,
6300 scic_sds_controller_default_request_handler,
6301 scic_sds_controller_default_request_handler,
6305 scic_sds_controller_default_request_handler,
6311 // SCI_BASE_CONTROLLER_STATE_INITIALIZING
6318 scic_sds_controller_default_start_operation_handler,
6319 scic_sds_controller_default_start_operation_handler,
6320 scic_sds_controller_default_request_handler,
6321 scic_sds_controller_default_request_handler,
6322 scic_sds_controller_default_request_handler,
6326 scic_sds_controller_default_request_handler,
6332 // SCI_BASE_CONTROLLER_STATE_INITIALIZED
6335 scic_sds_controller_initialized_state_start_handler,
6339 scic_sds_controller_default_start_operation_handler,
6340 scic_sds_controller_default_start_operation_handler,
6341 scic_sds_controller_default_request_handler,
6342 scic_sds_controller_default_request_handler,
6343 scic_sds_controller_default_request_handler,
6347 scic_sds_controller_default_request_handler,
6353 // SCI_BASE_CONTROLLER_STATE_STARTING
6360 scic_sds_controller_default_start_operation_handler,
6361 scic_sds_controller_default_start_operation_handler,
6362 scic_sds_controller_default_request_handler,
6363 scic_sds_controller_default_request_handler,
6364 scic_sds_controller_default_request_handler,
6368 scic_sds_controller_default_request_handler,
6369 scic_sds_controller_starting_state_link_up_handler,
6370 scic_sds_controller_starting_state_link_down_handler,
6374 // SCI_BASE_CONTROLLER_STATE_READY
6378 scic_sds_controller_ready_state_stop_handler,
6379 scic_sds_controller_general_reset_handler,
6381 scic_sds_controller_ready_state_start_io_handler,
6382 scic_sds_controller_default_start_operation_handler,
6383 scic_sds_controller_ready_state_complete_io_handler,
6384 scic_sds_controller_default_request_handler,
6385 scic_sds_controller_ready_state_continue_io_handler,
6386 scic_sds_controller_ready_state_start_task_handler,
6387 scic_sds_controller_ready_state_complete_io_handler
6389 scic_sds_controller_ready_state_terminate_request_handler,
6390 scic_sds_controller_ready_state_link_up_handler,
6391 scic_sds_controller_ready_state_link_down_handler,
6395 // SCI_BASE_CONTROLLER_STATE_RESETTING
6402 scic_sds_controller_default_start_operation_handler,
6403 scic_sds_controller_default_start_operation_handler,
6404 scic_sds_controller_default_request_handler,
6405 scic_sds_controller_default_request_handler,
6406 scic_sds_controller_default_request_handler,
6410 scic_sds_controller_default_request_handler,
6416 // SCI_BASE_CONTROLLER_STATE_STOPPING
6423 scic_sds_controller_default_start_operation_handler,
6424 scic_sds_controller_default_start_operation_handler,
6425 scic_sds_controller_stopping_state_complete_io_handler,
6426 scic_sds_controller_default_request_handler,
6427 scic_sds_controller_default_request_handler,
6431 scic_sds_controller_default_request_handler,
6435 scic_sds_controller_stopping_state_device_stopped_handler
6437 // SCI_BASE_CONTROLLER_STATE_STOPPED
6442 scic_sds_controller_failed_state_reset_handler,
6444 scic_sds_controller_default_start_operation_handler,
6445 scic_sds_controller_default_start_operation_handler,
6446 scic_sds_controller_default_request_handler,
6447 scic_sds_controller_default_request_handler,
6448 scic_sds_controller_default_request_handler,
6452 scic_sds_controller_default_request_handler,
6458 // SCI_BASE_CONTROLLER_STATE_FAILED
6463 scic_sds_controller_general_reset_handler,
6465 scic_sds_controller_failed_state_start_operation_handler,
6466 scic_sds_controller_failed_state_start_operation_handler,
6467 scic_sds_controller_default_request_handler,
6468 scic_sds_controller_default_request_handler,
6469 scic_sds_controller_default_request_handler,
6473 scic_sds_controller_failed_state_terminate_request_handler,
6481 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6482 * entry to the SCI_BASE_CONTROLLER_STATE_INITIAL.
6483 * - Set the state handlers to the controllers initial state.
6485 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6486 * SCIC_SDS_CONTROLLER object.
6490 * @todo This function should initialze the controller object.
6493 void scic_sds_controller_initial_state_enter(
6494 SCI_BASE_OBJECT_T *object
6497 SCIC_SDS_CONTROLLER_T *this_controller;
6498 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6500 scic_sds_controller_set_base_state_handlers(
6501 this_controller, SCI_BASE_CONTROLLER_STATE_INITIAL);
6503 sci_base_state_machine_change_state(
6504 &this_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_RESET);
6508 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6509 * entry to the SCI_BASE_CONTROLLER_STATE_RESET.
6510 * - Set the state handlers to the controllers reset state.
6512 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6513 * SCIC_SDS_CONTROLLER object.
6518 void scic_sds_controller_reset_state_enter(
6519 SCI_BASE_OBJECT_T *object
6523 SCIC_SDS_CONTROLLER_T *this_controller;
6524 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6526 scic_sds_controller_set_base_state_handlers(
6527 this_controller, SCI_BASE_CONTROLLER_STATE_RESET);
6529 scic_sds_port_configuration_agent_construct(&this_controller->port_agent);
6531 // Construct the ports for this controller
6532 for (index = 0; index < (SCI_MAX_PORTS + 1); index++)
6534 scic_sds_port_construct(
6535 &this_controller->port_table[index],
6536 (index == SCI_MAX_PORTS) ? SCIC_SDS_DUMMY_PORT : index,
6541 // Construct the phys for this controller
6542 for (index = 0; index < SCI_MAX_PHYS; index++)
6544 // Add all the PHYs to the dummy port
6545 scic_sds_phy_construct(
6546 &this_controller->phy_table[index],
6547 &this_controller->port_table[SCI_MAX_PORTS],
6552 this_controller->invalid_phy_mask = 0;
6554 // Set the default maximum values
6555 this_controller->completion_event_entries = SCU_EVENT_COUNT;
6556 this_controller->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT;
6557 this_controller->remote_node_entries = SCI_MAX_REMOTE_DEVICES;
6558 this_controller->logical_port_entries = SCI_MAX_PORTS;
6559 this_controller->task_context_entries = SCU_IO_REQUEST_COUNT;
6560 this_controller->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT;
6561 this_controller->uf_control.address_table.count= SCU_UNSOLICITED_FRAME_COUNT;
6563 // Initialize the User and OEM parameters to default values.
6564 scic_sds_controller_set_default_config_parameters(this_controller);
6568 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6569 * entry to the SCI_BASE_CONTROLLER_STATE_INITIALIZING.
6570 * - Set the state handlers to the controllers initializing state.
6572 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6573 * SCIC_SDS_CONTROLLER object.
6578 void scic_sds_controller_initializing_state_enter(
6579 SCI_BASE_OBJECT_T *object
6582 SCIC_SDS_CONTROLLER_T *this_controller;
6583 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6585 scic_sds_controller_set_base_state_handlers(
6586 this_controller, SCI_BASE_CONTROLLER_STATE_INITIALIZING);
6590 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6591 * entry to the SCI_BASE_CONTROLLER_STATE_INITIALIZED.
6592 * - Set the state handlers to the controllers initialized state.
6594 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6595 * SCIC_SDS_CONTROLLER object.
6600 void scic_sds_controller_initialized_state_enter(
6601 SCI_BASE_OBJECT_T *object
6604 SCIC_SDS_CONTROLLER_T *this_controller;
6605 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6607 scic_sds_controller_set_base_state_handlers(
6608 this_controller, SCI_BASE_CONTROLLER_STATE_INITIALIZED);
6612 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6613 * entry to the SCI_BASE_CONTROLLER_STATE_STARTING.
6614 * - Set the state handlers to the controllers starting state.
6616 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6617 * SCIC_SDS_CONTROLLER object.
6622 void scic_sds_controller_starting_state_enter(
6623 SCI_BASE_OBJECT_T *object
6626 SCIC_SDS_CONTROLLER_T *this_controller;
6627 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6629 scic_sds_controller_set_base_state_handlers(
6630 this_controller, SCI_BASE_CONTROLLER_STATE_STARTING);
6635 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
6636 * from the SCI_BASE_CONTROLLER_STATE_STARTING.
6637 * - This function stops the controller starting timeout timer.
6639 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6640 * SCIC_SDS_CONTROLLER object.
6645 void scic_sds_controller_starting_state_exit(
6646 SCI_BASE_OBJECT_T *object
6649 SCIC_SDS_CONTROLLER_T *this_controller;
6650 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6652 scic_cb_timer_stop(object, this_controller->timeout_timer);
6654 // We are done with this timer since we are exiting the starting
6655 // state so remove it
6656 scic_cb_timer_destroy(
6658 this_controller->phy_startup_timer
6661 this_controller->phy_startup_timer = NULL;
6665 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6666 * entry to the SCI_BASE_CONTROLLER_STATE_READY.
6667 * - Set the state handlers to the controllers ready state.
6669 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6670 * SCIC_SDS_CONTROLLER object.
6675 void scic_sds_controller_ready_state_enter(
6676 SCI_BASE_OBJECT_T *object
6679 U32 clock_gating_unit_value;
6680 SCIC_SDS_CONTROLLER_T *this_controller;
6681 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6683 scic_sds_controller_set_base_state_handlers(
6684 this_controller, SCI_BASE_CONTROLLER_STATE_READY);
6687 * enable clock gating for power control of the scu unit
6689 clock_gating_unit_value = SMU_CGUCR_READ(this_controller);
6691 clock_gating_unit_value &= ~( SMU_CGUCR_GEN_BIT(REGCLK_ENABLE)
6692 | SMU_CGUCR_GEN_BIT(TXCLK_ENABLE)
6693 | SMU_CGUCR_GEN_BIT(XCLK_ENABLE) );
6694 clock_gating_unit_value |= SMU_CGUCR_GEN_BIT(IDLE_ENABLE);
6696 SMU_CGUCR_WRITE(this_controller, clock_gating_unit_value);
6698 //set the default interrupt coalescence number and timeout value.
6699 scic_controller_set_interrupt_coalescence(
6700 this_controller, 0x10, 250);
6704 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
6705 * from the SCI_BASE_CONTROLLER_STATE_READY.
6706 * - This function does nothing.
6708 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6709 * SCIC_SDS_CONTROLLER object.
6714 void scic_sds_controller_ready_state_exit(
6715 SCI_BASE_OBJECT_T *object
6718 U32 clock_gating_unit_value;
6719 SCIC_SDS_CONTROLLER_T *this_controller;
6720 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6723 * restore clock gating for power control of the scu unit
6725 clock_gating_unit_value = SMU_CGUCR_READ(this_controller);
6727 clock_gating_unit_value &= ~SMU_CGUCR_GEN_BIT(IDLE_ENABLE);
6728 clock_gating_unit_value |= ( SMU_CGUCR_GEN_BIT(REGCLK_ENABLE)
6729 | SMU_CGUCR_GEN_BIT(TXCLK_ENABLE)
6730 | SMU_CGUCR_GEN_BIT(XCLK_ENABLE) );
6732 SMU_CGUCR_WRITE(this_controller, clock_gating_unit_value);
6734 //disable interrupt coalescence.
6735 scic_controller_set_interrupt_coalescence(this_controller, 0, 0);
6739 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6740 * entry to the SCI_BASE_CONTROLLER_STATE_READY.
6741 * - Set the state handlers to the controllers ready state.
6742 * - Stop all of the remote devices on this controller
6743 * - Stop the ports on this controller
6744 * - Stop the phys on this controller
6746 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6747 * SCIC_SDS_CONTROLLER object.
6752 void scic_sds_controller_stopping_state_enter(
6753 SCI_BASE_OBJECT_T *object
6756 SCIC_SDS_CONTROLLER_T *this_controller;
6757 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6759 scic_sds_controller_set_base_state_handlers(
6760 this_controller, SCI_BASE_CONTROLLER_STATE_STOPPING);
6762 // Stop all of the components for this controller in the reverse order
6763 // from which they are initialized.
6764 scic_sds_controller_stop_devices(this_controller);
6765 scic_sds_controller_stop_ports(this_controller);
6767 if (!scic_sds_controller_has_remote_devices_stopping(this_controller))
6769 sci_base_state_machine_change_state(
6770 &this_controller->parent.state_machine,
6771 SCI_BASE_CONTROLLER_STATE_STOPPED
6777 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
6778 * from the SCI_BASE_CONTROLLER_STATE_STOPPING.
6779 * - This function stops the controller stopping timeout timer.
6781 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6782 * SCIC_SDS_CONTROLLER object.
6787 void scic_sds_controller_stopping_state_exit(
6788 SCI_BASE_OBJECT_T *object
6791 SCIC_SDS_CONTROLLER_T *this_controller;
6792 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6794 scic_cb_timer_stop(this_controller, this_controller->timeout_timer);
6798 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6799 * entry to the SCI_BASE_CONTROLLER_STATE_STOPPED.
6800 * - Set the state handlers to the controllers stopped state.
6802 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6803 * SCIC_SDS_CONTROLLER object.
6808 void scic_sds_controller_stopped_state_enter(
6809 SCI_BASE_OBJECT_T *object
6812 SCIC_SDS_CONTROLLER_T *this_controller;
6813 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6815 scic_sds_controller_set_base_state_handlers(
6816 this_controller, SCI_BASE_CONTROLLER_STATE_STOPPED);
6818 // We are done with this timer until the next timer we initialize
6819 scic_cb_timer_destroy(
6821 this_controller->timeout_timer
6823 this_controller->timeout_timer = NULL;
6825 // Controller has stopped so disable all the phys on this controller
6826 scic_sds_controller_stop_phys(this_controller);
6828 scic_sds_port_configuration_agent_destroy(
6830 &this_controller->port_agent
6833 scic_cb_controller_stop_complete(this_controller, SCI_SUCCESS);
6837 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6838 * entry to the SCI_BASE_CONTROLLER_STATE_RESETTING.
6839 * - Set the state handlers to the controllers resetting state.
6840 * - Write to the SCU hardware reset register to force a reset
6841 * - Transition to the SCI_BASE_CONTROLLER_STATE_RESET
6843 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6844 * SCIC_SDS_CONTROLLER object.
6849 void scic_sds_controller_resetting_state_enter(
6850 SCI_BASE_OBJECT_T *object
6853 SCIC_SDS_CONTROLLER_T *this_controller;
6854 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6857 sci_base_object_get_logger(this_controller),
6858 SCIC_LOG_OBJECT_CONTROLLER,
6859 "scic_sds_controller_resetting_state_enter(0x%x) enter\n",
6863 scic_sds_controller_set_base_state_handlers(
6864 this_controller, SCI_BASE_CONTROLLER_STATE_RESETTING);
6866 scic_sds_controller_reset_hardware(this_controller);
6868 sci_base_state_machine_change_state(
6869 scic_sds_controller_get_base_state_machine(this_controller),
6870 SCI_BASE_CONTROLLER_STATE_RESET
6875 SCI_STATUS scic_sds_abort_reqests(
6876 SCIC_SDS_CONTROLLER_T * controller,
6877 SCIC_SDS_REMOTE_DEVICE_T * remote_device,
6878 SCIC_SDS_PORT_T * port
6881 SCI_STATUS status = SCI_SUCCESS;
6882 SCI_STATUS terminate_status = SCI_SUCCESS;
6883 SCIC_SDS_REQUEST_T *the_request;
6887 if (remote_device != NULL)
6888 request_count = remote_device->started_request_count;
6889 else if (port != NULL)
6890 request_count = port->started_request_count;
6892 request_count = SCI_MAX_IO_REQUESTS;
6896 (index < SCI_MAX_IO_REQUESTS) && (request_count > 0);
6899 the_request = controller->io_request_table[index];
6901 if (the_request != NULL)
6903 if (the_request->target_device == remote_device
6904 || the_request->target_device->owning_port == port
6905 || (remote_device == NULL && port == NULL))
6907 terminate_status = scic_controller_terminate_request(
6909 the_request->target_device,
6913 if (terminate_status != SCI_SUCCESS)
6914 status = terminate_status;
6924 SCI_STATUS scic_sds_terminate_reqests(
6925 SCIC_SDS_CONTROLLER_T *this_controller,
6926 SCIC_SDS_REMOTE_DEVICE_T *this_remote_device,
6927 SCIC_SDS_PORT_T *this_port
6930 SCI_STATUS status = SCI_SUCCESS;
6931 SCI_STATUS abort_status = SCI_SUCCESS;
6933 // move all request to abort state
6934 abort_status = scic_sds_abort_reqests(this_controller, this_remote_device, this_port);
6936 if (abort_status != SCI_SUCCESS)
6937 status = abort_status;
6939 //move all request to complete state
6940 if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR)
6941 abort_status = scic_sds_abort_reqests(this_controller, this_remote_device, this_port);
6943 if (abort_status != SCI_SUCCESS)
6944 status = abort_status;
6950 SCI_STATUS scic_sds_terminate_all_requests(
6951 SCIC_SDS_CONTROLLER_T * controller
6954 return scic_sds_terminate_reqests(controller, NULL, NULL);
6958 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6959 * entry to the SCI_BASE_CONTROLLER_STATE_FAILED.
6960 * - Set the state handlers to the controllers failed state.
6962 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6963 * SCIC_SDS_CONTROLLER object.
6968 void scic_sds_controller_failed_state_enter(
6969 SCI_BASE_OBJECT_T *object
6972 SCIC_SDS_CONTROLLER_T *this_controller;
6973 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6975 scic_sds_controller_set_base_state_handlers(
6976 this_controller, SCI_BASE_CONTROLLER_STATE_FAILED);
6978 if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR)
6979 scic_sds_terminate_all_requests(this_controller);
6981 scic_sds_controller_release_resource(this_controller);
6983 //notify framework the controller failed.
6984 scic_cb_controller_error(this_controller,
6985 this_controller->parent.error);
6988 // ---------------------------------------------------------------------------
6991 scic_sds_controller_state_table[SCI_BASE_CONTROLLER_MAX_STATES] =
6994 SCI_BASE_CONTROLLER_STATE_INITIAL,
6995 scic_sds_controller_initial_state_enter,
6999 SCI_BASE_CONTROLLER_STATE_RESET,
7000 scic_sds_controller_reset_state_enter,
7004 SCI_BASE_CONTROLLER_STATE_INITIALIZING,
7005 scic_sds_controller_initializing_state_enter,
7009 SCI_BASE_CONTROLLER_STATE_INITIALIZED,
7010 scic_sds_controller_initialized_state_enter,
7014 SCI_BASE_CONTROLLER_STATE_STARTING,
7015 scic_sds_controller_starting_state_enter,
7016 scic_sds_controller_starting_state_exit,
7019 SCI_BASE_CONTROLLER_STATE_READY,
7020 scic_sds_controller_ready_state_enter,
7021 scic_sds_controller_ready_state_exit,
7024 SCI_BASE_CONTROLLER_STATE_RESETTING,
7025 scic_sds_controller_resetting_state_enter,
7029 SCI_BASE_CONTROLLER_STATE_STOPPING,
7030 scic_sds_controller_stopping_state_enter,
7031 scic_sds_controller_stopping_state_exit,
7034 SCI_BASE_CONTROLLER_STATE_STOPPED,
7035 scic_sds_controller_stopped_state_enter,
7039 SCI_BASE_CONTROLLER_STATE_FAILED,
7040 scic_sds_controller_failed_state_enter,