2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 #include <sys/cdefs.h>
54 __FBSDID("$FreeBSD$");
59 * @brief This file contains the implementation of the SCIC_SDS_CONTROLLER
60 * public, protected, and private methods.
63 #include <dev/isci/types.h>
64 #include <dev/isci/scil/sci_util.h>
65 #include <dev/isci/scil/scic_controller.h>
66 #include <dev/isci/scil/scic_port.h>
67 #include <dev/isci/scil/scic_phy.h>
68 #include <dev/isci/scil/scic_remote_device.h>
69 #include <dev/isci/scil/scic_user_callback.h>
70 #include <dev/isci/scil/scic_sds_pci.h>
71 #include <dev/isci/scil/scic_sds_library.h>
72 #include <dev/isci/scil/scic_sds_controller.h>
73 #include <dev/isci/scil/scic_sds_controller_registers.h>
74 #include <dev/isci/scil/scic_sds_port.h>
75 #include <dev/isci/scil/scic_sds_phy.h>
76 #include <dev/isci/scil/scic_sds_remote_device.h>
77 #include <dev/isci/scil/scic_sds_request.h>
78 #include <dev/isci/scil/scic_sds_logger.h>
79 #include <dev/isci/scil/scic_sds_port_configuration_agent.h>
80 #include <dev/isci/scil/scu_constants.h>
81 #include <dev/isci/scil/scu_event_codes.h>
82 #include <dev/isci/scil/scu_completion_codes.h>
83 #include <dev/isci/scil/scu_task_context.h>
84 #include <dev/isci/scil/scu_remote_node_context.h>
85 #include <dev/isci/scil/scu_unsolicited_frame.h>
86 #include <dev/isci/scil/intel_pci.h>
87 #include <dev/isci/scil/scic_sgpio.h>
88 #include <dev/isci/scil/scic_sds_phy_registers.h>
90 #define SCU_CONTEXT_RAM_INIT_STALL_TIME 200
91 #define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT 3
92 #define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT 3
94 #define SCU_MAX_ZPT_DWORD_INDEX 131
97 * The number of milliseconds to wait for a phy to start.
99 #define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT 100
102 * The number of milliseconds to wait while a given phy is consuming
103 * power before allowing another set of phys to consume power.
104 * Ultimately, this will be specified by OEM parameter.
106 #define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500
109 * This macro will return the cycle bit of the completion queue entry
111 #define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000)
114 * This macro will normalize the completion queue get pointer so its value
115 * can be used as an index into an array
117 #define NORMALIZE_GET_POINTER(x) \
118 ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK)
121 * This macro will normalize the completion queue put pointer so its value
122 * can be used as an array inde
124 #define NORMALIZE_PUT_POINTER(x) \
125 ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK)
129 * This macro will normalize the completion queue cycle pointer so it
130 * matches the completion queue cycle bit
132 #define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \
133 (((U32)(SMU_CQGR_CYCLE_BIT & (x))) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT))
136 * This macro will normalize the completion queue event entry so its value
137 * can be used as an index.
139 #define NORMALIZE_EVENT_POINTER(x) \
141 ((U32)((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK)) \
142 >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \
146 * This macro will increment the controllers completion queue index value
147 * and possibly toggle the cycle bit if the completion queue index wraps
150 #define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \
151 INCREMENT_QUEUE_GET( \
154 (controller)->completion_queue_entries, \
159 * This macro will increment the controllers event queue index value and
160 * possibly toggle the event cycle bit if the event queue index wraps back
163 #define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \
164 INCREMENT_QUEUE_GET( \
167 (controller)->completion_event_entries, \
168 SMU_CQGR_EVENT_CYCLE_BIT \
171 //****************************************************************************-
172 //* SCIC SDS Controller Initialization Methods
173 //****************************************************************************-
176 * @brief This timer is used to start another phy after we have given up on
177 * the previous phy to transition to the ready state.
179 * @param[in] controller
182 void scic_sds_controller_phy_startup_timeout_handler(
187 SCIC_SDS_CONTROLLER_T *this_controller;
188 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
190 this_controller->phy_startup_timer_pending = FALSE;
192 status = SCI_FAILURE;
194 while (status != SCI_SUCCESS)
196 status = scic_sds_controller_start_next_phy(this_controller);
201 * This method initializes the phy startup operations for controller start.
203 * @param this_controller
206 SCI_STATUS scic_sds_controller_initialize_phy_startup(
207 SCIC_SDS_CONTROLLER_T *this_controller
210 this_controller->phy_startup_timer = scic_cb_timer_create(
212 scic_sds_controller_phy_startup_timeout_handler,
216 if (this_controller->phy_startup_timer == NULL)
218 return SCI_FAILURE_INSUFFICIENT_RESOURCES;
222 this_controller->next_phy_to_start = 0;
223 this_controller->phy_startup_timer_pending = FALSE;
230 * This method initializes the power control operations for the controller
233 * @param this_controller
235 void scic_sds_controller_initialize_power_control(
236 SCIC_SDS_CONTROLLER_T *this_controller
239 this_controller->power_control.timer = scic_cb_timer_create(
241 scic_sds_controller_power_control_timer_handler,
246 this_controller->power_control.requesters,
248 sizeof(this_controller->power_control.requesters)
251 this_controller->power_control.phys_waiting = 0;
252 this_controller->power_control.remote_devices_granted_power = 0;
255 // ---------------------------------------------------------------------------
257 #define SCU_REMOTE_NODE_CONTEXT_ALIGNMENT (32)
258 #define SCU_TASK_CONTEXT_ALIGNMENT (256)
259 #define SCU_UNSOLICITED_FRAME_ADDRESS_ALIGNMENT (64)
260 #define SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT (1024)
261 #define SCU_UNSOLICITED_FRAME_HEADER_ALIGNMENT (64)
263 // ---------------------------------------------------------------------------
266 * @brief This method builds the memory descriptor table for this
269 * @param[in] this_controller This parameter specifies the controller
270 * object for which to build the memory table.
274 void scic_sds_controller_build_memory_descriptor_table(
275 SCIC_SDS_CONTROLLER_T *this_controller
278 sci_base_mde_construct(
279 &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
280 SCU_COMPLETION_RAM_ALIGNMENT,
281 (sizeof(U32) * this_controller->completion_queue_entries),
282 (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
285 sci_base_mde_construct(
286 &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
287 SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
288 this_controller->remote_node_entries * sizeof(SCU_REMOTE_NODE_CONTEXT_T),
289 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
292 sci_base_mde_construct(
293 &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
294 SCU_TASK_CONTEXT_ALIGNMENT,
295 this_controller->task_context_entries * sizeof(SCU_TASK_CONTEXT_T),
296 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
299 // The UF buffer address table size must be programmed to a power
300 // of 2. Find the first power of 2 that is equal to or greater then
301 // the number of unsolicited frame buffers to be utilized.
302 scic_sds_unsolicited_frame_control_set_address_table_count(
303 &this_controller->uf_control
306 sci_base_mde_construct(
307 &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
308 SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
309 scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
310 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
315 * @brief This method validates the driver supplied memory descriptor
318 * @param[in] this_controller
322 SCI_STATUS scic_sds_controller_validate_memory_descriptor_table(
323 SCIC_SDS_CONTROLLER_T *this_controller
328 mde_list_valid = sci_base_mde_is_valid(
329 &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
330 SCU_COMPLETION_RAM_ALIGNMENT,
331 (sizeof(U32) * this_controller->completion_queue_entries),
332 (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
335 if (mde_list_valid == FALSE)
336 return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
338 mde_list_valid = sci_base_mde_is_valid(
339 &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
340 SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
341 this_controller->remote_node_entries * sizeof(SCU_REMOTE_NODE_CONTEXT_T),
342 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
345 if (mde_list_valid == FALSE)
346 return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
348 mde_list_valid = sci_base_mde_is_valid(
349 &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
350 SCU_TASK_CONTEXT_ALIGNMENT,
351 this_controller->task_context_entries * sizeof(SCU_TASK_CONTEXT_T),
352 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
355 if (mde_list_valid == FALSE)
356 return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
358 mde_list_valid = sci_base_mde_is_valid(
359 &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
360 SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
361 scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
362 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
365 if (mde_list_valid == FALSE)
366 return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
372 * @brief This method initializes the controller with the physical memory
373 * addresses that are used to communicate with the driver.
375 * @param[in] this_controller
379 void scic_sds_controller_ram_initialization(
380 SCIC_SDS_CONTROLLER_T *this_controller
383 SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde;
385 // The completion queue is actually placed in cacheable memory
386 // Therefore it no longer comes out of memory in the MDL.
387 mde = &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE];
388 this_controller->completion_queue = (U32*) mde->virtual_address;
389 SMU_CQBAR_WRITE(this_controller, mde->physical_address);
391 // Program the location of the Remote Node Context table
393 mde = &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT];
394 this_controller->remote_node_context_table = (SCU_REMOTE_NODE_CONTEXT_T *)
395 mde->virtual_address;
396 SMU_RNCBAR_WRITE(this_controller, mde->physical_address);
398 // Program the location of the Task Context table into the SCU.
399 mde = &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT];
400 this_controller->task_context_table = (SCU_TASK_CONTEXT_T *)
401 mde->virtual_address;
402 SMU_HTTBAR_WRITE(this_controller, mde->physical_address);
404 mde = &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER];
405 scic_sds_unsolicited_frame_control_construct(
406 &this_controller->uf_control, mde, this_controller
409 // Inform the silicon as to the location of the UF headers and
413 this_controller->uf_control.headers.physical_address);
416 this_controller->uf_control.address_table.physical_address);
418 //enable the ECC correction and detection.
421 (SIGNLE_BIT_ERROR_CORRECTION_ENABLE
422 | MULTI_BIT_ERROR_REPORTING_ENABLE
423 | SINGLE_BIT_ERROR_REPORTING_ENABLE) );
426 (SIGNLE_BIT_ERROR_CORRECTION_ENABLE
427 | MULTI_BIT_ERROR_REPORTING_ENABLE
428 | SINGLE_BIT_ERROR_REPORTING_ENABLE) );
432 * @brief This method initializes the task context data for the controller.
434 * @param[in] this_controller
438 void scic_sds_controller_assign_task_entries(
439 SCIC_SDS_CONTROLLER_T *this_controller
444 // Assign all the TCs to function 0
445 // TODO: Do we actually need to read this register to write it back?
446 task_assignment = SMU_TCA_READ(this_controller, 0);
451 | (SMU_TCA_GEN_VAL(STARTING, 0))
452 | (SMU_TCA_GEN_VAL(ENDING, this_controller->task_context_entries - 1))
453 | (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE))
456 SMU_TCA_WRITE(this_controller, 0, task_assignment);
460 * @brief This method initializes the hardware completion queue.
462 * @param[in] this_controller
464 void scic_sds_controller_initialize_completion_queue(
465 SCIC_SDS_CONTROLLER_T *this_controller
469 U32 completion_queue_control_value;
470 U32 completion_queue_get_value;
471 U32 completion_queue_put_value;
473 this_controller->completion_queue_get = 0;
475 completion_queue_control_value = (
476 SMU_CQC_QUEUE_LIMIT_SET(this_controller->completion_queue_entries - 1)
477 | SMU_CQC_EVENT_LIMIT_SET(this_controller->completion_event_entries - 1)
480 SMU_CQC_WRITE(this_controller, completion_queue_control_value);
482 // Set the completion queue get pointer and enable the queue
483 completion_queue_get_value = (
484 (SMU_CQGR_GEN_VAL(POINTER, 0))
485 | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0))
486 | (SMU_CQGR_GEN_BIT(ENABLE))
487 | (SMU_CQGR_GEN_BIT(EVENT_ENABLE))
490 SMU_CQGR_WRITE(this_controller, completion_queue_get_value);
492 this_controller->completion_queue_get = completion_queue_get_value;
494 // Set the completion queue put pointer
495 completion_queue_put_value = (
496 (SMU_CQPR_GEN_VAL(POINTER, 0))
497 | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0))
500 SMU_CQPR_WRITE(this_controller, completion_queue_put_value);
502 // Initialize the cycle bit of the completion queue entries
503 for (index = 0; index < this_controller->completion_queue_entries; index++)
505 // If get.cycle_bit != completion_queue.cycle_bit
506 // its not a valid completion queue entry
507 // so at system start all entries are invalid
508 this_controller->completion_queue[index] = 0x80000000;
513 * @brief This method initializes the hardware unsolicited frame queue.
515 * @param[in] this_controller
517 void scic_sds_controller_initialize_unsolicited_frame_queue(
518 SCIC_SDS_CONTROLLER_T *this_controller
521 U32 frame_queue_control_value;
522 U32 frame_queue_get_value;
523 U32 frame_queue_put_value;
525 // Write the queue size
526 frame_queue_control_value =
527 SCU_UFQC_GEN_VAL(QUEUE_SIZE, this_controller->uf_control.address_table.count);
529 SCU_UFQC_WRITE(this_controller, frame_queue_control_value);
531 // Setup the get pointer for the unsolicited frame queue
532 frame_queue_get_value = (
533 SCU_UFQGP_GEN_VAL(POINTER, 0)
534 | SCU_UFQGP_GEN_BIT(ENABLE_BIT)
537 SCU_UFQGP_WRITE(this_controller, frame_queue_get_value);
539 // Setup the put pointer for the unsolicited frame queue
540 frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0);
542 SCU_UFQPP_WRITE(this_controller, frame_queue_put_value);
546 * @brief This method enables the hardware port task scheduler.
548 * @param[in] this_controller
550 void scic_sds_controller_enable_port_task_scheduler(
551 SCIC_SDS_CONTROLLER_T *this_controller
554 U32 port_task_scheduler_value;
556 port_task_scheduler_value = SCU_PTSGCR_READ(this_controller);
558 port_task_scheduler_value |=
559 (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE));
561 SCU_PTSGCR_WRITE(this_controller, port_task_scheduler_value);
564 // ---------------------------------------------------------------------------
566 #ifdef ARLINGTON_BUILD
568 * This method will read from the lexington status register. This is required
569 * as a read fence to the lexington register writes.
571 * @param this_controller
573 void scic_sds_controller_lex_status_read_fence(
574 SCIC_SDS_CONTROLLER_T *this_controller
580 lex_status = lex_register_read(
581 this_controller, this_controller->lex_registers + 0xC4);
584 sci_base_object_get_logger(this_controller),
585 SCIC_LOG_OBJECT_CONTROLLER,
586 "Controller 0x%x lex_status = 0x%08x\n",
587 this_controller, lex_status
592 * This method will initialize the arlington through the LEX_BAR.
594 * @param this_controller
596 void scic_sds_controller_lex_atux_initialization(
597 SCIC_SDS_CONTROLLER_T *this_controller
600 // 1. Reset all SCU PHY
602 this_controller, this_controller->lex_registers + 0x28, 0x0020FFFF) ;
604 // 2. Write to LEX_CTRL
606 this_controller, this_controller->lex_registers + 0xC0, 0x00000700);
608 scic_sds_controller_lex_status_read_fence(this_controller);
610 // 3. Enable PCI Master
612 this_controller, this_controller->lex_registers + 0x70, 0x00000002);
614 // 4. Enable SCU Register Clock Domain
616 this_controller, this_controller->lex_registers + 0xC0, 0x00000300);
618 scic_sds_controller_lex_status_read_fence(this_controller);
620 // 5.1 Release PHY-A Reg Reset
622 this_controller, this_controller->lex_registers + 0x28, 0x0000FFFF);
624 // 5.2 Initialize the AFE for PHY-A
625 scic_sds_controller_afe_initialization(this_controller);
627 scic_sds_controller_lex_status_read_fence(this_controller);
630 // 5.3 Release PHY Reg Reset
632 this_controller, this_controller->lex_registers + 0x28, 0x0000FFFF);
635 // 6.1 Release PHY-B Reg Reset
637 this_controller, this_controller->lex_registers + 0x28, 0x0040FFFF) ;
639 // 6.2 Initialize the AFE for PHY-B
640 scic_sds_controller_afe_initialization(this_controller);
642 scic_sds_controller_lex_status_read_fence(this_controller);
645 // 6.3 Release PHY-B Reg Reset
647 this_controller, this_controller->lex_registers + 0x28, 0x0040FFFF) ;
650 // 7. Enable SCU clock domaion
652 this_controller, this_controller->lex_registers + 0xC0, 0x00000100);
654 scic_sds_controller_lex_status_read_fence(this_controller);
656 // 8. Release LEX SCU Reset
658 this_controller, this_controller->lex_registers + 0xC0, 0x00000000);
660 scic_sds_controller_lex_status_read_fence(this_controller);
662 #if !defined(DISABLE_INTERRUPTS)
663 // 8a. Set legacy interrupts (SCU INTx to PCI-x INTA)
665 this_controller, this_controller->lex_registers + 0xC0, 0x00000800);
667 scic_sds_controller_lex_status_read_fence(this_controller);
671 // 9. Override TXOLVL
674 this_controller, this_controller->lex_registers + 0xC0, 0x27800000);
677 // 10. Release PHY-A & PHY-B Resets
679 this_controller, this_controller->lex_registers + 0x28, 0x0000FF77);
682 this_controller, this_controller->lex_registers + 0x28, 0x0000FF55);
685 this_controller, this_controller->lex_registers + 0x28, 0x0000FF11);
688 this_controller, this_controller->lex_registers + 0x28, 0x0000FF00);
691 this_controller, this_controller->lex_registers + 0x28, 0x0003FF00);
693 #endif // ARLINGTON_BUILD
695 // ---------------------------------------------------------------------------
697 #ifdef ARLINGTON_BUILD
699 * This method enables chipwatch on the arlington board
701 * @param[in] this_controller
703 void scic_sds_controller_enable_chipwatch(
704 SCIC_SDS_CONTROLLER_T *this_controller
708 this_controller, this_controller->lex_registers + 0x88, 0x09090909);
711 this_controller, this_controller->lex_registers + 0x8C, 0xcac9c862);
716 * This macro is used to delay between writes to the AFE registers
717 * during AFE initialization.
719 #define AFE_REGISTER_WRITE_DELAY 10
722 * Initialize the AFE for this phy index.
724 * @todo We need to read the AFE setup from the OEM parameters
726 * @param[in] this_controller
730 #if defined(ARLINGTON_BUILD)
731 void scic_sds_controller_afe_initialization(
732 SCIC_SDS_CONTROLLER_T *this_controller
735 // 1. Establish Power
736 // Hold Bias, PLL, and RX TX in reset and powerdown
738 // pe_afe0_txpdn0,1,2,3 = 1
739 // pe_afe0_rxpdn0,1,2,3 = 1
740 // pe_afe0_txrst0,1,2,3_n = 0
741 // pe_afe0_rxrst0,1,2,3_n = 0
745 scu_afe_register_write(
746 this_controller, afe_pll_control, 0x00247506);
748 // 2. Write 0x00000000 to AFE XCVR Ctrl2
749 scu_afe_register_write(
750 this_controller, afe_dfx_transceiver_status_clear, 0x00000000);
752 // 3. afe0_override_en = 0
753 // afe0_pll_dis_override = 0
754 // afe0_tx_rst_override = 0
756 // pe_afe0_txrate = 01
757 // pe_afe0_rxrate = 01
758 // pe_afe0_txdis = 11
760 // pe_afe0_txovlv = 9'b001110000
761 scu_afe_register_write(
762 this_controller, afe_transceiver_control0[0], 0x0700141e);
764 // 4. Configure PLL Unit
765 // Write 0x00200506 to AFE PLL Ctrl Register 0
766 scu_afe_register_write(this_controller, afe_pll_control, 0x00200506);
767 scu_afe_register_write(this_controller, afe_pll_dfx_control, 0x10000080);
769 // 5. Configure Bias Unit
770 scu_afe_register_write(this_controller, afe_bias_control[0], 0x00124814);
771 scu_afe_register_write(this_controller, afe_bias_control[1], 0x24900000);
773 // 6. Configure Transceiver Units
774 scu_afe_register_write(
775 this_controller, afe_transceiver_control0[0], 0x0702941e);
777 scu_afe_register_write(
778 this_controller, afe_transceiver_control1[0], 0x0000000a);
780 // 7. Configure RX Units
781 scu_afe_register_write(
782 this_controller, afe_transceiver_equalization_control[0], 0x00ba2223);
784 scu_afe_register_write(
785 this_controller, reserved_0028_003c[2], 0x00000000);
787 // 8. Configure TX Units
788 scu_afe_register_write(
789 this_controller, afe_dfx_transmit_control_register[0], 0x03815428);
791 // 9. Transfer control to PE signals
792 scu_afe_register_write(
793 this_controller, afe_dfx_transceiver_status_clear, 0x00000010);
795 // 10. Release PLL Powerdown
796 scu_afe_register_write(this_controller, afe_pll_control, 0x00200504);
798 // 11. Release PLL Reset
799 scu_afe_register_write(this_controller, afe_pll_control, 0x00200505);
801 // 12. Wait for PLL to Lock
802 // (afe0_comm_sta [1:0] should go to 1'b11, and
803 // [5:2] is 0x5, 0x6, 0x7, 0x8, or 0x9
804 scu_afe_register_write(this_controller, afe_pll_control, 0x00200501);
806 while ((scu_afe_register_read(this_controller, afe_common_status) & 0x03) != 0x03)
808 // Give time for the PLLs to lock
809 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
812 // 13. pe_afe0_rxpdn0 = 0
813 // pe_afe0_rxrst0 = 1
814 // pe_afe0_txrst0_n = 1
815 // pe_afe_txoob0_n = 0
816 scu_afe_register_write(
817 this_controller, afe_transceiver_control0[0], 0x07028c11);
820 #elif defined(PLEASANT_RIDGE_BUILD)
822 void scic_sds_controller_afe_initialization(
823 SCIC_SDS_CONTROLLER_T *this_controller
829 #if defined(SPREADSHEET_AFE_SETTINGS)
830 // Clear DFX Status registers
831 scu_afe_register_write(
832 this_controller, afe_dfx_master_control0, 0x0000000f);
833 // Configure bias currents to normal
834 scu_afe_register_write(
835 this_controller, afe_bias_control, 0x0000aa00);
837 scu_afe_register_write(
838 this_controller, afe_pll_control0, 0x80000908);
840 // Wait for the PLL to lock
843 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
844 afe_status = scu_afe_register_read(
845 this_controller, afe_common_block_status);
847 while((afe_status & 0x00001000) == 0);
849 for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
851 // Initialize transceiver channels
852 scu_afe_register_write(
853 this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000157);
854 // Configure transceiver modes
855 scu_afe_register_write(
856 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016d1a);
857 // Configure receiver parameters
858 scu_afe_register_write(
859 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01501014);
860 // Configure transmitter parameters
861 scu_afe_register_write(
862 this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00000000);
863 // Configure transmitter equalization
864 scu_afe_register_write(
865 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0, 0x000bdd08);
866 scu_afe_register_write(
867 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1, 0x000ffc00);
868 scu_afe_register_write(
869 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2, 0x000b7c09);
870 scu_afe_register_write(
871 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3, 0x000afc6e);
872 // Configure transmitter SSC parameters
873 scu_afe_register_write(
874 this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00000000);
875 // Configure receiver parameters
876 scu_afe_register_write(
877 this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x3208903f);
879 // Start power on sequence
880 // Enable bias currents to transceivers and wait 200ns
881 scu_afe_register_write(
882 this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000154);
883 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
884 // Take receiver out of power down and wait 200ns
885 scu_afe_register_write(
886 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x3801611a);
887 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
888 // Take receiver out of reset and wait 200ns
889 scu_afe_register_write(
890 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x3801631a);
891 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
892 // Take transmitter out of power down and wait 200ns
893 scu_afe_register_write(
894 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016318);
895 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
896 // Take transmitter out of reset and wait 200ns
897 scu_afe_register_write(
898 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016319);
899 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
900 // Take transmitter out of DC idle
901 scu_afe_register_write(
902 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016319);
903 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
906 // Transfer control to the PEs
907 scu_afe_register_write(
908 this_controller, afe_dfx_master_control0, 0x00010f00);
909 #else // !defined(SPREADSHEET_AFE_SETTINGS)
910 // These are the AFEE settings used by the SV group
911 // Clear DFX Status registers
912 scu_afe_register_write(
913 this_controller, afe_dfx_master_control0, 0x0081000f);
914 // Configure bias currents to normal
915 scu_afe_register_write(
916 this_controller, afe_bias_control, 0x0000aa00);
918 scu_afe_register_write(
919 this_controller, afe_pll_control0, 0x80000908);
921 // Wait for the PLL to lock
922 // Note: this is done later in the SV shell script however this looks
923 // like the location to do this since we have enabled the PLL.
926 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
927 afe_status = scu_afe_register_read(
928 this_controller, afe_common_block_status);
930 while((afe_status & 0x00001000) == 0);
932 // Make sure BIST is disabled
933 scu_afe_register_write(
934 this_controller, afe_dfx_master_control1, 0x00000000);
935 // Shorten SAS SNW lock time
936 scu_afe_register_write(
937 this_controller, afe_pmsn_master_control0, 0x7bd316ad);
939 for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
941 // Initialize transceiver channels
942 scu_afe_register_write(
943 this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000174);
944 // Configure SSC control
945 scu_afe_register_write(
946 this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00030000);
947 // Configure transceiver modes
948 scu_afe_register_write(
949 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0000651a);
950 // Power up TX RX and RX OOB
951 scu_afe_register_write(
952 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006518);
953 // Enable RX OOB Detect
954 scu_afe_register_write(
955 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006518);
956 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
958 // Configure transmitter parameters
959 scu_afe_register_write(
960 this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00000000);
961 // Configure transmitter equalization
962 scu_afe_register_write(
963 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0, 0x000bdd08);
964 scu_afe_register_write(
965 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1, 0x000ffc00);
966 scu_afe_register_write(
967 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2, 0x000b7c09);
968 scu_afe_register_write(
969 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3, 0x000afc6e);
970 // Configure transmitter SSC parameters
973 scu_afe_register_write(
974 this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000154);
975 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
978 scu_afe_register_write(
979 this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x00000080);
981 scu_afe_register_write(
982 this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x01041042);
983 // Enable DFE/FFE and freeze
984 scu_afe_register_write(
985 this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x320891bf);
987 // Take receiver out of power down and wait 200ns
988 scu_afe_register_write(
989 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006118);
990 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
991 // TX Electrical Idle
992 scu_afe_register_write(
993 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006108);
994 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
997 scu_afe_register_write(
998 this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x0317108f);
1000 // Configure receiver parameters
1001 scu_afe_register_write(
1002 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01e00021);
1004 // Bring RX out of reset
1005 scu_afe_register_write(
1006 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006109);
1007 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1009 scu_afe_register_write(
1010 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006009);
1011 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1013 scu_afe_register_write(
1014 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006209);
1015 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1018 // Transfer control to the PEs
1019 scu_afe_register_write(
1020 this_controller, afe_dfx_master_control0, 0x00010f00);
1024 #elif defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
1026 void scic_sds_controller_afe_initialization(
1027 SCIC_SDS_CONTROLLER_T *this_controller
1032 U8 cable_selection_mask;
1035 (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_A0)
1036 && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_A2)
1037 && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_B0)
1038 && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_C0)
1039 && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_C1)
1042 // A programming bug has occurred if we are attempting to
1043 // support a PCI revision other than those listed. Default
1044 // to B0, and attempt to limp along if it isn't B0.
1046 this_controller->pci_revision = SCIC_SDS_PCI_REVISION_C1;
1049 cable_selection_mask =
1050 this_controller->oem_parameters.sds1.controller.cable_selection_mask;
1052 // These are the AFEE settings used by the SV group
1053 // Clear DFX Status registers
1054 scu_afe_register_write(
1055 this_controller, afe_dfx_master_control0, 0x0081000f);
1056 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1059 (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1060 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1061 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1064 // PM Rx Equalization Save, PM SPhy Rx Acknowledgement Timer, PM Stagger Timer
1065 scu_afe_register_write(
1066 this_controller, afe_pmsn_master_control2, 0x0007FFFF);
1067 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1070 // Configure bias currents to normal
1071 if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1072 scu_afe_register_write(this_controller, afe_bias_control, 0x00005500);
1073 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1074 scu_afe_register_write(this_controller, afe_bias_control, 0x00005A00);
1075 else if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1076 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) )
1077 scu_afe_register_write(this_controller, afe_bias_control, 0x00005F00);
1078 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1079 scu_afe_register_write(this_controller, afe_bias_control, 0x00005500);
1080 // For C0 the AFE BIAS Controll is unchanged
1082 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1085 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1086 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1088 scu_afe_register_write(this_controller, afe_pll_control0, 0x80040908);
1090 else if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1091 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) )
1093 scu_afe_register_write(this_controller, afe_pll_control0, 0x80040A08);
1095 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1097 scu_afe_register_write(this_controller, afe_pll_control0, 0x80000b08);
1098 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1099 scu_afe_register_write(this_controller, afe_pll_control0, 0x00000b08);
1100 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1101 scu_afe_register_write(this_controller, afe_pll_control0, 0x80000b08);
1104 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1106 // Wait for the PLL to lock
1107 // Note: this is done later in the SV shell script however this looks
1108 // like the location to do this since we have enabled the PLL.
1111 afe_status = scu_afe_register_read(
1112 this_controller, afe_common_block_status);
1113 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1115 while((afe_status & 0x00001000) == 0);
1117 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1118 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1120 // Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us)
1121 scu_afe_register_write(
1122 this_controller, afe_pmsn_master_control0, 0x7bcc96ad);
1123 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1126 for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
1128 U8 cable_length_long = (cable_selection_mask >> phy_id) & 1;
1129 U8 cable_length_medium = (cable_selection_mask >> (phy_id + 4)) & 1;
1131 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1132 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1134 // All defaults, except the Receive Word Alignament/Comma Detect
1135 // Enable....(0xe800)
1136 scu_afe_register_write(
1137 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00004512
1139 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1141 scu_afe_register_write(
1142 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x0050100F
1144 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1146 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1148 // Configure transmitter SSC parameters
1149 scu_afe_register_write(
1150 this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00030000
1152 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1154 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1156 // Configure transmitter SSC parameters
1157 scu_afe_register_write(
1158 this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00010202
1160 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1162 // All defaults, except the Receive Word Alignament/Comma Detect
1163 // Enable....(0xe800)
1164 scu_afe_register_write(
1165 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00014500
1167 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1169 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1171 // Configure transmitter SSC parameters
1172 scu_afe_register_write(
1173 this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00010202
1175 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1177 // All defaults, except the Receive Word Alignament/Comma Detect
1178 // Enable....(0xe800)
1179 scu_afe_register_write(
1180 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0001C500
1182 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1184 // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1185 // & increase TX int & ext bias 20%....(0xe85c)
1186 if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1188 scu_afe_register_write(
1190 scu_afe_xcvr[phy_id].afe_channel_control,
1194 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1196 scu_afe_register_write(
1198 scu_afe_xcvr[phy_id].afe_channel_control,
1202 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1204 // Power down TX and RX (PWRDNTX and PWRDNRX)
1205 scu_afe_register_write(
1207 scu_afe_xcvr[phy_id].afe_channel_control,
1211 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1213 // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1214 // & increase TX int & ext bias 20%....(0xe85c)
1215 scu_afe_register_write(
1217 scu_afe_xcvr[phy_id].afe_channel_control,
1221 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1223 scu_afe_register_write(
1225 scu_afe_xcvr[phy_id].afe_channel_control,
1229 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1231 // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1232 // & increase TX int & ext bias 20%....(0xe85c)
1233 scu_afe_register_write(
1235 scu_afe_xcvr[phy_id].afe_channel_control,
1239 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1241 scu_afe_register_write(
1243 scu_afe_xcvr[phy_id].afe_channel_control,
1244 cable_length_long ? 0x000002F7 :
1245 cable_length_medium ? 0x000001F7 : 0x000001F7
1248 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1250 // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
1251 // & increase TX int & ext bias 20%....(0xe85c)
1252 scu_afe_register_write(
1254 scu_afe_xcvr[phy_id].afe_channel_control,
1255 cable_length_long ? 0x000002F4 :
1256 cable_length_medium ? 0x000001F4 : 0x000001F4
1260 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1262 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1263 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
1265 // Enable TX equalization (0xe824)
1266 scu_afe_register_write(
1268 scu_afe_xcvr[phy_id].afe_tx_control,
1271 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1274 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1275 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1276 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0) )
1278 // RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
1279 // RDD=0x0(RX Detect Enabled) ....(0xe800)
1280 scu_afe_register_write(
1281 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00004100);
1282 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1284 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1286 scu_afe_register_write(
1287 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00014100);
1288 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1290 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1292 scu_afe_register_write(
1293 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0001c100);
1294 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1298 if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
1300 scu_afe_register_write(
1302 scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1306 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
1308 scu_afe_register_write(
1310 scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1314 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
1316 scu_afe_register_write(
1318 scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1321 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1323 // Enable TX equalization (0xe824)
1324 scu_afe_register_write(
1325 this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
1327 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
1329 scu_afe_register_write(
1330 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01400c0f);
1331 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1333 scu_afe_register_write(
1334 this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x3f6f103f);
1335 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1337 // Enable TX equalization (0xe824)
1338 scu_afe_register_write(
1339 this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
1341 else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
1343 scu_afe_register_write(
1344 this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1,
1345 cable_length_long ? 0x01500C0C :
1346 cable_length_medium ? 0x01400C0D : 0x02400C0D
1348 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1350 scu_afe_register_write(
1351 this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x000003e0);
1352 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1354 scu_afe_register_write(
1355 this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
1356 cable_length_long ? 0x33091C1F :
1357 cable_length_medium ? 0x3315181F : 0x2B17161F
1359 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1361 // Enable TX equalization (0xe824)
1362 scu_afe_register_write(
1363 this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
1366 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1368 scu_afe_register_write(
1369 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0,
1370 this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control0
1372 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1374 scu_afe_register_write(
1375 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1,
1376 this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control1
1378 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1380 scu_afe_register_write(
1381 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2,
1382 this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control2
1384 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1386 scu_afe_register_write(
1387 this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3,
1388 this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control3
1390 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1393 // Transfer control to the PEs
1394 scu_afe_register_write(
1395 this_controller, afe_dfx_master_control0, 0x00010f00);
1396 scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
1399 #error "Unsupported board type"
1402 //****************************************************************************-
1403 //* SCIC SDS Controller Internal Start/Stop Routines
1404 //****************************************************************************-
1408 * @brief This method will attempt to transition into the ready state
1409 * for the controller and indicate that the controller start
1410 * operation has completed if all criteria are met.
1412 * @param[in,out] this_controller This parameter indicates the controller
1413 * object for which to transition to ready.
1414 * @param[in] status This parameter indicates the status value to be
1415 * pass into the call to scic_cb_controller_start_complete().
1420 void scic_sds_controller_transition_to_ready(
1421 SCIC_SDS_CONTROLLER_T *this_controller,
1426 sci_base_object_get_logger(this_controller),
1427 SCIC_LOG_OBJECT_CONTROLLER,
1428 "scic_sds_controller_transition_to_ready(0x%x, 0x%x) enter\n",
1429 this_controller, status
1432 if (this_controller->parent.state_machine.current_state_id
1433 == SCI_BASE_CONTROLLER_STATE_STARTING)
1435 // We move into the ready state, because some of the phys/ports
1436 // may be up and operational.
1437 sci_base_state_machine_change_state(
1438 scic_sds_controller_get_base_state_machine(this_controller),
1439 SCI_BASE_CONTROLLER_STATE_READY
1442 scic_cb_controller_start_complete(this_controller, status);
1447 * @brief This method is the general timeout handler for the controller.
1448 * It will take the correct timetout action based on the current
1451 * @param[in] controller This parameter indicates the controller on which
1452 * a timeout occurred.
1456 void scic_sds_controller_timeout_handler(
1457 SCI_CONTROLLER_HANDLE_T controller
1460 SCI_BASE_CONTROLLER_STATES current_state;
1461 SCIC_SDS_CONTROLLER_T *this_controller;
1462 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
1464 current_state = sci_base_state_machine_get_state(
1465 scic_sds_controller_get_base_state_machine(this_controller)
1468 if (current_state == SCI_BASE_CONTROLLER_STATE_STARTING)
1470 scic_sds_controller_transition_to_ready(
1471 this_controller, SCI_FAILURE_TIMEOUT
1474 else if (current_state == SCI_BASE_CONTROLLER_STATE_STOPPING)
1476 sci_base_state_machine_change_state(
1477 scic_sds_controller_get_base_state_machine(this_controller),
1478 SCI_BASE_CONTROLLER_STATE_FAILED
1481 scic_cb_controller_stop_complete(controller, SCI_FAILURE_TIMEOUT);
1485 /// @todo Now what do we want to do in this case?
1487 sci_base_object_get_logger(this_controller),
1488 SCIC_LOG_OBJECT_CONTROLLER,
1489 "Controller timer fired when controller was not in a state being timed.\n"
1497 * @param[in] this_controller
1499 * @return SCI_STATUS
1501 SCI_STATUS scic_sds_controller_stop_ports(
1502 SCIC_SDS_CONTROLLER_T *this_controller
1507 SCI_STATUS port_status;
1509 status = SCI_SUCCESS;
1511 for (index = 0; index < this_controller->logical_port_entries; index++)
1513 port_status = this_controller->port_table[index].
1514 state_handlers->parent.stop_handler(&this_controller->port_table[index].parent);
1516 (port_status != SCI_SUCCESS)
1517 && (port_status != SCI_FAILURE_INVALID_STATE)
1520 status = SCI_FAILURE;
1523 sci_base_object_get_logger(this_controller),
1524 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
1525 "Controller stop operation failed to stop port %d because of status %d.\n",
1526 this_controller->port_table[index].logical_port_index, port_status
1537 * @param[in] this_controller
1540 void scic_sds_controller_phy_timer_start(
1541 SCIC_SDS_CONTROLLER_T *this_controller
1544 scic_cb_timer_start(
1546 this_controller->phy_startup_timer,
1547 SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
1550 this_controller->phy_startup_timer_pending = TRUE;
1556 * @param[in] this_controller
1558 void scic_sds_controller_phy_timer_stop(
1559 SCIC_SDS_CONTROLLER_T *this_controller
1564 this_controller->phy_startup_timer
1567 this_controller->phy_startup_timer_pending = FALSE;
1571 * @brief This method is called internally to determine whether the
1572 * controller start process is complete. This is only true when:
1573 * - all links have been given an opportunity to start
1574 * - have no indication of a connected device
1575 * - have an indication of a connected device and it has
1576 * finished the link training process.
1578 * @param[in] this_controller This parameter specifies the controller
1579 * object for which to start the next phy.
1583 BOOL scic_sds_controller_is_start_complete(
1584 SCIC_SDS_CONTROLLER_T *this_controller
1589 for (index = 0; index < SCI_MAX_PHYS; index++)
1591 SCIC_SDS_PHY_T *the_phy = & this_controller->phy_table[index];
1595 this_controller->oem_parameters.sds1.controller.mode_type
1596 == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
1600 this_controller->oem_parameters.sds1.controller.mode_type
1601 == SCIC_PORT_MANUAL_CONFIGURATION_MODE
1603 && (scic_sds_phy_get_port(the_phy) != SCI_INVALID_HANDLE)
1608 * The controller start operation is complete if and only
1610 * - all links have been given an opportunity to start
1611 * - have no indication of a connected device
1612 * - have an indication of a connected device and it has
1613 * finished the link training process.
1617 (the_phy->is_in_link_training == FALSE)
1618 && (the_phy->parent.state_machine.current_state_id
1619 == SCI_BASE_PHY_STATE_INITIAL)
1622 (the_phy->is_in_link_training == FALSE)
1623 && (the_phy->parent.state_machine.current_state_id
1624 == SCI_BASE_PHY_STATE_STOPPED)
1627 (the_phy->is_in_link_training == TRUE)
1628 && (the_phy->parent.state_machine.current_state_id
1629 == SCI_BASE_PHY_STATE_STARTING)
1632 this_controller->port_agent.phy_ready_mask
1633 != this_controller->port_agent.phy_configured_mask
1646 * @brief This method is called internally by the controller object to
1647 * start the next phy on the controller. If all the phys have
1648 * been starte, then this method will attempt to transition the
1649 * controller to the READY state and inform the user
1650 * (scic_cb_controller_start_complete()).
1652 * @param[in] this_controller This parameter specifies the controller
1653 * object for which to start the next phy.
1655 * @return SCI_STATUS
1657 SCI_STATUS scic_sds_controller_start_next_phy(
1658 SCIC_SDS_CONTROLLER_T *this_controller
1663 status = SCI_SUCCESS;
1665 if (this_controller->phy_startup_timer_pending == FALSE)
1667 if (this_controller->next_phy_to_start == SCI_MAX_PHYS)
1669 // The controller has successfully finished the start process.
1670 // Inform the SCI Core user and transition to the READY state.
1671 if (scic_sds_controller_is_start_complete(this_controller) == TRUE)
1673 scic_sds_controller_transition_to_ready(
1674 this_controller, SCI_SUCCESS
1680 SCIC_SDS_PHY_T * the_phy;
1682 the_phy = &this_controller->phy_table[this_controller->next_phy_to_start];
1685 this_controller->oem_parameters.sds1.controller.mode_type
1686 == SCIC_PORT_MANUAL_CONFIGURATION_MODE
1689 if (scic_sds_phy_get_port(the_phy) == SCI_INVALID_HANDLE)
1691 this_controller->next_phy_to_start++;
1693 // Caution recursion ahead be forwarned
1695 // The PHY was never added to a PORT in MPC mode so start the next phy in sequence
1696 // This phy will never go link up and will not draw power the OEM parameters either
1697 // configured the phy incorrectly for the PORT or it was never assigned to a PORT
1698 return scic_sds_controller_start_next_phy(this_controller);
1702 status = scic_phy_start(the_phy);
1704 if (status == SCI_SUCCESS)
1706 scic_sds_controller_phy_timer_start(this_controller);
1711 sci_base_object_get_logger(this_controller),
1712 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PHY,
1713 "Controller stop operation failed to stop phy %d because of status %d.\n",
1714 this_controller->phy_table[this_controller->next_phy_to_start].phy_index,
1719 this_controller->next_phy_to_start++;
1729 * @param[in] this_controller
1731 * @return SCI_STATUS
1733 SCI_STATUS scic_sds_controller_stop_phys(
1734 SCIC_SDS_CONTROLLER_T *this_controller
1739 SCI_STATUS phy_status;
1741 status = SCI_SUCCESS;
1743 for (index = 0; index < SCI_MAX_PHYS; index++)
1745 phy_status = scic_phy_stop(&this_controller->phy_table[index]);
1748 (phy_status != SCI_SUCCESS)
1749 && (phy_status != SCI_FAILURE_INVALID_STATE)
1752 status = SCI_FAILURE;
1755 sci_base_object_get_logger(this_controller),
1756 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PHY,
1757 "Controller stop operation failed to stop phy %d because of status %d.\n",
1758 this_controller->phy_table[index].phy_index, phy_status
1769 * @param[in] this_controller
1771 * @return SCI_STATUS
1773 SCI_STATUS scic_sds_controller_stop_devices(
1774 SCIC_SDS_CONTROLLER_T *this_controller
1779 SCI_STATUS device_status;
1781 status = SCI_SUCCESS;
1783 for (index = 0; index < this_controller->remote_node_entries; index++)
1785 if (this_controller->device_table[index] != SCI_INVALID_HANDLE)
1787 /// @todo What timeout value do we want to provide to this request?
1788 device_status = scic_remote_device_stop(this_controller->device_table[index], 0);
1791 (device_status != SCI_SUCCESS)
1792 && (device_status != SCI_FAILURE_INVALID_STATE)
1796 sci_base_object_get_logger(this_controller),
1797 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_SSP_REMOTE_TARGET,
1798 "Controller stop operation failed to stop device 0x%x because of status %d.\n",
1799 this_controller->device_table[index], device_status
1808 //****************************************************************************-
1809 //* SCIC SDS Controller Power Control (Staggered Spinup)
1810 //****************************************************************************-
1813 * This method starts the power control timer for this controller object.
1815 * @param this_controller
1818 void scic_sds_controller_power_control_timer_start(
1819 SCIC_SDS_CONTROLLER_T *this_controller
1822 scic_cb_timer_start(
1823 this_controller, this_controller->power_control.timer,
1824 SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL
1827 this_controller->power_control.timer_started = TRUE;
1831 * This method stops the power control timer for this controller object.
1833 * @param this_controller
1836 void scic_sds_controller_power_control_timer_stop(
1837 SCIC_SDS_CONTROLLER_T *this_controller
1840 if (this_controller->power_control.timer_started)
1843 this_controller, this_controller->power_control.timer
1846 this_controller->power_control.timer_started = FALSE;
1851 * This method stops and starts the power control timer for this controller object.
1853 * @param this_controller
1856 void scic_sds_controller_power_control_timer_restart(
1857 SCIC_SDS_CONTROLLER_T *this_controller
1860 scic_sds_controller_power_control_timer_stop(this_controller);
1861 scic_sds_controller_power_control_timer_start(this_controller);
1868 * @param[in] controller
1870 void scic_sds_controller_power_control_timer_handler(
1874 SCIC_SDS_CONTROLLER_T *this_controller;
1875 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
1877 this_controller->power_control.remote_devices_granted_power = 0;
1879 if (this_controller->power_control.phys_waiting == 0)
1881 this_controller->power_control.timer_started = FALSE;
1885 SCIC_SDS_PHY_T *the_phy = NULL;
1890 && (this_controller->power_control.phys_waiting != 0);
1893 if (this_controller->power_control.requesters[i] != NULL)
1895 if ( this_controller->power_control.remote_devices_granted_power <
1896 this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up
1899 the_phy = this_controller->power_control.requesters[i];
1900 this_controller->power_control.requesters[i] = NULL;
1901 this_controller->power_control.phys_waiting--;
1902 this_controller->power_control.remote_devices_granted_power ++;
1903 scic_sds_phy_consume_power_handler(the_phy);
1905 if (the_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
1908 SCIC_SDS_PHY_T * current_requester_phy;
1910 for (j = 0; j < SCI_MAX_PHYS; j++)
1912 current_requester_phy = this_controller->power_control.requesters[j];
1914 //Search the power_control queue to see if there are other phys attached to
1915 //the same remote device. If found, take all of them out of await_sas_power state.
1916 if (current_requester_phy != NULL &&
1917 current_requester_phy != the_phy &&
1918 current_requester_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high
1919 == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high &&
1920 current_requester_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low
1921 == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low)
1923 this_controller->power_control.requesters[j] = NULL;
1924 this_controller->power_control.phys_waiting--;
1925 scic_sds_phy_consume_power_handler(current_requester_phy);
1937 // It doesn't matter if the power list is empty, we need to start the
1938 // timer in case another phy becomes ready.
1939 scic_sds_controller_power_control_timer_start(this_controller);
1944 * @brief This method inserts the phy in the stagger spinup control queue.
1946 * @param[in] this_controller
1947 * @param[in] the_phy
1949 void scic_sds_controller_power_control_queue_insert(
1950 SCIC_SDS_CONTROLLER_T *this_controller,
1951 SCIC_SDS_PHY_T *the_phy
1954 ASSERT (the_phy != NULL);
1956 if( this_controller->power_control.remote_devices_granted_power <
1957 this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up
1960 this_controller->power_control.remote_devices_granted_power ++;
1961 scic_sds_phy_consume_power_handler(the_phy);
1963 //stop and start the power_control timer. When the timer fires, the
1964 //no_of_devices_granted_power will be set to 0
1965 scic_sds_controller_power_control_timer_restart (this_controller);
1969 //there are phys, attached to the same sas address as this phy, are already
1970 //in READY state, this phy don't need wait.
1972 SCIC_SDS_PHY_T * current_phy;
1973 for(i = 0; i < SCI_MAX_PHYS; i++)
1975 current_phy = &this_controller->phy_table[i];
1977 if (current_phy->parent.state_machine.current_state_id == SCI_BASE_PHY_STATE_READY &&
1978 current_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS &&
1979 current_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high
1980 == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high &&
1981 current_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low
1982 == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low)
1984 scic_sds_phy_consume_power_handler(the_phy);
1989 if (i == SCI_MAX_PHYS)
1991 //Add the phy in the waiting list
1992 this_controller->power_control.requesters[the_phy->phy_index] = the_phy;
1993 this_controller->power_control.phys_waiting++;
1999 * @brief This method removes the phy from the stagger spinup control
2002 * @param[in] this_controller
2003 * @param[in] the_phy
2005 void scic_sds_controller_power_control_queue_remove(
2006 SCIC_SDS_CONTROLLER_T *this_controller,
2007 SCIC_SDS_PHY_T *the_phy
2010 ASSERT (the_phy != NULL);
2012 if (this_controller->power_control.requesters[the_phy->phy_index] != NULL)
2014 this_controller->power_control.phys_waiting--;
2017 this_controller->power_control.requesters[the_phy->phy_index] = NULL;
2020 //****************************************************************************-
2021 //* SCIC SDS Controller Completion Routines
2022 //****************************************************************************-
2025 * @brief This method returns a TRUE value if the completion queue has
2026 * entries that can be processed
2028 * @param[in] this_controller
2031 * @retval TRUE if the completion queue has entries to process
2032 * FALSE if the completion queue has no entries to process
2035 BOOL scic_sds_controller_completion_queue_has_entries(
2036 SCIC_SDS_CONTROLLER_T *this_controller
2039 U32 get_value = this_controller->completion_queue_get;
2040 U32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK;
2042 NORMALIZE_GET_POINTER_CYCLE_BIT(get_value)
2043 == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
2052 // ---------------------------------------------------------------------------
2055 * @brief This method processes a task completion notification. This is
2056 * called from within the controller completion handler.
2058 * @param[in] this_controller
2059 * @param[in] completion_entry
2064 void scic_sds_controller_task_completion(
2065 SCIC_SDS_CONTROLLER_T *this_controller,
2066 U32 completion_entry
2070 SCIC_SDS_REQUEST_T *io_request;
2072 index = SCU_GET_COMPLETION_INDEX(completion_entry);
2073 io_request = this_controller->io_request_table[index];
2075 // Make sure that we really want to process this IO request
2077 (io_request != SCI_INVALID_HANDLE)
2078 && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)
2080 scic_sds_io_tag_get_sequence(io_request->io_tag)
2081 == this_controller->io_request_sequence[index]
2085 // Yep this is a valid io request pass it along to the io request handler
2086 scic_sds_io_request_tc_completion(io_request, completion_entry);
2091 * @brief This method processes an SDMA completion event. This is called
2092 * from within the controller completion handler.
2094 * @param[in] this_controller
2095 * @param[in] completion_entry
2100 void scic_sds_controller_sdma_completion(
2101 SCIC_SDS_CONTROLLER_T *this_controller,
2102 U32 completion_entry
2106 SCIC_SDS_REQUEST_T *io_request;
2107 SCIC_SDS_REMOTE_DEVICE_T *device;
2109 index = SCU_GET_COMPLETION_INDEX(completion_entry);
2111 switch (scu_get_command_request_type(completion_entry))
2113 case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC:
2114 case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC:
2115 io_request = this_controller->io_request_table[index];
2117 sci_base_object_get_logger(this_controller),
2118 SCIC_LOG_OBJECT_CONTROLLER
2119 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
2120 | SCIC_LOG_OBJECT_SSP_IO_REQUEST
2121 | SCIC_LOG_OBJECT_STP_IO_REQUEST,
2122 "SCIC SDS Completion type SDMA %x for io request %x\n",
2126 /// @todo For a post TC operation we need to fail the IO request
2129 case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC:
2130 case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC:
2131 case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC:
2132 device = this_controller->device_table[index];
2134 sci_base_object_get_logger(this_controller),
2135 SCIC_LOG_OBJECT_CONTROLLER
2136 | SCIC_LOG_OBJECT_SSP_REMOTE_TARGET
2137 | SCIC_LOG_OBJECT_SMP_REMOTE_TARGET
2138 | SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
2139 "SCIC SDS Completion type SDMA %x for remote device %x\n",
2143 /// @todo For a port RNC operation we need to fail the device
2148 sci_base_object_get_logger(this_controller),
2149 SCIC_LOG_OBJECT_CONTROLLER,
2150 "SCIC SDS Completion unknown SDMA completion type %x\n",
2156 /// This is an unexpected completion type and is un-recoverable
2157 /// Transition to the failed state and wait for a controller reset
2158 sci_base_state_machine_change_state(
2159 scic_sds_controller_get_base_state_machine(this_controller),
2160 SCI_BASE_CONTROLLER_STATE_FAILED
2165 * This method processes an unsolicited frame message. This is called from
2166 * within the controller completion handler.
2168 * @param[in] this_controller
2169 * @param[in] completion_entry
2174 void scic_sds_controller_unsolicited_frame(
2175 SCIC_SDS_CONTROLLER_T *this_controller,
2176 U32 completion_entry
2182 SCU_UNSOLICITED_FRAME_HEADER_T * frame_header;
2183 SCIC_SDS_PHY_T * phy;
2184 SCIC_SDS_REMOTE_DEVICE_T * device;
2186 SCI_STATUS result = SCI_FAILURE;
2188 frame_index = SCU_GET_FRAME_INDEX(completion_entry);
2191 = this_controller->uf_control.buffers.array[frame_index].header;
2192 this_controller->uf_control.buffers.array[frame_index].state
2193 = UNSOLICITED_FRAME_IN_USE;
2195 if (SCU_GET_FRAME_ERROR(completion_entry))
2197 /// @todo If the IAF frame or SIGNATURE FIS frame has an error will
2198 /// this cause a problem? We expect the phy initialization will
2199 /// fail if there is an error in the frame.
2200 scic_sds_controller_release_frame(this_controller, frame_index);
2204 if (frame_header->is_address_frame)
2206 index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
2207 phy = &this_controller->phy_table[index];
2210 result = scic_sds_phy_frame_handler(phy, frame_index);
2216 index = SCU_GET_COMPLETION_INDEX(completion_entry);
2218 if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
2220 // This is a signature fis or a frame from a direct attached SATA
2221 // device that has not yet been created. In either case forwared
2222 // the frame to the PE and let it take care of the frame data.
2223 index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
2224 phy = &this_controller->phy_table[index];
2225 result = scic_sds_phy_frame_handler(phy, frame_index);
2229 if (index < this_controller->remote_node_entries)
2230 device = this_controller->device_table[index];
2235 result = scic_sds_remote_device_frame_handler(device, frame_index);
2237 scic_sds_controller_release_frame(this_controller, frame_index);
2241 if (result != SCI_SUCCESS)
2243 /// @todo Is there any reason to report some additional error message
2244 /// when we get this failure notifiction?
2249 * @brief This method processes an event completion entry. This is called
2250 * from within the controller completion handler.
2252 * @param[in] this_controller
2253 * @param[in] completion_entry
2258 void scic_sds_controller_event_completion(
2259 SCIC_SDS_CONTROLLER_T *this_controller,
2260 U32 completion_entry
2264 SCIC_SDS_REQUEST_T *io_request;
2265 SCIC_SDS_REMOTE_DEVICE_T *device;
2266 SCIC_SDS_PHY_T *phy;
2268 index = SCU_GET_COMPLETION_INDEX(completion_entry);
2270 switch (scu_get_event_type(completion_entry))
2272 case SCU_EVENT_TYPE_SMU_COMMAND_ERROR:
2273 /// @todo The driver did something wrong and we need to fix the condtion.
2275 sci_base_object_get_logger(this_controller),
2276 SCIC_LOG_OBJECT_CONTROLLER,
2277 "SCIC Controller 0x%x received SMU command error 0x%x\n",
2278 this_controller, completion_entry
2282 case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR:
2283 // report fatal memory error
2284 this_controller->parent.error = SCI_CONTROLLER_FATAL_MEMORY_ERROR;
2286 sci_base_state_machine_change_state(
2287 scic_sds_controller_get_base_state_machine(this_controller),
2288 SCI_BASE_CONTROLLER_STATE_FAILED
2291 //continue as in following events
2292 case SCU_EVENT_TYPE_SMU_PCQ_ERROR:
2293 case SCU_EVENT_TYPE_SMU_ERROR:
2295 sci_base_object_get_logger(this_controller),
2296 SCIC_LOG_OBJECT_CONTROLLER,
2297 "SCIC Controller 0x%x received fatal controller event 0x%x\n",
2298 this_controller, completion_entry
2302 case SCU_EVENT_TYPE_TRANSPORT_ERROR:
2303 io_request = this_controller->io_request_table[index];
2304 scic_sds_io_request_event_handler(io_request, completion_entry);
2307 case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
2308 switch (scu_get_event_specifier(completion_entry))
2310 case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE:
2311 case SCU_EVENT_SPECIFIC_TASK_TIMEOUT:
2312 io_request = this_controller->io_request_table[index];
2313 if (io_request != SCI_INVALID_HANDLE)
2315 scic_sds_io_request_event_handler(io_request, completion_entry);
2320 sci_base_object_get_logger(this_controller),
2321 SCIC_LOG_OBJECT_CONTROLLER |
2322 SCIC_LOG_OBJECT_SMP_IO_REQUEST |
2323 SCIC_LOG_OBJECT_SSP_IO_REQUEST |
2324 SCIC_LOG_OBJECT_STP_IO_REQUEST,
2325 "SCIC Controller 0x%x received event 0x%x for io request object that doesnt exist.\n",
2326 this_controller, completion_entry
2331 case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT:
2332 device = this_controller->device_table[index];
2333 if (device != SCI_INVALID_HANDLE)
2335 scic_sds_remote_device_event_handler(device, completion_entry);
2340 sci_base_object_get_logger(this_controller),
2341 SCIC_LOG_OBJECT_CONTROLLER |
2342 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
2343 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
2344 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
2345 "SCIC Controller 0x%x received event 0x%x for remote device object that doesnt exist.\n",
2346 this_controller, completion_entry
2353 case SCU_EVENT_TYPE_BROADCAST_CHANGE:
2354 // direct the broadcast change event to the phy first and then let
2355 // the phy redirect the broadcast change to the port object
2356 case SCU_EVENT_TYPE_ERR_CNT_EVENT:
2357 // direct error counter event to the phy object since that is where
2358 // we get the event notification. This is a type 4 event.
2359 case SCU_EVENT_TYPE_OSSP_EVENT:
2360 index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
2361 phy = &this_controller->phy_table[index];
2362 scic_sds_phy_event_handler(phy, completion_entry);
2365 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
2366 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
2367 case SCU_EVENT_TYPE_RNC_OPS_MISC:
2368 if (index < this_controller->remote_node_entries)
2370 device = this_controller->device_table[index];
2374 scic_sds_remote_device_event_handler(device, completion_entry);
2380 sci_base_object_get_logger(this_controller),
2381 SCIC_LOG_OBJECT_CONTROLLER |
2382 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
2383 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
2384 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
2385 "SCIC Controller 0x%x received event 0x%x for remote device object 0x%0x that doesnt exist.\n",
2386 this_controller, completion_entry, index
2393 sci_base_object_get_logger(this_controller),
2394 SCIC_LOG_OBJECT_CONTROLLER,
2395 "SCIC Controller received unknown event code %x\n",
2403 * @brief This method is a private routine for processing the completion
2406 * @param[in] this_controller
2411 void scic_sds_controller_process_completions(
2412 SCIC_SDS_CONTROLLER_T *this_controller
2415 U32 completion_count = 0;
2416 U32 completion_entry;
2423 sci_base_object_get_logger(this_controller),
2424 SCIC_LOG_OBJECT_CONTROLLER,
2425 "scic_sds_controller_process_completions(0x%x) enter\n",
2430 sci_base_object_get_logger(this_controller),
2431 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2432 "completion queue begining get : 0x%08x\n",
2433 this_controller->completion_queue_get
2436 // Get the component parts of the completion queue
2437 get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
2438 get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
2440 event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
2441 event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
2444 NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
2445 == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
2450 completion_entry = this_controller->completion_queue[get_index];
2451 INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
2454 sci_base_object_get_logger(this_controller),
2455 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2456 "completion queue entry : 0x%08x\n",
2460 switch (SCU_GET_COMPLETION_TYPE(completion_entry))
2462 case SCU_COMPLETION_TYPE_TASK:
2463 scic_sds_controller_task_completion(this_controller, completion_entry);
2466 case SCU_COMPLETION_TYPE_SDMA:
2467 scic_sds_controller_sdma_completion(this_controller, completion_entry);
2470 case SCU_COMPLETION_TYPE_UFI:
2471 scic_sds_controller_unsolicited_frame(this_controller, completion_entry);
2474 case SCU_COMPLETION_TYPE_EVENT:
2475 scic_sds_controller_event_completion(this_controller, completion_entry);
2478 case SCU_COMPLETION_TYPE_NOTIFY:
2479 // Presently we do the same thing with a notify event that we do with the
2480 // other event codes.
2481 INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
2482 scic_sds_controller_event_completion(this_controller, completion_entry);
2487 sci_base_object_get_logger(this_controller),
2488 SCIC_LOG_OBJECT_CONTROLLER,
2489 "SCIC Controller received unknown completion type %x\n",
2496 // Update the get register if we completed one or more entries
2497 if (completion_count > 0)
2499 this_controller->completion_queue_get =
2500 SMU_CQGR_GEN_BIT(ENABLE)
2501 | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
2502 | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
2503 | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index) ;
2505 SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
2509 sci_base_object_get_logger(this_controller),
2510 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2511 "completion queue ending get : 0x%08x\n",
2512 this_controller->completion_queue_get
2518 * @brief This method is a private routine for processing the completion
2521 * @param[in] this_controller
2526 void scic_sds_controller_transitioned_process_completions(
2527 SCIC_SDS_CONTROLLER_T * this_controller
2530 U32 completion_count = 0;
2531 U32 completion_entry;
2538 sci_base_object_get_logger(this_controller),
2539 SCIC_LOG_OBJECT_CONTROLLER,
2540 "scic_sds_controller_transitioned_process_completions(0x%x) enter\n",
2545 sci_base_object_get_logger(this_controller),
2546 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2547 "completion queue begining get : 0x%08x\n",
2548 this_controller->completion_queue_get
2551 // Get the component parts of the completion queue
2552 get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
2553 get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
2555 event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
2556 event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
2559 NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
2560 == COMPLETION_QUEUE_CYCLE_BIT(
2561 this_controller->completion_queue[get_index])
2566 completion_entry = this_controller->completion_queue[get_index];
2567 INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
2570 sci_base_object_get_logger(this_controller),
2571 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2572 "completion queue entry : 0x%08x\n",
2576 switch (SCU_GET_COMPLETION_TYPE(completion_entry))
2578 case SCU_COMPLETION_TYPE_TASK:
2579 scic_sds_controller_task_completion(this_controller, completion_entry);
2582 case SCU_COMPLETION_TYPE_NOTIFY:
2583 INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
2586 case SCU_COMPLETION_TYPE_EVENT:
2587 case SCU_COMPLETION_TYPE_SDMA:
2588 case SCU_COMPLETION_TYPE_UFI:
2591 sci_base_object_get_logger(this_controller),
2592 SCIC_LOG_OBJECT_CONTROLLER,
2593 "SCIC Controller ignoring completion type %x\n",
2600 // Update the get register if we completed one or more entries
2601 if (completion_count > 0)
2603 this_controller->completion_queue_get =
2604 SMU_CQGR_GEN_BIT(ENABLE)
2605 | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
2606 | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
2607 | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index) ;
2609 SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
2613 sci_base_object_get_logger(this_controller),
2614 SCIC_LOG_OBJECT_COMPLETION_QUEUE,
2615 "completion queue ending get : 0x%08x\n",
2616 this_controller->completion_queue_get
2620 //****************************************************************************-
2621 //* SCIC SDS Controller Interrupt and Completion functions
2622 //****************************************************************************-
2625 * @brief This method provides standard (common) processing of interrupts
2626 * for polling and legacy based interrupts.
2628 * @param[in] controller
2629 * @param[in] interrupt_status
2631 * @return This method returns a boolean (BOOL) indication as to
2632 * whether an completions are pending to be processed.
2633 * @retval TRUE if an interrupt is to be processed
2634 * @retval FALSE if no interrupt was pending
2637 BOOL scic_sds_controller_standard_interrupt_handler(
2638 SCIC_SDS_CONTROLLER_T *this_controller,
2639 U32 interrupt_status
2642 BOOL is_completion_needed = FALSE;
2645 sci_base_object_get_logger(this_controller),
2646 SCIC_LOG_OBJECT_CONTROLLER,
2647 "scic_sds_controller_standard_interrupt_handler(0x%d,0x%d) enter\n",
2648 this_controller, interrupt_status
2652 (interrupt_status & SMU_ISR_QUEUE_ERROR)
2654 (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
2655 && (!scic_sds_controller_completion_queue_has_entries(this_controller))
2659 // We have a fatal error on the read of the completion queue bar
2661 // We have a fatal error there is nothing in the completion queue
2662 // but we have a report from the hardware that the queue is full
2663 /// @todo how do we request the a controller reset
2664 is_completion_needed = TRUE;
2665 this_controller->encountered_fatal_error = TRUE;
2668 if (scic_sds_controller_completion_queue_has_entries(this_controller))
2670 is_completion_needed = TRUE;
2673 return is_completion_needed;
2677 * @brief This is the method provided to handle polling for interrupts
2678 * for the controller object.
2680 * @param[in] controller
2683 * @retval TRUE if an interrupt is to be processed
2684 * @retval FALSE if no interrupt was pending
2687 BOOL scic_sds_controller_polling_interrupt_handler(
2688 SCI_CONTROLLER_HANDLE_T controller
2691 U32 interrupt_status;
2692 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
2695 sci_base_object_get_logger(controller),
2696 SCIC_LOG_OBJECT_CONTROLLER,
2697 "scic_sds_controller_polling_interrupt_handler(0x%d) enter\n",
2702 * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the hardware
2703 * indicates nothing is pending. Since we are not being called from a real
2704 * interrupt, we don't want to confuse the hardware by servicing the
2705 * completion queue before the hardware indicates it is ready. We'll
2706 * simply wait for another polling interval and check again.
2708 interrupt_status = SMU_ISR_READ(this_controller);
2709 if ((interrupt_status &
2710 (SMU_ISR_COMPLETION |
2711 SMU_ISR_QUEUE_ERROR |
2712 SMU_ISR_QUEUE_SUSPEND)) == 0)
2717 return scic_sds_controller_standard_interrupt_handler(
2718 controller, interrupt_status
2723 * @brief This is the method provided to handle completions when interrupt
2724 * polling is in use.
2726 * @param[in] controller
2731 void scic_sds_controller_polling_completion_handler(
2732 SCI_CONTROLLER_HANDLE_T controller
2735 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2738 sci_base_object_get_logger(controller),
2739 SCIC_LOG_OBJECT_CONTROLLER,
2740 "scic_sds_controller_polling_completion_handler(0x%d) enter\n",
2744 if (this_controller->encountered_fatal_error == TRUE)
2747 sci_base_object_get_logger(this_controller),
2748 SCIC_LOG_OBJECT_CONTROLLER,
2749 "SCIC Controller has encountered a fatal error.\n"
2752 sci_base_state_machine_change_state(
2753 scic_sds_controller_get_base_state_machine(this_controller),
2754 SCI_BASE_CONTROLLER_STATE_FAILED
2757 else if (scic_sds_controller_completion_queue_has_entries(this_controller))
2759 if (this_controller->restrict_completions == FALSE)
2760 scic_sds_controller_process_completions(this_controller);
2762 scic_sds_controller_transitioned_process_completions(this_controller);
2766 * The interrupt handler does not adjust the CQ's
2767 * get pointer. So, SCU's INTx pin stays asserted during the
2768 * interrupt handler even though it tries to clear the interrupt
2769 * source. Therefore, the completion handler must ensure that the
2770 * interrupt source is cleared. Otherwise, we get a spurious
2771 * interrupt for which the interrupt handler will not issue a
2772 * corresponding completion event. Also, we unmask interrupts.
2776 (U32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)
2780 #if !defined(DISABLE_INTERRUPTS)
2782 * @brief This is the method provided to handle legacy interrupts for the
2783 * controller object.
2785 * @param[in] controller
2788 * @retval TRUE if an interrupt is processed
2789 * FALSE if no interrupt was processed
2792 BOOL scic_sds_controller_legacy_interrupt_handler(
2793 SCI_CONTROLLER_HANDLE_T controller
2796 U32 interrupt_status;
2797 BOOL is_completion_needed;
2798 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
2800 interrupt_status = SMU_ISR_READ(this_controller);
2801 is_completion_needed = scic_sds_controller_standard_interrupt_handler(
2802 this_controller, interrupt_status
2805 return is_completion_needed;
2810 * @brief This is the method provided to handle legacy completions it is
2811 * expected that the SCI User will call this completion handler
2812 * anytime the interrupt handler reports that it has handled an
2815 * @param[in] controller
2820 void scic_sds_controller_legacy_completion_handler(
2821 SCI_CONTROLLER_HANDLE_T controller
2824 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2827 sci_base_object_get_logger(controller),
2828 SCIC_LOG_OBJECT_CONTROLLER,
2829 "scic_sds_controller_legacy_completion_handler(0x%d) enter\n",
2833 scic_sds_controller_polling_completion_handler(controller);
2835 SMU_IMR_WRITE(this_controller, 0x00000000);
2837 #ifdef IMR_READ_FENCE
2839 volatile U32 int_mask_value = 0;
2843 * Temporary code since we have seen with legacy interrupts
2844 * that interrupts are still masked after clearing the mask
2845 * above. This may be an Arlington problem or it may be an
2846 * old driver problem. Presently this code is turned off
2847 * since we have not seen this problem recently.
2851 int_mask_value = SMU_IMR_READ(this_controler);
2855 #ifdef ALLOW_ENTER_DEBUGGER
2860 } while (int_mask_value != 0);
2866 * @brief This is the method provided to handle an MSIX interrupt message
2867 * when there is just a single MSIX message being provided by the
2868 * hardware. This mode of operation is single vector mode.
2870 * @param[in] controller
2873 * @retval TRUE if an interrupt is processed
2874 * FALSE if no interrupt was processed
2877 BOOL scic_sds_controller_single_vector_interrupt_handler(
2878 SCI_CONTROLLER_HANDLE_T controller
2881 U32 interrupt_status;
2882 SCIC_SDS_CONTROLLER_T *this_controller;
2883 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2885 // Mask the interrupts
2886 // There is a race in the hardware that could cause us not to be notified
2887 // of an interrupt completion if we do not take this step. We will unmask
2888 // the interrupts in the completion routine.
2889 SMU_IMR_WRITE(this_controller, 0xFFFFFFFF);
2891 interrupt_status = SMU_ISR_READ(this_controller);
2892 interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
2895 (interrupt_status == 0)
2896 && scic_sds_controller_completion_queue_has_entries(this_controller)
2899 // There is at least one completion queue entry to process so we can
2900 // return a success and ignore for now the case of an error interrupt
2901 SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
2907 if (interrupt_status != 0)
2909 // There is an error interrupt pending so let it through and handle
2914 // Clear any offending interrupts since we could not find any to handle
2915 // and unmask them all
2916 SMU_ISR_WRITE(this_controller, 0x00000000);
2917 SMU_IMR_WRITE(this_controller, 0x00000000);
2923 * @brief This is the method provided to handle completions for a single
2926 * @param[in] controller
2929 void scic_sds_controller_single_vector_completion_handler(
2930 SCI_CONTROLLER_HANDLE_T controller
2933 U32 interrupt_status;
2934 SCIC_SDS_CONTROLLER_T *this_controller;
2935 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
2938 sci_base_object_get_logger(controller),
2939 SCIC_LOG_OBJECT_CONTROLLER,
2940 "scic_sds_controller_single_vector_completion_handler(0x%d) enter\n",
2944 interrupt_status = SMU_ISR_READ(this_controller);
2945 interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
2947 if (interrupt_status & SMU_ISR_QUEUE_ERROR)
2950 sci_base_object_get_logger(this_controller),
2951 SCIC_LOG_OBJECT_CONTROLLER,
2952 "SCIC Controller has encountered a fatal error.\n"
2955 // We have a fatal condition and must reset the controller
2956 // Leave the interrupt mask in place and get the controller reset
2957 sci_base_state_machine_change_state(
2958 scic_sds_controller_get_base_state_machine(this_controller),
2959 SCI_BASE_CONTROLLER_STATE_FAILED
2965 (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
2966 && !scic_sds_controller_completion_queue_has_entries(this_controller)
2970 sci_base_object_get_logger(this_controller),
2971 SCIC_LOG_OBJECT_CONTROLLER,
2972 "SCIC Controller has encountered a fatal error.\n"
2975 // We have a fatal condtion and must reset the controller
2976 // Leave the interrupt mask in place and get the controller reset
2977 sci_base_state_machine_change_state(
2978 scic_sds_controller_get_base_state_machine(this_controller),
2979 SCI_BASE_CONTROLLER_STATE_FAILED
2984 if (scic_sds_controller_completion_queue_has_entries(this_controller))
2986 scic_sds_controller_process_completions(this_controller);
2988 // We dont care which interrupt got us to processing the completion queu
2989 // so clear them both.
2992 (SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND)
2996 SMU_IMR_WRITE(this_controller, 0x00000000);
3000 * @brief This is the method provided to handle a MSIX message for a normal
3003 * @param[in] controller
3006 * @retval TRUE if an interrupt is processed
3007 * FALSE if no interrupt was processed
3010 BOOL scic_sds_controller_normal_vector_interrupt_handler(
3011 SCI_CONTROLLER_HANDLE_T controller
3014 SCIC_SDS_CONTROLLER_T *this_controller;
3015 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3017 if (scic_sds_controller_completion_queue_has_entries(this_controller))
3023 // we have a spurious interrupt it could be that we have already
3024 // emptied the completion queue from a previous interrupt
3025 SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
3027 // There is a race in the hardware that could cause us not to be notified
3028 // of an interrupt completion if we do not take this step. We will mask
3029 // then unmask the interrupts so if there is another interrupt pending
3030 // the clearing of the interrupt source we get the next interrupt message.
3031 SMU_IMR_WRITE(this_controller, 0xFF000000);
3032 SMU_IMR_WRITE(this_controller, 0x00000000);
3039 * @brief This is the method provided to handle the completions for a
3040 * normal MSIX message.
3042 * @param[in] controller
3045 void scic_sds_controller_normal_vector_completion_handler(
3046 SCI_CONTROLLER_HANDLE_T controller
3049 SCIC_SDS_CONTROLLER_T *this_controller;
3050 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3053 sci_base_object_get_logger(controller),
3054 SCIC_LOG_OBJECT_CONTROLLER,
3055 "scic_sds_controller_normal_vector_completion_handler(0x%d) enter\n",
3059 // Empty out the completion queue
3060 if (scic_sds_controller_completion_queue_has_entries(this_controller))
3062 scic_sds_controller_process_completions(this_controller);
3065 // Clear the interrupt and enable all interrupts again
3066 SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
3067 // Could we write the value of SMU_ISR_COMPLETION?
3068 SMU_IMR_WRITE(this_controller, 0xFF000000);
3069 SMU_IMR_WRITE(this_controller, 0x00000000);
3073 * @brief This is the method provided to handle the error MSIX message
3074 * interrupt. This is the normal operating mode for the hardware if
3077 * @param[in] controller
3080 * @retval TRUE if an interrupt is processed
3081 * FALSE if no interrupt was processed
3084 BOOL scic_sds_controller_error_vector_interrupt_handler(
3085 SCI_CONTROLLER_HANDLE_T controller
3088 U32 interrupt_status;
3089 SCIC_SDS_CONTROLLER_T *this_controller;
3090 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3093 interrupt_status = SMU_ISR_READ(this_controller);
3094 interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
3096 if (interrupt_status != 0)
3098 // There is an error interrupt pending so let it through and handle
3103 // There is a race in the hardware that could cause us not to be notified
3104 // of an interrupt completion if we do not take this step. We will mask
3105 // then unmask the error interrupts so if there was another interrupt
3106 // pending we will be notified.
3107 // Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)?
3108 SMU_IMR_WRITE(this_controller, 0x000000FF);
3109 SMU_IMR_WRITE(this_controller, 0x00000000);
3115 * @brief This is the method provided to handle the error completions when
3116 * the hardware is using two MSIX messages.
3118 * @param[in] controller
3121 void scic_sds_controller_error_vector_completion_handler(
3122 SCI_CONTROLLER_HANDLE_T controller
3125 U32 interrupt_status;
3126 SCIC_SDS_CONTROLLER_T *this_controller;
3127 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3130 sci_base_object_get_logger(controller),
3131 SCIC_LOG_OBJECT_CONTROLLER,
3132 "scic_sds_controller_error_vector_completion_handler(0x%d) enter\n",
3136 interrupt_status = SMU_ISR_READ(this_controller);
3139 (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
3140 && scic_sds_controller_completion_queue_has_entries(this_controller)
3143 scic_sds_controller_process_completions(this_controller);
3145 SMU_ISR_WRITE(this_controller, SMU_ISR_QUEUE_SUSPEND);
3150 sci_base_object_get_logger(this_controller),
3151 SCIC_LOG_OBJECT_CONTROLLER,
3152 "SCIC Controller reports CRC error on completion ISR %x\n",
3156 sci_base_state_machine_change_state(
3157 scic_sds_controller_get_base_state_machine(this_controller),
3158 SCI_BASE_CONTROLLER_STATE_FAILED
3164 // If we dont process any completions I am not sure that we want to do this.
3165 // We are in the middle of a hardware fault and should probably be reset.
3166 SMU_IMR_WRITE(this_controller, 0x00000000);
3169 #endif // !defined(DISABLE_INTERRUPTS)
3171 //****************************************************************************-
3172 //* SCIC SDS Controller External Methods
3173 //****************************************************************************-
3176 * @brief This method returns the sizeof the SCIC SDS Controller Object
3180 U32 scic_sds_controller_get_object_size(void)
3182 return sizeof(SCIC_SDS_CONTROLLER_T);
3186 * This method returns the minimum number of timers that are required by the
3187 * controller object. This will include required timers for phys and ports.
3190 * @retval The minimum number of timers that are required to make this
3191 * controller operational.
3193 U32 scic_sds_controller_get_min_timer_count(void)
3195 return SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT
3196 + scic_sds_port_get_min_timer_count()
3197 + scic_sds_phy_get_min_timer_count();
3201 * This method returns the maximum number of timers that are required by the
3202 * controller object. This will include required timers for phys and ports.
3205 * @retval The maximum number of timers that will be used by the controller
3208 U32 scic_sds_controller_get_max_timer_count(void)
3210 return SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT
3211 + scic_sds_port_get_max_timer_count()
3212 + scic_sds_phy_get_max_timer_count();
3218 * @param[in] this_controller
3219 * @param[in] the_port
3220 * @param[in] the_phy
3224 void scic_sds_controller_link_up(
3225 SCIC_SDS_CONTROLLER_T *this_controller,
3226 SCIC_SDS_PORT_T *the_port,
3227 SCIC_SDS_PHY_T *the_phy
3230 if (this_controller->state_handlers->link_up_handler != NULL)
3232 this_controller->state_handlers->link_up_handler(
3233 this_controller, the_port, the_phy);
3238 sci_base_object_get_logger(this_controller),
3239 SCIC_LOG_OBJECT_CONTROLLER,
3240 "SCIC Controller linkup event from phy %d in unexpected state %d\n",
3242 sci_base_state_machine_get_state(
3243 scic_sds_controller_get_base_state_machine(this_controller))
3251 * @param[in] this_controller
3252 * @param[in] the_port
3253 * @param[in] the_phy
3255 void scic_sds_controller_link_down(
3256 SCIC_SDS_CONTROLLER_T *this_controller,
3257 SCIC_SDS_PORT_T *the_port,
3258 SCIC_SDS_PHY_T *the_phy
3261 if (this_controller->state_handlers->link_down_handler != NULL)
3263 this_controller->state_handlers->link_down_handler(
3264 this_controller, the_port, the_phy);
3269 sci_base_object_get_logger(this_controller),
3270 SCIC_LOG_OBJECT_CONTROLLER,
3271 "SCIC Controller linkdown event from phy %d in unexpected state %d\n",
3273 sci_base_state_machine_get_state(
3274 scic_sds_controller_get_base_state_machine(this_controller))
3280 * @brief This method is called by the remote device to inform the controller
3281 * that this remote device has started.
3283 * @param[in] this_controller
3284 * @param[in] the_device
3286 void scic_sds_controller_remote_device_started(
3287 SCIC_SDS_CONTROLLER_T * this_controller,
3288 SCIC_SDS_REMOTE_DEVICE_T * the_device
3291 if (this_controller->state_handlers->remote_device_started_handler != NULL)
3293 this_controller->state_handlers->remote_device_started_handler(
3294 this_controller, the_device
3300 sci_base_object_get_logger(this_controller),
3301 SCIC_LOG_OBJECT_CONTROLLER,
3302 "SCIC Controller 0x%x remote device started event from device 0x%x in unexpected state %d\n",
3305 sci_base_state_machine_get_state(
3306 scic_sds_controller_get_base_state_machine(this_controller))
3312 * @brief This is a helper method to determine if any remote devices on this
3313 * controller are still in the stopping state.
3315 * @param[in] this_controller
3317 BOOL scic_sds_controller_has_remote_devices_stopping(
3318 SCIC_SDS_CONTROLLER_T * this_controller
3323 for (index = 0; index < this_controller->remote_node_entries; index++)
3326 (this_controller->device_table[index] != NULL)
3328 this_controller->device_table[index]->parent.state_machine.current_state_id
3329 == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
3341 * @brief This method is called by the remote device to inform the controller
3342 * object that the remote device has stopped.
3344 * @param[in] this_controller
3345 * @param[in] the_device
3347 void scic_sds_controller_remote_device_stopped(
3348 SCIC_SDS_CONTROLLER_T * this_controller,
3349 SCIC_SDS_REMOTE_DEVICE_T * the_device
3352 if (this_controller->state_handlers->remote_device_stopped_handler != NULL)
3354 this_controller->state_handlers->remote_device_stopped_handler(
3355 this_controller, the_device
3361 sci_base_object_get_logger(this_controller),
3362 SCIC_LOG_OBJECT_CONTROLLER,
3363 "SCIC Controller 0x%x remote device stopped event from device 0x%x in unexpected state %d\n",
3366 sci_base_state_machine_get_state(
3367 scic_sds_controller_get_base_state_machine(this_controller))
3373 * @brief This method will write to the SCU PCP register the request value.
3374 * The method is used to suspend/resume ports, devices, and phys.
3376 * @param[in] this_controller
3377 * @param[in] request
3379 void scic_sds_controller_post_request(
3380 SCIC_SDS_CONTROLLER_T *this_controller,
3385 sci_base_object_get_logger(this_controller),
3386 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_COMPLETION_QUEUE,
3387 "SCIC Controller 0x%08x post request 0x%08x\n",
3388 this_controller, request
3391 SMU_PCP_WRITE(this_controller, request);
3395 * @brief This method will copy the soft copy of the task context into
3396 * the physical memory accessible by the controller.
3398 * @note After this call is made the SCIC_SDS_IO_REQUEST object will
3399 * always point to the physical memory version of the task context.
3400 * Thus, all subsequent updates to the task context are performed in
3401 * the TC table (i.e. DMAable memory).
3403 * @param[in] this_controller This parameter specifies the controller for
3404 * which to copy the task context.
3405 * @param[in] this_request This parameter specifies the request for which
3406 * the task context is being copied.
3410 void scic_sds_controller_copy_task_context(
3411 SCIC_SDS_CONTROLLER_T *this_controller,
3412 SCIC_SDS_REQUEST_T *this_request
3415 SCU_TASK_CONTEXT_T *task_context_buffer;
3417 task_context_buffer = scic_sds_controller_get_task_context_buffer(
3418 this_controller, this_request->io_tag
3422 task_context_buffer,
3423 this_request->task_context_buffer,
3424 SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, sgl_snapshot_ac)
3427 // Now that the soft copy of the TC has been copied into the TC
3428 // table accessible by the silicon. Thus, any further changes to
3429 // the TC (e.g. TC termination) occur in the appropriate location.
3430 this_request->task_context_buffer = task_context_buffer;
3434 * @brief This method returns the task context buffer for the given io tag.
3436 * @param[in] this_controller
3439 * @return struct SCU_TASK_CONTEXT*
3441 SCU_TASK_CONTEXT_T * scic_sds_controller_get_task_context_buffer(
3442 SCIC_SDS_CONTROLLER_T * this_controller,
3446 U16 task_index = scic_sds_io_tag_get_index(io_tag);
3448 if (task_index < this_controller->task_context_entries)
3450 return &this_controller->task_context_table[task_index];
3457 * @brief This method returnst the sequence value from the io tag value
3459 * @param[in] this_controller
3464 U16 scic_sds_controller_get_io_sequence_from_tag(
3465 SCIC_SDS_CONTROLLER_T *this_controller,
3469 return scic_sds_io_tag_get_sequence(io_tag);
3473 * @brief This method returns the IO request associated with the tag value
3475 * @param[in] this_controller
3478 * @return SCIC_SDS_IO_REQUEST_T*
3479 * @retval NULL if there is no valid IO request at the tag value
3481 SCIC_SDS_REQUEST_T *scic_sds_controller_get_io_request_from_tag(
3482 SCIC_SDS_CONTROLLER_T *this_controller,
3489 task_index = scic_sds_io_tag_get_index(io_tag);
3491 if (task_index < this_controller->task_context_entries)
3493 if (this_controller->io_request_table[task_index] != SCI_INVALID_HANDLE)
3495 task_sequence = scic_sds_io_tag_get_sequence(io_tag);
3497 if (task_sequence == this_controller->io_request_sequence[task_index])
3499 return this_controller->io_request_table[task_index];
3504 return SCI_INVALID_HANDLE;
3508 * @brief This method allocates remote node index and the reserves the
3509 * remote node context space for use. This method can fail if there
3510 * are no more remote node index available.
3512 * @param[in] this_controller This is the controller object which contains
3513 * the set of free remote node ids
3514 * @param[in] the_devce This is the device object which is requesting the a
3516 * @param[out] node_id This is the remote node id that is assinged to the
3517 * device if one is available
3519 * @return SCI_STATUS
3520 * @retval SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote
3521 * node index available.
3523 SCI_STATUS scic_sds_controller_allocate_remote_node_context(
3524 SCIC_SDS_CONTROLLER_T * this_controller,
3525 SCIC_SDS_REMOTE_DEVICE_T * the_device,
3530 U32 remote_node_count = scic_sds_remote_device_node_count(the_device);
3532 node_index = scic_sds_remote_node_table_allocate_remote_node(
3533 &this_controller->available_remote_nodes, remote_node_count
3536 if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
3538 this_controller->device_table[node_index] = the_device;
3540 *node_id = node_index;
3545 return SCI_FAILURE_INSUFFICIENT_RESOURCES;
3549 * @brief This method frees the remote node index back to the available
3550 * pool. Once this is done the remote node context buffer is no
3551 * longer valid and can not be used.
3553 * @param[in] this_controller
3554 * @param[in] the_device
3555 * @param[in] node_id
3559 void scic_sds_controller_free_remote_node_context(
3560 SCIC_SDS_CONTROLLER_T * this_controller,
3561 SCIC_SDS_REMOTE_DEVICE_T * the_device,
3565 U32 remote_node_count = scic_sds_remote_device_node_count(the_device);
3567 if (this_controller->device_table[node_id] == the_device)
3569 this_controller->device_table[node_id] = SCI_INVALID_HANDLE;
3571 scic_sds_remote_node_table_release_remote_node_index(
3572 &this_controller->available_remote_nodes, remote_node_count, node_id
3578 * @brief This method returns the SCU_REMOTE_NODE_CONTEXT for the specified
3581 * @param[in] this_controller
3582 * @param[in] node_id
3584 * @return SCU_REMOTE_NODE_CONTEXT_T*
3586 SCU_REMOTE_NODE_CONTEXT_T *scic_sds_controller_get_remote_node_context_buffer(
3587 SCIC_SDS_CONTROLLER_T *this_controller,
3592 (node_id < this_controller->remote_node_entries)
3593 && (this_controller->device_table[node_id] != SCI_INVALID_HANDLE)
3596 return &this_controller->remote_node_context_table[node_id];
3603 * This method will combind the frame header and frame buffer to create
3604 * a SATA D2H register FIS
3606 * @param[out] resposne_buffer This is the buffer into which the D2H register
3607 * FIS will be constructed.
3608 * @param[in] frame_header This is the frame header returned by the hardware.
3609 * @param[in] frame_buffer This is the frame buffer returned by the hardware.
3613 void scic_sds_controller_copy_sata_response(
3614 void * response_buffer,
3615 void * frame_header,
3626 (char *)((char *)response_buffer + sizeof(U32)),
3628 sizeof(SATA_FIS_REG_D2H_T) - sizeof(U32)
3633 * @brief This method releases the frame once this is done the frame is
3634 * available for re-use by the hardware. The data contained in the
3635 * frame header and frame buffer is no longer valid.
3636 * The UF queue get pointer is only updated if UF control indicates
3637 * this is appropriate.
3639 * @param[in] this_controller
3640 * @param[in] frame_index
3644 void scic_sds_controller_release_frame(
3645 SCIC_SDS_CONTROLLER_T *this_controller,
3649 if (scic_sds_unsolicited_frame_control_release_frame(
3650 &this_controller->uf_control, frame_index) == TRUE)
3651 SCU_UFQGP_WRITE(this_controller, this_controller->uf_control.get);
3655 void scic_sds_controller_initialize_state_logging(
3656 SCIC_SDS_CONTROLLER_T *this_controller
3659 sci_base_state_machine_logger_initialize(
3660 &this_controller->parent.state_machine_logger,
3661 &this_controller->parent.state_machine,
3662 &this_controller->parent.parent,
3663 scic_cb_logger_log_states,
3664 "SCIC_SDS_CONTROLLER_T", "base state machine",
3665 SCIC_LOG_OBJECT_CONTROLLER
3669 void scic_sds_controller_deinitialize_state_logging(
3670 SCIC_SDS_CONTROLLER_T *this_controller
3673 sci_base_state_machine_logger_deinitialize(
3674 &this_controller->parent.state_machine_logger,
3675 &this_controller->parent.state_machine
3681 * @brief This method sets user parameters and OEM parameters to
3682 * default values. Users can override these values utilizing
3683 * the scic_user_parameters_set() and scic_oem_parameters_set()
3686 * @param[in] controller This parameter specifies the controller for
3687 * which to set the configuration parameters to their
3693 void scic_sds_controller_set_default_config_parameters(
3694 SCIC_SDS_CONTROLLER_T *this_controller
3699 // Default to APC mode.
3700 this_controller->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
3703 this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up = 1;
3705 // Default to no SSC operation.
3706 this_controller->oem_parameters.sds1.controller.ssc_sata_tx_spread_level = 0;
3707 this_controller->oem_parameters.sds1.controller.ssc_sas_tx_spread_level = 0;
3708 this_controller->oem_parameters.sds1.controller.ssc_sas_tx_type = 0;
3710 // Default to all phys to using short cables
3711 this_controller->oem_parameters.sds1.controller.cable_selection_mask = 0;
3713 // Initialize all of the port parameter information to narrow ports.
3714 for (index = 0; index < SCI_MAX_PORTS; index++)
3716 this_controller->oem_parameters.sds1.ports[index].phy_mask = 0;
3719 // Initialize all of the phy parameter information.
3720 for (index = 0; index < SCI_MAX_PHYS; index++)
3722 // Default to 6G (i.e. Gen 3) for now. User can override if
3724 this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2;
3726 //the frequencies cannot be 0
3727 this_controller->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f;
3728 this_controller->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff;
3729 this_controller->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33;
3731 // Previous Vitesse based expanders had a arbitration issue that
3732 // is worked around by having the upper 32-bits of SAS address
3733 // with a value greater then the Vitesse company identifier.
3734 // Hence, usage of 0x5FCFFFFF.
3735 this_controller->oem_parameters.sds1.phys[index].sas_address.sci_format.high
3738 // Add in controller index to ensure each controller will have unique SAS addresses by default.
3739 this_controller->oem_parameters.sds1.phys[index].sas_address.sci_format.low
3740 = 0x00000001 + this_controller->controller_index;
3742 if ( (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
3743 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
3744 || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0) )
3746 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control0 = 0x000E7C03;
3747 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control1 = 0x000E7C03;
3748 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control2 = 0x000E7C03;
3749 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control3 = 0x000E7C03;
3751 else // This must be SCIC_SDS_PCI_REVISION_C0
3753 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control0 = 0x000BDD08;
3754 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control1 = 0x000B7069;
3755 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control2 = 0x000B7C09;
3756 this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control3 = 0x000AFC6E;
3760 this_controller->user_parameters.sds1.stp_inactivity_timeout = 5;
3761 this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5;
3762 this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5;
3763 this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20;
3764 this_controller->user_parameters.sds1.no_outbound_task_timeout = 20;
3770 * @brief This method release resources in SCI controller.
3772 * @param[in] this_controller This parameter specifies the core
3773 * controller and associated objects whose resources are to be
3776 * @return This method returns a value indicating if the operation succeeded.
3777 * @retval SCI_SUCCESS This value indicates that all the timers are destroyed.
3778 * @retval SCI_FAILURE This value indicates certain failure during the process
3779 * of cleaning timer resource.
3782 SCI_STATUS scic_sds_controller_release_resource(
3783 SCIC_SDS_CONTROLLER_T * this_controller
3786 SCIC_SDS_PORT_T * port;
3787 SCIC_SDS_PHY_T * phy;
3791 sci_base_object_get_logger(this_controller),
3792 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
3793 "scic_sds_controller_release_resource(0x%x) enter\n",
3797 if(this_controller->phy_startup_timer != NULL)
3799 scic_cb_timer_destroy(this_controller, this_controller->phy_startup_timer);
3800 this_controller->phy_startup_timer = NULL;
3803 if(this_controller->power_control.timer != NULL)
3805 scic_cb_timer_destroy(this_controller, this_controller->power_control.timer);
3806 this_controller->power_control.timer = NULL;
3809 if(this_controller->timeout_timer != NULL)
3811 scic_cb_timer_destroy(this_controller, this_controller->timeout_timer);
3812 this_controller->timeout_timer = NULL;
3815 scic_sds_port_configuration_agent_release_resource(
3817 &this_controller->port_agent);
3819 for(index = 0; index < SCI_MAX_PORTS+1; index++)
3821 port = &this_controller->port_table[index];
3822 scic_sds_port_release_resource(this_controller, port);
3825 for(index = 0; index < SCI_MAX_PHYS; index++)
3827 phy = &this_controller->phy_table[index];
3828 scic_sds_phy_release_resource(this_controller, phy);
3836 * @brief This method process the ports configured message from port configuration
3839 * @param[in] this_controller This parameter specifies the core
3840 * controller that its ports are configured.
3844 void scic_sds_controller_port_agent_configured_ports(
3845 SCIC_SDS_CONTROLLER_T * this_controller
3848 //simply transit to ready. The function below checks the controller state
3849 scic_sds_controller_transition_to_ready(
3850 this_controller, SCI_SUCCESS
3855 //****************************************************************************-
3856 //* SCIC Controller Public Methods
3857 //****************************************************************************-
3859 SCI_STATUS scic_controller_construct(
3860 SCI_LIBRARY_HANDLE_T library,
3861 SCI_CONTROLLER_HANDLE_T controller,
3865 SCIC_SDS_LIBRARY_T *my_library;
3866 SCIC_SDS_CONTROLLER_T *this_controller;
3868 my_library = (SCIC_SDS_LIBRARY_T *)library;
3869 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3872 sci_base_object_get_logger(library),
3873 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
3874 "scic_controller_construct(0x%x, 0x%x) enter\n",
3878 // Just clear out the memory of the structure to be safe.
3879 memset(this_controller, 0, sizeof(SCIC_SDS_CONTROLLER_T));
3881 // Make sure that the static data is assigned before moving onto the
3882 // base constroller construct as this will cause the controller to
3883 // enter its initial state and the controller_index and pci_revision
3884 // will be required to complete those operations correctly
3885 this_controller->controller_index =
3886 scic_sds_library_get_controller_index(my_library, this_controller);
3888 this_controller->pci_revision = my_library->pci_revision;
3890 sci_base_controller_construct(
3891 &this_controller->parent,
3892 sci_base_object_get_logger(my_library),
3893 scic_sds_controller_state_table,
3894 this_controller->memory_descriptors,
3895 ARRAY_SIZE(this_controller->memory_descriptors),
3899 sci_object_set_association(controller, user_object);
3901 scic_sds_controller_initialize_state_logging(this_controller);
3903 scic_sds_pci_bar_initialization(this_controller);
3908 // ---------------------------------------------------------------------------
3910 SCI_STATUS scic_controller_initialize(
3911 SCI_CONTROLLER_HANDLE_T controller
3914 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
3915 SCIC_SDS_CONTROLLER_T *this_controller;
3916 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3919 sci_base_object_get_logger(controller),
3920 SCIC_LOG_OBJECT_CONTROLLER,
3921 "scic_controller_initialize(0x%x, 0x%d) enter\n",
3925 if (this_controller->state_handlers->parent.initialize_handler != NULL)
3927 status = this_controller->state_handlers->parent.initialize_handler(
3928 (SCI_BASE_CONTROLLER_T *)controller
3934 sci_base_object_get_logger(this_controller),
3935 SCIC_LOG_OBJECT_CONTROLLER,
3936 "SCIC Controller initialize operation requested in invalid state %d\n",
3937 sci_base_state_machine_get_state(
3938 scic_sds_controller_get_base_state_machine(this_controller))
3945 // ---------------------------------------------------------------------------
3947 U32 scic_controller_get_suggested_start_timeout(
3948 SCI_CONTROLLER_HANDLE_T controller
3951 // Validate the user supplied parameters.
3952 if (controller == SCI_INVALID_HANDLE)
3955 // The suggested minimum timeout value for a controller start operation:
3957 // Signature FIS Timeout
3958 // + Phy Start Timeout
3959 // + Number of Phy Spin Up Intervals
3960 // ---------------------------------
3961 // Number of milliseconds for the controller start operation.
3963 // NOTE: The number of phy spin up intervals will be equivalent
3964 // to the number of phys divided by the number phys allowed
3965 // per interval - 1 (once OEM parameters are supported).
3966 // Currently we assume only 1 phy per interval.
3968 return (SCIC_SDS_SIGNATURE_FIS_TIMEOUT
3969 + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
3970 + ((SCI_MAX_PHYS-1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL));
3973 // ---------------------------------------------------------------------------
3975 SCI_STATUS scic_controller_start(
3976 SCI_CONTROLLER_HANDLE_T controller,
3980 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
3981 SCIC_SDS_CONTROLLER_T *this_controller;
3982 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
3985 sci_base_object_get_logger(controller),
3986 SCIC_LOG_OBJECT_CONTROLLER,
3987 "scic_controller_start(0x%x, 0x%d) enter\n",
3991 if (this_controller->state_handlers->parent.start_handler != NULL)
3993 status = this_controller->state_handlers->parent.start_handler(
3994 (SCI_BASE_CONTROLLER_T *)controller, timeout
4000 sci_base_object_get_logger(this_controller),
4001 SCIC_LOG_OBJECT_CONTROLLER,
4002 "SCIC Controller start operation requested in invalid state %d\n",
4003 sci_base_state_machine_get_state(
4004 scic_sds_controller_get_base_state_machine(this_controller))
4011 // ---------------------------------------------------------------------------
4013 SCI_STATUS scic_controller_stop(
4014 SCI_CONTROLLER_HANDLE_T controller,
4018 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4019 SCIC_SDS_CONTROLLER_T *this_controller;
4020 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4023 sci_base_object_get_logger(controller),
4024 SCIC_LOG_OBJECT_CONTROLLER,
4025 "scic_controller_stop(0x%x, 0x%d) enter\n",
4029 if (this_controller->state_handlers->parent.stop_handler != NULL)
4031 status = this_controller->state_handlers->parent.stop_handler(
4032 (SCI_BASE_CONTROLLER_T *)controller, timeout
4038 sci_base_object_get_logger(this_controller),
4039 SCIC_LOG_OBJECT_CONTROLLER,
4040 "SCIC Controller stop operation requested in invalid state %d\n",
4041 sci_base_state_machine_get_state(
4042 scic_sds_controller_get_base_state_machine(this_controller))
4049 // ---------------------------------------------------------------------------
4051 SCI_STATUS scic_controller_reset(
4052 SCI_CONTROLLER_HANDLE_T controller
4055 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4056 SCIC_SDS_CONTROLLER_T *this_controller;
4057 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4060 sci_base_object_get_logger(controller),
4061 SCIC_LOG_OBJECT_CONTROLLER,
4062 "scic_controller_reset(0x%x) enter\n",
4066 if (this_controller->state_handlers->parent.reset_handler != NULL)
4068 status = this_controller->state_handlers->parent.reset_handler(
4069 (SCI_BASE_CONTROLLER_T *)controller
4075 sci_base_object_get_logger(this_controller),
4076 SCIC_LOG_OBJECT_CONTROLLER,
4077 "SCIC Controller reset operation requested in invalid state %d\n",
4078 sci_base_state_machine_get_state(
4079 scic_sds_controller_get_base_state_machine(this_controller))
4086 // ---------------------------------------------------------------------------
4088 SCI_STATUS scic_controller_get_handler_methods(
4089 SCIC_INTERRUPT_TYPE interrupt_type,
4091 SCIC_CONTROLLER_HANDLER_METHODS_T *handler_methods
4094 SCI_STATUS status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT;
4096 switch (interrupt_type)
4098 #if !defined(DISABLE_INTERRUPTS)
4099 case SCIC_LEGACY_LINE_INTERRUPT_TYPE:
4100 if (message_count == 0)
4102 handler_methods[0].interrupt_handler
4103 = scic_sds_controller_legacy_interrupt_handler;
4104 handler_methods[0].completion_handler
4105 = scic_sds_controller_legacy_completion_handler;
4107 status = SCI_SUCCESS;
4111 case SCIC_MSIX_INTERRUPT_TYPE:
4112 if (message_count == 1)
4114 handler_methods[0].interrupt_handler
4115 = scic_sds_controller_single_vector_interrupt_handler;
4116 handler_methods[0].completion_handler
4117 = scic_sds_controller_single_vector_completion_handler;
4119 status = SCI_SUCCESS;
4121 else if (message_count == 2)
4123 handler_methods[0].interrupt_handler
4124 = scic_sds_controller_normal_vector_interrupt_handler;
4125 handler_methods[0].completion_handler
4126 = scic_sds_controller_normal_vector_completion_handler;
4128 handler_methods[1].interrupt_handler
4129 = scic_sds_controller_error_vector_interrupt_handler;
4130 handler_methods[1].completion_handler
4131 = scic_sds_controller_error_vector_completion_handler;
4133 status = SCI_SUCCESS;
4136 #endif // !defined(DISABLE_INTERRUPTS)
4138 case SCIC_NO_INTERRUPTS:
4139 if (message_count == 0)
4142 handler_methods[0].interrupt_handler
4143 = scic_sds_controller_polling_interrupt_handler;
4144 handler_methods[0].completion_handler
4145 = scic_sds_controller_polling_completion_handler;
4147 status = SCI_SUCCESS;
4152 status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
4159 // ---------------------------------------------------------------------------
4161 SCI_IO_STATUS scic_controller_start_io(
4162 SCI_CONTROLLER_HANDLE_T controller,
4163 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4164 SCI_IO_REQUEST_HANDLE_T io_request,
4169 SCIC_SDS_CONTROLLER_T *this_controller;
4170 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4173 sci_base_object_get_logger(controller),
4174 SCIC_LOG_OBJECT_CONTROLLER,
4175 "scic_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
4176 controller, remote_device, io_request, io_tag
4179 status = this_controller->state_handlers->parent.start_io_handler(
4180 &this_controller->parent,
4181 (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4182 (SCI_BASE_REQUEST_T *)io_request,
4186 return (SCI_IO_STATUS)status;
4189 // ---------------------------------------------------------------------------
4191 SCI_STATUS scic_controller_terminate_request(
4192 SCI_CONTROLLER_HANDLE_T controller,
4193 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4194 SCI_IO_REQUEST_HANDLE_T request
4198 SCIC_SDS_CONTROLLER_T *this_controller;
4199 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4202 sci_base_object_get_logger(controller),
4203 SCIC_LOG_OBJECT_CONTROLLER,
4204 "scic_controller_terminate_request(0x%x, 0x%x, 0x%x) enter\n",
4205 controller, remote_device, request
4208 status = this_controller->state_handlers->terminate_request_handler(
4209 &this_controller->parent,
4210 (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4211 (SCI_BASE_REQUEST_T *)request
4217 // ---------------------------------------------------------------------------
4219 SCI_STATUS scic_controller_complete_io(
4220 SCI_CONTROLLER_HANDLE_T controller,
4221 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4222 SCI_IO_REQUEST_HANDLE_T io_request
4226 SCIC_SDS_CONTROLLER_T *this_controller;
4227 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4230 sci_base_object_get_logger(controller),
4231 SCIC_LOG_OBJECT_CONTROLLER,
4232 "scic_controller_complete_io(0x%x, 0x%x, 0x%x) enter\n",
4233 controller, remote_device, io_request
4236 status = this_controller->state_handlers->parent.complete_io_handler(
4237 &this_controller->parent,
4238 (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4239 (SCI_BASE_REQUEST_T *)io_request
4245 // ---------------------------------------------------------------------------
4247 #if !defined(DISABLE_TASK_MANAGEMENT)
4249 SCI_TASK_STATUS scic_controller_start_task(
4250 SCI_CONTROLLER_HANDLE_T controller,
4251 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4252 SCI_TASK_REQUEST_HANDLE_T task_request,
4256 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4257 SCIC_SDS_CONTROLLER_T *this_controller;
4258 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4261 sci_base_object_get_logger(controller),
4262 SCIC_LOG_OBJECT_CONTROLLER,
4263 "scic_controller_start_task(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
4264 controller, remote_device, task_request, task_tag
4267 if (this_controller->state_handlers->parent.start_task_handler != NULL)
4269 status = this_controller->state_handlers->parent.start_task_handler(
4270 &this_controller->parent,
4271 (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4272 (SCI_BASE_REQUEST_T *)task_request,
4279 sci_base_object_get_logger(controller),
4280 SCIC_LOG_OBJECT_CONTROLLER,
4281 "SCIC Controller starting task from invalid state\n"
4285 return (SCI_TASK_STATUS)status;
4288 // ---------------------------------------------------------------------------
4290 SCI_STATUS scic_controller_complete_task(
4291 SCI_CONTROLLER_HANDLE_T controller,
4292 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
4293 SCI_TASK_REQUEST_HANDLE_T task_request
4296 SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
4297 SCIC_SDS_CONTROLLER_T *this_controller;
4298 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4301 sci_base_object_get_logger(controller),
4302 SCIC_LOG_OBJECT_CONTROLLER,
4303 "scic_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n",
4304 controller, remote_device, task_request
4307 if (this_controller->state_handlers->parent.complete_task_handler != NULL)
4309 status = this_controller->state_handlers->parent.complete_task_handler(
4310 &this_controller->parent,
4311 (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
4312 (SCI_BASE_REQUEST_T *)task_request
4318 sci_base_object_get_logger(controller),
4319 SCIC_LOG_OBJECT_CONTROLLER,
4320 "SCIC Controller completing task from invalid state\n"
4327 #endif // !defined(DISABLE_TASK_MANAGEMENT)
4329 // ---------------------------------------------------------------------------
4331 SCI_STATUS scic_controller_get_port_handle(
4332 SCI_CONTROLLER_HANDLE_T controller,
4334 SCI_PORT_HANDLE_T * port_handle
4337 SCIC_SDS_CONTROLLER_T *this_controller;
4338 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4341 sci_base_object_get_logger(controller),
4342 SCIC_LOG_OBJECT_CONTROLLER,
4343 "scic_controller_get_port_handle(0x%x, 0x%x, 0x%x) enter\n",
4344 controller, port_index, port_handle
4347 if (port_index < this_controller->logical_port_entries)
4349 *port_handle = &this_controller->port_table[port_index];
4354 return SCI_FAILURE_INVALID_PORT;
4357 // ---------------------------------------------------------------------------
4359 SCI_STATUS scic_controller_get_phy_handle(
4360 SCI_CONTROLLER_HANDLE_T controller,
4362 SCI_PHY_HANDLE_T * phy_handle
4365 SCIC_SDS_CONTROLLER_T *this_controller;
4366 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4369 sci_base_object_get_logger(controller),
4370 SCIC_LOG_OBJECT_CONTROLLER,
4371 "scic_controller_get_phy_handle(0x%x, 0x%x, 0x%x) enter\n",
4372 controller, phy_index, phy_handle
4375 if (phy_index < ARRAY_SIZE(this_controller->phy_table))
4377 *phy_handle = &this_controller->phy_table[phy_index];
4383 sci_base_object_get_logger(this_controller),
4384 SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_CONTROLLER,
4385 "Controller:0x%x PhyId:0x%x invalid phy index\n",
4386 this_controller, phy_index
4389 return SCI_FAILURE_INVALID_PHY;
4392 // ---------------------------------------------------------------------------
4394 U16 scic_controller_allocate_io_tag(
4395 SCI_CONTROLLER_HANDLE_T controller
4400 SCIC_SDS_CONTROLLER_T *this_controller;
4401 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4404 sci_base_object_get_logger(controller),
4405 SCIC_LOG_OBJECT_CONTROLLER,
4406 "scic_controller_allocate_io_tag(0x%x) enter\n",
4410 if (!sci_pool_empty(this_controller->tci_pool))
4412 sci_pool_get(this_controller->tci_pool, task_context);
4414 sequence_count = this_controller->io_request_sequence[task_context];
4416 return scic_sds_io_tag_construct(sequence_count, task_context);
4419 return SCI_CONTROLLER_INVALID_IO_TAG;
4422 // ---------------------------------------------------------------------------
4424 SCI_STATUS scic_controller_free_io_tag(
4425 SCI_CONTROLLER_HANDLE_T controller,
4432 SCIC_SDS_CONTROLLER_T *this_controller;
4433 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4435 ASSERT(io_tag != SCI_CONTROLLER_INVALID_IO_TAG);
4438 sci_base_object_get_logger(controller),
4439 SCIC_LOG_OBJECT_CONTROLLER,
4440 "scic_controller_free_io_tag(0x%x, 0x%x) enter\n",
4444 sequence = scic_sds_io_tag_get_sequence(io_tag);
4445 index = scic_sds_io_tag_get_index(io_tag);
4447 if (!sci_pool_full(this_controller->tci_pool))
4449 if (sequence == this_controller->io_request_sequence[index])
4451 scic_sds_io_sequence_increment(
4452 this_controller->io_request_sequence[index]);
4454 sci_pool_put(this_controller->tci_pool, index);
4460 return SCI_FAILURE_INVALID_IO_TAG;
4463 // ---------------------------------------------------------------------------
4465 void scic_controller_enable_interrupts(
4466 SCI_CONTROLLER_HANDLE_T controller
4469 SCIC_SDS_CONTROLLER_T *this_controller;
4470 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4472 ASSERT(this_controller->smu_registers != NULL);
4474 SMU_IMR_WRITE(this_controller, 0x00000000);
4477 // ---------------------------------------------------------------------------
4479 void scic_controller_disable_interrupts(
4480 SCI_CONTROLLER_HANDLE_T controller
4483 SCIC_SDS_CONTROLLER_T *this_controller;
4484 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4486 ASSERT(this_controller->smu_registers != NULL);
4488 SMU_IMR_WRITE(this_controller, 0xffffffff);
4491 // ---------------------------------------------------------------------------
4493 SCI_STATUS scic_controller_set_mode(
4494 SCI_CONTROLLER_HANDLE_T controller,
4495 SCI_CONTROLLER_MODE operating_mode
4498 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4499 SCI_STATUS status = SCI_SUCCESS;
4502 sci_base_object_get_logger(controller),
4503 SCIC_LOG_OBJECT_CONTROLLER,
4504 "scic_controller_set_mode(0x%x, 0x%x) enter\n",
4505 controller, operating_mode
4509 (this_controller->parent.state_machine.current_state_id
4510 == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
4511 || (this_controller->parent.state_machine.current_state_id
4512 == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
4515 switch (operating_mode)
4517 case SCI_MODE_SPEED:
4518 this_controller->remote_node_entries =
4519 MIN(this_controller->remote_node_entries, SCI_MAX_REMOTE_DEVICES);
4520 this_controller->task_context_entries =
4521 MIN(this_controller->task_context_entries, SCU_IO_REQUEST_COUNT);
4522 this_controller->uf_control.buffers.count =
4523 MIN(this_controller->uf_control.buffers.count, SCU_UNSOLICITED_FRAME_COUNT);
4524 this_controller->completion_event_entries =
4525 MIN(this_controller->completion_event_entries, SCU_EVENT_COUNT);
4526 this_controller->completion_queue_entries =
4527 MIN(this_controller->completion_queue_entries, SCU_COMPLETION_QUEUE_COUNT);
4529 scic_sds_controller_build_memory_descriptor_table(this_controller);
4533 this_controller->remote_node_entries =
4534 MIN(this_controller->remote_node_entries, SCI_MIN_REMOTE_DEVICES);
4535 this_controller->task_context_entries =
4536 MIN(this_controller->task_context_entries, SCI_MIN_IO_REQUESTS);
4537 this_controller->uf_control.buffers.count =
4538 MIN(this_controller->uf_control.buffers.count, SCU_MIN_UNSOLICITED_FRAMES);
4539 this_controller->completion_event_entries =
4540 MIN(this_controller->completion_event_entries, SCU_MIN_EVENTS);
4541 this_controller->completion_queue_entries =
4542 MIN(this_controller->completion_queue_entries, SCU_MIN_COMPLETION_QUEUE_ENTRIES);
4544 scic_sds_controller_build_memory_descriptor_table(this_controller);
4548 status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
4553 status = SCI_FAILURE_INVALID_STATE;
4559 * This method will reset the controller hardware.
4561 * @param[in] this_controller The controller that is to be reset.
4563 void scic_sds_controller_reset_hardware(
4564 SCIC_SDS_CONTROLLER_T * this_controller
4567 // Disable interrupts so we dont take any spurious interrupts
4568 scic_controller_disable_interrupts(this_controller);
4571 SMU_SMUSRCR_WRITE(this_controller, 0xFFFFFFFF);
4573 // Delay for 1ms to before clearing the CQP and UFQPR.
4574 scic_cb_stall_execution(1000);
4576 // The write to the CQGR clears the CQP
4577 SMU_CQGR_WRITE(this_controller, 0x00000000);
4579 // The write to the UFQGP clears the UFQPR
4580 SCU_UFQGP_WRITE(this_controller, 0x00000000);
4583 // ---------------------------------------------------------------------------
4585 SCI_STATUS scic_user_parameters_set(
4586 SCI_CONTROLLER_HANDLE_T controller,
4587 SCIC_USER_PARAMETERS_T * scic_parms
4590 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4593 (this_controller->parent.state_machine.current_state_id
4594 == SCI_BASE_CONTROLLER_STATE_RESET)
4595 || (this_controller->parent.state_machine.current_state_id
4596 == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
4597 || (this_controller->parent.state_machine.current_state_id
4598 == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
4603 // Validate the user parameters. If they are not legal, then
4604 // return a failure.
4605 for (index = 0; index < SCI_MAX_PHYS; index++)
4608 ( scic_parms->sds1.phys[index].max_speed_generation
4609 <= SCIC_SDS_PARM_MAX_SPEED
4610 && scic_parms->sds1.phys[index].max_speed_generation
4611 > SCIC_SDS_PARM_NO_SPEED
4614 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4617 (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) ||
4618 (scic_parms->sds1.phys[index].align_insertion_frequency == 0) ||
4619 (scic_parms->sds1.phys[index].notify_enable_spin_up_insertion_frequency == 0)
4622 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4627 (scic_parms->sds1.stp_inactivity_timeout == 0) ||
4628 (scic_parms->sds1.ssp_inactivity_timeout == 0) ||
4629 (scic_parms->sds1.stp_max_occupancy_timeout == 0) ||
4630 (scic_parms->sds1.ssp_max_occupancy_timeout == 0) ||
4631 (scic_parms->sds1.no_outbound_task_timeout == 0)
4634 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4638 (&this_controller->user_parameters), scic_parms, sizeof(*scic_parms));
4643 return SCI_FAILURE_INVALID_STATE;
4646 // ---------------------------------------------------------------------------
4648 void scic_user_parameters_get(
4649 SCI_CONTROLLER_HANDLE_T controller,
4650 SCIC_USER_PARAMETERS_T * scic_parms
4653 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4655 memcpy(scic_parms, (&this_controller->user_parameters), sizeof(*scic_parms));
4658 // ---------------------------------------------------------------------------
4659 SCI_STATUS scic_oem_parameters_set(
4660 SCI_CONTROLLER_HANDLE_T controller,
4661 SCIC_OEM_PARAMETERS_T * scic_parms,
4662 U8 scic_parms_version
4665 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4666 SCI_BIOS_OEM_PARAM_ELEMENT_T *old_oem_params =
4667 (SCI_BIOS_OEM_PARAM_ELEMENT_T *)(&(scic_parms->sds1));
4671 (this_controller->parent.state_machine.current_state_id
4672 == SCI_BASE_CONTROLLER_STATE_RESET)
4673 || (this_controller->parent.state_machine.current_state_id
4674 == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
4675 || (this_controller->parent.state_machine.current_state_id
4676 == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
4680 U8 combined_phy_mask = 0;
4683 * Set the OEM parameter version for the controller. This comes
4684 * from the OEM parameter block header or the registry depending
4685 * on what WCDL is set to retrieve.
4687 this_controller->oem_parameters_version = scic_parms_version;
4689 // Validate the oem parameters. If they are not legal, then
4690 // return a failure.
4691 for(index=0; index<SCI_MAX_PORTS; index++)
4693 if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX)
4695 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4699 for(index=0; index<SCI_MAX_PHYS; index++)
4702 scic_parms->sds1.phys[index].sas_address.sci_format.high == 0
4703 && scic_parms->sds1.phys[index].sas_address.sci_format.low == 0
4706 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4709 #if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
4711 (scic_parms->sds1.phys[index].afe_tx_amp_control0 == 0) ||
4712 (scic_parms->sds1.phys[index].afe_tx_amp_control1 == 0) ||
4713 (scic_parms->sds1.phys[index].afe_tx_amp_control2 == 0) ||
4714 (scic_parms->sds1.phys[index].afe_tx_amp_control3 == 0)
4717 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4722 if (scic_parms->sds1.controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
4724 for(index=0; index<SCI_MAX_PHYS; index++)
4726 if (scic_parms->sds1.ports[index].phy_mask != 0)
4728 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4732 else if (scic_parms->sds1.controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE)
4734 for(index=0; index<SCI_MAX_PHYS; index++)
4736 combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask;
4739 if (combined_phy_mask == 0)
4741 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4746 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4749 if (scic_parms->sds1.controller.max_number_concurrent_device_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
4751 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4754 if (old_oem_params->controller.do_enable_ssc != 0)
4756 if ( (scic_parms_version == SCI_OEM_PARAM_VER_1_0)
4757 && (old_oem_params->controller.do_enable_ssc != 0x01))
4758 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4760 if (scic_parms_version >= SCI_OEM_PARAM_VER_1_1)
4762 SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T *oem_params =
4763 (SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T*)(&(scic_parms->sds1));
4765 U8 test = oem_params->controller.ssc_sata_tx_spread_level;
4766 if ( !((test == 0x0) || (test == 0x2) || (test == 0x3) ||
4767 (test == 0x6) || (test == 0x7)) )
4768 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4770 test = oem_params->controller.ssc_sas_tx_spread_level;
4771 if (oem_params->controller.ssc_sas_tx_type == 0)
4773 if ( !((test == 0x0) || (test == 0x2) || (test == 0x3)) )
4774 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4777 if (oem_params->controller.ssc_sas_tx_type == 1)
4779 if ( !((test == 0x0) || (test == 0x3) || (test == 0x6)) )
4780 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4786 (&this_controller->oem_parameters), scic_parms, sizeof(*scic_parms));
4790 return SCI_FAILURE_INVALID_STATE;
4793 // ---------------------------------------------------------------------------
4795 void scic_oem_parameters_get(
4796 SCI_CONTROLLER_HANDLE_T controller,
4797 SCIC_OEM_PARAMETERS_T * scic_parms
4800 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
4802 memcpy(scic_parms, (&this_controller->oem_parameters), sizeof(*scic_parms));
4805 // ---------------------------------------------------------------------------
4807 #if !defined(DISABLE_INTERRUPTS)
4809 #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853
4810 #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280
4811 #define INTERRUPT_COALESCE_TIMEOUT_MAX_US 2700000
4812 #define INTERRUPT_COALESCE_NUMBER_MAX 256
4813 #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN 7
4814 #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX 28
4816 SCI_STATUS scic_controller_set_interrupt_coalescence(
4817 SCI_CONTROLLER_HANDLE_T controller,
4818 U32 coalesce_number,
4819 U32 coalesce_timeout
4822 SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4823 U8 timeout_encode = 0;
4827 //Check if the input parameters fall in the range.
4828 if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX)
4829 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4831 // Defined encoding for interrupt coalescing timeout:
4832 // Value Min Max Units
4833 // ----- --- --- -----
4865 //Use the table above to decide the encode of interrupt coalescing timeout
4866 //value for register writing.
4867 if (coalesce_timeout == 0)
4871 //make the timeout value in unit of (10 ns).
4872 coalesce_timeout = coalesce_timeout * 100;
4873 min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10;
4874 max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10;
4876 //get the encode of timeout for register writing.
4877 for ( timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN;
4878 timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX;
4881 if (min <= coalesce_timeout && max > coalesce_timeout)
4883 else if (coalesce_timeout >= max && coalesce_timeout < min*2
4884 && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US*100)
4886 if ( (coalesce_timeout-max) < (2*min - coalesce_timeout) )
4901 if ( timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX+1 )
4902 //the value is out of range.
4903 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4908 (SMU_ICC_GEN_VAL(NUMBER, coalesce_number)|
4909 SMU_ICC_GEN_VAL(TIMER, timeout_encode))
4912 scic_controller->interrupt_coalesce_number = (U16)coalesce_number;
4913 scic_controller->interrupt_coalesce_timeout = coalesce_timeout/100;
4918 // ---------------------------------------------------------------------------
4920 void scic_controller_get_interrupt_coalescence(
4921 SCI_CONTROLLER_HANDLE_T controller,
4922 U32 * coalesce_number,
4923 U32 * coalesce_timeout
4926 SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4927 *coalesce_number = scic_controller->interrupt_coalesce_number;
4928 *coalesce_timeout = scic_controller->interrupt_coalesce_timeout;
4931 #endif // !defined(DISABLE_INTERRUPTS)
4933 // ---------------------------------------------------------------------------
4935 U32 scic_controller_get_scratch_ram_size(
4936 SCI_CONTROLLER_HANDLE_T controller
4939 return SCU_SCRATCH_RAM_SIZE_IN_DWORDS;
4942 // ---------------------------------------------------------------------------
4944 SCI_STATUS scic_controller_read_scratch_ram_dword(
4945 SCI_CONTROLLER_HANDLE_T controller,
4951 SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
4952 U32 status = SMU_SMUCSR_READ(scic_controller);
4954 //Check if the SCU Scratch RAM been initialized, if not return zeros
4955 if ((status & SCU_RAM_INIT_COMPLETED) != SCU_RAM_INIT_COMPLETED)
4957 *value = 0x00000000;
4961 if (offset < scic_controller_get_scratch_ram_size(controller))
4963 if(offset <= SCU_MAX_ZPT_DWORD_INDEX)
4965 zpt_index = offset + (offset - (offset % 4)) + 4;
4967 *value = scu_controller_scratch_ram_register_read(scic_controller,zpt_index);
4969 else //offset > SCU_MAX_ZPT_DWORD_INDEX
4971 offset = offset - 132;
4973 zpt_index = offset + (offset - (offset % 4)) + 4;
4975 *value = scu_controller_scratch_ram_register_read_ext(scic_controller,zpt_index);
4982 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
4986 // ---------------------------------------------------------------------------
4988 SCI_STATUS scic_controller_write_scratch_ram_dword(
4989 SCI_CONTROLLER_HANDLE_T controller,
4996 if (offset < scic_controller_get_scratch_ram_size(controller))
4998 SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5000 if(offset <= SCU_MAX_ZPT_DWORD_INDEX)
5002 zpt_index = offset + (offset - (offset % 4)) + 4;
5004 scu_controller_scratch_ram_register_write(scic_controller,zpt_index,value);
5006 else //offset > SCU_MAX_ZPT_DWORD_INDEX
5008 offset = offset - 132;
5010 zpt_index = offset + (offset - (offset % 4)) + 4;
5012 scu_controller_scratch_ram_register_write_ext(scic_controller,zpt_index,value);
5020 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
5024 // ---------------------------------------------------------------------------
5026 SCI_STATUS scic_controller_suspend(
5027 SCI_CONTROLLER_HANDLE_T controller
5030 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
5033 // As a precaution, disable interrupts. The user is required
5034 // to re-enable interrupts if so desired after the call.
5035 scic_controller_disable_interrupts(controller);
5037 // Stop all the timers
5038 // Maybe change the states of the objects to avoid processing stuff.
5041 // Suspend the Ports in order to ensure no unexpected
5042 // frame reception occurs on the links from the target
5043 for (index = 0; index < SCI_MAX_PORTS; index++)
5044 scic_sds_port_suspend_port_task_scheduler(
5045 &(this_controller->port_table[index]));
5047 // Disable/Reset the completion queue and unsolicited frame
5049 SMU_CQGR_WRITE(this_controller, 0x00000000);
5050 SCU_UFQGP_WRITE(this_controller, 0x00000000);
5052 // Clear any interrupts that may be pending or may have been generated
5053 // by setting CQGR and CQPR back to 0
5054 SMU_ISR_WRITE(this_controller, 0xFFFFFFFF);
5056 //reset the software get pointer to completion queue.
5057 this_controller->completion_queue_get = 0;
5062 // ---------------------------------------------------------------------------
5064 SCI_STATUS scic_controller_resume(
5065 SCI_CONTROLLER_HANDLE_T controller
5068 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
5071 // Initialize the completion queue and unsolicited frame queue.
5072 scic_sds_controller_initialize_completion_queue(this_controller);
5073 scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
5075 this_controller->restrict_completions = FALSE;
5077 // Release the port suspensions to allow for further successful
5079 for (index = 0; index < SCI_MAX_PORTS; index++)
5080 scic_sds_port_resume_port_task_scheduler(
5081 &(this_controller->port_table[index]));
5083 //check the link layer status register DWORD sync acquired bit to detect
5084 //link down event. If there is any link down event happened during controller
5085 //suspension, restart phy state machine.
5086 for (index = 0; index < SCI_MAX_PHYS; index ++)
5088 SCIC_SDS_PHY_T * curr_phy = &this_controller->phy_table[index];
5089 U32 link_layer_status = SCU_SAS_LLSTA_READ(curr_phy);
5091 if ((link_layer_status & SCU_SAS_LLSTA_DWORD_SYNCA_BIT) == 0)
5093 //Need to put the phy back to start OOB. Then an appropriate link event
5094 //message will be send to scic user.
5095 scic_sds_phy_restart_starting_state(curr_phy);
5102 // ---------------------------------------------------------------------------
5104 SCI_STATUS scic_controller_transition(
5105 SCI_CONTROLLER_HANDLE_T controller,
5106 BOOL restrict_completions
5109 SCI_STATUS result = SCI_FAILURE_INVALID_STATE;
5110 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
5114 sci_base_object_get_logger(controller),
5115 SCIC_LOG_OBJECT_CONTROLLER,
5116 "scic_controller_transition(0x%x) enter\n",
5120 if (this_controller->parent.state_machine.current_state_id
5121 == SCI_BASE_CONTROLLER_STATE_READY)
5123 // Ensure that there are no outstanding IO operations at this
5125 for (index = 0; index < SCI_MAX_PORTS; index++)
5127 if (this_controller->port_table[index].started_request_count != 0)
5131 scic_controller_suspend(controller);
5133 // Loop through the memory descriptor list and reprogram
5134 // the silicon memory registers accordingly.
5135 result = scic_sds_controller_validate_memory_descriptor_table(
5137 if (result == SCI_SUCCESS)
5139 scic_sds_controller_ram_initialization(this_controller);
5140 this_controller->restrict_completions = restrict_completions;
5143 scic_controller_resume(controller);
5149 // ---------------------------------------------------------------------------
5151 SCI_STATUS scic_controller_get_max_ports(
5152 SCI_CONTROLLER_HANDLE_T controller,
5156 *count = SCI_MAX_PORTS;
5160 // ---------------------------------------------------------------------------
5162 SCI_STATUS scic_controller_get_max_phys(
5163 SCI_CONTROLLER_HANDLE_T controller,
5167 *count = SCI_MAX_PHYS;
5172 //******************************************************************************
5173 //* CONTROLLER STATE MACHINE
5174 //******************************************************************************
5177 * This macro returns the maximum number of logical ports supported by the
5178 * hardware. The caller passes in the value read from the device context
5179 * capacity register and this macro will mash and shift the value
5182 #define smu_dcc_get_max_ports(dcc_value) \
5184 ( ((U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK)) \
5185 >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT ) + 1\
5189 * This macro returns the maximum number of task contexts supported by the
5190 * hardware. The caller passes in the value read from the device context
5191 * capacity register and this macro will mash and shift the value
5194 #define smu_dcc_get_max_task_context(dcc_value) \
5196 ( ((U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK)) \
5197 >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT ) + 1\
5201 * This macro returns the maximum number of remote node contexts supported
5202 * by the hardware. The caller passes in the value read from the device
5203 * context capacity register and this macro will mash and shift the value
5206 #define smu_dcc_get_max_remote_node_context(dcc_value) \
5208 ( ( (U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) )\
5209 >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT ) + 1\
5212 //*****************************************************************************
5213 //* DEFAULT STATE HANDLERS
5214 //*****************************************************************************
5217 * This method is called when the SCIC_SDS_CONTROLLER default start
5218 * io/task handler is in place.
5219 * - Issue a warning message
5221 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5222 * into a SCIC_SDS_CONTROLLER object.
5223 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
5224 * used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
5225 * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
5226 * would be cast to a SCIC_SDS_IO_REQUEST.
5227 * @param[in] io_tag This is the IO tag to be assigned to the IO request or
5228 * SCI_CONTROLLER_INVALID_IO_TAG.
5230 * @return SCI_STATUS
5231 * @retval SCI_FAILURE_INVALID_STATE
5234 SCI_STATUS scic_sds_controller_default_start_operation_handler(
5235 SCI_BASE_CONTROLLER_T *controller,
5236 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5237 SCI_BASE_REQUEST_T *io_request,
5241 SCIC_SDS_CONTROLLER_T *this_controller;
5242 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5245 sci_base_object_get_logger(this_controller),
5246 SCIC_LOG_OBJECT_CONTROLLER,
5247 "SCIC Controller requested to start an io/task from invalid state %d\n",
5248 sci_base_state_machine_get_state(
5249 scic_sds_controller_get_base_state_machine(this_controller))
5252 return SCI_FAILURE_INVALID_STATE;
5256 * This method is called when the SCIC_SDS_CONTROLLER default
5257 * request handler is in place.
5258 * - Issue a warning message
5260 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5261 * into a SCIC_SDS_CONTROLLER object.
5262 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
5263 * used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
5264 * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
5265 * would be cast to a SCIC_SDS_IO_REQUEST.
5267 * @return SCI_STATUS
5268 * @retval SCI_FAILURE_INVALID_STATE
5271 SCI_STATUS scic_sds_controller_default_request_handler(
5272 SCI_BASE_CONTROLLER_T *controller,
5273 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5274 SCI_BASE_REQUEST_T *io_request
5277 SCIC_SDS_CONTROLLER_T *this_controller;
5278 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5281 sci_base_object_get_logger(this_controller),
5282 SCIC_LOG_OBJECT_CONTROLLER,
5283 "SCIC Controller request operation from invalid state %d\n",
5284 sci_base_state_machine_get_state(
5285 scic_sds_controller_get_base_state_machine(this_controller))
5288 return SCI_FAILURE_INVALID_STATE;
5291 //*****************************************************************************
5292 //* GENERAL (COMMON) STATE HANDLERS
5293 //*****************************************************************************
5296 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5297 * reset handler is in place.
5298 * - Transition to SCI_BASE_CONTROLLER_STATE_RESETTING
5300 * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
5301 * SCIC_SDS_CONTROLLER object.
5303 * @return SCI_STATUS
5304 * @retval SCI_SUCCESS
5307 SCI_STATUS scic_sds_controller_general_reset_handler(
5308 SCI_BASE_CONTROLLER_T *controller
5311 SCIC_SDS_CONTROLLER_T *this_controller;
5312 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5315 sci_base_object_get_logger(controller),
5316 SCIC_LOG_OBJECT_CONTROLLER,
5317 "scic_sds_controller_resetting_state_enter(0x%x) enter\n",
5321 //Release resource. So far only resource to be released are timers.
5322 scic_sds_controller_release_resource(this_controller);
5324 // The reset operation is not a graceful cleanup just perform the state
5326 sci_base_state_machine_change_state(
5327 scic_sds_controller_get_base_state_machine(this_controller),
5328 SCI_BASE_CONTROLLER_STATE_RESETTING
5334 //*****************************************************************************
5335 //* RESET STATE HANDLERS
5336 //*****************************************************************************
5339 * This method is the SCIC_SDS_CONTROLLER initialize handler for the reset
5341 * - Currently this function does nothing
5343 * @param[in] controller This is the SCI_BASE_CONTROLLER object which is cast
5344 * into a SCIC_SDS_CONTROLLER object.
5346 * @return SCI_STATUS
5347 * @retval SCI_FAILURE
5349 * @todo This function is not yet implemented and is a valid request from the
5353 SCI_STATUS scic_sds_controller_reset_state_initialize_handler(
5354 SCI_BASE_CONTROLLER_T *controller
5358 SCI_STATUS result = SCI_SUCCESS;
5359 SCIC_SDS_CONTROLLER_T *this_controller;
5361 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5364 sci_base_object_get_logger(controller),
5365 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
5366 "scic_sds_controller_reset_state_initialize_handler(0x%x) enter\n",
5370 sci_base_state_machine_change_state(
5371 scic_sds_controller_get_base_state_machine(this_controller),
5372 SCI_BASE_CONTROLLER_STATE_INITIALIZING
5375 this_controller->timeout_timer = scic_cb_timer_create(
5377 scic_sds_controller_timeout_handler,
5381 scic_sds_controller_initialize_power_control(this_controller);
5383 /// todo: This should really be done in the reset state enter but
5384 /// the controller has not yet been initialized before getting
5385 /// to the reset enter state so the PCI BAR is not yet assigned
5386 scic_sds_controller_reset_hardware(this_controller);
5388 #if defined(ARLINGTON_BUILD)
5389 scic_sds_controller_lex_atux_initialization(this_controller);
5390 #elif defined(PLEASANT_RIDGE_BUILD) \
5391 || defined(PBG_HBA_A0_BUILD) \
5392 || defined(PBG_HBA_A2_BUILD)
5393 scic_sds_controller_afe_initialization(this_controller);
5394 #elif defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
5395 // There is nothing to do here for B0 since we do not have to
5396 // program the AFE registers.
5397 /// @todo The AFE settings are supposed to be correct for the B0 but
5398 /// presently they seem to be wrong.
5399 scic_sds_controller_afe_initialization(this_controller);
5400 #else // !defined(ARLINGTON_BUILD) && !defined(PLEASANT_RIDGE_BUILD)
5401 // What other systems do we want to add here?
5402 #endif // !defined(ARLINGTON_BUILD) && !defined(PLEASANT_RIDGE_BUILD)
5404 if (SCI_SUCCESS == result)
5409 // Take the hardware out of reset
5410 SMU_SMUSRCR_WRITE(this_controller, 0x00000000);
5412 /// @todo Provide meaningfull error code for hardware failure
5413 //result = SCI_FAILURE_CONTROLLER_HARDWARE;
5414 result = SCI_FAILURE;
5415 terminate_loop = 100;
5417 while (terminate_loop-- && (result != SCI_SUCCESS))
5419 // Loop until the hardware reports success
5420 scic_cb_stall_execution(SCU_CONTEXT_RAM_INIT_STALL_TIME);
5421 status = SMU_SMUCSR_READ(this_controller);
5423 if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED)
5425 result = SCI_SUCCESS;
5430 #ifdef ARLINGTON_BUILD
5431 scic_sds_controller_enable_chipwatch(this_controller);
5434 if (result == SCI_SUCCESS)
5436 U32 max_supported_ports;
5437 U32 max_supported_devices;
5438 U32 max_supported_io_requests;
5439 U32 device_context_capacity;
5441 // Determine what are the actaul device capacities that the
5442 // hardware will support
5443 device_context_capacity = SMU_DCC_READ(this_controller);
5445 max_supported_ports =
5446 smu_dcc_get_max_ports(device_context_capacity);
5447 max_supported_devices =
5448 smu_dcc_get_max_remote_node_context(device_context_capacity);
5449 max_supported_io_requests =
5450 smu_dcc_get_max_task_context(device_context_capacity);
5452 // Make all PEs that are unassigned match up with the logical ports
5453 for (index = 0; index < max_supported_ports; index++)
5457 this_controller->scu_registers->peg0.ptsg.protocol_engine[index],
5462 // Now that we have the correct hardware reported minimum values
5463 // build the MDL for the controller. Default to a performance
5465 scic_controller_set_mode(this_controller, SCI_MODE_SPEED);
5467 // Record the smaller of the two capacity values
5468 this_controller->logical_port_entries =
5469 MIN(max_supported_ports, this_controller->logical_port_entries);
5471 this_controller->task_context_entries =
5472 MIN(max_supported_io_requests, this_controller->task_context_entries);
5474 this_controller->remote_node_entries =
5475 MIN(max_supported_devices, this_controller->remote_node_entries);
5478 // Initialize hardware PCI Relaxed ordering in DMA engines
5479 if (result == SCI_SUCCESS)
5481 U32 dma_configuration;
5483 // Configure the payload DMA
5484 dma_configuration = SCU_PDMACR_READ(this_controller);
5485 dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
5486 SCU_PDMACR_WRITE(this_controller, dma_configuration);
5488 // Configure the control DMA
5489 dma_configuration = SCU_CDMACR_READ(this_controller);
5490 dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
5491 SCU_CDMACR_WRITE(this_controller, dma_configuration);
5494 // Initialize the PHYs before the PORTs because the PHY registers
5495 // are accessed during the port initialization.
5496 if (result == SCI_SUCCESS)
5498 // Initialize the phys
5500 (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS);
5503 result = scic_sds_phy_initialize(
5504 &this_controller->phy_table[index],
5505 &this_controller->scu_registers->peg0.pe[index].tl,
5506 &this_controller->scu_registers->peg0.pe[index].ll
5511 //Initialize the SGPIO Unit for HARDWARE controlled SGPIO
5512 if(result == SCI_SUCCESS)
5514 scic_sgpio_hardware_initialize(this_controller);
5517 if (result == SCI_SUCCESS)
5519 // Initialize the logical ports
5521 (index < this_controller->logical_port_entries)
5522 && (result == SCI_SUCCESS);
5525 result = scic_sds_port_initialize(
5526 &this_controller->port_table[index],
5527 &this_controller->scu_registers->peg0.ptsg.port[index],
5528 &this_controller->scu_registers->peg0.ptsg.protocol_engine,
5529 &this_controller->scu_registers->peg0.viit[index]
5534 if (SCI_SUCCESS == result)
5536 result = scic_sds_port_configuration_agent_initialize(
5538 &this_controller->port_agent
5542 // Advance the controller state machine
5543 if (result == SCI_SUCCESS)
5545 sci_base_state_machine_change_state(
5546 scic_sds_controller_get_base_state_machine(this_controller),
5547 SCI_BASE_CONTROLLER_STATE_INITIALIZED
5552 //stay in the same state and release the resource
5553 scic_sds_controller_release_resource(this_controller);
5556 sci_base_object_get_logger(controller),
5557 SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
5558 "Invalid Port Configuration from scic_sds_controller_reset_state_initialize_handler(0x%x) \n",
5567 //*****************************************************************************
5568 //* INITIALIZED STATE HANDLERS
5569 //*****************************************************************************
5572 * This method is the SCIC_SDS_CONTROLLER start handler for the initialized
5574 * - Validate we have a good memory descriptor table
5575 * - Initialze the physical memory before programming the hardware
5576 * - Program the SCU hardware with the physical memory addresses passed in
5577 * the memory descriptor table.
5578 * - Initialzie the TCi pool
5579 * - Initialize the RNi pool
5580 * - Initialize the completion queue
5581 * - Initialize the unsolicited frame data
5582 * - Take the SCU port task scheduler out of reset
5583 * - Start the first phy object.
5584 * - Transition to SCI_BASE_CONTROLLER_STATE_STARTING.
5586 * @param[in] controller This is the SCI_BASE_CONTROLLER object which is cast
5587 * into a SCIC_SDS_CONTROLLER object.
5588 * @param[in] timeout This is the allowed time for the controller object to
5589 * reach the started state.
5591 * @return SCI_STATUS
5592 * @retval SCI_SUCCESS if all of the controller start operations complete
5593 * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD if one or more of the
5594 * memory descriptor fields is invalid.
5597 SCI_STATUS scic_sds_controller_initialized_state_start_handler(
5598 SCI_BASE_CONTROLLER_T * controller,
5604 SCIC_SDS_CONTROLLER_T * this_controller;
5606 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5608 // Make sure that the SCI User filled in the memory descriptor table correctly
5609 result = scic_sds_controller_validate_memory_descriptor_table(this_controller);
5611 if (result == SCI_SUCCESS)
5613 // The memory descriptor list looks good so program the hardware
5614 scic_sds_controller_ram_initialization(this_controller);
5617 if (SCI_SUCCESS == result)
5619 // Build the TCi free pool
5620 sci_pool_initialize(this_controller->tci_pool);
5621 for (index = 0; index < this_controller->task_context_entries; index++)
5623 sci_pool_put(this_controller->tci_pool, index);
5626 // Build the RNi free pool
5627 scic_sds_remote_node_table_initialize(
5628 &this_controller->available_remote_nodes,
5629 this_controller->remote_node_entries
5633 if (SCI_SUCCESS == result)
5635 // Before anything else lets make sure we will not be interrupted
5637 scic_controller_disable_interrupts(controller);
5639 // Enable the port task scheduler
5640 scic_sds_controller_enable_port_task_scheduler(this_controller);
5642 // Assign all the task entries to this controller physical function
5643 scic_sds_controller_assign_task_entries(this_controller);
5645 // Now initialze the completion queue
5646 scic_sds_controller_initialize_completion_queue(this_controller);
5648 // Initialize the unsolicited frame queue for use
5649 scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
5651 // Setup the phy start timer
5652 result = scic_sds_controller_initialize_phy_startup(this_controller);
5655 // Start all of the ports on this controller
5658 (index < this_controller->logical_port_entries) && (result == SCI_SUCCESS);
5662 result = this_controller->port_table[index].
5663 state_handlers->parent.start_handler(&this_controller->port_table[index].parent);
5666 if (SCI_SUCCESS == result)
5668 scic_sds_controller_start_next_phy(this_controller);
5670 // See if the user requested to timeout this operation.
5672 scic_cb_timer_start(controller, this_controller->timeout_timer, timeout);
5674 sci_base_state_machine_change_state(
5675 scic_sds_controller_get_base_state_machine(this_controller),
5676 SCI_BASE_CONTROLLER_STATE_STARTING
5683 //*****************************************************************************
5684 //* STARTING STATE HANDLERS
5685 //*****************************************************************************
5688 * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
5689 * link up handler is called. This method will perform the following:
5690 * - Stop the phy timer
5691 * - Start the next phy
5692 * - Report the link up condition to the port object
5694 * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the link up
5696 * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
5697 * @param[in] phy This is the SCIC_SDS_PHY which has gone link up.
5702 void scic_sds_controller_starting_state_link_up_handler(
5703 SCIC_SDS_CONTROLLER_T *this_controller,
5704 SCIC_SDS_PORT_T *port,
5708 scic_sds_controller_phy_timer_stop(this_controller);
5710 this_controller->port_agent.link_up_handler(
5711 this_controller, &this_controller->port_agent, port, phy
5713 //scic_sds_port_link_up(port, phy);
5715 scic_sds_controller_start_next_phy(this_controller);
5719 * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
5720 * link down handler is called.
5721 * - Report the link down condition to the port object
5723 * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the
5724 * link down notification.
5725 * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
5726 * @param[in] phy This is the SCIC_SDS_PHY which has gone link down.
5731 void scic_sds_controller_starting_state_link_down_handler(
5732 SCIC_SDS_CONTROLLER_T *this_controller,
5733 SCIC_SDS_PORT_T *port,
5737 this_controller->port_agent.link_down_handler(
5738 this_controller, &this_controller->port_agent, port, phy
5740 //scic_sds_port_link_down(port, phy);
5743 //*****************************************************************************
5744 //* READY STATE HANDLERS
5745 //*****************************************************************************
5748 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5749 * stop handler is called.
5750 * - Start the timeout timer
5751 * - Transition to SCI_BASE_CONTROLLER_STATE_STOPPING.
5753 * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
5754 * SCIC_SDS_CONTROLLER object.
5755 * @param[in] timeout The timeout for when the stop operation should report a
5758 * @return SCI_STATUS
5759 * @retval SCI_SUCCESS
5762 SCI_STATUS scic_sds_controller_ready_state_stop_handler(
5763 SCI_BASE_CONTROLLER_T *controller,
5767 SCIC_SDS_CONTROLLER_T *this_controller;
5768 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5770 // See if the user requested to timeout this operation
5772 scic_cb_timer_start(controller, this_controller->timeout_timer, timeout);
5774 sci_base_state_machine_change_state(
5775 scic_sds_controller_get_base_state_machine(this_controller),
5776 SCI_BASE_CONTROLLER_STATE_STOPPING
5783 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5784 * and the start io handler is called.
5785 * - Start the io request on the remote device
5787 * - assign the io_request to the io_request_table
5788 * - post the request to the hardware
5790 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5791 * into a SCIC_SDS_CONTROLLER object.
5792 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5793 * SCIC_SDS_REMOTE_DEVICE object.
5794 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5795 * SCIC_SDS_IO_REQUEST object.
5796 * @param[in] io_tag This is the IO tag to be assigned to the IO request or
5797 * SCI_CONTROLLER_INVALID_IO_TAG.
5799 * @return SCI_STATUS
5800 * @retval SCI_SUCCESS if the start io operation succeeds
5801 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
5802 * allocated for the io request.
5803 * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
5804 * state to accept io requests.
5806 * @todo How does the io_tag parameter get assigned to the io request?
5809 SCI_STATUS scic_sds_controller_ready_state_start_io_handler(
5810 SCI_BASE_CONTROLLER_T *controller,
5811 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5812 SCI_BASE_REQUEST_T *io_request,
5818 SCIC_SDS_CONTROLLER_T *this_controller;
5819 SCIC_SDS_REQUEST_T *the_request;
5820 SCIC_SDS_REMOTE_DEVICE_T *the_device;
5822 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5823 the_request = (SCIC_SDS_REQUEST_T *)io_request;
5824 the_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
5826 status = scic_sds_remote_device_start_io(this_controller, the_device, the_request);
5828 if (status == SCI_SUCCESS)
5830 this_controller->io_request_table[
5831 scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5833 scic_sds_controller_post_request(
5835 scic_sds_request_get_post_context(the_request)
5843 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5844 * and the complete io handler is called.
5845 * - Complete the io request on the remote device
5847 * - remove the io_request to the io_request_table
5849 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5850 * into a SCIC_SDS_CONTROLLER object.
5851 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5852 * SCIC_SDS_REMOTE_DEVICE object.
5853 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5854 * SCIC_SDS_IO_REQUEST object.
5856 * @return SCI_STATUS
5857 * @retval SCI_SUCCESS if the start io operation succeeds
5858 * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
5859 * state to accept io requests.
5862 SCI_STATUS scic_sds_controller_ready_state_complete_io_handler(
5863 SCI_BASE_CONTROLLER_T *controller,
5864 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5865 SCI_BASE_REQUEST_T *io_request
5870 SCIC_SDS_CONTROLLER_T *this_controller;
5871 SCIC_SDS_REQUEST_T *the_request;
5872 SCIC_SDS_REMOTE_DEVICE_T *the_device;
5874 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5875 the_request = (SCIC_SDS_REQUEST_T *)io_request;
5876 the_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
5878 status = scic_sds_remote_device_complete_io(
5879 this_controller, the_device, the_request);
5881 if (status == SCI_SUCCESS)
5883 index = scic_sds_io_tag_get_index(the_request->io_tag);
5884 this_controller->io_request_table[index] = SCI_INVALID_HANDLE;
5891 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5892 * and the continue io handler is called.
5894 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5895 * into a SCIC_SDS_CONTROLLER object.
5896 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5897 * SCIC_SDS_REMOTE_DEVICE object.
5898 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5899 * SCIC_SDS_IO_REQUEST object.
5901 * @return SCI_STATUS
5904 SCI_STATUS scic_sds_controller_ready_state_continue_io_handler(
5905 SCI_BASE_CONTROLLER_T *controller,
5906 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5907 SCI_BASE_REQUEST_T *io_request
5910 SCIC_SDS_CONTROLLER_T *this_controller;
5911 SCIC_SDS_REQUEST_T *the_request;
5913 the_request = (SCIC_SDS_REQUEST_T *)io_request;
5914 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
5916 this_controller->io_request_table[
5917 scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5919 scic_sds_controller_post_request(
5921 scic_sds_request_get_post_context(the_request)
5928 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5929 * and the start task handler is called.
5930 * - The remote device is requested to start the task request
5932 * - assign the task to the io_request_table
5933 * - post the request to the SCU hardware
5935 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
5936 * into a SCIC_SDS_CONTROLLER object.
5937 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
5938 * SCIC_SDS_REMOTE_DEVICE object.
5939 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
5940 * SCIC_SDS_IO_REQUEST object.
5941 * @param[in] task_tag This is the task tag to be assigned to the task request
5942 * or SCI_CONTROLLER_INVALID_IO_TAG.
5944 * @return SCI_STATUS
5945 * @retval SCI_SUCCESS if the start io operation succeeds
5946 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
5947 * allocated for the io request.
5948 * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
5949 * state to accept io requests.
5951 * @todo How does the io tag get assigned in this code path?
5954 SCI_STATUS scic_sds_controller_ready_state_start_task_handler(
5955 SCI_BASE_CONTROLLER_T *controller,
5956 SCI_BASE_REMOTE_DEVICE_T *remote_device,
5957 SCI_BASE_REQUEST_T *io_request,
5961 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)
5963 SCIC_SDS_REQUEST_T *the_request = (SCIC_SDS_REQUEST_T *)
5965 SCIC_SDS_REMOTE_DEVICE_T *the_device = (SCIC_SDS_REMOTE_DEVICE_T *)
5969 status = scic_sds_remote_device_start_task(
5970 this_controller, the_device, the_request
5973 if (status == SCI_SUCCESS)
5975 this_controller->io_request_table[
5976 scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5978 scic_sds_controller_post_request(
5980 scic_sds_request_get_post_context(the_request)
5983 else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS)
5985 this_controller->io_request_table[
5986 scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
5988 //We will let framework know this task request started successfully,
5989 //although core is still woring on starting the request (to post tc when
5991 status = SCI_SUCCESS;
5997 * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
5998 * and the terminate request handler is called.
5999 * - call the io request terminate function
6001 * - post the terminate request to the SCU hardware
6003 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6004 * into a SCIC_SDS_CONTROLLER object.
6005 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6006 * SCIC_SDS_REMOTE_DEVICE object.
6007 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
6008 * SCIC_SDS_IO_REQUEST object.
6010 * @return SCI_STATUS
6011 * @retval SCI_SUCCESS if the start io operation succeeds
6012 * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
6013 * state to accept io requests.
6016 SCI_STATUS scic_sds_controller_ready_state_terminate_request_handler(
6017 SCI_BASE_CONTROLLER_T *controller,
6018 SCI_BASE_REMOTE_DEVICE_T *remote_device,
6019 SCI_BASE_REQUEST_T *io_request
6022 SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)
6024 SCIC_SDS_REQUEST_T *the_request = (SCIC_SDS_REQUEST_T *)
6028 status = scic_sds_io_request_terminate(the_request);
6029 if (status == SCI_SUCCESS)
6031 // Utilize the original post context command and or in the POST_TC_ABORT
6032 // request sub-type.
6033 scic_sds_controller_post_request(
6035 scic_sds_request_get_post_context(the_request)
6036 | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT
6044 * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
6045 * link up handler is called. This method will perform the following:
6046 * - Stop the phy timer
6047 * - Start the next phy
6048 * - Report the link up condition to the port object
6050 * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the link up
6052 * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
6053 * @param[in] phy This is the SCIC_SDS_PHY which has gone link up.
6058 void scic_sds_controller_ready_state_link_up_handler(
6059 SCIC_SDS_CONTROLLER_T *this_controller,
6060 SCIC_SDS_PORT_T *port,
6064 this_controller->port_agent.link_up_handler(
6065 this_controller, &this_controller->port_agent, port, phy
6070 * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
6071 * link down handler is called.
6072 * - Report the link down condition to the port object
6074 * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the
6075 * link down notification.
6076 * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
6077 * @param[in] phy This is the SCIC_SDS_PHY which has gone link down.
6082 void scic_sds_controller_ready_state_link_down_handler(
6083 SCIC_SDS_CONTROLLER_T *this_controller,
6084 SCIC_SDS_PORT_T *port,
6088 this_controller->port_agent.link_down_handler(
6089 this_controller, &this_controller->port_agent, port, phy
6093 //*****************************************************************************
6094 //* STOPPING STATE HANDLERS
6095 //*****************************************************************************
6098 * This method is called when the SCIC_SDS_CONTROLLER is in a stopping state
6099 * and the complete io handler is called.
6100 * - This function is not yet implemented
6102 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6103 * into a SCIC_SDS_CONTROLLER object.
6104 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6105 * SCIC_SDS_REMOTE_DEVICE object.
6106 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
6107 * SCIC_SDS_IO_REQUEST object.
6109 * @return SCI_STATUS
6110 * @retval SCI_FAILURE
6113 SCI_STATUS scic_sds_controller_stopping_state_complete_io_handler(
6114 SCI_BASE_CONTROLLER_T *controller,
6115 SCI_BASE_REMOTE_DEVICE_T *remote_device,
6116 SCI_BASE_REQUEST_T *io_request
6119 SCIC_SDS_CONTROLLER_T *this_controller;
6120 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
6122 /// @todo Implement this function
6127 * This method is called when the SCIC_SDS_CONTROLLER is in a stopping state
6128 * and the a remote device has stopped.
6130 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6131 * into a SCIC_SDS_CONTROLLER object.
6132 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6133 * SCIC_SDS_REMOTE_DEVICE object.
6138 void scic_sds_controller_stopping_state_device_stopped_handler(
6139 SCIC_SDS_CONTROLLER_T * controller,
6140 SCIC_SDS_REMOTE_DEVICE_T * remote_device
6143 if (!scic_sds_controller_has_remote_devices_stopping(controller))
6145 sci_base_state_machine_change_state(
6146 &controller->parent.state_machine,
6147 SCI_BASE_CONTROLLER_STATE_STOPPED
6152 //*****************************************************************************
6153 //* STOPPED STATE HANDLERS
6154 //*****************************************************************************
6156 //*****************************************************************************
6157 //* FAILED STATE HANDLERS
6158 //*****************************************************************************
6161 * This method is called when the SCIC_SDS_CONTROLLER failed state start
6162 * io/task handler is in place.
6163 * - Issue a warning message
6165 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6166 * into a SCIC_SDS_CONTROLLER object.
6167 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
6168 * used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
6169 * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
6170 * would be cast to a SCIC_SDS_IO_REQUEST.
6171 * @param[in] io_tag This is the IO tag to be assigned to the IO request or
6172 * SCI_CONTROLLER_INVALID_IO_TAG.
6174 * @return SCI_FAILURE
6175 * @retval SCI_FAILURE
6178 SCI_STATUS scic_sds_controller_failed_state_start_operation_handler(
6179 SCI_BASE_CONTROLLER_T *controller,
6180 SCI_BASE_REMOTE_DEVICE_T *remote_device,
6181 SCI_BASE_REQUEST_T *io_request,
6185 SCIC_SDS_CONTROLLER_T *this_controller;
6186 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
6189 sci_base_object_get_logger(this_controller),
6190 SCIC_LOG_OBJECT_CONTROLLER,
6191 "SCIC Controller requested to start an io/task from failed state %d\n",
6192 sci_base_state_machine_get_state(
6193 scic_sds_controller_get_base_state_machine(this_controller))
6200 * This method is called when the SCIC_SDS_CONTROLLER is in the failed state
6201 * reset handler is in place.
6202 * - Transition to SCI_BASE_CONTROLLER_STATE_RESETTING
6204 * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
6205 * SCIC_SDS_CONTROLLER object.
6207 * @return SCI_STATUS
6208 * @retval SCI_FAILURE if fatal memory error occurred
6211 SCI_STATUS scic_sds_controller_failed_state_reset_handler(
6212 SCI_BASE_CONTROLLER_T *controller
6215 SCIC_SDS_CONTROLLER_T *this_controller;
6216 this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
6218 if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR) {
6220 sci_base_object_get_logger(controller),
6221 SCIC_LOG_OBJECT_CONTROLLER,
6222 "scic_sds_controller_resetting_state_enter(0x%x) enter\n not allowed with fatal memory error",
6228 return scic_sds_controller_general_reset_handler(controller);
6233 * This method is called when the SCIC_SDS_CONTROLLER is in the failed state
6234 * and the terminate request handler is called.
6235 * - call the io request terminate function
6237 * - post the terminate request to the SCU hardware
6239 * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
6240 * into a SCIC_SDS_CONTROLLER object.
6241 * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
6242 * SCIC_SDS_REMOTE_DEVICE object.
6243 * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
6244 * SCIC_SDS_IO_REQUEST object.
6246 * @return SCI_STATUS
6247 * @retval SCI_SUCCESS if the start io operation succeeds
6248 * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
6249 * state to accept io requests.
6252 SCI_STATUS scic_sds_controller_failed_state_terminate_request_handler(
6253 SCI_BASE_CONTROLLER_T *controller,
6254 SCI_BASE_REMOTE_DEVICE_T *remote_device,
6255 SCI_BASE_REQUEST_T *io_request
6258 SCIC_SDS_REQUEST_T *the_request = (SCIC_SDS_REQUEST_T *)
6261 return scic_sds_io_request_terminate(the_request);
6264 SCIC_SDS_CONTROLLER_STATE_HANDLER_T
6265 scic_sds_controller_state_handler_table[SCI_BASE_CONTROLLER_MAX_STATES] =
6267 // SCI_BASE_CONTROLLER_STATE_INITIAL
6274 scic_sds_controller_default_start_operation_handler,
6275 scic_sds_controller_default_start_operation_handler,
6276 scic_sds_controller_default_request_handler,
6277 scic_sds_controller_default_request_handler,
6278 scic_sds_controller_default_request_handler,
6282 scic_sds_controller_default_request_handler,
6288 // SCI_BASE_CONTROLLER_STATE_RESET
6294 scic_sds_controller_reset_state_initialize_handler,
6295 scic_sds_controller_default_start_operation_handler,
6296 scic_sds_controller_default_start_operation_handler,
6297 scic_sds_controller_default_request_handler,
6298 scic_sds_controller_default_request_handler,
6299 scic_sds_controller_default_request_handler,
6303 scic_sds_controller_default_request_handler,
6309 // SCI_BASE_CONTROLLER_STATE_INITIALIZING
6316 scic_sds_controller_default_start_operation_handler,
6317 scic_sds_controller_default_start_operation_handler,
6318 scic_sds_controller_default_request_handler,
6319 scic_sds_controller_default_request_handler,
6320 scic_sds_controller_default_request_handler,
6324 scic_sds_controller_default_request_handler,
6330 // SCI_BASE_CONTROLLER_STATE_INITIALIZED
6333 scic_sds_controller_initialized_state_start_handler,
6337 scic_sds_controller_default_start_operation_handler,
6338 scic_sds_controller_default_start_operation_handler,
6339 scic_sds_controller_default_request_handler,
6340 scic_sds_controller_default_request_handler,
6341 scic_sds_controller_default_request_handler,
6345 scic_sds_controller_default_request_handler,
6351 // SCI_BASE_CONTROLLER_STATE_STARTING
6358 scic_sds_controller_default_start_operation_handler,
6359 scic_sds_controller_default_start_operation_handler,
6360 scic_sds_controller_default_request_handler,
6361 scic_sds_controller_default_request_handler,
6362 scic_sds_controller_default_request_handler,
6366 scic_sds_controller_default_request_handler,
6367 scic_sds_controller_starting_state_link_up_handler,
6368 scic_sds_controller_starting_state_link_down_handler,
6372 // SCI_BASE_CONTROLLER_STATE_READY
6376 scic_sds_controller_ready_state_stop_handler,
6377 scic_sds_controller_general_reset_handler,
6379 scic_sds_controller_ready_state_start_io_handler,
6380 scic_sds_controller_default_start_operation_handler,
6381 scic_sds_controller_ready_state_complete_io_handler,
6382 scic_sds_controller_default_request_handler,
6383 scic_sds_controller_ready_state_continue_io_handler,
6384 scic_sds_controller_ready_state_start_task_handler,
6385 scic_sds_controller_ready_state_complete_io_handler
6387 scic_sds_controller_ready_state_terminate_request_handler,
6388 scic_sds_controller_ready_state_link_up_handler,
6389 scic_sds_controller_ready_state_link_down_handler,
6393 // SCI_BASE_CONTROLLER_STATE_RESETTING
6400 scic_sds_controller_default_start_operation_handler,
6401 scic_sds_controller_default_start_operation_handler,
6402 scic_sds_controller_default_request_handler,
6403 scic_sds_controller_default_request_handler,
6404 scic_sds_controller_default_request_handler,
6408 scic_sds_controller_default_request_handler,
6414 // SCI_BASE_CONTROLLER_STATE_STOPPING
6421 scic_sds_controller_default_start_operation_handler,
6422 scic_sds_controller_default_start_operation_handler,
6423 scic_sds_controller_stopping_state_complete_io_handler,
6424 scic_sds_controller_default_request_handler,
6425 scic_sds_controller_default_request_handler,
6429 scic_sds_controller_default_request_handler,
6433 scic_sds_controller_stopping_state_device_stopped_handler
6435 // SCI_BASE_CONTROLLER_STATE_STOPPED
6440 scic_sds_controller_failed_state_reset_handler,
6442 scic_sds_controller_default_start_operation_handler,
6443 scic_sds_controller_default_start_operation_handler,
6444 scic_sds_controller_default_request_handler,
6445 scic_sds_controller_default_request_handler,
6446 scic_sds_controller_default_request_handler,
6450 scic_sds_controller_default_request_handler,
6456 // SCI_BASE_CONTROLLER_STATE_FAILED
6461 scic_sds_controller_general_reset_handler,
6463 scic_sds_controller_failed_state_start_operation_handler,
6464 scic_sds_controller_failed_state_start_operation_handler,
6465 scic_sds_controller_default_request_handler,
6466 scic_sds_controller_default_request_handler,
6467 scic_sds_controller_default_request_handler,
6471 scic_sds_controller_failed_state_terminate_request_handler,
6479 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6480 * entry to the SCI_BASE_CONTROLLER_STATE_INITIAL.
6481 * - Set the state handlers to the controllers initial state.
6483 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6484 * SCIC_SDS_CONTROLLER object.
6488 * @todo This function should initialze the controller object.
6491 void scic_sds_controller_initial_state_enter(
6492 SCI_BASE_OBJECT_T *object
6495 SCIC_SDS_CONTROLLER_T *this_controller;
6496 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6498 scic_sds_controller_set_base_state_handlers(
6499 this_controller, SCI_BASE_CONTROLLER_STATE_INITIAL);
6501 sci_base_state_machine_change_state(
6502 &this_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_RESET);
6506 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6507 * entry to the SCI_BASE_CONTROLLER_STATE_RESET.
6508 * - Set the state handlers to the controllers reset state.
6510 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6511 * SCIC_SDS_CONTROLLER object.
6516 void scic_sds_controller_reset_state_enter(
6517 SCI_BASE_OBJECT_T *object
6521 SCIC_SDS_CONTROLLER_T *this_controller;
6522 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6524 scic_sds_controller_set_base_state_handlers(
6525 this_controller, SCI_BASE_CONTROLLER_STATE_RESET);
6527 scic_sds_port_configuration_agent_construct(&this_controller->port_agent);
6529 // Construct the ports for this controller
6530 for (index = 0; index < (SCI_MAX_PORTS + 1); index++)
6532 scic_sds_port_construct(
6533 &this_controller->port_table[index],
6534 (index == SCI_MAX_PORTS) ? SCIC_SDS_DUMMY_PORT : index,
6539 // Construct the phys for this controller
6540 for (index = 0; index < SCI_MAX_PHYS; index++)
6542 // Add all the PHYs to the dummy port
6543 scic_sds_phy_construct(
6544 &this_controller->phy_table[index],
6545 &this_controller->port_table[SCI_MAX_PORTS],
6550 this_controller->invalid_phy_mask = 0;
6552 // Set the default maximum values
6553 this_controller->completion_event_entries = SCU_EVENT_COUNT;
6554 this_controller->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT;
6555 this_controller->remote_node_entries = SCI_MAX_REMOTE_DEVICES;
6556 this_controller->logical_port_entries = SCI_MAX_PORTS;
6557 this_controller->task_context_entries = SCU_IO_REQUEST_COUNT;
6558 this_controller->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT;
6559 this_controller->uf_control.address_table.count= SCU_UNSOLICITED_FRAME_COUNT;
6561 // Initialize the User and OEM parameters to default values.
6562 scic_sds_controller_set_default_config_parameters(this_controller);
6566 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6567 * entry to the SCI_BASE_CONTROLLER_STATE_INITIALIZING.
6568 * - Set the state handlers to the controllers initializing state.
6570 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6571 * SCIC_SDS_CONTROLLER object.
6576 void scic_sds_controller_initializing_state_enter(
6577 SCI_BASE_OBJECT_T *object
6580 SCIC_SDS_CONTROLLER_T *this_controller;
6581 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6583 scic_sds_controller_set_base_state_handlers(
6584 this_controller, SCI_BASE_CONTROLLER_STATE_INITIALIZING);
6588 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6589 * entry to the SCI_BASE_CONTROLLER_STATE_INITIALIZED.
6590 * - Set the state handlers to the controllers initialized state.
6592 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6593 * SCIC_SDS_CONTROLLER object.
6598 void scic_sds_controller_initialized_state_enter(
6599 SCI_BASE_OBJECT_T *object
6602 SCIC_SDS_CONTROLLER_T *this_controller;
6603 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6605 scic_sds_controller_set_base_state_handlers(
6606 this_controller, SCI_BASE_CONTROLLER_STATE_INITIALIZED);
6610 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6611 * entry to the SCI_BASE_CONTROLLER_STATE_STARTING.
6612 * - Set the state handlers to the controllers starting state.
6614 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6615 * SCIC_SDS_CONTROLLER object.
6620 void scic_sds_controller_starting_state_enter(
6621 SCI_BASE_OBJECT_T *object
6624 SCIC_SDS_CONTROLLER_T *this_controller;
6625 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6627 scic_sds_controller_set_base_state_handlers(
6628 this_controller, SCI_BASE_CONTROLLER_STATE_STARTING);
6633 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
6634 * from the SCI_BASE_CONTROLLER_STATE_STARTING.
6635 * - This function stops the controller starting timeout timer.
6637 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6638 * SCIC_SDS_CONTROLLER object.
6643 void scic_sds_controller_starting_state_exit(
6644 SCI_BASE_OBJECT_T *object
6647 SCIC_SDS_CONTROLLER_T *this_controller;
6648 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6650 scic_cb_timer_stop(object, this_controller->timeout_timer);
6652 // We are done with this timer since we are exiting the starting
6653 // state so remove it
6654 scic_cb_timer_destroy(
6656 this_controller->phy_startup_timer
6659 this_controller->phy_startup_timer = NULL;
6663 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6664 * entry to the SCI_BASE_CONTROLLER_STATE_READY.
6665 * - Set the state handlers to the controllers ready state.
6667 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6668 * SCIC_SDS_CONTROLLER object.
6673 void scic_sds_controller_ready_state_enter(
6674 SCI_BASE_OBJECT_T *object
6677 U32 clock_gating_unit_value;
6678 SCIC_SDS_CONTROLLER_T *this_controller;
6679 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6681 scic_sds_controller_set_base_state_handlers(
6682 this_controller, SCI_BASE_CONTROLLER_STATE_READY);
6685 * enable clock gating for power control of the scu unit
6687 clock_gating_unit_value = SMU_CGUCR_READ(this_controller);
6689 clock_gating_unit_value &= ~( SMU_CGUCR_GEN_BIT(REGCLK_ENABLE)
6690 | SMU_CGUCR_GEN_BIT(TXCLK_ENABLE)
6691 | SMU_CGUCR_GEN_BIT(XCLK_ENABLE) );
6692 clock_gating_unit_value |= SMU_CGUCR_GEN_BIT(IDLE_ENABLE);
6694 SMU_CGUCR_WRITE(this_controller, clock_gating_unit_value);
6696 //set the default interrupt coalescence number and timeout value.
6697 scic_controller_set_interrupt_coalescence(
6698 this_controller, 0x10, 250);
6702 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
6703 * from the SCI_BASE_CONTROLLER_STATE_READY.
6704 * - This function does nothing.
6706 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6707 * SCIC_SDS_CONTROLLER object.
6712 void scic_sds_controller_ready_state_exit(
6713 SCI_BASE_OBJECT_T *object
6716 U32 clock_gating_unit_value;
6717 SCIC_SDS_CONTROLLER_T *this_controller;
6718 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6721 * restore clock gating for power control of the scu unit
6723 clock_gating_unit_value = SMU_CGUCR_READ(this_controller);
6725 clock_gating_unit_value &= ~SMU_CGUCR_GEN_BIT(IDLE_ENABLE);
6726 clock_gating_unit_value |= ( SMU_CGUCR_GEN_BIT(REGCLK_ENABLE)
6727 | SMU_CGUCR_GEN_BIT(TXCLK_ENABLE)
6728 | SMU_CGUCR_GEN_BIT(XCLK_ENABLE) );
6730 SMU_CGUCR_WRITE(this_controller, clock_gating_unit_value);
6732 //disable interrupt coalescence.
6733 scic_controller_set_interrupt_coalescence(this_controller, 0, 0);
6737 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6738 * entry to the SCI_BASE_CONTROLLER_STATE_READY.
6739 * - Set the state handlers to the controllers ready state.
6740 * - Stop all of the remote devices on this controller
6741 * - Stop the ports on this controller
6742 * - Stop the phys on this controller
6744 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6745 * SCIC_SDS_CONTROLLER object.
6750 void scic_sds_controller_stopping_state_enter(
6751 SCI_BASE_OBJECT_T *object
6754 SCIC_SDS_CONTROLLER_T *this_controller;
6755 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6757 scic_sds_controller_set_base_state_handlers(
6758 this_controller, SCI_BASE_CONTROLLER_STATE_STOPPING);
6760 // Stop all of the components for this controller in the reverse order
6761 // from which they are initialized.
6762 scic_sds_controller_stop_devices(this_controller);
6763 scic_sds_controller_stop_ports(this_controller);
6765 if (!scic_sds_controller_has_remote_devices_stopping(this_controller))
6767 sci_base_state_machine_change_state(
6768 &this_controller->parent.state_machine,
6769 SCI_BASE_CONTROLLER_STATE_STOPPED
6775 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
6776 * from the SCI_BASE_CONTROLLER_STATE_STOPPING.
6777 * - This function stops the controller stopping timeout timer.
6779 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6780 * SCIC_SDS_CONTROLLER object.
6785 void scic_sds_controller_stopping_state_exit(
6786 SCI_BASE_OBJECT_T *object
6789 SCIC_SDS_CONTROLLER_T *this_controller;
6790 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6792 scic_cb_timer_stop(this_controller, this_controller->timeout_timer);
6796 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6797 * entry to the SCI_BASE_CONTROLLER_STATE_STOPPED.
6798 * - Set the state handlers to the controllers stopped state.
6800 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6801 * SCIC_SDS_CONTROLLER object.
6806 void scic_sds_controller_stopped_state_enter(
6807 SCI_BASE_OBJECT_T *object
6810 SCIC_SDS_CONTROLLER_T *this_controller;
6811 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6813 scic_sds_controller_set_base_state_handlers(
6814 this_controller, SCI_BASE_CONTROLLER_STATE_STOPPED);
6816 // We are done with this timer until the next timer we initialize
6817 scic_cb_timer_destroy(
6819 this_controller->timeout_timer
6821 this_controller->timeout_timer = NULL;
6823 // Controller has stopped so disable all the phys on this controller
6824 scic_sds_controller_stop_phys(this_controller);
6826 scic_sds_port_configuration_agent_destroy(
6828 &this_controller->port_agent
6831 scic_cb_controller_stop_complete(this_controller, SCI_SUCCESS);
6835 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6836 * entry to the SCI_BASE_CONTROLLER_STATE_RESETTING.
6837 * - Set the state handlers to the controllers resetting state.
6838 * - Write to the SCU hardware reset register to force a reset
6839 * - Transition to the SCI_BASE_CONTROLLER_STATE_RESET
6841 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6842 * SCIC_SDS_CONTROLLER object.
6847 void scic_sds_controller_resetting_state_enter(
6848 SCI_BASE_OBJECT_T *object
6851 SCIC_SDS_CONTROLLER_T *this_controller;
6852 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6855 sci_base_object_get_logger(this_controller),
6856 SCIC_LOG_OBJECT_CONTROLLER,
6857 "scic_sds_controller_resetting_state_enter(0x%x) enter\n",
6861 scic_sds_controller_set_base_state_handlers(
6862 this_controller, SCI_BASE_CONTROLLER_STATE_RESETTING);
6864 scic_sds_controller_reset_hardware(this_controller);
6866 sci_base_state_machine_change_state(
6867 scic_sds_controller_get_base_state_machine(this_controller),
6868 SCI_BASE_CONTROLLER_STATE_RESET
6873 SCI_STATUS scic_sds_abort_reqests(
6874 SCIC_SDS_CONTROLLER_T * controller,
6875 SCIC_SDS_REMOTE_DEVICE_T * remote_device,
6876 SCIC_SDS_PORT_T * port
6879 SCI_STATUS status = SCI_SUCCESS;
6880 SCI_STATUS terminate_status = SCI_SUCCESS;
6881 SCIC_SDS_REQUEST_T *the_request;
6885 if (remote_device != NULL)
6886 request_count = remote_device->started_request_count;
6887 else if (port != NULL)
6888 request_count = port->started_request_count;
6890 request_count = SCI_MAX_IO_REQUESTS;
6894 (index < SCI_MAX_IO_REQUESTS) && (request_count > 0);
6897 the_request = controller->io_request_table[index];
6899 if (the_request != NULL)
6901 if (the_request->target_device == remote_device
6902 || the_request->target_device->owning_port == port
6903 || (remote_device == NULL && port == NULL))
6905 terminate_status = scic_controller_terminate_request(
6907 the_request->target_device,
6911 if (terminate_status != SCI_SUCCESS)
6912 status = terminate_status;
6922 SCI_STATUS scic_sds_terminate_reqests(
6923 SCIC_SDS_CONTROLLER_T *this_controller,
6924 SCIC_SDS_REMOTE_DEVICE_T *this_remote_device,
6925 SCIC_SDS_PORT_T *this_port
6928 SCI_STATUS status = SCI_SUCCESS;
6929 SCI_STATUS abort_status = SCI_SUCCESS;
6931 // move all request to abort state
6932 abort_status = scic_sds_abort_reqests(this_controller, this_remote_device, this_port);
6934 if (abort_status != SCI_SUCCESS)
6935 status = abort_status;
6937 //move all request to complete state
6938 if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR)
6939 abort_status = scic_sds_abort_reqests(this_controller, this_remote_device, this_port);
6941 if (abort_status != SCI_SUCCESS)
6942 status = abort_status;
6948 SCI_STATUS scic_sds_terminate_all_requests(
6949 SCIC_SDS_CONTROLLER_T * controller
6952 return scic_sds_terminate_reqests(controller, NULL, NULL);
6956 * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
6957 * entry to the SCI_BASE_CONTROLLER_STATE_FAILED.
6958 * - Set the state handlers to the controllers failed state.
6960 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
6961 * SCIC_SDS_CONTROLLER object.
6966 void scic_sds_controller_failed_state_enter(
6967 SCI_BASE_OBJECT_T *object
6970 SCIC_SDS_CONTROLLER_T *this_controller;
6971 this_controller= (SCIC_SDS_CONTROLLER_T *)object;
6973 scic_sds_controller_set_base_state_handlers(
6974 this_controller, SCI_BASE_CONTROLLER_STATE_FAILED);
6976 if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR)
6977 scic_sds_terminate_all_requests(this_controller);
6979 scic_sds_controller_release_resource(this_controller);
6981 //notify framework the controller failed.
6982 scic_cb_controller_error(this_controller,
6983 this_controller->parent.error);
6986 // ---------------------------------------------------------------------------
6989 scic_sds_controller_state_table[SCI_BASE_CONTROLLER_MAX_STATES] =
6992 SCI_BASE_CONTROLLER_STATE_INITIAL,
6993 scic_sds_controller_initial_state_enter,
6997 SCI_BASE_CONTROLLER_STATE_RESET,
6998 scic_sds_controller_reset_state_enter,
7002 SCI_BASE_CONTROLLER_STATE_INITIALIZING,
7003 scic_sds_controller_initializing_state_enter,
7007 SCI_BASE_CONTROLLER_STATE_INITIALIZED,
7008 scic_sds_controller_initialized_state_enter,
7012 SCI_BASE_CONTROLLER_STATE_STARTING,
7013 scic_sds_controller_starting_state_enter,
7014 scic_sds_controller_starting_state_exit,
7017 SCI_BASE_CONTROLLER_STATE_READY,
7018 scic_sds_controller_ready_state_enter,
7019 scic_sds_controller_ready_state_exit,
7022 SCI_BASE_CONTROLLER_STATE_RESETTING,
7023 scic_sds_controller_resetting_state_enter,
7027 SCI_BASE_CONTROLLER_STATE_STOPPING,
7028 scic_sds_controller_stopping_state_enter,
7029 scic_sds_controller_stopping_state_exit,
7032 SCI_BASE_CONTROLLER_STATE_STOPPED,
7033 scic_sds_controller_stopped_state_enter,
7037 SCI_BASE_CONTROLLER_STATE_FAILED,
7038 scic_sds_controller_failed_state_enter,