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