2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
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.
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
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.
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.
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.
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
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
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.
55 #include <sys/cdefs.h>
56 __FBSDID("$FreeBSD$");
61 * @brief This file contains the implementation for the operations on an
62 * SCIC_SDS_IO_REQUEST object.
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>
92 #if !defined(DISABLE_ATAPI)
93 #include <dev/isci/scil/scic_sds_stp_packet_request.h>
97 * @struct SCI_SINGLE_LEVEL_LUN
99 * @brief this struct describes the single level LUN structure
102 typedef struct SCI_SINGLE_LEVEL_LUN
105 U8 address_method : 2;
107 U8 second_level_lun[2];
108 U8 third_level_lun[2];
109 U8 forth_level_lun[2];
111 } SCI_SINGLE_LEVEL_LUN_T;
114 //****************************************************************************
115 //* SCIC SDS IO REQUEST CONSTANTS
116 //****************************************************************************
119 * We have no timer requirements for IO requests right now
121 #define SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT (0)
122 #define SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT (0)
124 //****************************************************************************
125 //* SCIC SDS IO REQUEST MACROS
126 //****************************************************************************
129 * This is a helper macro to return the os handle for this request object.
131 #define scic_sds_request_get_user_request(request) \
132 ((request)->user_request)
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
141 #define scic_ssp_io_request_get_object_size() \
143 sizeof(SCI_SSP_COMMAND_IU_T) \
145 + sizeof(SCI_SSP_RESPONSE_IU_T) \
150 * This macro returns the address of the ssp command buffer in the io
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) \
159 * This macro aligns the ssp command buffer in DWORD alignment
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) \
168 * This macro returns the DWORD-aligned ssp command buffer
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) \
177 * This macro returns the address of the ssp response buffer in the io
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) \
187 * This macro aligns the ssp response buffer in DWORD-aligned fashion
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) \
196 * This macro returns the DWORD-aligned ssp response buffer
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) \
205 * This macro returns the address of the task context buffer in the io
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) \
215 * This macro returns the aligned task context buffer
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)) \
224 * This macro returns the address of the sgl elment pairs in the io request
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) \
233 #if !defined(DISABLE_TASK_MANAGEMENT)
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.
239 #define scic_ssp_task_request_get_object_size() \
241 sizeof(SCI_SSP_TASK_IU_T) \
242 + sizeof(SCI_SSP_RESPONSE_IU_T) \
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
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) \
256 * This macro returns the address of the ssp response buffer in the task
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) \
266 * This macro returs the task context buffer for the SSP task request.
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) \
274 #endif // !defined(DISABLE_TASK_MANAGEMENT)
277 //****************************************************************************
278 //* SCIC SDS IO REQUEST PRIVATE METHODS
279 //****************************************************************************
283 * This method will initialize state transition logging for the task request
286 * @param[in] this_request This is the request for which to track state
289 void scic_sds_request_initialize_state_logging(
290 SCIC_SDS_REQUEST_T *this_request
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
306 if (this_request->has_started_substate_machine)
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
322 * This method will stop the state transition logging for the task request
325 * @param[in] this_request The task request object on which to stop state
326 * transition logging.
328 void scic_sds_request_deinitialize_state_logging(
329 SCIC_SDS_REQUEST_T *this_request
332 sci_base_state_machine_logger_deinitialize(
333 &this_request->parent.state_machine_logger,
334 &this_request->parent.state_machine
337 if (this_request->has_started_substate_machine)
339 sci_base_state_machine_logger_deinitialize(
340 &this_request->started_substate_machine_logger,
341 &this_request->started_substate_machine
345 #endif // SCI_LOGGING
348 * This method returns the size required to store an SSP IO request object.
353 U32 scic_sds_ssp_request_get_object_size(void)
355 return sizeof(SCIC_SDS_REQUEST_T)
356 + scic_ssp_io_request_get_object_size()
357 + sizeof(SCU_TASK_CONTEXT_T)
359 + sizeof(SCU_SGL_ELEMENT_PAIR_T) * SCU_MAX_SGL_ELEMENT_PAIRS;
363 * @brief This method returns the sgl element pair for the specificed
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.
371 * @return This method returns a pointer to an SCU_SGL_ELEMENT_PAIR.
373 SCU_SGL_ELEMENT_PAIR_T *scic_sds_request_get_sgl_element_pair(
374 SCIC_SDS_REQUEST_T *this_request,
378 SCU_TASK_CONTEXT_T *task_context;
380 task_context = (SCU_TASK_CONTEXT_T *)this_request->task_context_buffer;
382 if (sgl_pair_index == 0)
384 return &task_context->sgl_pair_ab;
386 else if (sgl_pair_index == 1)
388 return &task_context->sgl_pair_cd;
391 return &this_request->sgl_element_pair_buffer[sgl_pair_index - 2];
395 * @brief This function will build the SGL list for an IO request.
397 * @param[in] this_request This parameter specifies the IO request for which
398 * to build the Scatter-Gather List.
402 void scic_sds_request_build_sgl(
403 SCIC_SDS_REQUEST_T *this_request
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;
413 os_handle = scic_sds_request_get_user_request(this_request);
414 scic_cb_io_request_get_next_sge(os_handle, NULL, &os_sge);
416 while (os_sge != NULL)
419 scic_sds_request_get_sgl_element_pair(this_request, sgl_pair_index);
421 SCU_SGL_COPY(os_handle, scu_sgl_list->A, os_sge);
423 scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
427 SCU_SGL_COPY(os_handle, scu_sgl_list->B, os_sge);
429 scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
433 SCU_SGL_ZERO(scu_sgl_list->B);
436 if (previous_pair != NULL)
438 scic_cb_io_request_get_physical_address(
439 scic_sds_request_get_controller(this_request),
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);
451 previous_pair = scu_sgl_list;
455 if (scu_sgl_list != NULL)
457 scu_sgl_list->next_pair_upper = 0;
458 scu_sgl_list->next_pair_lower = 0;
463 * @brief This method initializes common portions of the io request object.
464 * This includes construction of the SCI_BASE_REQUEST_T parent.
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
481 void scic_sds_general_request_construct(
482 SCIC_SDS_CONTROLLER_T * the_controller,
483 SCIC_SDS_REMOTE_DEVICE_T * the_target,
485 void * user_io_request_object,
486 SCIC_SDS_REQUEST_T * this_request
489 sci_base_request_construct(
490 &this_request->parent,
491 sci_base_object_get_logger(the_controller),
492 scic_sds_request_state_table
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);
505 this_request->sci_status = SCI_SUCCESS;
506 this_request->scu_status = 0;
507 this_request->post_context = 0xFFFFFFFF;
509 this_request->is_task_management_request = FALSE;
511 if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG)
513 this_request->was_tag_assigned_by_user = FALSE;
514 this_request->task_context_buffer = NULL;
518 this_request->was_tag_assigned_by_user = TRUE;
520 this_request->task_context_buffer =
521 scic_sds_controller_get_task_context_buffer(
522 this_request->owning_controller, io_tag);
527 * @brief This method build the remainder of the IO request object.
529 * @pre The scic_sds_general_request_construct() must be called before this
532 * @param[in] this_request This parameter specifies the request object being
537 void scic_sds_ssp_io_request_assign_buffers(
538 SCIC_SDS_REQUEST_T *this_request
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);
550 if (this_request->was_tag_assigned_by_user == FALSE)
552 this_request->task_context_buffer =
553 scic_sds_ssp_request_get_task_context_buffer(this_request);
558 * @brief This method constructs the SSP Command IU data for this io
561 * @param[in] this_request This parameter specifies the request object for
562 * which the SSP command information unit is being built.
567 void scic_sds_io_request_build_ssp_command_iu(
568 SCIC_SDS_REQUEST_T *this_request
571 SCI_SINGLE_LEVEL_LUN_T lun;
572 SCI_SSP_COMMAND_IU_T *command_frame;
578 (SCI_SSP_COMMAND_IU_T *)this_request->command_buffer;
580 os_handle = scic_sds_request_get_user_request(this_request);
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,
591 ((U32 *)command_frame)[2] = 0;
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);
598 command_frame->additional_cdb_length = cdb_length - 16;
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),
605 (cdb_length + 3) / sizeof(U32)
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);
615 #if !defined(DISABLE_TASK_MANAGEMENT)
618 * @brief This method constructs the SSP Task IU data for this io request
621 * @param[in] this_request
626 void scic_sds_task_request_build_ssp_task_iu(
627 SCIC_SDS_REQUEST_T *this_request
630 SCI_SSP_TASK_IU_T *command_frame;
634 (SCI_SSP_TASK_IU_T *)this_request->command_buffer;
636 os_handle = scic_sds_request_get_user_request(this_request);
638 command_frame->lun_upper = 0;
639 command_frame->lun_lower = scic_cb_ssp_task_request_get_lun(os_handle);
641 ((U32 *)command_frame)[2] = 0;
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);
649 #endif // !defined(DISABLE_TASK_MANAGEMENT)
652 * @brief This method is will fill in the SCU Task Context for any type of
655 * @param[in] this_request
656 * @param[in] task_context
661 void scu_ssp_reqeust_construct_task_context(
662 SCIC_SDS_REQUEST_T * this_request,
663 SCU_TASK_CONTEXT_T * task_context
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;
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);
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;
689 task_context->remote_node_index =
690 scic_sds_remote_device_get_index(this_request->target_device);
691 task_context->command_code = 0;
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;
700 task_context->address_modifier = 0;
702 //task_context->type.ssp.tag = this_request->io_tag;
703 task_context->task_phase = 0x01;
705 if (this_request->was_tag_assigned_by_user)
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
711 scic_sds_controller_get_protocol_engine_group(owning_controller)
712 << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
715 scic_sds_port_get_index(target_port)
716 << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
718 | scic_sds_io_tag_get_index(this_request->io_tag)
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
727 scic_sds_controller_get_protocol_engine_group(owning_controller)
728 << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
731 scic_sds_port_get_index(target_port)
732 << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
734 // This is not assigned because we have to wait until we get a TCi
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),
742 this_request->command_buffer,
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);
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),
755 this_request->response_buffer,
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);
766 * @brief This method is will fill in the SCU Task Context for a SSP IO
769 * @param[in] this_request
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
780 SCU_TASK_CONTEXT_T *task_context;
782 task_context = scic_sds_request_get_task_context(this_request);
784 scu_ssp_reqeust_construct_task_context(this_request, task_context);
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;
789 switch (data_direction)
791 case SCI_IO_REQUEST_DATA_IN:
792 case SCI_IO_REQUEST_NO_DATA:
793 task_context->task_type = SCU_TASK_TYPE_IOREAD;
795 case SCI_IO_REQUEST_DATA_OUT:
796 task_context->task_type = SCU_TASK_TYPE_IOWRITE;
800 task_context->transfer_length_bytes = transfer_length_bytes;
802 if (task_context->transfer_length_bytes > 0)
804 scic_sds_request_build_sgl(this_request);
808 #if !defined(DISABLE_TASK_MANAGEMENT)
811 * @brief This method will fill in the remainder of the io request object
812 * for SSP Task requests.
814 * @param[in] this_request
818 void scic_sds_ssp_task_request_assign_buffers(
819 SCIC_SDS_REQUEST_T *this_request
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;
829 if (this_request->was_tag_assigned_by_user == FALSE)
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);
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
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
851 * @param[in] this_request This parameter specifies the task request object
857 void scu_ssp_task_request_construct_task_context(
858 SCIC_SDS_REQUEST_T *this_request
861 SCU_TASK_CONTEXT_T *task_context;
863 task_context = scic_sds_request_get_task_context(this_request);
865 scu_ssp_reqeust_construct_task_context(this_request, task_context);
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);
875 #endif // !defined(DISABLE_TASK_MANAGEMENT)
877 #if !defined(DISABLE_PASS_THROUGH)
879 * @brief This method constructs the SSP Command IU data for this
880 * ssp passthrough comand request object.
882 * @param[in] this_request This parameter specifies the request object for
883 * which the SSP command information unit is being built.
885 * @return SCI_STATUS, returns invalid parameter is cdb > 16
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
893 SCI_SSP_COMMAND_IU_T *command_frame;
894 U32 cdb_length = 0, additional_cdb_length = 0;
895 U8 *cdb_buffer, *additional_cdb_buffer;
897 SCI_STATUS sci_status = SCI_SUCCESS;
898 SCI_SINGLE_LEVEL_LUN_T lun;
901 (SCI_SSP_COMMAND_IU_T *)this_request->command_buffer;
904 ssp_passthru_cb->scic_cb_ssp_passthru_get_lun (
908 memset(&lun, 0, sizeof(lun));
909 lun.lun_number = *scsi_lun;
910 scic_word_copy_with_swap(
911 (U32 *)command_frame->lun,
915 ((U32 *)command_frame)[2] = 0;
917 ssp_passthru_cb->scic_cb_ssp_passthru_get_cdb(
921 &additional_cdb_length,
922 &additional_cdb_buffer
925 command_frame->additional_cdb_length = additional_cdb_length;
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)
933 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
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),
940 (cdb_length + 3) / sizeof(U32)
943 /////-------- End fo TODO
945 command_frame->enable_first_burst = 0;
946 command_frame->task_priority = 0; //todo: check with Richard ????
948 //get the task attribute
949 command_frame->task_attribute = ssp_passthru_cb->scic_cb_ssp_passthru_get_task_attribute (
955 #endif // !defined(DISABLE_PASS_THROUGH)
957 //****************************************************************************
958 //* SCIC Interface Implementation
959 //****************************************************************************
961 #if !defined(DISABLE_TASK_MANAGEMENT)
963 * This method returns the size required to store an SSP task request object.
968 U32 scic_sds_ssp_task_request_get_object_size(void)
970 return sizeof(SCIC_SDS_REQUEST_T)
971 + scic_ssp_task_request_get_object_size()
972 + sizeof(SCU_TASK_CONTEXT_T)
977 U32 scic_task_request_get_object_size(void)
979 U32 ssp_task_request_size;
980 U32 stp_task_request_size;
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();
985 return MAX(ssp_task_request_size, stp_task_request_size);
988 #endif // !defined(DISABLE_TASK_MANAGEMENT)
990 // ---------------------------------------------------------------------------
992 U32 scic_io_request_get_object_size(void)
994 U32 ssp_request_size;
995 U32 stp_request_size;
996 U32 smp_request_size;
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();
1002 return MAX(ssp_request_size, MAX(stp_request_size, smp_request_size));
1005 // ---------------------------------------------------------------------------
1007 SCIC_TRANSPORT_PROTOCOL scic_io_request_get_protocol(
1008 SCI_IO_REQUEST_HANDLE_T scic_io_request
1011 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
1012 return this_request->protocol;
1015 // ---------------------------------------------------------------------------
1017 U32 scic_sds_request_get_min_timer_count(void)
1019 return SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT;
1022 // ---------------------------------------------------------------------------
1024 U32 scic_sds_request_get_max_timer_count(void)
1026 return SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT;
1029 // ---------------------------------------------------------------------------
1031 SCI_STATUS scic_io_request_construct(
1032 SCI_CONTROLLER_HANDLE_T scic_controller,
1033 SCI_REMOTE_DEVICE_HANDLE_T scic_remote_device,
1035 void * user_io_request_object,
1036 void * scic_io_request_memory,
1037 SCI_IO_REQUEST_HANDLE_T * new_scic_io_request_handle
1040 SCI_STATUS status = SCI_SUCCESS;
1041 SCIC_SDS_REQUEST_T * this_request;
1042 SMP_DISCOVER_RESPONSE_PROTOCOLS_T device_protocol;
1044 this_request = (SCIC_SDS_REQUEST_T * )scic_io_request_memory;
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
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,
1062 user_io_request_object,
1067 scic_sds_remote_device_get_index((SCIC_SDS_REMOTE_DEVICE_T *)scic_remote_device)
1068 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
1071 return SCI_FAILURE_INVALID_REMOTE_DEVICE;
1074 scic_remote_device_get_protocols(scic_remote_device, &device_protocol);
1076 if (device_protocol.u.bits.attached_ssp_target)
1078 scic_sds_ssp_io_request_assign_buffers(this_request);
1080 else if (device_protocol.u.bits.attached_stp_target)
1082 scic_sds_stp_request_assign_buffers(this_request);
1083 memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
1085 else if (device_protocol.u.bits.attached_smp_target)
1087 scic_sds_smp_request_assign_buffers(this_request);
1088 memset(this_request->command_buffer, 0, sizeof(SMP_REQUEST_T));
1092 status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
1095 if (status == SCI_SUCCESS)
1098 this_request->task_context_buffer,
1100 SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, sgl_pair_ab)
1102 *new_scic_io_request_handle = scic_io_request_memory;
1108 // ---------------------------------------------------------------------------
1110 #if !defined(DISABLE_TASK_MANAGEMENT)
1112 SCI_STATUS scic_task_request_construct(
1113 SCI_CONTROLLER_HANDLE_T controller,
1114 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
1116 void *user_io_request_object,
1117 void *scic_task_request_memory,
1118 SCI_TASK_REQUEST_HANDLE_T *new_scic_task_request_handle
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;
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
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,
1142 user_io_request_object,
1146 scic_remote_device_get_protocols(remote_device, &device_protocol);
1148 if (device_protocol.u.bits.attached_ssp_target)
1150 scic_sds_ssp_task_request_assign_buffers(this_request);
1152 this_request->has_started_substate_machine = TRUE;
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
1162 else if (device_protocol.u.bits.attached_stp_target)
1164 scic_sds_stp_request_assign_buffers(this_request);
1168 status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
1171 if (status == SCI_SUCCESS)
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;
1181 #endif // !defined(DISABLE_TASK_MANAGEMENT)
1183 // ---------------------------------------------------------------------------
1185 SCI_STATUS scic_io_request_construct_basic_ssp(
1186 SCI_IO_REQUEST_HANDLE_T scic_io_request
1190 SCIC_SDS_REQUEST_T *this_request;
1191 this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
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",
1200 this_request->protocol = SCIC_SSP_PROTOCOL;
1202 os_handle = scic_sds_request_get_user_request(this_request);
1204 scu_ssp_io_request_construct_task_context(
1206 scic_cb_io_request_get_data_direction(os_handle),
1207 scic_cb_io_request_get_transfer_length(os_handle)
1211 scic_sds_io_request_build_ssp_command_iu(this_request);
1213 scic_sds_request_initialize_state_logging(this_request);
1215 sci_base_state_machine_change_state(
1216 &this_request->parent.state_machine,
1217 SCI_BASE_REQUEST_STATE_CONSTRUCTED
1223 // ---------------------------------------------------------------------------
1225 #if !defined(DISABLE_TASK_MANAGEMENT)
1227 SCI_STATUS scic_task_request_construct_ssp(
1228 SCI_TASK_REQUEST_HANDLE_T scic_task_request
1231 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)
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",
1241 // Construct the SSP Task SCU Task Context
1242 scu_ssp_task_request_construct_task_context(this_request);
1244 // Fill in the SSP Task IU
1245 scic_sds_task_request_build_ssp_task_iu(this_request);
1247 scic_sds_request_initialize_state_logging(this_request);
1249 sci_base_state_machine_change_state(
1250 &this_request->parent.state_machine,
1251 SCI_BASE_REQUEST_STATE_CONSTRUCTED
1257 #endif // !defined(DISABLE_TASK_MANAGEMENT)
1259 // ---------------------------------------------------------------------------
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
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
1273 /// @todo Implement after 1.1
1277 // ---------------------------------------------------------------------------
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
1285 SCI_STATUS status = SCI_SUCCESS;
1286 SCIC_SDS_REQUEST_T * this_request;
1288 this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
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",
1297 //build the task context from the pass through buffer
1298 scu_ssp_io_request_construct_task_context(
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)
1304 //build the ssp command iu from the pass through buffer
1305 status = scic_sds_io_request_build_ssp_command_iu_pass_through (
1309 if (status != SCI_SUCCESS)
1314 /* initialize the logging */
1315 scic_sds_request_initialize_state_logging(this_request);
1317 sci_base_state_machine_change_state(
1318 &this_request->parent.state_machine,
1319 SCI_BASE_REQUEST_STATE_CONSTRUCTED
1324 #endif // !defined(DISABLE_PASS_THROUGH)
1326 // ---------------------------------------------------------------------------
1328 #if !defined(DISABLE_TASK_MANAGEMENT)
1330 SCI_STATUS scic_task_request_construct_sata(
1331 SCI_TASK_REQUEST_HANDLE_T scic_task_request
1335 SCIC_SDS_REQUEST_T * this_request;
1338 this_request = (SCIC_SDS_REQUEST_T *)scic_task_request;
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",
1348 scic_cb_request_get_sat_protocol(this_request->user_request);
1350 this_request->sat_protocol = sat_protocol;
1352 switch (sat_protocol)
1354 case SAT_PROTOCOL_ATA_HARD_RESET:
1355 case SAT_PROTOCOL_SOFT_RESET:
1356 status = scic_sds_stp_soft_reset_request_construct(this_request);
1359 case SAT_PROTOCOL_PIO_DATA_IN:
1360 status = scic_sds_stp_pio_request_construct(this_request, sat_protocol, FALSE);
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
1371 status = SCI_FAILURE;
1375 if (status == SCI_SUCCESS)
1377 scic_sds_request_initialize_state_logging(this_request);
1379 sci_base_state_machine_change_state(
1380 &this_request->parent.state_machine,
1381 SCI_BASE_REQUEST_STATE_CONSTRUCTED
1388 #endif // !defined(DISABLE_TASK_MANAGEMENT)
1390 // ---------------------------------------------------------------------------
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
1398 SCI_STATUS status = SCI_SUCCESS;
1399 SCIC_SDS_REQUEST_T * this_request;
1402 U32 transfer_length;
1403 SCI_IO_REQUEST_DATA_DIRECTION data_direction;
1405 this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
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",
1414 passthru_cb->scic_cb_stp_passthru_get_register_fis(this_request, ®_fis);
1416 if (reg_fis == NULL)
1418 status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
1421 if (status == SCI_SUCCESS)
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));
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);
1431 status = scic_sds_io_request_construct_sata(
1440 this_request->protocol = SCIC_STP_PROTOCOL;
1445 #endif // !defined(DISABLE_PASS_THROUGH)
1447 // ---------------------------------------------------------------------------
1449 U16 scic_io_request_get_io_tag(
1450 SCI_IO_REQUEST_HANDLE_T scic_io_request
1453 SCIC_SDS_REQUEST_T *this_request;
1454 this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
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",
1463 return this_request->io_tag;
1466 // ---------------------------------------------------------------------------
1468 U32 scic_request_get_controller_status(
1469 SCI_IO_REQUEST_HANDLE_T io_request
1472 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T*)io_request;
1473 return this_request->scu_status;
1476 U32 scic_request_get_sci_status(
1477 SCI_IO_REQUEST_HANDLE_T io_request
1480 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T*)io_request;
1481 return this_request->sci_status;
1484 // ---------------------------------------------------------------------------
1486 void * scic_io_request_get_rx_frame(
1487 SCI_IO_REQUEST_HANDLE_T scic_io_request,
1491 void * frame_buffer = NULL;
1492 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
1494 ASSERT(offset < SCU_UNSOLICITED_FRAME_BUFFER_SIZE);
1496 if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX)
1498 scic_sds_unsolicited_frame_control_get_buffer(
1499 &(this_request->owning_controller->uf_control),
1500 this_request->saved_rx_frame_index,
1505 return frame_buffer;
1508 void * scic_io_request_get_command_iu_address(
1509 SCI_IO_REQUEST_HANDLE_T scic_io_request
1512 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
1514 return this_request->command_buffer;
1517 // ---------------------------------------------------------------------------
1519 void * scic_io_request_get_response_iu_address(
1520 SCI_IO_REQUEST_HANDLE_T scic_io_request
1523 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
1525 return this_request->response_buffer;
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
1535 SCIC_SDS_REQUEST_T * scic_sds_request;
1537 scic_sds_request = (SCIC_SDS_REQUEST_T *) scic_io_request;
1539 if ( SMU_AMR_READ (scic_sds_request->owning_controller) == 0)
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,
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))
1559 //****************************************************************************
1560 //* SCIC SDS Interface Implementation
1561 //****************************************************************************
1564 * This method invokes the base state start request handler for the
1565 * SCIC_SDS_IO_REQUEST_T object.
1567 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
1568 * start operation is to be executed.
1570 * @return SCI_STATUS
1572 SCI_STATUS scic_sds_request_start(
1573 SCIC_SDS_REQUEST_T *this_request
1577 this_request->device_sequence
1578 == scic_sds_remote_device_get_sequence(this_request->target_device)
1581 return this_request->state_handlers->parent.start_handler(
1582 &this_request->parent
1590 * This method invokes the base state terminate request handber for the
1591 * SCIC_SDS_IO_REQUEST_T object.
1593 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
1594 * start operation is to be executed.
1596 * @return SCI_STATUS
1598 SCI_STATUS scic_sds_io_request_terminate(
1599 SCIC_SDS_REQUEST_T *this_request
1602 return this_request->state_handlers->parent.abort_handler(
1603 &this_request->parent);
1607 * This method invokes the base state request completion handler for the
1608 * SCIC_SDS_IO_REQUEST_T object.
1610 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
1611 * start operation is to be executed.
1613 * @return SCI_STATUS
1615 SCI_STATUS scic_sds_io_request_complete(
1616 SCIC_SDS_REQUEST_T *this_request
1619 return this_request->state_handlers->parent.complete_handler(
1620 &this_request->parent);
1624 * This method invokes the core state handler for the SCIC_SDS_IO_REQUEST_T
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
1632 * @return SCI_STATUS
1634 SCI_STATUS scic_sds_io_request_event_handler(
1635 SCIC_SDS_REQUEST_T * this_request,
1639 return this_request->state_handlers->event_handler(this_request, event_code);
1643 * This method invokes the core state frame handler for the
1644 * SCIC_SDS_IO_REQUEST_T object.
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
1651 * @return SCI_STATUS
1653 SCI_STATUS scic_sds_io_request_frame_handler(
1654 SCIC_SDS_REQUEST_T * this_request,
1658 return this_request->state_handlers->frame_handler(this_request, frame_index);
1662 * This method invokes the core state task complete handler for the
1663 * SCIC_SDS_IO_REQUEST_T object.
1665 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the task
1666 * start operation is to be executed.
1668 * @return SCI_STATUS
1670 SCI_STATUS scic_sds_task_request_complete(
1671 SCIC_SDS_REQUEST_T *this_request
1674 return this_request->state_handlers->parent.complete_handler(&this_request->parent);
1677 //****************************************************************************
1678 //* SCIC SDS PROTECTED METHODS
1679 //****************************************************************************
1682 * @brief This method copies response data for requests returning response
1683 * data instead of sense data.
1685 * @param[in] this_request This parameter specifies the request object for
1686 * which to copy the response data.
1690 void scic_sds_io_request_copy_response(
1691 SCIC_SDS_REQUEST_T *this_request
1694 void * response_buffer;
1695 U32 user_response_length;
1696 U32 core_response_length;
1697 SCI_SSP_RESPONSE_IU_T * ssp_response;
1699 ssp_response = (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
1701 response_buffer = scic_cb_ssp_task_request_get_response_data_address(
1702 this_request->user_request
1705 user_response_length = scic_cb_ssp_task_request_get_response_data_length(
1706 this_request->user_request
1709 core_response_length = sci_ssp_get_response_data_length(
1710 ssp_response->response_data_length
1713 user_response_length = MIN(user_response_length, core_response_length);
1715 memcpy(response_buffer, ssp_response->data, user_response_length);
1718 //******************************************************************************
1719 //* REQUEST STATE MACHINE
1720 //******************************************************************************
1722 //*****************************************************************************
1723 //* DEFAULT STATE HANDLERS
1724 //*****************************************************************************
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.
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
1735 * @return SCI_STATUS
1736 * @retval SCI_FAILURE_INVALID_STATE
1738 SCI_STATUS scic_sds_request_default_start_handler(
1739 SCI_BASE_REQUEST_T *request
1743 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
1745 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1746 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1747 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
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)
1754 return SCI_FAILURE_INVALID_STATE;
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.
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
1766 * @return SCI_STATUS
1767 * @retval SCI_FAILURE_INVALID_STATE
1769 SCI_STATUS scic_sds_request_default_abort_handler(
1770 SCI_BASE_REQUEST_T *request
1774 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
1776 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1777 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1778 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
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)
1785 return SCI_FAILURE_INVALID_STATE;
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.
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
1797 * @return SCI_STATUS
1798 * @retval SCI_FAILURE_INVALID_STATE
1800 SCI_STATUS scic_sds_request_default_complete_handler(
1801 SCI_BASE_REQUEST_T *request
1805 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
1807 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1808 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1809 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
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)
1816 return SCI_FAILURE_INVALID_STATE;
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.
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
1828 * @return SCI_STATUS
1829 * @retval SCI_FAILURE_INVALID_STATE
1831 SCI_STATUS scic_sds_request_default_destruct_handler(
1832 SCI_BASE_REQUEST_T *request
1836 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
1838 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1839 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1840 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
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)
1847 return SCI_FAILURE_INVALID_STATE;
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.
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
1859 * @return SCI_STATUS
1860 * @retval SCI_FAILURE_INVALID_STATE
1862 SCI_STATUS scic_sds_request_default_tc_completion_handler(
1863 SCIC_SDS_REQUEST_T * this_request,
1868 sci_base_object_get_logger(this_request),
1870 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1871 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1872 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
1874 "SCIC IO Request given task completion notification %x while in wrong state %d\n",
1876 sci_base_state_machine_get_state(&this_request->parent.state_machine)
1879 return SCI_FAILURE_INVALID_STATE;
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.
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
1892 * @return SCI_STATUS
1893 * @retval SCI_FAILURE_INVALID_STATE
1895 SCI_STATUS scic_sds_request_default_event_handler(
1896 SCIC_SDS_REQUEST_T * this_request,
1901 sci_base_object_get_logger(this_request),
1903 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1904 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1905 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
1907 "SCIC IO Request given event code notification %x while in wrong state %d\n",
1909 sci_base_state_machine_get_state(&this_request->parent.state_machine)
1912 return SCI_FAILURE_INVALID_STATE;
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.
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
1924 * @return SCI_STATUS
1925 * @retval SCI_FAILURE_INVALID_STATE
1927 SCI_STATUS scic_sds_request_default_frame_handler(
1928 SCIC_SDS_REQUEST_T * this_request,
1933 sci_base_object_get_logger(this_request),
1935 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1936 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1937 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
1939 "SCIC IO Request given unexpected frame %x while in state %d\n",
1941 sci_base_state_machine_get_state(&this_request->parent.state_machine)
1944 scic_sds_controller_release_frame(
1945 this_request->owning_controller, frame_index);
1947 return SCI_FAILURE_INVALID_STATE;
1950 //*****************************************************************************
1951 //* CONSTRUCTED STATE HANDLERS
1952 //*****************************************************************************
1955 * This method implements the action taken when a constructed
1956 * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request.
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.
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
1967 * @return SCI_STATUS
1968 * @retval SCI_SUCCESS
1969 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES
1972 SCI_STATUS scic_sds_request_constructed_state_start_handler(
1973 SCI_BASE_REQUEST_T *request
1976 SCU_TASK_CONTEXT_T *task_context;
1977 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
1979 if (this_request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG)
1981 this_request->io_tag =
1982 scic_controller_allocate_io_tag(this_request->owning_controller);
1985 // Record the IO Tag in the request
1986 if (this_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)
1988 task_context = this_request->task_context_buffer;
1990 task_context->task_index = scic_sds_io_tag_get_index(this_request->io_tag);
1992 switch (task_context->protocol_type)
1994 case SCU_TASK_CONTEXT_PROTOCOL_SMP:
1995 case SCU_TASK_CONTEXT_PROTOCOL_SSP:
1997 task_context->type.ssp.tag = this_request->io_tag;
1998 task_context->type.ssp.target_port_transfer_tag = 0xFFFF;
2001 case SCU_TASK_CONTEXT_PROTOCOL_STP:
2003 //task_context->type.stp.ncq_tag = this_request->ncq_tag;
2006 case SCU_TASK_CONTEXT_PROTOCOL_NONE:
2007 /// @todo When do we set no protocol type?
2011 // This should never happen since we build the IO requests
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)
2019 scic_sds_controller_copy_task_context(
2020 this_request->owning_controller, this_request
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);
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
2036 return SCI_FAILURE_INSUFFICIENT_RESOURCES;
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.
2043 * Since the request has not yet been posted to the hardware the request
2044 * transitions to the completed state.
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
2050 * @return SCI_STATUS
2051 * @retval SCI_SUCCESS
2054 SCI_STATUS scic_sds_request_constructed_state_abort_handler(
2055 SCI_BASE_REQUEST_T *request
2058 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
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(
2064 SCU_TASK_DONE_TASK_ABORT,
2065 SCI_FAILURE_IO_TERMINATED
2068 sci_base_state_machine_change_state(
2069 &this_request->parent.state_machine,
2070 SCI_BASE_REQUEST_STATE_COMPLETED
2076 //*****************************************************************************
2077 //* STARTED STATE HANDLERS
2078 //*****************************************************************************
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.
2084 * Since the request has been posted to the hardware the io request state is
2085 * changed to the aborting state.
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
2091 * @return SCI_STATUS
2092 * @retval SCI_SUCCESS
2094 SCI_STATUS scic_sds_request_started_state_abort_handler(
2095 SCI_BASE_REQUEST_T *request
2098 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
2100 if (this_request->has_started_substate_machine)
2102 sci_base_state_machine_stop(&this_request->started_substate_machine);
2105 sci_base_state_machine_change_state(
2106 &this_request->parent.state_machine,
2107 SCI_BASE_REQUEST_STATE_ABORTING
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.
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.
2125 SCI_STATUS scic_sds_request_started_state_tc_completion_handler(
2126 SCIC_SDS_REQUEST_T * this_request,
2131 SCI_SSP_RESPONSE_IU_T * response_buffer;
2134 * @todo Any SDMA return code of other than 0 is bad
2135 * decode 0x003C0000 to determine SDMA status
2137 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
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
2145 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP):
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)
2160 if (response->status == 0)
2162 scic_sds_request_set_status(
2163 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
2168 scic_sds_request_set_status(
2170 SCU_TASK_DONE_CHECK_RESPONSE,
2171 SCI_FAILURE_IO_RESPONSE_VALID
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)
2184 scic_sds_request_set_status(
2186 SCU_TASK_DONE_CHECK_RESPONSE,
2187 SCI_FAILURE_IO_RESPONSE_VALID
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?
2195 (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
2197 response_buffer->data_present & SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK;
2199 if ((data_present == 0x01) || (data_present == 0x02))
2201 scic_sds_request_set_status(
2203 SCU_TASK_DONE_CHECK_RESPONSE,
2204 SCI_FAILURE_IO_RESPONSE_VALID
2209 scic_sds_request_set_status(
2210 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
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)
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
2235 scic_sds_request_set_status(
2237 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
2238 SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
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
2249 scic_sds_request_set_status(
2251 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
2252 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
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(
2270 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
2271 SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
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):
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
2298 scic_sds_request_set_status(
2300 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
2301 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2307 * @todo This is probably wrong for ACK/NAK timeout conditions
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
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.
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.
2327 * If the frame type is not a response buffer an error is logged.
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
2332 * @param[in] frame_index This is the index of the unsolicited frame to be
2335 * @return SCI_STATUS
2336 * @retval SCI_SUCCESS
2337 * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE
2340 SCI_STATUS scic_sds_request_started_state_frame_handler(
2341 SCIC_SDS_REQUEST_T * this_request,
2346 SCI_SSP_FRAME_HEADER_T *frame_header;
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),
2352 (void**) &frame_header
2355 if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME)
2357 SCI_SSP_RESPONSE_IU_T *response_buffer;
2359 status = scic_sds_unsolicited_frame_control_get_buffer(
2360 &(scic_sds_request_get_controller(this_request)->uf_control),
2362 (void**) &response_buffer
2365 scic_word_copy_with_swap(
2366 this_request->response_buffer,
2367 (U32 *)response_buffer,
2368 sizeof(SCI_SSP_RESPONSE_IU_T)
2371 response_buffer = (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
2374 (response_buffer->data_present == 0x01)
2375 || (response_buffer->data_present == 0x02)
2378 scic_sds_request_set_status(
2380 SCU_TASK_DONE_CHECK_RESPONSE,
2381 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2386 scic_sds_request_set_status(
2387 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
2394 // This was not a response frame why did it get forwarded?
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
2403 // In any case we are done with this frame buffer return it to the
2405 scic_sds_controller_release_frame(
2406 this_request->owning_controller, frame_index
2412 //*****************************************************************************
2413 //* COMPLETED STATE HANDLERS
2414 //*****************************************************************************
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.
2421 * This method frees up any io request resources that have been allocated and
2422 * transitions the request to its final state.
2424 * @todo Consider stopping the state machine instead of transitioning to the
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
2431 * @return SCI_STATUS
2432 * @retval SCI_SUCCESS
2435 SCI_STATUS scic_sds_request_completed_state_complete_handler(
2436 SCI_BASE_REQUEST_T *request
2439 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
2441 if (this_request->was_tag_assigned_by_user != TRUE)
2443 scic_controller_free_io_tag(
2444 this_request->owning_controller, this_request->io_tag
2448 if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX)
2450 scic_sds_controller_release_frame(
2451 this_request->owning_controller, this_request->saved_rx_frame_index);
2454 sci_base_state_machine_change_state(
2455 &this_request->parent.state_machine,
2456 SCI_BASE_REQUEST_STATE_FINAL
2459 scic_sds_request_deinitialize_state_logging(this_request);
2464 //*****************************************************************************
2465 //* ABORTING STATE HANDLERS
2466 //*****************************************************************************
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.
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.
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
2480 * @return SCI_STATUS
2481 * @retval SCI_SUCCESS
2484 SCI_STATUS scic_sds_request_aborting_state_abort_handler(
2485 SCI_BASE_REQUEST_T *request
2488 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
2490 sci_base_state_machine_change_state(
2491 &this_request->parent.state_machine,
2492 SCI_BASE_REQUEST_STATE_COMPLETED
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.
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.
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
2510 * @return SCI_STATUS
2511 * @retval SCI_SUCCESS
2514 SCI_STATUS scic_sds_request_aborting_state_tc_completion_handler(
2515 SCIC_SDS_REQUEST_T * this_request,
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
2526 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
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
2534 sci_base_state_machine_change_state(
2535 &this_request->parent.state_machine,
2536 SCI_BASE_REQUEST_STATE_COMPLETED
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?
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.
2553 * This method discards the unsolicited frame since we are waiting for the
2554 * abort task completion.
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
2560 * @return SCI_STATUS
2561 * @retval SCI_SUCCESS
2564 SCI_STATUS scic_sds_request_aborting_state_frame_handler(
2565 SCIC_SDS_REQUEST_T * this_request,
2569 // TODO: Is it even possible to get an unsolicited frame in the aborting state?
2571 scic_sds_controller_release_frame(
2572 this_request->owning_controller, frame_index);
2577 // ---------------------------------------------------------------------------
2579 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
2580 scic_sds_request_state_handler_table[SCI_BASE_REQUEST_MAX_STATES] =
2582 // SCI_BASE_REQUEST_STATE_INITIAL
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
2590 scic_sds_request_default_tc_completion_handler,
2591 scic_sds_request_default_event_handler,
2592 scic_sds_request_default_frame_handler
2594 // SCI_BASE_REQUEST_STATE_CONSTRUCTED
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
2602 scic_sds_request_default_tc_completion_handler,
2603 scic_sds_request_default_event_handler,
2604 scic_sds_request_default_frame_handler
2606 // SCI_BASE_REQUEST_STATE_STARTED
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
2614 scic_sds_request_started_state_tc_completion_handler,
2615 scic_sds_request_default_event_handler,
2616 scic_sds_request_started_state_frame_handler
2618 // SCI_BASE_REQUEST_STATE_COMPLETED
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
2626 scic_sds_request_default_tc_completion_handler,
2627 scic_sds_request_default_event_handler,
2628 scic_sds_request_default_frame_handler
2630 // SCI_BASE_REQUEST_STATE_ABORTING
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
2638 scic_sds_request_aborting_state_tc_completion_handler,
2639 scic_sds_request_default_event_handler,
2640 scic_sds_request_aborting_state_frame_handler,
2642 // SCI_BASE_REQUEST_STATE_FINAL
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
2650 scic_sds_request_default_tc_completion_handler,
2651 scic_sds_request_default_event_handler,
2652 scic_sds_request_default_frame_handler
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.
2662 * @param[in] object This parameter specifies the base object for which the
2663 * state transition is occurring.
2668 void scic_sds_request_initial_state_enter(
2669 SCI_BASE_OBJECT_T *object
2672 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2676 scic_sds_request_state_handler_table,
2677 SCI_BASE_REQUEST_STATE_INITIAL
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.
2686 * @param[in] object The io request object that is to enter the constructed
2692 void scic_sds_request_constructed_state_enter(
2693 SCI_BASE_OBJECT_T *object
2696 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2700 scic_sds_request_state_handler_table,
2701 SCI_BASE_REQUEST_STATE_CONSTRUCTED
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.
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.
2717 void scic_sds_request_started_state_enter(
2718 SCI_BASE_OBJECT_T *object
2721 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2725 scic_sds_request_state_handler_table,
2726 SCI_BASE_REQUEST_STATE_STARTED
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);
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.
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.
2747 void scic_sds_request_started_state_exit(
2748 SCI_BASE_OBJECT_T *object
2751 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2753 if (this_request->has_started_substate_machine == TRUE)
2754 sci_base_state_machine_stop(&this_request->started_substate_machine);
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.
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.
2771 void scic_sds_request_completed_state_enter(
2772 SCI_BASE_OBJECT_T *object
2775 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2779 scic_sds_request_state_handler_table,
2780 SCI_BASE_REQUEST_STATE_COMPLETED
2783 // Tell the SCI_USER that the IO request is complete
2784 if (this_request->is_task_management_request == FALSE)
2786 scic_cb_io_request_complete(
2787 scic_sds_request_get_controller(this_request),
2788 scic_sds_request_get_device(this_request),
2790 this_request->sci_status
2795 scic_cb_task_request_complete(
2796 scic_sds_request_get_controller(this_request),
2797 scic_sds_request_get_device(this_request),
2799 this_request->sci_status
2805 * This method implements the actions taken when entering the
2806 * SCI_BASE_REQUEST_STATE_ABORTING state.
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.
2815 void scic_sds_request_aborting_state_enter(
2816 SCI_BASE_OBJECT_T *object
2819 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2821 // Setting the abort bit in the Task Context is required by the silicon.
2822 this_request->task_context_buffer->abort = 1;
2826 scic_sds_request_state_handler_table,
2827 SCI_BASE_REQUEST_STATE_ABORTING
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.
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.
2843 void scic_sds_request_final_state_enter(
2844 SCI_BASE_OBJECT_T *object
2847 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2851 scic_sds_request_state_handler_table,
2852 SCI_BASE_REQUEST_STATE_FINAL
2856 // ---------------------------------------------------------------------------
2859 scic_sds_request_state_table[SCI_BASE_REQUEST_MAX_STATES] =
2862 SCI_BASE_REQUEST_STATE_INITIAL,
2863 scic_sds_request_initial_state_enter,
2867 SCI_BASE_REQUEST_STATE_CONSTRUCTED,
2868 scic_sds_request_constructed_state_enter,
2872 SCI_BASE_REQUEST_STATE_STARTED,
2873 scic_sds_request_started_state_enter,
2874 scic_sds_request_started_state_exit
2877 SCI_BASE_REQUEST_STATE_COMPLETED,
2878 scic_sds_request_completed_state_enter,
2882 SCI_BASE_REQUEST_STATE_ABORTING,
2883 scic_sds_request_aborting_state_enter,
2887 SCI_BASE_REQUEST_STATE_FINAL,
2888 scic_sds_request_final_state_enter,