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*/ 290static 291void 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*/ 315static 316void 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*/ 335static 336SCI_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 357static 358SCI_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 378static 379SCI_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 398static 399SCI_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 417static 418SCI_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 435static 436SCI_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 453static 454SCI_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*/ 481static 482SCI_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*/ 502static 503SCI_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// --------------------------------------------------------------------------- 521static 522SCI_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 541static 542SCI_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 577static 578SCI_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 614static 615SCI_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 628static 629SCI_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 693static 694SCI_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*/ 758static 759SCI_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*/ 796static 797SCI_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 806static 807SCI_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 855static 856SCI_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*/ 908static 909SCI_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 921static 922SCI_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*/ 945static 946SCI_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*/ 972static 973SCI_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 981static 982SCI_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*/ 1118static 1119void 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*/ 1146static 1147void 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*/ 1168static 1169void 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*/ 1217static 1218void 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*/ 1246static 1247void 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*/ 1283static 1284void 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*/ 1305static 1306void 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*/ 1327static 1328void 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*/ 1369static 1370void 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*/ 1396static 1397void 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*/ 1418static 1419void 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*/ 1440static 1441void 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