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