xref: /freebsd/sys/dev/isci/scil/scic_sds_request.c (revision 81ad6265)
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, &reg_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