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 #if !defined(DISABLE_ATAPI) 57 58 #include <dev/isci/scil/scic_sds_stp_packet_request.h> 59 #include <dev/isci/scil/scic_sds_logger.h> 60 #include <dev/isci/scil/scic_sds_controller.h> 61 #include <dev/isci/scil/scic_sds_remote_device.h> 62 #include <dev/isci/scil/scic_remote_device.h> 63 #include <dev/isci/scil/sci_util.h> 64 #include <dev/isci/scil/intel_sas.h> 65 #include <dev/isci/scil/intel_ata.h> 66 #include <dev/isci/scil/intel_sata.h> 67 #include <dev/isci/scil/scic_user_callback.h> 68 #include <dev/isci/sci_environment.h> 69 #include <dev/isci/scil/intel_sat.h> 70 #include <dev/isci/scil/scic_sds_request.h> 71 #include <dev/isci/scil/scic_controller.h> 72 #include <dev/isci/scil/scu_completion_codes.h> 73 #include <dev/isci/scil/scu_task_context.h> 74 #include <dev/isci/scil/scic_sds_stp_packet_request.h> 75 #include <dev/isci/scil/sci_base_state.h> 76 77 /** 78 * @brief This method will fill in the SCU Task Context for a PACKET fis. And 79 * construct the request STARTED sub-state machine for Packet Protocol 80 * IO. 81 * 82 * @param[in] this_request This parameter specifies the stp packet request object 83 * being constructed. 84 * 85 * @return none 86 */ 87 SCI_STATUS scic_sds_stp_packet_request_construct( 88 SCIC_SDS_REQUEST_T *this_request 89 ) 90 { 91 SATA_FIS_REG_H2D_T * h2d_fis = 92 scic_stp_io_request_get_h2d_reg_address( 93 this_request 94 ); 95 96 // Work around, we currently only support PACKET DMA protocol, so we 97 // need to make change to Packet Fis features field. 98 h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA; 99 100 scic_sds_stp_non_ncq_request_construct(this_request); 101 102 // Build the Packet Fis task context structure 103 scu_stp_raw_request_construct_task_context( 104 (SCIC_SDS_STP_REQUEST_T*) this_request, 105 this_request->task_context_buffer 106 ); 107 108 sci_base_state_machine_construct( 109 &this_request->started_substate_machine, 110 &this_request->parent.parent, 111 scic_sds_stp_packet_request_started_substate_table, 112 SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE 113 ); 114 115 return SCI_SUCCESS; 116 } 117 118 119 /** 120 * @brief This method will fill in the SCU Task Context for a Packet request 121 * command phase in PACKET DMA DATA (IN/OUT) type. The following 122 * important settings are utilized: 123 * 124 * -# task_type == SCU_TASK_TYPE_PACKET_DMA. This simply indicates 125 * that a normal request type (i.e. non-raw frame) is being 126 * utilized to perform task management. 127 * -# control_frame == 1. This ensures that the proper endianness 128 * is set so that the bytes are transmitted in the right order 129 * for a smp request frame. 130 * 131 * @param[in] this_request This parameter specifies the smp request object 132 * being constructed. 133 * @param[in] task_context The task_context to be reconstruct for packet 134 * request command phase. 135 * @return none 136 */ 137 void scu_stp_packet_request_command_phase_construct_task_context( 138 SCIC_SDS_REQUEST_T * this_request, 139 SCU_TASK_CONTEXT_T * task_context 140 ) 141 { 142 void * atapi_cdb; 143 U32 atapi_cdb_length; 144 SCIC_SDS_STP_REQUEST_T * stp_request = (SCIC_SDS_STP_REQUEST_T *)this_request; 145 146 // reference: SSTL 1.13.4.2 147 // task_type, sata_direction 148 if ( scic_cb_io_request_get_data_direction(this_request->user_request) 149 == SCI_IO_REQUEST_DATA_OUT ) 150 { 151 task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT; 152 task_context->sata_direction = 0; 153 } 154 else // todo: for NO_DATA command, we need to send out raw frame. 155 { 156 task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN; 157 task_context->sata_direction = 1; 158 } 159 160 // sata header 161 memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT)); 162 task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; 163 164 // Copy in the command IU with CDB so that the commandIU address doesn't 165 // change. 166 memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T)); 167 168 atapi_cdb = 169 scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request); 170 171 atapi_cdb_length = 172 scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request); 173 174 memcpy(((U8 *)this_request->command_buffer+sizeof(U32)), atapi_cdb, atapi_cdb_length); 175 176 atapi_cdb_length = 177 MAX(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length); 178 179 task_context->ssp_command_iu_length = 180 ((atapi_cdb_length % 4) == 0) ? 181 (atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1); 182 183 // task phase is set to TX_CMD 184 task_context->task_phase = 0x1; 185 186 // retry counter 187 task_context->stp_retry_count = 0; 188 189 if (scic_cb_request_is_initial_construction(this_request->user_request)) 190 { 191 // data transfer size. 192 task_context->transfer_length_bytes = 193 scic_cb_io_request_get_transfer_length(this_request->user_request); 194 195 // sgls were already built when request was constructed, so don't need to 196 // to do it here 197 } 198 else 199 { 200 // data transfer size, need to be 4 bytes aligned. 201 task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2); 202 203 scic_sds_stp_packet_internal_request_sense_build_sgl(this_request); 204 } 205 } 206 207 /** 208 * @brief This method will fill in the SCU Task Context for a DATA fis 209 * containing CDB in Raw Frame type. The TC for previous Packet 210 * fis was already there, we only need to change the H2D fis content. 211 * 212 * @param[in] this_request This parameter specifies the smp request object 213 * being constructed. 214 * @param[in] task_context The task_context to be reconstruct for packet 215 * request command phase. 216 * @return none 217 */ 218 void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( 219 SCIC_SDS_REQUEST_T * this_request, 220 SCU_TASK_CONTEXT_T * task_context 221 ) 222 { 223 void * atapi_cdb = 224 scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request); 225 226 U32 atapi_cdb_length = 227 scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request); 228 229 memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T)); 230 memcpy( ((U8 *)this_request->command_buffer+sizeof(U32)), atapi_cdb, atapi_cdb_length); 231 232 memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT)); 233 task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; 234 235 //Note the data send out has to be 4 bytes aligned. Or else out hardware will 236 //patch non-zero bytes and cause the target device unhappy. 237 task_context->transfer_length_bytes = 12; 238 } 239 240 241 /* 242 *@brief This methods decode the D2H status FIS and retrieve the sense data, 243 * then pass the sense data to user request. 244 * 245 *@param[in] this_request The request receive D2H status FIS. 246 *@param[in] status_fis The D2H status fis to be processed. 247 * 248 */ 249 SCI_STATUS scic_sds_stp_packet_request_process_status_fis( 250 SCIC_SDS_REQUEST_T * this_request, 251 SATA_FIS_REG_D2H_T * status_fis 252 ) 253 { 254 SCI_STATUS status = SCI_SUCCESS; 255 256 //TODO: Process the error status fis, retrieve sense data. 257 if (status_fis->status & ATA_STATUS_REG_ERROR_BIT) 258 status = SCI_FAILURE_IO_RESPONSE_VALID; 259 260 return status; 261 } 262 263 /* 264 *@brief This methods builds sgl for internal REQUEST SENSE stp packet 265 * command using this request response buffer, only one sge is 266 * needed. 267 * 268 *@param[in] this_request The request receive request sense data. 269 * 270 */ 271 void scic_sds_stp_packet_internal_request_sense_build_sgl( 272 SCIC_SDS_REQUEST_T * this_request 273 ) 274 { 275 void *sge; 276 SCU_SGL_ELEMENT_PAIR_T *scu_sgl_list = NULL; 277 SCU_TASK_CONTEXT_T *task_context; 278 SCI_PHYSICAL_ADDRESS physical_address; 279 280 SCI_SSP_RESPONSE_IU_T * rsp_iu = 281 (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer; 282 sge = (void*)&rsp_iu->data[0]; 283 284 task_context = (SCU_TASK_CONTEXT_T *)this_request->task_context_buffer; 285 scu_sgl_list = &task_context->sgl_pair_ab; 286 287 scic_cb_io_request_get_physical_address( 288 scic_sds_request_get_controller(this_request), 289 this_request, 290 ((char *)sge), 291 &physical_address 292 ); 293 294 scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address); 295 scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address); 296 scu_sgl_list->A.length = task_context->transfer_length_bytes; 297 scu_sgl_list->A.address_modifier = 0; 298 299 SCU_SGL_ZERO(scu_sgl_list->B); 300 } 301 302 //****************************************************************************** 303 //* STP PACKET REQUEST STATE MACHINES 304 //****************************************************************************** 305 306 /** 307 * @brief This method processes the completions transport layer (TL) status 308 * to determine if the Packet FIS was sent successfully. If the Packet 309 * FIS was sent successfully, then the state for the Packet request 310 * transits to waiting for a PIO SETUP frame. 311 * 312 * @param[in] this_request This parameter specifies the request for which 313 * the TC completion was received. 314 * @param[in] completion_code This parameter indicates the completion status 315 * information for the TC. 316 * 317 * @return Indicate if the tc completion handler was successful. 318 * @retval SCI_SUCCESS currently this method always returns success. 319 */ 320 static 321 SCI_STATUS scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler( 322 SCIC_SDS_REQUEST_T * this_request, 323 U32 completion_code 324 ) 325 { 326 SCI_STATUS status = SCI_SUCCESS; 327 328 SCIC_LOG_TRACE(( 329 sci_base_object_get_logger(this_request), 330 SCIC_LOG_OBJECT_STP_IO_REQUEST, 331 "scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n", 332 this_request, completion_code 333 )); 334 335 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 336 { 337 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 338 scic_sds_request_set_status( 339 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 340 ); 341 342 sci_base_state_machine_change_state( 343 &this_request->started_substate_machine, 344 SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE 345 ); 346 break; 347 348 default: 349 // All other completion status cause the IO to be complete. If a NAK 350 // was received, then it is up to the user to retry the request. 351 scic_sds_request_set_status( 352 this_request, 353 SCU_NORMALIZE_COMPLETION_STATUS(completion_code), 354 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 355 ); 356 357 sci_base_state_machine_change_state( 358 &this_request->parent.state_machine, 359 SCI_BASE_REQUEST_STATE_COMPLETED 360 ); 361 break; 362 } 363 364 return status; 365 } 366 367 368 /** 369 * @brief This method processes an unsolicited frame while the Packet request 370 * is waiting for a PIO SETUP FIS. It will release 371 * the unsolicited frame, and transition the request to the 372 * COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE state. 373 * 374 * @param[in] this_request This parameter specifies the request for which 375 * the unsolicited frame was received. 376 * @param[in] frame_index This parameter indicates the unsolicited frame 377 * index that should contain the response. 378 * 379 * @return This method returns an indication of whether the pio setup 380 * frame was handled successfully or not. 381 * @retval SCI_SUCCESS Currently this value is always returned and indicates 382 * successful processing of the TC response. 383 * 384 */ 385 static 386 SCI_STATUS scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler( 387 SCIC_SDS_REQUEST_T * request, 388 U32 frame_index 389 ) 390 { 391 SCI_STATUS status; 392 SATA_FIS_HEADER_T * frame_header; 393 U32 * frame_buffer; 394 SCIC_SDS_STP_REQUEST_T * this_request; 395 396 this_request = (SCIC_SDS_STP_REQUEST_T *)request; 397 398 SCIC_LOG_TRACE(( 399 sci_base_object_get_logger(this_request), 400 SCIC_LOG_OBJECT_STP_IO_REQUEST, 401 "scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(0x%x, 0x%x) enter\n", 402 this_request, frame_index 403 )); 404 405 status = scic_sds_unsolicited_frame_control_get_header( 406 &(this_request->parent.owning_controller->uf_control), 407 frame_index, 408 (void**) &frame_header 409 ); 410 411 if (status == SCI_SUCCESS) 412 { 413 ASSERT(frame_header->fis_type == SATA_FIS_TYPE_PIO_SETUP); 414 415 // Get from the frame buffer the PIO Setup Data, although we don't need 416 // any info from this pio setup fis. 417 scic_sds_unsolicited_frame_control_get_buffer( 418 &(this_request->parent.owning_controller->uf_control), 419 frame_index, 420 (void**) &frame_buffer 421 ); 422 423 // Get the data from the PIO Setup 424 // The SCU Hardware returns first word in the frame_header and the rest 425 // of the data is in the frame buffer so we need to back up one dword 426 this_request->type.packet.device_preferred_cdb_length = 427 (U16)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->transfter_count; 428 429 // Frame has been decoded return it to the controller 430 scic_sds_controller_release_frame( 431 this_request->parent.owning_controller, frame_index 432 ); 433 434 sci_base_state_machine_change_state( 435 &this_request->parent.started_substate_machine, 436 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE 437 ); 438 } 439 else 440 { 441 SCIC_LOG_ERROR(( 442 sci_base_object_get_logger(this_request), 443 SCIC_LOG_OBJECT_STP_IO_REQUEST, 444 "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n", 445 this_request, frame_index, status 446 )); 447 } 448 449 return status; 450 } 451 452 453 /** 454 * @brief This method processes the completions transport layer (TL) status 455 * to determine if the PACKET command data FIS was sent successfully. 456 * If successfully, then the state for the packet request 457 * transits to COMPLETE state. If not successfully, the request transits 458 * to COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE. 459 * 460 * @param[in] this_request This parameter specifies the request for which 461 * the TC completion was received. 462 * @param[in] completion_code This parameter indicates the completion status 463 * information for the TC. 464 * 465 * @return Indicate if the tc completion handler was successful. 466 * @retval SCI_SUCCESS currently this method always returns success. 467 */ 468 static 469 SCI_STATUS scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler( 470 SCIC_SDS_REQUEST_T * this_request, 471 U32 completion_code 472 ) 473 { 474 SCI_STATUS status = SCI_SUCCESS; 475 U8 sat_packet_protocol = this_request->sat_protocol; 476 477 SCIC_LOG_TRACE(( 478 sci_base_object_get_logger(this_request), 479 SCIC_LOG_OBJECT_STP_IO_REQUEST, 480 "scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n", 481 this_request, completion_code 482 )); 483 484 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 485 { 486 case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): 487 scic_sds_request_set_status( 488 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 489 ); 490 491 if ( sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN 492 || sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT 493 ) 494 sci_base_state_machine_change_state( 495 &this_request->parent.state_machine, 496 SCI_BASE_REQUEST_STATE_COMPLETED 497 ); 498 else 499 sci_base_state_machine_change_state( 500 &this_request->started_substate_machine, 501 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE 502 ); 503 break; 504 505 case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT): 506 if (scic_io_request_get_number_of_bytes_transferred(this_request) < 507 scic_cb_io_request_get_transfer_length(this_request->user_request)) 508 { 509 scic_sds_request_set_status( 510 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY 511 ); 512 513 sci_base_state_machine_change_state( 514 &this_request->started_substate_machine, 515 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE 516 ); 517 518 //change the device state to ATAPI_ERROR. 519 sci_base_state_machine_change_state( 520 &this_request->target_device->ready_substate_machine, 521 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR 522 ); 523 524 status = this_request->sci_status; 525 } 526 break; 527 528 case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT): 529 //In this case, there is no UF coming after. compelte the IO now. 530 scic_sds_request_set_status( 531 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 532 ); 533 534 sci_base_state_machine_change_state( 535 &this_request->parent.state_machine, 536 SCI_BASE_REQUEST_STATE_COMPLETED 537 ); 538 539 break; 540 541 default: 542 if (this_request->sci_status != SCI_SUCCESS) 543 { //The io status was set already. This means an UF for the status 544 //fis was received already. 545 546 //A device suspension event is expected, we need to have the device 547 //coming out of suspension, then complete the IO. 548 sci_base_state_machine_change_state( 549 &this_request->started_substate_machine, 550 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE 551 ); 552 553 //change the device state to ATAPI_ERROR. 554 sci_base_state_machine_change_state( 555 &this_request->target_device->ready_substate_machine, 556 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR 557 ); 558 559 status = this_request->sci_status; 560 } 561 else 562 { //If receiving any non-sucess TC status, no UF received yet, then an UF for 563 //the status fis is coming after. 564 scic_sds_request_set_status( 565 this_request, 566 SCU_TASK_DONE_CHECK_RESPONSE, 567 SCI_FAILURE_IO_RESPONSE_VALID 568 ); 569 570 sci_base_state_machine_change_state( 571 &this_request->started_substate_machine, 572 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE 573 ); 574 } 575 break; 576 } 577 578 return status; 579 } 580 581 582 /** 583 * @brief This method processes an unsolicited frame. 584 * 585 * @param[in] this_request This parameter specifies the request for which 586 * the unsolicited frame was received. 587 * @param[in] frame_index This parameter indicates the unsolicited frame 588 * index that should contain the response. 589 * 590 * @return This method returns an indication of whether the UF 591 * frame was handled successfully or not. 592 * @retval SCI_SUCCESS Currently this value is always returned and indicates 593 * successful processing of the TC response. 594 * 595 */ 596 static 597 SCI_STATUS scic_sds_stp_packet_request_command_phase_common_frame_handler( 598 SCIC_SDS_REQUEST_T * request, 599 U32 frame_index 600 ) 601 { 602 SCI_STATUS status; 603 SATA_FIS_HEADER_T * frame_header; 604 U32 * frame_buffer; 605 SCIC_SDS_STP_REQUEST_T * this_request; 606 607 this_request = (SCIC_SDS_STP_REQUEST_T *)request; 608 609 SCIC_LOG_TRACE(( 610 sci_base_object_get_logger(this_request), 611 SCIC_LOG_OBJECT_STP_IO_REQUEST, 612 "scic_sds_stp_packet_request_command_phase_await_d2h_frame_handler(0x%x, 0x%x) enter\n", 613 this_request, frame_index 614 )); 615 616 status = scic_sds_unsolicited_frame_control_get_header( 617 &(this_request->parent.owning_controller->uf_control), 618 frame_index, 619 (void**) &frame_header 620 ); 621 622 if (status == SCI_SUCCESS) 623 { 624 ASSERT(frame_header->fis_type == SATA_FIS_TYPE_REGD2H); 625 626 // Get from the frame buffer the PIO Setup Data, although we don't need 627 // any info from this pio setup fis. 628 scic_sds_unsolicited_frame_control_get_buffer( 629 &(this_request->parent.owning_controller->uf_control), 630 frame_index, 631 (void**) &frame_buffer 632 ); 633 634 scic_sds_controller_copy_sata_response( 635 &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer 636 ); 637 638 // Frame has been decoded return it to the controller 639 scic_sds_controller_release_frame( 640 this_request->parent.owning_controller, frame_index 641 ); 642 } 643 644 return status; 645 } 646 647 /** 648 * @brief This method processes an unsolicited frame while the packet request is 649 * expecting TC completion. It will process the FIS and construct sense 650 * data. 651 * 652 * @param[in] this_request This parameter specifies the request for which 653 * the unsolicited frame was received. 654 * @param[in] frame_index This parameter indicates the unsolicited frame 655 * index that should contain the response. 656 * 657 * @return This method returns an indication of whether the UF 658 * frame was handled successfully or not. 659 * @retval SCI_SUCCESS Currently this value is always returned and indicates 660 * successful processing of the TC response. 661 * 662 */ 663 static 664 SCI_STATUS scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler( 665 SCIC_SDS_REQUEST_T * request, 666 U32 frame_index 667 ) 668 { 669 SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request; 670 671 SCI_STATUS status = 672 scic_sds_stp_packet_request_command_phase_common_frame_handler( 673 request, frame_index); 674 675 if (status == SCI_SUCCESS) 676 { 677 // The command has completed with error status from target device. 678 status = scic_sds_stp_packet_request_process_status_fis( 679 request, &this_request->d2h_reg_fis); 680 681 if (status != SCI_SUCCESS) 682 { 683 scic_sds_request_set_status( 684 &this_request->parent, 685 SCU_TASK_DONE_CHECK_RESPONSE, 686 status 687 ); 688 } 689 else 690 scic_sds_request_set_status( 691 &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS 692 ); 693 } 694 695 return status; 696 } 697 698 699 /** 700 * @brief This method processes an unsolicited frame while the packet request is 701 * expecting TC completion. It will process the FIS and construct sense 702 * data. 703 * 704 * @param[in] this_request This parameter specifies the request for which 705 * the unsolicited frame was received. 706 * @param[in] frame_index This parameter indicates the unsolicited frame 707 * index that should contain the response. 708 * 709 * @return This method returns an indication of whether the UF 710 * frame was handled successfully or not. 711 * @retval SCI_SUCCESS Currently this value is always returned and indicates 712 * successful processing of the TC response. 713 * 714 */ 715 static 716 SCI_STATUS scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler( 717 SCIC_SDS_REQUEST_T * request, 718 U32 frame_index 719 ) 720 { 721 SCI_STATUS status = 722 scic_sds_stp_packet_request_command_phase_common_frame_handler( 723 request, frame_index); 724 725 SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request; 726 727 if (status == SCI_SUCCESS) 728 { 729 // The command has completed with error status from target device. 730 status = scic_sds_stp_packet_request_process_status_fis( 731 request, &this_request->d2h_reg_fis); 732 733 if (status != SCI_SUCCESS) 734 { 735 scic_sds_request_set_status( 736 request, 737 SCU_TASK_DONE_CHECK_RESPONSE, 738 status 739 ); 740 } 741 else 742 scic_sds_request_set_status( 743 request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 744 ); 745 746 //Always complete the NON_DATA command right away, no need to delay completion 747 //even an error status fis came from target device. 748 sci_base_state_machine_change_state( 749 &request->parent.state_machine, 750 SCI_BASE_REQUEST_STATE_COMPLETED 751 ); 752 } 753 754 return status; 755 } 756 757 static 758 SCI_STATUS scic_sds_stp_packet_request_started_completion_delay_complete_handler( 759 SCI_BASE_REQUEST_T *request 760 ) 761 { 762 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)request; 763 764 sci_base_state_machine_change_state( 765 &this_request->parent.state_machine, 766 SCI_BASE_REQUEST_STATE_COMPLETED 767 ); 768 769 return this_request->sci_status; 770 } 771 772 // --------------------------------------------------------------------------- 773 774 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T 775 scic_sds_stp_packet_request_started_substate_handler_table 776 [SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES] = 777 { 778 // SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE 779 { 780 { 781 scic_sds_request_default_start_handler, 782 scic_sds_request_started_state_abort_handler, 783 scic_sds_request_default_complete_handler, 784 scic_sds_request_default_destruct_handler 785 }, 786 scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler, 787 scic_sds_request_default_event_handler, 788 scic_sds_request_default_frame_handler 789 }, 790 // SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE 791 { 792 { 793 scic_sds_request_default_start_handler, 794 scic_sds_request_started_state_abort_handler, 795 scic_sds_request_default_complete_handler, 796 scic_sds_request_default_destruct_handler 797 }, 798 scic_sds_request_default_tc_completion_handler, 799 scic_sds_request_default_event_handler, 800 scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler 801 }, 802 // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE 803 { 804 { 805 scic_sds_request_default_start_handler, 806 scic_sds_request_started_state_abort_handler, 807 scic_sds_request_default_complete_handler, 808 scic_sds_request_default_destruct_handler 809 }, 810 scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler, 811 scic_sds_request_default_event_handler, 812 scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler 813 }, 814 // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE 815 { 816 { 817 scic_sds_request_default_start_handler, 818 scic_sds_request_started_state_abort_handler, 819 scic_sds_request_default_complete_handler, 820 scic_sds_request_default_destruct_handler 821 }, 822 scic_sds_request_default_tc_completion_handler, 823 scic_sds_request_default_event_handler, 824 scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler 825 }, 826 // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE 827 { 828 { 829 scic_sds_request_default_start_handler, 830 scic_sds_request_started_state_abort_handler, 831 scic_sds_stp_packet_request_started_completion_delay_complete_handler, 832 scic_sds_request_default_destruct_handler 833 }, 834 scic_sds_request_default_tc_completion_handler, 835 scic_sds_request_default_event_handler, 836 scic_sds_request_default_frame_handler 837 } 838 }; 839 840 /** 841 * @file 842 * 843 * @brief This file contains the Packet IO started substate machine 844 * for the SCIC_SDS_IO_REQUEST object. 845 */ 846 static 847 void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter( 848 SCI_BASE_OBJECT_T *object 849 ) 850 { 851 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 852 853 SET_STATE_HANDLER( 854 this_request, 855 scic_sds_stp_packet_request_started_substate_handler_table, 856 SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE 857 ); 858 859 scic_sds_remote_device_set_working_request( 860 this_request->target_device, this_request 861 ); 862 } 863 864 static 865 void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter( 866 SCI_BASE_OBJECT_T *object 867 ) 868 { 869 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 870 871 SET_STATE_HANDLER( 872 this_request, 873 scic_sds_stp_packet_request_started_substate_handler_table, 874 SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE 875 ); 876 } 877 878 static 879 void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter( 880 SCI_BASE_OBJECT_T *object 881 ) 882 { 883 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 884 U8 sat_packet_protocol = this_request->sat_protocol; 885 886 SCU_TASK_CONTEXT_T *task_context; 887 SCI_STATUS status; 888 889 // Recycle the TC and reconstruct it for sending out data fis containing 890 // CDB. 891 task_context = scic_sds_controller_get_task_context_buffer( 892 this_request->owning_controller, this_request->io_tag); 893 894 if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA) 895 scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( 896 this_request, task_context); 897 else 898 scu_stp_packet_request_command_phase_construct_task_context( 899 this_request, task_context); 900 901 // send the new TC out. 902 status = this_request->owning_controller->state_handlers->parent.continue_io_handler( 903 &this_request->owning_controller->parent, 904 &this_request->target_device->parent, 905 &this_request->parent 906 ); 907 908 if (status == SCI_SUCCESS) 909 SET_STATE_HANDLER( 910 this_request, 911 scic_sds_stp_packet_request_started_substate_handler_table, 912 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE 913 ); 914 } 915 916 static 917 void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter( 918 SCI_BASE_OBJECT_T *object 919 ) 920 { 921 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 922 923 SET_STATE_HANDLER( 924 this_request, 925 scic_sds_stp_packet_request_started_substate_handler_table, 926 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE 927 ); 928 } 929 930 static 931 void scic_sds_stp_packet_request_started_completion_delay_enter( 932 SCI_BASE_OBJECT_T *object 933 ) 934 { 935 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 936 937 SET_STATE_HANDLER( 938 this_request, 939 scic_sds_stp_packet_request_started_substate_handler_table, 940 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE 941 ); 942 } 943 944 945 // --------------------------------------------------------------------------- 946 SCI_BASE_STATE_T 947 scic_sds_stp_packet_request_started_substate_table 948 [SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES] = 949 { 950 { 951 SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE, 952 scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter, 953 NULL 954 }, 955 { 956 SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE, 957 scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter, 958 NULL 959 }, 960 { 961 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE, 962 scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter, 963 NULL 964 }, 965 { 966 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE, 967 scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter, 968 NULL 969 }, 970 { 971 SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE, 972 scic_sds_stp_packet_request_started_completion_delay_enter, 973 NULL 974 } 975 }; 976 977 #endif //#if !defined(DISABLE_ATAPI) 978 979