1 /*- 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of version 2 of the GNU General Public License as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21 * The full GNU General Public License is included in this distribution 22 * in the file called LICENSE.GPL. 23 * 24 * BSD LICENSE 25 * 26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * * Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * * Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 */ 52 53 #include <sys/cdefs.h> 54 __FBSDID("$FreeBSD$"); 55 56 /** 57 * @file 58 * 59 * @brief This file contains the implementation for the operations on an 60 * SCIC_SDS_IO_REQUEST object. 61 */ 62 63 #include <dev/isci/scil/intel_sat.h> 64 #include <dev/isci/scil/intel_sata.h> 65 #include <dev/isci/scil/intel_sas.h> 66 #include <dev/isci/scil/sci_util.h> 67 #include <dev/isci/scil/sci_base_request.h> 68 #include <dev/isci/scil/scic_controller.h> 69 #include <dev/isci/scil/scic_io_request.h> 70 #include <dev/isci/scil/scic_remote_device.h> 71 #include <dev/isci/scil/scic_user_callback.h> 72 #include <dev/isci/scil/scic_sds_logger.h> 73 #include <dev/isci/scil/scic_sds_request.h> 74 #include <dev/isci/scil/scic_sds_pci.h> 75 #include <dev/isci/scil/scic_sds_stp_request.h> 76 #include <dev/isci/scil/scic_sds_controller.h> 77 #include <dev/isci/scil/scic_sds_controller_registers.h> 78 #include <dev/isci/scil/scic_sds_remote_device.h> 79 #include <dev/isci/scil/scic_sds_port.h> 80 #include <dev/isci/scil/scic_task_request.h> 81 #include <dev/isci/scil/scu_constants.h> 82 #include <dev/isci/scil/scu_task_context.h> 83 #include <dev/isci/scil/scic_sds_smp_request.h> 84 #include <dev/isci/sci_environment.h> 85 #include <dev/isci/scil/scic_sds_unsolicited_frame_control.h> 86 #include <dev/isci/scil/sci_types.h> 87 #include <dev/isci/scil/scu_completion_codes.h> 88 #include <dev/isci/scil/intel_scsi.h> 89 90 #if !defined(DISABLE_ATAPI) 91 #include <dev/isci/scil/scic_sds_stp_packet_request.h> 92 #endif 93 94 /** 95 * @struct SCI_SINGLE_LEVEL_LUN 96 * 97 * @brief this struct describes the single level LUN structure 98 * as per the SAM 4. 99 */ 100 typedef struct SCI_SINGLE_LEVEL_LUN 101 { 102 U8 bus_id : 6; 103 U8 address_method : 2; 104 U8 lun_number; 105 U8 second_level_lun[2]; 106 U8 third_level_lun[2]; 107 U8 forth_level_lun[2]; 108 109 } SCI_SINGLE_LEVEL_LUN_T; 110 111 112 //**************************************************************************** 113 //* SCIC SDS IO REQUEST CONSTANTS 114 //**************************************************************************** 115 116 /** 117 * We have no timer requirements for IO requests right now 118 */ 119 #define SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT (0) 120 #define SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT (0) 121 122 //**************************************************************************** 123 //* SCIC SDS IO REQUEST MACROS 124 //**************************************************************************** 125 126 /** 127 * This is a helper macro to return the os handle for this request object. 128 */ 129 #define scic_sds_request_get_user_request(request) \ 130 ((request)->user_request) 131 132 133 /** 134 * This macro returns the sizeof memory required to store the an SSP IO 135 * request. This does not include the size of the SGL or SCU Task Context 136 * memory.The sizeof(U32) are needed for DWORD alignment of the command IU 137 * and response IU 138 */ 139 #define scic_ssp_io_request_get_object_size() \ 140 ( \ 141 sizeof(SCI_SSP_COMMAND_IU_T) \ 142 + sizeof (U32) \ 143 + sizeof(SCI_SSP_RESPONSE_IU_T) \ 144 + sizeof (U32) \ 145 ) 146 147 /** 148 * This macro returns the address of the ssp command buffer in the io 149 * request memory 150 */ 151 #define scic_sds_ssp_request_get_command_buffer_unaligned(memory) \ 152 ((SCI_SSP_COMMAND_IU_T *)( \ 153 ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) \ 154 )) 155 156 /** 157 * This macro aligns the ssp command buffer in DWORD alignment 158 */ 159 #define scic_sds_ssp_request_align_command_buffer(address) \ 160 ((SCI_SSP_COMMAND_IU_T *)( \ 161 (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \ 162 & ~(sizeof(U32)- 1) \ 163 )) 164 165 /** 166 * This macro returns the DWORD-aligned ssp command buffer 167 */ 168 #define scic_sds_ssp_request_get_command_buffer(memory) \ 169 ((SCI_SSP_COMMAND_IU_T *) \ 170 ((char *)scic_sds_ssp_request_align_command_buffer( \ 171 (char *) scic_sds_ssp_request_get_command_buffer_unaligned(memory) \ 172 ))) 173 174 /** 175 * This macro returns the address of the ssp response buffer in the io 176 * request memory 177 */ 178 #define scic_sds_ssp_request_get_response_buffer_unaligned(memory) \ 179 ((SCI_SSP_RESPONSE_IU_T *)( \ 180 ((char *)(scic_sds_ssp_request_get_command_buffer(memory))) \ 181 + sizeof(SCI_SSP_COMMAND_IU_T) \ 182 )) 183 184 /** 185 * This macro aligns the ssp response buffer in DWORD-aligned fashion 186 */ 187 #define scic_sds_ssp_request_align_response_buffer(memory) \ 188 ((SCI_SSP_RESPONSE_IU_T *)( \ 189 (((POINTER_UINT)(memory)) + (sizeof(U32) - 1)) \ 190 & ~(sizeof(U32)- 1) \ 191 )) 192 193 /** 194 * This macro returns the DWORD-aligned ssp response buffer 195 */ 196 #define scic_sds_ssp_request_get_response_buffer(memory) \ 197 ((SCI_SSP_RESPONSE_IU_T *) \ 198 ((char *)scic_sds_ssp_request_align_response_buffer ( \ 199 (char *)scic_sds_ssp_request_get_response_buffer_unaligned(memory) \ 200 ))) 201 202 /** 203 * This macro returns the address of the task context buffer in the io 204 * request memory 205 */ 206 #define scic_sds_ssp_request_get_task_context_buffer_unaligned(memory) \ 207 ((SCU_TASK_CONTEXT_T *)( \ 208 ((char *)(scic_sds_ssp_request_get_response_buffer(memory))) \ 209 + sizeof(SCI_SSP_RESPONSE_IU_T) \ 210 )) 211 212 /** 213 * This macro returns the aligned task context buffer 214 */ 215 #define scic_sds_ssp_request_get_task_context_buffer(memory) \ 216 ((SCU_TASK_CONTEXT_T *)( \ 217 ((char *)scic_sds_request_align_task_context_buffer( \ 218 (char *)scic_sds_ssp_request_get_task_context_buffer_unaligned(memory)) \ 219 ))) 220 221 /** 222 * This macro returns the address of the sgl elment pairs in the io request 223 * memory buffer 224 */ 225 #define scic_sds_ssp_request_get_sgl_element_buffer(memory) \ 226 ((SCU_SGL_ELEMENT_PAIR_T *)( \ 227 ((char *)(scic_sds_ssp_request_get_task_context_buffer(memory))) \ 228 + sizeof(SCU_TASK_CONTEXT_T) \ 229 )) 230 231 #if !defined(DISABLE_TASK_MANAGEMENT) 232 233 /** 234 * This macro returns the sizeof of memory required to store an SSP Task 235 * request. This does not include the size of the SCU Task Context memory. 236 */ 237 #define scic_ssp_task_request_get_object_size() \ 238 ( \ 239 sizeof(SCI_SSP_TASK_IU_T) \ 240 + sizeof(SCI_SSP_RESPONSE_IU_T) \ 241 ) 242 243 /** 244 * This macro returns the address of the ssp command buffer in the task 245 * request memory. Yes its the same as the above macro except for the 246 * name. 247 */ 248 #define scic_sds_ssp_task_request_get_command_buffer(memory) \ 249 ((SCI_SSP_TASK_IU_T *)( \ 250 ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) \ 251 )) 252 253 /** 254 * This macro returns the address of the ssp response buffer in the task 255 * request memory. 256 */ 257 #define scic_sds_ssp_task_request_get_response_buffer(memory) \ 258 ((SCI_SSP_RESPONSE_IU_T *)( \ 259 ((char *)(scic_sds_ssp_task_request_get_command_buffer(memory))) \ 260 + sizeof(SCI_SSP_TASK_IU_T) \ 261 )) 262 263 /** 264 * This macro returs the task context buffer for the SSP task request. 265 */ 266 #define scic_sds_ssp_task_request_get_task_context_buffer(memory) \ 267 ((SCU_TASK_CONTEXT_T *)( \ 268 ((char *)(scic_sds_ssp_task_request_get_response_buffer(memory))) \ 269 + sizeof(SCI_SSP_RESPONSE_IU_T) \ 270 )) 271 272 #endif // !defined(DISABLE_TASK_MANAGEMENT) 273 274 275 //**************************************************************************** 276 //* SCIC SDS IO REQUEST PRIVATE METHODS 277 //**************************************************************************** 278 279 #ifdef SCI_LOGGING 280 /** 281 * This method will initialize state transition logging for the task request 282 * object. 283 * 284 * @param[in] this_request This is the request for which to track state 285 * transitions. 286 */ 287 void scic_sds_request_initialize_state_logging( 288 SCIC_SDS_REQUEST_T *this_request 289 ) 290 { 291 sci_base_state_machine_logger_initialize( 292 &this_request->parent.state_machine_logger, 293 &this_request->parent.state_machine, 294 &this_request->parent.parent, 295 scic_cb_logger_log_states, 296 this_request->is_task_management_request ? 297 "SCIC_SDS_IO_REQUEST_T(Task)" : "SCIC_SDS_IO_REQUEST_T(IO)", 298 "base state machine", 299 SCIC_LOG_OBJECT_SMP_IO_REQUEST | 300 SCIC_LOG_OBJECT_STP_IO_REQUEST | 301 SCIC_LOG_OBJECT_SSP_IO_REQUEST 302 ); 303 304 if (this_request->has_started_substate_machine) 305 { 306 sci_base_state_machine_logger_initialize( 307 &this_request->started_substate_machine_logger, 308 &this_request->started_substate_machine, 309 &this_request->parent.parent, 310 scic_cb_logger_log_states, 311 "SCIC_SDS_IO_REQUEST_T(Task)", "starting substate machine", 312 SCIC_LOG_OBJECT_SMP_IO_REQUEST | 313 SCIC_LOG_OBJECT_STP_IO_REQUEST | 314 SCIC_LOG_OBJECT_SSP_IO_REQUEST 315 ); 316 } 317 } 318 319 /** 320 * This method will stop the state transition logging for the task request 321 * object. 322 * 323 * @param[in] this_request The task request object on which to stop state 324 * transition logging. 325 */ 326 void scic_sds_request_deinitialize_state_logging( 327 SCIC_SDS_REQUEST_T *this_request 328 ) 329 { 330 sci_base_state_machine_logger_deinitialize( 331 &this_request->parent.state_machine_logger, 332 &this_request->parent.state_machine 333 ); 334 335 if (this_request->has_started_substate_machine) 336 { 337 sci_base_state_machine_logger_deinitialize( 338 &this_request->started_substate_machine_logger, 339 &this_request->started_substate_machine 340 ); 341 } 342 } 343 #endif // SCI_LOGGING 344 345 /** 346 * This method returns the size required to store an SSP IO request object. 347 * 348 * @return U32 349 */ 350 static 351 U32 scic_sds_ssp_request_get_object_size(void) 352 { 353 return sizeof(SCIC_SDS_REQUEST_T) 354 + scic_ssp_io_request_get_object_size() 355 + sizeof(SCU_TASK_CONTEXT_T) 356 + CACHE_LINE_SIZE 357 + sizeof(SCU_SGL_ELEMENT_PAIR_T) * SCU_MAX_SGL_ELEMENT_PAIRS; 358 } 359 360 /** 361 * @brief This method returns the sgl element pair for the specificed 362 * sgl_pair index. 363 * 364 * @param[in] this_request This parameter specifies the IO request for which 365 * to retrieve the Scatter-Gather List element pair. 366 * @param[in] sgl_pair_index This parameter specifies the index into the SGL 367 * element pair to be retrieved. 368 * 369 * @return This method returns a pointer to an SCU_SGL_ELEMENT_PAIR. 370 */ 371 SCU_SGL_ELEMENT_PAIR_T *scic_sds_request_get_sgl_element_pair( 372 SCIC_SDS_REQUEST_T *this_request, 373 U32 sgl_pair_index 374 ) 375 { 376 SCU_TASK_CONTEXT_T *task_context; 377 378 task_context = (SCU_TASK_CONTEXT_T *)this_request->task_context_buffer; 379 380 if (sgl_pair_index == 0) 381 { 382 return &task_context->sgl_pair_ab; 383 } 384 else if (sgl_pair_index == 1) 385 { 386 return &task_context->sgl_pair_cd; 387 } 388 389 return &this_request->sgl_element_pair_buffer[sgl_pair_index - 2]; 390 } 391 392 /** 393 * @brief This function will build the SGL list for an IO request. 394 * 395 * @param[in] this_request This parameter specifies the IO request for which 396 * to build the Scatter-Gather List. 397 * 398 * @return none 399 */ 400 void scic_sds_request_build_sgl( 401 SCIC_SDS_REQUEST_T *this_request 402 ) 403 { 404 void *os_sge; 405 void *os_handle; 406 SCI_PHYSICAL_ADDRESS physical_address; 407 U32 sgl_pair_index = 0; 408 SCU_SGL_ELEMENT_PAIR_T *scu_sgl_list = NULL; 409 SCU_SGL_ELEMENT_PAIR_T *previous_pair = NULL; 410 411 os_handle = scic_sds_request_get_user_request(this_request); 412 scic_cb_io_request_get_next_sge(os_handle, NULL, &os_sge); 413 414 while (os_sge != NULL) 415 { 416 scu_sgl_list = 417 scic_sds_request_get_sgl_element_pair(this_request, sgl_pair_index); 418 419 SCU_SGL_COPY(os_handle, scu_sgl_list->A, os_sge); 420 421 scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge); 422 423 if (os_sge != NULL) 424 { 425 SCU_SGL_COPY(os_handle, scu_sgl_list->B, os_sge); 426 427 scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge); 428 } 429 else 430 { 431 SCU_SGL_ZERO(scu_sgl_list->B); 432 } 433 434 if (previous_pair != NULL) 435 { 436 scic_cb_io_request_get_physical_address( 437 scic_sds_request_get_controller(this_request), 438 this_request, 439 scu_sgl_list, 440 &physical_address 441 ); 442 443 previous_pair->next_pair_upper = 444 sci_cb_physical_address_upper(physical_address); 445 previous_pair->next_pair_lower = 446 sci_cb_physical_address_lower(physical_address); 447 } 448 449 previous_pair = scu_sgl_list; 450 sgl_pair_index++; 451 } 452 453 if (scu_sgl_list != NULL) 454 { 455 scu_sgl_list->next_pair_upper = 0; 456 scu_sgl_list->next_pair_lower = 0; 457 } 458 } 459 460 /** 461 * @brief This method initializes common portions of the io request object. 462 * This includes construction of the SCI_BASE_REQUEST_T parent. 463 * 464 * @param[in] the_controller This parameter specifies the controller for which 465 * the request is being constructed. 466 * @param[in] the_target This parameter specifies the remote device for which 467 * the request is being constructed. 468 * @param[in] io_tag This parameter specifies the IO tag to be utilized for 469 * this request. This parameter can be set to 470 * SCI_CONTROLLER_INVALID_IO_TAG. 471 * @param[in] user_io_request_object This parameter specifies the user 472 * request object for which the request is being constructed. 473 * @param[in] this_request This parameter specifies the request being 474 * constructed. 475 * 476 * @return none 477 */ 478 static 479 void scic_sds_general_request_construct( 480 SCIC_SDS_CONTROLLER_T * the_controller, 481 SCIC_SDS_REMOTE_DEVICE_T * the_target, 482 U16 io_tag, 483 void * user_io_request_object, 484 SCIC_SDS_REQUEST_T * this_request 485 ) 486 { 487 sci_base_request_construct( 488 &this_request->parent, 489 sci_base_object_get_logger(the_controller), 490 scic_sds_request_state_table 491 ); 492 493 this_request->io_tag = io_tag; 494 this_request->user_request = user_io_request_object; 495 this_request->owning_controller = the_controller; 496 this_request->target_device = the_target; 497 this_request->has_started_substate_machine = FALSE; 498 this_request->protocol = SCIC_NO_PROTOCOL; 499 this_request->sat_protocol = 0xFF; 500 this_request->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; 501 this_request->device_sequence = scic_sds_remote_device_get_sequence(the_target); 502 503 this_request->sci_status = SCI_SUCCESS; 504 this_request->scu_status = 0; 505 this_request->post_context = 0xFFFFFFFF; 506 507 this_request->is_task_management_request = FALSE; 508 509 if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) 510 { 511 this_request->was_tag_assigned_by_user = FALSE; 512 this_request->task_context_buffer = NULL; 513 } 514 else 515 { 516 this_request->was_tag_assigned_by_user = TRUE; 517 518 this_request->task_context_buffer = 519 scic_sds_controller_get_task_context_buffer( 520 this_request->owning_controller, io_tag); 521 } 522 } 523 524 /** 525 * @brief This method build the remainder of the IO request object. 526 * 527 * @pre The scic_sds_general_request_construct() must be called before this 528 * call is valid. 529 * 530 * @param[in] this_request This parameter specifies the request object being 531 * constructed. 532 * 533 * @return none 534 */ 535 void scic_sds_ssp_io_request_assign_buffers( 536 SCIC_SDS_REQUEST_T *this_request 537 ) 538 { 539 this_request->command_buffer = 540 scic_sds_ssp_request_get_command_buffer(this_request); 541 this_request->response_buffer = 542 scic_sds_ssp_request_get_response_buffer(this_request); 543 this_request->sgl_element_pair_buffer = 544 scic_sds_ssp_request_get_sgl_element_buffer(this_request); 545 this_request->sgl_element_pair_buffer = 546 scic_sds_request_align_sgl_element_buffer(this_request->sgl_element_pair_buffer); 547 548 if (this_request->was_tag_assigned_by_user == FALSE) 549 { 550 this_request->task_context_buffer = 551 scic_sds_ssp_request_get_task_context_buffer(this_request); 552 } 553 } 554 555 /** 556 * @brief This method constructs the SSP Command IU data for this io 557 * request object. 558 * 559 * @param[in] this_request This parameter specifies the request object for 560 * which the SSP command information unit is being built. 561 * 562 * @return none 563 */ 564 static 565 void scic_sds_io_request_build_ssp_command_iu( 566 SCIC_SDS_REQUEST_T *this_request 567 ) 568 { 569 SCI_SINGLE_LEVEL_LUN_T lun; 570 SCI_SSP_COMMAND_IU_T *command_frame; 571 void *os_handle; 572 U32 cdb_length; 573 U32 *cdb_buffer; 574 575 command_frame = 576 (SCI_SSP_COMMAND_IU_T *)this_request->command_buffer; 577 578 os_handle = scic_sds_request_get_user_request(this_request); 579 580 ((U32 *)&lun)[0] = 0; 581 ((U32 *)&lun)[1] = 0; 582 lun.lun_number = scic_cb_ssp_io_request_get_lun(os_handle) &0xff; 583 /// @todo Is it ok to leave junk at the end of the cdb buffer? 584 scic_word_copy_with_swap( 585 (U32 *)command_frame->lun, 586 (U32 *)&lun, 587 sizeof(lun)); 588 589 ((U32 *)command_frame)[2] = 0; 590 591 cdb_length = scic_cb_ssp_io_request_get_cdb_length(os_handle); 592 cdb_buffer = (U32 *)scic_cb_ssp_io_request_get_cdb_address(os_handle); 593 594 if (cdb_length > 16) 595 { 596 command_frame->additional_cdb_length = cdb_length - 16; 597 } 598 599 /// @todo Is it ok to leave junk at the end of the cdb buffer? 600 scic_word_copy_with_swap( 601 (U32 *)(&command_frame->cdb), 602 (U32 *)(cdb_buffer), 603 (cdb_length + 3) / sizeof(U32) 604 ); 605 606 command_frame->enable_first_burst = 0; 607 command_frame->task_priority = 608 scic_cb_ssp_io_request_get_command_priority(os_handle); 609 command_frame->task_attribute = 610 scic_cb_ssp_io_request_get_task_attribute(os_handle); 611 } 612 613 #if !defined(DISABLE_TASK_MANAGEMENT) 614 615 /** 616 * @brief This method constructs the SSP Task IU data for this io request 617 * object. 618 * 619 * @param[in] this_request 620 * 621 * @return none 622 */ 623 static 624 void scic_sds_task_request_build_ssp_task_iu( 625 SCIC_SDS_REQUEST_T *this_request 626 ) 627 { 628 SCI_SSP_TASK_IU_T *command_frame; 629 void *os_handle; 630 631 command_frame = 632 (SCI_SSP_TASK_IU_T *)this_request->command_buffer; 633 634 os_handle = scic_sds_request_get_user_request(this_request); 635 636 command_frame->lun_upper = 0; 637 command_frame->lun_lower = scic_cb_ssp_task_request_get_lun(os_handle); 638 639 ((U32 *)command_frame)[2] = 0; 640 641 command_frame->task_function = 642 scic_cb_ssp_task_request_get_function(os_handle); 643 command_frame->task_tag = 644 scic_cb_ssp_task_request_get_io_tag_to_manage(os_handle); 645 } 646 647 #endif // !defined(DISABLE_TASK_MANAGEMENT) 648 649 /** 650 * @brief This method is will fill in the SCU Task Context for any type of 651 * SSP request. 652 * 653 * @param[in] this_request 654 * @param[in] task_context 655 * 656 * @return none 657 */ 658 static 659 void scu_ssp_reqeust_construct_task_context( 660 SCIC_SDS_REQUEST_T * this_request, 661 SCU_TASK_CONTEXT_T * task_context 662 ) 663 { 664 SCI_PHYSICAL_ADDRESS physical_address; 665 SCIC_SDS_CONTROLLER_T *owning_controller; 666 SCIC_SDS_REMOTE_DEVICE_T *target_device; 667 SCIC_SDS_PORT_T *target_port; 668 669 owning_controller = scic_sds_request_get_controller(this_request); 670 target_device = scic_sds_request_get_device(this_request); 671 target_port = scic_sds_request_get_port(this_request); 672 673 // Fill in the TC with the its required data 674 task_context->abort = 0; 675 task_context->priority = 0; 676 task_context->initiator_request = 1; 677 task_context->connection_rate = 678 scic_remote_device_get_connection_rate(target_device); 679 task_context->protocol_engine_index = 680 scic_sds_controller_get_protocol_engine_group(owning_controller); 681 task_context->logical_port_index = 682 scic_sds_port_get_index(target_port); 683 task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; 684 task_context->valid = SCU_TASK_CONTEXT_VALID; 685 task_context->context_type = SCU_TASK_CONTEXT_TYPE; 686 687 task_context->remote_node_index = 688 scic_sds_remote_device_get_index(this_request->target_device); 689 task_context->command_code = 0; 690 691 task_context->link_layer_control = 0; 692 task_context->do_not_dma_ssp_good_response = 1; 693 task_context->strict_ordering = 0; 694 task_context->control_frame = 0; 695 task_context->timeout_enable = 0; 696 task_context->block_guard_enable = 0; 697 698 task_context->address_modifier = 0; 699 700 //task_context->type.ssp.tag = this_request->io_tag; 701 task_context->task_phase = 0x01; 702 703 if (this_request->was_tag_assigned_by_user) 704 { 705 // Build the task context now since we have already read the data 706 this_request->post_context = ( 707 SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC 708 | ( 709 scic_sds_controller_get_protocol_engine_group(owning_controller) 710 << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 711 ) 712 | ( 713 scic_sds_port_get_index(target_port) 714 << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 715 ) 716 | scic_sds_io_tag_get_index(this_request->io_tag) 717 ); 718 } 719 else 720 { 721 // Build the task context now since we have already read the data 722 this_request->post_context = ( 723 SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC 724 | ( 725 scic_sds_controller_get_protocol_engine_group(owning_controller) 726 << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 727 ) 728 | ( 729 scic_sds_port_get_index(target_port) 730 << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 731 ) 732 // This is not assigned because we have to wait until we get a TCi 733 ); 734 } 735 736 // Copy the physical address for the command buffer to the SCU Task Context 737 scic_cb_io_request_get_physical_address( 738 scic_sds_request_get_controller(this_request), 739 this_request, 740 this_request->command_buffer, 741 &physical_address 742 ); 743 744 task_context->command_iu_upper = 745 sci_cb_physical_address_upper(physical_address); 746 task_context->command_iu_lower = 747 sci_cb_physical_address_lower(physical_address); 748 749 // Copy the physical address for the response buffer to the SCU Task Context 750 scic_cb_io_request_get_physical_address( 751 scic_sds_request_get_controller(this_request), 752 this_request, 753 this_request->response_buffer, 754 &physical_address 755 ); 756 757 task_context->response_iu_upper = 758 sci_cb_physical_address_upper(physical_address); 759 task_context->response_iu_lower = 760 sci_cb_physical_address_lower(physical_address); 761 } 762 763 /** 764 * @brief This method is will fill in the SCU Task Context for a SSP IO 765 * request. 766 * 767 * @param[in] this_request 768 * 769 * @return none 770 */ 771 static 772 void scu_ssp_io_request_construct_task_context( 773 SCIC_SDS_REQUEST_T *this_request, 774 SCI_IO_REQUEST_DATA_DIRECTION data_direction, 775 U32 transfer_length_bytes 776 ) 777 { 778 SCU_TASK_CONTEXT_T *task_context; 779 780 task_context = scic_sds_request_get_task_context(this_request); 781 782 scu_ssp_reqeust_construct_task_context(this_request, task_context); 783 784 task_context->ssp_command_iu_length = sizeof(SCI_SSP_COMMAND_IU_T) / sizeof(U32); 785 task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME; 786 787 switch (data_direction) 788 { 789 case SCI_IO_REQUEST_DATA_IN: 790 case SCI_IO_REQUEST_NO_DATA: 791 task_context->task_type = SCU_TASK_TYPE_IOREAD; 792 break; 793 case SCI_IO_REQUEST_DATA_OUT: 794 task_context->task_type = SCU_TASK_TYPE_IOWRITE; 795 break; 796 } 797 798 task_context->transfer_length_bytes = transfer_length_bytes; 799 800 if (task_context->transfer_length_bytes > 0) 801 { 802 scic_sds_request_build_sgl(this_request); 803 } 804 } 805 806 #if !defined(DISABLE_TASK_MANAGEMENT) 807 808 /** 809 * @brief This method will fill in the remainder of the io request object 810 * for SSP Task requests. 811 * 812 * @param[in] this_request 813 * 814 * @return none 815 */ 816 void scic_sds_ssp_task_request_assign_buffers( 817 SCIC_SDS_REQUEST_T *this_request 818 ) 819 { 820 // Assign all of the buffer pointers 821 this_request->command_buffer = 822 scic_sds_ssp_task_request_get_command_buffer(this_request); 823 this_request->response_buffer = 824 scic_sds_ssp_task_request_get_response_buffer(this_request); 825 this_request->sgl_element_pair_buffer = NULL; 826 827 if (this_request->was_tag_assigned_by_user == FALSE) 828 { 829 this_request->task_context_buffer = 830 scic_sds_ssp_task_request_get_task_context_buffer(this_request); 831 this_request->task_context_buffer = 832 scic_sds_request_align_task_context_buffer(this_request->task_context_buffer); 833 } 834 } 835 836 /** 837 * @brief This method will fill in the SCU Task Context for a SSP Task 838 * request. The following important settings are utilized: 839 * -# priority == SCU_TASK_PRIORITY_HIGH. This ensures that the 840 * task request is issued ahead of other task destined for the 841 * same Remote Node. 842 * -# task_type == SCU_TASK_TYPE_IOREAD. This simply indicates 843 * that a normal request type (i.e. non-raw frame) is being 844 * utilized to perform task management. 845 * -# control_frame == 1. This ensures that the proper endianness 846 * is set so that the bytes are transmitted in the right order 847 * for a task frame. 848 * 849 * @param[in] this_request This parameter specifies the task request object 850 * being constructed. 851 * 852 * @return none 853 */ 854 static 855 void scu_ssp_task_request_construct_task_context( 856 SCIC_SDS_REQUEST_T *this_request 857 ) 858 { 859 SCU_TASK_CONTEXT_T *task_context; 860 861 task_context = scic_sds_request_get_task_context(this_request); 862 863 scu_ssp_reqeust_construct_task_context(this_request, task_context); 864 865 task_context->control_frame = 1; 866 task_context->priority = SCU_TASK_PRIORITY_HIGH; 867 task_context->task_type = SCU_TASK_TYPE_RAW_FRAME; 868 task_context->transfer_length_bytes = 0; 869 task_context->type.ssp.frame_type = SCI_SAS_TASK_FRAME; 870 task_context->ssp_command_iu_length = sizeof(SCI_SSP_TASK_IU_T) / sizeof(U32); 871 } 872 873 #endif // !defined(DISABLE_TASK_MANAGEMENT) 874 875 #if !defined(DISABLE_PASS_THROUGH) 876 /** 877 * @brief This method constructs the SSP Command IU data for this 878 * ssp passthrough comand request object. 879 * 880 * @param[in] this_request This parameter specifies the request object for 881 * which the SSP command information unit is being built. 882 * 883 * @return SCI_STATUS, returns invalid parameter is cdb > 16 884 */ 885 static 886 SCI_STATUS scic_sds_io_request_build_ssp_command_iu_pass_through( 887 SCIC_SDS_REQUEST_T *this_request, 888 SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS_T *ssp_passthru_cb 889 ) 890 { 891 SCI_SSP_COMMAND_IU_T *command_frame; 892 U32 cdb_length = 0, additional_cdb_length = 0; 893 U8 *cdb_buffer, *additional_cdb_buffer; 894 U8 *scsi_lun; 895 SCI_STATUS sci_status = SCI_SUCCESS; 896 SCI_SINGLE_LEVEL_LUN_T lun; 897 898 command_frame = 899 (SCI_SSP_COMMAND_IU_T *)this_request->command_buffer; 900 901 //get the lun 902 ssp_passthru_cb->scic_cb_ssp_passthru_get_lun ( 903 this_request, 904 &scsi_lun 905 ); 906 memset(&lun, 0, sizeof(lun)); 907 lun.lun_number = *scsi_lun; 908 scic_word_copy_with_swap( 909 (U32 *)command_frame->lun, 910 (U32 *)&lun, 911 sizeof(lun)); 912 913 ((U32 *)command_frame)[2] = 0; 914 915 ssp_passthru_cb->scic_cb_ssp_passthru_get_cdb( 916 this_request, 917 &cdb_length, 918 &cdb_buffer, 919 &additional_cdb_length, 920 &additional_cdb_buffer 921 ); 922 923 command_frame->additional_cdb_length = additional_cdb_length; 924 925 // ----------- TODO 926 ///todo: what to do with additional cdb length and buffer as the current command buffer is 927 // 16 bytes in intel_sas.h 928 // ??? see the SAS command IU 929 if (additional_cdb_length > 0) 930 { 931 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 932 } 933 934 /// @todo Is it ok to leave junk at the end of the cdb buffer? 935 scic_word_copy_with_swap( 936 (U32 *)(&command_frame->cdb), 937 (U32 *)(cdb_buffer), 938 (cdb_length + 3) / sizeof(U32) 939 ); 940 941 /////-------- End fo TODO 942 943 command_frame->enable_first_burst = 0; 944 command_frame->task_priority = 0; //todo: check with Richard ???? 945 946 //get the task attribute 947 command_frame->task_attribute = ssp_passthru_cb->scic_cb_ssp_passthru_get_task_attribute ( 948 this_request 949 ); 950 951 return sci_status; 952 } 953 #endif // !defined(DISABLE_PASS_THROUGH) 954 955 //**************************************************************************** 956 //* SCIC Interface Implementation 957 //**************************************************************************** 958 959 #if !defined(DISABLE_TASK_MANAGEMENT) 960 /** 961 * This method returns the size required to store an SSP task request object. 962 * 963 * @return U32 964 */ 965 static 966 U32 scic_sds_ssp_task_request_get_object_size(void) 967 { 968 return sizeof(SCIC_SDS_REQUEST_T) 969 + scic_ssp_task_request_get_object_size() 970 + sizeof(SCU_TASK_CONTEXT_T) 971 + CACHE_LINE_SIZE; 972 } 973 974 975 U32 scic_task_request_get_object_size(void) 976 { 977 U32 ssp_task_request_size; 978 U32 stp_task_request_size; 979 980 ssp_task_request_size = scic_sds_ssp_task_request_get_object_size(); 981 stp_task_request_size = scic_sds_stp_task_request_get_object_size(); 982 983 return MAX(ssp_task_request_size, stp_task_request_size); 984 } 985 986 #endif // !defined(DISABLE_TASK_MANAGEMENT) 987 988 // --------------------------------------------------------------------------- 989 990 U32 scic_io_request_get_object_size(void) 991 { 992 U32 ssp_request_size; 993 U32 stp_request_size; 994 U32 smp_request_size; 995 996 ssp_request_size = scic_sds_ssp_request_get_object_size(); 997 stp_request_size = scic_sds_stp_request_get_object_size(); 998 smp_request_size = scic_sds_smp_request_get_object_size(); 999 1000 return MAX(ssp_request_size, MAX(stp_request_size, smp_request_size)); 1001 } 1002 1003 // --------------------------------------------------------------------------- 1004 1005 SCIC_TRANSPORT_PROTOCOL scic_io_request_get_protocol( 1006 SCI_IO_REQUEST_HANDLE_T scic_io_request 1007 ) 1008 { 1009 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T * )scic_io_request; 1010 return this_request->protocol; 1011 } 1012 1013 // --------------------------------------------------------------------------- 1014 1015 U32 scic_sds_request_get_min_timer_count(void) 1016 { 1017 return SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT; 1018 } 1019 1020 // --------------------------------------------------------------------------- 1021 1022 U32 scic_sds_request_get_max_timer_count(void) 1023 { 1024 return SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT; 1025 } 1026 1027 // --------------------------------------------------------------------------- 1028 1029 SCI_STATUS scic_io_request_construct( 1030 SCI_CONTROLLER_HANDLE_T scic_controller, 1031 SCI_REMOTE_DEVICE_HANDLE_T scic_remote_device, 1032 U16 io_tag, 1033 void * user_io_request_object, 1034 void * scic_io_request_memory, 1035 SCI_IO_REQUEST_HANDLE_T * new_scic_io_request_handle 1036 ) 1037 { 1038 SCI_STATUS status = SCI_SUCCESS; 1039 SCIC_SDS_REQUEST_T * this_request; 1040 SMP_DISCOVER_RESPONSE_PROTOCOLS_T device_protocol; 1041 1042 this_request = (SCIC_SDS_REQUEST_T * )scic_io_request_memory; 1043 1044 SCIC_LOG_TRACE(( 1045 sci_base_object_get_logger(scic_controller), 1046 (SCIC_LOG_OBJECT_SSP_IO_REQUEST 1047 |SCIC_LOG_OBJECT_SMP_IO_REQUEST 1048 |SCIC_LOG_OBJECT_STP_IO_REQUEST), 1049 "scic_io_request_construct(0x%x, 0x%x, 0x02x, 0x%x, 0x%x, 0x%x) enter\n", 1050 scic_controller, scic_remote_device, 1051 io_tag, user_io_request_object, 1052 this_request, new_scic_io_request_handle 1053 )); 1054 1055 // Build the common part of the request 1056 scic_sds_general_request_construct( 1057 (SCIC_SDS_CONTROLLER_T *)scic_controller, 1058 (SCIC_SDS_REMOTE_DEVICE_T *)scic_remote_device, 1059 io_tag, 1060 user_io_request_object, 1061 this_request 1062 ); 1063 1064 if ( 1065 scic_sds_remote_device_get_index((SCIC_SDS_REMOTE_DEVICE_T *)scic_remote_device) 1066 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 1067 ) 1068 { 1069 return SCI_FAILURE_INVALID_REMOTE_DEVICE; 1070 } 1071 1072 scic_remote_device_get_protocols(scic_remote_device, &device_protocol); 1073 1074 if (device_protocol.u.bits.attached_ssp_target) 1075 { 1076 scic_sds_ssp_io_request_assign_buffers(this_request); 1077 } 1078 else if (device_protocol.u.bits.attached_stp_target) 1079 { 1080 scic_sds_stp_request_assign_buffers(this_request); 1081 memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T)); 1082 } 1083 else if (device_protocol.u.bits.attached_smp_target) 1084 { 1085 scic_sds_smp_request_assign_buffers(this_request); 1086 memset(this_request->command_buffer, 0, sizeof(SMP_REQUEST_T)); 1087 } 1088 else 1089 { 1090 status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; 1091 } 1092 1093 if (status == SCI_SUCCESS) 1094 { 1095 memset( 1096 this_request->task_context_buffer, 1097 0, 1098 SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, sgl_pair_ab) 1099 ); 1100 *new_scic_io_request_handle = scic_io_request_memory; 1101 } 1102 1103 return status; 1104 } 1105 1106 // --------------------------------------------------------------------------- 1107 1108 #if !defined(DISABLE_TASK_MANAGEMENT) 1109 1110 SCI_STATUS scic_task_request_construct( 1111 SCI_CONTROLLER_HANDLE_T controller, 1112 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 1113 U16 io_tag, 1114 void *user_io_request_object, 1115 void *scic_task_request_memory, 1116 SCI_TASK_REQUEST_HANDLE_T *new_scic_task_request_handle 1117 ) 1118 { 1119 SCI_STATUS status = SCI_SUCCESS; 1120 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *) 1121 scic_task_request_memory; 1122 SMP_DISCOVER_RESPONSE_PROTOCOLS_T device_protocol; 1123 1124 SCIC_LOG_TRACE(( 1125 sci_base_object_get_logger(controller), 1126 (SCIC_LOG_OBJECT_SSP_IO_REQUEST 1127 |SCIC_LOG_OBJECT_SMP_IO_REQUEST 1128 |SCIC_LOG_OBJECT_STP_IO_REQUEST), 1129 "scic_task_request_construct(0x%x, 0x%x, 0x02x, 0x%x, 0x%x, 0x%x) enter\n", 1130 controller, remote_device, 1131 io_tag, user_io_request_object, 1132 scic_task_request_memory, new_scic_task_request_handle 1133 )); 1134 1135 // Build the common part of the request 1136 scic_sds_general_request_construct( 1137 (SCIC_SDS_CONTROLLER_T *)controller, 1138 (SCIC_SDS_REMOTE_DEVICE_T *)remote_device, 1139 io_tag, 1140 user_io_request_object, 1141 this_request 1142 ); 1143 1144 scic_remote_device_get_protocols(remote_device, &device_protocol); 1145 1146 if (device_protocol.u.bits.attached_ssp_target) 1147 { 1148 scic_sds_ssp_task_request_assign_buffers(this_request); 1149 1150 this_request->has_started_substate_machine = TRUE; 1151 1152 // Construct the started sub-state machine. 1153 sci_base_state_machine_construct( 1154 &this_request->started_substate_machine, 1155 &this_request->parent.parent, 1156 scic_sds_io_request_started_task_mgmt_substate_table, 1157 SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION 1158 ); 1159 } 1160 else if (device_protocol.u.bits.attached_stp_target) 1161 { 1162 scic_sds_stp_request_assign_buffers(this_request); 1163 } 1164 else 1165 { 1166 status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; 1167 } 1168 1169 if (status == SCI_SUCCESS) 1170 { 1171 this_request->is_task_management_request = TRUE; 1172 memset(this_request->task_context_buffer, 0x00, sizeof(SCU_TASK_CONTEXT_T)); 1173 *new_scic_task_request_handle = scic_task_request_memory; 1174 } 1175 1176 return status; 1177 } 1178 1179 #endif // !defined(DISABLE_TASK_MANAGEMENT) 1180 1181 // --------------------------------------------------------------------------- 1182 1183 SCI_STATUS scic_io_request_construct_basic_ssp( 1184 SCI_IO_REQUEST_HANDLE_T scic_io_request 1185 ) 1186 { 1187 void *os_handle; 1188 SCIC_SDS_REQUEST_T *this_request; 1189 this_request = (SCIC_SDS_REQUEST_T *)scic_io_request; 1190 1191 SCIC_LOG_TRACE(( 1192 sci_base_object_get_logger(this_request), 1193 SCIC_LOG_OBJECT_SSP_IO_REQUEST, 1194 "scic_io_request_construct_basic_ssp(0x%x) enter\n", 1195 this_request 1196 )); 1197 1198 this_request->protocol = SCIC_SSP_PROTOCOL; 1199 1200 os_handle = scic_sds_request_get_user_request(this_request); 1201 1202 scu_ssp_io_request_construct_task_context( 1203 this_request, 1204 scic_cb_io_request_get_data_direction(os_handle), 1205 scic_cb_io_request_get_transfer_length(os_handle) 1206 ); 1207 1208 1209 scic_sds_io_request_build_ssp_command_iu(this_request); 1210 1211 scic_sds_request_initialize_state_logging(this_request); 1212 1213 sci_base_state_machine_change_state( 1214 &this_request->parent.state_machine, 1215 SCI_BASE_REQUEST_STATE_CONSTRUCTED 1216 ); 1217 1218 return SCI_SUCCESS; 1219 } 1220 1221 // --------------------------------------------------------------------------- 1222 1223 #if !defined(DISABLE_TASK_MANAGEMENT) 1224 1225 SCI_STATUS scic_task_request_construct_ssp( 1226 SCI_TASK_REQUEST_HANDLE_T scic_task_request 1227 ) 1228 { 1229 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *) 1230 scic_task_request; 1231 1232 SCIC_LOG_TRACE(( 1233 sci_base_object_get_logger(this_request), 1234 SCIC_LOG_OBJECT_SSP_IO_REQUEST, 1235 "scic_task_request_construct_ssp(0x%x) enter\n", 1236 this_request 1237 )); 1238 1239 // Construct the SSP Task SCU Task Context 1240 scu_ssp_task_request_construct_task_context(this_request); 1241 1242 // Fill in the SSP Task IU 1243 scic_sds_task_request_build_ssp_task_iu(this_request); 1244 1245 scic_sds_request_initialize_state_logging(this_request); 1246 1247 sci_base_state_machine_change_state( 1248 &this_request->parent.state_machine, 1249 SCI_BASE_REQUEST_STATE_CONSTRUCTED 1250 ); 1251 1252 return SCI_SUCCESS; 1253 } 1254 1255 #endif // !defined(DISABLE_TASK_MANAGEMENT) 1256 1257 // --------------------------------------------------------------------------- 1258 1259 SCI_STATUS scic_io_request_construct_advanced_ssp( 1260 SCI_IO_REQUEST_HANDLE_T scic_io_request, 1261 SCIC_IO_SSP_PARAMETERS_T * io_parameters 1262 ) 1263 { 1264 SCIC_LOG_TRACE(( 1265 sci_base_object_get_logger(scic_io_request), 1266 SCIC_LOG_OBJECT_SSP_IO_REQUEST, 1267 "scic_io_request_construct_advanced_ssp(0x%x, 0x%x) enter\n", 1268 io_parameters, scic_io_request 1269 )); 1270 1271 /// @todo Implement after 1.1 1272 return SCI_FAILURE; 1273 } 1274 1275 // --------------------------------------------------------------------------- 1276 1277 #if !defined(DISABLE_PASS_THROUGH) 1278 SCI_STATUS scic_io_request_construct_ssp_pass_through ( 1279 void * scic_io_request, 1280 SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS_T *ssp_passthru_cb 1281 ) 1282 { 1283 SCI_STATUS status = SCI_SUCCESS; 1284 SCIC_SDS_REQUEST_T * this_request; 1285 1286 this_request = (SCIC_SDS_REQUEST_T * )scic_io_request; 1287 1288 SCIC_LOG_TRACE(( 1289 sci_base_object_get_logger(scic_io_request), 1290 SCIC_LOG_OBJECT_STP_IO_REQUEST, 1291 "scic_io_request_construct_ssp_pass_through(0x%x) enter\n", 1292 scic_io_request 1293 )); 1294 1295 //build the task context from the pass through buffer 1296 scu_ssp_io_request_construct_task_context( 1297 this_request, 1298 ssp_passthru_cb->common_callbacks.scic_cb_passthru_get_data_direction (this_request), 1299 ssp_passthru_cb->common_callbacks.scic_cb_passthru_get_transfer_length(this_request) 1300 ); 1301 1302 //build the ssp command iu from the pass through buffer 1303 status = scic_sds_io_request_build_ssp_command_iu_pass_through ( 1304 this_request, 1305 ssp_passthru_cb 1306 ); 1307 if (status != SCI_SUCCESS) 1308 { 1309 return status; 1310 } 1311 1312 /* initialize the logging */ 1313 scic_sds_request_initialize_state_logging(this_request); 1314 1315 sci_base_state_machine_change_state( 1316 &this_request->parent.state_machine, 1317 SCI_BASE_REQUEST_STATE_CONSTRUCTED 1318 ); 1319 1320 return status; 1321 } 1322 #endif // !defined(DISABLE_PASS_THROUGH) 1323 1324 // --------------------------------------------------------------------------- 1325 1326 #if !defined(DISABLE_TASK_MANAGEMENT) 1327 1328 SCI_STATUS scic_task_request_construct_sata( 1329 SCI_TASK_REQUEST_HANDLE_T scic_task_request 1330 ) 1331 { 1332 SCI_STATUS status; 1333 SCIC_SDS_REQUEST_T * this_request; 1334 U8 sat_protocol; 1335 1336 this_request = (SCIC_SDS_REQUEST_T *)scic_task_request; 1337 1338 SCIC_LOG_TRACE(( 1339 sci_base_object_get_logger(this_request), 1340 SCIC_LOG_OBJECT_STP_IO_REQUEST, 1341 "scic_task_request_construct_sata(0x%x) enter\n", 1342 this_request 1343 )); 1344 1345 sat_protocol = 1346 scic_cb_request_get_sat_protocol(this_request->user_request); 1347 1348 this_request->sat_protocol = sat_protocol; 1349 1350 switch (sat_protocol) 1351 { 1352 case SAT_PROTOCOL_ATA_HARD_RESET: 1353 case SAT_PROTOCOL_SOFT_RESET: 1354 status = scic_sds_stp_soft_reset_request_construct(this_request); 1355 break; 1356 1357 case SAT_PROTOCOL_PIO_DATA_IN: 1358 status = scic_sds_stp_pio_request_construct(this_request, sat_protocol, FALSE); 1359 break; 1360 1361 default: 1362 SCIC_LOG_ERROR(( 1363 sci_base_object_get_logger(this_request), 1364 SCIC_LOG_OBJECT_STP_IO_REQUEST, 1365 "SCIC IO Request 0x%x received un-handled SAT Protocl %d.\n", 1366 this_request, sat_protocol 1367 )); 1368 1369 status = SCI_FAILURE; 1370 break; 1371 } 1372 1373 if (status == SCI_SUCCESS) 1374 { 1375 scic_sds_request_initialize_state_logging(this_request); 1376 1377 sci_base_state_machine_change_state( 1378 &this_request->parent.state_machine, 1379 SCI_BASE_REQUEST_STATE_CONSTRUCTED 1380 ); 1381 } 1382 1383 return status; 1384 } 1385 1386 #endif // !defined(DISABLE_TASK_MANAGEMENT) 1387 1388 // --------------------------------------------------------------------------- 1389 1390 #if !defined(DISABLE_PASS_THROUGH) 1391 SCI_STATUS scic_io_request_construct_sata_pass_through( 1392 SCI_IO_REQUEST_HANDLE_T scic_io_request, 1393 SCIC_STP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb 1394 ) 1395 { 1396 SCI_STATUS status = SCI_SUCCESS; 1397 SCIC_SDS_REQUEST_T * this_request; 1398 U8 sat_protocol; 1399 U8 * reg_fis; 1400 U32 transfer_length; 1401 SCI_IO_REQUEST_DATA_DIRECTION data_direction; 1402 1403 this_request = (SCIC_SDS_REQUEST_T * )scic_io_request; 1404 1405 SCIC_LOG_TRACE(( 1406 sci_base_object_get_logger(scic_io_request), 1407 SCIC_LOG_OBJECT_STP_IO_REQUEST, 1408 "scic_io_request_construct_sata_pass_through(0x%x) enter\n", 1409 scic_io_request 1410 )); 1411 1412 passthru_cb->scic_cb_stp_passthru_get_register_fis(this_request, ®_fis); 1413 1414 if (reg_fis == NULL) 1415 { 1416 status = SCI_FAILURE_INVALID_PARAMETER_VALUE; 1417 } 1418 1419 if (status == SCI_SUCCESS) 1420 { 1421 //copy the H2D Reg fis blindly from the request to the SCU command buffer 1422 memcpy ((U8 *)this_request->command_buffer, (U8 *)reg_fis, sizeof(SATA_FIS_REG_H2D_T)); 1423 1424 //continue to create the request 1425 sat_protocol = passthru_cb->scic_cb_stp_passthru_get_protocol(this_request); 1426 transfer_length = passthru_cb->common_callbacks.scic_cb_passthru_get_transfer_length(this_request); 1427 data_direction = passthru_cb->common_callbacks.scic_cb_passthru_get_data_direction(this_request); 1428 1429 status = scic_sds_io_request_construct_sata( 1430 this_request, 1431 sat_protocol, 1432 transfer_length, 1433 data_direction, 1434 TRUE, 1435 TRUE 1436 ); 1437 1438 this_request->protocol = SCIC_STP_PROTOCOL; 1439 } 1440 1441 return status; 1442 } 1443 #endif // !defined(DISABLE_PASS_THROUGH) 1444 1445 // --------------------------------------------------------------------------- 1446 1447 U16 scic_io_request_get_io_tag( 1448 SCI_IO_REQUEST_HANDLE_T scic_io_request 1449 ) 1450 { 1451 SCIC_SDS_REQUEST_T *this_request; 1452 this_request = (SCIC_SDS_REQUEST_T *)scic_io_request; 1453 1454 SCIC_LOG_TRACE(( 1455 sci_base_object_get_logger(scic_io_request), 1456 SCIC_LOG_OBJECT_SMP_IO_REQUEST, 1457 "scic_io_request_get_io_tag(0x%x) enter\n", 1458 scic_io_request 1459 )); 1460 1461 return this_request->io_tag; 1462 } 1463 1464 // --------------------------------------------------------------------------- 1465 1466 U32 scic_request_get_controller_status( 1467 SCI_IO_REQUEST_HANDLE_T io_request 1468 ) 1469 { 1470 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T*)io_request; 1471 return this_request->scu_status; 1472 } 1473 1474 U32 scic_request_get_sci_status( 1475 SCI_IO_REQUEST_HANDLE_T io_request 1476 ) 1477 { 1478 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T*)io_request; 1479 return this_request->sci_status; 1480 } 1481 1482 // --------------------------------------------------------------------------- 1483 1484 void * scic_io_request_get_rx_frame( 1485 SCI_IO_REQUEST_HANDLE_T scic_io_request, 1486 U32 offset 1487 ) 1488 { 1489 void * frame_buffer = NULL; 1490 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request; 1491 1492 ASSERT(offset < SCU_UNSOLICITED_FRAME_BUFFER_SIZE); 1493 1494 if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) 1495 { 1496 scic_sds_unsolicited_frame_control_get_buffer( 1497 &(this_request->owning_controller->uf_control), 1498 this_request->saved_rx_frame_index, 1499 &frame_buffer 1500 ); 1501 } 1502 1503 return frame_buffer; 1504 } 1505 1506 void * scic_io_request_get_command_iu_address( 1507 SCI_IO_REQUEST_HANDLE_T scic_io_request 1508 ) 1509 { 1510 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request; 1511 1512 return this_request->command_buffer; 1513 } 1514 1515 // --------------------------------------------------------------------------- 1516 1517 void * scic_io_request_get_response_iu_address( 1518 SCI_IO_REQUEST_HANDLE_T scic_io_request 1519 ) 1520 { 1521 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request; 1522 1523 return this_request->response_buffer; 1524 } 1525 1526 // --------------------------------------------------------------------------- 1527 #define SCU_TASK_CONTEXT_SRAM 0x200000 1528 U32 scic_io_request_get_number_of_bytes_transferred ( 1529 SCI_IO_REQUEST_HANDLE_T scic_io_request 1530 ) 1531 { 1532 U32 ret_val = 0; 1533 SCIC_SDS_REQUEST_T * scic_sds_request; 1534 1535 scic_sds_request = (SCIC_SDS_REQUEST_T *) scic_io_request; 1536 1537 if ( SMU_AMR_READ (scic_sds_request->owning_controller) == 0) 1538 { 1539 //get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where 1540 // BAR1 is the scu_registers 1541 // 0x20002C = 0x200000 + 0x2c 1542 // = start of task context SRAM + offset of (type.ssp.data_offset) 1543 // TCi is the io_tag of SCIC_SDS_REQUEST 1544 ret_val = scic_sds_pci_read_scu_dword( 1545 scic_sds_request->owning_controller, 1546 ( 1547 (U8 *) scic_sds_request->owning_controller->scu_registers + 1548 ( SCU_TASK_CONTEXT_SRAM + SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, type.ssp.data_offset) ) + 1549 ( ( sizeof (SCU_TASK_CONTEXT_T) ) * scic_sds_io_tag_get_index (scic_sds_request->io_tag)) 1550 ) 1551 ); 1552 } 1553 1554 return ret_val; 1555 } 1556 1557 //**************************************************************************** 1558 //* SCIC SDS Interface Implementation 1559 //**************************************************************************** 1560 1561 /** 1562 * This method invokes the base state start request handler for the 1563 * SCIC_SDS_IO_REQUEST_T object. 1564 * 1565 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the 1566 * start operation is to be executed. 1567 * 1568 * @return SCI_STATUS 1569 */ 1570 SCI_STATUS scic_sds_request_start( 1571 SCIC_SDS_REQUEST_T *this_request 1572 ) 1573 { 1574 if ( 1575 this_request->device_sequence 1576 == scic_sds_remote_device_get_sequence(this_request->target_device) 1577 ) 1578 { 1579 return this_request->state_handlers->parent.start_handler( 1580 &this_request->parent 1581 ); 1582 } 1583 1584 return SCI_FAILURE; 1585 } 1586 1587 /** 1588 * This method invokes the base state terminate request handber for the 1589 * SCIC_SDS_IO_REQUEST_T object. 1590 * 1591 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the 1592 * start operation is to be executed. 1593 * 1594 * @return SCI_STATUS 1595 */ 1596 SCI_STATUS scic_sds_io_request_terminate( 1597 SCIC_SDS_REQUEST_T *this_request 1598 ) 1599 { 1600 return this_request->state_handlers->parent.abort_handler( 1601 &this_request->parent); 1602 } 1603 1604 /** 1605 * This method invokes the base state request completion handler for the 1606 * SCIC_SDS_IO_REQUEST_T object. 1607 * 1608 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the 1609 * start operation is to be executed. 1610 * 1611 * @return SCI_STATUS 1612 */ 1613 SCI_STATUS scic_sds_io_request_complete( 1614 SCIC_SDS_REQUEST_T *this_request 1615 ) 1616 { 1617 return this_request->state_handlers->parent.complete_handler( 1618 &this_request->parent); 1619 } 1620 1621 /** 1622 * This method invokes the core state handler for the SCIC_SDS_IO_REQUEST_T 1623 * object. 1624 * 1625 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the 1626 * start operation is to be executed. 1627 * @param[in] event_code The event code returned by the hardware for the task 1628 * reqeust. 1629 * 1630 * @return SCI_STATUS 1631 */ 1632 SCI_STATUS scic_sds_io_request_event_handler( 1633 SCIC_SDS_REQUEST_T * this_request, 1634 U32 event_code 1635 ) 1636 { 1637 return this_request->state_handlers->event_handler(this_request, event_code); 1638 } 1639 1640 /** 1641 * This method invokes the core state frame handler for the 1642 * SCIC_SDS_IO_REQUEST_T object. 1643 * 1644 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the 1645 * start operation is to be executed. 1646 * @param[in] frame_index The frame index returned by the hardware for the 1647 * reqeust object. 1648 * 1649 * @return SCI_STATUS 1650 */ 1651 SCI_STATUS scic_sds_io_request_frame_handler( 1652 SCIC_SDS_REQUEST_T * this_request, 1653 U32 frame_index 1654 ) 1655 { 1656 return this_request->state_handlers->frame_handler(this_request, frame_index); 1657 } 1658 1659 /** 1660 * This method invokes the core state task complete handler for the 1661 * SCIC_SDS_IO_REQUEST_T object. 1662 * 1663 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the task 1664 * start operation is to be executed. 1665 * 1666 * @return SCI_STATUS 1667 */ 1668 SCI_STATUS scic_sds_task_request_complete( 1669 SCIC_SDS_REQUEST_T *this_request 1670 ) 1671 { 1672 return this_request->state_handlers->parent.complete_handler(&this_request->parent); 1673 } 1674 1675 //**************************************************************************** 1676 //* SCIC SDS PROTECTED METHODS 1677 //**************************************************************************** 1678 1679 /** 1680 * @brief This method copies response data for requests returning response 1681 * data instead of sense data. 1682 * 1683 * @param[in] this_request This parameter specifies the request object for 1684 * which to copy the response data. 1685 * 1686 * @return none 1687 */ 1688 void scic_sds_io_request_copy_response( 1689 SCIC_SDS_REQUEST_T *this_request 1690 ) 1691 { 1692 void * response_buffer; 1693 U32 user_response_length; 1694 U32 core_response_length; 1695 SCI_SSP_RESPONSE_IU_T * ssp_response; 1696 1697 ssp_response = (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer; 1698 1699 response_buffer = scic_cb_ssp_task_request_get_response_data_address( 1700 this_request->user_request 1701 ); 1702 1703 user_response_length = scic_cb_ssp_task_request_get_response_data_length( 1704 this_request->user_request 1705 ); 1706 1707 core_response_length = sci_ssp_get_response_data_length( 1708 ssp_response->response_data_length 1709 ); 1710 1711 user_response_length = MIN(user_response_length, core_response_length); 1712 1713 memcpy(response_buffer, ssp_response->data, user_response_length); 1714 } 1715 1716 //****************************************************************************** 1717 //* REQUEST STATE MACHINE 1718 //****************************************************************************** 1719 1720 //***************************************************************************** 1721 //* DEFAULT STATE HANDLERS 1722 //***************************************************************************** 1723 1724 /** 1725 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T 1726 * object receives a scic_sds_request_start() request. The default action is 1727 * to log a warning and return a failure status. 1728 * 1729 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 1730 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 1731 * requested. 1732 * 1733 * @return SCI_STATUS 1734 * @retval SCI_FAILURE_INVALID_STATE 1735 */ 1736 SCI_STATUS scic_sds_request_default_start_handler( 1737 SCI_BASE_REQUEST_T *request 1738 ) 1739 { 1740 SCIC_LOG_WARNING(( 1741 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request), 1742 ( 1743 SCIC_LOG_OBJECT_SSP_IO_REQUEST 1744 | SCIC_LOG_OBJECT_STP_IO_REQUEST 1745 | SCIC_LOG_OBJECT_SMP_IO_REQUEST 1746 ), 1747 "SCIC IO Request requested to start while in wrong state %d\n", 1748 sci_base_state_machine_get_state( 1749 &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine) 1750 )); 1751 1752 return SCI_FAILURE_INVALID_STATE; 1753 } 1754 1755 /** 1756 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T 1757 * object receives a scic_sds_request_terminate() request. The default action 1758 * is to log a warning and return a failure status. 1759 * 1760 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 1761 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 1762 * requested. 1763 * 1764 * @return SCI_STATUS 1765 * @retval SCI_FAILURE_INVALID_STATE 1766 */ 1767 SCI_STATUS scic_sds_request_default_abort_handler( 1768 SCI_BASE_REQUEST_T *request 1769 ) 1770 { 1771 SCIC_LOG_WARNING(( 1772 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request), 1773 ( 1774 SCIC_LOG_OBJECT_SSP_IO_REQUEST 1775 | SCIC_LOG_OBJECT_STP_IO_REQUEST 1776 | SCIC_LOG_OBJECT_SMP_IO_REQUEST 1777 ), 1778 "SCIC IO Request requested to abort while in wrong state %d\n", 1779 sci_base_state_machine_get_state( 1780 &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine) 1781 )); 1782 1783 return SCI_FAILURE_INVALID_STATE; 1784 } 1785 1786 /** 1787 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T 1788 * object receives a scic_sds_request_complete() request. The default action 1789 * is to log a warning and return a failure status. 1790 * 1791 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 1792 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 1793 * requested. 1794 * 1795 * @return SCI_STATUS 1796 * @retval SCI_FAILURE_INVALID_STATE 1797 */ 1798 SCI_STATUS scic_sds_request_default_complete_handler( 1799 SCI_BASE_REQUEST_T *request 1800 ) 1801 { 1802 SCIC_LOG_WARNING(( 1803 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request), 1804 ( 1805 SCIC_LOG_OBJECT_SSP_IO_REQUEST 1806 | SCIC_LOG_OBJECT_STP_IO_REQUEST 1807 | SCIC_LOG_OBJECT_SMP_IO_REQUEST 1808 ), 1809 "SCIC IO Request requested to complete while in wrong state %d\n", 1810 sci_base_state_machine_get_state( 1811 &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine) 1812 )); 1813 1814 return SCI_FAILURE_INVALID_STATE; 1815 } 1816 1817 /** 1818 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T 1819 * object receives a scic_sds_request_complete() request. The default action 1820 * is to log a warning and return a failure status. 1821 * 1822 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 1823 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 1824 * requested. 1825 * 1826 * @return SCI_STATUS 1827 * @retval SCI_FAILURE_INVALID_STATE 1828 */ 1829 SCI_STATUS scic_sds_request_default_destruct_handler( 1830 SCI_BASE_REQUEST_T *request 1831 ) 1832 { 1833 SCIC_LOG_WARNING(( 1834 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request), 1835 ( 1836 SCIC_LOG_OBJECT_SSP_IO_REQUEST 1837 | SCIC_LOG_OBJECT_STP_IO_REQUEST 1838 | SCIC_LOG_OBJECT_SMP_IO_REQUEST 1839 ), 1840 "SCIC IO Request requested to destroy while in wrong state %d\n", 1841 sci_base_state_machine_get_state( 1842 &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine) 1843 )); 1844 1845 return SCI_FAILURE_INVALID_STATE; 1846 } 1847 1848 /** 1849 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T 1850 * object receives a scic_sds_task_request_complete() request. The default 1851 * action is to log a warning and return a failure status. 1852 * 1853 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 1854 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 1855 * requested. 1856 * 1857 * @return SCI_STATUS 1858 * @retval SCI_FAILURE_INVALID_STATE 1859 */ 1860 SCI_STATUS scic_sds_request_default_tc_completion_handler( 1861 SCIC_SDS_REQUEST_T * this_request, 1862 U32 completion_code 1863 ) 1864 { 1865 SCIC_LOG_WARNING(( 1866 sci_base_object_get_logger(this_request), 1867 ( 1868 SCIC_LOG_OBJECT_SSP_IO_REQUEST 1869 | SCIC_LOG_OBJECT_STP_IO_REQUEST 1870 | SCIC_LOG_OBJECT_SMP_IO_REQUEST 1871 ), 1872 "SCIC IO Request given task completion notification %x while in wrong state %d\n", 1873 completion_code, 1874 sci_base_state_machine_get_state(&this_request->parent.state_machine) 1875 )); 1876 1877 return SCI_FAILURE_INVALID_STATE; 1878 1879 } 1880 1881 /** 1882 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T 1883 * object receives a scic_sds_request_event_handler() request. The default 1884 * action is to log a warning and return a failure status. 1885 * 1886 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 1887 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 1888 * requested. 1889 * 1890 * @return SCI_STATUS 1891 * @retval SCI_FAILURE_INVALID_STATE 1892 */ 1893 SCI_STATUS scic_sds_request_default_event_handler( 1894 SCIC_SDS_REQUEST_T * this_request, 1895 U32 event_code 1896 ) 1897 { 1898 SCIC_LOG_WARNING(( 1899 sci_base_object_get_logger(this_request), 1900 ( 1901 SCIC_LOG_OBJECT_SSP_IO_REQUEST 1902 | SCIC_LOG_OBJECT_STP_IO_REQUEST 1903 | SCIC_LOG_OBJECT_SMP_IO_REQUEST 1904 ), 1905 "SCIC IO Request given event code notification %x while in wrong state %d\n", 1906 event_code, 1907 sci_base_state_machine_get_state(&this_request->parent.state_machine) 1908 )); 1909 1910 return SCI_FAILURE_INVALID_STATE; 1911 } 1912 1913 /** 1914 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T 1915 * object receives a scic_sds_request_event_handler() request. The default 1916 * action is to log a warning and return a failure status. 1917 * 1918 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 1919 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 1920 * requested. 1921 * 1922 * @return SCI_STATUS 1923 * @retval SCI_FAILURE_INVALID_STATE 1924 */ 1925 SCI_STATUS scic_sds_request_default_frame_handler( 1926 SCIC_SDS_REQUEST_T * this_request, 1927 U32 frame_index 1928 ) 1929 { 1930 SCIC_LOG_WARNING(( 1931 sci_base_object_get_logger(this_request), 1932 ( 1933 SCIC_LOG_OBJECT_SSP_IO_REQUEST 1934 | SCIC_LOG_OBJECT_STP_IO_REQUEST 1935 | SCIC_LOG_OBJECT_SMP_IO_REQUEST 1936 ), 1937 "SCIC IO Request given unexpected frame %x while in state %d\n", 1938 frame_index, 1939 sci_base_state_machine_get_state(&this_request->parent.state_machine) 1940 )); 1941 1942 scic_sds_controller_release_frame( 1943 this_request->owning_controller, frame_index); 1944 1945 return SCI_FAILURE_INVALID_STATE; 1946 } 1947 1948 //***************************************************************************** 1949 //* CONSTRUCTED STATE HANDLERS 1950 //***************************************************************************** 1951 1952 /** 1953 * This method implements the action taken when a constructed 1954 * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request. 1955 * 1956 * This method will, if necessary, allocate a TCi for the io request object 1957 * and then will, if necessary, copy the constructed TC data into the actual 1958 * TC buffer. If everything is successful the post context field is updated 1959 * with the TCi so the controller can post the request to the hardware. 1960 * 1961 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 1962 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 1963 * requested. 1964 * 1965 * @return SCI_STATUS 1966 * @retval SCI_SUCCESS 1967 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES 1968 */ 1969 static 1970 SCI_STATUS scic_sds_request_constructed_state_start_handler( 1971 SCI_BASE_REQUEST_T *request 1972 ) 1973 { 1974 SCU_TASK_CONTEXT_T *task_context; 1975 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request; 1976 1977 if (this_request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) 1978 { 1979 this_request->io_tag = 1980 scic_controller_allocate_io_tag(this_request->owning_controller); 1981 } 1982 1983 // Record the IO Tag in the request 1984 if (this_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) 1985 { 1986 task_context = this_request->task_context_buffer; 1987 1988 task_context->task_index = scic_sds_io_tag_get_index(this_request->io_tag); 1989 1990 switch (task_context->protocol_type) 1991 { 1992 case SCU_TASK_CONTEXT_PROTOCOL_SMP: 1993 case SCU_TASK_CONTEXT_PROTOCOL_SSP: 1994 // SSP/SMP Frame 1995 task_context->type.ssp.tag = this_request->io_tag; 1996 task_context->type.ssp.target_port_transfer_tag = 0xFFFF; 1997 break; 1998 1999 case SCU_TASK_CONTEXT_PROTOCOL_STP: 2000 // STP/SATA Frame 2001 //task_context->type.stp.ncq_tag = this_request->ncq_tag; 2002 break; 2003 2004 case SCU_TASK_CONTEXT_PROTOCOL_NONE: 2005 /// @todo When do we set no protocol type? 2006 break; 2007 2008 default: 2009 // This should never happen since we build the IO requests 2010 break; 2011 } 2012 2013 // Check to see if we need to copy the task context buffer 2014 // or have been building into the task context buffer 2015 if (this_request->was_tag_assigned_by_user == FALSE) 2016 { 2017 scic_sds_controller_copy_task_context( 2018 this_request->owning_controller, this_request 2019 ); 2020 } 2021 2022 // Add to the post_context the io tag value 2023 this_request->post_context |= scic_sds_io_tag_get_index(this_request->io_tag); 2024 2025 // Everything is good go ahead and change state 2026 sci_base_state_machine_change_state( 2027 &this_request->parent.state_machine, 2028 SCI_BASE_REQUEST_STATE_STARTED 2029 ); 2030 2031 return SCI_SUCCESS; 2032 } 2033 2034 return SCI_FAILURE_INSUFFICIENT_RESOURCES; 2035 } 2036 2037 /** 2038 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T 2039 * object receives a scic_sds_request_terminate() request. 2040 * 2041 * Since the request has not yet been posted to the hardware the request 2042 * transitions to the completed state. 2043 * 2044 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 2045 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 2046 * requested. 2047 * 2048 * @return SCI_STATUS 2049 * @retval SCI_SUCCESS 2050 */ 2051 static 2052 SCI_STATUS scic_sds_request_constructed_state_abort_handler( 2053 SCI_BASE_REQUEST_T *request 2054 ) 2055 { 2056 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request; 2057 2058 // This request has been terminated by the user make sure that the correct 2059 // status code is returned 2060 scic_sds_request_set_status( 2061 this_request, 2062 SCU_TASK_DONE_TASK_ABORT, 2063 SCI_FAILURE_IO_TERMINATED 2064 ); 2065 2066 sci_base_state_machine_change_state( 2067 &this_request->parent.state_machine, 2068 SCI_BASE_REQUEST_STATE_COMPLETED 2069 ); 2070 2071 return SCI_SUCCESS; 2072 } 2073 2074 //***************************************************************************** 2075 //* STARTED STATE HANDLERS 2076 //***************************************************************************** 2077 2078 /** 2079 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T 2080 * object receives a scic_sds_request_terminate() request. 2081 * 2082 * Since the request has been posted to the hardware the io request state is 2083 * changed to the aborting state. 2084 * 2085 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 2086 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 2087 * requested. 2088 * 2089 * @return SCI_STATUS 2090 * @retval SCI_SUCCESS 2091 */ 2092 SCI_STATUS scic_sds_request_started_state_abort_handler( 2093 SCI_BASE_REQUEST_T *request 2094 ) 2095 { 2096 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request; 2097 2098 if (this_request->has_started_substate_machine) 2099 { 2100 sci_base_state_machine_stop(&this_request->started_substate_machine); 2101 } 2102 2103 sci_base_state_machine_change_state( 2104 &this_request->parent.state_machine, 2105 SCI_BASE_REQUEST_STATE_ABORTING 2106 ); 2107 2108 return SCI_SUCCESS; 2109 } 2110 2111 /** 2112 * @brief This method process TC (task context) completions for normal IO 2113 * request (i.e. Task/Abort Completions of type 0). This method will 2114 * update the SCIC_SDS_IO_REQUEST_T::status field. 2115 * 2116 * @param[in] this_request This parameter specifies the request for which 2117 * a completion occurred. 2118 * @param[in] completion_code This parameter specifies the completion code 2119 * received from the SCU. 2120 * 2121 * @return none 2122 */ 2123 SCI_STATUS scic_sds_request_started_state_tc_completion_handler( 2124 SCIC_SDS_REQUEST_T * this_request, 2125 U32 completion_code 2126 ) 2127 { 2128 U8 data_present; 2129 SCI_SSP_RESPONSE_IU_T * response_buffer; 2130 2131 /** 2132 * @todo Any SDMA return code of other than 0 is bad 2133 * decode 0x003C0000 to determine SDMA status 2134 */ 2135 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 2136 { 2137 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 2138 scic_sds_request_set_status( 2139 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 2140 ); 2141 break; 2142 2143 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP): 2144 { 2145 // There are times when the SCU hardware will return an early response 2146 // because the io request specified more data than is returned by the 2147 // target device (mode pages, inquiry data, etc.). We must check the 2148 // response stats to see if this is truly a failed request or a good 2149 // request that just got completed early. 2150 SCI_SSP_RESPONSE_IU_T *response = (SCI_SSP_RESPONSE_IU_T *) 2151 this_request->response_buffer; 2152 scic_word_copy_with_swap( 2153 this_request->response_buffer, 2154 this_request->response_buffer, 2155 sizeof(SCI_SSP_RESPONSE_IU_T) / sizeof(U32) 2156 ); 2157 2158 if (response->status == 0) 2159 { 2160 scic_sds_request_set_status( 2161 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY 2162 ); 2163 } 2164 else 2165 { 2166 scic_sds_request_set_status( 2167 this_request, 2168 SCU_TASK_DONE_CHECK_RESPONSE, 2169 SCI_FAILURE_IO_RESPONSE_VALID 2170 ); 2171 } 2172 } 2173 break; 2174 2175 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE): 2176 scic_word_copy_with_swap( 2177 this_request->response_buffer, 2178 this_request->response_buffer, 2179 sizeof(SCI_SSP_RESPONSE_IU_T) / sizeof(U32) 2180 ); 2181 2182 scic_sds_request_set_status( 2183 this_request, 2184 SCU_TASK_DONE_CHECK_RESPONSE, 2185 SCI_FAILURE_IO_RESPONSE_VALID 2186 ); 2187 break; 2188 2189 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR): 2190 /// @todo With TASK_DONE_RESP_LEN_ERR is the response frame guaranteed 2191 /// to be received before this completion status is posted? 2192 response_buffer = 2193 (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer; 2194 data_present = 2195 response_buffer->data_present & SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK; 2196 2197 if ((data_present == 0x01) || (data_present == 0x02)) 2198 { 2199 scic_sds_request_set_status( 2200 this_request, 2201 SCU_TASK_DONE_CHECK_RESPONSE, 2202 SCI_FAILURE_IO_RESPONSE_VALID 2203 ); 2204 } 2205 else 2206 { 2207 scic_sds_request_set_status( 2208 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 2209 ); 2210 } 2211 break; 2212 2213 //only stp device gets suspended. 2214 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): 2215 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_PERR): 2216 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_ERR): 2217 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_DATA_LEN_ERR): 2218 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_ABORT_ERR): 2219 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_WD_LEN): 2220 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): 2221 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_RESP): 2222 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS): 2223 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): 2224 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR): 2225 if (this_request->protocol == SCIC_STP_PROTOCOL) 2226 { 2227 SCIC_LOG_ERROR(( 2228 sci_base_object_get_logger(this_request), 2229 SCIC_LOG_OBJECT_STP_IO_REQUEST, 2230 "SCIC IO Request 0x%x returning REMOTE_DEVICE_RESET_REQUIRED for completion code 0x%x\n", 2231 this_request, completion_code 2232 )); 2233 scic_sds_request_set_status( 2234 this_request, 2235 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, 2236 SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED 2237 ); 2238 } 2239 else 2240 { 2241 SCIC_LOG_ERROR(( 2242 sci_base_object_get_logger(this_request), 2243 SCIC_LOG_OBJECT_SSP_IO_REQUEST, 2244 "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n", 2245 this_request, completion_code 2246 )); 2247 scic_sds_request_set_status( 2248 this_request, 2249 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, 2250 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 2251 ); 2252 } 2253 break; 2254 2255 //both stp/ssp device gets suspended 2256 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LF_ERR): 2257 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_WRONG_DESTINATION): 2258 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1): 2259 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2): 2260 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3): 2261 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_BAD_DESTINATION): 2262 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_ZONE_VIOLATION): 2263 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY): 2264 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED): 2265 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): 2266 scic_sds_request_set_status( 2267 this_request, 2268 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, 2269 SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED 2270 ); 2271 break; 2272 2273 //neither ssp nor stp gets suspended. 2274 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_CMD_ERR): 2275 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_XR): 2276 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_IU_LEN_ERR): 2277 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDMA_ERR): 2278 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OFFSET_ERR): 2279 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EXCESS_DATA): 2280 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): 2281 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): 2282 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): 2283 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): 2284 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_DATA): 2285 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OPEN_FAIL): 2286 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_VIIT_ENTRY_NV): 2287 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV): 2288 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND): 2289 default: 2290 SCIC_LOG_ERROR(( 2291 sci_base_object_get_logger(this_request), 2292 SCIC_LOG_OBJECT_SSP_IO_REQUEST | SCIC_LOG_OBJECT_STP_IO_REQUEST, 2293 "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n", 2294 this_request, completion_code 2295 )); 2296 scic_sds_request_set_status( 2297 this_request, 2298 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, 2299 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 2300 ); 2301 break; 2302 } 2303 2304 /** 2305 * @todo This is probably wrong for ACK/NAK timeout conditions 2306 */ 2307 2308 // In all cases we will treat this as the completion of the IO request. 2309 sci_base_state_machine_change_state( 2310 &this_request->parent.state_machine, 2311 SCI_BASE_REQUEST_STATE_COMPLETED 2312 ); 2313 2314 return SCI_SUCCESS; 2315 } 2316 2317 /** 2318 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T 2319 * object receives a scic_sds_request_frame_handler() request. 2320 * 2321 * This method first determines the frame type received. If this is a 2322 * response frame then the response data is copied to the io request response 2323 * buffer for processing at completion time. 2324 * 2325 * If the frame type is not a response buffer an error is logged. 2326 * 2327 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 2328 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 2329 * requested. 2330 * @param[in] frame_index This is the index of the unsolicited frame to be 2331 * processed. 2332 * 2333 * @return SCI_STATUS 2334 * @retval SCI_SUCCESS 2335 * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE 2336 */ 2337 static 2338 SCI_STATUS scic_sds_request_started_state_frame_handler( 2339 SCIC_SDS_REQUEST_T * this_request, 2340 U32 frame_index 2341 ) 2342 { 2343 SCI_STATUS status; 2344 SCI_SSP_FRAME_HEADER_T *frame_header; 2345 2346 /// @todo If this is a response frame we must record that we received it 2347 status = scic_sds_unsolicited_frame_control_get_header( 2348 &(scic_sds_request_get_controller(this_request)->uf_control), 2349 frame_index, 2350 (void**) &frame_header 2351 ); 2352 2353 if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME) 2354 { 2355 SCI_SSP_RESPONSE_IU_T *response_buffer; 2356 2357 status = scic_sds_unsolicited_frame_control_get_buffer( 2358 &(scic_sds_request_get_controller(this_request)->uf_control), 2359 frame_index, 2360 (void**) &response_buffer 2361 ); 2362 2363 scic_word_copy_with_swap( 2364 this_request->response_buffer, 2365 (U32 *)response_buffer, 2366 sizeof(SCI_SSP_RESPONSE_IU_T) 2367 ); 2368 2369 response_buffer = (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer; 2370 2371 if ( 2372 (response_buffer->data_present == 0x01) 2373 || (response_buffer->data_present == 0x02) 2374 ) 2375 { 2376 scic_sds_request_set_status( 2377 this_request, 2378 SCU_TASK_DONE_CHECK_RESPONSE, 2379 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 2380 ); 2381 } 2382 else 2383 { 2384 scic_sds_request_set_status( 2385 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 2386 ); 2387 } 2388 2389 } 2390 else 2391 { 2392 // This was not a response frame why did it get forwarded? 2393 SCIC_LOG_ERROR(( 2394 sci_base_object_get_logger(this_request), 2395 SCIC_LOG_OBJECT_SSP_IO_REQUEST, 2396 "SCIC IO Request 0x%x received unexpected frame %d type 0x%02x\n", 2397 this_request, frame_index, frame_header->frame_type 2398 )); 2399 } 2400 2401 // In any case we are done with this frame buffer return it to the 2402 // controller 2403 scic_sds_controller_release_frame( 2404 this_request->owning_controller, frame_index 2405 ); 2406 2407 return SCI_SUCCESS; 2408 } 2409 2410 //***************************************************************************** 2411 //* COMPLETED STATE HANDLERS 2412 //***************************************************************************** 2413 2414 2415 /** 2416 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T 2417 * object receives a scic_sds_request_complete() request. 2418 * 2419 * This method frees up any io request resources that have been allocated and 2420 * transitions the request to its final state. 2421 * 2422 * @todo Consider stopping the state machine instead of transitioning to the 2423 * final state? 2424 * 2425 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 2426 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 2427 * requested. 2428 * 2429 * @return SCI_STATUS 2430 * @retval SCI_SUCCESS 2431 */ 2432 static 2433 SCI_STATUS scic_sds_request_completed_state_complete_handler( 2434 SCI_BASE_REQUEST_T *request 2435 ) 2436 { 2437 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request; 2438 2439 if (this_request->was_tag_assigned_by_user != TRUE) 2440 { 2441 scic_controller_free_io_tag( 2442 this_request->owning_controller, this_request->io_tag 2443 ); 2444 } 2445 2446 if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) 2447 { 2448 scic_sds_controller_release_frame( 2449 this_request->owning_controller, this_request->saved_rx_frame_index); 2450 } 2451 2452 sci_base_state_machine_change_state( 2453 &this_request->parent.state_machine, 2454 SCI_BASE_REQUEST_STATE_FINAL 2455 ); 2456 2457 scic_sds_request_deinitialize_state_logging(this_request); 2458 2459 return SCI_SUCCESS; 2460 } 2461 2462 //***************************************************************************** 2463 //* ABORTING STATE HANDLERS 2464 //***************************************************************************** 2465 2466 /** 2467 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T 2468 * object receives a scic_sds_request_terminate() request. 2469 * 2470 * This method is the io request aborting state abort handlers. On receipt of 2471 * a multiple terminate requests the io request will transition to the 2472 * completed state. This should not happen in normal operation. 2473 * 2474 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 2475 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 2476 * requested. 2477 * 2478 * @return SCI_STATUS 2479 * @retval SCI_SUCCESS 2480 */ 2481 static 2482 SCI_STATUS scic_sds_request_aborting_state_abort_handler( 2483 SCI_BASE_REQUEST_T *request 2484 ) 2485 { 2486 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request; 2487 2488 sci_base_state_machine_change_state( 2489 &this_request->parent.state_machine, 2490 SCI_BASE_REQUEST_STATE_COMPLETED 2491 ); 2492 2493 return SCI_SUCCESS; 2494 } 2495 2496 /** 2497 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T 2498 * object receives a scic_sds_request_task_completion() request. 2499 * 2500 * This method decodes the completion type waiting for the abort task complete 2501 * notification. When the abort task complete is received the io request 2502 * transitions to the completed state. 2503 * 2504 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 2505 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 2506 * requested. 2507 * 2508 * @return SCI_STATUS 2509 * @retval SCI_SUCCESS 2510 */ 2511 static 2512 SCI_STATUS scic_sds_request_aborting_state_tc_completion_handler( 2513 SCIC_SDS_REQUEST_T * this_request, 2514 U32 completion_code 2515 ) 2516 { 2517 SCIC_LOG_TRACE(( 2518 sci_base_object_get_logger(this_request), 2519 SCIC_LOG_OBJECT_TASK_MANAGEMENT, 2520 "scic_sds_request_aborting_state_tc_completion_handler(0x%x,0x%x) enter\n", 2521 this_request, completion_code 2522 )); 2523 2524 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 2525 { 2526 case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): 2527 case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT): 2528 scic_sds_request_set_status( 2529 this_request, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED 2530 ); 2531 2532 sci_base_state_machine_change_state( 2533 &this_request->parent.state_machine, 2534 SCI_BASE_REQUEST_STATE_COMPLETED 2535 ); 2536 break; 2537 2538 default: 2539 // Unless we get some strange error wait for the task abort to complete 2540 // TODO: Should there be a state change for this completion? 2541 break; 2542 } 2543 2544 return SCI_SUCCESS; 2545 } 2546 2547 /** 2548 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T 2549 * object receives a scic_sds_request_frame_handler() request. 2550 * 2551 * This method discards the unsolicited frame since we are waiting for the 2552 * abort task completion. 2553 * 2554 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to 2555 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is 2556 * requested. 2557 * 2558 * @return SCI_STATUS 2559 * @retval SCI_SUCCESS 2560 */ 2561 static 2562 SCI_STATUS scic_sds_request_aborting_state_frame_handler( 2563 SCIC_SDS_REQUEST_T * this_request, 2564 U32 frame_index 2565 ) 2566 { 2567 // TODO: Is it even possible to get an unsolicited frame in the aborting state? 2568 2569 scic_sds_controller_release_frame( 2570 this_request->owning_controller, frame_index); 2571 2572 return SCI_SUCCESS; 2573 } 2574 2575 // --------------------------------------------------------------------------- 2576 2577 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T 2578 scic_sds_request_state_handler_table[SCI_BASE_REQUEST_MAX_STATES] = 2579 { 2580 // SCI_BASE_REQUEST_STATE_INITIAL 2581 { 2582 { 2583 scic_sds_request_default_start_handler, 2584 scic_sds_request_default_abort_handler, 2585 scic_sds_request_default_complete_handler, 2586 scic_sds_request_default_destruct_handler 2587 }, 2588 scic_sds_request_default_tc_completion_handler, 2589 scic_sds_request_default_event_handler, 2590 scic_sds_request_default_frame_handler 2591 }, 2592 // SCI_BASE_REQUEST_STATE_CONSTRUCTED 2593 { 2594 { 2595 scic_sds_request_constructed_state_start_handler, 2596 scic_sds_request_constructed_state_abort_handler, 2597 scic_sds_request_default_complete_handler, 2598 scic_sds_request_default_destruct_handler 2599 }, 2600 scic_sds_request_default_tc_completion_handler, 2601 scic_sds_request_default_event_handler, 2602 scic_sds_request_default_frame_handler 2603 }, 2604 // SCI_BASE_REQUEST_STATE_STARTED 2605 { 2606 { 2607 scic_sds_request_default_start_handler, 2608 scic_sds_request_started_state_abort_handler, 2609 scic_sds_request_default_complete_handler, 2610 scic_sds_request_default_destruct_handler 2611 }, 2612 scic_sds_request_started_state_tc_completion_handler, 2613 scic_sds_request_default_event_handler, 2614 scic_sds_request_started_state_frame_handler 2615 }, 2616 // SCI_BASE_REQUEST_STATE_COMPLETED 2617 { 2618 { 2619 scic_sds_request_default_start_handler, 2620 scic_sds_request_default_abort_handler, 2621 scic_sds_request_completed_state_complete_handler, 2622 scic_sds_request_default_destruct_handler 2623 }, 2624 scic_sds_request_default_tc_completion_handler, 2625 scic_sds_request_default_event_handler, 2626 scic_sds_request_default_frame_handler 2627 }, 2628 // SCI_BASE_REQUEST_STATE_ABORTING 2629 { 2630 { 2631 scic_sds_request_default_start_handler, 2632 scic_sds_request_aborting_state_abort_handler, 2633 scic_sds_request_default_complete_handler, 2634 scic_sds_request_default_destruct_handler 2635 }, 2636 scic_sds_request_aborting_state_tc_completion_handler, 2637 scic_sds_request_default_event_handler, 2638 scic_sds_request_aborting_state_frame_handler, 2639 }, 2640 // SCI_BASE_REQUEST_STATE_FINAL 2641 { 2642 { 2643 scic_sds_request_default_start_handler, 2644 scic_sds_request_default_abort_handler, 2645 scic_sds_request_default_complete_handler, 2646 scic_sds_request_default_destruct_handler 2647 }, 2648 scic_sds_request_default_tc_completion_handler, 2649 scic_sds_request_default_event_handler, 2650 scic_sds_request_default_frame_handler 2651 } 2652 }; 2653 2654 /** 2655 * This method implements the actions taken when entering the 2656 * SCI_BASE_REQUEST_STATE_INITIAL state. This state is entered when the 2657 * initial base request is constructed. Entry into the initial state sets all 2658 * handlers for the io request object to their default handlers. 2659 * 2660 * @param[in] object This parameter specifies the base object for which the 2661 * state transition is occurring. 2662 * 2663 * @return none 2664 */ 2665 static 2666 void scic_sds_request_initial_state_enter( 2667 SCI_BASE_OBJECT_T *object 2668 ) 2669 { 2670 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2671 2672 SET_STATE_HANDLER( 2673 this_request, 2674 scic_sds_request_state_handler_table, 2675 SCI_BASE_REQUEST_STATE_INITIAL 2676 ); 2677 } 2678 2679 /** 2680 * This method implements the actions taken when entering the 2681 * SCI_BASE_REQUEST_STATE_CONSTRUCTED state. 2682 * The method sets the state handlers for the constructed state. 2683 * 2684 * @param[in] object The io request object that is to enter the constructed 2685 * state. 2686 * 2687 * @return none 2688 */ 2689 static 2690 void scic_sds_request_constructed_state_enter( 2691 SCI_BASE_OBJECT_T *object 2692 ) 2693 { 2694 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2695 2696 SET_STATE_HANDLER( 2697 this_request, 2698 scic_sds_request_state_handler_table, 2699 SCI_BASE_REQUEST_STATE_CONSTRUCTED 2700 ); 2701 } 2702 2703 /** 2704 * This method implements the actions taken when entering the 2705 * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a 2706 * SCSI Task request we must enter the started substate machine. 2707 * 2708 * @param[in] object This parameter specifies the base object for which the 2709 * state transition is occurring. This is cast into a 2710 * SCIC_SDS_IO_REQUEST object. 2711 * 2712 * @return none 2713 */ 2714 static 2715 void scic_sds_request_started_state_enter( 2716 SCI_BASE_OBJECT_T *object 2717 ) 2718 { 2719 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2720 2721 SET_STATE_HANDLER( 2722 this_request, 2723 scic_sds_request_state_handler_table, 2724 SCI_BASE_REQUEST_STATE_STARTED 2725 ); 2726 2727 // Most of the request state machines have a started substate machine so 2728 // start its execution on the entry to the started state. 2729 if (this_request->has_started_substate_machine == TRUE) 2730 sci_base_state_machine_start(&this_request->started_substate_machine); 2731 } 2732 2733 /** 2734 * This method implements the actions taken when exiting the 2735 * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be 2736 * to stop the started substate machine. 2737 * 2738 * @param[in] object This parameter specifies the base object for which the 2739 * state transition is occurring. This object is cast into a 2740 * SCIC_SDS_IO_REQUEST object. 2741 * 2742 * @return none 2743 */ 2744 static 2745 void scic_sds_request_started_state_exit( 2746 SCI_BASE_OBJECT_T *object 2747 ) 2748 { 2749 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2750 2751 if (this_request->has_started_substate_machine == TRUE) 2752 sci_base_state_machine_stop(&this_request->started_substate_machine); 2753 } 2754 2755 /** 2756 * This method implements the actions taken when entering the 2757 * SCI_BASE_REQUEST_STATE_COMPLETED state. This state is entered when the 2758 * SCIC_SDS_IO_REQUEST has completed. The method will decode the request 2759 * completion status and convert it to an SCI_STATUS to return in the 2760 * completion callback function. 2761 * 2762 * @param[in] object This parameter specifies the base object for which the 2763 * state transition is occurring. This object is cast into a 2764 * SCIC_SDS_IO_REQUEST object. 2765 * 2766 * @return none 2767 */ 2768 static 2769 void scic_sds_request_completed_state_enter( 2770 SCI_BASE_OBJECT_T *object 2771 ) 2772 { 2773 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2774 2775 SET_STATE_HANDLER( 2776 this_request, 2777 scic_sds_request_state_handler_table, 2778 SCI_BASE_REQUEST_STATE_COMPLETED 2779 ); 2780 2781 // Tell the SCI_USER that the IO request is complete 2782 if (this_request->is_task_management_request == FALSE) 2783 { 2784 scic_cb_io_request_complete( 2785 scic_sds_request_get_controller(this_request), 2786 scic_sds_request_get_device(this_request), 2787 this_request, 2788 this_request->sci_status 2789 ); 2790 } 2791 else 2792 { 2793 scic_cb_task_request_complete( 2794 scic_sds_request_get_controller(this_request), 2795 scic_sds_request_get_device(this_request), 2796 this_request, 2797 this_request->sci_status 2798 ); 2799 } 2800 } 2801 2802 /** 2803 * This method implements the actions taken when entering the 2804 * SCI_BASE_REQUEST_STATE_ABORTING state. 2805 * 2806 * @param[in] object This parameter specifies the base object for which the 2807 * state transition is occurring. This object is cast into a 2808 * SCIC_SDS_IO_REQUEST object. 2809 * 2810 * @return none 2811 */ 2812 static 2813 void scic_sds_request_aborting_state_enter( 2814 SCI_BASE_OBJECT_T *object 2815 ) 2816 { 2817 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2818 2819 // Setting the abort bit in the Task Context is required by the silicon. 2820 this_request->task_context_buffer->abort = 1; 2821 2822 SET_STATE_HANDLER( 2823 this_request, 2824 scic_sds_request_state_handler_table, 2825 SCI_BASE_REQUEST_STATE_ABORTING 2826 ); 2827 } 2828 2829 /** 2830 * This method implements the actions taken when entering the 2831 * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the 2832 * state handlers in place. 2833 * 2834 * @param[in] object This parameter specifies the base object for which the 2835 * state transition is occurring. This is cast into a 2836 * SCIC_SDS_IO_REQUEST object. 2837 * 2838 * @return none 2839 */ 2840 static 2841 void scic_sds_request_final_state_enter( 2842 SCI_BASE_OBJECT_T *object 2843 ) 2844 { 2845 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2846 2847 SET_STATE_HANDLER( 2848 this_request, 2849 scic_sds_request_state_handler_table, 2850 SCI_BASE_REQUEST_STATE_FINAL 2851 ); 2852 } 2853 2854 // --------------------------------------------------------------------------- 2855 2856 SCI_BASE_STATE_T 2857 scic_sds_request_state_table[SCI_BASE_REQUEST_MAX_STATES] = 2858 { 2859 { 2860 SCI_BASE_REQUEST_STATE_INITIAL, 2861 scic_sds_request_initial_state_enter, 2862 NULL 2863 }, 2864 { 2865 SCI_BASE_REQUEST_STATE_CONSTRUCTED, 2866 scic_sds_request_constructed_state_enter, 2867 NULL 2868 }, 2869 { 2870 SCI_BASE_REQUEST_STATE_STARTED, 2871 scic_sds_request_started_state_enter, 2872 scic_sds_request_started_state_exit 2873 }, 2874 { 2875 SCI_BASE_REQUEST_STATE_COMPLETED, 2876 scic_sds_request_completed_state_enter, 2877 NULL 2878 }, 2879 { 2880 SCI_BASE_REQUEST_STATE_ABORTING, 2881 scic_sds_request_aborting_state_enter, 2882 NULL 2883 }, 2884 { 2885 SCI_BASE_REQUEST_STATE_FINAL, 2886 scic_sds_request_final_state_enter, 2887 NULL 2888 } 2889 }; 2890 2891