1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0 3 * 4 * This file is provided under a dual BSD/GPLv2 license. When using or 5 * redistributing this file, you may do so under either license. 6 * 7 * GPL LICENSE SUMMARY 8 * 9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of version 2 of the GNU General Public License as 13 * published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 23 * The full GNU General Public License is included in this distribution 24 * in the file called LICENSE.GPL. 25 * 26 * BSD LICENSE 27 * 28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 35 * * Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * * Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in 39 * the documentation and/or other materials provided with the 40 * distribution. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 */ 54 55 #include <sys/cdefs.h> 56 /** 57 * @file 58 * 59 * @brief This file contains the structures, constants, and prototypes 60 * associated with the remote node context in the silicon. It 61 * exists to model and manage the remote node context in the silicon. 62 */ 63 64 #include <dev/isci/scil/sci_util.h> 65 #include <dev/isci/scil/scic_sds_logger.h> 66 #include <dev/isci/scil/scic_sds_controller.h> 67 #include <dev/isci/scil/scic_sds_remote_device.h> 68 #include <dev/isci/scil/scic_sds_remote_node_context.h> 69 #include <dev/isci/scil/sci_base_state_machine.h> 70 #include <dev/isci/scil/scic_remote_device.h> 71 #include <dev/isci/scil/scic_sds_port.h> 72 #include <dev/isci/scil/scu_event_codes.h> 73 #include <dev/isci/scil/scu_task_context.h> 74 75 /** 76 * @brief 77 */ 78 void scic_sds_remote_node_context_construct( 79 SCIC_SDS_REMOTE_DEVICE_T * device, 80 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc, 81 U16 remote_node_index 82 ) 83 { 84 memset (rnc, 0, sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T) ); 85 86 rnc->remote_node_index = remote_node_index; 87 rnc->device = device; 88 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; 89 90 rnc->parent.logger = device->parent.parent.logger; 91 92 sci_base_state_machine_construct( 93 &rnc->state_machine, 94 &rnc->parent, 95 scic_sds_remote_node_context_state_table, 96 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE 97 ); 98 99 sci_base_state_machine_start(&rnc->state_machine); 100 101 // State logging initialization takes place late for the remote node context 102 // see the resume state handler for the initial state. 103 } 104 105 /** 106 * This method will return TRUE if the RNC is not in the initial state. In 107 * all other states the RNC is considered active and this will return TRUE. 108 * 109 * @note The destroy request of the state machine drives the RNC back to the 110 * initial state. If the state machine changes then this routine will 111 * also have to be changed. 112 * 113 * @param[in] this_rnc The RNC for which the is posted request is being made. 114 * 115 * @return BOOL 116 * @retval TRUE if the state machine is not in the initial state 117 * @retval FALSE if the state machine is in the initial state 118 */ 119 BOOL scic_sds_remote_node_context_is_initialized( 120 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc 121 ) 122 { 123 U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine); 124 125 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE) 126 { 127 return FALSE; 128 } 129 130 return TRUE; 131 } 132 133 /** 134 * This method will return TRUE if the remote node context is in a READY state 135 * otherwise it will return FALSE 136 * 137 * @param[in] this_rnc The state of the remote node context object to check. 138 * 139 * @return BOOL 140 * @retval TRUE if the remote node context is in the ready state. 141 * @retval FALSE if the remote node context is not in the ready state. 142 */ 143 BOOL scic_sds_remote_node_context_is_ready( 144 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc 145 ) 146 { 147 U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine); 148 149 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) 150 { 151 return TRUE; 152 } 153 154 return FALSE; 155 } 156 157 /** 158 * This method will construct the RNC buffer for this remote device object. 159 * 160 * @param[in] this_device The remote device to use to construct the RNC 161 * buffer. 162 * @param[in] rnc The buffer into which the remote device data will be copied. 163 * 164 * @return none 165 */ 166 void scic_sds_remote_node_context_construct_buffer( 167 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc 168 ) 169 { 170 SCU_REMOTE_NODE_CONTEXT_T * rnc; 171 SCIC_SDS_CONTROLLER_T * the_controller; 172 173 the_controller = scic_sds_remote_device_get_controller(this_rnc->device); 174 175 rnc = scic_sds_controller_get_remote_node_context_buffer( 176 the_controller, this_rnc->remote_node_index); 177 178 memset( 179 rnc, 180 0x00, 181 sizeof(SCU_REMOTE_NODE_CONTEXT_T) 182 * scic_sds_remote_device_node_count(this_rnc->device) 183 ); 184 185 rnc->ssp.remote_node_index = this_rnc->remote_node_index; 186 rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width; 187 rnc->ssp.logical_port_index = 188 scic_sds_remote_device_get_port_index(this_rnc->device); 189 190 rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high); 191 rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low); 192 193 rnc->ssp.nexus_loss_timer_enable = TRUE; 194 rnc->ssp.check_bit = FALSE; 195 rnc->ssp.is_valid = FALSE; 196 rnc->ssp.is_remote_node_context = TRUE; 197 rnc->ssp.function_number = 0; 198 199 rnc->ssp.arbitration_wait_time = 0; 200 201 202 if ( 203 this_rnc->device->target_protocols.u.bits.attached_sata_device 204 || this_rnc->device->target_protocols.u.bits.attached_stp_target 205 ) 206 { 207 rnc->ssp.connection_occupancy_timeout = 208 the_controller->user_parameters.sds1.stp_max_occupancy_timeout; 209 rnc->ssp.connection_inactivity_timeout = 210 the_controller->user_parameters.sds1.stp_inactivity_timeout; 211 } 212 else 213 { 214 rnc->ssp.connection_occupancy_timeout = 215 the_controller->user_parameters.sds1.ssp_max_occupancy_timeout; 216 rnc->ssp.connection_inactivity_timeout = 217 the_controller->user_parameters.sds1.ssp_inactivity_timeout; 218 } 219 220 rnc->ssp.initial_arbitration_wait_time = 0; 221 222 // Open Address Frame Parameters 223 rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate; 224 rnc->ssp.oaf_features = 0; 225 rnc->ssp.oaf_source_zone_group = 0; 226 rnc->ssp.oaf_more_compatibility_features = 0; 227 } 228 229 // --------------------------------------------------------------------------- 230 231 #ifdef SCI_LOGGING 232 /** 233 * This method will enable and turn on state transition logging for the remote 234 * node context object. 235 * 236 * @param[in] this_rnc The remote node context for which state transition 237 * logging is to be enabled. 238 * 239 * @return none 240 */ 241 void scic_sds_remote_node_context_initialize_state_logging( 242 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc 243 ) 244 { 245 sci_base_state_machine_logger_initialize( 246 &this_rnc->state_machine_logger, 247 &this_rnc->state_machine, 248 &this_rnc->parent, 249 scic_cb_logger_log_states, 250 "SCIC_SDS_REMOTE_NODE_CONTEXT_T", "state machine", 251 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 252 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 253 SCIC_LOG_OBJECT_STP_REMOTE_TARGET 254 ); 255 } 256 257 /** 258 * This method will stop the state machine logging for this object and should 259 * be called before the object is destroyed. 260 * 261 * @param[in] this_rnc The remote node context on which to stop logging state 262 * transitions. 263 * 264 * @return none 265 */ 266 void scic_sds_remote_node_context_deinitialize_state_logging( 267 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc 268 ) 269 { 270 sci_base_state_machine_logger_deinitialize( 271 &this_rnc->state_machine_logger, 272 &this_rnc->state_machine 273 ); 274 } 275 #endif 276 277 /** 278 * This method will setup the remote node context object so it will transition 279 * to its ready state. If the remote node context is already setup to 280 * transition to its final state then this function does nothing. 281 * 282 * @param[in] this_rnc 283 * @param[in] the_callback 284 * @param[in] callback_parameter 285 * 286 * @return none 287 */ 288 static 289 void scic_sds_remote_node_context_setup_to_resume( 290 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 291 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 292 void * callback_parameter 293 ) 294 { 295 if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) 296 { 297 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY; 298 this_rnc->user_callback = the_callback; 299 this_rnc->user_cookie = callback_parameter; 300 } 301 } 302 303 /** 304 * This method will setup the remote node context object so it will 305 * transition to its final state. 306 * 307 * @param[in] this_rnc 308 * @param[in] the_callback 309 * @param[in] callback_parameter 310 * 311 * @return none 312 */ 313 static 314 void scic_sds_remote_node_context_setup_to_destory( 315 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 316 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 317 void * callback_parameter 318 ) 319 { 320 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL; 321 this_rnc->user_callback = the_callback; 322 this_rnc->user_cookie = callback_parameter; 323 } 324 325 /** 326 * This method will continue to resume a remote node context. This is used 327 * in the states where a resume is requested while a resume is in progress. 328 * 329 * @param[in] this_rnc 330 * @param[in] the_callback 331 * @param[in] callback_parameter 332 */ 333 static 334 SCI_STATUS scic_sds_remote_node_context_continue_to_resume_handler( 335 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 336 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 337 void * callback_parameter 338 ) 339 { 340 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) 341 { 342 this_rnc->user_callback = the_callback; 343 this_rnc->user_cookie = callback_parameter; 344 345 return SCI_SUCCESS; 346 } 347 348 return SCI_FAILURE_INVALID_STATE; 349 } 350 351 //****************************************************************************** 352 //* REMOTE NODE CONTEXT STATE MACHINE 353 //****************************************************************************** 354 355 static 356 SCI_STATUS scic_sds_remote_node_context_default_destruct_handler( 357 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 358 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 359 void * callback_parameter 360 ) 361 { 362 SCIC_LOG_WARNING(( 363 sci_base_object_get_logger(this_rnc->device), 364 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 365 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 366 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 367 "SCIC Remote Node Context 0x%x requested to stop while in unexpected state %d\n", 368 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine) 369 )); 370 371 // We have decided that the destruct request on the remote node context can not fail 372 // since it is either in the initial/destroyed state or is can be destroyed. 373 return SCI_SUCCESS; 374 } 375 376 static 377 SCI_STATUS scic_sds_remote_node_context_default_suspend_handler( 378 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 379 U32 suspend_type, 380 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 381 void * callback_parameter 382 ) 383 { 384 SCIC_LOG_WARNING(( 385 sci_base_object_get_logger(this_rnc->device), 386 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 387 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 388 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 389 "SCIC Remote Node Context 0x%x requested to suspend while in wrong state %d\n", 390 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine) 391 )); 392 393 return SCI_FAILURE_INVALID_STATE; 394 } 395 396 static 397 SCI_STATUS scic_sds_remote_node_context_default_resume_handler( 398 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 399 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 400 void * callback_parameter 401 ) 402 { 403 SCIC_LOG_WARNING(( 404 sci_base_object_get_logger(this_rnc->device), 405 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 406 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 407 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 408 "SCIC Remote Node Context 0x%x requested to resume while in wrong state %d\n", 409 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine) 410 )); 411 412 return SCI_FAILURE_INVALID_STATE; 413 } 414 415 static 416 SCI_STATUS scic_sds_remote_node_context_default_start_io_handler( 417 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 418 struct SCIC_SDS_REQUEST * the_request 419 ) 420 { 421 SCIC_LOG_WARNING(( 422 sci_base_object_get_logger(this_rnc->device), 423 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 424 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 425 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 426 "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n", 427 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine) 428 )); 429 430 return SCI_FAILURE_INVALID_STATE; 431 } 432 433 static 434 SCI_STATUS scic_sds_remote_node_context_default_start_task_handler( 435 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 436 struct SCIC_SDS_REQUEST * the_request 437 ) 438 { 439 SCIC_LOG_WARNING(( 440 sci_base_object_get_logger(this_rnc->device), 441 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 442 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 443 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 444 "SCIC Remote Node Context 0x%x requested to start task 0x%x while in wrong state %d\n", 445 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine) 446 )); 447 448 return SCI_FAILURE; 449 } 450 451 static 452 SCI_STATUS scic_sds_remote_node_context_default_event_handler( 453 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 454 U32 event_code 455 ) 456 { 457 SCIC_LOG_WARNING(( 458 sci_base_object_get_logger(this_rnc->device), 459 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 460 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 461 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 462 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in wrong state %d\n", 463 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine) 464 )); 465 466 return SCI_FAILURE_INVALID_STATE; 467 } 468 469 /** 470 * This method determines if the task request can be started by the SCU 471 * hardware. When the RNC is in the ready state any task can be started. 472 * 473 * @param[in] this_rnc The rnc for which the task request is targeted. 474 * @param[in] the_request The request which is going to be started. 475 * 476 * @return SCI_STATUS 477 * @retval SCI_SUCCESS 478 */ 479 static 480 SCI_STATUS scic_sds_remote_node_context_success_start_task_handler( 481 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 482 struct SCIC_SDS_REQUEST * the_request 483 ) 484 { 485 return SCI_SUCCESS; 486 } 487 488 /** 489 * This method handles destruct calls from the various state handlers. The 490 * remote node context can be requested to destroy from any state. If there 491 * was a user callback it is always replaced with the request to destroy user 492 * callback. 493 * 494 * @param[in] this_rnc 495 * @param[in] the_callback 496 * @param[in] callback_parameter 497 * 498 * @return SCI_STATUS 499 */ 500 static 501 SCI_STATUS scic_sds_remote_node_context_general_destruct_handler( 502 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 503 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 504 void * callback_parameter 505 ) 506 { 507 scic_sds_remote_node_context_setup_to_destory( 508 this_rnc, the_callback, callback_parameter 509 ); 510 511 sci_base_state_machine_change_state( 512 &this_rnc->state_machine, 513 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE 514 ); 515 516 return SCI_SUCCESS; 517 } 518 // --------------------------------------------------------------------------- 519 static 520 SCI_STATUS scic_sds_remote_node_context_reset_required_start_io_handler( 521 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 522 struct SCIC_SDS_REQUEST * the_request 523 ) 524 { 525 SCIC_LOG_WARNING(( 526 sci_base_object_get_logger(this_rnc->device), 527 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 528 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 529 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 530 "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n", 531 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine) 532 )); 533 534 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; 535 } 536 537 // --------------------------------------------------------------------------- 538 539 static 540 SCI_STATUS scic_sds_remote_node_context_initial_state_resume_handler( 541 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 542 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 543 void * callback_parameter 544 ) 545 { 546 if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) 547 { 548 scic_sds_remote_node_context_setup_to_resume( 549 this_rnc, the_callback, callback_parameter 550 ); 551 552 scic_sds_remote_node_context_construct_buffer(this_rnc); 553 554 #if defined (SCI_LOGGING) 555 // If a remote node context has a logger already, don't work on its state 556 // logging. 557 if (this_rnc->state_machine.previous_state_id 558 != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE) 559 scic_sds_remote_node_context_initialize_state_logging(this_rnc); 560 #endif 561 562 sci_base_state_machine_change_state( 563 &this_rnc->state_machine, 564 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE 565 ); 566 567 return SCI_SUCCESS; 568 } 569 570 return SCI_FAILURE_INVALID_STATE; 571 } 572 573 // --------------------------------------------------------------------------- 574 575 static 576 SCI_STATUS scic_sds_remote_node_context_posting_state_event_handler( 577 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 578 U32 event_code 579 ) 580 { 581 SCI_STATUS status; 582 583 switch (scu_get_event_code(event_code)) 584 { 585 case SCU_EVENT_POST_RNC_COMPLETE: 586 status = SCI_SUCCESS; 587 588 sci_base_state_machine_change_state( 589 &this_rnc->state_machine, 590 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE 591 ); 592 break; 593 594 default: 595 status = SCI_FAILURE; 596 SCIC_LOG_WARNING(( 597 sci_base_object_get_logger(this_rnc->device), 598 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 599 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 600 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 601 "SCIC Remote Node Context 0x%x requested to process unexpected event 0x%x while in posting state\n", 602 this_rnc, event_code 603 )); 604 break; 605 } 606 607 return status; 608 } 609 610 // --------------------------------------------------------------------------- 611 612 static 613 SCI_STATUS scic_sds_remote_node_context_invalidating_state_destruct_handler( 614 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 615 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 616 void * callback_parameter 617 ) 618 { 619 scic_sds_remote_node_context_setup_to_destory( 620 this_rnc, the_callback, callback_parameter 621 ); 622 623 return SCI_SUCCESS; 624 } 625 626 static 627 SCI_STATUS scic_sds_remote_node_context_invalidating_state_event_handler( 628 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 629 U32 event_code 630 ) 631 { 632 SCI_STATUS status; 633 634 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) 635 { 636 status = SCI_SUCCESS; 637 638 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) 639 { 640 sci_base_state_machine_change_state( 641 &this_rnc->state_machine, 642 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE 643 ); 644 } 645 else 646 { 647 sci_base_state_machine_change_state( 648 &this_rnc->state_machine, 649 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE 650 ); 651 } 652 } 653 else 654 { 655 switch (scu_get_event_type(event_code)) 656 { 657 case SCU_EVENT_TYPE_RNC_SUSPEND_TX: 658 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: 659 // We really dont care if the hardware is going to suspend 660 // the device since it's being invalidated anyway 661 SCIC_LOG_INFO(( 662 sci_base_object_get_logger(this_rnc->device), 663 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 664 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 665 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 666 "SCIC Remote Node Context 0x%x was suspeneded by hardware while being invalidated.\n", 667 this_rnc 668 )); 669 status = SCI_SUCCESS; 670 break; 671 672 default: 673 SCIC_LOG_WARNING(( 674 sci_base_object_get_logger(this_rnc->device), 675 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 676 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 677 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 678 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n", 679 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine) 680 )); 681 status = SCI_FAILURE; 682 break; 683 } 684 } 685 686 return status; 687 } 688 689 // --------------------------------------------------------------------------- 690 691 static 692 SCI_STATUS scic_sds_remote_node_context_resuming_state_event_handler( 693 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 694 U32 event_code 695 ) 696 { 697 SCI_STATUS status; 698 699 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) 700 { 701 status = SCI_SUCCESS; 702 703 sci_base_state_machine_change_state( 704 &this_rnc->state_machine, 705 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE 706 ); 707 } 708 else 709 { 710 switch (scu_get_event_type(event_code)) 711 { 712 case SCU_EVENT_TYPE_RNC_SUSPEND_TX: 713 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: 714 // We really dont care if the hardware is going to suspend 715 // the device since it's being resumed anyway 716 SCIC_LOG_INFO(( 717 sci_base_object_get_logger(this_rnc->device), 718 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 719 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 720 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 721 "SCIC Remote Node Context 0x%x was suspeneded by hardware while being resumed.\n", 722 this_rnc 723 )); 724 status = SCI_SUCCESS; 725 break; 726 727 default: 728 SCIC_LOG_WARNING(( 729 sci_base_object_get_logger(this_rnc->device), 730 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 731 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 732 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 733 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n", 734 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine) 735 )); 736 status = SCI_FAILURE; 737 break; 738 } 739 } 740 741 return status; 742 } 743 744 // --------------------------------------------------------------------------- 745 746 /** 747 * This method will handle the suspend requests from the ready state. 748 * 749 * @param[in] this_rnc The remote node context object being suspended. 750 * @param[in] the_callback The callback when the suspension is complete. 751 * @param[in] callback_parameter The parameter that is to be passed into the 752 * callback. 753 * 754 * @return SCI_SUCCESS 755 */ 756 static 757 SCI_STATUS scic_sds_remote_node_context_ready_state_suspend_handler( 758 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 759 U32 suspend_type, 760 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 761 void * callback_parameter 762 ) 763 { 764 this_rnc->user_callback = the_callback; 765 this_rnc->user_cookie = callback_parameter; 766 this_rnc->suspension_code = suspend_type; 767 768 if (suspend_type == SCI_SOFTWARE_SUSPENSION) 769 { 770 scic_sds_remote_device_post_request( 771 this_rnc->device, 772 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX 773 ); 774 } 775 776 sci_base_state_machine_change_state( 777 &this_rnc->state_machine, 778 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE 779 ); 780 781 return SCI_SUCCESS; 782 } 783 784 /** 785 * This method determines if the io request can be started by the SCU 786 * hardware. When the RNC is in the ready state any io request can be started. 787 * 788 * @param[in] this_rnc The rnc for which the io request is targeted. 789 * @param[in] the_request The request which is going to be started. 790 * 791 * @return SCI_STATUS 792 * @retval SCI_SUCCESS 793 */ 794 static 795 SCI_STATUS scic_sds_remote_node_context_ready_state_start_io_handler( 796 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 797 struct SCIC_SDS_REQUEST * the_request 798 ) 799 { 800 return SCI_SUCCESS; 801 } 802 803 804 static 805 SCI_STATUS scic_sds_remote_node_context_ready_state_event_handler( 806 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 807 U32 event_code 808 ) 809 { 810 SCI_STATUS status; 811 812 switch (scu_get_event_type(event_code)) 813 { 814 case SCU_EVENT_TL_RNC_SUSPEND_TX: 815 sci_base_state_machine_change_state( 816 &this_rnc->state_machine, 817 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE 818 ); 819 820 this_rnc->suspension_code = scu_get_event_specifier(event_code); 821 status = SCI_SUCCESS; 822 break; 823 824 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: 825 sci_base_state_machine_change_state( 826 &this_rnc->state_machine, 827 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE 828 ); 829 830 this_rnc->suspension_code = scu_get_event_specifier(event_code); 831 status = SCI_SUCCESS; 832 break; 833 834 default: 835 SCIC_LOG_WARNING(( 836 sci_base_object_get_logger(this_rnc->device), 837 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 838 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 839 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 840 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n", 841 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine) 842 )); 843 844 status = SCI_FAILURE; 845 break; 846 } 847 848 return status; 849 } 850 851 // --------------------------------------------------------------------------- 852 853 static 854 SCI_STATUS scic_sds_remote_node_context_tx_suspended_state_resume_handler( 855 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 856 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 857 void * callback_parameter 858 ) 859 { 860 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols; 861 862 scic_sds_remote_node_context_setup_to_resume( 863 this_rnc, the_callback, callback_parameter 864 ); 865 866 // If this is an expander attached SATA device we must invalidate 867 // and repost the RNC since this is the only way to clear the 868 // TCi to NCQ tag mapping table for the RNi 869 // All other device types we can just resume. 870 scic_remote_device_get_protocols(this_rnc->device, &protocols); 871 872 if ( 873 (protocols.u.bits.attached_stp_target == 1) 874 && !(this_rnc->device->is_direct_attached) 875 ) 876 { 877 sci_base_state_machine_change_state( 878 &this_rnc->state_machine, 879 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE 880 ); 881 } 882 else 883 { 884 sci_base_state_machine_change_state( 885 &this_rnc->state_machine, 886 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE 887 ); 888 } 889 890 return SCI_SUCCESS; 891 } 892 893 /** 894 * This method will report a success or failure attempt to start a new task 895 * request to the hardware. Since all task requests are sent on the high 896 * priority queue they can be sent when the RCN is in a TX suspend state. 897 * 898 * @param[in] this_rnc The remote node context which is to receive the task 899 * request. 900 * @param[in] the_request The task request to be transmitted to the remote 901 * target device. 902 * 903 * @return SCI_STATUS 904 * @retval SCI_SUCCESS 905 */ 906 static 907 SCI_STATUS scic_sds_remote_node_context_suspended_start_task_handler( 908 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 909 struct SCIC_SDS_REQUEST * the_request 910 ) 911 { 912 scic_sds_remote_node_context_resume(this_rnc, NULL, NULL); 913 914 return SCI_SUCCESS; 915 } 916 917 // --------------------------------------------------------------------------- 918 919 static 920 SCI_STATUS scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler( 921 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 922 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 923 void * callback_parameter 924 ) 925 { 926 scic_sds_remote_node_context_setup_to_resume( 927 this_rnc, the_callback, callback_parameter 928 ); 929 930 sci_base_state_machine_change_state( 931 &this_rnc->state_machine, 932 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE 933 ); 934 935 return SCI_FAILURE_INVALID_STATE; 936 } 937 938 // --------------------------------------------------------------------------- 939 940 /** 941 * 942 */ 943 static 944 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_resume_handler( 945 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, 946 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, 947 void * callback_parameter 948 ) 949 { 950 scic_sds_remote_node_context_setup_to_resume( 951 this_rnc, the_callback, callback_parameter 952 ); 953 954 return SCI_SUCCESS; 955 } 956 957 /** 958 * This method will report a success or failure attempt to start a new task 959 * request to the hardware. Since all task requests are sent on the high 960 * priority queue they can be sent when the RCN is in a TX suspend state. 961 * 962 * @param[in] this_rnc The remote node context which is to receive the task 963 * request. 964 * @param[in] the_request The task request to be transmitted to the remote 965 * target device. 966 * 967 * @return SCI_STATUS 968 * @retval SCI_SUCCESS 969 */ 970 static 971 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_start_task_handler( 972 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 973 struct SCIC_SDS_REQUEST * the_request 974 ) 975 { 976 return SCI_SUCCESS; 977 } 978 979 static 980 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_event_handler( 981 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, 982 U32 event_code 983 ) 984 { 985 SCI_STATUS status; 986 987 switch (scu_get_event_type(event_code)) 988 { 989 case SCU_EVENT_TL_RNC_SUSPEND_TX: 990 sci_base_state_machine_change_state( 991 &this_rnc->state_machine, 992 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE 993 ); 994 995 this_rnc->suspension_code = scu_get_event_specifier(event_code); 996 status = SCI_SUCCESS; 997 break; 998 999 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: 1000 sci_base_state_machine_change_state( 1001 &this_rnc->state_machine, 1002 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE 1003 ); 1004 1005 this_rnc->suspension_code = scu_get_event_specifier(event_code); 1006 status = SCI_SUCCESS; 1007 break; 1008 1009 default: 1010 SCIC_LOG_WARNING(( 1011 sci_base_object_get_logger(this_rnc->device), 1012 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1013 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1014 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1015 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n", 1016 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine) 1017 )); 1018 1019 status = SCI_FAILURE; 1020 break; 1021 } 1022 1023 return status; 1024 } 1025 1026 // --------------------------------------------------------------------------- 1027 1028 SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS 1029 scic_sds_remote_node_context_state_handler_table[ 1030 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] = 1031 { 1032 // SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE 1033 { 1034 scic_sds_remote_node_context_default_destruct_handler, 1035 scic_sds_remote_node_context_default_suspend_handler, 1036 scic_sds_remote_node_context_initial_state_resume_handler, 1037 scic_sds_remote_node_context_default_start_io_handler, 1038 scic_sds_remote_node_context_default_start_task_handler, 1039 scic_sds_remote_node_context_default_event_handler 1040 }, 1041 // SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE 1042 { 1043 scic_sds_remote_node_context_general_destruct_handler, 1044 scic_sds_remote_node_context_default_suspend_handler, 1045 scic_sds_remote_node_context_continue_to_resume_handler, 1046 scic_sds_remote_node_context_default_start_io_handler, 1047 scic_sds_remote_node_context_default_start_task_handler, 1048 scic_sds_remote_node_context_posting_state_event_handler 1049 }, 1050 // SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE 1051 { 1052 scic_sds_remote_node_context_invalidating_state_destruct_handler, 1053 scic_sds_remote_node_context_default_suspend_handler, 1054 scic_sds_remote_node_context_continue_to_resume_handler, 1055 scic_sds_remote_node_context_default_start_io_handler, 1056 scic_sds_remote_node_context_default_start_task_handler, 1057 scic_sds_remote_node_context_invalidating_state_event_handler 1058 }, 1059 // SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE 1060 { 1061 scic_sds_remote_node_context_general_destruct_handler, 1062 scic_sds_remote_node_context_default_suspend_handler, 1063 scic_sds_remote_node_context_continue_to_resume_handler, 1064 scic_sds_remote_node_context_default_start_io_handler, 1065 scic_sds_remote_node_context_success_start_task_handler, 1066 scic_sds_remote_node_context_resuming_state_event_handler 1067 }, 1068 // SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE 1069 { 1070 scic_sds_remote_node_context_general_destruct_handler, 1071 scic_sds_remote_node_context_ready_state_suspend_handler, 1072 scic_sds_remote_node_context_default_resume_handler, 1073 scic_sds_remote_node_context_ready_state_start_io_handler, 1074 scic_sds_remote_node_context_success_start_task_handler, 1075 scic_sds_remote_node_context_ready_state_event_handler 1076 }, 1077 // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE 1078 { 1079 scic_sds_remote_node_context_general_destruct_handler, 1080 scic_sds_remote_node_context_default_suspend_handler, 1081 scic_sds_remote_node_context_tx_suspended_state_resume_handler, 1082 scic_sds_remote_node_context_reset_required_start_io_handler, 1083 scic_sds_remote_node_context_suspended_start_task_handler, 1084 scic_sds_remote_node_context_default_event_handler 1085 }, 1086 // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE 1087 { 1088 scic_sds_remote_node_context_general_destruct_handler, 1089 scic_sds_remote_node_context_default_suspend_handler, 1090 scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler, 1091 scic_sds_remote_node_context_reset_required_start_io_handler, 1092 scic_sds_remote_node_context_suspended_start_task_handler, 1093 scic_sds_remote_node_context_default_event_handler 1094 }, 1095 // SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE 1096 { 1097 scic_sds_remote_node_context_general_destruct_handler, 1098 scic_sds_remote_node_context_default_suspend_handler, 1099 scic_sds_remote_node_context_await_suspension_state_resume_handler, 1100 scic_sds_remote_node_context_reset_required_start_io_handler, 1101 scic_sds_remote_node_context_await_suspension_state_start_task_handler, 1102 scic_sds_remote_node_context_await_suspension_state_event_handler 1103 } 1104 }; 1105 1106 //***************************************************************************** 1107 //* REMOTE NODE CONTEXT PRIVATE METHODS 1108 //***************************************************************************** 1109 1110 /** 1111 * This method just calls the user callback function and then resets the 1112 * callback. 1113 * 1114 * @param[in out] rnc 1115 */ 1116 static 1117 void scic_sds_remote_node_context_notify_user( 1118 SCIC_SDS_REMOTE_NODE_CONTEXT_T *rnc 1119 ) 1120 { 1121 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK local_user_callback = rnc->user_callback; 1122 void * local_user_cookie = rnc->user_cookie; 1123 1124 //we need to set the user_callback to NULL before it is called, because 1125 //the user callback's stack may eventually also set up a new set of 1126 //user callback. If we nullify the user_callback after it is called, 1127 //we are in the risk to lose the freshly set user callback. 1128 rnc->user_callback = NULL; 1129 rnc->user_cookie = NULL; 1130 1131 if (local_user_callback != NULL) 1132 { 1133 (*local_user_callback)(local_user_cookie); 1134 } 1135 } 1136 1137 /** 1138 * This method will continue the remote node context state machine by 1139 * requesting to resume the remote node context state machine from its current 1140 * state. 1141 * 1142 * @param[in] rnc 1143 */ 1144 static 1145 void scic_sds_remote_node_context_continue_state_transitions( 1146 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc 1147 ) 1148 { 1149 if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) 1150 { 1151 rnc->state_handlers->resume_handler( 1152 rnc, rnc->user_callback, rnc->user_cookie 1153 ); 1154 } 1155 } 1156 1157 /** 1158 * This method will mark the rnc buffer as being valid and post the request to 1159 * the hardware. 1160 * 1161 * @param[in] this_rnc The remote node context object that is to be 1162 * validated. 1163 * 1164 * @return none 1165 */ 1166 static 1167 void scic_sds_remote_node_context_validate_context_buffer( 1168 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc 1169 ) 1170 { 1171 SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer; 1172 1173 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( 1174 scic_sds_remote_device_get_controller(this_rnc->device), 1175 this_rnc->remote_node_index 1176 ); 1177 1178 rnc_buffer->ssp.is_valid = TRUE; 1179 1180 if ( 1181 !this_rnc->device->is_direct_attached 1182 && this_rnc->device->target_protocols.u.bits.attached_stp_target 1183 ) 1184 { 1185 scic_sds_remote_device_post_request( 1186 this_rnc->device, 1187 SCU_CONTEXT_COMMAND_POST_RNC_96 1188 ); 1189 } 1190 else 1191 { 1192 scic_sds_remote_device_post_request( 1193 this_rnc->device, 1194 SCU_CONTEXT_COMMAND_POST_RNC_32 1195 ); 1196 1197 if (this_rnc->device->is_direct_attached) 1198 { 1199 scic_sds_port_setup_transports( 1200 this_rnc->device->owning_port, 1201 this_rnc->remote_node_index 1202 ); 1203 } 1204 } 1205 } 1206 1207 /** 1208 * This method will update the RNC buffer and post the invalidate request. 1209 * 1210 * @param[in] this_rnc The remote node context object that is to be 1211 * invalidated. 1212 * 1213 * @return none 1214 */ 1215 static 1216 void scic_sds_remote_node_context_invalidate_context_buffer( 1217 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc 1218 ) 1219 { 1220 SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer; 1221 1222 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( 1223 scic_sds_remote_device_get_controller(this_rnc->device), 1224 this_rnc->remote_node_index 1225 ); 1226 1227 rnc_buffer->ssp.is_valid = FALSE; 1228 1229 scic_sds_remote_device_post_request( 1230 this_rnc->device, 1231 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE 1232 ); 1233 } 1234 1235 //***************************************************************************** 1236 //* REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS 1237 //***************************************************************************** 1238 1239 /** 1240 * 1241 * 1242 * @param[in] object 1243 */ 1244 static 1245 void scic_sds_remote_node_context_initial_state_enter( 1246 SCI_BASE_OBJECT_T * object 1247 ) 1248 { 1249 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc; 1250 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object; 1251 1252 SET_STATE_HANDLER( 1253 rnc, 1254 scic_sds_remote_node_context_state_handler_table, 1255 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE 1256 ); 1257 1258 // Check to see if we have gotten back to the initial state because someone 1259 // requested to destroy the remote node context object. 1260 if ( 1261 rnc->state_machine.previous_state_id 1262 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE 1263 ) 1264 { 1265 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; 1266 1267 scic_sds_remote_node_context_notify_user(rnc); 1268 1269 // Since we are destroying the remote node context deinitialize the state logging 1270 // should we resume the remote node context the state logging will be reinitialized 1271 // on the resume handler. 1272 scic_sds_remote_node_context_deinitialize_state_logging(rnc); 1273 } 1274 } 1275 1276 /** 1277 * 1278 * 1279 * @param[in] object 1280 */ 1281 static 1282 void scic_sds_remote_node_context_posting_state_enter( 1283 SCI_BASE_OBJECT_T * object 1284 ) 1285 { 1286 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc; 1287 this_rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object; 1288 1289 SET_STATE_HANDLER( 1290 this_rnc, 1291 scic_sds_remote_node_context_state_handler_table, 1292 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE 1293 ); 1294 1295 scic_sds_remote_node_context_validate_context_buffer(this_rnc); 1296 } 1297 1298 /** 1299 * 1300 * 1301 * @param[in] object 1302 */ 1303 static 1304 void scic_sds_remote_node_context_invalidating_state_enter( 1305 SCI_BASE_OBJECT_T * object 1306 ) 1307 { 1308 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc; 1309 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object; 1310 1311 SET_STATE_HANDLER( 1312 rnc, 1313 scic_sds_remote_node_context_state_handler_table, 1314 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE 1315 ); 1316 1317 scic_sds_remote_node_context_invalidate_context_buffer(rnc); 1318 } 1319 1320 /** 1321 * 1322 * 1323 * @param[in] object 1324 */ 1325 static 1326 void scic_sds_remote_node_context_resuming_state_enter( 1327 SCI_BASE_OBJECT_T * object 1328 ) 1329 { 1330 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc; 1331 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols; 1332 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object; 1333 1334 SET_STATE_HANDLER( 1335 rnc, 1336 scic_sds_remote_node_context_state_handler_table, 1337 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE 1338 ); 1339 1340 // For direct attached SATA devices we need to clear the TLCR 1341 // NCQ to TCi tag mapping on the phy and in cases where we 1342 // resume because of a target reset we also need to update 1343 // the STPTLDARNI register with the RNi of the device 1344 scic_remote_device_get_protocols(rnc->device, &protocols); 1345 1346 if ( 1347 (protocols.u.bits.attached_stp_target == 1) 1348 && (rnc->device->is_direct_attached) 1349 ) 1350 { 1351 scic_sds_port_setup_transports( 1352 rnc->device->owning_port, rnc->remote_node_index 1353 ); 1354 } 1355 1356 scic_sds_remote_device_post_request( 1357 rnc->device, 1358 SCU_CONTEXT_COMMAND_POST_RNC_RESUME 1359 ); 1360 } 1361 1362 /** 1363 * 1364 * 1365 * @param[in] object 1366 */ 1367 static 1368 void scic_sds_remote_node_context_ready_state_enter( 1369 SCI_BASE_OBJECT_T * object 1370 ) 1371 { 1372 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc; 1373 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object; 1374 1375 SET_STATE_HANDLER( 1376 rnc, 1377 scic_sds_remote_node_context_state_handler_table, 1378 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE 1379 ); 1380 1381 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; 1382 1383 if (rnc->user_callback != NULL) 1384 { 1385 scic_sds_remote_node_context_notify_user(rnc); 1386 } 1387 } 1388 1389 /** 1390 * 1391 * 1392 * @param[in] object 1393 */ 1394 static 1395 void scic_sds_remote_node_context_tx_suspended_state_enter( 1396 SCI_BASE_OBJECT_T * object 1397 ) 1398 { 1399 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc; 1400 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object; 1401 1402 SET_STATE_HANDLER( 1403 rnc, 1404 scic_sds_remote_node_context_state_handler_table, 1405 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE 1406 ); 1407 1408 scic_sds_remote_node_context_continue_state_transitions(rnc); 1409 } 1410 1411 /** 1412 * 1413 * 1414 * @param[in] object 1415 */ 1416 static 1417 void scic_sds_remote_node_context_tx_rx_suspended_state_enter( 1418 SCI_BASE_OBJECT_T * object 1419 ) 1420 { 1421 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc; 1422 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object; 1423 1424 SET_STATE_HANDLER( 1425 rnc, 1426 scic_sds_remote_node_context_state_handler_table, 1427 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE 1428 ); 1429 1430 scic_sds_remote_node_context_continue_state_transitions(rnc); 1431 } 1432 1433 /** 1434 * 1435 * 1436 * @param[in] object 1437 */ 1438 static 1439 void scic_sds_remote_node_context_await_suspension_state_enter( 1440 SCI_BASE_OBJECT_T * object 1441 ) 1442 { 1443 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc; 1444 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object; 1445 1446 SET_STATE_HANDLER( 1447 rnc, 1448 scic_sds_remote_node_context_state_handler_table, 1449 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE 1450 ); 1451 } 1452 1453 // --------------------------------------------------------------------------- 1454 1455 SCI_BASE_STATE_T 1456 scic_sds_remote_node_context_state_table[ 1457 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] = 1458 { 1459 { 1460 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE, 1461 scic_sds_remote_node_context_initial_state_enter, 1462 NULL 1463 }, 1464 { 1465 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE, 1466 scic_sds_remote_node_context_posting_state_enter, 1467 NULL 1468 }, 1469 { 1470 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE, 1471 scic_sds_remote_node_context_invalidating_state_enter, 1472 NULL 1473 }, 1474 { 1475 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE, 1476 scic_sds_remote_node_context_resuming_state_enter, 1477 NULL 1478 }, 1479 { 1480 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE, 1481 scic_sds_remote_node_context_ready_state_enter, 1482 NULL 1483 }, 1484 { 1485 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE, 1486 scic_sds_remote_node_context_tx_suspended_state_enter, 1487 NULL 1488 }, 1489 { 1490 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE, 1491 scic_sds_remote_node_context_tx_rx_suspended_state_enter, 1492 NULL 1493 }, 1494 { 1495 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE, 1496 scic_sds_remote_node_context_await_suspension_state_enter, 1497 NULL 1498 } 1499 }; 1500 1501