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