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