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