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 methods and state machines for SATA/STP 60 * remote devices. 61 */ 62 63 #include <dev/isci/scil/intel_sat.h> 64 #include <dev/isci/scil/intel_ata.h> 65 #include <dev/isci/scil/intel_sata.h> 66 #include <dev/isci/scil/scic_remote_device.h> 67 #include <dev/isci/scil/scic_user_callback.h> 68 #include <dev/isci/scil/scic_sds_logger.h> 69 #include <dev/isci/scil/scic_sds_controller.h> 70 #include <dev/isci/scil/scic_sds_port.h> 71 #include <dev/isci/scil/scic_sds_remote_device.h> 72 #include <dev/isci/scil/scic_sds_request.h> 73 #include <dev/isci/scil/scu_event_codes.h> 74 #include <dev/isci/scil/scu_completion_codes.h> 75 #include <dev/isci/scil/sci_base_state.h> 76 77 /** 78 * This method will perform the STP request completion processing common 79 * to IO requests and task requests of all types 80 * 81 * @param[in] device This parameter specifies the device for which the 82 * request is being completed. 83 * @param[in] request This parameter specifies the request being completed. 84 * 85 * @return This method returns an indication as to whether the request 86 * processing completed successfully. 87 */ 88 static 89 SCI_STATUS scic_sds_stp_remote_device_complete_request( 90 SCI_BASE_REMOTE_DEVICE_T * device, 91 SCI_BASE_REQUEST_T * request 92 ) 93 { 94 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 95 SCIC_SDS_REQUEST_T * the_request = (SCIC_SDS_REQUEST_T *)request; 96 SCI_STATUS status; 97 98 status = scic_sds_io_request_complete(the_request); 99 100 if (status == SCI_SUCCESS) 101 { 102 status = scic_sds_port_complete_io( 103 this_device->owning_port, this_device, the_request 104 ); 105 106 if (status == SCI_SUCCESS) 107 { 108 scic_sds_remote_device_decrement_request_count(this_device); 109 if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) 110 { 111 //This request causes hardware error, device needs to be Lun Reset. 112 //So here we force the state machine to IDLE state so the rest IOs 113 //can reach RNC state handler, these IOs will be completed by RNC with 114 //status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". 115 sci_base_state_machine_change_state( 116 &this_device->ready_substate_machine, 117 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET 118 ); 119 } 120 else if (scic_sds_remote_device_get_request_count(this_device) == 0) 121 { 122 sci_base_state_machine_change_state( 123 &this_device->ready_substate_machine, 124 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE 125 ); 126 } 127 } 128 } 129 130 if (status != SCI_SUCCESS) 131 { 132 SCIC_LOG_ERROR(( 133 sci_base_object_get_logger(this_device), 134 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 135 "Port:0x%x Device:0x%x Request:0x%x Status:0x%x could not complete\n", 136 this_device->owning_port, this_device, the_request, status 137 )); 138 } 139 140 return status; 141 } 142 143 //***************************************************************************** 144 //* STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS 145 //***************************************************************************** 146 147 /** 148 * This is the READY NCQ substate handler to start task management request. In this 149 * routine, we suspend and resume the RNC. 150 * 151 * @param[in] device The target device a task management request towards to. 152 * @param[in] request The task request. 153 * 154 * @return SCI_STATUS Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status 155 * to let controller_start_task_handler know that the controller can't post TC for 156 * task request yet, instead, when RNC gets resumed, a controller_continue_task 157 * callback will be called. 158 */ 159 static 160 SCI_STATUS scic_sds_stp_remote_device_ready_substate_start_request_handler( 161 SCI_BASE_REMOTE_DEVICE_T * device, 162 SCI_BASE_REQUEST_T * request 163 ) 164 { 165 SCI_STATUS status; 166 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 167 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)request; 168 169 // Will the port allow the io request to start? 170 status = this_device->owning_port->state_handlers->start_io_handler( 171 this_device->owning_port, 172 this_device, 173 this_request 174 ); 175 176 if (SCI_SUCCESS == status) 177 { 178 status = 179 scic_sds_remote_node_context_start_task(this_device->rnc, this_request); 180 181 if (SCI_SUCCESS == status) 182 { 183 status = this_request->state_handlers->parent.start_handler(request); 184 } 185 186 if (status == SCI_SUCCESS) 187 { 188 /// @note If the remote device state is not IDLE this will replace 189 /// the request that probably resulted in the task management 190 /// request. 191 this_device->working_request = this_request; 192 193 sci_base_state_machine_change_state( 194 &this_device->ready_substate_machine, 195 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD 196 ); 197 198 //The remote node context must cleanup the TCi to NCQ mapping table. 199 //The only way to do this correctly is to either write to the TLCR 200 //register or to invalidate and repost the RNC. In either case the 201 //remote node context state machine will take the correct action when 202 //the remote node context is suspended and later resumed. 203 scic_sds_remote_node_context_suspend( 204 this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); 205 206 scic_sds_remote_node_context_resume( 207 this_device->rnc, 208 (SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK) 209 scic_sds_remote_device_continue_request, 210 this_device); 211 } 212 213 scic_sds_remote_device_start_request(this_device,this_request,status); 214 215 //We need to let the controller start request handler know that it can't 216 //post TC yet. We will provide a callback function to post TC when RNC gets 217 //resumed. 218 return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; 219 } 220 221 return status; 222 } 223 224 //***************************************************************************** 225 //* STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS 226 //***************************************************************************** 227 228 /** 229 * This method will handle the start io operation for a sata device that is in 230 * the command idle state. 231 * - Evalute the type of IO request to be started 232 * - If its an NCQ request change to NCQ substate 233 * - If its any other command change to the CMD substate 234 * 235 * @note If this is a softreset we may want to have a different substate. 236 * 237 * @param [in] device 238 * @param [in] request 239 * 240 * @return SCI_STATUS 241 */ 242 static 243 SCI_STATUS scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( 244 SCI_BASE_REMOTE_DEVICE_T * device, 245 SCI_BASE_REQUEST_T * request 246 ) 247 { 248 SCI_STATUS status; 249 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 250 SCIC_SDS_REQUEST_T * io_request = (SCIC_SDS_REQUEST_T *)request; 251 252 253 // Will the port allow the io request to start? 254 status = this_device->owning_port->state_handlers->start_io_handler( 255 this_device->owning_port, 256 this_device, 257 io_request 258 ); 259 260 if (status == SCI_SUCCESS) 261 { 262 status = 263 scic_sds_remote_node_context_start_io(this_device->rnc, io_request); 264 265 if (status == SCI_SUCCESS) 266 { 267 status = io_request->state_handlers->parent.start_handler(request); 268 } 269 270 if (status == SCI_SUCCESS) 271 { 272 if (io_request->sat_protocol == SAT_PROTOCOL_FPDMA) 273 { 274 sci_base_state_machine_change_state( 275 &this_device->ready_substate_machine, 276 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ 277 ); 278 } 279 else 280 { 281 this_device->working_request = io_request; 282 283 sci_base_state_machine_change_state( 284 &this_device->ready_substate_machine, 285 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD 286 ); 287 } 288 } 289 290 scic_sds_remote_device_start_request(this_device, io_request, status); 291 } 292 293 return status; 294 } 295 296 297 /** 298 * This method will handle the event for a sata device that is in 299 * the idle state. We pick up suspension events to handle specifically 300 * to this state. We resume the RNC right away. 301 * 302 * @param [in] device The device received event. 303 * @param [in] event_code The event code. 304 * 305 * @return SCI_STATUS 306 */ 307 static 308 SCI_STATUS scic_sds_stp_remote_device_ready_idle_substate_event_handler( 309 SCIC_SDS_REMOTE_DEVICE_T * this_device, 310 U32 event_code 311 ) 312 { 313 SCI_STATUS status; 314 315 status = scic_sds_remote_device_general_event_handler(this_device, event_code); 316 317 if (status == SCI_SUCCESS) 318 { 319 if ((scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX 320 || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) 321 && (this_device->rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)) 322 { 323 status = scic_sds_remote_node_context_resume( 324 this_device->rnc, NULL, NULL); 325 } 326 } 327 328 return status; 329 } 330 331 332 //***************************************************************************** 333 //* STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS 334 //***************************************************************************** 335 336 /** 337 * 338 */ 339 static 340 SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( 341 SCI_BASE_REMOTE_DEVICE_T * device, 342 SCI_BASE_REQUEST_T * request 343 ) 344 { 345 SCI_STATUS status; 346 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 347 SCIC_SDS_REQUEST_T * io_request = (SCIC_SDS_REQUEST_T *)request; 348 349 if (io_request->sat_protocol == SAT_PROTOCOL_FPDMA) 350 { 351 status = this_device->owning_port->state_handlers->start_io_handler( 352 this_device->owning_port, 353 this_device, 354 io_request 355 ); 356 357 if (status == SCI_SUCCESS) 358 { 359 status = scic_sds_remote_node_context_start_io(this_device->rnc, io_request); 360 361 if (status == SCI_SUCCESS) 362 { 363 status = io_request->state_handlers->parent.start_handler(request); 364 } 365 366 scic_sds_remote_device_start_request(this_device, io_request, status); 367 } 368 } 369 else 370 { 371 status = SCI_FAILURE_INVALID_STATE; 372 } 373 374 return status; 375 } 376 377 /** 378 * This method will handle events received while the STP device is in the 379 * ready command substate. 380 * 381 * @param [in] this_device This is the device object that is receiving the 382 * event. 383 * @param [in] event_code The event code to process. 384 * 385 * @return SCI_STATUS 386 */ 387 static 388 SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_event_handler( 389 SCIC_SDS_REMOTE_DEVICE_T * this_device, 390 U32 event_code 391 ) 392 { 393 SCI_STATUS status; 394 395 status = scic_sds_remote_device_general_event_handler(this_device, event_code); 396 397 switch (scu_get_event_code(event_code)) 398 { 399 case SCU_EVENT_TL_RNC_SUSPEND_TX: 400 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: 401 /// @todo We need to decode and understand why the hardware suspended the device. 402 /// The suspension reason was probably due to an SDB error FIS received. 403 break; 404 405 case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_DATA_LEN_ERR: 406 case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_OFFSET_ERR: 407 case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_DMASETUP_DIERR: 408 case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_XFERCNT_ERR: 409 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX_DONE_PLD_LEN_ERR: 410 this_device->not_ready_reason = 411 SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; 412 413 sci_base_state_machine_change_state( 414 &this_device->ready_substate_machine, 415 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR 416 ); 417 418 // We have a notification that the driver requested a suspend operation 419 // this should not happen. 420 SCIC_LOG_WARNING(( 421 sci_base_object_get_logger(this_device), 422 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 423 "SCIC Remote device 0x%x received driver suspend event %x while in ncq ready substate %d\n", 424 this_device, event_code, sci_base_state_machine_get_state(&this_device->ready_substate_machine) 425 )); 426 427 // Since we didn't expect to get here start the device again. 428 status = scic_sds_remote_device_resume(this_device); 429 break; 430 431 case SCU_EVENT_POST_RCN_RELEASE: 432 /// @todo Do we need to store the suspend state on the device? 433 SCIC_LOG_INFO(( 434 sci_base_object_get_logger(this_device), 435 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 436 "SCIC Remote device 0x%x received driver release event %x while in the ready substate %d\n", 437 this_device, event_code, sci_base_state_machine_get_state(&this_device->ready_substate_machine) 438 )); 439 break; 440 441 default: 442 // Some other event just log it and continue 443 SCIC_LOG_WARNING(( 444 sci_base_object_get_logger(this_device), 445 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 446 "SCIC Remote device 0x%x received driver unexpected event %x while in the ready substate %d\n", 447 this_device, event_code, sci_base_state_machine_get_state(&this_device->ready_substate_machine) 448 )); 449 450 status = SCI_FAILURE_INVALID_STATE; 451 break; 452 } 453 454 return status; 455 } 456 457 /** 458 * 459 * 460 * @param[in] this_device 461 * @param[in] frame_index 462 * 463 * @return SCI_STATUS 464 */ 465 static 466 SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( 467 SCIC_SDS_REMOTE_DEVICE_T * this_device, 468 U32 frame_index 469 ) 470 { 471 SCI_STATUS status; 472 SATA_FIS_HEADER_T * frame_header; 473 474 status = scic_sds_unsolicited_frame_control_get_header( 475 &(scic_sds_remote_device_get_controller(this_device)->uf_control), 476 frame_index, 477 (void **)&frame_header 478 ); 479 480 if (status == SCI_SUCCESS) 481 { 482 if ( 483 (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS) 484 && (frame_header->status & ATA_STATUS_REG_ERROR_BIT) 485 ) 486 { 487 this_device->not_ready_reason = 488 SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; 489 490 /** @todo Check sactive and complete associated IO if any. */ 491 492 sci_base_state_machine_change_state( 493 &this_device->ready_substate_machine, 494 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR 495 ); 496 } 497 else if ( 498 (frame_header->fis_type == SATA_FIS_TYPE_REGD2H) 499 && (frame_header->status & ATA_STATUS_REG_ERROR_BIT) 500 ) 501 { 502 // Some devices return D2H FIS when an NCQ error is detected. 503 // Treat this like an SDB error FIS ready reason. 504 this_device->not_ready_reason = 505 SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; 506 507 sci_base_state_machine_change_state( 508 &this_device->ready_substate_machine, 509 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR 510 ); 511 } 512 else 513 { 514 status = SCI_FAILURE; 515 } 516 517 scic_sds_controller_release_frame( 518 scic_sds_remote_device_get_controller(this_device), frame_index 519 ); 520 } 521 522 return status; 523 } 524 525 //***************************************************************************** 526 //* STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS 527 //***************************************************************************** 528 529 /** 530 * This device is already handling a command it can not accept new commands 531 * until this one is complete. 532 * 533 * @param[in] device 534 * @param[in] request 535 * 536 * @return SCI_STATUS 537 */ 538 static 539 SCI_STATUS scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( 540 SCI_BASE_REMOTE_DEVICE_T * device, 541 SCI_BASE_REQUEST_T * request 542 ) 543 { 544 return SCI_FAILURE_INVALID_STATE; 545 } 546 547 static 548 SCI_STATUS scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( 549 SCIC_SDS_REMOTE_DEVICE_T * this_device, 550 U32 suspend_type 551 ) 552 { 553 SCI_STATUS status; 554 555 status = scic_sds_remote_node_context_suspend( 556 this_device->rnc, suspend_type, NULL, NULL 557 ); 558 559 return status; 560 } 561 562 /** 563 * 564 * 565 * @param[in] this_device 566 * @param[in] frame_index 567 * 568 * @return SCI_STATUS 569 */ 570 static 571 SCI_STATUS scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( 572 SCIC_SDS_REMOTE_DEVICE_T * this_device, 573 U32 frame_index 574 ) 575 { 576 SCI_STATUS status; 577 578 /// The device doe not process any UF received from the hardware while 579 /// in this state. All unsolicited frames are forwarded to the io request 580 /// object. 581 status = scic_sds_io_request_frame_handler( 582 this_device->working_request, 583 frame_index 584 ); 585 586 return status; 587 } 588 589 590 //***************************************************************************** 591 //* STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS 592 //***************************************************************************** 593 594 595 //***************************************************************************** 596 //* STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS 597 //***************************************************************************** 598 static 599 SCI_STATUS scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( 600 SCI_BASE_REMOTE_DEVICE_T * device, 601 SCI_BASE_REQUEST_T * request 602 ) 603 { 604 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; 605 } 606 607 608 609 /** 610 * This method will perform the STP request (both io or task) completion 611 * processing for await reset state. 612 * 613 * @param[in] device This parameter specifies the device for which the 614 * request is being completed. 615 * @param[in] request This parameter specifies the request being completed. 616 * 617 * @return This method returns an indication as to whether the request 618 * processing completed successfully. 619 */ 620 static 621 SCI_STATUS scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( 622 SCI_BASE_REMOTE_DEVICE_T * device, 623 SCI_BASE_REQUEST_T * request 624 ) 625 { 626 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 627 SCIC_SDS_REQUEST_T * the_request = (SCIC_SDS_REQUEST_T *)request; 628 SCI_STATUS status; 629 630 status = scic_sds_io_request_complete(the_request); 631 632 if (status == SCI_SUCCESS) 633 { 634 status = scic_sds_port_complete_io( 635 this_device->owning_port, this_device, the_request 636 ); 637 638 if (status == SCI_SUCCESS) 639 scic_sds_remote_device_decrement_request_count(this_device); 640 } 641 642 if (status != SCI_SUCCESS) 643 { 644 SCIC_LOG_ERROR(( 645 sci_base_object_get_logger(this_device), 646 SCIC_LOG_OBJECT_STP_REMOTE_TARGET, 647 "Port:0x%x Device:0x%x Request:0x%x Status:0x%x could not complete\n", 648 this_device->owning_port, this_device, the_request, status 649 )); 650 } 651 652 return status; 653 } 654 655 #if !defined(DISABLE_ATAPI) 656 //***************************************************************************** 657 //* STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS 658 //***************************************************************************** 659 660 /** 661 * This method will handle the event for a ATAPI device that is in 662 * the ATAPI ERROR state. We pick up suspension events to handle specifically 663 * to this state. We resume the RNC right away. We then complete the outstanding 664 * IO to this device. 665 * 666 * @param [in] device The device received event. 667 * @param [in] event_code The event code. 668 * 669 * @return SCI_STATUS 670 */ 671 static 672 SCI_STATUS scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler( 673 SCIC_SDS_REMOTE_DEVICE_T * this_device, 674 U32 event_code 675 ) 676 { 677 SCI_STATUS status; 678 679 status = scic_sds_remote_device_general_event_handler(this_device, event_code); 680 681 if (status == SCI_SUCCESS) 682 { 683 if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX 684 || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) 685 { 686 status = scic_sds_remote_node_context_resume( 687 this_device->rnc, 688 (SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK) 689 this_device->working_request->state_handlers->parent.complete_handler, 690 (void *)this_device->working_request 691 ); 692 } 693 } 694 695 return status; 696 } 697 #endif // !defined(DISABLE_ATAPI) 698 699 // --------------------------------------------------------------------------- 700 701 SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T 702 scic_sds_stp_remote_device_ready_substate_handler_table[ 703 SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = 704 { 705 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE 706 { 707 { 708 scic_sds_remote_device_default_start_handler, 709 scic_sds_remote_device_ready_state_stop_handler, 710 scic_sds_remote_device_default_fail_handler, 711 scic_sds_remote_device_default_destruct_handler, 712 scic_sds_remote_device_ready_state_reset_handler, 713 scic_sds_remote_device_default_reset_complete_handler, 714 scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, 715 scic_sds_remote_device_default_complete_request_handler, 716 scic_sds_remote_device_default_continue_request_handler, 717 scic_sds_stp_remote_device_ready_substate_start_request_handler, 718 scic_sds_remote_device_default_complete_request_handler 719 }, 720 scic_sds_remote_device_default_suspend_handler, 721 scic_sds_remote_device_default_resume_handler, 722 scic_sds_stp_remote_device_ready_idle_substate_event_handler, 723 scic_sds_remote_device_default_frame_handler 724 }, 725 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD 726 { 727 { 728 scic_sds_remote_device_default_start_handler, 729 scic_sds_remote_device_ready_state_stop_handler, 730 scic_sds_remote_device_default_fail_handler, 731 scic_sds_remote_device_default_destruct_handler, 732 scic_sds_remote_device_ready_state_reset_handler, 733 scic_sds_remote_device_default_reset_complete_handler, 734 scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, 735 scic_sds_stp_remote_device_complete_request, 736 scic_sds_remote_device_default_continue_request_handler, 737 scic_sds_stp_remote_device_ready_substate_start_request_handler, 738 scic_sds_stp_remote_device_complete_request, 739 }, 740 scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, 741 scic_sds_remote_device_default_resume_handler, 742 scic_sds_remote_device_general_event_handler, 743 scic_sds_stp_remote_device_ready_cmd_substate_frame_handler 744 }, 745 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ 746 { 747 { 748 scic_sds_remote_device_default_start_handler, 749 scic_sds_remote_device_ready_state_stop_handler, 750 scic_sds_remote_device_default_fail_handler, 751 scic_sds_remote_device_default_destruct_handler, 752 scic_sds_remote_device_ready_state_reset_handler, 753 scic_sds_remote_device_default_reset_complete_handler, 754 scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, 755 scic_sds_stp_remote_device_complete_request, 756 scic_sds_remote_device_default_continue_request_handler, 757 scic_sds_stp_remote_device_ready_substate_start_request_handler, 758 scic_sds_stp_remote_device_complete_request 759 }, 760 scic_sds_remote_device_default_suspend_handler, 761 scic_sds_remote_device_default_resume_handler, 762 scic_sds_stp_remote_device_ready_ncq_substate_event_handler, 763 scic_sds_stp_remote_device_ready_ncq_substate_frame_handler 764 }, 765 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR 766 { 767 { 768 scic_sds_remote_device_default_start_handler, 769 scic_sds_remote_device_ready_state_stop_handler, 770 scic_sds_remote_device_default_fail_handler, 771 scic_sds_remote_device_default_destruct_handler, 772 scic_sds_remote_device_ready_state_reset_handler, 773 scic_sds_remote_device_default_reset_complete_handler, 774 scic_sds_remote_device_default_start_request_handler, 775 scic_sds_stp_remote_device_complete_request, 776 scic_sds_remote_device_default_continue_request_handler, 777 scic_sds_stp_remote_device_ready_substate_start_request_handler, 778 scic_sds_stp_remote_device_complete_request 779 }, 780 scic_sds_remote_device_default_suspend_handler, 781 scic_sds_remote_device_default_resume_handler, 782 scic_sds_remote_device_general_event_handler, 783 scic_sds_remote_device_general_frame_handler 784 }, 785 #if !defined(DISABLE_ATAPI) 786 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR 787 { 788 { 789 scic_sds_remote_device_default_start_handler, 790 scic_sds_remote_device_ready_state_stop_handler, 791 scic_sds_remote_device_default_fail_handler, 792 scic_sds_remote_device_default_destruct_handler, 793 scic_sds_remote_device_ready_state_reset_handler, 794 scic_sds_remote_device_default_reset_complete_handler, 795 scic_sds_remote_device_default_start_request_handler, 796 scic_sds_stp_remote_device_complete_request, 797 scic_sds_remote_device_default_continue_request_handler, 798 scic_sds_stp_remote_device_ready_substate_start_request_handler, 799 scic_sds_stp_remote_device_complete_request 800 }, 801 scic_sds_remote_device_default_suspend_handler, 802 scic_sds_remote_device_default_resume_handler, 803 scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler, 804 scic_sds_remote_device_general_frame_handler 805 }, 806 #endif 807 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET 808 { 809 { 810 scic_sds_remote_device_default_start_handler, 811 scic_sds_remote_device_ready_state_stop_handler, 812 scic_sds_remote_device_default_fail_handler, 813 scic_sds_remote_device_default_destruct_handler, 814 scic_sds_remote_device_ready_state_reset_handler, 815 scic_sds_remote_device_default_reset_complete_handler, 816 scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, 817 scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, 818 scic_sds_remote_device_default_continue_request_handler, 819 scic_sds_stp_remote_device_ready_substate_start_request_handler, 820 scic_sds_stp_remote_device_complete_request 821 }, 822 scic_sds_remote_device_default_suspend_handler, 823 scic_sds_remote_device_default_resume_handler, 824 scic_sds_remote_device_general_event_handler, 825 scic_sds_remote_device_general_frame_handler 826 } 827 }; 828 829 //***************************************************************************** 830 //* STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS 831 //***************************************************************************** 832 833 static 834 void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( 835 void * user_cookie 836 ) 837 { 838 SCIC_SDS_REMOTE_DEVICE_T * this_device; 839 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_cookie; 840 841 // For NCQ operation we do not issue a 842 // scic_cb_remote_device_not_ready(). As a result, avoid sending 843 // the ready notification. 844 if (this_device->ready_substate_machine.previous_state_id 845 != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) 846 { 847 scic_cb_remote_device_ready( 848 scic_sds_remote_device_get_controller(this_device), this_device 849 ); 850 } 851 } 852 853 //***************************************************************************** 854 //* STP REMOTE DEVICE READY IDLE SUBSTATE 855 //***************************************************************************** 856 857 /** 858 * 859 * @param[in] device This is the SCI base object which is cast into a 860 * SCIC_SDS_REMOTE_DEVICE object. 861 * 862 * @return none 863 */ 864 static 865 void scic_sds_stp_remote_device_ready_idle_substate_enter( 866 SCI_BASE_OBJECT_T * device 867 ) 868 { 869 SCIC_SDS_REMOTE_DEVICE_T * this_device; 870 871 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 872 873 SET_STATE_HANDLER( 874 this_device, 875 scic_sds_stp_remote_device_ready_substate_handler_table, 876 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE 877 ); 878 879 this_device->working_request = NULL; 880 881 if (scic_sds_remote_node_context_is_ready(this_device->rnc)) 882 { 883 // Since the RNC is ready, it's alright to finish completion 884 // processing (e.g. signal the remote device is ready). 885 scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( 886 this_device 887 ); 888 } 889 else 890 { 891 scic_sds_remote_node_context_resume( 892 this_device->rnc, 893 scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, 894 this_device 895 ); 896 } 897 } 898 899 //***************************************************************************** 900 //* STP REMOTE DEVICE READY CMD SUBSTATE 901 //***************************************************************************** 902 903 /** 904 * 905 * 906 * @param[in] device This is the SCI base object which is cast into a 907 * SCIC_SDS_REMOTE_DEVICE object. 908 * 909 * @return none 910 */ 911 static 912 void scic_sds_stp_remote_device_ready_cmd_substate_enter( 913 SCI_BASE_OBJECT_T * device 914 ) 915 { 916 SCIC_SDS_REMOTE_DEVICE_T * this_device; 917 918 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 919 920 ASSERT(this_device->working_request != NULL); 921 922 SET_STATE_HANDLER( 923 this_device, 924 scic_sds_stp_remote_device_ready_substate_handler_table, 925 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD 926 ); 927 928 scic_cb_remote_device_not_ready( 929 scic_sds_remote_device_get_controller(this_device), 930 this_device, 931 SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED 932 ); 933 } 934 935 //***************************************************************************** 936 //* STP REMOTE DEVICE READY NCQ SUBSTATE 937 //***************************************************************************** 938 939 /** 940 * 941 * 942 * @param[in] device This is the SCI base object which is cast into a 943 * SCIC_SDS_REMOTE_DEVICE object. 944 * 945 * @return none 946 */ 947 static 948 void scic_sds_stp_remote_device_ready_ncq_substate_enter( 949 SCI_BASE_OBJECT_T * device 950 ) 951 { 952 SCIC_SDS_REMOTE_DEVICE_T * this_device; 953 954 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 955 956 SET_STATE_HANDLER( 957 this_device, 958 scic_sds_stp_remote_device_ready_substate_handler_table, 959 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ 960 ); 961 } 962 963 //***************************************************************************** 964 //* STP REMOTE DEVICE READY NCQ ERROR SUBSTATE 965 //***************************************************************************** 966 967 /** 968 * 969 * 970 * @param[in] device This is the SCI base object which is cast into a 971 * SCIC_SDS_REMOTE_DEVICE object. 972 * 973 * @return none 974 */ 975 static 976 void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( 977 SCI_BASE_OBJECT_T * device 978 ) 979 { 980 SCIC_SDS_REMOTE_DEVICE_T * this_device; 981 982 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 983 984 SET_STATE_HANDLER( 985 this_device, 986 scic_sds_stp_remote_device_ready_substate_handler_table, 987 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR 988 ); 989 990 if(this_device->not_ready_reason == 991 SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) 992 { 993 scic_cb_remote_device_not_ready( 994 scic_sds_remote_device_get_controller(this_device), 995 this_device, 996 this_device->not_ready_reason 997 ); 998 } 999 } 1000 1001 //***************************************************************************** 1002 //* STP REMOTE DEVICE READY AWAIT RESET SUBSTATE 1003 //***************************************************************************** 1004 1005 /** 1006 * @brief The enter routine to READY AWAIT RESET substate. 1007 * 1008 * @param[in] device This is the SCI base object which is cast into a 1009 * SCIC_SDS_REMOTE_DEVICE object. 1010 * 1011 * @return none 1012 */ 1013 static 1014 void scic_sds_stp_remote_device_ready_await_reset_substate_enter( 1015 SCI_BASE_OBJECT_T * device 1016 ) 1017 { 1018 SCIC_SDS_REMOTE_DEVICE_T * this_device; 1019 1020 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 1021 1022 SET_STATE_HANDLER( 1023 this_device, 1024 scic_sds_stp_remote_device_ready_substate_handler_table, 1025 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET 1026 ); 1027 } 1028 1029 #if !defined(DISABLE_ATAPI) 1030 //***************************************************************************** 1031 //* STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE 1032 //***************************************************************************** 1033 1034 /** 1035 * @brief The enter routine to READY ATAPI ERROR substate. 1036 * 1037 * @param[in] device This is the SCI base object which is cast into a 1038 * SCIC_SDS_REMOTE_DEVICE object. 1039 * 1040 * @return none 1041 */ 1042 static 1043 void scic_sds_stp_remote_device_ready_atapi_error_substate_enter( 1044 SCI_BASE_OBJECT_T * device 1045 ) 1046 { 1047 SCIC_SDS_REMOTE_DEVICE_T * this_device; 1048 1049 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 1050 1051 SET_STATE_HANDLER( 1052 this_device, 1053 scic_sds_stp_remote_device_ready_substate_handler_table, 1054 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR 1055 ); 1056 } 1057 #endif // !defined(DISABLE_ATAPI) 1058 1059 // --------------------------------------------------------------------------- 1060 1061 SCI_BASE_STATE_T 1062 scic_sds_stp_remote_device_ready_substate_table[ 1063 SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = 1064 { 1065 { 1066 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, 1067 scic_sds_stp_remote_device_ready_idle_substate_enter, 1068 NULL 1069 }, 1070 { 1071 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD, 1072 scic_sds_stp_remote_device_ready_cmd_substate_enter, 1073 NULL 1074 }, 1075 { 1076 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ, 1077 scic_sds_stp_remote_device_ready_ncq_substate_enter, 1078 NULL 1079 }, 1080 { 1081 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR, 1082 scic_sds_stp_remote_device_ready_ncq_error_substate_enter, 1083 NULL 1084 }, 1085 #if !defined(DISABLE_ATAPI) 1086 { 1087 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR, 1088 scic_sds_stp_remote_device_ready_atapi_error_substate_enter, 1089 NULL 1090 }, 1091 #endif 1092 { 1093 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET, 1094 scic_sds_stp_remote_device_ready_await_reset_substate_enter, 1095 NULL 1096 } 1097 }; 1098 1099