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