1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0 3 * 4 * This file is provided under a dual BSD/GPLv2 license. When using or 5 * redistributing this file, you may do so under either license. 6 * 7 * GPL LICENSE SUMMARY 8 * 9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of version 2 of the GNU General Public License as 13 * published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 23 * The full GNU General Public License is included in this distribution 24 * in the file called LICENSE.GPL. 25 * 26 * BSD LICENSE 27 * 28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 35 * * Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * * Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in 39 * the documentation and/or other materials provided with the 40 * distribution. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 */ 54 55 #include <sys/cdefs.h> 56 /** 57 * @file 58 * 59 * @brief This file contains the implementation of the SCIC_SDS_PHY public and 60 * protected methods. 61 */ 62 63 #include <dev/isci/scil/scic_user_callback.h> 64 #include <dev/isci/scil/scic_phy.h> 65 #include <dev/isci/scil/scic_sds_phy.h> 66 #include <dev/isci/scil/scic_sds_port.h> 67 #include <dev/isci/scil/scic_sds_controller_registers.h> 68 #include <dev/isci/scil/scic_sds_phy_registers.h> 69 #include <dev/isci/scil/scic_sds_logger.h> 70 #include <dev/isci/scil/scic_sds_remote_node_context.h> 71 #include <dev/isci/scil/sci_util.h> 72 #include <dev/isci/scil/scic_sds_controller.h> 73 #include <dev/isci/scil/scu_event_codes.h> 74 #include <dev/isci/scil/sci_base_state.h> 75 #include <dev/isci/scil/intel_ata.h> 76 #include <dev/isci/scil/intel_sata.h> 77 #include <dev/isci/scil/sci_base_state_machine.h> 78 #include <dev/isci/scil/scic_sds_port_registers.h> 79 80 #define SCIC_SDS_PHY_MIN_TIMER_COUNT (SCI_MAX_PHYS) 81 #define SCIC_SDS_PHY_MAX_TIMER_COUNT (SCI_MAX_PHYS) 82 83 // Maximum arbitration wait time in micro-seconds 84 #define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700) 85 86 #define AFE_REGISTER_WRITE_DELAY 10 87 88 //***************************************************************************** 89 //* SCIC SDS PHY Internal Methods 90 //***************************************************************************** 91 92 /** 93 * @brief This method will initialize the phy transport layer registers 94 * 95 * @param[in] this_phy 96 * @param[in] transport_layer_registers 97 * 98 * @return SCI_STATUS 99 */ 100 static 101 SCI_STATUS scic_sds_phy_transport_layer_initialization( 102 SCIC_SDS_PHY_T *this_phy, 103 SCU_TRANSPORT_LAYER_REGISTERS_T *transport_layer_registers 104 ) 105 { 106 U32 tl_control; 107 108 SCIC_LOG_TRACE(( 109 sci_base_object_get_logger(this_phy), 110 SCIC_LOG_OBJECT_PHY, 111 "scic_sds_phy_link_layer_initialization(this_phy:0x%x, link_layer_registers:0x%x)\n", 112 this_phy, transport_layer_registers 113 )); 114 115 this_phy->transport_layer_registers = transport_layer_registers; 116 117 SCU_STPTLDARNI_WRITE(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); 118 119 // Hardware team recommends that we enable the STP prefetch for all transports 120 tl_control = SCU_TLCR_READ(this_phy); 121 tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH); 122 SCU_TLCR_WRITE(this_phy, tl_control); 123 124 return SCI_SUCCESS; 125 } 126 127 /** 128 * @brief This method will initialize the phy link layer registers 129 * 130 * @param[in] this_phy 131 * @param[in] link_layer_registers 132 * 133 * @return SCI_STATUS 134 */ 135 static 136 SCI_STATUS scic_sds_phy_link_layer_initialization( 137 SCIC_SDS_PHY_T *this_phy, 138 SCU_LINK_LAYER_REGISTERS_T *link_layer_registers 139 ) 140 { 141 U32 phy_configuration; 142 SAS_CAPABILITIES_T phy_capabilities; 143 U32 parity_check = 0; 144 U32 parity_count = 0; 145 U32 link_layer_control; 146 U32 phy_timer_timeout_values; 147 U32 clksm_value = 0; 148 149 SCIC_LOG_TRACE(( 150 sci_base_object_get_logger(this_phy), 151 SCIC_LOG_OBJECT_PHY, 152 "scic_sds_phy_link_layer_initialization(this_phy:0x%x, link_layer_registers:0x%x)\n", 153 this_phy, link_layer_registers 154 )); 155 156 this_phy->link_layer_registers = link_layer_registers; 157 158 // Set our IDENTIFY frame data 159 #define SCI_END_DEVICE 0x01 160 161 SCU_SAS_TIID_WRITE( 162 this_phy, 163 ( SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) 164 | SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) 165 | SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) 166 | SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) 167 | SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE) ) 168 ); 169 170 // Write the device SAS Address 171 SCU_SAS_TIDNH_WRITE(this_phy, 0xFEDCBA98); 172 SCU_SAS_TIDNL_WRITE(this_phy, this_phy->phy_index); 173 174 // Write the source SAS Address 175 SCU_SAS_TISSAH_WRITE( 176 this_phy, 177 this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[ 178 this_phy->phy_index].sas_address.sci_format.high 179 ); 180 SCU_SAS_TISSAL_WRITE( 181 this_phy, 182 this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[ 183 this_phy->phy_index].sas_address.sci_format.low 184 ); 185 186 // Clear and Set the PHY Identifier 187 SCU_SAS_TIPID_WRITE(this_phy, 0x00000000); 188 SCU_SAS_TIPID_WRITE(this_phy, SCU_SAS_TIPID_GEN_VALUE(ID, this_phy->phy_index)); 189 190 // Change the initial state of the phy configuration register 191 phy_configuration = SCU_SAS_PCFG_READ(this_phy); 192 193 // Hold OOB state machine in reset 194 phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); 195 SCU_SAS_PCFG_WRITE(this_phy, phy_configuration); 196 197 // Configure the SNW capabilities 198 phy_capabilities.u.all = 0; 199 phy_capabilities.u.bits.start = 1; 200 phy_capabilities.u.bits.gen3_without_ssc_supported = 1; 201 phy_capabilities.u.bits.gen2_without_ssc_supported = 1; 202 phy_capabilities.u.bits.gen1_without_ssc_supported = 1; 203 204 /* 205 * Set up SSC settings according to version of OEM Parameters. 206 */ 207 { 208 U8 header_version, enable_sata, enable_sas, 209 sata_spread, sas_type, sas_spread; 210 OEM_SSC_PARAMETERS_T ssc; 211 212 header_version = this_phy->owning_port->owning_controller-> 213 oem_parameters_version; 214 215 ssc.bf.ssc_sata_tx_spread_level = 216 this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sata_tx_spread_level; 217 ssc.bf.ssc_sas_tx_spread_level = 218 this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sas_tx_spread_level; 219 ssc.bf.ssc_sas_tx_type = 220 this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sas_tx_type; 221 enable_sata = enable_sas = sata_spread = sas_type = sas_spread = 0; 222 223 if (header_version == SCI_OEM_PARAM_VER_1_0) 224 { 225 /* 226 * Version 1.0 is merely turning SSC on to default values.; 227 */ 228 if (ssc.do_enable_ssc != 0) 229 { 230 enable_sas = enable_sata = TRUE; 231 sas_type = 0x0; // Downspreading 232 sata_spread = 0x2; // +0 to -1419 PPM 233 sas_spread = 0x2; // +0 to -1419 PPM 234 } 235 } 236 else // header_version >= SCI_OEM_PARAM_VER_1_1 237 { 238 /* 239 * Version 1.1 can turn on SAS and SATA independently and 240 * specify spread levels. Also can specify spread type for SAS. 241 */ 242 if ((sata_spread = ssc.bf.ssc_sata_tx_spread_level) != 0) 243 enable_sata = TRUE; // Downspreading only 244 if ((sas_spread = ssc.bf.ssc_sas_tx_spread_level) != 0) 245 { 246 enable_sas = TRUE; 247 sas_type = ssc.bf.ssc_sas_tx_type; 248 } 249 } 250 251 if (enable_sas == TRUE) 252 { 253 U32 reg_val = scu_afe_register_read( 254 this_phy->owning_port->owning_controller, 255 scu_afe_xcvr[this_phy->phy_index]. 256 afe_xcvr_control0); 257 reg_val |= (0x00100000 | (((U32)sas_type) << 19)); 258 scu_afe_register_write( 259 this_phy->owning_port->owning_controller, 260 scu_afe_xcvr[this_phy->phy_index].afe_xcvr_control0, 261 reg_val); 262 263 reg_val = scu_afe_register_read( 264 this_phy->owning_port->owning_controller, 265 scu_afe_xcvr[this_phy->phy_index]. 266 afe_tx_ssc_control); 267 reg_val |= (((U32)(sas_spread)) << 8); 268 scu_afe_register_write( 269 this_phy->owning_port->owning_controller, 270 scu_afe_xcvr[this_phy->phy_index].afe_tx_ssc_control, 271 reg_val); 272 phy_capabilities.u.bits.gen3_with_ssc_supported = 1; 273 phy_capabilities.u.bits.gen2_with_ssc_supported = 1; 274 phy_capabilities.u.bits.gen1_with_ssc_supported = 1; 275 } 276 277 if (enable_sata == TRUE) 278 { 279 U32 reg_val = scu_afe_register_read( 280 this_phy->owning_port->owning_controller, 281 scu_afe_xcvr[this_phy->phy_index]. 282 afe_tx_ssc_control); 283 reg_val |= (U32)sata_spread; 284 scu_afe_register_write( 285 this_phy->owning_port->owning_controller, 286 scu_afe_xcvr[this_phy->phy_index].afe_tx_ssc_control, 287 reg_val); 288 289 reg_val = scu_link_layer_register_read( 290 this_phy, 291 stp_control); 292 reg_val |= (U32)(1 << 12); 293 scu_link_layer_register_write( 294 this_phy, 295 stp_control, 296 reg_val); 297 } 298 } 299 300 // The SAS specification indicates that the phy_capabilities that 301 // are transmitted shall have an even parity. Calculate the parity. 302 parity_check = phy_capabilities.u.all; 303 while (parity_check != 0) 304 { 305 if (parity_check & 0x1) 306 parity_count++; 307 parity_check >>= 1; 308 } 309 310 // If parity indicates there are an odd number of bits set, then 311 // set the parity bit to 1 in the phy capabilities. 312 if ((parity_count % 2) != 0) 313 phy_capabilities.u.bits.parity = 1; 314 315 SCU_SAS_PHYCAP_WRITE(this_phy, phy_capabilities.u.all); 316 317 // Set the enable spinup period but disable the ability to send notify enable spinup 318 SCU_SAS_ENSPINUP_WRITE( 319 this_phy, 320 SCU_ENSPINUP_GEN_VAL( 321 COUNT, 322 this_phy->owning_port->owning_controller->user_parameters.sds1. 323 phys[this_phy->phy_index].notify_enable_spin_up_insertion_frequency 324 ) 325 ); 326 327 // Write the ALIGN Insertion Ferequency for connected phy and inpendent of connected state 328 clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL ( 329 CONNECTED, 330 this_phy->owning_port->owning_controller->user_parameters.sds1. 331 phys[this_phy->phy_index].in_connection_align_insertion_frequency 332 ); 333 334 clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL ( 335 GENERAL, 336 this_phy->owning_port->owning_controller->user_parameters.sds1. 337 phys[this_phy->phy_index].align_insertion_frequency 338 ); 339 340 SCU_SAS_CLKSM_WRITE ( this_phy, clksm_value); 341 342 343 #if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) 344 /// @todo Provide a way to write this register correctly 345 scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421); 346 #elif defined(PBG_BUILD) 347 if ( 348 (this_phy->owning_port->owning_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) 349 || (this_phy->owning_port->owning_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1) 350 ) 351 { 352 scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x04210400); 353 scu_link_layer_register_write(this_phy, sas_primitive_timeout, 0x20A7C05); 354 } 355 else 356 { 357 scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421); 358 } 359 #else 360 /// @todo Provide a way to write this register correctly 361 scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x0e739ce7); 362 #endif 363 364 link_layer_control = SCU_SAS_LLCTL_GEN_VAL( 365 NO_OUTBOUND_TASK_TIMEOUT, 366 (U8) this_phy->owning_port->owning_controller-> 367 user_parameters.sds1.no_outbound_task_timeout 368 ); 369 370 #if PHY_MAX_LINK_SPEED_GENERATION == SCIC_SDS_PARM_GEN1_SPEED 371 #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1 372 #elif PHY_MAX_LINK_SPEED_GENERATION == SCIC_SDS_PARM_GEN2_SPEED 373 #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2 374 #else 375 #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3 376 #endif // PHY_MAX_LINK_SPEED_GENERATION 377 378 if (this_phy->owning_port->owning_controller->user_parameters.sds1. 379 phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED) 380 { 381 link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( 382 MAX_LINK_RATE, COMPILED_MAX_LINK_RATE 383 ); 384 } 385 else if (this_phy->owning_port->owning_controller->user_parameters.sds1. 386 phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED) 387 { 388 link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( 389 MAX_LINK_RATE, 390 MIN( 391 SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2, 392 COMPILED_MAX_LINK_RATE) 393 ); 394 } 395 else 396 { 397 link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( 398 MAX_LINK_RATE, 399 MIN( 400 SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1, 401 COMPILED_MAX_LINK_RATE) 402 ); 403 } 404 405 scu_link_layer_register_write( 406 this_phy, link_layer_control, link_layer_control 407 ); 408 409 phy_timer_timeout_values = scu_link_layer_register_read( 410 this_phy, 411 phy_timer_timeout_values 412 ); 413 414 // Clear the default 0x36 (54us) RATE_CHANGE timeout value. 415 phy_timer_timeout_values &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF); 416 417 // Set RATE_CHANGE timeout value to 0x3B (59us). This ensures SCU can 418 // lock with 3Gb drive when SCU max rate is set to 1.5Gb. 419 phy_timer_timeout_values |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B); 420 421 scu_link_layer_register_write( 422 this_phy, phy_timer_timeout_values, phy_timer_timeout_values 423 ); 424 425 // Program the max ARB time for the PHY to 700us so we inter-operate with 426 // the PMC expander which shuts down PHYs if the expander PHY generates too 427 // many breaks. This time value will guarantee that the initiator PHY will 428 // generate the break. 429 #if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) 430 scu_link_layer_register_write( 431 this_phy, 432 maximum_arbitration_wait_timer_timeout, 433 SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME 434 ); 435 #endif // defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) 436 437 // Disable the link layer hang detection timer 438 scu_link_layer_register_write( 439 this_phy, link_layer_hang_detection_timeout, 0x00000000 440 ); 441 442 // We can exit the initial state to the stopped state 443 sci_base_state_machine_change_state( 444 scic_sds_phy_get_base_state_machine(this_phy), 445 SCI_BASE_PHY_STATE_STOPPED 446 ); 447 448 return SCI_SUCCESS; 449 } 450 451 /** 452 * This function will handle the sata SIGNATURE FIS timeout condition. It 453 * will restart the starting substate machine since we dont know what has 454 * actually happening. 455 * 456 * @param[in] cookie This object is cast to the SCIC_SDS_PHY_T object. 457 * 458 * @return none 459 */ 460 void scic_sds_phy_sata_timeout( SCI_OBJECT_HANDLE_T cookie) 461 { 462 SCIC_SDS_PHY_T * this_phy = (SCIC_SDS_PHY_T *)cookie; 463 464 SCIC_LOG_INFO(( 465 sci_base_object_get_logger(this_phy), 466 SCIC_LOG_OBJECT_PHY, 467 "SCIC SDS Phy 0x%x did not receive signature fis before timeout.\n", 468 this_phy 469 )); 470 471 sci_base_state_machine_stop( 472 scic_sds_phy_get_starting_substate_machine(this_phy)); 473 474 sci_base_state_machine_change_state( 475 scic_sds_phy_get_base_state_machine(this_phy), 476 SCI_BASE_PHY_STATE_STARTING 477 ); 478 } 479 480 //***************************************************************************** 481 //* SCIC SDS PHY External Methods 482 //***************************************************************************** 483 484 /** 485 * @brief This method returns the object size for a phy object. 486 * 487 * @return U32 488 */ 489 U32 scic_sds_phy_get_object_size(void) 490 { 491 return sizeof(SCIC_SDS_PHY_T); 492 } 493 494 /** 495 * @brief This method returns the minimum number of timers required for a 496 * phy object. 497 * 498 * @return U32 499 */ 500 U32 scic_sds_phy_get_min_timer_count(void) 501 { 502 return SCIC_SDS_PHY_MIN_TIMER_COUNT; 503 } 504 505 /** 506 * @brief This method returns the maximum number of timers required for a 507 * phy object. 508 * 509 * @return U32 510 */ 511 U32 scic_sds_phy_get_max_timer_count(void) 512 { 513 return SCIC_SDS_PHY_MAX_TIMER_COUNT; 514 } 515 516 #ifdef SCI_LOGGING 517 static 518 void scic_sds_phy_initialize_state_logging( 519 SCIC_SDS_PHY_T *this_phy 520 ) 521 { 522 sci_base_state_machine_logger_initialize( 523 &this_phy->parent.state_machine_logger, 524 &this_phy->parent.state_machine, 525 &this_phy->parent.parent, 526 scic_cb_logger_log_states, 527 "SCIC_SDS_PHY_T", "base state machine", 528 SCIC_LOG_OBJECT_PHY 529 ); 530 531 sci_base_state_machine_logger_initialize( 532 &this_phy->starting_substate_machine_logger, 533 &this_phy->starting_substate_machine, 534 &this_phy->parent.parent, 535 scic_cb_logger_log_states, 536 "SCIC_SDS_PHY_T", "starting substate machine", 537 SCIC_LOG_OBJECT_PHY 538 ); 539 } 540 #endif // SCI_LOGGING 541 542 #ifdef SCIC_DEBUG_ENABLED 543 /** 544 * Debug code to record the state transitions in the phy 545 * 546 * @param our_observer 547 * @param the_state_machine 548 */ 549 void scic_sds_phy_observe_state_change( 550 SCI_BASE_OBSERVER_T * our_observer, 551 SCI_BASE_SUBJECT_T * the_subject 552 ) 553 { 554 SCIC_SDS_PHY_T *this_phy; 555 SCI_BASE_STATE_MACHINE_T *the_state_machine; 556 557 U8 transition_requestor; 558 U32 base_state_id; 559 U32 starting_substate_id; 560 561 the_state_machine = (SCI_BASE_STATE_MACHINE_T *)the_subject; 562 this_phy = (SCIC_SDS_PHY_T *)the_state_machine->state_machine_owner; 563 564 if (the_state_machine == &this_phy->parent.state_machine) 565 { 566 transition_requestor = 0x01; 567 } 568 else if (the_state_machine == &this_phy->starting_substate_machine) 569 { 570 transition_requestor = 0x02; 571 } 572 else 573 { 574 transition_requestor = 0xFF; 575 } 576 577 base_state_id = 578 sci_base_state_machine_get_state(&this_phy->parent.state_machine); 579 starting_substate_id = 580 sci_base_state_machine_get_state(&this_phy->starting_substate_machine); 581 582 this_phy->state_record.state_transition_table[ 583 this_phy->state_record.index++] = ( (transition_requestor << 24) 584 | ((U8)base_state_id << 8) 585 | ((U8)starting_substate_id)); 586 587 this_phy->state_record.index = 588 this_phy->state_record.index & (MAX_STATE_TRANSITION_RECORD - 1); 589 590 } 591 #endif // SCIC_DEBUG_ENABLED 592 593 #ifdef SCIC_DEBUG_ENABLED 594 /** 595 * This method initializes the state record debug information for the phy 596 * object. 597 * 598 * @pre The state machines for the phy object must be constructed before this 599 * function is called. 600 * 601 * @param this_phy The phy which is being initialized. 602 */ 603 void scic_sds_phy_initialize_state_recording( 604 SCIC_SDS_PHY_T *this_phy 605 ) 606 { 607 this_phy->state_record.index = 0; 608 609 sci_base_observer_initialize( 610 &this_phy->state_record.base_state_observer, 611 scic_sds_phy_observe_state_change, 612 &this_phy->parent.state_machine.parent 613 ); 614 615 sci_base_observer_initialize( 616 &this_phy->state_record.starting_state_observer, 617 scic_sds_phy_observe_state_change, 618 &this_phy->starting_substate_machine.parent 619 ); 620 } 621 #endif // SCIC_DEBUG_ENABLED 622 623 /** 624 * @brief This method will construct the SCIC_SDS_PHY object 625 * 626 * @param[in] this_phy 627 * @param[in] owning_port 628 * @param[in] phy_index 629 * 630 * @return none 631 */ 632 void scic_sds_phy_construct( 633 SCIC_SDS_PHY_T *this_phy, 634 SCIC_SDS_PORT_T *owning_port, 635 U8 phy_index 636 ) 637 { 638 // Call the base constructor first 639 // Copy the logger from the port (this could be the dummy port) 640 sci_base_phy_construct( 641 &this_phy->parent, 642 sci_base_object_get_logger(owning_port), 643 scic_sds_phy_state_table 644 ); 645 646 // Copy the rest of the input data to our locals 647 this_phy->owning_port = owning_port; 648 this_phy->phy_index = phy_index; 649 this_phy->bcn_received_while_port_unassigned = FALSE; 650 this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; 651 this_phy->link_layer_registers = NULL; 652 this_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; 653 this_phy->sata_timeout_timer = NULL; 654 655 // Clear out the identification buffer data 656 memset(&this_phy->phy_type, 0, sizeof(this_phy->phy_type)); 657 658 // Clear out the error counter data 659 memset(this_phy->error_counter, 0, sizeof(this_phy->error_counter)); 660 661 // Initialize the substate machines 662 sci_base_state_machine_construct( 663 &this_phy->starting_substate_machine, 664 &this_phy->parent.parent, 665 scic_sds_phy_starting_substates, 666 SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL 667 ); 668 669 #ifdef SCI_LOGGING 670 scic_sds_phy_initialize_state_logging(this_phy); 671 #endif // SCI_LOGGING 672 673 #ifdef SCIC_DEBUG_ENABLED 674 scic_sds_phy_initialize_state_recording(this_phy); 675 #endif // SCIC_DEBUG_ENABLED 676 } 677 678 /** 679 * @brief This method returns the port currently containing this phy. 680 * If the phy is currently contained by the dummy port, then 681 * the phy is considered to not be part of a port. 682 * 683 * @param[in] this_phy This parameter specifies the phy for which to 684 * retrieve the containing port. 685 * 686 * @return This method returns a handle to a port that contains 687 * the supplied phy. 688 * @retval SCI_INVALID_HANDLE This value is returned if the phy is not 689 * part of a real port (i.e. it's contained in the dummy port). 690 * @retval !SCI_INVALID_HANDLE All other values indicate a handle/pointer 691 * to the port containing the phy. 692 */ 693 SCI_PORT_HANDLE_T scic_sds_phy_get_port( 694 SCIC_SDS_PHY_T *this_phy 695 ) 696 { 697 SCIC_LOG_TRACE(( 698 sci_base_object_get_logger(this_phy), 699 SCIC_LOG_OBJECT_PHY, 700 "scic_phy_get_port(0x%x) enter\n", 701 this_phy 702 )); 703 704 if (scic_sds_port_get_index(this_phy->owning_port) == SCIC_SDS_DUMMY_PORT) 705 return SCI_INVALID_HANDLE; 706 707 return this_phy->owning_port; 708 } 709 710 /** 711 * @brief This method will assign a port to the phy object. 712 * 713 * @param[in, out] this_phy This parameter specifies the phy for which 714 * to assign a port object. 715 * @param[in] the_port This parameter is the port to assing to the phy. 716 */ 717 void scic_sds_phy_set_port( 718 SCIC_SDS_PHY_T * this_phy, 719 SCIC_SDS_PORT_T * the_port 720 ) 721 { 722 this_phy->owning_port = the_port; 723 724 if (this_phy->bcn_received_while_port_unassigned) 725 { 726 this_phy->bcn_received_while_port_unassigned = FALSE; 727 scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy); 728 } 729 } 730 731 /** 732 * @brief This method will initialize the constructed phy 733 * 734 * @param[in] this_phy 735 * @param[in] link_layer_registers 736 * 737 * @return SCI_STATUS 738 */ 739 SCI_STATUS scic_sds_phy_initialize( 740 SCIC_SDS_PHY_T *this_phy, 741 void *transport_layer_registers, 742 SCU_LINK_LAYER_REGISTERS_T *link_layer_registers 743 ) 744 { 745 SCIC_LOG_TRACE(( 746 sci_base_object_get_logger(this_phy), 747 SCIC_LOG_OBJECT_PHY, 748 "scic_sds_phy_initialize(this_phy:0x%x, link_layer_registers:0x%x)\n", 749 this_phy, link_layer_registers 750 )); 751 752 // Perform the initialization of the TL hardware 753 scic_sds_phy_transport_layer_initialization(this_phy, transport_layer_registers); 754 755 // Perofrm the initialization of the PE hardware 756 scic_sds_phy_link_layer_initialization(this_phy, link_layer_registers); 757 758 // There is nothing that needs to be done in this state just 759 // transition to the stopped state. 760 sci_base_state_machine_change_state( 761 scic_sds_phy_get_base_state_machine(this_phy), 762 SCI_BASE_PHY_STATE_STOPPED 763 ); 764 765 return SCI_SUCCESS; 766 } 767 768 /** 769 * This method assigns the direct attached device ID for this phy. 770 * 771 * @param[in] this_phy The phy for which the direct attached device id is to 772 * be assigned. 773 * @param[in] device_id The direct attached device ID to assign to the phy. 774 * This will either be the RNi for the device or an invalid RNi if there 775 * is no current device assigned to the phy. 776 */ 777 void scic_sds_phy_setup_transport( 778 SCIC_SDS_PHY_T * this_phy, 779 U32 device_id 780 ) 781 { 782 U32 tl_control; 783 784 SCU_STPTLDARNI_WRITE(this_phy, device_id); 785 786 // The read should guarntee that the first write gets posted 787 // before the next write 788 tl_control = SCU_TLCR_READ(this_phy); 789 tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); 790 SCU_TLCR_WRITE(this_phy, tl_control); 791 } 792 793 /** 794 * This function will perform the register reads/writes to suspend the SCU 795 * hardware protocol engine. 796 * 797 * @param[in,out] this_phy The phy object to be suspended. 798 * 799 * @return none 800 */ 801 void scic_sds_phy_suspend( 802 SCIC_SDS_PHY_T * this_phy 803 ) 804 { 805 U32 scu_sas_pcfg_value; 806 807 scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); 808 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); 809 SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); 810 811 scic_sds_phy_setup_transport( 812 this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 813 ); 814 } 815 816 /** 817 * This function will perform the register reads/writes required to resume the 818 * SCU hardware protocol engine. 819 * 820 * @param[in,out] this_phy The phy object to resume. 821 * 822 * @return none 823 */ 824 void scic_sds_phy_resume( 825 SCIC_SDS_PHY_T * this_phy 826 ) 827 { 828 U32 scu_sas_pcfg_value; 829 830 scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); 831 832 scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); 833 834 SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); 835 } 836 837 /** 838 * @brief This method returns the local sas address assigned to this phy. 839 * 840 * @param[in] this_phy This parameter specifies the phy for which 841 * to retrieve the local SAS address. 842 * @param[out] sas_address This parameter specifies the location into 843 * which to copy the local SAS address. 844 * 845 * @return none 846 */ 847 void scic_sds_phy_get_sas_address( 848 SCIC_SDS_PHY_T *this_phy, 849 SCI_SAS_ADDRESS_T *sas_address 850 ) 851 { 852 SCIC_LOG_TRACE(( 853 sci_base_object_get_logger(this_phy), 854 SCIC_LOG_OBJECT_PHY, 855 "scic_sds_phy_get_sas_address(this_phy:0x%x, sas_address:0x%x)\n", 856 this_phy, sas_address 857 )); 858 859 sas_address->high = SCU_SAS_TISSAH_READ(this_phy); 860 sas_address->low = SCU_SAS_TISSAL_READ(this_phy); 861 } 862 863 /** 864 * @brief This method returns the remote end-point (i.e. attached) 865 * sas address assigned to this phy. 866 * 867 * @param[in] this_phy This parameter specifies the phy for which 868 * to retrieve the remote end-point SAS address. 869 * @param[out] sas_address This parameter specifies the location into 870 * which to copy the remote end-point SAS address. 871 * 872 * @return none 873 */ 874 void scic_sds_phy_get_attached_sas_address( 875 SCIC_SDS_PHY_T *this_phy, 876 SCI_SAS_ADDRESS_T *sas_address 877 ) 878 { 879 SCIC_LOG_TRACE(( 880 sci_base_object_get_logger(this_phy), 881 SCIC_LOG_OBJECT_PHY, 882 "scic_sds_phy_get_attached_sas_address(0x%x, 0x%x) enter\n", 883 this_phy, sas_address 884 )); 885 886 sas_address->high 887 = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high; 888 sas_address->low 889 = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low; 890 } 891 892 /** 893 * @brief This method returns the supported protocols assigned to 894 * this phy 895 * 896 * @param[in] this_phy 897 * @param[out] protocols 898 */ 899 void scic_sds_phy_get_protocols( 900 SCIC_SDS_PHY_T *this_phy, 901 SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols 902 ) 903 { 904 U32 tiid_value = SCU_SAS_TIID_READ(this_phy); 905 906 //Check each bit of this register. please refer to 907 //SAS Transmit Identification Register (SAS_TIID). 908 if (tiid_value & 0x2) 909 protocols->u.bits.smp_target = 1; 910 911 if (tiid_value & 0x4) 912 protocols->u.bits.stp_target = 1; 913 914 if (tiid_value & 0x8) 915 protocols->u.bits.ssp_target = 1; 916 917 if (tiid_value & 0x200) 918 protocols->u.bits.smp_initiator = 1; 919 920 if ((tiid_value & 0x400)) 921 protocols->u.bits.stp_initiator = 1; 922 923 if (tiid_value & 0x800) 924 protocols->u.bits.ssp_initiator = 1; 925 926 SCIC_LOG_TRACE(( 927 sci_base_object_get_logger(this_phy), 928 SCIC_LOG_OBJECT_PHY, 929 "scic_sds_phy_get_protocols(this_phy:0x%x, protocols:0x%x)\n", 930 this_phy, protocols->u.all 931 )); 932 } 933 934 /** 935 * This method returns the supported protocols for the attached phy. If this 936 * is a SAS phy the protocols are returned from the identify address frame. 937 * If this is a SATA phy then protocols are made up and the target phy is an 938 * STP target phy. 939 * 940 * @note The caller will get the entire set of bits for the protocol value. 941 * 942 * @param[in] this_phy The parameter is the phy object for which the attached 943 * phy protcols are to be returned. 944 * @param[out] protocols The parameter is the returned protocols for the 945 * attached phy. 946 */ 947 void scic_sds_phy_get_attached_phy_protocols( 948 SCIC_SDS_PHY_T *this_phy, 949 SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols 950 ) 951 { 952 SCIC_LOG_TRACE(( 953 sci_base_object_get_logger(this_phy), 954 SCIC_LOG_OBJECT_PHY, 955 "scic_sds_phy_get_attached_phy_protocols(this_phy:0x%x, protocols:0x%x[0x%x])\n", 956 this_phy, protocols, protocols->u.all 957 )); 958 959 protocols->u.all = 0; 960 961 if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) 962 { 963 protocols->u.all = 964 this_phy->phy_type.sas.identify_address_frame_buffer.protocols.u.all; 965 } 966 else if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) 967 { 968 protocols->u.bits.stp_target = 1; 969 } 970 } 971 972 973 /** 974 * @brief This method release resources in for a scic phy. 975 * 976 * @param[in] controller This parameter specifies the core controller, one of 977 * its phy's resources are to be released. 978 * @param[in] this_phy This parameter specifies the phy whose resource is to 979 * be released. 980 */ 981 void scic_sds_phy_release_resource( 982 SCIC_SDS_CONTROLLER_T * controller, 983 SCIC_SDS_PHY_T * this_phy 984 ) 985 { 986 SCIC_LOG_TRACE(( 987 sci_base_object_get_logger(this_phy), 988 SCIC_LOG_OBJECT_PHY, 989 "scic_sds_phy_release_resource(0x%x, 0x%x)\n", 990 controller, this_phy 991 )); 992 993 //Currently, the only resource to be released is a timer. 994 if (this_phy->sata_timeout_timer != NULL) 995 { 996 scic_cb_timer_destroy(controller, this_phy->sata_timeout_timer); 997 this_phy->sata_timeout_timer = NULL; 998 } 999 } 1000 1001 1002 //***************************************************************************** 1003 //* SCIC SDS PHY Handler Redirects 1004 //***************************************************************************** 1005 1006 /** 1007 * @brief This method will attempt to reset the phy. This 1008 * request is only valid when the phy is in an ready 1009 * state 1010 * 1011 * @param[in] this_phy 1012 * 1013 * @return SCI_STATUS 1014 */ 1015 SCI_STATUS scic_sds_phy_reset( 1016 SCIC_SDS_PHY_T * this_phy 1017 ) 1018 { 1019 SCIC_LOG_TRACE(( 1020 sci_base_object_get_logger(this_phy), 1021 SCIC_LOG_OBJECT_PHY, 1022 "scic_sds_phy_reset(this_phy:0x%08x)\n", 1023 this_phy 1024 )); 1025 1026 return this_phy->state_handlers->parent.reset_handler( 1027 &this_phy->parent 1028 ); 1029 } 1030 1031 /** 1032 * @brief This method will process the event code received. 1033 * 1034 * @param[in] this_phy 1035 * @param[in] event_code 1036 * 1037 * @return SCI_STATUS 1038 */ 1039 SCI_STATUS scic_sds_phy_event_handler( 1040 SCIC_SDS_PHY_T *this_phy, 1041 U32 event_code 1042 ) 1043 { 1044 SCIC_LOG_TRACE(( 1045 sci_base_object_get_logger(this_phy), 1046 SCIC_LOG_OBJECT_PHY, 1047 "scic_sds_phy_event_handler(this_phy:0x%08x, event_code:%x)\n", 1048 this_phy, event_code 1049 )); 1050 1051 return this_phy->state_handlers->event_handler(this_phy, event_code); 1052 } 1053 1054 /** 1055 * @brief This method will process the frame index received. 1056 * 1057 * @param[in] this_phy 1058 * @param[in] frame_index 1059 * 1060 * @return SCI_STATUS 1061 */ 1062 SCI_STATUS scic_sds_phy_frame_handler( 1063 SCIC_SDS_PHY_T *this_phy, 1064 U32 frame_index 1065 ) 1066 { 1067 SCIC_LOG_TRACE(( 1068 sci_base_object_get_logger(this_phy), 1069 SCIC_LOG_OBJECT_PHY, 1070 "scic_sds_phy_frame_handler(this_phy:0x%08x, frame_index:%d)\n", 1071 this_phy, frame_index 1072 )); 1073 1074 return this_phy->state_handlers->frame_handler(this_phy, frame_index); 1075 } 1076 1077 /** 1078 * @brief This method will give the phy permission to consume power 1079 * 1080 * @param[in] this_phy 1081 * 1082 * @return SCI_STATUS 1083 */ 1084 SCI_STATUS scic_sds_phy_consume_power_handler( 1085 SCIC_SDS_PHY_T *this_phy 1086 ) 1087 { 1088 SCIC_LOG_TRACE(( 1089 sci_base_object_get_logger(this_phy), 1090 SCIC_LOG_OBJECT_PHY, 1091 "scic_sds_phy_consume_power_handler(this_phy:0x%08x)\n", 1092 this_phy 1093 )); 1094 1095 return this_phy->state_handlers->consume_power_handler(this_phy); 1096 } 1097 1098 //***************************************************************************** 1099 //* SCIC PHY Public Methods 1100 //***************************************************************************** 1101 1102 SCI_STATUS scic_phy_get_properties( 1103 SCI_PHY_HANDLE_T phy, 1104 SCIC_PHY_PROPERTIES_T * properties 1105 ) 1106 { 1107 SCIC_SDS_PHY_T *this_phy; 1108 U8 max_speed_generation; 1109 1110 this_phy = (SCIC_SDS_PHY_T *)phy; 1111 1112 SCIC_LOG_TRACE(( 1113 sci_base_object_get_logger(this_phy), 1114 SCIC_LOG_OBJECT_PHY, 1115 "scic_phy_get_properties(0x%x, 0x%x) enter\n", 1116 this_phy, properties 1117 )); 1118 1119 if (phy == SCI_INVALID_HANDLE) 1120 { 1121 return SCI_FAILURE_INVALID_PHY; 1122 } 1123 1124 memset(properties, 0, sizeof(SCIC_PHY_PROPERTIES_T)); 1125 1126 //get max link rate of this phy set by user. 1127 max_speed_generation = 1128 this_phy->owning_port->owning_controller->user_parameters.sds1. 1129 phys[this_phy->phy_index].max_speed_generation; 1130 1131 properties->negotiated_link_rate = this_phy->max_negotiated_speed; 1132 1133 if (max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED) 1134 properties->max_link_rate = SCI_SAS_600_GB; 1135 else if (max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED) 1136 properties->max_link_rate = SCI_SAS_300_GB; 1137 else 1138 properties->max_link_rate = SCI_SAS_150_GB; 1139 1140 properties->index = this_phy->phy_index; 1141 properties->owning_port = scic_sds_phy_get_port(this_phy); 1142 1143 scic_sds_phy_get_protocols(this_phy, &properties->transmit_iaf.protocols); 1144 1145 properties->transmit_iaf.sas_address.high = 1146 this_phy->owning_port->owning_controller->oem_parameters.sds1. 1147 phys[this_phy->phy_index].sas_address.sci_format.high; 1148 1149 properties->transmit_iaf.sas_address.low = 1150 this_phy->owning_port->owning_controller->oem_parameters.sds1. 1151 phys[this_phy->phy_index].sas_address.sci_format.low; 1152 1153 return SCI_SUCCESS; 1154 } 1155 1156 // --------------------------------------------------------------------------- 1157 1158 SCI_STATUS scic_sas_phy_get_properties( 1159 SCI_PHY_HANDLE_T phy, 1160 SCIC_SAS_PHY_PROPERTIES_T * properties 1161 ) 1162 { 1163 SCIC_SDS_PHY_T *this_phy; 1164 this_phy = (SCIC_SDS_PHY_T *)phy; 1165 1166 SCIC_LOG_TRACE(( 1167 sci_base_object_get_logger(this_phy), 1168 SCIC_LOG_OBJECT_PHY, 1169 "scic_sas_phy_get_properties(0x%x, 0x%x) enter\n", 1170 this_phy, properties 1171 )); 1172 1173 if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) 1174 { 1175 memcpy( 1176 &properties->received_iaf, 1177 &this_phy->phy_type.sas.identify_address_frame_buffer, 1178 sizeof(SCI_SAS_IDENTIFY_ADDRESS_FRAME_T) 1179 ); 1180 1181 properties->received_capabilities.u.all 1182 = SCU_SAS_RECPHYCAP_READ(this_phy); 1183 1184 return SCI_SUCCESS; 1185 } 1186 1187 return SCI_FAILURE; 1188 } 1189 1190 // --------------------------------------------------------------------------- 1191 1192 SCI_STATUS scic_sata_phy_get_properties( 1193 SCI_PHY_HANDLE_T phy, 1194 SCIC_SATA_PHY_PROPERTIES_T * properties 1195 ) 1196 { 1197 SCIC_SDS_PHY_T *this_phy; 1198 this_phy = (SCIC_SDS_PHY_T *)phy; 1199 1200 SCIC_LOG_TRACE(( 1201 sci_base_object_get_logger(this_phy), 1202 SCIC_LOG_OBJECT_PHY, 1203 "scic_sata_phy_get_properties(0x%x, 0x%x) enter\n", 1204 this_phy, properties 1205 )); 1206 1207 if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) 1208 { 1209 memcpy( 1210 &properties->signature_fis, 1211 &this_phy->phy_type.sata.signature_fis_buffer, 1212 sizeof(SATA_FIS_REG_D2H_T) 1213 ); 1214 1215 /// @todo add support for port selectors. 1216 properties->is_port_selector_present = FALSE; 1217 1218 return SCI_SUCCESS; 1219 } 1220 1221 return SCI_FAILURE; 1222 } 1223 1224 // --------------------------------------------------------------------------- 1225 1226 #if !defined(DISABLE_PORT_SELECTORS) 1227 1228 SCI_STATUS scic_sata_phy_send_port_selection_signal( 1229 SCI_PHY_HANDLE_T phy 1230 ) 1231 { 1232 SCIC_SDS_PHY_T *this_phy; 1233 this_phy = (SCIC_SDS_PHY_T *)phy; 1234 1235 SCIC_LOG_TRACE(( 1236 sci_base_object_get_logger(this_phy), 1237 SCIC_LOG_OBJECT_PHY, 1238 "scic_sata_phy_send_port_selection_signals(0x%x) enter\n", 1239 this_phy 1240 )); 1241 1242 /// @todo To be implemented 1243 ASSERT(FALSE); 1244 return SCI_FAILURE; 1245 } 1246 1247 #endif // !defined(DISABLE_PORT_SELECTORS) 1248 1249 // --------------------------------------------------------------------------- 1250 1251 #if !defined(DISABLE_PHY_COUNTERS) 1252 1253 SCI_STATUS scic_phy_enable_counter( 1254 SCI_PHY_HANDLE_T phy, 1255 SCIC_PHY_COUNTER_ID_T counter_id 1256 ) 1257 { 1258 SCIC_SDS_PHY_T *this_phy; 1259 SCI_STATUS status = SCI_SUCCESS; 1260 this_phy = (SCIC_SDS_PHY_T *)phy; 1261 1262 SCIC_LOG_TRACE(( 1263 sci_base_object_get_logger(this_phy), 1264 SCIC_LOG_OBJECT_PHY, 1265 "scic_phy_enable_counter(0x%x, 0x%x) enter\n", 1266 this_phy, counter_id 1267 )); 1268 1269 switch(counter_id) 1270 { 1271 case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT: 1272 { 1273 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1274 control |= (1 << SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX); 1275 SCU_SAS_ECENCR_WRITE(this_phy, control); 1276 } 1277 break; 1278 case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT: 1279 { 1280 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1281 control |= (1 << SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX); 1282 SCU_SAS_ECENCR_WRITE(this_phy, control); 1283 } 1284 break; 1285 case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED: 1286 { 1287 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1288 control |= (1 << SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX); 1289 SCU_SAS_ECENCR_WRITE(this_phy, control); 1290 } 1291 break; 1292 case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT: 1293 { 1294 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1295 control |= (1 << SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX); 1296 SCU_SAS_ECENCR_WRITE(this_phy, control); 1297 } 1298 break; 1299 case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT: 1300 { 1301 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1302 control |= (1 << SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX); 1303 SCU_SAS_ECENCR_WRITE(this_phy, control); 1304 } 1305 break; 1306 case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED: 1307 { 1308 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1309 control |= (1 << SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX); 1310 SCU_SAS_ECENCR_WRITE(this_phy, control); 1311 } 1312 break; 1313 1314 // These error counters are enabled by default, and cannot be 1315 // disabled. Return SCI_SUCCESS to denote that they are 1316 // enabled, hiding the fact that enabling the counter is 1317 // a no-op. 1318 case SCIC_PHY_COUNTER_RECEIVED_FRAME: 1319 case SCIC_PHY_COUNTER_TRANSMITTED_FRAME: 1320 case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD: 1321 case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD: 1322 case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR: 1323 case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR: 1324 case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR: 1325 case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME: 1326 case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT: 1327 case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE: 1328 case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR: 1329 break; 1330 1331 default: 1332 status = SCI_FAILURE; 1333 break; 1334 } 1335 return status; 1336 } 1337 1338 // --------------------------------------------------------------------------- 1339 1340 SCI_STATUS scic_phy_disable_counter( 1341 SCI_PHY_HANDLE_T phy, 1342 SCIC_PHY_COUNTER_ID_T counter_id 1343 ) 1344 { 1345 SCIC_SDS_PHY_T *this_phy; 1346 SCI_STATUS status = SCI_SUCCESS; 1347 1348 this_phy = (SCIC_SDS_PHY_T *)phy; 1349 1350 SCIC_LOG_TRACE(( 1351 sci_base_object_get_logger(this_phy), 1352 SCIC_LOG_OBJECT_PHY, 1353 "scic_phy_disable_counter(0x%x, 0x%x) enter\n", 1354 this_phy, counter_id 1355 )); 1356 1357 switch(counter_id) 1358 { 1359 case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT: 1360 { 1361 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1362 control &= ~(1 << SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX); 1363 SCU_SAS_ECENCR_WRITE(this_phy, control); 1364 } 1365 break; 1366 case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT: 1367 { 1368 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1369 control &= ~(1 << SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX); 1370 SCU_SAS_ECENCR_WRITE(this_phy, control); 1371 } 1372 break; 1373 case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED: 1374 { 1375 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1376 control &= ~(1 << SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX); 1377 SCU_SAS_ECENCR_WRITE(this_phy, control); 1378 } 1379 break; 1380 case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT: 1381 { 1382 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1383 control &= ~(1 << SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX); 1384 SCU_SAS_ECENCR_WRITE(this_phy, control); 1385 } 1386 break; 1387 case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT: 1388 { 1389 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1390 control &= ~(1 << SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX); 1391 SCU_SAS_ECENCR_WRITE(this_phy, control); 1392 } 1393 break; 1394 case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED: 1395 { 1396 U32 control = SCU_SAS_ECENCR_READ(this_phy); 1397 control &= ~(1 << SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX); 1398 SCU_SAS_ECENCR_WRITE(this_phy, control); 1399 } 1400 break; 1401 1402 // These error counters cannot be disabled, so return SCI_FAILURE. 1403 case SCIC_PHY_COUNTER_RECEIVED_FRAME: 1404 case SCIC_PHY_COUNTER_TRANSMITTED_FRAME: 1405 case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD: 1406 case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD: 1407 case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR: 1408 case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR: 1409 case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR: 1410 case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME: 1411 case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT: 1412 case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE: 1413 case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR: 1414 default: 1415 status = SCI_FAILURE; 1416 break; 1417 } 1418 return status; 1419 } 1420 1421 // --------------------------------------------------------------------------- 1422 1423 SCI_STATUS scic_phy_get_counter( 1424 SCI_PHY_HANDLE_T phy, 1425 SCIC_PHY_COUNTER_ID_T counter_id, 1426 U32 * data 1427 ) 1428 { 1429 SCIC_SDS_PHY_T *this_phy; 1430 SCI_STATUS status = SCI_SUCCESS; 1431 this_phy = (SCIC_SDS_PHY_T *)phy; 1432 1433 SCIC_LOG_TRACE(( 1434 sci_base_object_get_logger(this_phy), 1435 SCIC_LOG_OBJECT_PHY, 1436 "scic_phy_get_counter(0x%x, 0x%x) enter\n", 1437 this_phy, counter_id 1438 )); 1439 1440 switch(counter_id) 1441 { 1442 case SCIC_PHY_COUNTER_RECEIVED_FRAME: 1443 *data = scu_link_layer_register_read(this_phy, received_frame_count); 1444 break; 1445 case SCIC_PHY_COUNTER_TRANSMITTED_FRAME: 1446 *data = scu_link_layer_register_read(this_phy, transmit_frame_count); 1447 break; 1448 case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD: 1449 *data = scu_link_layer_register_read(this_phy, received_dword_count); 1450 break; 1451 case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD: 1452 *data = scu_link_layer_register_read(this_phy, transmit_dword_count); 1453 break; 1454 case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR: 1455 *data = scu_link_layer_register_read(this_phy, loss_of_sync_error_count); 1456 break; 1457 case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR: 1458 *data = scu_link_layer_register_read(this_phy, running_disparity_error_count); 1459 break; 1460 case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR: 1461 *data = scu_link_layer_register_read(this_phy, received_frame_crc_error_count); 1462 break; 1463 case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT: 1464 *data = this_phy->error_counter[SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX]; 1465 break; 1466 case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT: 1467 *data = this_phy->error_counter[SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX]; 1468 break; 1469 case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED: 1470 *data = this_phy->error_counter[SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX]; 1471 break; 1472 case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT: 1473 *data = this_phy->error_counter[SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX]; 1474 break; 1475 case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT: 1476 *data = this_phy->error_counter[SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX]; 1477 break; 1478 case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED: 1479 *data = this_phy->error_counter[SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX]; 1480 break; 1481 case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME: 1482 *data = scu_link_layer_register_read(this_phy, received_short_frame_count); 1483 break; 1484 case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT: 1485 *data = scu_link_layer_register_read(this_phy, received_frame_without_credit_count); 1486 break; 1487 case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE: 1488 *data = scu_link_layer_register_read(this_phy, received_frame_after_done_count); 1489 break; 1490 case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR: 1491 *data = scu_link_layer_register_read(this_phy, phy_reset_problem_count); 1492 break; 1493 default: 1494 status = SCI_FAILURE; 1495 break; 1496 } 1497 1498 return status; 1499 } 1500 1501 // --------------------------------------------------------------------------- 1502 1503 SCI_STATUS scic_phy_clear_counter( 1504 SCI_PHY_HANDLE_T phy, 1505 SCIC_PHY_COUNTER_ID_T counter_id 1506 ) 1507 { 1508 SCIC_SDS_PHY_T *this_phy; 1509 SCI_STATUS status = SCI_SUCCESS; 1510 this_phy = (SCIC_SDS_PHY_T *)phy; 1511 1512 SCIC_LOG_TRACE(( 1513 sci_base_object_get_logger(this_phy), 1514 SCIC_LOG_OBJECT_PHY, 1515 "scic_phy_clear_counter(0x%x, 0x%x) enter\n", 1516 this_phy, counter_id 1517 )); 1518 1519 switch(counter_id) 1520 { 1521 case SCIC_PHY_COUNTER_RECEIVED_FRAME: 1522 scu_link_layer_register_write(this_phy, received_frame_count, 0); 1523 break; 1524 case SCIC_PHY_COUNTER_TRANSMITTED_FRAME: 1525 scu_link_layer_register_write(this_phy, transmit_frame_count, 0); 1526 break; 1527 case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD: 1528 scu_link_layer_register_write(this_phy, received_dword_count, 0); 1529 break; 1530 case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD: 1531 scu_link_layer_register_write(this_phy, transmit_dword_count, 0); 1532 break; 1533 case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR: 1534 scu_link_layer_register_write(this_phy, loss_of_sync_error_count, 0); 1535 break; 1536 case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR: 1537 scu_link_layer_register_write(this_phy, running_disparity_error_count, 0); 1538 break; 1539 case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR: 1540 scu_link_layer_register_write(this_phy, received_frame_crc_error_count, 0); 1541 break; 1542 case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT: 1543 this_phy->error_counter[SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX] = 0; 1544 break; 1545 case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT: 1546 this_phy->error_counter[SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX] = 0; 1547 break; 1548 case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED: 1549 this_phy->error_counter[SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX] = 0; 1550 break; 1551 case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT: 1552 this_phy->error_counter[SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX] = 0; 1553 break; 1554 case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT: 1555 this_phy->error_counter[SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX] = 0; 1556 break; 1557 case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED: 1558 this_phy->error_counter[SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX] = 0; 1559 break; 1560 case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME: 1561 scu_link_layer_register_write(this_phy, received_short_frame_count, 0); 1562 break; 1563 case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT: 1564 scu_link_layer_register_write(this_phy, received_frame_without_credit_count, 0); 1565 break; 1566 case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE: 1567 scu_link_layer_register_write(this_phy, received_frame_after_done_count, 0); 1568 break; 1569 case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR: 1570 scu_link_layer_register_write(this_phy, phy_reset_problem_count, 0); 1571 break; 1572 default: 1573 status = SCI_FAILURE; 1574 } 1575 1576 return status; 1577 } 1578 1579 #endif // !defined(DISABLE_PHY_COUNTERS) 1580 1581 SCI_STATUS scic_phy_stop( 1582 SCI_PHY_HANDLE_T phy 1583 ) 1584 { 1585 SCIC_SDS_PHY_T *this_phy; 1586 this_phy = (SCIC_SDS_PHY_T *)phy; 1587 1588 SCIC_LOG_TRACE(( 1589 sci_base_object_get_logger(this_phy), 1590 SCIC_LOG_OBJECT_PHY, 1591 "scic_phy_stop(this_phy:0x%x)\n", 1592 this_phy 1593 )); 1594 1595 return this_phy->state_handlers->parent.stop_handler(&this_phy->parent); 1596 } 1597 1598 SCI_STATUS scic_phy_start( 1599 SCI_PHY_HANDLE_T phy 1600 ) 1601 { 1602 SCIC_SDS_PHY_T *this_phy; 1603 this_phy = (SCIC_SDS_PHY_T *)phy; 1604 1605 SCIC_LOG_TRACE(( 1606 sci_base_object_get_logger(this_phy), 1607 SCIC_LOG_OBJECT_PHY, 1608 "scic_phy_start(this_phy:0x%x)\n", 1609 this_phy 1610 )); 1611 1612 return this_phy->state_handlers->parent.start_handler(&this_phy->parent); 1613 } 1614 1615 //****************************************************************************** 1616 //* PHY STATE MACHINE 1617 //****************************************************************************** 1618 1619 //*************************************************************************** 1620 //* DEFAULT HANDLERS 1621 //*************************************************************************** 1622 1623 /** 1624 * This is the default method for phy a start request. It will report a 1625 * warning and exit. 1626 * 1627 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1628 * SCIC_SDS_PHY object. 1629 * 1630 * @return SCI_STATUS 1631 * @retval SCI_FAILURE_INVALID_STATE 1632 */ 1633 SCI_STATUS scic_sds_phy_default_start_handler( 1634 SCI_BASE_PHY_T *phy 1635 ) 1636 { 1637 SCIC_SDS_PHY_T *this_phy; 1638 this_phy = (SCIC_SDS_PHY_T *)phy; 1639 1640 SCIC_LOG_WARNING(( 1641 sci_base_object_get_logger(this_phy), 1642 SCIC_LOG_OBJECT_PHY, 1643 "SCIC Phy 0x%08x requested to start from invalid state %d\n", 1644 this_phy, 1645 sci_base_state_machine_get_state(&this_phy->parent.state_machine) 1646 )); 1647 1648 return SCI_FAILURE_INVALID_STATE; 1649 1650 } 1651 1652 /** 1653 * This is the default method for phy a stop request. It will report a 1654 * warning and exit. 1655 * 1656 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1657 * SCIC_SDS_PHY object. 1658 * 1659 * @return SCI_STATUS 1660 * @retval SCI_FAILURE_INVALID_STATE 1661 */ 1662 SCI_STATUS scic_sds_phy_default_stop_handler( 1663 SCI_BASE_PHY_T *phy 1664 ) 1665 { 1666 SCIC_SDS_PHY_T *this_phy; 1667 this_phy = (SCIC_SDS_PHY_T *)phy; 1668 1669 SCIC_LOG_WARNING(( 1670 sci_base_object_get_logger(this_phy), 1671 SCIC_LOG_OBJECT_PHY, 1672 "SCIC Phy 0x%08x requested to stop from invalid state %d\n", 1673 this_phy, 1674 sci_base_state_machine_get_state(&this_phy->parent.state_machine) 1675 )); 1676 1677 return SCI_FAILURE_INVALID_STATE; 1678 } 1679 1680 /** 1681 * This is the default method for phy a reset request. It will report a 1682 * warning and exit. 1683 * 1684 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1685 * SCIC_SDS_PHY object. 1686 * 1687 * @return SCI_STATUS 1688 * @retval SCI_FAILURE_INVALID_STATE 1689 */ 1690 SCI_STATUS scic_sds_phy_default_reset_handler( 1691 SCI_BASE_PHY_T * phy 1692 ) 1693 { 1694 SCIC_SDS_PHY_T *this_phy; 1695 this_phy = (SCIC_SDS_PHY_T *)phy; 1696 1697 SCIC_LOG_WARNING(( 1698 sci_base_object_get_logger(this_phy), 1699 SCIC_LOG_OBJECT_PHY, 1700 "SCIC Phy 0x%08x requested to reset from invalid state %d\n", 1701 this_phy, 1702 sci_base_state_machine_get_state(&this_phy->parent.state_machine) 1703 )); 1704 1705 return SCI_FAILURE_INVALID_STATE; 1706 } 1707 1708 /** 1709 * This is the default method for phy a destruct request. It will report a 1710 * warning and exit. 1711 * 1712 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1713 * SCIC_SDS_PHY object. 1714 * 1715 * @return SCI_STATUS 1716 * @retval SCI_FAILURE_INVALID_STATE 1717 */ 1718 SCI_STATUS scic_sds_phy_default_destroy_handler( 1719 SCI_BASE_PHY_T *phy 1720 ) 1721 { 1722 SCIC_SDS_PHY_T *this_phy; 1723 this_phy = (SCIC_SDS_PHY_T *)phy; 1724 1725 /// @todo Implement something for the default 1726 SCIC_LOG_WARNING(( 1727 sci_base_object_get_logger(this_phy), 1728 SCIC_LOG_OBJECT_PHY, 1729 "SCIC Phy 0x%08x requested to destroy from invalid state %d\n", 1730 this_phy, 1731 sci_base_state_machine_get_state(&this_phy->parent.state_machine) 1732 )); 1733 1734 return SCI_FAILURE_INVALID_STATE; 1735 } 1736 1737 /** 1738 * This is the default method for a phy frame handling request. It will 1739 * report a warning, release the frame and exit. 1740 * 1741 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1742 * SCIC_SDS_PHY object. 1743 * @param[in] frame_index This is the frame index that was received from the 1744 * SCU hardware. 1745 * 1746 * @return SCI_STATUS 1747 * @retval SCI_FAILURE_INVALID_STATE 1748 */ 1749 SCI_STATUS scic_sds_phy_default_frame_handler( 1750 SCIC_SDS_PHY_T *this_phy, 1751 U32 frame_index 1752 ) 1753 { 1754 SCIC_LOG_WARNING(( 1755 sci_base_object_get_logger(this_phy), 1756 SCIC_LOG_OBJECT_PHY, 1757 "SCIC Phy 0x%08x received unexpected frame data %d while in state %d\n", 1758 this_phy, frame_index, 1759 sci_base_state_machine_get_state(&this_phy->parent.state_machine) 1760 )); 1761 1762 scic_sds_controller_release_frame( 1763 scic_sds_phy_get_controller(this_phy), frame_index); 1764 1765 return SCI_FAILURE_INVALID_STATE; 1766 } 1767 1768 /** 1769 * This is the default method for a phy event handler. It will report a 1770 * warning and exit. 1771 * 1772 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1773 * SCIC_SDS_PHY object. 1774 * @param[in] event_code This is the event code that was received from the SCU 1775 * hardware. 1776 * 1777 * @return SCI_STATUS 1778 * @retval SCI_FAILURE_INVALID_STATE 1779 */ 1780 SCI_STATUS scic_sds_phy_default_event_handler( 1781 SCIC_SDS_PHY_T *this_phy, 1782 U32 event_code 1783 ) 1784 { 1785 SCIC_LOG_WARNING(( 1786 sci_base_object_get_logger(this_phy), 1787 SCIC_LOG_OBJECT_PHY, 1788 "SCIC Phy 0x%08x received unexpected event status %x while in state %d\n", 1789 this_phy, event_code, 1790 sci_base_state_machine_get_state(&this_phy->parent.state_machine) 1791 )); 1792 1793 return SCI_FAILURE_INVALID_STATE; 1794 } 1795 1796 /** 1797 * This is the default method for a phy consume power handler. It will report 1798 * a warning and exit. 1799 * 1800 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1801 * SCIC_SDS_PHY object. 1802 * 1803 * @return SCI_STATUS 1804 * @retval SCI_FAILURE_INVALID_STATE 1805 */ 1806 SCI_STATUS scic_sds_phy_default_consume_power_handler( 1807 SCIC_SDS_PHY_T *this_phy 1808 ) 1809 { 1810 SCIC_LOG_WARNING(( 1811 sci_base_object_get_logger(this_phy), 1812 SCIC_LOG_OBJECT_PHY, 1813 "SCIC Phy 0x%08x given unexpected permission to consume power while in state %d\n", 1814 this_phy, 1815 sci_base_state_machine_get_state(&this_phy->parent.state_machine) 1816 )); 1817 1818 return SCI_FAILURE_INVALID_STATE; 1819 } 1820 1821 //****************************************************************************** 1822 //* PHY STOPPED STATE HANDLERS 1823 //****************************************************************************** 1824 1825 /** 1826 * This method takes the SCIC_SDS_PHY from a stopped state and attempts to 1827 * start it. 1828 * - The phy state machine is transitioned to the 1829 * SCI_BASE_PHY_STATE_STARTING. 1830 * 1831 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1832 * SCIC_SDS_PHY object. 1833 * 1834 * @return SCI_STATUS 1835 * @retval SCI_SUCCESS 1836 */ 1837 static 1838 SCI_STATUS scic_sds_phy_stopped_state_start_handler( 1839 SCI_BASE_PHY_T *phy 1840 ) 1841 { 1842 SCIC_SDS_PHY_T *this_phy; 1843 this_phy = (SCIC_SDS_PHY_T *)phy; 1844 1845 1846 1847 // Create the SIGNATURE FIS Timeout timer for this phy 1848 this_phy->sata_timeout_timer = scic_cb_timer_create( 1849 scic_sds_phy_get_controller(this_phy), 1850 scic_sds_phy_sata_timeout, 1851 this_phy 1852 ); 1853 1854 if (this_phy->sata_timeout_timer != NULL) 1855 { 1856 sci_base_state_machine_change_state( 1857 scic_sds_phy_get_base_state_machine(this_phy), 1858 SCI_BASE_PHY_STATE_STARTING 1859 ); 1860 } 1861 1862 return SCI_SUCCESS; 1863 } 1864 1865 /** 1866 * This method takes the SCIC_SDS_PHY from a stopped state and destroys it. 1867 * - This function takes no action. 1868 * 1869 * @todo Shouldn't this function transition the SCI_BASE_PHY::state_machine to 1870 * the SCI_BASE_PHY_STATE_FINAL? 1871 * 1872 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1873 * SCIC_SDS_PHY object. 1874 * 1875 * @return SCI_STATUS 1876 * @retval SCI_SUCCESS 1877 */ 1878 static 1879 SCI_STATUS scic_sds_phy_stopped_state_destroy_handler( 1880 SCI_BASE_PHY_T *phy 1881 ) 1882 { 1883 SCIC_SDS_PHY_T *this_phy; 1884 this_phy = (SCIC_SDS_PHY_T *)phy; 1885 1886 /// @todo what do we actually need to do here? 1887 return SCI_SUCCESS; 1888 } 1889 1890 //****************************************************************************** 1891 //* PHY STARTING STATE HANDLERS 1892 //****************************************************************************** 1893 1894 // All of these state handlers are mapped to the starting sub-state machine 1895 1896 //****************************************************************************** 1897 //* PHY READY STATE HANDLERS 1898 //****************************************************************************** 1899 1900 /** 1901 * This method takes the SCIC_SDS_PHY from a ready state and attempts to stop 1902 * it. 1903 * - The phy state machine is transitioned to the SCI_BASE_PHY_STATE_STOPPED. 1904 * 1905 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1906 * SCIC_SDS_PHY object. 1907 * 1908 * @return SCI_STATUS 1909 * @retval SCI_SUCCESS 1910 */ 1911 static 1912 SCI_STATUS scic_sds_phy_ready_state_stop_handler( 1913 SCI_BASE_PHY_T *phy 1914 ) 1915 { 1916 SCIC_SDS_PHY_T *this_phy; 1917 this_phy = (SCIC_SDS_PHY_T *)phy; 1918 1919 sci_base_state_machine_change_state( 1920 scic_sds_phy_get_base_state_machine(this_phy), 1921 SCI_BASE_PHY_STATE_STOPPED 1922 ); 1923 1924 scic_sds_controller_link_down( 1925 scic_sds_phy_get_controller(this_phy), 1926 scic_sds_phy_get_port(this_phy), 1927 this_phy 1928 ); 1929 1930 return SCI_SUCCESS; 1931 } 1932 1933 /** 1934 * This method takes the SCIC_SDS_PHY from a ready state and attempts to reset 1935 * it. 1936 * - The phy state machine is transitioned to the SCI_BASE_PHY_STATE_STARTING. 1937 * 1938 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 1939 * SCIC_SDS_PHY object. 1940 * 1941 * @return SCI_STATUS 1942 * @retval SCI_SUCCESS 1943 */ 1944 static 1945 SCI_STATUS scic_sds_phy_ready_state_reset_handler( 1946 SCI_BASE_PHY_T * phy 1947 ) 1948 { 1949 SCIC_SDS_PHY_T * this_phy; 1950 this_phy = (SCIC_SDS_PHY_T *)phy; 1951 1952 sci_base_state_machine_change_state( 1953 scic_sds_phy_get_base_state_machine(this_phy), 1954 SCI_BASE_PHY_STATE_RESETTING 1955 ); 1956 1957 return SCI_SUCCESS; 1958 } 1959 1960 /** 1961 * This method request the SCIC_SDS_PHY handle the received event. The only 1962 * event that we are interested in while in the ready state is the link 1963 * failure event. 1964 * - decoded event is a link failure 1965 * - transition the SCIC_SDS_PHY back to the SCI_BASE_PHY_STATE_STARTING 1966 * state. 1967 * - any other event received will report a warning message 1968 * 1969 * @param[in] phy This is the SCIC_SDS_PHY object which has received the 1970 * event. 1971 * 1972 * @return SCI_STATUS 1973 * @retval SCI_SUCCESS if the event received is a link failure 1974 * @retval SCI_FAILURE_INVALID_STATE for any other event received. 1975 */ 1976 static 1977 SCI_STATUS scic_sds_phy_ready_state_event_handler( 1978 SCIC_SDS_PHY_T *this_phy, 1979 U32 event_code 1980 ) 1981 { 1982 SCI_STATUS result = SCI_FAILURE; 1983 1984 switch (scu_get_event_code(event_code)) 1985 { 1986 case SCU_EVENT_LINK_FAILURE: 1987 // Link failure change state back to the starting state 1988 sci_base_state_machine_change_state( 1989 scic_sds_phy_get_base_state_machine(this_phy), 1990 SCI_BASE_PHY_STATE_STARTING 1991 ); 1992 1993 result = SCI_SUCCESS; 1994 break; 1995 1996 case SCU_EVENT_BROADCAST_CHANGE: 1997 // Broadcast change received. Notify the port. 1998 if (scic_sds_phy_get_port(this_phy) != SCI_INVALID_HANDLE) 1999 scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy); 2000 else 2001 this_phy->bcn_received_while_port_unassigned = TRUE; 2002 break; 2003 2004 case SCU_EVENT_ERR_CNT(RX_CREDIT_BLOCKED_RECEIVED): 2005 case SCU_EVENT_ERR_CNT(TX_DONE_CREDIT_TIMEOUT): 2006 case SCU_EVENT_ERR_CNT(RX_DONE_CREDIT_TIMEOUT): 2007 case SCU_EVENT_ERR_CNT(INACTIVITY_TIMER_EXPIRED): 2008 case SCU_EVENT_ERR_CNT(TX_DONE_ACK_NAK_TIMEOUT): 2009 case SCU_EVENT_ERR_CNT(RX_DONE_ACK_NAK_TIMEOUT): 2010 { 2011 U32 error_counter_index = 2012 scu_get_event_specifier(event_code) >> SCU_EVENT_SPECIFIC_CODE_SHIFT; 2013 2014 this_phy->error_counter[error_counter_index]++; 2015 result = SCI_SUCCESS; 2016 } 2017 break; 2018 2019 default: 2020 SCIC_LOG_WARNING(( 2021 sci_base_object_get_logger(this_phy), 2022 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS, 2023 "SCIC PHY 0x%x ready state machine received unexpected event_code %x\n", 2024 this_phy, event_code 2025 )); 2026 result = SCI_FAILURE_INVALID_STATE; 2027 break; 2028 } 2029 2030 return result; 2031 } 2032 2033 // --------------------------------------------------------------------------- 2034 2035 /** 2036 * This is the resetting state event handler. 2037 * 2038 * @param[in] this_phy This is the SCIC_SDS_PHY object which is receiving the 2039 * event. 2040 * @param[in] event_code This is the event code to be processed. 2041 * 2042 * @return SCI_STATUS 2043 * @retval SCI_FAILURE_INVALID_STATE 2044 */ 2045 static 2046 SCI_STATUS scic_sds_phy_resetting_state_event_handler( 2047 SCIC_SDS_PHY_T *this_phy, 2048 U32 event_code 2049 ) 2050 { 2051 SCI_STATUS result = SCI_FAILURE; 2052 2053 switch (scu_get_event_code(event_code)) 2054 { 2055 case SCU_EVENT_HARD_RESET_TRANSMITTED: 2056 // Link failure change state back to the starting state 2057 sci_base_state_machine_change_state( 2058 scic_sds_phy_get_base_state_machine(this_phy), 2059 SCI_BASE_PHY_STATE_STARTING 2060 ); 2061 2062 result = SCI_SUCCESS; 2063 break; 2064 2065 default: 2066 SCIC_LOG_WARNING(( 2067 sci_base_object_get_logger(this_phy), 2068 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS, 2069 "SCIC PHY 0x%x resetting state machine received unexpected event_code %x\n", 2070 this_phy, event_code 2071 )); 2072 2073 result = SCI_FAILURE_INVALID_STATE; 2074 break; 2075 } 2076 2077 return result; 2078 } 2079 2080 // --------------------------------------------------------------------------- 2081 2082 SCIC_SDS_PHY_STATE_HANDLER_T 2083 scic_sds_phy_state_handler_table[SCI_BASE_PHY_MAX_STATES] = 2084 { 2085 // SCI_BASE_PHY_STATE_INITIAL 2086 { 2087 { 2088 scic_sds_phy_default_start_handler, 2089 scic_sds_phy_default_stop_handler, 2090 scic_sds_phy_default_reset_handler, 2091 scic_sds_phy_default_destroy_handler 2092 }, 2093 scic_sds_phy_default_frame_handler, 2094 scic_sds_phy_default_event_handler, 2095 scic_sds_phy_default_consume_power_handler 2096 }, 2097 // SCI_BASE_PHY_STATE_STOPPED 2098 { 2099 { 2100 scic_sds_phy_stopped_state_start_handler, 2101 scic_sds_phy_default_stop_handler, 2102 scic_sds_phy_default_reset_handler, 2103 scic_sds_phy_stopped_state_destroy_handler 2104 }, 2105 scic_sds_phy_default_frame_handler, 2106 scic_sds_phy_default_event_handler, 2107 scic_sds_phy_default_consume_power_handler 2108 }, 2109 // SCI_BASE_PHY_STATE_STARTING 2110 { 2111 { 2112 scic_sds_phy_default_start_handler, 2113 scic_sds_phy_default_stop_handler, 2114 scic_sds_phy_default_reset_handler, 2115 scic_sds_phy_default_destroy_handler 2116 }, 2117 scic_sds_phy_default_frame_handler, 2118 scic_sds_phy_default_event_handler, 2119 scic_sds_phy_default_consume_power_handler 2120 }, 2121 // SCI_BASE_PHY_STATE_READY 2122 { 2123 { 2124 scic_sds_phy_default_start_handler, 2125 scic_sds_phy_ready_state_stop_handler, 2126 scic_sds_phy_ready_state_reset_handler, 2127 scic_sds_phy_default_destroy_handler 2128 }, 2129 scic_sds_phy_default_frame_handler, 2130 scic_sds_phy_ready_state_event_handler, 2131 scic_sds_phy_default_consume_power_handler 2132 }, 2133 // SCI_BASE_PHY_STATE_RESETTING 2134 { 2135 { 2136 scic_sds_phy_default_start_handler, 2137 scic_sds_phy_default_stop_handler, 2138 scic_sds_phy_default_reset_handler, 2139 scic_sds_phy_default_destroy_handler 2140 }, 2141 scic_sds_phy_default_frame_handler, 2142 scic_sds_phy_resetting_state_event_handler, 2143 scic_sds_phy_default_consume_power_handler 2144 }, 2145 // SCI_BASE_PHY_STATE_FINAL 2146 { 2147 { 2148 scic_sds_phy_default_start_handler, 2149 scic_sds_phy_default_stop_handler, 2150 scic_sds_phy_default_reset_handler, 2151 scic_sds_phy_default_destroy_handler 2152 }, 2153 scic_sds_phy_default_frame_handler, 2154 scic_sds_phy_default_event_handler, 2155 scic_sds_phy_default_consume_power_handler 2156 } 2157 }; 2158 2159 //**************************************************************************** 2160 //* PHY STATE PRIVATE METHODS 2161 //**************************************************************************** 2162 2163 /** 2164 * This method will stop the SCIC_SDS_PHY object. This does not reset the 2165 * protocol engine it just suspends it and places it in a state where it will 2166 * not cause the end device to power up. 2167 * 2168 * @param[in] this_phy This is the SCIC_SDS_PHY object to stop. 2169 * 2170 * @return none 2171 */ 2172 static 2173 void scu_link_layer_stop_protocol_engine( 2174 SCIC_SDS_PHY_T *this_phy 2175 ) 2176 { 2177 U32 scu_sas_pcfg_value; 2178 U32 enable_spinup_value; 2179 2180 // Suspend the protocol engine and place it in a sata spinup hold state 2181 scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); 2182 scu_sas_pcfg_value |= ( 2183 SCU_SAS_PCFG_GEN_BIT(OOB_RESET) 2184 | SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) 2185 | SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) 2186 ); 2187 SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); 2188 2189 // Disable the notify enable spinup primitives 2190 enable_spinup_value = SCU_SAS_ENSPINUP_READ(this_phy); 2191 enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE); 2192 SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup_value); 2193 } 2194 2195 /** 2196 * This method will start the OOB/SN state machine for this SCIC_SDS_PHY 2197 * object. 2198 * 2199 * @param[in] this_phy This is the SCIC_SDS_PHY object on which to start the 2200 * OOB/SN state machine. 2201 */ 2202 static 2203 void scu_link_layer_start_oob( 2204 SCIC_SDS_PHY_T *this_phy 2205 ) 2206 { 2207 U32 scu_sas_pcfg_value; 2208 2209 /* Reset OOB sequence - start */ 2210 scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); 2211 scu_sas_pcfg_value &= 2212 ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); 2213 SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); 2214 SCU_SAS_PCFG_READ(this_phy); 2215 /* Reset OOB sequence - end */ 2216 2217 /* Start OOB sequence - start */ 2218 scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); 2219 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); 2220 SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); 2221 SCU_SAS_PCFG_READ(this_phy); 2222 /* Start OOB sequence - end */ 2223 } 2224 2225 /** 2226 * This method will transmit a hard reset request on the specified phy. The 2227 * SCU hardware requires that we reset the OOB state machine and set the hard 2228 * reset bit in the phy configuration register. 2229 * We then must start OOB over with the hard reset bit set. 2230 * 2231 * @param[in] this_phy 2232 */ 2233 static 2234 void scu_link_layer_tx_hard_reset( 2235 SCIC_SDS_PHY_T *this_phy 2236 ) 2237 { 2238 U32 phy_configuration_value; 2239 2240 // SAS Phys must wait for the HARD_RESET_TX event notification to transition 2241 // to the starting state. 2242 phy_configuration_value = SCU_SAS_PCFG_READ(this_phy); 2243 phy_configuration_value |= 2244 (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | SCU_SAS_PCFG_GEN_BIT(OOB_RESET)); 2245 SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value); 2246 2247 // Now take the OOB state machine out of reset 2248 phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); 2249 phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); 2250 SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value); 2251 } 2252 2253 //**************************************************************************** 2254 //* PHY BASE STATE METHODS 2255 //**************************************************************************** 2256 2257 /** 2258 * This method will perform the actions required by the SCIC_SDS_PHY on 2259 * entering the SCI_BASE_PHY_STATE_INITIAL. 2260 * - This function sets the state handlers for the phy object base state 2261 * machine initial state. 2262 * 2263 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2264 * SCIC_SDS_PHY object. 2265 * 2266 * @return none 2267 */ 2268 static 2269 void scic_sds_phy_initial_state_enter( 2270 SCI_BASE_OBJECT_T *object 2271 ) 2272 { 2273 SCIC_SDS_PHY_T *this_phy; 2274 this_phy = (SCIC_SDS_PHY_T *)object; 2275 2276 scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_INITIAL); 2277 } 2278 2279 /** 2280 * This method will perform the actions required by the SCIC_SDS_PHY on 2281 * entering the SCI_BASE_PHY_STATE_INITIAL. 2282 * - This function sets the state handlers for the phy object base state 2283 * machine initial state. 2284 * - The SCU hardware is requested to stop the protocol engine. 2285 * 2286 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2287 * SCIC_SDS_PHY object. 2288 * 2289 * @return none 2290 */ 2291 static 2292 void scic_sds_phy_stopped_state_enter( 2293 SCI_BASE_OBJECT_T *object 2294 ) 2295 { 2296 SCIC_SDS_PHY_T *this_phy; 2297 this_phy = (SCIC_SDS_PHY_T *)object; 2298 2299 /// @todo We need to get to the controller to place this PE in a reset state 2300 scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED); 2301 2302 if (this_phy->sata_timeout_timer != NULL) 2303 { 2304 scic_cb_timer_destroy( 2305 scic_sds_phy_get_controller(this_phy), 2306 this_phy->sata_timeout_timer 2307 ); 2308 2309 this_phy->sata_timeout_timer = NULL; 2310 } 2311 2312 scu_link_layer_stop_protocol_engine(this_phy); 2313 } 2314 2315 /** 2316 * This method will perform the actions required by the SCIC_SDS_PHY on 2317 * entering the SCI_BASE_PHY_STATE_STARTING. 2318 * - This function sets the state handlers for the phy object base state 2319 * machine starting state. 2320 * - The SCU hardware is requested to start OOB/SN on this protocol engine. 2321 * - The phy starting substate machine is started. 2322 * - If the previous state was the ready state then the 2323 * SCIC_SDS_CONTROLLER is informed that the phy has gone link down. 2324 * 2325 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2326 * SCIC_SDS_PHY object. 2327 * 2328 * @return none 2329 */ 2330 static 2331 void scic_sds_phy_starting_state_enter( 2332 SCI_BASE_OBJECT_T *object 2333 ) 2334 { 2335 SCIC_SDS_PHY_T *this_phy; 2336 this_phy = (SCIC_SDS_PHY_T *)object; 2337 2338 scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STARTING); 2339 2340 scu_link_layer_stop_protocol_engine(this_phy); 2341 scu_link_layer_start_oob(this_phy); 2342 2343 // We don't know what kind of phy we are going to be just yet 2344 this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; 2345 this_phy->bcn_received_while_port_unassigned = FALSE; 2346 2347 // Change over to the starting substate machine to continue 2348 sci_base_state_machine_start(&this_phy->starting_substate_machine); 2349 2350 if (this_phy->parent.state_machine.previous_state_id 2351 == SCI_BASE_PHY_STATE_READY) 2352 { 2353 scic_sds_controller_link_down( 2354 scic_sds_phy_get_controller(this_phy), 2355 scic_sds_phy_get_port(this_phy), 2356 this_phy 2357 ); 2358 } 2359 } 2360 2361 /** 2362 * This method will perform the actions required by the SCIC_SDS_PHY on 2363 * entering the SCI_BASE_PHY_STATE_READY. 2364 * - This function sets the state handlers for the phy object base state 2365 * machine ready state. 2366 * - The SCU hardware protocol engine is resumed. 2367 * - The SCIC_SDS_CONTROLLER is informed that the phy object has gone link 2368 * up. 2369 * 2370 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2371 * SCIC_SDS_PHY object. 2372 * 2373 * @return none 2374 */ 2375 static 2376 void scic_sds_phy_ready_state_enter( 2377 SCI_BASE_OBJECT_T *object 2378 ) 2379 { 2380 SCIC_SDS_PHY_T *this_phy; 2381 this_phy = (SCIC_SDS_PHY_T *)object; 2382 2383 scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_READY); 2384 2385 scic_sds_controller_link_up( 2386 scic_sds_phy_get_controller(this_phy), 2387 scic_sds_phy_get_port(this_phy), 2388 this_phy 2389 ); 2390 } 2391 2392 /** 2393 * This method will perform the actions required by the SCIC_SDS_PHY on 2394 * exiting the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU 2395 * hardware protocol engine represented by this SCIC_SDS_PHY object. 2396 * 2397 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2398 * SCIC_SDS_PHY object. 2399 * 2400 * @return none 2401 */ 2402 static 2403 void scic_sds_phy_ready_state_exit( 2404 SCI_BASE_OBJECT_T *object 2405 ) 2406 { 2407 SCIC_SDS_PHY_T *this_phy; 2408 this_phy = (SCIC_SDS_PHY_T *)object; 2409 2410 scic_sds_phy_suspend(this_phy); 2411 } 2412 2413 /** 2414 * This method will perform the actions required by the SCIC_SDS_PHY on 2415 * entering the SCI_BASE_PHY_STATE_RESETTING. 2416 * - This function sets the state handlers for the phy object base state 2417 * machine resetting state. 2418 * 2419 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2420 * SCIC_SDS_PHY object. 2421 * 2422 * @return none 2423 */ 2424 static 2425 void scic_sds_phy_resetting_state_enter( 2426 SCI_BASE_OBJECT_T *object 2427 ) 2428 { 2429 SCIC_SDS_PHY_T * this_phy; 2430 this_phy = (SCIC_SDS_PHY_T *)object; 2431 2432 scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_RESETTING); 2433 2434 // The phy is being reset, therefore deactivate it from the port. 2435 // In the resetting state we don't notify the user regarding 2436 // link up and link down notifications. 2437 scic_sds_port_deactivate_phy(this_phy->owning_port, this_phy, FALSE); 2438 2439 if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) 2440 { 2441 scu_link_layer_tx_hard_reset(this_phy); 2442 } 2443 else 2444 { 2445 // The SCU does not need to have a descrete reset state so just go back to 2446 // the starting state. 2447 sci_base_state_machine_change_state( 2448 &this_phy->parent.state_machine, 2449 SCI_BASE_PHY_STATE_STARTING 2450 ); 2451 } 2452 } 2453 2454 /** 2455 * This method will perform the actions required by the SCIC_SDS_PHY on 2456 * entering the SCI_BASE_PHY_STATE_FINAL. 2457 * - This function sets the state handlers for the phy object base state 2458 * machine final state. 2459 * 2460 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2461 * SCIC_SDS_PHY object. 2462 * 2463 * @return none 2464 */ 2465 static 2466 void scic_sds_phy_final_state_enter( 2467 SCI_BASE_OBJECT_T *object 2468 ) 2469 { 2470 SCIC_SDS_PHY_T *this_phy; 2471 this_phy = (SCIC_SDS_PHY_T *)object; 2472 2473 scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_FINAL); 2474 2475 // Nothing to do here 2476 } 2477 2478 // --------------------------------------------------------------------------- 2479 2480 SCI_BASE_STATE_T scic_sds_phy_state_table[SCI_BASE_PHY_MAX_STATES] = 2481 { 2482 { 2483 SCI_BASE_PHY_STATE_INITIAL, 2484 scic_sds_phy_initial_state_enter, 2485 NULL, 2486 }, 2487 { 2488 SCI_BASE_PHY_STATE_STOPPED, 2489 scic_sds_phy_stopped_state_enter, 2490 NULL, 2491 }, 2492 { 2493 SCI_BASE_PHY_STATE_STARTING, 2494 scic_sds_phy_starting_state_enter, 2495 NULL, 2496 }, 2497 { 2498 SCI_BASE_PHY_STATE_READY, 2499 scic_sds_phy_ready_state_enter, 2500 scic_sds_phy_ready_state_exit, 2501 }, 2502 { 2503 SCI_BASE_PHY_STATE_RESETTING, 2504 scic_sds_phy_resetting_state_enter, 2505 NULL, 2506 }, 2507 { 2508 SCI_BASE_PHY_STATE_FINAL, 2509 scic_sds_phy_final_state_enter, 2510 NULL, 2511 } 2512 }; 2513 2514 //****************************************************************************** 2515 //* PHY STARTING SUB-STATE MACHINE 2516 //****************************************************************************** 2517 2518 //***************************************************************************** 2519 //* SCIC SDS PHY HELPER FUNCTIONS 2520 //***************************************************************************** 2521 2522 2523 /** 2524 * This method continues the link training for the phy as if it were a SAS PHY 2525 * instead of a SATA PHY. This is done because the completion queue had a SAS 2526 * PHY DETECTED event when the state machine was expecting a SATA PHY event. 2527 * 2528 * @param[in] this_phy The phy object that received SAS PHY DETECTED. 2529 * 2530 * @return none 2531 */ 2532 static 2533 void scic_sds_phy_start_sas_link_training( 2534 SCIC_SDS_PHY_T * this_phy 2535 ) 2536 { 2537 U32 phy_control; 2538 2539 phy_control = SCU_SAS_PCFG_READ(this_phy); 2540 phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD); 2541 SCU_SAS_PCFG_WRITE(this_phy, phy_control); 2542 2543 sci_base_state_machine_change_state( 2544 &this_phy->starting_substate_machine, 2545 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN 2546 ); 2547 2548 this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; 2549 } 2550 2551 /** 2552 * This method continues the link training for the phy as if it were a SATA 2553 * PHY instead of a SAS PHY. This is done because the completion queue had a 2554 * SATA SPINUP HOLD event when the state machine was expecting a SAS PHY 2555 * event. 2556 * 2557 * @param[in] this_phy The phy object that received a SATA SPINUP HOLD event 2558 * 2559 * @return none 2560 */ 2561 static 2562 void scic_sds_phy_start_sata_link_training( 2563 SCIC_SDS_PHY_T * this_phy 2564 ) 2565 { 2566 sci_base_state_machine_change_state( 2567 &this_phy->starting_substate_machine, 2568 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER 2569 ); 2570 2571 this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; 2572 } 2573 2574 /** 2575 * @brief This method performs processing common to all protocols upon 2576 * completion of link training. 2577 * 2578 * @param[in,out] this_phy This parameter specifies the phy object for which 2579 * link training has completed. 2580 * @param[in] max_link_rate This parameter specifies the maximum link 2581 * rate to be associated with this phy. 2582 * @param[in] next_state This parameter specifies the next state for the 2583 * phy's starting sub-state machine. 2584 * 2585 * @return none 2586 */ 2587 static 2588 void scic_sds_phy_complete_link_training( 2589 SCIC_SDS_PHY_T * this_phy, 2590 SCI_SAS_LINK_RATE max_link_rate, 2591 U32 next_state 2592 ) 2593 { 2594 this_phy->max_negotiated_speed = max_link_rate; 2595 2596 sci_base_state_machine_change_state( 2597 scic_sds_phy_get_starting_substate_machine(this_phy), next_state 2598 ); 2599 } 2600 2601 /** 2602 * This method restarts the SCIC_SDS_PHY objects base state machine in the 2603 * starting state from any starting substate. 2604 * 2605 * @param[in] this_phy The SCIC_SDS_PHY object to restart. 2606 * 2607 * @return none 2608 */ 2609 void scic_sds_phy_restart_starting_state( 2610 SCIC_SDS_PHY_T *this_phy 2611 ) 2612 { 2613 // Stop the current substate machine 2614 sci_base_state_machine_stop( 2615 scic_sds_phy_get_starting_substate_machine(this_phy) 2616 ); 2617 2618 // Re-enter the base state machine starting state 2619 sci_base_state_machine_change_state( 2620 scic_sds_phy_get_base_state_machine(this_phy), 2621 SCI_BASE_PHY_STATE_STARTING 2622 ); 2623 } 2624 2625 2626 //***************************************************************************** 2627 //* SCIC SDS PHY general handlers 2628 //***************************************************************************** 2629 2630 static 2631 SCI_STATUS scic_sds_phy_starting_substate_general_stop_handler( 2632 SCI_BASE_PHY_T *phy 2633 ) 2634 { 2635 SCIC_SDS_PHY_T *this_phy; 2636 this_phy = (SCIC_SDS_PHY_T *)phy; 2637 2638 sci_base_state_machine_stop( 2639 &this_phy->starting_substate_machine 2640 ); 2641 2642 sci_base_state_machine_change_state( 2643 &phy->state_machine, 2644 SCI_BASE_PHY_STATE_STOPPED 2645 ); 2646 2647 return SCI_SUCCESS; 2648 } 2649 2650 //***************************************************************************** 2651 //* SCIC SDS PHY EVENT_HANDLERS 2652 //***************************************************************************** 2653 2654 /** 2655 * This method is called when an event notification is received for the phy 2656 * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. 2657 * - decode the event 2658 * - sas phy detected causes a state transition to the wait for speed 2659 * event notification. 2660 * - any other events log a warning message and set a failure status 2661 * 2662 * @param[in] phy This SCIC_SDS_PHY object which has received an event. 2663 * @param[in] event_code This is the event code which the phy object is to 2664 * decode. 2665 * 2666 * @return SCI_STATUS 2667 * @retval SCI_SUCCESS on any valid event notification 2668 * @retval SCI_FAILURE on any unexpected event notifation 2669 */ 2670 static 2671 SCI_STATUS scic_sds_phy_starting_substate_await_ossp_event_handler( 2672 SCIC_SDS_PHY_T *this_phy, 2673 U32 event_code 2674 ) 2675 { 2676 U32 result = SCI_SUCCESS; 2677 2678 switch (scu_get_event_code(event_code)) 2679 { 2680 case SCU_EVENT_SAS_PHY_DETECTED: 2681 scic_sds_phy_start_sas_link_training(this_phy); 2682 this_phy->is_in_link_training = TRUE; 2683 break; 2684 2685 case SCU_EVENT_SATA_SPINUP_HOLD: 2686 scic_sds_phy_start_sata_link_training(this_phy); 2687 this_phy->is_in_link_training = TRUE; 2688 break; 2689 2690 default: 2691 SCIC_LOG_WARNING(( 2692 sci_base_object_get_logger(this_phy), 2693 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS, 2694 "PHY starting substate machine received unexpected event_code %x\n", 2695 event_code 2696 )); 2697 2698 result = SCI_FAILURE; 2699 break; 2700 } 2701 2702 return result; 2703 } 2704 2705 /** 2706 * This method is called when an event notification is received for the phy 2707 * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. 2708 * - decode the event 2709 * - sas phy detected returns us back to this state. 2710 * - speed event detected causes a state transition to the wait for iaf. 2711 * - identify timeout is an un-expected event and the state machine is 2712 * restarted. 2713 * - link failure events restart the starting state machine 2714 * - any other events log a warning message and set a failure status 2715 * 2716 * @param[in] phy This SCIC_SDS_PHY object which has received an event. 2717 * @param[in] event_code This is the event code which the phy object is to 2718 * decode. 2719 * 2720 * @return SCI_STATUS 2721 * @retval SCI_SUCCESS on any valid event notification 2722 * @retval SCI_FAILURE on any unexpected event notifation 2723 */ 2724 static 2725 SCI_STATUS scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler( 2726 SCIC_SDS_PHY_T *this_phy, 2727 U32 event_code 2728 ) 2729 { 2730 U32 result = SCI_SUCCESS; 2731 2732 switch (scu_get_event_code(event_code)) 2733 { 2734 case SCU_EVENT_SAS_PHY_DETECTED: 2735 // Why is this being reported again by the controller? 2736 // We would re-enter this state so just stay here 2737 break; 2738 2739 case SCU_EVENT_SAS_15: 2740 case SCU_EVENT_SAS_15_SSC: 2741 scic_sds_phy_complete_link_training( 2742 this_phy, SCI_SAS_150_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF 2743 ); 2744 break; 2745 2746 case SCU_EVENT_SAS_30: 2747 case SCU_EVENT_SAS_30_SSC: 2748 scic_sds_phy_complete_link_training( 2749 this_phy, SCI_SAS_300_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF 2750 ); 2751 break; 2752 2753 case SCU_EVENT_SAS_60: 2754 case SCU_EVENT_SAS_60_SSC: 2755 scic_sds_phy_complete_link_training( 2756 this_phy, SCI_SAS_600_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF 2757 ); 2758 break; 2759 2760 case SCU_EVENT_SATA_SPINUP_HOLD: 2761 // We were doing SAS PHY link training and received a SATA PHY event 2762 // continue OOB/SN as if this were a SATA PHY 2763 scic_sds_phy_start_sata_link_training(this_phy); 2764 break; 2765 2766 case SCU_EVENT_LINK_FAILURE: 2767 // Link failure change state back to the starting state 2768 scic_sds_phy_restart_starting_state(this_phy); 2769 break; 2770 2771 default: 2772 SCIC_LOG_WARNING(( 2773 sci_base_object_get_logger(this_phy), 2774 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS, 2775 "PHY starting substate machine received unexpected event_code %x\n", 2776 event_code 2777 )); 2778 2779 result = SCI_FAILURE; 2780 break; 2781 } 2782 2783 return result; 2784 } 2785 2786 /** 2787 * This method is called when an event notification is received for the phy 2788 * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. 2789 * - decode the event 2790 * - sas phy detected event backs up the state machine to the await 2791 * speed notification. 2792 * - identify timeout is an un-expected event and the state machine is 2793 * restarted. 2794 * - link failure events restart the starting state machine 2795 * - any other events log a warning message and set a failure status 2796 * 2797 * @param[in] phy This SCIC_SDS_PHY object which has received an event. 2798 * @param[in] event_code This is the event code which the phy object is to 2799 * decode. 2800 * 2801 * @return SCI_STATUS 2802 * @retval SCI_SUCCESS on any valid event notification 2803 * @retval SCI_FAILURE on any unexpected event notifation 2804 */ 2805 static 2806 SCI_STATUS scic_sds_phy_starting_substate_await_iaf_uf_event_handler( 2807 SCIC_SDS_PHY_T *this_phy, 2808 U32 event_code 2809 ) 2810 { 2811 U32 result = SCI_SUCCESS; 2812 2813 switch (scu_get_event_code(event_code)) 2814 { 2815 case SCU_EVENT_SAS_PHY_DETECTED: 2816 // Backup the state machine 2817 scic_sds_phy_start_sas_link_training(this_phy); 2818 break; 2819 2820 case SCU_EVENT_SATA_SPINUP_HOLD: 2821 // We were doing SAS PHY link training and received a SATA PHY event 2822 // continue OOB/SN as if this were a SATA PHY 2823 scic_sds_phy_start_sata_link_training(this_phy); 2824 break; 2825 2826 case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: 2827 case SCU_EVENT_LINK_FAILURE: 2828 case SCU_EVENT_HARD_RESET_RECEIVED: 2829 // Start the oob/sn state machine over again 2830 scic_sds_phy_restart_starting_state(this_phy); 2831 break; 2832 2833 default: 2834 SCIC_LOG_WARNING(( 2835 sci_base_object_get_logger(this_phy), 2836 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS, 2837 "PHY starting substate machine received unexpected event_code %x\n", 2838 event_code 2839 )); 2840 2841 result = SCI_FAILURE; 2842 break; 2843 } 2844 2845 return result; 2846 } 2847 2848 /** 2849 * This method is called when an event notification is received for the phy 2850 * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_POWER. 2851 * - decode the event 2852 * - link failure events restart the starting state machine 2853 * - any other events log a warning message and set a failure status 2854 * 2855 * @param[in] phy This SCIC_SDS_PHY object which has received an event. 2856 * @param[in] event_code This is the event code which the phy object is to 2857 * decode. 2858 * 2859 * @return SCI_STATUS 2860 * @retval SCI_SUCCESS on a link failure event 2861 * @retval SCI_FAILURE on any unexpected event notifation 2862 */ 2863 static 2864 SCI_STATUS scic_sds_phy_starting_substate_await_sas_power_event_handler( 2865 SCIC_SDS_PHY_T *this_phy, 2866 U32 event_code 2867 ) 2868 { 2869 U32 result = SCI_SUCCESS; 2870 2871 switch (scu_get_event_code(event_code)) 2872 { 2873 case SCU_EVENT_LINK_FAILURE: 2874 // Link failure change state back to the starting state 2875 scic_sds_phy_restart_starting_state(this_phy); 2876 break; 2877 2878 default: 2879 SCIC_LOG_WARNING(( 2880 sci_base_object_get_logger(this_phy), 2881 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS, 2882 "PHY starting substate machine received unexpected event_code %x\n", 2883 event_code 2884 )); 2885 2886 result = SCI_FAILURE; 2887 break; 2888 } 2889 2890 return result; 2891 } 2892 2893 /** 2894 * This method is called when an event notification is received for the phy 2895 * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. 2896 * - decode the event 2897 * - link failure events restart the starting state machine 2898 * - sata spinup hold events are ignored since they are expected 2899 * - any other events log a warning message and set a failure status 2900 * 2901 * @param[in] phy This SCIC_SDS_PHY object which has received an event. 2902 * @param[in] event_code This is the event code which the phy object is to 2903 * decode. 2904 * 2905 * @return SCI_STATUS 2906 * @retval SCI_SUCCESS on a link failure event 2907 * @retval SCI_FAILURE on any unexpected event notifation 2908 */ 2909 static 2910 SCI_STATUS scic_sds_phy_starting_substate_await_sata_power_event_handler( 2911 SCIC_SDS_PHY_T *this_phy, 2912 U32 event_code 2913 ) 2914 { 2915 U32 result = SCI_SUCCESS; 2916 2917 switch (scu_get_event_code(event_code)) 2918 { 2919 case SCU_EVENT_LINK_FAILURE: 2920 // Link failure change state back to the starting state 2921 scic_sds_phy_restart_starting_state(this_phy); 2922 break; 2923 2924 case SCU_EVENT_SATA_SPINUP_HOLD: 2925 // These events are received every 10ms and are expected while in this state 2926 break; 2927 2928 case SCU_EVENT_SAS_PHY_DETECTED: 2929 // There has been a change in the phy type before OOB/SN for the 2930 // SATA finished start down the SAS link traning path. 2931 scic_sds_phy_start_sas_link_training(this_phy); 2932 break; 2933 2934 default: 2935 SCIC_LOG_WARNING(( 2936 sci_base_object_get_logger(this_phy), 2937 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS, 2938 "PHY starting substate machine received unexpected event_code %x\n", 2939 event_code 2940 )); 2941 2942 result = SCI_FAILURE; 2943 break; 2944 } 2945 2946 return result; 2947 } 2948 2949 /** 2950 * This method is called when an event notification is received for the phy 2951 * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. 2952 * - decode the event 2953 * - link failure events restart the starting state machine 2954 * - sata spinup hold events are ignored since they are expected 2955 * - sata phy detected event change to the wait speed event 2956 * - any other events log a warning message and set a failure status 2957 * 2958 * @param[in] phy This SCIC_SDS_PHY object which has received an event. 2959 * @param[in] event_code This is the event code which the phy object is to 2960 * decode. 2961 * 2962 * @return SCI_STATUS 2963 * @retval SCI_SUCCESS on a link failure event 2964 * @retval SCI_FAILURE on any unexpected event notifation 2965 */ 2966 static 2967 SCI_STATUS scic_sds_phy_starting_substate_await_sata_phy_event_handler( 2968 SCIC_SDS_PHY_T *this_phy, 2969 U32 event_code 2970 ) 2971 { 2972 U32 result = SCI_SUCCESS; 2973 2974 switch (scu_get_event_code(event_code)) 2975 { 2976 case SCU_EVENT_LINK_FAILURE: 2977 // Link failure change state back to the starting state 2978 scic_sds_phy_restart_starting_state(this_phy); 2979 break; 2980 2981 case SCU_EVENT_SATA_SPINUP_HOLD: 2982 // These events might be received since we dont know how many may be in 2983 // the completion queue while waiting for power 2984 break; 2985 2986 case SCU_EVENT_SATA_PHY_DETECTED: 2987 this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; 2988 2989 // We have received the SATA PHY notification change state 2990 sci_base_state_machine_change_state( 2991 scic_sds_phy_get_starting_substate_machine(this_phy), 2992 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN 2993 ); 2994 break; 2995 2996 case SCU_EVENT_SAS_PHY_DETECTED: 2997 // There has been a change in the phy type before OOB/SN for the 2998 // SATA finished start down the SAS link traning path. 2999 scic_sds_phy_start_sas_link_training(this_phy); 3000 break; 3001 3002 default: 3003 SCIC_LOG_WARNING(( 3004 sci_base_object_get_logger(this_phy), 3005 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS, 3006 "PHY starting substate machine received unexpected event_code %x\n", 3007 event_code 3008 )); 3009 3010 result = SCI_FAILURE; 3011 break; 3012 } 3013 3014 return result; 3015 } 3016 3017 /** 3018 * This method is called when an event notification is received for the phy 3019 * object when in the state 3020 * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. 3021 * - decode the event 3022 * - sata phy detected returns us back to this state. 3023 * - speed event detected causes a state transition to the wait for 3024 * signature. 3025 * - link failure events restart the starting state machine 3026 * - any other events log a warning message and set a failure status 3027 * 3028 * @param[in] phy This SCIC_SDS_PHY object which has received an event. 3029 * @param[in] event_code This is the event code which the phy object is to 3030 * decode. 3031 * 3032 * @return SCI_STATUS 3033 * @retval SCI_SUCCESS on any valid event notification 3034 * @retval SCI_FAILURE on any unexpected event notifation 3035 */ 3036 static 3037 SCI_STATUS scic_sds_phy_starting_substate_await_sata_speed_event_handler( 3038 SCIC_SDS_PHY_T *this_phy, 3039 U32 event_code 3040 ) 3041 { 3042 U32 result = SCI_SUCCESS; 3043 3044 switch (scu_get_event_code(event_code)) 3045 { 3046 case SCU_EVENT_SATA_PHY_DETECTED: 3047 // The hardware reports multiple SATA PHY detected events 3048 // ignore the extras 3049 break; 3050 3051 case SCU_EVENT_SATA_15: 3052 case SCU_EVENT_SATA_15_SSC: 3053 scic_sds_phy_complete_link_training( 3054 this_phy, 3055 SCI_SAS_150_GB, 3056 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF 3057 ); 3058 break; 3059 3060 case SCU_EVENT_SATA_30: 3061 case SCU_EVENT_SATA_30_SSC: 3062 scic_sds_phy_complete_link_training( 3063 this_phy, 3064 SCI_SAS_300_GB, 3065 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF 3066 ); 3067 break; 3068 3069 case SCU_EVENT_SATA_60: 3070 case SCU_EVENT_SATA_60_SSC: 3071 scic_sds_phy_complete_link_training( 3072 this_phy, 3073 SCI_SAS_600_GB, 3074 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF 3075 ); 3076 break; 3077 3078 case SCU_EVENT_LINK_FAILURE: 3079 // Link failure change state back to the starting state 3080 scic_sds_phy_restart_starting_state(this_phy); 3081 break; 3082 3083 case SCU_EVENT_SAS_PHY_DETECTED: 3084 // There has been a change in the phy type before OOB/SN for the 3085 // SATA finished start down the SAS link traning path. 3086 scic_sds_phy_start_sas_link_training(this_phy); 3087 break; 3088 3089 default: 3090 SCIC_LOG_WARNING(( 3091 sci_base_object_get_logger(this_phy), 3092 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS, 3093 "PHY starting substate machine received unexpected event_code %x\n", 3094 event_code 3095 )); 3096 3097 result = SCI_FAILURE; 3098 break; 3099 } 3100 3101 return result; 3102 } 3103 3104 /** 3105 * This method is called when an event notification is received for the phy 3106 * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. 3107 * - decode the event 3108 * - sas phy detected event backs up the state machine to the await 3109 * speed notification. 3110 * - identify timeout is an un-expected event and the state machine is 3111 * restarted. 3112 * - link failure events restart the starting state machine 3113 * - any other events log a warning message and set a failure status 3114 * 3115 * @param[in] phy This SCIC_SDS_PHY object which has received an event. 3116 * @param[in] event_code This is the event code which the phy object is to 3117 * decode. 3118 * 3119 * @return SCI_STATUS 3120 * @retval SCI_SUCCESS on any valid event notification 3121 * @retval SCI_FAILURE on any unexpected event notifation 3122 */ 3123 static 3124 SCI_STATUS scic_sds_phy_starting_substate_await_sig_fis_event_handler( 3125 SCIC_SDS_PHY_T *this_phy, 3126 U32 event_code 3127 ) 3128 { 3129 U32 result = SCI_SUCCESS; 3130 3131 switch (scu_get_event_code(event_code)) 3132 { 3133 case SCU_EVENT_SATA_PHY_DETECTED: 3134 // Backup the state machine 3135 sci_base_state_machine_change_state( 3136 scic_sds_phy_get_starting_substate_machine(this_phy), 3137 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN 3138 ); 3139 break; 3140 3141 case SCU_EVENT_LINK_FAILURE: 3142 // Link failure change state back to the starting state 3143 scic_sds_phy_restart_starting_state(this_phy); 3144 break; 3145 3146 default: 3147 SCIC_LOG_WARNING(( 3148 sci_base_object_get_logger(this_phy), 3149 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS, 3150 "PHY starting substate machine received unexpected event_code %x\n", 3151 event_code 3152 )); 3153 3154 result = SCI_FAILURE; 3155 break; 3156 } 3157 3158 return result; 3159 } 3160 3161 3162 //***************************************************************************** 3163 //* SCIC SDS PHY FRAME_HANDLERS 3164 //***************************************************************************** 3165 3166 /** 3167 * This method decodes the unsolicited frame when the SCIC_SDS_PHY is in the 3168 * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. 3169 * - Get the UF Header 3170 * - If the UF is an IAF 3171 * - Copy IAF data to local phy object IAF data buffer. 3172 * - Change starting substate to wait power. 3173 * - else 3174 * - log warning message of unexpected unsolicted frame 3175 * - release frame buffer 3176 * 3177 * @param[in] phy This is SCIC_SDS_PHY object which is being requested to 3178 * decode the frame data. 3179 * @param[in] frame_index This is the index of the unsolicited frame which was 3180 * received for this phy. 3181 * 3182 * @return SCI_STATUS 3183 * @retval SCI_SUCCESS 3184 */ 3185 static 3186 SCI_STATUS scic_sds_phy_starting_substate_await_iaf_uf_frame_handler( 3187 SCIC_SDS_PHY_T *this_phy, 3188 U32 frame_index 3189 ) 3190 { 3191 SCI_STATUS result; 3192 U32 *frame_words; 3193 SCI_SAS_IDENTIFY_ADDRESS_FRAME_T *identify_frame; 3194 3195 result = scic_sds_unsolicited_frame_control_get_header( 3196 &(scic_sds_phy_get_controller(this_phy)->uf_control), 3197 frame_index, 3198 (void **)&frame_words); 3199 3200 if (result != SCI_SUCCESS) 3201 { 3202 return result; 3203 } 3204 3205 frame_words[0] = SCIC_SWAP_DWORD(frame_words[0]); 3206 identify_frame = (SCI_SAS_IDENTIFY_ADDRESS_FRAME_T *)frame_words; 3207 3208 if (identify_frame->address_frame_type == 0) 3209 { 3210 // Byte swap the rest of the frame so we can make 3211 // a copy of the buffer 3212 frame_words[1] = SCIC_SWAP_DWORD(frame_words[1]); 3213 frame_words[2] = SCIC_SWAP_DWORD(frame_words[2]); 3214 frame_words[3] = SCIC_SWAP_DWORD(frame_words[3]); 3215 frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]); 3216 frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]); 3217 3218 memcpy( 3219 &this_phy->phy_type.sas.identify_address_frame_buffer, 3220 identify_frame, 3221 sizeof(SCI_SAS_IDENTIFY_ADDRESS_FRAME_T) 3222 ); 3223 3224 if (identify_frame->protocols.u.bits.smp_target) 3225 { 3226 // We got the IAF for an expander PHY go to the final state since 3227 // there are no power requirements for expander phys. 3228 sci_base_state_machine_change_state( 3229 scic_sds_phy_get_starting_substate_machine(this_phy), 3230 SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL 3231 ); 3232 } 3233 else 3234 { 3235 // We got the IAF we can now go to the await spinup semaphore state 3236 sci_base_state_machine_change_state( 3237 scic_sds_phy_get_starting_substate_machine(this_phy), 3238 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER 3239 ); 3240 } 3241 3242 result = SCI_SUCCESS; 3243 } 3244 else 3245 { 3246 SCIC_LOG_WARNING(( 3247 sci_base_object_get_logger(this_phy), 3248 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_UNSOLICITED_FRAMES, 3249 "PHY starting substate machine received unexpected frame id %x\n", 3250 frame_index 3251 )); 3252 } 3253 3254 // Regardless of the result release this frame since we are done with it 3255 scic_sds_controller_release_frame( 3256 scic_sds_phy_get_controller(this_phy), frame_index 3257 ); 3258 3259 return result; 3260 } 3261 3262 /** 3263 * This method decodes the unsolicited frame when the SCIC_SDS_PHY is in the 3264 * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. 3265 * - Get the UF Header 3266 * - If the UF is an SIGNATURE FIS 3267 * - Copy IAF data to local phy object SIGNATURE FIS data buffer. 3268 * - else 3269 * - log warning message of unexpected unsolicted frame 3270 * - release frame buffer 3271 * 3272 * @param[in] phy This is SCIC_SDS_PHY object which is being requested to 3273 * decode the frame data. 3274 * @param[in] frame_index This is the index of the unsolicited frame which was 3275 * received for this phy. 3276 * 3277 * @return SCI_STATUS 3278 * @retval SCI_SUCCESS 3279 * 3280 * @todo Must decode the SIGNATURE FIS data 3281 */ 3282 static 3283 SCI_STATUS scic_sds_phy_starting_substate_await_sig_fis_frame_handler( 3284 SCIC_SDS_PHY_T *this_phy, 3285 U32 frame_index 3286 ) 3287 { 3288 SCI_STATUS result; 3289 U32 * frame_words; 3290 SATA_FIS_HEADER_T * fis_frame_header; 3291 U32 * fis_frame_data; 3292 3293 result = scic_sds_unsolicited_frame_control_get_header( 3294 &(scic_sds_phy_get_controller(this_phy)->uf_control), 3295 frame_index, 3296 (void **)&frame_words); 3297 3298 if (result != SCI_SUCCESS) 3299 { 3300 return result; 3301 } 3302 3303 fis_frame_header = (SATA_FIS_HEADER_T *)frame_words; 3304 3305 if ( 3306 (fis_frame_header->fis_type == SATA_FIS_TYPE_REGD2H) 3307 && !(fis_frame_header->status & ATA_STATUS_REG_BSY_BIT) 3308 ) 3309 { 3310 scic_sds_unsolicited_frame_control_get_buffer( 3311 &(scic_sds_phy_get_controller(this_phy)->uf_control), 3312 frame_index, 3313 (void **)&fis_frame_data 3314 ); 3315 3316 scic_sds_controller_copy_sata_response( 3317 &this_phy->phy_type.sata.signature_fis_buffer, 3318 frame_words, 3319 fis_frame_data 3320 ); 3321 3322 // We got the IAF we can now go to the await spinup semaphore state 3323 sci_base_state_machine_change_state( 3324 scic_sds_phy_get_starting_substate_machine(this_phy), 3325 SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL 3326 ); 3327 3328 result = SCI_SUCCESS; 3329 } 3330 else 3331 { 3332 SCIC_LOG_WARNING(( 3333 sci_base_object_get_logger(this_phy), 3334 SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_UNSOLICITED_FRAMES, 3335 "PHY starting substate machine received unexpected frame id %x\n", 3336 frame_index 3337 )); 3338 } 3339 3340 // Regardless of the result release this frame since we are done with it 3341 scic_sds_controller_release_frame( 3342 scic_sds_phy_get_controller(this_phy), frame_index 3343 ); 3344 3345 return result; 3346 } 3347 3348 //***************************************************************************** 3349 //* SCIC SDS PHY POWER_HANDLERS 3350 //***************************************************************************** 3351 3352 /** 3353 * This method is called by the SCIC_SDS_CONTROLLER when the phy object is 3354 * granted power. 3355 * - The notify enable spinups are turned on for this phy object 3356 * - The phy state machine is transitioned to the 3357 * SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. 3358 * 3359 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 3360 * SCIC_SDS_PHY object. 3361 * 3362 * @return SCI_STATUS 3363 * @retval SCI_SUCCESS 3364 */ 3365 static 3366 SCI_STATUS scic_sds_phy_starting_substate_await_sas_power_consume_power_handler( 3367 SCIC_SDS_PHY_T *this_phy 3368 ) 3369 { 3370 U32 enable_spinup; 3371 3372 enable_spinup = SCU_SAS_ENSPINUP_READ(this_phy); 3373 enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE); 3374 SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup); 3375 3376 // Change state to the final state this substate machine has run to completion 3377 sci_base_state_machine_change_state( 3378 scic_sds_phy_get_starting_substate_machine(this_phy), 3379 SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL 3380 ); 3381 3382 return SCI_SUCCESS; 3383 } 3384 3385 /** 3386 * This method is called by the SCIC_SDS_CONTROLLER when the phy object is 3387 * granted power. 3388 * - The phy state machine is transitioned to the 3389 * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. 3390 * 3391 * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 3392 * SCIC_SDS_PHY object. 3393 * 3394 * @return SCI_STATUS 3395 * @retval SCI_SUCCESS 3396 */ 3397 static 3398 SCI_STATUS scic_sds_phy_starting_substate_await_sata_power_consume_power_handler( 3399 SCIC_SDS_PHY_T *this_phy 3400 ) 3401 { 3402 U32 scu_sas_pcfg_value; 3403 3404 // Release the spinup hold state and reset the OOB state machine 3405 scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); 3406 scu_sas_pcfg_value &= 3407 ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE)); 3408 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); 3409 SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); 3410 3411 // Now restart the OOB operation 3412 scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); 3413 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); 3414 SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); 3415 3416 // Change state to the final state this substate machine has run to completion 3417 sci_base_state_machine_change_state( 3418 scic_sds_phy_get_starting_substate_machine(this_phy), 3419 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN 3420 ); 3421 3422 return SCI_SUCCESS; 3423 } 3424 3425 // --------------------------------------------------------------------------- 3426 3427 SCIC_SDS_PHY_STATE_HANDLER_T 3428 scic_sds_phy_starting_substate_handler_table[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] = 3429 { 3430 // SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL 3431 { 3432 { 3433 scic_sds_phy_default_start_handler, 3434 scic_sds_phy_starting_substate_general_stop_handler, 3435 scic_sds_phy_default_reset_handler, 3436 scic_sds_phy_default_destroy_handler 3437 }, 3438 scic_sds_phy_default_frame_handler, 3439 scic_sds_phy_default_event_handler, 3440 scic_sds_phy_default_consume_power_handler 3441 }, 3442 // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN 3443 { 3444 { 3445 scic_sds_phy_default_start_handler, 3446 scic_sds_phy_starting_substate_general_stop_handler, 3447 scic_sds_phy_default_reset_handler, 3448 scic_sds_phy_default_destroy_handler 3449 }, 3450 scic_sds_phy_default_frame_handler, 3451 scic_sds_phy_starting_substate_await_ossp_event_handler, 3452 scic_sds_phy_default_consume_power_handler 3453 }, 3454 // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN 3455 { 3456 { 3457 scic_sds_phy_default_start_handler, 3458 scic_sds_phy_starting_substate_general_stop_handler, 3459 scic_sds_phy_default_reset_handler, 3460 scic_sds_phy_default_destroy_handler 3461 }, 3462 scic_sds_phy_default_frame_handler, 3463 scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, 3464 scic_sds_phy_default_consume_power_handler 3465 }, 3466 // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF 3467 { 3468 { 3469 scic_sds_phy_default_start_handler, 3470 scic_sds_phy_default_stop_handler, 3471 scic_sds_phy_default_reset_handler, 3472 scic_sds_phy_default_destroy_handler 3473 }, 3474 scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, 3475 scic_sds_phy_starting_substate_await_iaf_uf_event_handler, 3476 scic_sds_phy_default_consume_power_handler 3477 }, 3478 // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER 3479 { 3480 { 3481 scic_sds_phy_default_start_handler, 3482 scic_sds_phy_starting_substate_general_stop_handler, 3483 scic_sds_phy_default_reset_handler, 3484 scic_sds_phy_default_destroy_handler 3485 }, 3486 scic_sds_phy_default_frame_handler, 3487 scic_sds_phy_starting_substate_await_sas_power_event_handler, 3488 scic_sds_phy_starting_substate_await_sas_power_consume_power_handler 3489 }, 3490 // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, 3491 { 3492 { 3493 scic_sds_phy_default_start_handler, 3494 scic_sds_phy_starting_substate_general_stop_handler, 3495 scic_sds_phy_default_reset_handler, 3496 scic_sds_phy_default_destroy_handler 3497 }, 3498 scic_sds_phy_default_frame_handler, 3499 scic_sds_phy_starting_substate_await_sata_power_event_handler, 3500 scic_sds_phy_starting_substate_await_sata_power_consume_power_handler 3501 }, 3502 // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, 3503 { 3504 { 3505 scic_sds_phy_default_start_handler, 3506 scic_sds_phy_starting_substate_general_stop_handler, 3507 scic_sds_phy_default_reset_handler, 3508 scic_sds_phy_default_destroy_handler 3509 }, 3510 scic_sds_phy_default_frame_handler, 3511 scic_sds_phy_starting_substate_await_sata_phy_event_handler, 3512 scic_sds_phy_default_consume_power_handler 3513 }, 3514 // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, 3515 { 3516 { 3517 scic_sds_phy_default_start_handler, 3518 scic_sds_phy_starting_substate_general_stop_handler, 3519 scic_sds_phy_default_reset_handler, 3520 scic_sds_phy_default_destroy_handler 3521 }, 3522 scic_sds_phy_default_frame_handler, 3523 scic_sds_phy_starting_substate_await_sata_speed_event_handler, 3524 scic_sds_phy_default_consume_power_handler 3525 }, 3526 // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, 3527 { 3528 { 3529 scic_sds_phy_default_start_handler, 3530 scic_sds_phy_starting_substate_general_stop_handler, 3531 scic_sds_phy_default_reset_handler, 3532 scic_sds_phy_default_destroy_handler 3533 }, 3534 scic_sds_phy_starting_substate_await_sig_fis_frame_handler, 3535 scic_sds_phy_starting_substate_await_sig_fis_event_handler, 3536 scic_sds_phy_default_consume_power_handler 3537 }, 3538 // SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL 3539 { 3540 { 3541 scic_sds_phy_default_start_handler, 3542 scic_sds_phy_starting_substate_general_stop_handler, 3543 scic_sds_phy_default_reset_handler, 3544 scic_sds_phy_default_destroy_handler 3545 }, 3546 scic_sds_phy_default_frame_handler, 3547 scic_sds_phy_default_event_handler, 3548 scic_sds_phy_default_consume_power_handler 3549 } 3550 }; 3551 3552 /** 3553 * This macro sets the starting substate handlers by state_id 3554 */ 3555 #define scic_sds_phy_set_starting_substate_handlers(phy, state_id) \ 3556 scic_sds_phy_set_state_handlers( \ 3557 (phy), \ 3558 &scic_sds_phy_starting_substate_handler_table[(state_id)] \ 3559 ) 3560 3561 //**************************************************************************** 3562 //* PHY STARTING SUBSTATE METHODS 3563 //**************************************************************************** 3564 3565 /** 3566 * This method will perform the actions required by the SCIC_SDS_PHY on 3567 * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL. 3568 * - The initial state handlers are put in place for the SCIC_SDS_PHY 3569 * object. 3570 * - The state is changed to the wait phy type event notification. 3571 * 3572 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3573 * SCIC_SDS_PHY object. 3574 * 3575 * @return none 3576 */ 3577 static 3578 void scic_sds_phy_starting_initial_substate_enter( 3579 SCI_BASE_OBJECT_T *object 3580 ) 3581 { 3582 SCIC_SDS_PHY_T *this_phy; 3583 this_phy = (SCIC_SDS_PHY_T *)object; 3584 3585 scic_sds_phy_set_starting_substate_handlers( 3586 this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); 3587 3588 // This is just an temporary state go off to the starting state 3589 sci_base_state_machine_change_state( 3590 scic_sds_phy_get_starting_substate_machine(this_phy), 3591 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN 3592 ); 3593 } 3594 3595 /** 3596 * This method will perform the actions required by the SCIC_SDS_PHY on 3597 * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN. 3598 * - Set the SCIC_SDS_PHY object state handlers for this state. 3599 * 3600 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3601 * SCIC_SDS_PHY object. 3602 * 3603 * @return none 3604 */ 3605 static 3606 void scic_sds_phy_starting_await_ossp_en_substate_enter( 3607 SCI_BASE_OBJECT_T *object 3608 ) 3609 { 3610 SCIC_SDS_PHY_T *this_phy; 3611 this_phy = (SCIC_SDS_PHY_T *)object; 3612 3613 scic_sds_phy_set_starting_substate_handlers( 3614 this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN 3615 ); 3616 } 3617 3618 /** 3619 * This method will perform the actions required by the SCIC_SDS_PHY on 3620 * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. 3621 * - Set the SCIC_SDS_PHY object state handlers for this state. 3622 * 3623 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3624 * SCIC_SDS_PHY object. 3625 * 3626 * @return none 3627 */ 3628 static 3629 void scic_sds_phy_starting_await_sas_speed_en_substate_enter( 3630 SCI_BASE_OBJECT_T *object 3631 ) 3632 { 3633 SCIC_SDS_PHY_T *this_phy; 3634 this_phy = (SCIC_SDS_PHY_T *)object; 3635 3636 scic_sds_phy_set_starting_substate_handlers( 3637 this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN 3638 ); 3639 } 3640 3641 /** 3642 * This method will perform the actions required by the SCIC_SDS_PHY on 3643 * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. 3644 * - Set the SCIC_SDS_PHY object state handlers for this state. 3645 * 3646 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3647 * SCIC_SDS_PHY object. 3648 * 3649 * @return none 3650 */ 3651 static 3652 void scic_sds_phy_starting_await_iaf_uf_substate_enter( 3653 SCI_BASE_OBJECT_T *object 3654 ) 3655 { 3656 SCIC_SDS_PHY_T *this_phy; 3657 this_phy = (SCIC_SDS_PHY_T *)object; 3658 3659 scic_sds_phy_set_starting_substate_handlers( 3660 this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF 3661 ); 3662 } 3663 3664 /** 3665 * This method will perform the actions required by the SCIC_SDS_PHY on 3666 * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. 3667 * - Set the SCIC_SDS_PHY object state handlers for this state. 3668 * - Add this phy object to the power control queue 3669 * 3670 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3671 * SCIC_SDS_PHY object. 3672 * 3673 * @return none 3674 */ 3675 static 3676 void scic_sds_phy_starting_await_sas_power_substate_enter( 3677 SCI_BASE_OBJECT_T *object 3678 ) 3679 { 3680 SCIC_SDS_PHY_T *this_phy; 3681 this_phy = (SCIC_SDS_PHY_T *)object; 3682 3683 scic_sds_phy_set_starting_substate_handlers( 3684 this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER 3685 ); 3686 3687 scic_sds_controller_power_control_queue_insert( 3688 scic_sds_phy_get_controller(this_phy), 3689 this_phy 3690 ); 3691 } 3692 3693 /** 3694 * This method will perform the actions required by the SCIC_SDS_PHY on 3695 * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. 3696 * - Remove the SCIC_SDS_PHY object from the power control queue. 3697 * 3698 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3699 * SCIC_SDS_PHY object. 3700 * 3701 * @return none 3702 */ 3703 static 3704 void scic_sds_phy_starting_await_sas_power_substate_exit( 3705 SCI_BASE_OBJECT_T *object 3706 ) 3707 { 3708 SCIC_SDS_PHY_T *this_phy; 3709 this_phy = (SCIC_SDS_PHY_T *)object; 3710 3711 scic_sds_controller_power_control_queue_remove( 3712 scic_sds_phy_get_controller(this_phy), this_phy 3713 ); 3714 } 3715 3716 /** 3717 * This method will perform the actions required by the SCIC_SDS_PHY on 3718 * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. 3719 * - Set the SCIC_SDS_PHY object state handlers for this state. 3720 * - Add this phy object to the power control queue 3721 * 3722 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3723 * SCIC_SDS_PHY object. 3724 * 3725 * @return none 3726 */ 3727 static 3728 void scic_sds_phy_starting_await_sata_power_substate_enter( 3729 SCI_BASE_OBJECT_T *object 3730 ) 3731 { 3732 SCIC_SDS_PHY_T *this_phy; 3733 this_phy = (SCIC_SDS_PHY_T *)object; 3734 3735 scic_sds_phy_set_starting_substate_handlers( 3736 this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER 3737 ); 3738 3739 scic_sds_controller_power_control_queue_insert( 3740 scic_sds_phy_get_controller(this_phy), 3741 this_phy 3742 ); 3743 } 3744 3745 /** 3746 * This method will perform the actions required by the SCIC_SDS_PHY on 3747 * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. 3748 * - Remove the SCIC_SDS_PHY object from the power control queue. 3749 * 3750 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3751 * SCIC_SDS_PHY object. 3752 * 3753 * @return none 3754 */ 3755 static 3756 void scic_sds_phy_starting_await_sata_power_substate_exit( 3757 SCI_BASE_OBJECT_T *object 3758 ) 3759 { 3760 SCIC_SDS_PHY_T *this_phy; 3761 this_phy = (SCIC_SDS_PHY_T *)object; 3762 3763 scic_sds_controller_power_control_queue_remove( 3764 scic_sds_phy_get_controller(this_phy), 3765 this_phy 3766 ); 3767 } 3768 3769 /** 3770 * This method will perform the actions required by the SCIC_SDS_PHY on 3771 * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. 3772 * - Set the SCIC_SDS_PHY object state handlers for this state. 3773 * 3774 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3775 * SCIC_SDS_PHY object. 3776 * 3777 * @return none 3778 */ 3779 static 3780 void scic_sds_phy_starting_await_sata_phy_substate_enter( 3781 SCI_BASE_OBJECT_T *object 3782 ) 3783 { 3784 SCIC_SDS_PHY_T *this_phy; 3785 this_phy = (SCIC_SDS_PHY_T *)object; 3786 3787 scic_sds_phy_set_starting_substate_handlers( 3788 this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN 3789 ); 3790 3791 scic_cb_timer_start( 3792 scic_sds_phy_get_controller(this_phy), 3793 this_phy->sata_timeout_timer, 3794 SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 3795 ); 3796 } 3797 3798 /** 3799 * This method will perform the actions required by the SCIC_SDS_PHY on 3800 * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. 3801 * - stop the timer that was started on entry to await sata phy 3802 * event notification 3803 * 3804 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3805 * SCIC_SDS_PHY object. 3806 * 3807 * @return none 3808 */ 3809 static 3810 void scic_sds_phy_starting_await_sata_phy_substate_exit( 3811 SCI_BASE_OBJECT_T *object 3812 ) 3813 { 3814 SCIC_SDS_PHY_T *this_phy; 3815 this_phy = (SCIC_SDS_PHY_T *)object; 3816 3817 scic_cb_timer_stop( 3818 scic_sds_phy_get_controller(this_phy), 3819 this_phy->sata_timeout_timer 3820 ); 3821 } 3822 3823 /** 3824 * This method will perform the actions required by the SCIC_SDS_PHY on 3825 * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. 3826 * - Set the SCIC_SDS_PHY object state handlers for this state. 3827 * 3828 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3829 * SCIC_SDS_PHY object. 3830 * 3831 * @return none 3832 */ 3833 static 3834 void scic_sds_phy_starting_await_sata_speed_substate_enter( 3835 SCI_BASE_OBJECT_T *object 3836 ) 3837 { 3838 SCIC_SDS_PHY_T *this_phy; 3839 this_phy = (SCIC_SDS_PHY_T *)object; 3840 3841 scic_sds_phy_set_starting_substate_handlers( 3842 this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN 3843 ); 3844 3845 scic_cb_timer_start( 3846 scic_sds_phy_get_controller(this_phy), 3847 this_phy->sata_timeout_timer, 3848 SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 3849 ); 3850 } 3851 3852 /** 3853 * This method will perform the actions required by the SCIC_SDS_PHY on 3854 * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. 3855 * - stop the timer that was started on entry to await sata phy 3856 * event notification 3857 * 3858 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3859 * SCIC_SDS_PHY object. 3860 * 3861 * @return none 3862 */ 3863 static 3864 void scic_sds_phy_starting_await_sata_speed_substate_exit( 3865 SCI_BASE_OBJECT_T *object 3866 ) 3867 { 3868 SCIC_SDS_PHY_T *this_phy; 3869 this_phy = (SCIC_SDS_PHY_T *)object; 3870 3871 scic_cb_timer_stop( 3872 scic_sds_phy_get_controller(this_phy), 3873 this_phy->sata_timeout_timer 3874 ); 3875 } 3876 3877 /** 3878 * This method will perform the actions required by the SCIC_SDS_PHY on 3879 * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. 3880 * - Set the SCIC_SDS_PHY object state handlers for this state. 3881 * - Start the SIGNATURE FIS timeout timer 3882 * 3883 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3884 * SCIC_SDS_PHY object. 3885 * 3886 * @return none 3887 */ 3888 static 3889 void scic_sds_phy_starting_await_sig_fis_uf_substate_enter( 3890 SCI_BASE_OBJECT_T *object 3891 ) 3892 { 3893 BOOL continue_to_ready_state; 3894 SCIC_SDS_PHY_T * this_phy; 3895 3896 this_phy = (SCIC_SDS_PHY_T *)object; 3897 3898 scic_sds_phy_set_starting_substate_handlers( 3899 this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF 3900 ); 3901 3902 continue_to_ready_state = scic_sds_port_link_detected( 3903 this_phy->owning_port, 3904 this_phy 3905 ); 3906 3907 if (continue_to_ready_state) 3908 { 3909 // Clear the PE suspend condition so we can actually receive SIG FIS 3910 // The hardware will not respond to the XRDY until the PE suspend 3911 // condition is cleared. 3912 scic_sds_phy_resume(this_phy); 3913 3914 scic_cb_timer_start( 3915 scic_sds_phy_get_controller(this_phy), 3916 this_phy->sata_timeout_timer, 3917 SCIC_SDS_SIGNATURE_FIS_TIMEOUT 3918 ); 3919 } 3920 else 3921 { 3922 this_phy->is_in_link_training = FALSE; 3923 } 3924 } 3925 3926 /** 3927 * This method will perform the actions required by the SCIC_SDS_PHY on 3928 * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. 3929 * - Stop the SIGNATURE FIS timeout timer. 3930 * 3931 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3932 * SCIC_SDS_PHY object. 3933 * 3934 * @return none 3935 */ 3936 static 3937 void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( 3938 SCI_BASE_OBJECT_T *object 3939 ) 3940 { 3941 SCIC_SDS_PHY_T *this_phy; 3942 this_phy = (SCIC_SDS_PHY_T *)object; 3943 3944 scic_cb_timer_stop( 3945 scic_sds_phy_get_controller(this_phy), 3946 this_phy->sata_timeout_timer 3947 ); 3948 } 3949 3950 /** 3951 * This method will perform the actions required by the SCIC_SDS_PHY on 3952 * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. 3953 * - Set the SCIC_SDS_PHY object state handlers for this state. 3954 * - Change base state machine to the ready state. 3955 * 3956 * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3957 * SCIC_SDS_PHY object. 3958 * 3959 * @return none 3960 */ 3961 static 3962 void scic_sds_phy_starting_final_substate_enter( 3963 SCI_BASE_OBJECT_T *object 3964 ) 3965 { 3966 SCIC_SDS_PHY_T *this_phy; 3967 this_phy = (SCIC_SDS_PHY_T *)object; 3968 3969 scic_sds_phy_set_starting_substate_handlers( 3970 this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL 3971 ); 3972 3973 // State machine has run to completion so exit out and change 3974 // the base state machine to the ready state 3975 sci_base_state_machine_change_state( 3976 scic_sds_phy_get_base_state_machine(this_phy), 3977 SCI_BASE_PHY_STATE_READY); 3978 } 3979 3980 // --------------------------------------------------------------------------- 3981 3982 SCI_BASE_STATE_T 3983 scic_sds_phy_starting_substates[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] = 3984 { 3985 { 3986 SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL, 3987 scic_sds_phy_starting_initial_substate_enter, 3988 NULL, 3989 }, 3990 { 3991 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN, 3992 scic_sds_phy_starting_await_ossp_en_substate_enter, 3993 NULL, 3994 }, 3995 { 3996 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN, 3997 scic_sds_phy_starting_await_sas_speed_en_substate_enter, 3998 NULL, 3999 }, 4000 { 4001 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF, 4002 scic_sds_phy_starting_await_iaf_uf_substate_enter, 4003 NULL, 4004 }, 4005 { 4006 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER, 4007 scic_sds_phy_starting_await_sas_power_substate_enter, 4008 scic_sds_phy_starting_await_sas_power_substate_exit, 4009 }, 4010 { 4011 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, 4012 scic_sds_phy_starting_await_sata_power_substate_enter, 4013 scic_sds_phy_starting_await_sata_power_substate_exit 4014 }, 4015 { 4016 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, 4017 scic_sds_phy_starting_await_sata_phy_substate_enter, 4018 scic_sds_phy_starting_await_sata_phy_substate_exit 4019 }, 4020 { 4021 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, 4022 scic_sds_phy_starting_await_sata_speed_substate_enter, 4023 scic_sds_phy_starting_await_sata_speed_substate_exit 4024 }, 4025 { 4026 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, 4027 scic_sds_phy_starting_await_sig_fis_uf_substate_enter, 4028 scic_sds_phy_starting_await_sig_fis_uf_substate_exit 4029 }, 4030 { 4031 SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL, 4032 scic_sds_phy_starting_final_substate_enter, 4033 NULL, 4034 } 4035 }; 4036 4037