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