1 /*- 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of version 2 of the GNU General Public License as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21 * The full GNU General Public License is included in this distribution 22 * in the file called LICENSE.GPL. 23 * 24 * BSD LICENSE 25 * 26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * * Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * * Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 */ 52 53 #include <sys/cdefs.h> 54 __FBSDID("$FreeBSD$"); 55 56 /** 57 * @file 58 * 59 * @brief This file contains the implementation of remote device, it's 60 * methods and state machine. 61 */ 62 63 #include <dev/isci/scil/intel_sas.h> 64 #include <dev/isci/scil/sci_util.h> 65 #include <dev/isci/scil/scic_port.h> 66 #include <dev/isci/scil/scic_phy.h> 67 #include <dev/isci/scil/scic_remote_device.h> 68 #include <dev/isci/scil/scic_sds_port.h> 69 #include <dev/isci/scil/scic_sds_phy.h> 70 #include <dev/isci/scil/scic_sds_remote_device.h> 71 #include <dev/isci/scil/scic_sds_request.h> 72 #include <dev/isci/scil/scic_sds_controller.h> 73 #include <dev/isci/scil/scic_sds_logger.h> 74 #include <dev/isci/scil/scic_user_callback.h> 75 #include <dev/isci/scil/scic_controller.h> 76 #include <dev/isci/scil/scic_sds_logger.h> 77 #include <dev/isci/scil/scic_sds_remote_node_context.h> 78 #include <dev/isci/scil/scu_event_codes.h> 79 80 #define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT (1000) 81 82 //***************************************************************************** 83 //* CORE REMOTE DEVICE PUBLIC METHODS 84 //***************************************************************************** 85 86 U32 scic_remote_device_get_object_size(void) 87 { 88 return sizeof(SCIC_SDS_REMOTE_DEVICE_T) 89 + sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T); 90 } 91 92 // --------------------------------------------------------------------------- 93 94 void scic_remote_device_construct( 95 SCI_PORT_HANDLE_T port, 96 void * remote_device_memory, 97 SCI_REMOTE_DEVICE_HANDLE_T * new_remote_device_handle 98 ) 99 { 100 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T*) 101 remote_device_memory; 102 SCIC_SDS_PORT_T *the_port = (SCIC_SDS_PORT_T*) port; 103 104 SCIC_LOG_TRACE(( 105 sci_base_object_get_logger(the_port), 106 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 107 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 108 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 109 "scic_remote_device_construct(0x%x, 0x%x, 0x%x) enter\n", 110 port, remote_device_memory, new_remote_device_handle 111 )); 112 113 memset(remote_device_memory, 0, sizeof(SCIC_SDS_REMOTE_DEVICE_T)); 114 115 *new_remote_device_handle = this_device; 116 this_device->owning_port = the_port; 117 this_device->started_request_count = 0; 118 this_device->rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *) 119 ((char *)this_device + sizeof(SCIC_SDS_REMOTE_DEVICE_T)); 120 121 sci_base_remote_device_construct( 122 &this_device->parent, 123 sci_base_object_get_logger(the_port), 124 scic_sds_remote_device_state_table 125 ); 126 127 scic_sds_remote_node_context_construct( 128 this_device, 129 this_device->rnc, 130 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 131 ); 132 133 sci_object_set_association(this_device->rnc, this_device); 134 135 scic_sds_remote_device_initialize_state_logging(this_device); 136 } 137 138 // --------------------------------------------------------------------------- 139 140 SCI_STATUS scic_remote_device_da_construct( 141 SCI_REMOTE_DEVICE_HANDLE_T remote_device 142 ) 143 { 144 SCI_STATUS status; 145 U16 remote_node_index; 146 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T*) 147 remote_device; 148 SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T protocols; 149 SCIC_PORT_PROPERTIES_T properties; 150 151 SCIC_LOG_TRACE(( 152 sci_base_object_get_logger(this_device->owning_port), 153 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 154 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 155 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 156 "scic_remote_device_da_construct(0x%x) enter\n", 157 remote_device 158 )); 159 160 // This information is request to determine how many remote node context 161 // entries will be needed to store the remote node. 162 scic_sds_port_get_attached_protocols(this_device->owning_port,&protocols); 163 this_device->target_protocols.u.all = protocols.u.all; 164 this_device->is_direct_attached = TRUE; 165 #if !defined(DISABLE_ATAPI) 166 this_device->is_atapi = scic_sds_remote_device_is_atapi(this_device); 167 #endif 168 169 scic_port_get_properties(this_device->owning_port, &properties); 170 //Get accurate port width from port's phy mask for a DA device. 171 SCI_GET_BITS_SET_COUNT(properties.phy_mask, this_device->device_port_width); 172 173 status = scic_sds_controller_allocate_remote_node_context( 174 this_device->owning_port->owning_controller, 175 this_device, 176 &remote_node_index 177 ); 178 179 if (status == SCI_SUCCESS) 180 { 181 scic_sds_remote_node_context_set_remote_node_index( 182 this_device->rnc, remote_node_index 183 ); 184 185 scic_sds_port_get_attached_sas_address( 186 this_device->owning_port, &this_device->device_address 187 ); 188 189 if (this_device->target_protocols.u.bits.attached_ssp_target) 190 { 191 this_device->has_ready_substate_machine = FALSE; 192 } 193 else if (this_device->target_protocols.u.bits.attached_stp_target) 194 { 195 this_device->has_ready_substate_machine = TRUE; 196 197 sci_base_state_machine_construct( 198 &this_device->ready_substate_machine, 199 &this_device->parent.parent, 200 scic_sds_stp_remote_device_ready_substate_table, 201 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE 202 ); 203 } 204 else if (this_device->target_protocols.u.bits.attached_smp_target) 205 { 206 this_device->has_ready_substate_machine = TRUE; 207 208 //add the SMP ready substate machine construction here 209 sci_base_state_machine_construct( 210 &this_device->ready_substate_machine, 211 &this_device->parent.parent, 212 scic_sds_smp_remote_device_ready_substate_table, 213 SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE 214 ); 215 } 216 217 this_device->connection_rate = scic_sds_port_get_max_allowed_speed( 218 this_device->owning_port 219 ); 220 221 /// @todo Should I assign the port width by reading all of the phys on the port? 222 this_device->device_port_width = 1; 223 } 224 225 return status; 226 } 227 228 229 // --------------------------------------------------------------------------- 230 231 void scic_sds_remote_device_get_info_from_smp_discover_response( 232 SCIC_SDS_REMOTE_DEVICE_T * this_device, 233 SMP_RESPONSE_DISCOVER_T * discover_response 234 ) 235 { 236 // decode discover_response to set sas_address to this_device. 237 this_device->device_address.high = 238 discover_response->attached_sas_address.high; 239 240 this_device->device_address.low = 241 discover_response->attached_sas_address.low; 242 243 this_device->target_protocols.u.all = discover_response->protocols.u.all; 244 } 245 246 247 // --------------------------------------------------------------------------- 248 249 SCI_STATUS scic_remote_device_ea_construct( 250 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 251 SMP_RESPONSE_DISCOVER_T * discover_response 252 ) 253 { 254 SCI_STATUS status; 255 256 SCIC_SDS_REMOTE_DEVICE_T *this_device; 257 SCIC_SDS_CONTROLLER_T *the_controller; 258 259 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 260 261 SCIC_LOG_TRACE(( 262 sci_base_object_get_logger(this_device->owning_port), 263 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 264 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 265 "scic_remote_device_ea_sas_construct0x%x, 0x%x) enter\n", 266 remote_device, discover_response 267 )); 268 269 the_controller = scic_sds_port_get_controller(this_device->owning_port); 270 271 scic_sds_remote_device_get_info_from_smp_discover_response( 272 this_device, discover_response 273 ); 274 275 status = scic_sds_controller_allocate_remote_node_context( 276 the_controller, 277 this_device, 278 &this_device->rnc->remote_node_index 279 ); 280 281 if (status == SCI_SUCCESS) 282 { 283 if (this_device->target_protocols.u.bits.attached_ssp_target) 284 { 285 this_device->has_ready_substate_machine = FALSE; 286 } 287 else if (this_device->target_protocols.u.bits.attached_smp_target) 288 { 289 this_device->has_ready_substate_machine = TRUE; 290 291 //add the SMP ready substate machine construction here 292 sci_base_state_machine_construct( 293 &this_device->ready_substate_machine, 294 &this_device->parent.parent, 295 scic_sds_smp_remote_device_ready_substate_table, 296 SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE 297 ); 298 } 299 else if (this_device->target_protocols.u.bits.attached_stp_target) 300 { 301 this_device->has_ready_substate_machine = TRUE; 302 303 sci_base_state_machine_construct( 304 &this_device->ready_substate_machine, 305 &this_device->parent.parent, 306 scic_sds_stp_remote_device_ready_substate_table, 307 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE 308 ); 309 } 310 311 // For SAS-2 the physical link rate is actually a logical link 312 // rate that incorporates multiplexing. The SCU doesn't 313 // incorporate multiplexing and for the purposes of the 314 // connection the logical link rate is that same as the 315 // physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay 316 // one another, so this code works for both situations. 317 this_device->connection_rate = MIN( 318 scic_sds_port_get_max_allowed_speed( this_device->owning_port), 319 discover_response->u2.sas1_1.negotiated_physical_link_rate 320 ); 321 322 /// @todo Should I assign the port width by reading all of the phys on the port? 323 this_device->device_port_width = 1; 324 } 325 326 return status; 327 } 328 329 // --------------------------------------------------------------------------- 330 331 SCI_STATUS scic_remote_device_destruct( 332 SCI_REMOTE_DEVICE_HANDLE_T remote_device 333 ) 334 { 335 SCIC_SDS_REMOTE_DEVICE_T *this_device; 336 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 337 338 SCIC_LOG_TRACE(( 339 sci_base_object_get_logger(this_device), 340 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 341 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 342 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 343 "scic_remote_device_destruct(0x%x) enter\n", 344 remote_device 345 )); 346 347 return this_device->state_handlers->parent.destruct_handler(&this_device->parent); 348 } 349 350 // --------------------------------------------------------------------------- 351 352 #if !defined(DISABLE_WIDE_PORTED_TARGETS) 353 354 SCI_STATUS scic_remote_device_set_port_width( 355 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 356 U8 new_port_width 357 ) 358 { 359 SCIC_SDS_REMOTE_DEVICE_T *this_device; 360 361 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 362 363 SCIC_LOG_TRACE(( 364 sci_base_object_get_logger(this_device), 365 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 366 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 367 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 368 "scic_remote_device_set_port_width(0x%x, 0x%x) enter\n", 369 remote_device, new_port_width 370 )); 371 372 if(new_port_width != 0) 373 { 374 this_device->device_port_width = new_port_width; 375 376 return SCI_SUCCESS; 377 } 378 else 379 return SCI_FAILURE; 380 } 381 382 // --------------------------------------------------------------------------- 383 384 U8 scic_remote_device_get_port_width( 385 SCI_REMOTE_DEVICE_HANDLE_T remote_device 386 ) 387 { 388 SCIC_SDS_REMOTE_DEVICE_T *this_device; 389 390 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 391 392 SCIC_LOG_TRACE(( 393 sci_base_object_get_logger(this_device), 394 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 395 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 396 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 397 "scic_remote_device_get_port_width(0x%x) enter\n", 398 remote_device 399 )); 400 401 return (U8)this_device->device_port_width; 402 } 403 404 #endif // !defined(DISABLE_WIDE_PORTED_TARGETS) 405 406 // --------------------------------------------------------------------------- 407 408 SCI_STATUS scic_remote_device_start( 409 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 410 U32 timeout 411 ) 412 { 413 SCIC_SDS_REMOTE_DEVICE_T *this_device; 414 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 415 416 SCIC_LOG_TRACE(( 417 sci_base_object_get_logger(this_device), 418 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 419 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 420 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 421 "scic_remote_device_start(0x%x, 0x%x) enter\n", 422 remote_device, timeout 423 )); 424 425 return this_device->state_handlers->parent.start_handler(&this_device->parent); 426 } 427 428 // --------------------------------------------------------------------------- 429 430 SCI_STATUS scic_remote_device_stop( 431 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 432 U32 timeout 433 ) 434 { 435 SCIC_SDS_REMOTE_DEVICE_T *this_device; 436 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 437 438 SCIC_LOG_TRACE(( 439 sci_base_object_get_logger(this_device), 440 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 441 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 442 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 443 "scic_remote_device_stop(0x%x, 0x%x) enter\n", 444 remote_device, timeout 445 )); 446 447 return this_device->state_handlers->parent.stop_handler(&this_device->parent); 448 } 449 450 /** 451 * This method invokes the remote device reset handler. 452 * 453 * @param[in] this_device The remote device for which the reset is being 454 * requested. 455 * 456 * @return SCI_STATUS 457 */ 458 SCI_STATUS scic_remote_device_reset( 459 SCI_REMOTE_DEVICE_HANDLE_T remote_device 460 ) 461 { 462 SCIC_SDS_REMOTE_DEVICE_T *this_device; 463 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 464 465 SCIC_LOG_TRACE(( 466 sci_base_object_get_logger(this_device), 467 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 468 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 469 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 470 "scic_remote_device_reset(0x%x) enter\n", 471 remote_device 472 )); 473 474 return this_device->state_handlers->parent.reset_handler(&this_device->parent); 475 } 476 477 /** 478 * This method invokes the remote device reset handler. 479 * 480 * @param[in] this_device The remote device for which the reset is being 481 * requested. 482 * 483 * @return SCI_STATUS 484 */ 485 SCI_STATUS scic_remote_device_reset_complete( 486 SCI_REMOTE_DEVICE_HANDLE_T remote_device 487 ) 488 { 489 SCIC_SDS_REMOTE_DEVICE_T *this_device; 490 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 491 492 SCIC_LOG_TRACE(( 493 sci_base_object_get_logger(this_device), 494 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 495 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 496 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 497 "scic_remote_device_reset_complete(0x%x) enter\n", 498 remote_device 499 )); 500 501 return this_device->state_handlers->parent.reset_complete_handler(&this_device->parent); 502 } 503 504 /** 505 * This method invokes the remote device reset handler. 506 * 507 * @param[in] this_device The remote device for which the reset is being 508 * requested. 509 * 510 * @return SCI_STATUS 511 */ 512 U32 scic_remote_device_get_suggested_reset_timeout( 513 SCI_REMOTE_DEVICE_HANDLE_T remote_device 514 ) 515 { 516 SCIC_SDS_REMOTE_DEVICE_T *this_device; 517 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 518 519 SCIC_LOG_TRACE(( 520 sci_base_object_get_logger(this_device), 521 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 522 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 523 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 524 "scic_remote_device_get_suggested_reset_timeout(0x%x) enter\n", 525 remote_device 526 )); 527 528 if (this_device->target_protocols.u.bits.attached_stp_target) 529 { 530 return SCIC_SDS_SIGNATURE_FIS_TIMEOUT; 531 } 532 533 return SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT; 534 } 535 536 // --------------------------------------------------------------------------- 537 538 SCI_STATUS scic_remote_device_set_max_connection_rate( 539 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 540 SCI_SAS_LINK_RATE connection_rate 541 ) 542 { 543 SCIC_SDS_REMOTE_DEVICE_T *this_device; 544 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 545 546 SCIC_LOG_TRACE(( 547 sci_base_object_get_logger(this_device), 548 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 549 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 550 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 551 "scic_remote_device_set_max_connection_rate(0x%x, 0x%x) enter\n", 552 remote_device, connection_rate 553 )); 554 555 this_device->connection_rate = connection_rate; 556 557 return SCI_SUCCESS; 558 } 559 560 // --------------------------------------------------------------------------- 561 562 SCI_SAS_LINK_RATE scic_remote_device_get_connection_rate( 563 SCI_REMOTE_DEVICE_HANDLE_T remote_device 564 ) 565 { 566 SCIC_SDS_REMOTE_DEVICE_T *this_device; 567 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 568 569 SCIC_LOG_TRACE(( 570 sci_base_object_get_logger(this_device), 571 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 572 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 573 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 574 "scic_remote_device_get_connection_rate(0x%x) enter\n", 575 remote_device 576 )); 577 578 return this_device->connection_rate; 579 } 580 581 // --------------------------------------------------------------------------- 582 583 void scic_remote_device_get_protocols( 584 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 585 SMP_DISCOVER_RESPONSE_PROTOCOLS_T * protocols 586 ) 587 { 588 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *) 589 remote_device; 590 591 SCIC_LOG_TRACE(( 592 sci_base_object_get_logger(this_device), 593 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 594 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 595 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 596 "scic_remote_device_get_protocols(0x%x) enter\n", 597 remote_device 598 )); 599 600 protocols->u.all = this_device->target_protocols.u.all; 601 } 602 603 // --------------------------------------------------------------------------- 604 605 void scic_remote_device_get_sas_address( 606 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 607 SCI_SAS_ADDRESS_T * sas_address 608 ) 609 { 610 SCIC_SDS_REMOTE_DEVICE_T *this_device; 611 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device; 612 613 SCIC_LOG_TRACE(( 614 sci_base_object_get_logger(this_device), 615 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 616 SCIC_LOG_OBJECT_STP_REMOTE_TARGET | 617 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 618 "scic_remote_device_get_sas_address(0x%x, 0x%x) enter\n", 619 remote_device, sas_address 620 )); 621 622 sas_address->low = this_device->device_address.low; 623 sas_address->high = this_device->device_address.high; 624 } 625 626 // --------------------------------------------------------------------------- 627 #if !defined(DISABLE_ATAPI) 628 BOOL scic_remote_device_is_atapi( 629 SCI_REMOTE_DEVICE_HANDLE_T device_handle 630 ) 631 { 632 return ((SCIC_SDS_REMOTE_DEVICE_T *)device_handle)->is_atapi; 633 } 634 #endif 635 636 637 //***************************************************************************** 638 //* SCU DRIVER STANDARD (SDS) REMOTE DEVICE IMPLEMENTATIONS 639 //***************************************************************************** 640 641 /** 642 * Remote device timer requirements 643 */ 644 #define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0) 645 #define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES) 646 647 /** 648 * @brief This method returns the minimum number of timers required for all 649 * remote devices. 650 * 651 * @return U32 652 */ 653 U32 scic_sds_remote_device_get_min_timer_count(void) 654 { 655 return SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT; 656 } 657 658 /** 659 * @brief This method returns the maximum number of timers requried for all 660 * remote devices. 661 * 662 * @return U32 663 */ 664 U32 scic_sds_remote_device_get_max_timer_count(void) 665 { 666 return SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT; 667 } 668 669 // --------------------------------------------------------------------------- 670 671 #ifdef SCI_LOGGING 672 /** 673 * This method will enable and turn on state transition logging for the remote 674 * device object. 675 * 676 * @param[in] this_device The device for which state transition logging is to 677 * be enabled. 678 * 679 * @return Nothing 680 */ 681 void scic_sds_remote_device_initialize_state_logging( 682 SCIC_SDS_REMOTE_DEVICE_T *this_device 683 ) 684 { 685 sci_base_state_machine_logger_initialize( 686 &this_device->parent.state_machine_logger, 687 &this_device->parent.state_machine, 688 &this_device->parent.parent, 689 scic_cb_logger_log_states, 690 "SCIC_SDS_REMOTE_DEVICE_T", "base state machine", 691 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 692 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 693 SCIC_LOG_OBJECT_STP_REMOTE_TARGET 694 ); 695 696 if (this_device->has_ready_substate_machine) 697 { 698 sci_base_state_machine_logger_initialize( 699 &this_device->ready_substate_machine_logger, 700 &this_device->ready_substate_machine, 701 &this_device->parent.parent, 702 scic_cb_logger_log_states, 703 "SCIC_SDS_REMOTE_DEVICE_T", "ready substate machine", 704 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 705 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 706 SCIC_LOG_OBJECT_STP_REMOTE_TARGET 707 ); 708 } 709 } 710 711 /** 712 * This method will stop the state machine logging for this object and should 713 * be called before the object is destroyed. 714 * 715 * @param[in] this_device The device on which to stop logging state 716 * transitions. 717 * 718 * @return Nothing 719 */ 720 void scic_sds_remote_device_deinitialize_state_logging( 721 SCIC_SDS_REMOTE_DEVICE_T *this_device 722 ) 723 { 724 sci_base_state_machine_logger_deinitialize( 725 &this_device->parent.state_machine_logger, 726 &this_device->parent.state_machine 727 ); 728 729 if (this_device->has_ready_substate_machine) 730 { 731 sci_base_state_machine_logger_deinitialize( 732 &this_device->ready_substate_machine_logger, 733 &this_device->ready_substate_machine 734 ); 735 } 736 } 737 #endif 738 739 /** 740 * This method invokes the remote device suspend state handler. 741 * 742 * @param[in] this_device The remote device for which the suspend is being 743 * requested. 744 * 745 * @return SCI_STATUS 746 */ 747 SCI_STATUS scic_sds_remote_device_suspend( 748 SCIC_SDS_REMOTE_DEVICE_T *this_device, 749 U32 suspend_type 750 ) 751 { 752 return this_device->state_handlers->suspend_handler(this_device, suspend_type); 753 } 754 755 /** 756 * This method invokes the remote device resume state handler. 757 * 758 * @param[in] this_device The remote device for which the resume is being 759 * requested. 760 * 761 * @return SCI_STATUS 762 */ 763 SCI_STATUS scic_sds_remote_device_resume( 764 SCIC_SDS_REMOTE_DEVICE_T *this_device 765 ) 766 { 767 return this_device->state_handlers->resume_handler(this_device); 768 } 769 770 /** 771 * This method invokes the frame handler for the remote device state machine 772 * 773 * @param[in] this_device The remote device for which the event handling is 774 * being requested. 775 * @param[in] frame_index This is the frame index that is being processed. 776 * 777 * @return SCI_STATUS 778 */ 779 SCI_STATUS scic_sds_remote_device_frame_handler( 780 SCIC_SDS_REMOTE_DEVICE_T *this_device, 781 U32 frame_index 782 ) 783 { 784 return this_device->state_handlers->frame_handler(this_device, frame_index); 785 } 786 787 /** 788 * This method invokes the remote device event handler. 789 * 790 * @param[in] this_device The remote device for which the event handling is 791 * being requested. 792 * @param[in] event_code This is the event code that is to be processed. 793 * 794 * @return SCI_STATUS 795 */ 796 SCI_STATUS scic_sds_remote_device_event_handler( 797 SCIC_SDS_REMOTE_DEVICE_T *this_device, 798 U32 event_code 799 ) 800 { 801 return this_device->state_handlers->event_handler(this_device, event_code); 802 } 803 804 /** 805 * This method invokes the remote device start io handler. 806 * 807 * @param[in] controller The controller that is starting the io request. 808 * @param[in] this_device The remote device for which the start io handling is 809 * being requested. 810 * @param[in] io_request The io request that is being started. 811 * 812 * @return SCI_STATUS 813 */ 814 SCI_STATUS scic_sds_remote_device_start_io( 815 SCIC_SDS_CONTROLLER_T *controller, 816 SCIC_SDS_REMOTE_DEVICE_T *this_device, 817 SCIC_SDS_REQUEST_T *io_request 818 ) 819 { 820 return this_device->state_handlers->parent.start_io_handler( 821 &this_device->parent, &io_request->parent); 822 } 823 824 /** 825 * This method invokes the remote device complete io handler. 826 * 827 * @param[in] controller The controller that is completing the io request. 828 * @param[in] this_device The remote device for which the complete io handling 829 * is being requested. 830 * @param[in] io_request The io request that is being completed. 831 * 832 * @return SCI_STATUS 833 */ 834 SCI_STATUS scic_sds_remote_device_complete_io( 835 SCIC_SDS_CONTROLLER_T *controller, 836 SCIC_SDS_REMOTE_DEVICE_T *this_device, 837 SCIC_SDS_REQUEST_T *io_request 838 ) 839 { 840 return this_device->state_handlers->parent.complete_io_handler( 841 &this_device->parent, &io_request->parent); 842 } 843 844 /** 845 * This method invokes the remote device start task handler. 846 * 847 * @param[in] controller The controller that is starting the task request. 848 * @param[in] this_device The remote device for which the start task handling 849 * is being requested. 850 * @param[in] io_request The task request that is being started. 851 * 852 * @return SCI_STATUS 853 */ 854 SCI_STATUS scic_sds_remote_device_start_task( 855 SCIC_SDS_CONTROLLER_T *controller, 856 SCIC_SDS_REMOTE_DEVICE_T *this_device, 857 SCIC_SDS_REQUEST_T *io_request 858 ) 859 { 860 return this_device->state_handlers->parent.start_task_handler( 861 &this_device->parent, &io_request->parent); 862 } 863 864 /** 865 * This method takes the request and bulids an appropriate SCU context for the 866 * request and then requests the controller to post the request. 867 * 868 * @param[in] this_device 869 * @param[in] request 870 * 871 * @return none 872 */ 873 void scic_sds_remote_device_post_request( 874 SCIC_SDS_REMOTE_DEVICE_T * this_device, 875 U32 request 876 ) 877 { 878 U32 context; 879 880 context = scic_sds_remote_device_build_command_context(this_device, request); 881 882 scic_sds_controller_post_request( 883 scic_sds_remote_device_get_controller(this_device), 884 context 885 ); 886 } 887 888 #if !defined(DISABLE_ATAPI) 889 /** 890 * This method check the signature fis of a stp device to decide whether 891 * a device is atapi or not. 892 * 893 * @param[in] this_device The device to be checked. 894 * 895 * @return TRUE if a device is atapi device. False if a device is not atapi. 896 */ 897 BOOL scic_sds_remote_device_is_atapi( 898 SCIC_SDS_REMOTE_DEVICE_T * this_device 899 ) 900 { 901 if (!this_device->target_protocols.u.bits.attached_stp_target) 902 return FALSE; 903 else if (this_device->is_direct_attached) 904 { 905 SCIC_SDS_PHY_T * phy; 906 SCIC_SATA_PHY_PROPERTIES_T properties; 907 SATA_FIS_REG_D2H_T * signature_fis; 908 phy = scic_sds_port_get_a_connected_phy(this_device->owning_port); 909 scic_sata_phy_get_properties(phy, &properties); 910 911 //decode the signature fis. 912 signature_fis = &(properties.signature_fis); 913 914 if ( (signature_fis->sector_count == 0x01) 915 && (signature_fis->lba_low == 0x01) 916 && (signature_fis->lba_mid == 0x14) 917 && (signature_fis->lba_high == 0xEB) 918 && ( (signature_fis->device & 0x5F) == 0x00) 919 ) 920 { 921 // An ATA device supporting the PACKET command set. 922 return TRUE; 923 } 924 else 925 return FALSE; 926 } 927 else 928 { 929 //Expander supported ATAPI device is not currently supported. 930 return FALSE; 931 } 932 } 933 934 #endif // !defined(DISABLE_ATAPI) 935 936 //****************************************************************************** 937 //* REMOTE DEVICE STATE MACHINE 938 //****************************************************************************** 939 940 /** 941 * This method is called once the remote node context is ready to be 942 * freed. The remote device can now report that its stop operation is 943 * complete. 944 * 945 * @param[in] user_parameter This is cast to a remote device object. 946 * 947 * @return none 948 */ 949 static 950 void scic_sds_cb_remote_device_rnc_destruct_complete( 951 void * user_parameter 952 ) 953 { 954 SCIC_SDS_REMOTE_DEVICE_T * this_device; 955 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_parameter; 956 957 ASSERT(this_device->started_request_count == 0); 958 959 sci_base_state_machine_change_state( 960 scic_sds_remote_device_get_base_state_machine(this_device), 961 SCI_BASE_REMOTE_DEVICE_STATE_STOPPED 962 ); 963 } 964 965 /** 966 * This method is called once the remote node context has transisitioned to a 967 * ready state. This is the indication that the remote device object can also 968 * transition to ready. 969 * 970 * @param[in] user_parameter This is cast to a remote device object. 971 * 972 * @return none 973 */ 974 static 975 void scic_sds_remote_device_resume_complete_handler( 976 void * user_parameter 977 ) 978 { 979 SCIC_SDS_REMOTE_DEVICE_T * this_device; 980 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_parameter; 981 982 if ( 983 sci_base_state_machine_get_state(&this_device->parent.state_machine) 984 != SCI_BASE_REMOTE_DEVICE_STATE_READY 985 ) 986 { 987 sci_base_state_machine_change_state( 988 &this_device->parent.state_machine, 989 SCI_BASE_REMOTE_DEVICE_STATE_READY 990 ); 991 } 992 } 993 994 /** 995 * This method will perform the STP request start processing common 996 * to IO requests and task requests of all types. 997 * 998 * @param[in] device This parameter specifies the device for which the 999 * request is being started. 1000 * @param[in] request This parameter specifies the request being started. 1001 * @param[in] status This parameter specifies the current start operation 1002 * status. 1003 * 1004 * @return none 1005 */ 1006 void scic_sds_remote_device_start_request( 1007 SCIC_SDS_REMOTE_DEVICE_T * this_device, 1008 SCIC_SDS_REQUEST_T * the_request, 1009 SCI_STATUS status 1010 ) 1011 { 1012 // We still have a fault in starting the io complete it on the port 1013 if (status == SCI_SUCCESS) 1014 scic_sds_remote_device_increment_request_count(this_device); 1015 else 1016 { 1017 this_device->owning_port->state_handlers->complete_io_handler( 1018 this_device->owning_port, this_device, the_request 1019 ); 1020 } 1021 } 1022 1023 1024 /** 1025 * This method will continue to post tc for a STP request. This method usually 1026 * serves as a callback when RNC gets resumed during a task management sequence. 1027 * 1028 * @param[in] request This parameter specifies the request being continued. 1029 * 1030 * @return none 1031 */ 1032 void scic_sds_remote_device_continue_request( 1033 SCIC_SDS_REMOTE_DEVICE_T * this_device 1034 ) 1035 { 1036 // we need to check if this request is still valid to continue. 1037 if (this_device->working_request != NULL) 1038 { 1039 SCIC_SDS_REQUEST_T * this_request = this_device->working_request; 1040 1041 this_request->owning_controller->state_handlers->parent.continue_io_handler( 1042 &this_request->owning_controller->parent, 1043 &this_request->target_device->parent, 1044 &this_request->parent 1045 ); 1046 } 1047 } 1048 1049 /** 1050 * @brief This method will terminate all of the IO requests in the 1051 * controllers IO request table that were targeted for this 1052 * device. 1053 * 1054 * @param[in] this_device This parameter specifies the remote device 1055 * for which to attempt to terminate all requests. 1056 * 1057 * @return This method returns an indication as to whether all requests 1058 * were successfully terminated. If a single request fails to 1059 * be terminated, then this method will return the failure. 1060 */ 1061 static 1062 SCI_STATUS scic_sds_remote_device_terminate_requests( 1063 SCIC_SDS_REMOTE_DEVICE_T *this_device 1064 ) 1065 { 1066 return scic_sds_terminate_reqests( 1067 this_device->owning_port->owning_controller, 1068 this_device, 1069 NULL); 1070 } 1071 1072 //***************************************************************************** 1073 //* DEFAULT STATE HANDLERS 1074 //***************************************************************************** 1075 1076 /** 1077 * This method is the default start handler. It logs a warning and returns a 1078 * failure. 1079 * 1080 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1081 * SCIC_SDS_REMOTE_DEVICE. 1082 * 1083 * @return SCI_STATUS 1084 * @retval SCI_FAILURE_INVALID_STATE 1085 */ 1086 SCI_STATUS scic_sds_remote_device_default_start_handler( 1087 SCI_BASE_REMOTE_DEVICE_T *device 1088 ) 1089 { 1090 SCIC_LOG_WARNING(( 1091 sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device), 1092 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1093 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1094 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1095 "SCIC Remote Device requested to start while in wrong state %d\n", 1096 sci_base_state_machine_get_state( 1097 scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device)) 1098 )); 1099 1100 return SCI_FAILURE_INVALID_STATE; 1101 } 1102 1103 /** 1104 * This method is the default stop handler. It logs a warning and returns a 1105 * failure. 1106 * 1107 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1108 * SCIC_SDS_REMOTE_DEVICE. 1109 * 1110 * @return SCI_STATUS 1111 * @retval SCI_FAILURE_INVALID_STATE 1112 */ 1113 SCI_STATUS scic_sds_remote_device_default_stop_handler( 1114 SCI_BASE_REMOTE_DEVICE_T *device 1115 ) 1116 { 1117 SCIC_LOG_WARNING(( 1118 sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device), 1119 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1120 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1121 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1122 "SCIC Remote Device requested to stop while in wrong state %d\n", 1123 sci_base_state_machine_get_state( 1124 scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device)) 1125 )); 1126 1127 return SCI_FAILURE_INVALID_STATE; 1128 } 1129 1130 /** 1131 * This method is the default fail handler. It logs a warning and returns a 1132 * failure. 1133 * 1134 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1135 * SCIC_SDS_REMOTE_DEVICE. 1136 * 1137 * @return SCI_STATUS 1138 * @retval SCI_FAILURE_INVALID_STATE 1139 */ 1140 SCI_STATUS scic_sds_remote_device_default_fail_handler( 1141 SCI_BASE_REMOTE_DEVICE_T *device 1142 ) 1143 { 1144 SCIC_LOG_WARNING(( 1145 sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device), 1146 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1147 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1148 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1149 "SCIC Remote Device requested to fail while in wrong state %d\n", 1150 sci_base_state_machine_get_state( 1151 scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device)) 1152 )); 1153 1154 return SCI_FAILURE_INVALID_STATE; 1155 } 1156 1157 /** 1158 * This method is the default destruct handler. It logs a warning and returns 1159 * a failure. 1160 * 1161 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1162 * SCIC_SDS_REMOTE_DEVICE. 1163 * 1164 * @return SCI_STATUS 1165 * @retval SCI_FAILURE_INVALID_STATE 1166 */ 1167 SCI_STATUS scic_sds_remote_device_default_destruct_handler( 1168 SCI_BASE_REMOTE_DEVICE_T *device 1169 ) 1170 { 1171 SCIC_LOG_WARNING(( 1172 sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device), 1173 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1174 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1175 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1176 "SCIC Remote Device requested to destroy while in wrong state %d\n", 1177 sci_base_state_machine_get_state( 1178 scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device)) 1179 )); 1180 1181 return SCI_FAILURE_INVALID_STATE; 1182 } 1183 1184 /** 1185 * This method is the default reset handler. It logs a warning and returns a 1186 * failure. 1187 * 1188 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1189 * SCIC_SDS_REMOTE_DEVICE. 1190 * 1191 * @return SCI_STATUS 1192 * @retval SCI_FAILURE_INVALID_STATE 1193 */ 1194 SCI_STATUS scic_sds_remote_device_default_reset_handler( 1195 SCI_BASE_REMOTE_DEVICE_T *device 1196 ) 1197 { 1198 SCIC_LOG_WARNING(( 1199 sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device), 1200 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1201 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1202 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1203 "SCIC Remote Device requested to reset while in wrong state %d\n", 1204 sci_base_state_machine_get_state( 1205 scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device)) 1206 )); 1207 1208 return SCI_FAILURE_INVALID_STATE; 1209 } 1210 1211 /** 1212 * This method is the default reset complete handler. It logs a warning and 1213 * returns a failure. 1214 * 1215 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1216 * SCIC_SDS_REMOTE_DEVICE. 1217 * 1218 * @return SCI_STATUS 1219 * @retval SCI_FAILURE_INVALID_STATE 1220 */ 1221 SCI_STATUS scic_sds_remote_device_default_reset_complete_handler( 1222 SCI_BASE_REMOTE_DEVICE_T *device 1223 ) 1224 { 1225 SCIC_LOG_WARNING(( 1226 sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device), 1227 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1228 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1229 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1230 "SCIC Remote Device requested to complete reset while in wrong state %d\n", 1231 sci_base_state_machine_get_state( 1232 scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device)) 1233 )); 1234 1235 return SCI_FAILURE_INVALID_STATE; 1236 } 1237 1238 /** 1239 * This method is the default suspend handler. It logs a warning and returns 1240 * a failure. 1241 * 1242 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1243 * SCIC_SDS_REMOTE_DEVICE. 1244 * 1245 * @return SCI_STATUS 1246 * @retval SCI_FAILURE_INVALID_STATE 1247 */ 1248 SCI_STATUS scic_sds_remote_device_default_suspend_handler( 1249 SCIC_SDS_REMOTE_DEVICE_T *this_device, 1250 U32 suspend_type 1251 ) 1252 { 1253 SCIC_LOG_WARNING(( 1254 sci_base_object_get_logger(this_device), 1255 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1256 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1257 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1258 "SCIC Remote Device 0x%x requested to suspend %d while in wrong state %d\n", 1259 this_device, suspend_type, 1260 sci_base_state_machine_get_state( 1261 scic_sds_remote_device_get_base_state_machine(this_device)) 1262 )); 1263 1264 return SCI_FAILURE_INVALID_STATE; 1265 } 1266 1267 /** 1268 * This method is the default resume handler. It logs a warning and returns a 1269 * failure. 1270 * 1271 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1272 * SCIC_SDS_REMOTE_DEVICE. 1273 * 1274 * @return SCI_STATUS 1275 * @retval SCI_FAILURE_INVALID_STATE 1276 */ 1277 SCI_STATUS scic_sds_remote_device_default_resume_handler( 1278 SCIC_SDS_REMOTE_DEVICE_T *this_device 1279 ) 1280 { 1281 SCIC_LOG_WARNING(( 1282 sci_base_object_get_logger(this_device), 1283 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1284 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1285 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1286 "SCIC Remote Device requested to resume while in wrong state %d\n", 1287 sci_base_state_machine_get_state( 1288 scic_sds_remote_device_get_base_state_machine(this_device)) 1289 )); 1290 1291 return SCI_FAILURE_INVALID_STATE; 1292 } 1293 1294 #if defined(SCI_LOGGING) 1295 /** 1296 * This is a private method for emitting log messages related to events reported 1297 * to the remote device from the controller object. 1298 * 1299 * @param [in] this_device This is the device object that is receiving the 1300 * event. 1301 * @param [in] event_code The event code to process. 1302 * 1303 * @return None 1304 */ 1305 static void scic_sds_emit_event_log_message( 1306 SCIC_SDS_REMOTE_DEVICE_T * this_device, 1307 U32 event_code, 1308 char * message_guts, 1309 BOOL ready_state 1310 ) 1311 { 1312 SCIC_LOG_WARNING(( 1313 sci_base_object_get_logger(this_device), 1314 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1315 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1316 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1317 "SCIC Remote device 0x%x (state %d) received %s %x while in the %sready %s%d\n", 1318 this_device, 1319 sci_base_state_machine_get_state( 1320 scic_sds_remote_device_get_base_state_machine(this_device)), 1321 message_guts, event_code, 1322 (ready_state) 1323 ? "" 1324 : "not ", 1325 (this_device->has_ready_substate_machine) 1326 ? "substate " 1327 : "", 1328 (this_device->has_ready_substate_machine) 1329 ? sci_base_state_machine_get_state(&this_device->ready_substate_machine) 1330 : 0 1331 )); 1332 } 1333 #else // defined(SCI_LOGGING) 1334 #define scic_sds_emit_event_log_message(device, event_code, message, state) 1335 #endif // defined(SCI_LOGGING) 1336 1337 /** 1338 * This method is the default event handler. It will call the RNC state 1339 * machine handler for any RNC events otherwise it will log a warning and 1340 * returns a failure. 1341 * 1342 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1343 * SCIC_SDS_REMOTE_DEVICE. 1344 * @param[in] event_code The event code that the SCIC_SDS_CONTROLLER wants the 1345 * device object to process. 1346 * 1347 * @return SCI_STATUS 1348 * @retval SCI_FAILURE_INVALID_STATE 1349 */ 1350 static 1351 SCI_STATUS scic_sds_remote_device_core_event_handler( 1352 SCIC_SDS_REMOTE_DEVICE_T *this_device, 1353 U32 event_code, 1354 BOOL is_ready_state 1355 ) 1356 { 1357 SCI_STATUS status; 1358 1359 switch (scu_get_event_type(event_code)) 1360 { 1361 case SCU_EVENT_TYPE_RNC_OPS_MISC: 1362 case SCU_EVENT_TYPE_RNC_SUSPEND_TX: 1363 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: 1364 status = scic_sds_remote_node_context_event_handler(this_device->rnc, event_code); 1365 break; 1366 case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: 1367 1368 if( scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT ) 1369 { 1370 status = SCI_SUCCESS; 1371 1372 // Suspend the associated RNC 1373 scic_sds_remote_node_context_suspend( this_device->rnc, 1374 SCI_SOFTWARE_SUSPENSION, 1375 NULL, NULL ); 1376 1377 scic_sds_emit_event_log_message( 1378 this_device, event_code, 1379 (is_ready_state) 1380 ? "I_T_Nexus_Timeout event" 1381 : "I_T_Nexus_Timeout event in wrong state", 1382 is_ready_state ); 1383 1384 break; 1385 } 1386 // Else, fall through and treat as unhandled... 1387 1388 default: 1389 scic_sds_emit_event_log_message( this_device, event_code, 1390 (is_ready_state) 1391 ? "unexpected event" 1392 : "unexpected event in wrong state", 1393 is_ready_state ); 1394 status = SCI_FAILURE_INVALID_STATE; 1395 break; 1396 } 1397 1398 return status; 1399 } 1400 /** 1401 * This method is the default event handler. It will call the RNC state 1402 * machine handler for any RNC events otherwise it will log a warning and 1403 * returns a failure. 1404 * 1405 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1406 * SCIC_SDS_REMOTE_DEVICE. 1407 * @param[in] event_code The event code that the SCIC_SDS_CONTROLLER wants the 1408 * device object to process. 1409 * 1410 * @return SCI_STATUS 1411 * @retval SCI_FAILURE_INVALID_STATE 1412 */ 1413 SCI_STATUS scic_sds_remote_device_default_event_handler( 1414 SCIC_SDS_REMOTE_DEVICE_T *this_device, 1415 U32 event_code 1416 ) 1417 { 1418 return scic_sds_remote_device_core_event_handler( this_device, 1419 event_code, 1420 FALSE ); 1421 } 1422 1423 /** 1424 * This method is the default unsolicited frame handler. It logs a warning, 1425 * releases the frame and returns a failure. 1426 * 1427 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1428 * SCIC_SDS_REMOTE_DEVICE. 1429 * @param[in] frame_index The frame index for which the SCIC_SDS_CONTROLLER 1430 * wants this device object to process. 1431 * 1432 * @return SCI_STATUS 1433 * @retval SCI_FAILURE_INVALID_STATE 1434 */ 1435 SCI_STATUS scic_sds_remote_device_default_frame_handler( 1436 SCIC_SDS_REMOTE_DEVICE_T *this_device, 1437 U32 frame_index 1438 ) 1439 { 1440 SCIC_LOG_WARNING(( 1441 sci_base_object_get_logger(this_device), 1442 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1443 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1444 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1445 "SCIC Remote Device requested to handle frame %x while in wrong state %d\n", 1446 frame_index, 1447 sci_base_state_machine_get_state(&this_device->parent.state_machine) 1448 )); 1449 1450 // Return the frame back to the controller 1451 scic_sds_controller_release_frame( 1452 scic_sds_remote_device_get_controller(this_device), frame_index 1453 ); 1454 1455 return SCI_FAILURE_INVALID_STATE; 1456 } 1457 1458 /** 1459 * This method is the default start io handler. It logs a warning and returns 1460 * a failure. 1461 * 1462 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1463 * SCIC_SDS_REMOTE_DEVICE. 1464 * @param[in] request The SCI_BASE_REQUEST which is then cast into a 1465 * SCIC_SDS_IO_REQUEST to start. 1466 * 1467 * @return SCI_STATUS 1468 * @retval SCI_FAILURE_INVALID_STATE 1469 */ 1470 SCI_STATUS scic_sds_remote_device_default_start_request_handler( 1471 SCI_BASE_REMOTE_DEVICE_T *device, 1472 SCI_BASE_REQUEST_T *request 1473 ) 1474 { 1475 SCIC_LOG_WARNING(( 1476 sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device), 1477 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1478 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1479 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1480 "SCIC Remote Device requested to start io request %x while in wrong state %d\n", 1481 request, 1482 sci_base_state_machine_get_state( 1483 scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device)) 1484 )); 1485 1486 return SCI_FAILURE_INVALID_STATE; 1487 } 1488 1489 /** 1490 * This method is the default complete io handler. It logs a warning and 1491 * returns a failure. 1492 * 1493 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1494 * SCIC_SDS_REMOTE_DEVICE. 1495 * @param[in] request The SCI_BASE_REQUEST which is then cast into a 1496 * SCIC_SDS_IO_REQUEST to complete. 1497 * 1498 * 1499 * @return SCI_STATUS 1500 * @retval SCI_FAILURE_INVALID_STATE 1501 */ 1502 SCI_STATUS scic_sds_remote_device_default_complete_request_handler( 1503 SCI_BASE_REMOTE_DEVICE_T *device, 1504 SCI_BASE_REQUEST_T *request 1505 ) 1506 { 1507 SCIC_LOG_WARNING(( 1508 sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device), 1509 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1510 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1511 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1512 "SCIC Remote Device requested to complete io_request %x while in wrong state %d\n", 1513 request, 1514 sci_base_state_machine_get_state( 1515 scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device)) 1516 )); 1517 1518 return SCI_FAILURE_INVALID_STATE; 1519 } 1520 1521 /** 1522 * This method is the default continue io handler. It logs a warning and 1523 * returns a failure. 1524 * 1525 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1526 * SCIC_SDS_REMOTE_DEVICE. 1527 * @param[in] request The SCI_BASE_REQUEST which is then cast into a 1528 * SCIC_SDS_IO_REQUEST to continue. 1529 * 1530 * @return SCI_STATUS 1531 * @retval SCI_FAILURE_INVALID_STATE 1532 */ 1533 SCI_STATUS scic_sds_remote_device_default_continue_request_handler( 1534 SCI_BASE_REMOTE_DEVICE_T *device, 1535 SCI_BASE_REQUEST_T *request 1536 ) 1537 { 1538 SCIC_LOG_WARNING(( 1539 sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device), 1540 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | 1541 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | 1542 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 1543 "SCIC Remote Device requested to continue io request %x while in wrong state %d\n", 1544 request, 1545 sci_base_state_machine_get_state( 1546 scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device)) 1547 )); 1548 1549 return SCI_FAILURE_INVALID_STATE; 1550 } 1551 1552 /** 1553 * This method is the general suspend handler. 1554 * 1555 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1556 * SCIC_SDS_REMOTE_DEVICE. 1557 * 1558 * @return SCI_STATUS 1559 * @retval SCI_FAILURE_INVALID_STATE 1560 */ 1561 static 1562 SCI_STATUS scic_sds_remote_device_general_suspend_handler( 1563 SCIC_SDS_REMOTE_DEVICE_T *this_device, 1564 U32 suspend_type 1565 ) 1566 { 1567 return scic_sds_remote_node_context_suspend(this_device->rnc, suspend_type, NULL, NULL); 1568 } 1569 1570 /** 1571 * This method is the general suspend handler. It logs a warning and returns 1572 * a failure. 1573 * 1574 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1575 * SCIC_SDS_REMOTE_DEVICE. 1576 * 1577 * @return SCI_STATUS 1578 * @retval SCI_FAILURE_INVALID_STATE 1579 */ 1580 static 1581 SCI_STATUS scic_sds_remote_device_general_resume_handler( 1582 SCIC_SDS_REMOTE_DEVICE_T *this_device 1583 ) 1584 { 1585 return scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL); 1586 } 1587 1588 //***************************************************************************** 1589 //* NORMAL STATE HANDLERS 1590 //***************************************************************************** 1591 1592 /** 1593 * This method is a general ssp frame handler. In most cases the device 1594 * object needs to route the unsolicited frame processing to the io request 1595 * object. This method decodes the tag for the io request object and routes 1596 * the unsolicited frame to that object. 1597 * 1598 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a 1599 * SCIC_SDS_REMOTE_DEVICE. 1600 * @param[in] frame_index The frame index for which the SCIC_SDS_CONTROLLER 1601 * wants this device object to process. 1602 * 1603 * @return SCI_STATUS 1604 * @retval SCI_FAILURE_INVALID_STATE 1605 */ 1606 SCI_STATUS scic_sds_remote_device_general_frame_handler( 1607 SCIC_SDS_REMOTE_DEVICE_T *this_device, 1608 U32 frame_index 1609 ) 1610 { 1611 SCI_STATUS result; 1612 SCI_SSP_FRAME_HEADER_T *frame_header; 1613 SCIC_SDS_REQUEST_T *io_request; 1614 1615 result = scic_sds_unsolicited_frame_control_get_header( 1616 &(scic_sds_remote_device_get_controller(this_device)->uf_control), 1617 frame_index, 1618 (void **)&frame_header 1619 ); 1620 1621 if (SCI_SUCCESS == result) 1622 { 1623 io_request = scic_sds_controller_get_io_request_from_tag( 1624 scic_sds_remote_device_get_controller(this_device), frame_header->tag); 1625 1626 if ( (io_request == SCI_INVALID_HANDLE) 1627 || (io_request->target_device != this_device) ) 1628 { 1629 // We could not map this tag to a valid IO request 1630 // Just toss the frame and continue 1631 scic_sds_controller_release_frame( 1632 scic_sds_remote_device_get_controller(this_device), frame_index 1633 ); 1634 } 1635 else 1636 { 1637 // The IO request is now in charge of releasing the frame 1638 result = io_request->state_handlers->frame_handler( 1639 io_request, frame_index); 1640 } 1641 } 1642 1643 return result; 1644 } 1645 1646 /** 1647 * This is a common method for handling events reported to the remote device 1648 * from the controller object. 1649 * 1650 * @param [in] this_device This is the device object that is receiving the 1651 * event. 1652 * @param [in] event_code The event code to process. 1653 * 1654 * @return SCI_STATUS 1655 */ 1656 SCI_STATUS scic_sds_remote_device_general_event_handler( 1657 SCIC_SDS_REMOTE_DEVICE_T * this_device, 1658 U32 event_code 1659 ) 1660 { 1661 return scic_sds_remote_device_core_event_handler( this_device, 1662 event_code, 1663 TRUE ); 1664 } 1665 1666 //***************************************************************************** 1667 //* STOPPED STATE HANDLERS 1668 //***************************************************************************** 1669 1670 /** 1671 * This method takes the SCIC_SDS_REMOTE_DEVICE from a stopped state and 1672 * attempts to start it. The RNC buffer for the device is constructed and 1673 * the device state machine is transitioned to the 1674 * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING. 1675 * 1676 * @param[in] device 1677 * 1678 * @return SCI_STATUS 1679 * @retval SCI_SUCCESS if there is an RNC buffer available to construct the 1680 * remote device. 1681 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer 1682 * available in which to construct the remote device. 1683 */ 1684 static 1685 SCI_STATUS scic_sds_remote_device_stopped_state_start_handler( 1686 SCI_BASE_REMOTE_DEVICE_T *device 1687 ) 1688 { 1689 SCI_STATUS status; 1690 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 1691 1692 status = scic_sds_remote_node_context_resume( 1693 this_device->rnc, 1694 scic_sds_remote_device_resume_complete_handler, 1695 this_device 1696 ); 1697 1698 if (status == SCI_SUCCESS) 1699 { 1700 sci_base_state_machine_change_state( 1701 scic_sds_remote_device_get_base_state_machine(this_device), 1702 SCI_BASE_REMOTE_DEVICE_STATE_STARTING 1703 ); 1704 } 1705 1706 return status; 1707 } 1708 1709 /** 1710 * This method will stop a SCIC_SDS_REMOTE_DEVICE that is already in a stopped 1711 * state. This is not considered an error since the device is already 1712 * stopped. 1713 * 1714 * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a 1715 * SCIC_SDS_REMOTE_DEVICE. 1716 * 1717 * @return SCI_STATUS 1718 * @retval SCI_SUCCESS 1719 */ 1720 static 1721 SCI_STATUS scic_sds_remote_device_stopped_state_stop_handler( 1722 SCI_BASE_REMOTE_DEVICE_T *this_device 1723 ) 1724 { 1725 return SCI_SUCCESS; 1726 } 1727 1728 /** 1729 * This method will destruct a SCIC_SDS_REMOTE_DEVICE that is in a stopped 1730 * state. This is the only state from which a destruct request will succeed. 1731 * The RNi for this SCIC_SDS_REMOTE_DEVICE is returned to the free pool and 1732 * the device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL. 1733 * 1734 * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a 1735 * SCIC_SDS_REMOTE_DEVICE. 1736 * 1737 * @return SCI_STATUS 1738 * @retval SCI_SUCCESS 1739 */ 1740 static 1741 SCI_STATUS scic_sds_remote_device_stopped_state_destruct_handler( 1742 SCI_BASE_REMOTE_DEVICE_T *device 1743 ) 1744 { 1745 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 1746 1747 SCIC_SDS_CONTROLLER_T * the_controller = 1748 scic_sds_remote_device_get_controller(this_device); 1749 1750 the_controller->remote_device_sequence[this_device->rnc->remote_node_index]++; 1751 1752 scic_sds_controller_free_remote_node_context( 1753 the_controller, 1754 this_device, 1755 this_device->rnc->remote_node_index 1756 ); 1757 1758 scic_sds_remote_node_context_set_remote_node_index( 1759 this_device->rnc, 1760 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 1761 ); 1762 1763 sci_base_state_machine_change_state( 1764 scic_sds_remote_device_get_base_state_machine(this_device), 1765 SCI_BASE_REMOTE_DEVICE_STATE_FINAL 1766 ); 1767 1768 scic_sds_remote_device_deinitialize_state_logging(this_device); 1769 1770 return SCI_SUCCESS; 1771 } 1772 1773 //***************************************************************************** 1774 //* STARTING STATE HANDLERS 1775 //***************************************************************************** 1776 1777 static 1778 SCI_STATUS scic_sds_remote_device_starting_state_stop_handler( 1779 SCI_BASE_REMOTE_DEVICE_T *device 1780 ) 1781 { 1782 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 1783 1784 /* 1785 * This device has not yet started so there had better be no IO requests 1786 */ 1787 ASSERT(this_device->started_request_count == 0); 1788 1789 /* 1790 * Destroy the remote node context 1791 */ 1792 scic_sds_remote_node_context_destruct( 1793 this_device->rnc, 1794 scic_sds_cb_remote_device_rnc_destruct_complete, 1795 this_device 1796 ); 1797 1798 /* 1799 * Transition to the stopping state and wait for the remote node to 1800 * complete being posted and invalidated. 1801 */ 1802 sci_base_state_machine_change_state( 1803 scic_sds_remote_device_get_base_state_machine(this_device), 1804 SCI_BASE_REMOTE_DEVICE_STATE_STOPPING 1805 ); 1806 1807 return SCI_SUCCESS; 1808 } 1809 1810 //***************************************************************************** 1811 //* INITIALIZING STATE HANDLERS 1812 //***************************************************************************** 1813 1814 /* There is nothing to do here for SSP devices */ 1815 1816 //***************************************************************************** 1817 //* READY STATE HANDLERS 1818 //***************************************************************************** 1819 1820 /** 1821 * This method is the default stop handler for the SCIC_SDS_REMOTE_DEVICE 1822 * ready substate machine. It will stop the current substate machine and 1823 * transition the base state machine to SCI_BASE_REMOTE_DEVICE_STATE_STOPPING. 1824 * 1825 * @param[in] device The SCI_BASE_REMOTE_DEVICE object which is cast to a 1826 * SCIC_SDS_REMOTE_DEVICE object. 1827 * 1828 * @return SCI_STATUS 1829 * @retval SCI_SUCCESS 1830 */ 1831 SCI_STATUS scic_sds_remote_device_ready_state_stop_handler( 1832 SCI_BASE_REMOTE_DEVICE_T *device 1833 ) 1834 { 1835 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 1836 SCI_STATUS status = SCI_SUCCESS; 1837 1838 // Request the parent state machine to transition to the stopping state 1839 sci_base_state_machine_change_state( 1840 scic_sds_remote_device_get_base_state_machine(this_device), 1841 SCI_BASE_REMOTE_DEVICE_STATE_STOPPING 1842 ); 1843 1844 if (this_device->started_request_count == 0) 1845 { 1846 scic_sds_remote_node_context_destruct( 1847 this_device->rnc, 1848 scic_sds_cb_remote_device_rnc_destruct_complete, 1849 this_device 1850 ); 1851 } 1852 else 1853 status = scic_sds_remote_device_terminate_requests(this_device); 1854 1855 return status; 1856 } 1857 1858 /** 1859 * This is the ready state device reset handler 1860 * 1861 * @param[in] device The SCI_BASE_REMOTE_DEVICE object which is cast to a 1862 * SCIC_SDS_REMOTE_DEVICE object. 1863 * 1864 * @return SCI_STATUS 1865 */ 1866 SCI_STATUS scic_sds_remote_device_ready_state_reset_handler( 1867 SCI_BASE_REMOTE_DEVICE_T *device 1868 ) 1869 { 1870 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 1871 1872 // Request the parent state machine to transition to the stopping state 1873 sci_base_state_machine_change_state( 1874 scic_sds_remote_device_get_base_state_machine(this_device), 1875 SCI_BASE_REMOTE_DEVICE_STATE_RESETTING 1876 ); 1877 1878 return SCI_SUCCESS; 1879 } 1880 1881 /** 1882 * This method will attempt to start a task request for this device object. 1883 * The remote device object will issue the start request for the task and if 1884 * successful it will start the request for the port object then increment its 1885 * own requet count. 1886 * 1887 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a 1888 * SCIC_SDS_REMOTE_DEVICE for which the request is to be started. 1889 * @param[in] request The SCI_BASE_REQUEST which is cast to a 1890 * SCIC_SDS_IO_REQUEST that is to be started. 1891 * 1892 * @return SCI_STATUS 1893 * @retval SCI_SUCCESS if the task request is started for this device object. 1894 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request object could 1895 * not get the resources to start. 1896 */ 1897 static 1898 SCI_STATUS scic_sds_remote_device_ready_state_start_task_handler( 1899 SCI_BASE_REMOTE_DEVICE_T *device, 1900 SCI_BASE_REQUEST_T *request 1901 ) 1902 { 1903 SCI_STATUS result; 1904 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 1905 SCIC_SDS_REQUEST_T *task_request = (SCIC_SDS_REQUEST_T *)request; 1906 1907 // See if the port is in a state where we can start the IO request 1908 result = scic_sds_port_start_io( 1909 scic_sds_remote_device_get_port(this_device), this_device, task_request); 1910 1911 if (result == SCI_SUCCESS) 1912 { 1913 result = scic_sds_remote_node_context_start_task( 1914 this_device->rnc, task_request 1915 ); 1916 1917 if (result == SCI_SUCCESS) 1918 { 1919 result = scic_sds_request_start(task_request); 1920 } 1921 1922 scic_sds_remote_device_start_request(this_device, task_request, result); 1923 } 1924 1925 return result; 1926 } 1927 1928 /** 1929 * This method will attempt to start an io request for this device object. The 1930 * remote device object will issue the start request for the io and if 1931 * successful it will start the request for the port object then increment its 1932 * own requet count. 1933 * 1934 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a 1935 * SCIC_SDS_REMOTE_DEVICE for which the request is to be started. 1936 * @param[in] request The SCI_BASE_REQUEST which is cast to a 1937 * SCIC_SDS_IO_REQUEST that is to be started. 1938 * 1939 * @return SCI_STATUS 1940 * @retval SCI_SUCCESS if the io request is started for this device object. 1941 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request object could 1942 * not get the resources to start. 1943 */ 1944 static 1945 SCI_STATUS scic_sds_remote_device_ready_state_start_io_handler( 1946 SCI_BASE_REMOTE_DEVICE_T *device, 1947 SCI_BASE_REQUEST_T *request 1948 ) 1949 { 1950 SCI_STATUS result; 1951 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 1952 SCIC_SDS_REQUEST_T *io_request = (SCIC_SDS_REQUEST_T *)request; 1953 1954 // See if the port is in a state where we can start the IO request 1955 result = scic_sds_port_start_io( 1956 scic_sds_remote_device_get_port(this_device), this_device, io_request); 1957 1958 if (result == SCI_SUCCESS) 1959 { 1960 result = scic_sds_remote_node_context_start_io( 1961 this_device->rnc, io_request 1962 ); 1963 1964 if (result == SCI_SUCCESS) 1965 { 1966 result = scic_sds_request_start(io_request); 1967 } 1968 1969 scic_sds_remote_device_start_request(this_device, io_request, result); 1970 } 1971 1972 return result; 1973 } 1974 1975 /** 1976 * This method will complete the request for the remote device object. The 1977 * method will call the completion handler for the request object and if 1978 * successful it will complete the request on the port object then decrement 1979 * its own started_request_count. 1980 * 1981 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a 1982 * SCIC_SDS_REMOTE_DEVICE for which the request is to be completed. 1983 * @param[in] request The SCI_BASE_REQUEST which is cast to a 1984 * SCIC_SDS_IO_REQUEST that is to be completed. 1985 * 1986 * @return SCI_STATUS 1987 */ 1988 static 1989 SCI_STATUS scic_sds_remote_device_ready_state_complete_request_handler( 1990 SCI_BASE_REMOTE_DEVICE_T *device, 1991 SCI_BASE_REQUEST_T *request 1992 ) 1993 { 1994 SCI_STATUS result; 1995 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 1996 SCIC_SDS_REQUEST_T *the_request = (SCIC_SDS_REQUEST_T *)request; 1997 1998 result = scic_sds_request_complete(the_request); 1999 2000 if (result == SCI_SUCCESS) 2001 { 2002 // See if the port is in a state where we can start the IO request 2003 result = scic_sds_port_complete_io( 2004 scic_sds_remote_device_get_port(this_device), this_device, the_request); 2005 2006 if (result == SCI_SUCCESS) 2007 { 2008 scic_sds_remote_device_decrement_request_count(this_device); 2009 } 2010 } 2011 2012 return result; 2013 } 2014 2015 //***************************************************************************** 2016 //* STOPPING STATE HANDLERS 2017 //***************************************************************************** 2018 2019 /** 2020 * This method will stop a SCIC_SDS_REMOTE_DEVICE that is already in the 2021 * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an 2022 * error since we allow a stop request on a device that is alreay stopping or 2023 * stopped. 2024 * 2025 * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a 2026 * SCIC_SDS_REMOTE_DEVICE. 2027 * 2028 * @return SCI_STATUS 2029 * @retval SCI_SUCCESS 2030 */ 2031 static 2032 SCI_STATUS scic_sds_remote_device_stopping_state_stop_handler( 2033 SCI_BASE_REMOTE_DEVICE_T *device 2034 ) 2035 { 2036 // All requests should have been terminated, but if there is an 2037 // attempt to stop a device already in the stopping state, then 2038 // try again to terminate. 2039 return scic_sds_remote_device_terminate_requests( 2040 (SCIC_SDS_REMOTE_DEVICE_T*)device); 2041 } 2042 2043 2044 /** 2045 * This method completes requests for this SCIC_SDS_REMOTE_DEVICE while it is 2046 * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the 2047 * complete method for the request object and if that is successful the port 2048 * object is called to complete the task request. Then the device object 2049 * itself completes the task request. If SCIC_SDS_REMOTE_DEVICE 2050 * started_request_count goes to 0 and the invalidate RNC request has 2051 * completed the device object can transition to the 2052 * SCI_BASE_REMOTE_DEVICE_STATE_STOPPED. 2053 * 2054 * @param[in] device The device object for which the request is completing. 2055 * @param[in] request The task request that is being completed. 2056 * 2057 * @return SCI_STATUS 2058 */ 2059 static 2060 SCI_STATUS scic_sds_remote_device_stopping_state_complete_request_handler( 2061 SCI_BASE_REMOTE_DEVICE_T *device, 2062 SCI_BASE_REQUEST_T *request 2063 ) 2064 { 2065 SCI_STATUS status = SCI_SUCCESS; 2066 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request; 2067 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 2068 2069 status = scic_sds_request_complete(this_request); 2070 if (status == SCI_SUCCESS) 2071 { 2072 status = scic_sds_port_complete_io( 2073 scic_sds_remote_device_get_port(this_device), 2074 this_device, 2075 this_request 2076 ); 2077 2078 if (status == SCI_SUCCESS) 2079 { 2080 scic_sds_remote_device_decrement_request_count(this_device); 2081 2082 if (scic_sds_remote_device_get_request_count(this_device) == 0) 2083 { 2084 scic_sds_remote_node_context_destruct( 2085 this_device->rnc, 2086 scic_sds_cb_remote_device_rnc_destruct_complete, 2087 this_device 2088 ); 2089 } 2090 } 2091 } 2092 2093 return status; 2094 } 2095 2096 //***************************************************************************** 2097 //* RESETTING STATE HANDLERS 2098 //***************************************************************************** 2099 2100 /** 2101 * This method will complete the reset operation when the device is in the 2102 * resetting state. 2103 * 2104 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is to be cast into a 2105 * SCIC_SDS_REMOTE_DEVICE object. 2106 * 2107 * @return SCI_STATUS 2108 */ 2109 static 2110 SCI_STATUS scic_sds_remote_device_resetting_state_reset_complete_handler( 2111 SCI_BASE_REMOTE_DEVICE_T * device 2112 ) 2113 { 2114 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 2115 2116 sci_base_state_machine_change_state( 2117 &this_device->parent.state_machine, 2118 SCI_BASE_REMOTE_DEVICE_STATE_READY 2119 ); 2120 2121 return SCI_SUCCESS; 2122 } 2123 2124 /** 2125 * This method will stop the remote device while in the resetting state. 2126 * 2127 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is to be cast into a 2128 * SCIC_SDS_REMOTE_DEVICE object. 2129 * 2130 * @return SCI_STATUS 2131 */ 2132 static 2133 SCI_STATUS scic_sds_remote_device_resetting_state_stop_handler( 2134 SCI_BASE_REMOTE_DEVICE_T * device 2135 ) 2136 { 2137 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 2138 2139 sci_base_state_machine_change_state( 2140 &this_device->parent.state_machine, 2141 SCI_BASE_REMOTE_DEVICE_STATE_STOPPING 2142 ); 2143 2144 return SCI_SUCCESS; 2145 } 2146 2147 /** 2148 * This method completes requests for this SCIC_SDS_REMOTE_DEVICE while it is 2149 * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the 2150 * complete method for the request object and if that is successful the port 2151 * object is called to complete the task request. Then the device object 2152 * itself completes the task request. 2153 * 2154 * @param[in] device The device object for which the request is completing. 2155 * @param[in] request The task request that is being completed. 2156 * 2157 * @return SCI_STATUS 2158 */ 2159 static 2160 SCI_STATUS scic_sds_remote_device_resetting_state_complete_request_handler( 2161 SCI_BASE_REMOTE_DEVICE_T *device, 2162 SCI_BASE_REQUEST_T *request 2163 ) 2164 { 2165 SCI_STATUS status = SCI_SUCCESS; 2166 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request; 2167 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 2168 2169 status = scic_sds_request_complete(this_request); 2170 2171 if (status == SCI_SUCCESS) 2172 { 2173 status = scic_sds_port_complete_io( 2174 scic_sds_remote_device_get_port(this_device), this_device, this_request); 2175 2176 if (status == SCI_SUCCESS) 2177 { 2178 scic_sds_remote_device_decrement_request_count(this_device); 2179 } 2180 } 2181 2182 return status; 2183 } 2184 2185 //***************************************************************************** 2186 //* FAILED STATE HANDLERS 2187 //***************************************************************************** 2188 2189 SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T 2190 scic_sds_remote_device_state_handler_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] = 2191 { 2192 // SCI_BASE_REMOTE_DEVICE_STATE_INITIAL 2193 { 2194 { 2195 scic_sds_remote_device_default_start_handler, 2196 scic_sds_remote_device_default_stop_handler, 2197 scic_sds_remote_device_default_fail_handler, 2198 scic_sds_remote_device_default_destruct_handler, 2199 scic_sds_remote_device_default_reset_handler, 2200 scic_sds_remote_device_default_reset_complete_handler, 2201 scic_sds_remote_device_default_start_request_handler, 2202 scic_sds_remote_device_default_complete_request_handler, 2203 scic_sds_remote_device_default_continue_request_handler, 2204 scic_sds_remote_device_default_start_request_handler, 2205 scic_sds_remote_device_default_complete_request_handler 2206 }, 2207 scic_sds_remote_device_default_suspend_handler, 2208 scic_sds_remote_device_default_resume_handler, 2209 scic_sds_remote_device_default_event_handler, 2210 scic_sds_remote_device_default_frame_handler 2211 }, 2212 // SCI_BASE_REMOTE_DEVICE_STATE_STOPPED 2213 { 2214 { 2215 scic_sds_remote_device_stopped_state_start_handler, 2216 scic_sds_remote_device_stopped_state_stop_handler, 2217 scic_sds_remote_device_default_fail_handler, 2218 scic_sds_remote_device_stopped_state_destruct_handler, 2219 scic_sds_remote_device_default_reset_handler, 2220 scic_sds_remote_device_default_reset_complete_handler, 2221 scic_sds_remote_device_default_start_request_handler, 2222 scic_sds_remote_device_default_complete_request_handler, 2223 scic_sds_remote_device_default_continue_request_handler, 2224 scic_sds_remote_device_default_start_request_handler, 2225 scic_sds_remote_device_default_complete_request_handler 2226 }, 2227 scic_sds_remote_device_default_suspend_handler, 2228 scic_sds_remote_device_default_resume_handler, 2229 scic_sds_remote_device_default_event_handler, 2230 scic_sds_remote_device_default_frame_handler 2231 }, 2232 // SCI_BASE_REMOTE_DEVICE_STATE_STARTING 2233 { 2234 { 2235 scic_sds_remote_device_default_start_handler, 2236 scic_sds_remote_device_starting_state_stop_handler, 2237 scic_sds_remote_device_default_fail_handler, 2238 scic_sds_remote_device_default_destruct_handler, 2239 scic_sds_remote_device_default_reset_handler, 2240 scic_sds_remote_device_default_reset_complete_handler, 2241 scic_sds_remote_device_default_start_request_handler, 2242 scic_sds_remote_device_default_complete_request_handler, 2243 scic_sds_remote_device_default_continue_request_handler, 2244 scic_sds_remote_device_default_start_request_handler, 2245 scic_sds_remote_device_default_complete_request_handler 2246 }, 2247 scic_sds_remote_device_default_suspend_handler, 2248 scic_sds_remote_device_default_resume_handler, 2249 scic_sds_remote_device_general_event_handler, 2250 scic_sds_remote_device_default_frame_handler 2251 }, 2252 // SCI_BASE_REMOTE_DEVICE_STATE_READY 2253 { 2254 { 2255 scic_sds_remote_device_default_start_handler, 2256 scic_sds_remote_device_ready_state_stop_handler, 2257 scic_sds_remote_device_default_fail_handler, 2258 scic_sds_remote_device_default_destruct_handler, 2259 scic_sds_remote_device_ready_state_reset_handler, 2260 scic_sds_remote_device_default_reset_complete_handler, 2261 scic_sds_remote_device_ready_state_start_io_handler, 2262 scic_sds_remote_device_ready_state_complete_request_handler, 2263 scic_sds_remote_device_default_continue_request_handler, 2264 scic_sds_remote_device_ready_state_start_task_handler, 2265 scic_sds_remote_device_ready_state_complete_request_handler 2266 }, 2267 scic_sds_remote_device_general_suspend_handler, 2268 scic_sds_remote_device_general_resume_handler, 2269 scic_sds_remote_device_general_event_handler, 2270 scic_sds_remote_device_general_frame_handler, 2271 }, 2272 // SCI_BASE_REMOTE_DEVICE_STATE_STOPPING 2273 { 2274 { 2275 scic_sds_remote_device_default_start_handler, 2276 scic_sds_remote_device_stopping_state_stop_handler, 2277 scic_sds_remote_device_default_fail_handler, 2278 scic_sds_remote_device_default_destruct_handler, 2279 scic_sds_remote_device_default_reset_handler, 2280 scic_sds_remote_device_default_reset_complete_handler, 2281 scic_sds_remote_device_default_start_request_handler, 2282 scic_sds_remote_device_stopping_state_complete_request_handler, 2283 scic_sds_remote_device_default_continue_request_handler, 2284 scic_sds_remote_device_default_start_request_handler, 2285 scic_sds_remote_device_stopping_state_complete_request_handler 2286 }, 2287 scic_sds_remote_device_default_suspend_handler, 2288 scic_sds_remote_device_default_resume_handler, 2289 scic_sds_remote_device_general_event_handler, 2290 scic_sds_remote_device_general_frame_handler 2291 }, 2292 // SCI_BASE_REMOTE_DEVICE_STATE_FAILED 2293 { 2294 { 2295 scic_sds_remote_device_default_start_handler, 2296 scic_sds_remote_device_default_stop_handler, 2297 scic_sds_remote_device_default_fail_handler, 2298 scic_sds_remote_device_default_destruct_handler, 2299 scic_sds_remote_device_default_reset_handler, 2300 scic_sds_remote_device_default_reset_complete_handler, 2301 scic_sds_remote_device_default_start_request_handler, 2302 scic_sds_remote_device_default_complete_request_handler, 2303 scic_sds_remote_device_default_continue_request_handler, 2304 scic_sds_remote_device_default_start_request_handler, 2305 scic_sds_remote_device_default_complete_request_handler 2306 }, 2307 scic_sds_remote_device_default_suspend_handler, 2308 scic_sds_remote_device_default_resume_handler, 2309 scic_sds_remote_device_default_event_handler, 2310 scic_sds_remote_device_general_frame_handler 2311 }, 2312 // SCI_BASE_REMOTE_DEVICE_STATE_RESETTING 2313 { 2314 { 2315 scic_sds_remote_device_default_start_handler, 2316 scic_sds_remote_device_resetting_state_stop_handler, 2317 scic_sds_remote_device_default_fail_handler, 2318 scic_sds_remote_device_default_destruct_handler, 2319 scic_sds_remote_device_default_reset_handler, 2320 scic_sds_remote_device_resetting_state_reset_complete_handler, 2321 scic_sds_remote_device_default_start_request_handler, 2322 scic_sds_remote_device_resetting_state_complete_request_handler, 2323 scic_sds_remote_device_default_continue_request_handler, 2324 scic_sds_remote_device_default_start_request_handler, 2325 scic_sds_remote_device_resetting_state_complete_request_handler 2326 }, 2327 scic_sds_remote_device_default_suspend_handler, 2328 scic_sds_remote_device_default_resume_handler, 2329 scic_sds_remote_device_default_event_handler, 2330 scic_sds_remote_device_general_frame_handler 2331 }, 2332 #if !defined(DISABLE_WIDE_PORTED_TARGETS) 2333 // SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH - unused by SCIC 2334 { 2335 { 2336 scic_sds_remote_device_default_start_handler, 2337 scic_sds_remote_device_default_stop_handler, 2338 scic_sds_remote_device_default_fail_handler, 2339 scic_sds_remote_device_default_destruct_handler, 2340 scic_sds_remote_device_default_reset_handler, 2341 scic_sds_remote_device_default_reset_complete_handler, 2342 scic_sds_remote_device_default_start_request_handler, 2343 scic_sds_remote_device_default_complete_request_handler, 2344 scic_sds_remote_device_default_continue_request_handler, 2345 scic_sds_remote_device_default_start_request_handler, 2346 scic_sds_remote_device_default_complete_request_handler 2347 }, 2348 scic_sds_remote_device_default_suspend_handler, 2349 scic_sds_remote_device_default_resume_handler, 2350 scic_sds_remote_device_default_event_handler, 2351 scic_sds_remote_device_default_frame_handler 2352 }, 2353 #endif 2354 // SCI_BASE_REMOTE_DEVICE_STATE_FINAL 2355 { 2356 { 2357 scic_sds_remote_device_default_start_handler, 2358 scic_sds_remote_device_default_stop_handler, 2359 scic_sds_remote_device_default_fail_handler, 2360 scic_sds_remote_device_default_destruct_handler, 2361 scic_sds_remote_device_default_reset_handler, 2362 scic_sds_remote_device_default_reset_complete_handler, 2363 scic_sds_remote_device_default_start_request_handler, 2364 scic_sds_remote_device_default_complete_request_handler, 2365 scic_sds_remote_device_default_continue_request_handler, 2366 scic_sds_remote_device_default_start_request_handler, 2367 scic_sds_remote_device_default_complete_request_handler 2368 }, 2369 scic_sds_remote_device_default_suspend_handler, 2370 scic_sds_remote_device_default_resume_handler, 2371 scic_sds_remote_device_default_event_handler, 2372 scic_sds_remote_device_default_frame_handler 2373 } 2374 }; 2375 2376 /** 2377 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it 2378 * immediatly transitions the remote device object to the stopped state. 2379 * 2380 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a 2381 * SCIC_SDS_REMOTE_DEVICE. 2382 * 2383 * @return none 2384 */ 2385 static 2386 void scic_sds_remote_device_initial_state_enter( 2387 SCI_BASE_OBJECT_T *object 2388 ) 2389 { 2390 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 2391 2392 SET_STATE_HANDLER( 2393 this_device, 2394 scic_sds_remote_device_state_handler_table, 2395 SCI_BASE_REMOTE_DEVICE_STATE_INITIAL 2396 ); 2397 2398 // Initial state is a transitional state to the stopped state 2399 sci_base_state_machine_change_state( 2400 scic_sds_remote_device_get_base_state_machine(this_device), 2401 SCI_BASE_REMOTE_DEVICE_STATE_STOPPED 2402 ); 2403 } 2404 2405 /** 2406 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it 2407 * sets the stopped state handlers and if this state is entered from the 2408 * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING then the SCI User is informed that 2409 * the device stop is complete. 2410 * 2411 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a 2412 * SCIC_SDS_REMOTE_DEVICE. 2413 * 2414 * @return none 2415 */ 2416 static 2417 void scic_sds_remote_device_stopped_state_enter( 2418 SCI_BASE_OBJECT_T *object 2419 ) 2420 { 2421 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 2422 2423 SET_STATE_HANDLER( 2424 this_device, 2425 scic_sds_remote_device_state_handler_table, 2426 SCI_BASE_REMOTE_DEVICE_STATE_STOPPED 2427 ); 2428 2429 // If we are entering from the stopping state let the SCI User know that 2430 // the stop operation has completed. 2431 if (this_device->parent.state_machine.previous_state_id 2432 == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) 2433 { 2434 scic_cb_remote_device_stop_complete( 2435 scic_sds_remote_device_get_controller(this_device), 2436 this_device, 2437 SCI_SUCCESS 2438 ); 2439 } 2440 2441 scic_sds_controller_remote_device_stopped( 2442 scic_sds_remote_device_get_controller(this_device), 2443 this_device 2444 ); 2445 } 2446 2447 /** 2448 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it 2449 * sets the starting state handlers, sets the device not ready, and posts the 2450 * remote node context to the hardware. 2451 * 2452 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a 2453 * SCIC_SDS_REMOTE_DEVICE. 2454 * 2455 * @return none 2456 */ 2457 static 2458 void scic_sds_remote_device_starting_state_enter( 2459 SCI_BASE_OBJECT_T *object 2460 ) 2461 { 2462 SCIC_SDS_CONTROLLER_T * the_controller; 2463 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 2464 2465 the_controller = scic_sds_remote_device_get_controller(this_device); 2466 2467 SET_STATE_HANDLER( 2468 this_device, 2469 scic_sds_remote_device_state_handler_table, 2470 SCI_BASE_REMOTE_DEVICE_STATE_STARTING 2471 ); 2472 2473 scic_cb_remote_device_not_ready( 2474 the_controller, 2475 this_device, 2476 SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED 2477 ); 2478 } 2479 2480 2481 /** 2482 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets 2483 * the ready state handlers, and starts the ready substate machine. 2484 * 2485 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a 2486 * SCIC_SDS_REMOTE_DEVICE. 2487 * 2488 * @return none 2489 */ 2490 static 2491 void scic_sds_remote_device_ready_state_enter( 2492 SCI_BASE_OBJECT_T *object 2493 ) 2494 { 2495 SCIC_SDS_CONTROLLER_T * the_controller; 2496 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 2497 2498 the_controller = scic_sds_remote_device_get_controller(this_device); 2499 2500 SET_STATE_HANDLER( 2501 this_device, 2502 scic_sds_remote_device_state_handler_table, 2503 SCI_BASE_REMOTE_DEVICE_STATE_READY 2504 ); 2505 2506 /// @todo Check the device object for the proper return code for this 2507 /// callback 2508 scic_cb_remote_device_start_complete( 2509 the_controller, this_device, SCI_SUCCESS 2510 ); 2511 2512 scic_sds_controller_remote_device_started( 2513 the_controller, this_device 2514 ); 2515 2516 if (this_device->has_ready_substate_machine) 2517 { 2518 sci_base_state_machine_start(&this_device->ready_substate_machine); 2519 } 2520 else 2521 { 2522 scic_cb_remote_device_ready(the_controller, this_device); 2523 } 2524 } 2525 2526 /** 2527 * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does 2528 * nothing. 2529 * 2530 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a 2531 * SCIC_SDS_REMOTE_DEVICE. 2532 * 2533 * @return none 2534 */ 2535 static 2536 void scic_sds_remote_device_ready_state_exit( 2537 SCI_BASE_OBJECT_T *object 2538 ) 2539 { 2540 SCIC_SDS_CONTROLLER_T * the_controller; 2541 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 2542 2543 the_controller = scic_sds_remote_device_get_controller(this_device); 2544 2545 if (this_device->has_ready_substate_machine) 2546 { 2547 sci_base_state_machine_stop(&this_device->ready_substate_machine); 2548 } 2549 else 2550 { 2551 scic_cb_remote_device_not_ready( 2552 the_controller, 2553 this_device, 2554 SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED 2555 ); 2556 } 2557 } 2558 2559 /** 2560 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING it 2561 * sets the stopping state handlers and posts an RNC invalidate request to the 2562 * SCU hardware. 2563 * 2564 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a 2565 * SCIC_SDS_REMOTE_DEVICE. 2566 * 2567 * @return none 2568 */ 2569 static 2570 void scic_sds_remote_device_stopping_state_enter( 2571 SCI_BASE_OBJECT_T *object 2572 ) 2573 { 2574 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 2575 2576 SET_STATE_HANDLER( 2577 this_device, 2578 scic_sds_remote_device_state_handler_table, 2579 SCI_BASE_REMOTE_DEVICE_STATE_STOPPING 2580 ); 2581 } 2582 2583 /** 2584 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FAILED it 2585 * sets the stopping state handlers. 2586 * 2587 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a 2588 * SCIC_SDS_REMOTE_DEVICE. 2589 * 2590 * @return none 2591 */ 2592 static 2593 void scic_sds_remote_device_failed_state_enter( 2594 SCI_BASE_OBJECT_T *object 2595 ) 2596 { 2597 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 2598 2599 SET_STATE_HANDLER( 2600 this_device, 2601 scic_sds_remote_device_state_handler_table, 2602 SCI_BASE_REMOTE_DEVICE_STATE_FAILED 2603 ); 2604 } 2605 2606 /** 2607 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it 2608 * sets the resetting state handlers. 2609 * 2610 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a 2611 * SCIC_SDS_REMOTE_DEVICE. 2612 * 2613 * @return none 2614 */ 2615 static 2616 void scic_sds_remote_device_resetting_state_enter( 2617 SCI_BASE_OBJECT_T *object 2618 ) 2619 { 2620 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 2621 2622 SET_STATE_HANDLER( 2623 this_device, 2624 scic_sds_remote_device_state_handler_table, 2625 SCI_BASE_REMOTE_DEVICE_STATE_RESETTING 2626 ); 2627 2628 scic_sds_remote_node_context_suspend( 2629 this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); 2630 } 2631 2632 /** 2633 * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it 2634 * does nothing. 2635 * 2636 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a 2637 * SCIC_SDS_REMOTE_DEVICE. 2638 * 2639 * @return none 2640 */ 2641 static 2642 void scic_sds_remote_device_resetting_state_exit( 2643 SCI_BASE_OBJECT_T *object 2644 ) 2645 { 2646 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 2647 2648 scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL); 2649 } 2650 2651 /** 2652 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FINAL it sets 2653 * the final state handlers. 2654 * 2655 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a 2656 * SCIC_SDS_REMOTE_DEVICE. 2657 * 2658 * @return none 2659 */ 2660 static 2661 void scic_sds_remote_device_final_state_enter( 2662 SCI_BASE_OBJECT_T *object 2663 ) 2664 { 2665 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 2666 2667 SET_STATE_HANDLER( 2668 this_device, 2669 scic_sds_remote_device_state_handler_table, 2670 SCI_BASE_REMOTE_DEVICE_STATE_FINAL 2671 ); 2672 } 2673 2674 // --------------------------------------------------------------------------- 2675 2676 SCI_BASE_STATE_T 2677 scic_sds_remote_device_state_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] = 2678 { 2679 { 2680 SCI_BASE_REMOTE_DEVICE_STATE_INITIAL, 2681 scic_sds_remote_device_initial_state_enter, 2682 NULL 2683 }, 2684 { 2685 SCI_BASE_REMOTE_DEVICE_STATE_STOPPED, 2686 scic_sds_remote_device_stopped_state_enter, 2687 NULL 2688 }, 2689 { 2690 SCI_BASE_REMOTE_DEVICE_STATE_STARTING, 2691 scic_sds_remote_device_starting_state_enter, 2692 NULL 2693 }, 2694 { 2695 SCI_BASE_REMOTE_DEVICE_STATE_READY, 2696 scic_sds_remote_device_ready_state_enter, 2697 scic_sds_remote_device_ready_state_exit 2698 }, 2699 { 2700 SCI_BASE_REMOTE_DEVICE_STATE_STOPPING, 2701 scic_sds_remote_device_stopping_state_enter, 2702 NULL 2703 }, 2704 { 2705 SCI_BASE_REMOTE_DEVICE_STATE_FAILED, 2706 scic_sds_remote_device_failed_state_enter, 2707 NULL 2708 }, 2709 { 2710 SCI_BASE_REMOTE_DEVICE_STATE_RESETTING, 2711 scic_sds_remote_device_resetting_state_enter, 2712 scic_sds_remote_device_resetting_state_exit 2713 }, 2714 #if !defined(DISABLE_WIDE_PORTED_TARGETS) 2715 { //Not used by SCIC 2716 SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH, 2717 NULL, 2718 NULL 2719 }, 2720 #endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS) 2721 { 2722 SCI_BASE_REMOTE_DEVICE_STATE_FINAL, 2723 scic_sds_remote_device_final_state_enter, 2724 NULL 2725 } 2726 }; 2727 2728