xref: /freebsd/sys/dev/isci/scil/scic_sds_stp_request.c (revision b9f654b163bce26de79705e77b872427c9f2afa1)
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 #include <dev/isci/scil/intel_sat.h>
59 #include <dev/isci/scil/intel_sata.h>
60 #include <dev/isci/scil/sci_types.h>
61 #include <dev/isci/scil/scic_remote_device.h>
62 #include <dev/isci/scil/scic_user_callback.h>
63 #include <dev/isci/scil/scic_sds_controller.h>
64 #include <dev/isci/scil/scic_sds_remote_device.h>
65 #include <dev/isci/scil/scic_sds_stp_request.h>
66 #include <dev/isci/scil/scic_sds_stp_pio_request.h>
67 #include <dev/isci/scil/scic_sds_logger.h>
68 #include <dev/isci/sci_environment.h>
69 #include <dev/isci/scil/sci_base_state_machine.h>
70 #include <dev/isci/scil/scu_task_context.h>
71 #include <dev/isci/scil/intel_ata.h>
72 #include <dev/isci/scil/sci_util.h>
73 #include <dev/isci/scil/scic_sds_logger.h>
74 #include <dev/isci/scil/scic_sds_request.h>
75 #include <dev/isci/scil/scic_sds_stp_request.h>
76 #include <dev/isci/scil/scu_completion_codes.h>
77 #include <dev/isci/scil/scu_event_codes.h>
78 #include <dev/isci/scil/sci_base_state.h>
79 #include <dev/isci/scil/scic_sds_unsolicited_frame_control.h>
80 #include <dev/isci/scil/scic_io_request.h>
81 
82 #if !defined(DISABLE_ATAPI)
83 #include <dev/isci/scil/scic_sds_stp_packet_request.h>
84 #endif
85 
86 /**
87  * This macro returns the address of the stp h2d reg fis buffer in the io
88  * request memory
89  */
90 #define scic_sds_stp_request_get_h2d_reg_buffer_unaligned(memory) \
91    ((SATA_FIS_REG_H2D_T *)( \
92       ((char *)(memory)) + sizeof(SCIC_SDS_STP_REQUEST_T) \
93    ))
94 
95 /**
96  * This macro aligns the stp command buffer in DWORD alignment
97 */
98 #define scic_sds_stp_request_align_h2d_reg_buffer(address) \
99    ((SATA_FIS_REG_H2D_T *)( \
100       (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
101          & ~(sizeof(U32)- 1) \
102       ))
103 
104 /**
105  * This macro returns the DWORD-aligned stp command buffer
106 */
107 #define scic_sds_stp_request_get_h2d_reg_buffer(memory) \
108    ((SATA_FIS_REG_H2D_T *)  \
109        ((char *)scic_sds_stp_request_align_h2d_reg_buffer( \
110        (char *) scic_sds_stp_request_get_h2d_reg_buffer_unaligned(memory) \
111    )))
112 
113 /**
114  * This macro returns the address of the stp response buffer in the io
115  * request memory
116  */
117 #define scic_sds_stp_request_get_response_buffer_unaligned(memory) \
118    ((SATA_FIS_REG_D2H_T *)( \
119          ((char *)(scic_sds_stp_request_get_h2d_reg_buffer(memory))) \
120        + sizeof(SATA_FIS_REG_H2D_T) \
121    ))
122 
123 
124 /**
125  * This macro aligns the stp response buffer in DWORD alignment
126 */
127 #define scic_sds_stp_request_align_response_buffer(address) \
128    ((SATA_FIS_REG_D2H_T *)( \
129       (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
130          & ~(sizeof(U32)- 1) \
131    ))
132 
133 /**
134  * This macro returns the DWORD-aligned stp response buffer
135 */
136 #define scic_sds_stp_request_get_response_buffer(memory) \
137    ((SATA_FIS_REG_D2H_T *)  \
138       ((char *)scic_sds_stp_request_align_response_buffer( \
139          (char *)scic_sds_stp_request_get_response_buffer_unaligned(memory) \
140    )))
141 
142 
143 /**
144  * This macro returns the address of the task context buffer in the io
145  * request memory
146  */
147 #define scic_sds_stp_request_get_task_context_buffer_unaligned(memory) \
148    ((SCU_TASK_CONTEXT_T *)( \
149         ((char *)(scic_sds_stp_request_get_response_buffer(memory))) \
150       + sizeof(SCI_SSP_RESPONSE_IU_T) \
151    ))
152 
153 /**
154  * This macro returns the aligned task context buffer
155  */
156 #define scic_sds_stp_request_get_task_context_buffer(memory) \
157    ((SCU_TASK_CONTEXT_T *)( \
158       ((char *)scic_sds_request_align_task_context_buffer( \
159          (char *)scic_sds_stp_request_get_task_context_buffer_unaligned(memory)) \
160     )))
161 
162 /**
163  * This macro returns the address of the sgl elment pairs in the io request
164  * memory buffer
165  */
166 #define scic_sds_stp_request_get_sgl_element_buffer(memory) \
167    ((SCU_SGL_ELEMENT_PAIR_T *)( \
168         ((char *)(scic_sds_stp_request_get_task_context_buffer(memory))) \
169       + sizeof(SCU_TASK_CONTEXT_T) \
170     ))
171 
172 
173 /**
174  * This method return the memory space commonly required for STP IO and
175  * task requests.
176  *
177  * @return U32
178  */
179 static
180 U32 scic_sds_stp_common_request_get_object_size(void)
181 {
182    return   sizeof(SCIC_SDS_STP_REQUEST_T)
183           + sizeof(SATA_FIS_REG_H2D_T)
184           + sizeof(U32)
185           + sizeof(SATA_FIS_REG_D2H_T)
186           + sizeof(U32)
187           + sizeof(SCU_TASK_CONTEXT_T)
188           + CACHE_LINE_SIZE;
189 }
190 
191 
192 /**
193  * This method return the memory space required for STP PIO requests.
194  *
195  * @return U32
196  */
197 U32 scic_sds_stp_request_get_object_size(void)
198 {
199    return   scic_sds_stp_common_request_get_object_size()
200           + sizeof(SCU_SGL_ELEMENT_PAIR_T) * SCU_MAX_SGL_ELEMENT_PAIRS;
201 }
202 
203 
204 /**
205  * This method return the memory space required for STP task requests.
206  *
207  * @return U32
208  */
209 U32 scic_sds_stp_task_request_get_object_size(void)
210 {
211    return scic_sds_stp_common_request_get_object_size();
212 }
213 
214 
215 /**
216  *
217  *
218  * @param[in] this_request
219  */
220 void scic_sds_stp_request_assign_buffers(
221    SCIC_SDS_REQUEST_T * request
222 )
223 {
224    SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
225 
226    this_request->parent.command_buffer =
227       scic_sds_stp_request_get_h2d_reg_buffer(this_request);
228    this_request->parent.response_buffer =
229       scic_sds_stp_request_get_response_buffer(this_request);
230    this_request->parent.sgl_element_pair_buffer =
231       scic_sds_stp_request_get_sgl_element_buffer(this_request);
232    this_request->parent.sgl_element_pair_buffer =
233       scic_sds_request_align_sgl_element_buffer(this_request->parent.sgl_element_pair_buffer);
234 
235    if (this_request->parent.was_tag_assigned_by_user == FALSE)
236    {
237       this_request->parent.task_context_buffer =
238          scic_sds_stp_request_get_task_context_buffer(this_request);
239    }
240 }
241 
242 /**
243  * @brief This method is will fill in the SCU Task Context for any type of
244  *        SATA request.  This is called from the various SATA constructors.
245  *
246  * @pre The general io request construction is complete.
247  * @pre The buffer assignment for the command buffer is complete.
248  *
249  * @param[in] this_request The general IO request object which is to be used
250  *       in constructing the SCU task context.
251  * @param[in] task_context The buffer pointer for the SCU task context which
252  *       is being constructed.
253  *
254  * @return none
255  *
256  * @todo Revisit task context construction to determine what is common for
257  *       SSP/SMP/STP task context structures.
258  */
259 void scu_sata_reqeust_construct_task_context(
260    SCIC_SDS_REQUEST_T * this_request,
261    SCU_TASK_CONTEXT_T * task_context
262 )
263 {
264    SCI_PHYSICAL_ADDRESS      physical_address;
265    SCIC_SDS_CONTROLLER_T    *owning_controller;
266    SCIC_SDS_REMOTE_DEVICE_T *target_device;
267    SCIC_SDS_PORT_T          *target_port;
268 
269    owning_controller = scic_sds_request_get_controller(this_request);
270    target_device = scic_sds_request_get_device(this_request);
271    target_port = scic_sds_request_get_port(this_request);
272 
273    // Fill in the TC with the its required data
274    task_context->abort = 0;
275    task_context->priority = SCU_TASK_PRIORITY_NORMAL;
276    task_context->initiator_request = 1;
277    task_context->connection_rate =
278       scic_remote_device_get_connection_rate(target_device);
279    task_context->protocol_engine_index =
280       scic_sds_controller_get_protocol_engine_group(owning_controller);
281    task_context->logical_port_index =
282       scic_sds_port_get_index(target_port);
283    task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP;
284    task_context->valid = SCU_TASK_CONTEXT_VALID;
285    task_context->context_type = SCU_TASK_CONTEXT_TYPE;
286 
287    task_context->remote_node_index =
288       scic_sds_remote_device_get_index(this_request->target_device);
289    task_context->command_code = 0;
290 
291    task_context->link_layer_control = 0;
292    task_context->do_not_dma_ssp_good_response = 1;
293    task_context->strict_ordering = 0;
294    task_context->control_frame = 0;
295    task_context->timeout_enable = 0;
296    task_context->block_guard_enable = 0;
297 
298    task_context->address_modifier = 0;
299    task_context->task_phase = 0x01;
300 
301    task_context->ssp_command_iu_length =
302       (sizeof(SATA_FIS_REG_H2D_T) - sizeof(U32)) / sizeof(U32);
303 
304    // Set the first word of the H2D REG FIS
305    task_context->type.words[0] = *(U32 *)this_request->command_buffer;
306 
307    if (this_request->was_tag_assigned_by_user)
308    {
309       // Build the task context now since we have already read the data
310       this_request->post_context = (
311            SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
312          | (
313                 scic_sds_controller_get_protocol_engine_group(owning_controller)
314              << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
315            )
316          | (
317                  scic_sds_port_get_index(target_port)
318               << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
319            )
320          | scic_sds_io_tag_get_index(this_request->io_tag)
321       );
322    }
323    else
324    {
325       // Build the task context now since we have already read the data
326       this_request->post_context = (
327            SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
328          | (
329                scic_sds_controller_get_protocol_engine_group(owning_controller)
330             << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
331            )
332          | (
333                 scic_sds_port_get_index(target_port)
334              << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
335            )
336          // This is not assigned because we have to wait until we get a TCi
337       );
338    }
339 
340    // Copy the physical address for the command buffer to the SCU Task Context
341    // We must offset the command buffer by 4 bytes because the first 4 bytes are
342    // transferred in the body of the TC
343    scic_cb_io_request_get_physical_address(
344       scic_sds_request_get_controller(this_request),
345       this_request,
346       ((char *)this_request->command_buffer) + sizeof(U32),
347       &physical_address
348    );
349 
350    task_context->command_iu_upper =
351       sci_cb_physical_address_upper(physical_address);
352    task_context->command_iu_lower =
353       sci_cb_physical_address_lower(physical_address);
354 
355    // SATA Requests do not have a response buffer
356    task_context->response_iu_upper = 0;
357    task_context->response_iu_lower = 0;
358 }
359 
360 /**
361  * This method will perform any general sata request construction.
362  *
363  * @todo What part of SATA IO request construction is general?
364  *
365  * @param[in] this_request
366  *
367  * @return none
368  */
369 void scic_sds_stp_non_ncq_request_construct(
370    SCIC_SDS_REQUEST_T * this_request
371 )
372 {
373    this_request->has_started_substate_machine = TRUE;
374 }
375 
376 /**
377  * This method will perform request construction common to all types of
378  * STP requests that are optimized by the silicon (i.e. UDMA, NCQ).
379  *
380  * @param[in,out] this_request This parameter specifies the request to be
381  *                constructed as an optimized request.
382  * @param[in] optimized_task_type This parameter specifies whether the
383  *            request is to be an UDMA request or a NCQ request.
384  *            - A value of 0 indicates UDMA.
385  *            - A value of 1 indicates NCQ.
386  *
387  * @return This method returns an indication as to whether the construction
388  *         was successful.
389  */
390 static
391 void scic_sds_stp_optimized_request_construct(
392    SCIC_SDS_REQUEST_T * this_request,
393    U8                   optimized_task_type,
394    U32                  transfer_length,
395    SCI_IO_REQUEST_DATA_DIRECTION data_direction
396 )
397 {
398    SCU_TASK_CONTEXT_T * task_context = this_request->task_context_buffer;
399 
400    // Build the STP task context structure
401    scu_sata_reqeust_construct_task_context(this_request, task_context);
402 
403    // Copy over the number of bytes to be transferred
404    task_context->transfer_length_bytes = transfer_length;
405 
406    if ( data_direction == SCI_IO_REQUEST_DATA_OUT )
407    {
408       // The difference between the DMA IN and DMA OUT request task type
409       // values are consistent with the difference between FPDMA READ
410       // and FPDMA WRITE values.  Add the supplied task type parameter
411       // to this difference to set the task type properly for this
412       // DATA OUT (WRITE) case.
413       task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT
414                                                      - SCU_TASK_TYPE_DMA_IN);
415    }
416    else
417    {
418       // For the DATA IN (READ) case, simply save the supplied
419       // optimized task type.
420       task_context->task_type = optimized_task_type;
421    }
422 }
423 
424 /**
425  * This method performs the operations common to all SATA/STP requests
426  * utilizing the raw frame method.
427  *
428  * @param[in] this_request This parameter specifies the STP request object
429  *            for which to construct a RAW command frame task context.
430  * @param[in] task_context This parameter specifies the SCU specific
431  *            task context buffer to construct.
432  *
433  * @return none
434  */
435 void scu_stp_raw_request_construct_task_context(
436    SCIC_SDS_STP_REQUEST_T * this_request,
437    SCU_TASK_CONTEXT_T     * task_context
438 )
439 {
440    scu_sata_reqeust_construct_task_context(&this_request->parent, task_context);
441 
442    task_context->control_frame         = 0;
443    task_context->priority              = SCU_TASK_PRIORITY_NORMAL;
444    task_context->task_type             = SCU_TASK_TYPE_SATA_RAW_FRAME;
445    task_context->type.stp.fis_type     = SATA_FIS_TYPE_REGH2D;
446    task_context->transfer_length_bytes = sizeof(SATA_FIS_REG_H2D_T) - sizeof(U32);
447 }
448 
449 /**
450  * This method will construct the STP Non-data request and its associated
451  * TC data.  A non-data request essentially behaves like a 0 length read
452  * request in the SCU.
453  *
454  * @param[in] this_request This parameter specifies the core request
455  *            object to construction into an STP/SATA non-data request.
456  *
457  * @return This method currently always returns SCI_SUCCESS
458  */
459 SCI_STATUS scic_sds_stp_non_data_request_construct(
460    SCIC_SDS_REQUEST_T * this_request
461 )
462 {
463    scic_sds_stp_non_ncq_request_construct(this_request);
464 
465    // Build the STP task context structure
466    scu_stp_raw_request_construct_task_context(
467       (SCIC_SDS_STP_REQUEST_T*) this_request,
468       this_request->task_context_buffer
469    );
470 
471    sci_base_state_machine_construct(
472       &this_request->started_substate_machine,
473       &this_request->parent.parent,
474       scic_sds_stp_request_started_non_data_substate_table,
475       SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE
476    );
477 
478    return SCI_SUCCESS;
479 }
480 
481 
482 SCI_STATUS scic_sds_stp_soft_reset_request_construct(
483    SCIC_SDS_REQUEST_T * this_request
484 )
485 {
486    scic_sds_stp_non_ncq_request_construct(this_request);
487 
488    // Build the STP task context structure
489    scu_stp_raw_request_construct_task_context(
490       (SCIC_SDS_STP_REQUEST_T*) this_request,
491       this_request->task_context_buffer
492    );
493 
494    sci_base_state_machine_construct(
495       &this_request->started_substate_machine,
496       &this_request->parent.parent,
497       scic_sds_stp_request_started_soft_reset_substate_table,
498       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
499    );
500 
501    return SCI_SUCCESS;
502 }
503 
504 /**
505  * @brief This method constructs the SATA request object.
506  *
507  * @param[in] this_request
508  * @param[in] sat_protocol
509  * @param[in] transfer_length
510  * @param[in] data_direction
511  * @param[in] copy_rx_frame
512  * @param[in] do_translate_sgl This parameter specifies whether SGL
513  *            translation should be performed or if the user is handling
514  *            it.
515  *
516  * @return SCI_STATUS
517  */
518 SCI_STATUS scic_sds_io_request_construct_sata(
519    SCIC_SDS_REQUEST_T          * this_request,
520    U8                            sat_protocol,
521    U32                           transfer_length,
522    SCI_IO_REQUEST_DATA_DIRECTION data_direction,
523    BOOL                          copy_rx_frame,
524    BOOL                          do_translate_sgl
525 )
526 {
527    SCI_STATUS  status = SCI_SUCCESS;
528 
529    this_request->protocol = SCIC_STP_PROTOCOL;
530 
531    this_request->sat_protocol = sat_protocol;
532 
533    switch (sat_protocol)
534    {
535    case SAT_PROTOCOL_FPDMA:
536       scic_sds_stp_optimized_request_construct(
537          this_request,
538          SCU_TASK_TYPE_FPDMAQ_READ,
539          transfer_length,
540          data_direction
541       );
542 
543       // Copy over the SGL elements
544       if (do_translate_sgl == TRUE)
545          scic_sds_request_build_sgl(this_request);
546    break;
547 
548    case SAT_PROTOCOL_UDMA_DATA_IN:
549    case SAT_PROTOCOL_UDMA_DATA_OUT:
550       scic_sds_stp_non_ncq_request_construct(this_request);
551 
552       scic_sds_stp_optimized_request_construct(
553          this_request, SCU_TASK_TYPE_DMA_IN, transfer_length, data_direction
554       );
555 
556       // Copy over the SGL elements
557       if (do_translate_sgl == TRUE)
558          scic_sds_request_build_sgl(this_request);
559 
560       sci_base_state_machine_construct(
561          &this_request->started_substate_machine,
562          &this_request->parent.parent,
563          scic_sds_stp_request_started_udma_substate_table,
564          SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
565       );
566    break;
567 
568    case SAT_PROTOCOL_PIO_DATA_IN:
569    case SAT_PROTOCOL_PIO_DATA_OUT:
570       status = scic_sds_stp_pio_request_construct(
571                   this_request, sat_protocol, copy_rx_frame);
572    break;
573 
574    case SAT_PROTOCOL_ATA_HARD_RESET:
575    case SAT_PROTOCOL_SOFT_RESET:
576       status = scic_sds_stp_soft_reset_request_construct(this_request);
577    break;
578 
579    case SAT_PROTOCOL_NON_DATA:
580       status = scic_sds_stp_non_data_request_construct(this_request);
581    break;
582 
583 #if !defined(DISABLE_ATAPI)
584    case SAT_PROTOCOL_PACKET_NON_DATA:
585    case SAT_PROTOCOL_PACKET_DMA_DATA_IN:
586    case SAT_PROTOCOL_PACKET_DMA_DATA_OUT:
587    case SAT_PROTOCOL_PACKET_PIO_DATA_IN:
588    case SAT_PROTOCOL_PACKET_PIO_DATA_OUT:
589       status = scic_sds_stp_packet_request_construct(this_request);
590       if (do_translate_sgl == TRUE)
591          scic_sds_request_build_sgl(this_request);
592    break;
593 #endif
594 
595    case SAT_PROTOCOL_DMA_QUEUED:
596    case SAT_PROTOCOL_DMA:
597    case SAT_PROTOCOL_DEVICE_DIAGNOSTIC:
598    case SAT_PROTOCOL_DEVICE_RESET:
599    case SAT_PROTOCOL_RETURN_RESPONSE_INFO:
600    default:
601       SCIC_LOG_ERROR((
602          sci_base_object_get_logger(this_request),
603          SCIC_LOG_OBJECT_STP_IO_REQUEST,
604          "SCIC IO Request 0x%x received un-handled SAT Protocol %d.\n",
605          this_request, sat_protocol
606       ));
607 
608       status = SCI_FAILURE;
609    break;
610    }
611 
612    if (status == SCI_SUCCESS)
613    {
614       scic_sds_request_initialize_state_logging(this_request);
615 
616       sci_base_state_machine_change_state(
617          &this_request->parent.state_machine,
618          SCI_BASE_REQUEST_STATE_CONSTRUCTED
619       );
620    }
621 
622    return status;
623 }
624 
625 //****************************************************************************
626 //* SCIC Interface Implementation
627 //****************************************************************************
628 
629 void scic_stp_io_request_set_ncq_tag(
630    SCI_IO_REQUEST_HANDLE_T  scic_io_request,
631    U16                      ncq_tag
632 )
633 {
634    /**
635     * @note This could be made to return an error to the user if the user
636     *       attempts to set the NCQ tag in the wrong state.
637     */
638    SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
639    this_request->task_context_buffer->type.stp.ncq_tag = ncq_tag;
640 }
641 
642 // ---------------------------------------------------------------------------
643 
644 void * scic_stp_io_request_get_h2d_reg_address(
645    SCI_IO_REQUEST_HANDLE_T  scic_io_request
646 )
647 {
648    SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
649 
650    return this_request->command_buffer;
651 }
652 
653 // ---------------------------------------------------------------------------
654 
655 void * scic_stp_io_request_get_d2h_reg_address(
656    SCI_IO_REQUEST_HANDLE_T  scic_io_request
657 )
658 {
659    SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)scic_io_request;
660 
661    return &this_request->d2h_reg_fis;
662 }
663 
664 /**
665  * Get the next SGL element from the request.
666  *    - Check on which SGL element pair we are working
667  *    - if working on SLG pair element A
668  *       - advance to element B
669  *    - else
670  *       - check to see if there are more SGL element pairs
671  *           for this IO request
672  *       - if there are more SGL element pairs
673  *          - advance to the next pair and return element A
674  *
675  * @param[in] this_request
676  *
677  * @return SCU_SGL_ELEMENT_T*
678  */
679 SCU_SGL_ELEMENT_T * scic_sds_stp_request_pio_get_next_sgl(
680    SCIC_SDS_STP_REQUEST_T * this_request
681 )
682 {
683    SCU_SGL_ELEMENT_T * current_sgl;
684 
685    if (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A)
686    {
687       if (
688             (this_request->type.pio.request_current.sgl_pair->B.address_lower == 0)
689          && (this_request->type.pio.request_current.sgl_pair->B.address_upper == 0)
690          )
691       {
692          current_sgl = NULL;
693       }
694       else
695       {
696          this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_B;
697          current_sgl = &(this_request->type.pio.request_current.sgl_pair->B);
698       }
699    }
700    else
701    {
702       if (
703             (this_request->type.pio.request_current.sgl_pair->next_pair_lower == 0)
704          && (this_request->type.pio.request_current.sgl_pair->next_pair_upper == 0)
705          )
706       {
707          current_sgl = NULL;
708       }
709       else
710       {
711          this_request->type.pio.request_current.sgl_pair =
712             scic_sds_request_get_sgl_element_pair(
713                &(this_request->parent),
714                ++this_request->type.pio.sgl_pair_index
715             );
716 
717          this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A;
718 
719          current_sgl = &(this_request->type.pio.request_current.sgl_pair->A);
720       }
721    }
722 
723    return current_sgl;
724 }
725 
726 /**
727  * This method will construct the SATA PIO request.
728  *
729  * @param[in] scic_io_request The core request object which is cast to a SATA
730  *            PIO request object.
731  *
732  * @return This method returns an indication as to whether the construction
733  *         was successful.
734  * @retval SCI_SUCCESS Currently this method always returns this value.
735  */
736 SCI_STATUS scic_sds_stp_pio_request_construct(
737    SCIC_SDS_REQUEST_T  * scic_io_request,
738    U8                    sat_protocol,
739    BOOL                  copy_rx_frame
740 )
741 {
742    SCIC_SDS_STP_REQUEST_T * this_request;
743 
744    this_request = (SCIC_SDS_STP_REQUEST_T *)scic_io_request;
745 
746    scic_sds_stp_non_ncq_request_construct(&this_request->parent);
747 
748    scu_stp_raw_request_construct_task_context(
749       this_request, this_request->parent.task_context_buffer
750    );
751 
752    this_request->type.pio.current_transfer_bytes = 0;
753    this_request->type.pio.ending_error = 0;
754    this_request->type.pio.ending_status = 0;
755 
756    this_request->type.pio.request_current.sgl_offset = 0;
757    this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A;
758    this_request->type.pio.sat_protocol = sat_protocol;
759    this_request->type.pio.sgl_pair_index = 0;
760 
761    if ((copy_rx_frame) || (sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT))
762    {
763       scic_sds_request_build_sgl(&this_request->parent);
764       // Since the IO request copy of the TC contains the same data as
765       // the actual TC this pointer is vaild for either.
766       this_request->type.pio.request_current.sgl_pair =
767          &this_request->parent.task_context_buffer->sgl_pair_ab;
768    }
769    else
770    {
771       // The user does not want the data copied to the SGL buffer location
772       this_request->type.pio.request_current.sgl_pair = NULL;
773    }
774 
775    sci_base_state_machine_construct(
776       &this_request->parent.started_substate_machine,
777       &this_request->parent.parent.parent,
778       scic_sds_stp_request_started_pio_substate_table,
779       SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
780    );
781 
782    return SCI_SUCCESS;
783 }
784 
785 //******************************************************************************
786 //* STP NON-DATA STATE MACHINE
787 //******************************************************************************
788 
789 /**
790  * This method processes a TC completion.  The expected TC completion is
791  * for the transmission of the H2D register FIS containing the SATA/STP
792  * non-data request.
793  *
794  * @param[in] this_request
795  * @param[in] completion_code
796  *
797  * @return This method always successfully processes the TC completion.
798  * @retval SCI_SUCCESS This value is always returned.
799  */
800 static
801 SCI_STATUS scic_sds_stp_request_non_data_await_h2d_tc_completion_handler(
802    SCIC_SDS_REQUEST_T * this_request,
803    U32                  completion_code
804 )
805 {
806    SCIC_LOG_TRACE((
807       sci_base_object_get_logger(this_request),
808       SCIC_LOG_OBJECT_STP_IO_REQUEST,
809       "scic_sds_stp_request_non_data_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n",
810       this_request, completion_code
811    ));
812 
813    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
814    {
815    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
816       scic_sds_request_set_status(
817          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
818       );
819 
820       sci_base_state_machine_change_state(
821          &this_request->started_substate_machine,
822          SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE
823       );
824       break;
825 
826    default:
827       // All other completion status cause the IO to be complete.  If a NAK
828       // was received, then it is up to the user to retry the request.
829       scic_sds_request_set_status(
830          this_request,
831          SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
832          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
833       );
834 
835       sci_base_state_machine_change_state(
836          &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
837       );
838       break;
839    }
840 
841    return SCI_SUCCESS;
842 }
843 
844 /**
845  * This method processes frames received from the target while waiting
846  * for a device to host register FIS.  If a non-register FIS is received
847  * during this time, it is treated as a protocol violation from an
848  * IO perspective.
849  *
850  * @param[in] request This parameter specifies the request for which a
851  *            frame has been received.
852  * @param[in] frame_index This parameter specifies the index of the frame
853  *            that has been received.
854  *
855  * @return Indicate if the received frame was processed successfully.
856  */
857 static
858 SCI_STATUS scic_sds_stp_request_non_data_await_d2h_frame_handler(
859    SCIC_SDS_REQUEST_T * request,
860    U32                  frame_index
861 )
862 {
863    SCI_STATUS               status;
864    SATA_FIS_HEADER_T      * frame_header;
865    U32                    * frame_buffer;
866    SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
867 
868    // Save off the controller, so that we do not touch the request after it
869    //  is completed.
870    SCIC_SDS_CONTROLLER_T  * owning_controller = this_request->parent.owning_controller;
871 
872    SCIC_LOG_TRACE((
873       sci_base_object_get_logger(this_request),
874       SCIC_LOG_OBJECT_STP_IO_REQUEST,
875       "scic_sds_stp_request_non_data_await_d2h_frame_handler(0x%x, 0x%x) enter\n",
876       this_request, frame_index
877    ));
878 
879    status = scic_sds_unsolicited_frame_control_get_header(
880                &(owning_controller->uf_control),
881                frame_index,
882                (void**) &frame_header
883             );
884 
885    if (status == SCI_SUCCESS)
886    {
887       switch (frame_header->fis_type)
888       {
889       case SATA_FIS_TYPE_REGD2H:
890          scic_sds_unsolicited_frame_control_get_buffer(
891             &(owning_controller->uf_control),
892             frame_index,
893             (void**) &frame_buffer
894          );
895 
896          scic_sds_controller_copy_sata_response(
897             &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
898          );
899 
900          // The command has completed with error
901          scic_sds_request_set_status(
902             &this_request->parent,
903             SCU_TASK_DONE_CHECK_RESPONSE,
904             SCI_FAILURE_IO_RESPONSE_VALID
905          );
906          break;
907 
908       default:
909          SCIC_LOG_WARNING((
910             sci_base_object_get_logger(this_request),
911             SCIC_LOG_OBJECT_STP_IO_REQUEST,
912             "IO Request:0x%x Frame Id:%d protocol violation occurred\n",
913             this_request, frame_index
914          ));
915 
916          scic_sds_request_set_status(
917             &this_request->parent,
918             SCU_TASK_DONE_UNEXP_FIS,
919             SCI_FAILURE_PROTOCOL_VIOLATION
920          );
921          break;
922       }
923 
924       sci_base_state_machine_change_state(
925          &this_request->parent.parent.state_machine,
926          SCI_BASE_REQUEST_STATE_COMPLETED
927       );
928 
929       // Frame has been decoded return it to the controller
930       scic_sds_controller_release_frame(
931          owning_controller, frame_index
932       );
933    }
934    else
935    {
936       SCIC_LOG_ERROR((
937          sci_base_object_get_logger(this_request),
938          SCIC_LOG_OBJECT_STP_IO_REQUEST,
939          "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
940          this_request, frame_index, status
941       ));
942    }
943 
944    return status;
945 }
946 
947 // ---------------------------------------------------------------------------
948 
949 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
950    scic_sds_stp_request_started_non_data_substate_handler_table
951       [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_MAX_SUBSTATES] =
952 {
953    // SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE
954    {
955       {
956          scic_sds_request_default_start_handler,
957          scic_sds_request_started_state_abort_handler,
958          scic_sds_request_default_complete_handler,
959          scic_sds_request_default_destruct_handler
960       },
961       scic_sds_stp_request_non_data_await_h2d_tc_completion_handler,
962       scic_sds_request_default_event_handler,
963       scic_sds_request_default_frame_handler
964    },
965    // SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE
966    {
967       {
968          scic_sds_request_default_start_handler,
969          scic_sds_request_started_state_abort_handler,
970          scic_sds_request_default_complete_handler,
971          scic_sds_request_default_destruct_handler
972       },
973       scic_sds_request_default_tc_completion_handler,
974       scic_sds_request_default_event_handler,
975       scic_sds_stp_request_non_data_await_d2h_frame_handler
976    }
977 };
978 
979 static
980 void scic_sds_stp_request_started_non_data_await_h2d_completion_enter(
981    SCI_BASE_OBJECT_T *object
982 )
983 {
984    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
985 
986    SET_STATE_HANDLER(
987       this_request,
988       scic_sds_stp_request_started_non_data_substate_handler_table,
989       SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE
990    );
991 
992    scic_sds_remote_device_set_working_request(
993       this_request->target_device, this_request
994    );
995 }
996 
997 static
998 void scic_sds_stp_request_started_non_data_await_d2h_enter(
999    SCI_BASE_OBJECT_T *object
1000 )
1001 {
1002    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
1003 
1004    SET_STATE_HANDLER(
1005       this_request,
1006       scic_sds_stp_request_started_non_data_substate_handler_table,
1007       SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE
1008    );
1009 }
1010 
1011 // ---------------------------------------------------------------------------
1012 
1013 SCI_BASE_STATE_T scic_sds_stp_request_started_non_data_substate_table
1014 [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_MAX_SUBSTATES] =
1015 {
1016    {
1017       SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE,
1018       scic_sds_stp_request_started_non_data_await_h2d_completion_enter,
1019       NULL
1020    },
1021    {
1022       SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE,
1023       scic_sds_stp_request_started_non_data_await_d2h_enter,
1024       NULL
1025    }
1026 };
1027 
1028 //******************************************************************************
1029 //* STP PIO STATE MACHINE
1030 //******************************************************************************
1031 
1032 #define SCU_MAX_FRAME_BUFFER_SIZE  0x400  // 1K is the maximum SCU frame data payload
1033 
1034 /**
1035  * This function will transmit DATA_FIS from (current sgl + offset) for input parameter length.
1036  * current sgl and offset is alreay stored in the IO request
1037  *
1038  * @param[in] this_request
1039  * @param[in] length
1040  *
1041  * @return SCI_STATUS
1042  */
1043 static
1044 SCI_STATUS scic_sds_stp_request_pio_data_out_trasmit_data_frame (
1045    SCIC_SDS_REQUEST_T * this_request,
1046    U32                  length
1047 )
1048 {
1049    SCI_STATUS status = SCI_SUCCESS;
1050    SCU_SGL_ELEMENT_T *  current_sgl;
1051    SCIC_SDS_STP_REQUEST_T * this_sds_stp_request = (SCIC_SDS_STP_REQUEST_T *)this_request;
1052 
1053    // Recycle the TC and reconstruct it for sending out DATA FIS containing
1054    // for the data from current_sgl+offset for the input length
1055    SCU_TASK_CONTEXT_T * task_context = scic_sds_controller_get_task_context_buffer(
1056                                           this_request->owning_controller,
1057                                           this_request->io_tag
1058                                        );
1059 
1060    if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A)
1061    {
1062       current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A);
1063    }
1064    else
1065    {
1066       current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B);
1067    }
1068 
1069    //update the TC
1070    task_context->command_iu_upper = current_sgl->address_upper;
1071    task_context->command_iu_lower = current_sgl->address_lower;
1072    task_context->transfer_length_bytes = length;
1073    task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
1074 
1075    // send the new TC out.
1076    status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
1077       &this_request->owning_controller->parent,
1078       &this_request->target_device->parent,
1079       &this_request->parent
1080    );
1081 
1082    return status;
1083 
1084 }
1085 
1086 /**
1087  *
1088  *
1089  * @param[in] this_request
1090  *
1091  * @return SCI_STATUS
1092  */
1093 static
1094 SCI_STATUS scic_sds_stp_request_pio_data_out_transmit_data(
1095    SCIC_SDS_REQUEST_T * this_sds_request
1096 )
1097 {
1098 
1099    SCU_SGL_ELEMENT_T *  current_sgl;
1100    U32                  sgl_offset;
1101    U32                  remaining_bytes_in_current_sgl = 0;
1102    SCI_STATUS           status = SCI_SUCCESS;
1103 
1104    SCIC_SDS_STP_REQUEST_T * this_sds_stp_request = (SCIC_SDS_STP_REQUEST_T *)this_sds_request;
1105 
1106    sgl_offset = this_sds_stp_request->type.pio.request_current.sgl_offset;
1107 
1108    if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A)
1109    {
1110       current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A);
1111       remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->A.length - sgl_offset;
1112    }
1113    else
1114    {
1115       current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B);
1116       remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->B.length - sgl_offset;
1117    }
1118 
1119 
1120    if (this_sds_stp_request->type.pio.pio_transfer_bytes > 0)
1121    {
1122       if (this_sds_stp_request->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl )
1123       {
1124          //recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl
1125          status = scic_sds_stp_request_pio_data_out_trasmit_data_frame (this_sds_request, remaining_bytes_in_current_sgl);
1126          if (status == SCI_SUCCESS)
1127          {
1128             this_sds_stp_request->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl;
1129             sgl_offset = 0;
1130          }
1131       }
1132       else if (this_sds_stp_request->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl )
1133       {
1134          //recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes
1135          scic_sds_stp_request_pio_data_out_trasmit_data_frame (this_sds_request, this_sds_stp_request->type.pio.pio_transfer_bytes);
1136 
1137          if (status == SCI_SUCCESS)
1138          {
1139             //Sgl offset will be adjusted and saved for future
1140             sgl_offset += this_sds_stp_request->type.pio.pio_transfer_bytes;
1141             current_sgl->address_lower += this_sds_stp_request->type.pio.pio_transfer_bytes;
1142             this_sds_stp_request->type.pio.pio_transfer_bytes = 0;
1143          }
1144       }
1145    }
1146 
1147    if (status == SCI_SUCCESS)
1148    {
1149       this_sds_stp_request->type.pio.request_current.sgl_offset = sgl_offset;
1150    }
1151 
1152    return status;
1153 }
1154 
1155 /**
1156  * Copy the data from the buffer for the length specified to the IO reqeust
1157  * SGL specified data region.
1158  *
1159  * @param[in] this_request The request that is used for the SGL processing.
1160  * @param[in] data_buffer The buffer of data to be copied.
1161  * @param[in] length  The length of the data transfer.
1162  *
1163  * @return SCI_STATUS
1164  */
1165 static
1166 SCI_STATUS scic_sds_stp_request_pio_data_in_copy_data_buffer(
1167    SCIC_SDS_STP_REQUEST_T * this_request,
1168    U8                     * data_buffer,
1169    U32                      length
1170 )
1171 {
1172    SCI_STATUS          status;
1173    SCU_SGL_ELEMENT_T * current_sgl;
1174    U32                 sgl_offset;
1175    U32                 data_offset;
1176    U8                * source_address;
1177 
1178    // Initial setup to get the current working SGL and the offset within the buffer
1179    current_sgl =
1180       (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) ?
1181          &(this_request->type.pio.request_current.sgl_pair->A) :
1182          &(this_request->type.pio.request_current.sgl_pair->B) ;
1183 
1184    sgl_offset = this_request->type.pio.request_current.sgl_offset;
1185 
1186    source_address = data_buffer;
1187    data_offset = this_request->type.pio.current_transfer_bytes;
1188    status = SCI_SUCCESS;
1189 
1190    // While we are still doing Ok and there is more data to transfer
1191    while (
1192             (length > 0)
1193          && (status == SCI_SUCCESS)
1194          )
1195    {
1196       if (current_sgl->length == sgl_offset)
1197       {
1198          // This SGL has been exauhasted so we need to get the next SGL
1199          current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_request);
1200 
1201          if (current_sgl == NULL)
1202             status = SCI_FAILURE;
1203          else
1204             sgl_offset = 0;
1205       }
1206       else
1207       {
1208 #ifdef ENABLE_OSSL_COPY_BUFFER
1209          scic_cb_io_request_copy_buffer(this_request, data_buffer, data_offset, length);
1210          length = 0;
1211 #else
1212          U8 * destination_address;
1213          U32  copy_length;
1214 
1215          destination_address = (U8 *)scic_cb_io_request_get_virtual_address_from_sgl(
1216             this_request,
1217             data_offset
1218          );
1219 
1220          copy_length = MIN(length, current_sgl->length - sgl_offset);
1221 
1222          memcpy(destination_address, source_address, copy_length);
1223 
1224          length -= copy_length;
1225          sgl_offset += copy_length;
1226          data_offset += copy_length;
1227          source_address += copy_length;
1228 #endif
1229       }
1230    }
1231 
1232    this_request->type.pio.request_current.sgl_offset = sgl_offset;
1233 
1234    return status;
1235 }
1236 
1237 /**
1238  * Copy the data buffer to the io request data region.
1239  *
1240  * @param[in] this_request The PIO DATA IN request that is to receive the
1241  *       data.
1242  * @param[in] data_buffer The buffer to copy from.
1243  *
1244  * @return SCI_STATUS
1245  */
1246 static
1247 SCI_STATUS scic_sds_stp_request_pio_data_in_copy_data(
1248    SCIC_SDS_STP_REQUEST_T * this_request,
1249    U8                     * data_buffer
1250 )
1251 {
1252    SCI_STATUS status;
1253 
1254    // If there is less than 1K remaining in the transfer request
1255    // copy just the data for the transfer
1256    if (this_request->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE)
1257    {
1258       status = scic_sds_stp_request_pio_data_in_copy_data_buffer(
1259          this_request,data_buffer,this_request->type.pio.pio_transfer_bytes);
1260 
1261       if (status == SCI_SUCCESS)
1262       {
1263          // All data for this PIO request has now been copied, so we don't
1264          //  technically need to update current_transfer_bytes here - just
1265          //  doing it for completeness.
1266          this_request->type.pio.current_transfer_bytes += this_request->type.pio.pio_transfer_bytes;
1267          this_request->type.pio.pio_transfer_bytes = 0;
1268       }
1269    }
1270    else
1271    {
1272       // We are transferring the whole frame so copy
1273       status = scic_sds_stp_request_pio_data_in_copy_data_buffer(
1274          this_request, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE);
1275 
1276       if (status == SCI_SUCCESS)
1277       {
1278          this_request->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE;
1279          this_request->type.pio.current_transfer_bytes += SCU_MAX_FRAME_BUFFER_SIZE;
1280       }
1281    }
1282 
1283    return status;
1284 }
1285 
1286 /**
1287  *
1288  *
1289  * @param[in] this_request
1290  * @param[in] completion_code
1291  *
1292  * @return SCI_STATUS
1293  */
1294 static
1295 SCI_STATUS scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler(
1296    SCIC_SDS_REQUEST_T * this_request,
1297    U32                  completion_code
1298 )
1299 {
1300    SCI_STATUS status = SCI_SUCCESS;
1301 
1302    SCIC_LOG_TRACE((
1303       sci_base_object_get_logger(this_request),
1304       SCIC_LOG_OBJECT_STP_IO_REQUEST,
1305       "scic_sds_stp_request_pio_data_in_await_h2d_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
1306       this_request, completion_code
1307    ));
1308 
1309    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
1310    {
1311    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
1312       scic_sds_request_set_status(
1313          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
1314       );
1315 
1316       sci_base_state_machine_change_state(
1317          &this_request->started_substate_machine,
1318          SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1319       );
1320       break;
1321 
1322    default:
1323       // All other completion status cause the IO to be complete.  If a NAK
1324       // was received, then it is up to the user to retry the request.
1325       scic_sds_request_set_status(
1326          this_request,
1327          SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
1328          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
1329       );
1330 
1331       sci_base_state_machine_change_state(
1332          &this_request->parent.state_machine,
1333          SCI_BASE_REQUEST_STATE_COMPLETED
1334       );
1335       break;
1336    }
1337 
1338    return status;
1339 }
1340 
1341 /**
1342  *
1343  *
1344  * @param[in] this_request
1345  * @param[in] frame_index
1346  *
1347  * @return SCI_STATUS
1348  */
1349 static
1350 SCI_STATUS scic_sds_stp_request_pio_await_frame_frame_handler(
1351    SCIC_SDS_REQUEST_T * request,
1352    U32                  frame_index
1353 )
1354 {
1355    SCI_STATUS               status;
1356    SATA_FIS_HEADER_T      * frame_header;
1357    U32                    * frame_buffer;
1358    SCIC_SDS_STP_REQUEST_T * this_request;
1359    SCIC_SDS_CONTROLLER_T  * owning_controller;
1360 
1361    this_request = (SCIC_SDS_STP_REQUEST_T *)request;
1362 
1363    // Save off the controller, so that we do not touch the request after it
1364    //  is completed.
1365    owning_controller = this_request->parent.owning_controller;
1366 
1367    SCIC_LOG_TRACE((
1368       sci_base_object_get_logger(this_request),
1369       SCIC_LOG_OBJECT_STP_IO_REQUEST,
1370       "scic_sds_stp_request_pio_data_in_await_frame_frame_handler(0x%x, 0x%x) enter\n",
1371       this_request, frame_index
1372    ));
1373 
1374    status = scic_sds_unsolicited_frame_control_get_header(
1375       &(owning_controller->uf_control),
1376       frame_index,
1377       (void**) &frame_header
1378    );
1379 
1380    if (status == SCI_SUCCESS)
1381    {
1382       switch (frame_header->fis_type)
1383       {
1384       case SATA_FIS_TYPE_PIO_SETUP:
1385          // Get from the frame buffer the PIO Setup Data
1386          scic_sds_unsolicited_frame_control_get_buffer(
1387             &(owning_controller->uf_control),
1388             frame_index,
1389             (void**) &frame_buffer
1390          );
1391 
1392          // Get the data from the PIO Setup
1393          // The SCU Hardware returns first word in the frame_header and the rest
1394          // of the data is in the frame buffer so we need to back up one dword
1395          this_request->type.pio.pio_transfer_bytes =
1396             (U16)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->transfter_count;
1397          this_request->type.pio.ending_status =
1398             (U8)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->ending_status;
1399 
1400          scic_sds_controller_copy_sata_response(
1401             &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
1402          );
1403 
1404          this_request->d2h_reg_fis.status =
1405             this_request->type.pio.ending_status;
1406 
1407          //The next state is dependent on whether the request was PIO Data-in or Data out
1408          if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_IN)
1409          {
1410          sci_base_state_machine_change_state(
1411             &this_request->parent.started_substate_machine,
1412             SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
1413             );
1414          }
1415          else if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT)
1416          {
1417             //Transmit data
1418             status = scic_sds_stp_request_pio_data_out_transmit_data ( request);
1419             if (status == SCI_SUCCESS)
1420             {
1421                sci_base_state_machine_change_state(
1422                   &this_request->parent.started_substate_machine,
1423                   SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
1424                );
1425             }
1426          }
1427       break;
1428 
1429       case SATA_FIS_TYPE_SETDEVBITS:
1430          sci_base_state_machine_change_state(
1431             &this_request->parent.started_substate_machine,
1432             SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1433             );
1434       break;
1435 
1436       case SATA_FIS_TYPE_REGD2H:
1437          if ( (frame_header->status & ATA_STATUS_REG_BSY_BIT) == 0)
1438          {
1439             scic_sds_unsolicited_frame_control_get_buffer(
1440                &(owning_controller->uf_control),
1441                frame_index,
1442                (void**) &frame_buffer
1443             );
1444 
1445             scic_sds_controller_copy_sata_response(
1446                &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer);
1447 
1448             scic_sds_request_set_status(
1449                &this_request->parent,
1450                SCU_TASK_DONE_CHECK_RESPONSE,
1451                SCI_FAILURE_IO_RESPONSE_VALID
1452             );
1453 
1454             sci_base_state_machine_change_state(
1455                &this_request->parent.parent.state_machine,
1456                SCI_BASE_REQUEST_STATE_COMPLETED
1457             );
1458          }
1459          else
1460          {
1461             // Now why is the drive sending a D2H Register FIS when it is still busy?
1462             // Do nothing since we are still in the right state.
1463             SCIC_LOG_INFO((
1464                sci_base_object_get_logger(this_request),
1465                SCIC_LOG_OBJECT_STP_IO_REQUEST,
1466                "SCIC PIO Request 0x%x received D2H Register FIS with BSY status 0x%x\n",
1467                this_request, frame_header->status
1468             ));
1469          }
1470          break;
1471 
1472          default:
1473          break;
1474          }
1475 
1476       // Frame is decoded return it to the controller
1477       scic_sds_controller_release_frame(
1478          owning_controller,
1479          frame_index
1480       );
1481    }
1482    else
1483    {
1484       SCIC_LOG_ERROR((
1485          sci_base_object_get_logger(this_request),
1486          SCIC_LOG_OBJECT_STP_IO_REQUEST,
1487          "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
1488          this_request, frame_index, status
1489       ));
1490    }
1491 
1492    return status;
1493 }
1494 
1495 /**
1496  *
1497  *
1498  * @param[in] this_request
1499  * @param[in] frame_index
1500  *
1501  * @return SCI_STATUS
1502  */
1503 static
1504 SCI_STATUS scic_sds_stp_request_pio_data_in_await_data_frame_handler(
1505    SCIC_SDS_REQUEST_T * request,
1506    U32                  frame_index
1507 )
1508 {
1509    SCI_STATUS               status;
1510    SATA_FIS_HEADER_T      * frame_header;
1511    SATA_FIS_DATA_T        * frame_buffer;
1512    SCIC_SDS_STP_REQUEST_T * this_request;
1513    SCIC_SDS_CONTROLLER_T  * owning_controller;
1514 
1515    this_request = (SCIC_SDS_STP_REQUEST_T *)request;
1516 
1517    // Save off the controller, so that we do not touch the request after it
1518    //  is completed.
1519    owning_controller = this_request->parent.owning_controller;
1520 
1521    SCIC_LOG_TRACE((
1522       sci_base_object_get_logger(this_request),
1523       SCIC_LOG_OBJECT_STP_IO_REQUEST,
1524       "scic_sds_stp_request_pio_data_in_await_data_frame_handler(0x%x, 0x%x) enter\n",
1525       this_request, frame_index
1526    ));
1527 
1528    status = scic_sds_unsolicited_frame_control_get_header(
1529       &(owning_controller->uf_control),
1530       frame_index,
1531       (void**) &frame_header
1532    );
1533 
1534    if (status == SCI_SUCCESS)
1535    {
1536       if (frame_header->fis_type == SATA_FIS_TYPE_DATA)
1537       {
1538          if (this_request->type.pio.request_current.sgl_pair == NULL)
1539          {
1540             this_request->parent.saved_rx_frame_index = frame_index;
1541             this_request->type.pio.pio_transfer_bytes = 0;
1542          }
1543          else
1544          {
1545             status = scic_sds_unsolicited_frame_control_get_buffer(
1546                &(owning_controller->uf_control),
1547                frame_index,
1548                (void**) &frame_buffer
1549             );
1550 
1551             status = scic_sds_stp_request_pio_data_in_copy_data(this_request, (U8 *)frame_buffer);
1552 
1553             // Frame is decoded return it to the controller
1554             scic_sds_controller_release_frame(
1555                owning_controller,
1556                frame_index
1557             );
1558          }
1559 
1560          // Check for the end of the transfer, are there more bytes remaining
1561          // for this data transfer
1562          if (
1563                (status == SCI_SUCCESS)
1564             && (this_request->type.pio.pio_transfer_bytes == 0)
1565             )
1566          {
1567             if ((this_request->type.pio.ending_status & ATA_STATUS_REG_BSY_BIT) == 0)
1568             {
1569                scic_sds_request_set_status(
1570                   &this_request->parent,
1571                   SCU_TASK_DONE_CHECK_RESPONSE,
1572                   SCI_FAILURE_IO_RESPONSE_VALID
1573                );
1574 
1575                sci_base_state_machine_change_state(
1576                   &this_request->parent.parent.state_machine,
1577                   SCI_BASE_REQUEST_STATE_COMPLETED
1578                );
1579             }
1580             else
1581             {
1582                sci_base_state_machine_change_state(
1583                   &this_request->parent.started_substate_machine,
1584                   SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1585                );
1586             }
1587          }
1588       }
1589       else
1590       {
1591          SCIC_LOG_ERROR((
1592             sci_base_object_get_logger(this_request),
1593             SCIC_LOG_OBJECT_STP_IO_REQUEST,
1594             "SCIC PIO Request 0x%x received frame %d with fis type 0x%02x when expecting a data fis.\n",
1595             this_request, frame_index, frame_header->fis_type
1596          ));
1597 
1598          scic_sds_request_set_status(
1599             &this_request->parent,
1600             SCU_TASK_DONE_GOOD,
1601             SCI_FAILURE_IO_REQUIRES_SCSI_ABORT
1602          );
1603 
1604          sci_base_state_machine_change_state(
1605             &this_request->parent.parent.state_machine,
1606             SCI_BASE_REQUEST_STATE_COMPLETED
1607          );
1608 
1609          // Frame is decoded return it to the controller
1610          scic_sds_controller_release_frame(
1611             owning_controller,
1612             frame_index
1613          );
1614       }
1615    }
1616    else
1617    {
1618       SCIC_LOG_ERROR((
1619          sci_base_object_get_logger(this_request),
1620          SCIC_LOG_OBJECT_STP_IO_REQUEST,
1621          "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
1622          this_request, frame_index, status
1623       ));
1624    }
1625 
1626    return status;
1627 }
1628 
1629 
1630 /**
1631  *
1632  *
1633  * @param[in] this_request
1634  * @param[in] completion_code
1635  *
1636  * @return SCI_STATUS
1637  */
1638 static
1639 SCI_STATUS scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler(
1640 
1641    SCIC_SDS_REQUEST_T * this_request,
1642    U32                  completion_code
1643 )
1644 {
1645    SCI_STATUS  status                     = SCI_SUCCESS;
1646    BOOL        all_frames_transferred     = FALSE;
1647 
1648    SCIC_SDS_STP_REQUEST_T *this_scic_sds_stp_request = (SCIC_SDS_STP_REQUEST_T *) this_request;
1649 
1650    SCIC_LOG_TRACE((
1651       sci_base_object_get_logger(this_request),
1652       SCIC_LOG_OBJECT_STP_IO_REQUEST,
1653       "scic_sds_stp_request_pio_data_in_await_h2d_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
1654       this_request, completion_code
1655    ));
1656 
1657    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
1658    {
1659       case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
1660          //Transmit data
1661          if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes != 0)
1662          {
1663             status = scic_sds_stp_request_pio_data_out_transmit_data ( this_request);
1664             if (status == SCI_SUCCESS)
1665             {
1666                if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0)
1667                all_frames_transferred = TRUE;
1668             }
1669          }
1670          else if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0)
1671          {
1672             //this will happen if the all data is written at the first time after the pio setup fis is received
1673             all_frames_transferred  = TRUE;
1674          }
1675 
1676          //all data transferred.
1677          if (all_frames_transferred)
1678          {
1679             //Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE
1680             //and wait for PIO_SETUP fis / or D2H REg fis.
1681             sci_base_state_machine_change_state(
1682                &this_request->started_substate_machine,
1683                SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1684             );
1685          }
1686          break;
1687 
1688       default:
1689          // All other completion status cause the IO to be complete.  If a NAK
1690          // was received, then it is up to the user to retry the request.
1691          scic_sds_request_set_status(
1692             this_request,
1693             SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
1694             SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
1695          );
1696 
1697          sci_base_state_machine_change_state(
1698             &this_request->parent.state_machine,
1699             SCI_BASE_REQUEST_STATE_COMPLETED
1700          );
1701          break;
1702    }
1703 
1704    return status;
1705 }
1706 
1707 /**
1708  * This method will handle any link layer events while waiting for the data
1709  * frame.
1710  *
1711  * @param[in] request This is the request which is receiving the event.
1712  * @param[in] event_code This is the event code that the request on which the
1713  *       request is expected to take action.
1714  *
1715  * @return SCI_STATUS
1716  * @retval SCI_SUCCESS
1717  * @retval SCI_FAILURE
1718  */
1719 static
1720 SCI_STATUS scic_sds_stp_request_pio_data_in_await_data_event_handler(
1721    SCIC_SDS_REQUEST_T * request,
1722    U32                  event_code
1723 )
1724 {
1725    SCI_STATUS status;
1726 
1727    switch (scu_get_event_specifier(event_code))
1728    {
1729    case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT:
1730       // We are waiting for data and the SCU has R_ERR the data frame.
1731       // Go back to waiting for the D2H Register FIS
1732       sci_base_state_machine_change_state(
1733          &request->started_substate_machine,
1734          SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1735       );
1736 
1737       status = SCI_SUCCESS;
1738       break;
1739 
1740    default:
1741       SCIC_LOG_ERROR((
1742          sci_base_object_get_logger(request),
1743          SCIC_LOG_OBJECT_STP_IO_REQUEST,
1744          "SCIC PIO Request 0x%x received unexpected event 0x%08x\n",
1745          request, event_code
1746       ));
1747 
1748       /// @todo Should we fail the PIO request when we get an unexpected event?
1749       status = SCI_FAILURE;
1750       break;
1751    }
1752 
1753    return status;
1754 }
1755 
1756 // ---------------------------------------------------------------------------
1757 
1758 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
1759    scic_sds_stp_request_started_pio_substate_handler_table
1760       [SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES] =
1761 {
1762    // SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
1763    {
1764       {
1765          scic_sds_request_default_start_handler,
1766          scic_sds_request_started_state_abort_handler,
1767          scic_sds_request_default_complete_handler,
1768          scic_sds_request_default_destruct_handler
1769       },
1770       scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler,
1771       scic_sds_request_default_event_handler,
1772       scic_sds_request_default_frame_handler
1773    },
1774    // SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1775    {
1776       {
1777          scic_sds_request_default_start_handler,
1778          //scic_sds_stp_pio_request_data_in_await_frame_abort_handler,
1779          scic_sds_request_started_state_abort_handler,
1780          scic_sds_request_default_complete_handler,
1781          scic_sds_request_default_destruct_handler
1782       },
1783       scic_sds_request_default_tc_completion_handler,
1784       scic_sds_request_default_event_handler,
1785       scic_sds_stp_request_pio_await_frame_frame_handler
1786    },
1787    // SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
1788    {
1789       {
1790          scic_sds_request_default_start_handler,
1791          //scic_sds_stp_pio_request_data_in_await_data_abort_handler,
1792          scic_sds_request_started_state_abort_handler,
1793          scic_sds_request_default_complete_handler,
1794          scic_sds_request_default_destruct_handler
1795       },
1796       scic_sds_request_default_tc_completion_handler,
1797       scic_sds_stp_request_pio_data_in_await_data_event_handler,
1798       scic_sds_stp_request_pio_data_in_await_data_frame_handler
1799    },
1800    //SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
1801    {
1802       {
1803          scic_sds_request_default_start_handler,
1804          scic_sds_request_started_state_abort_handler,
1805          scic_sds_request_default_complete_handler,
1806          scic_sds_request_default_destruct_handler
1807       },
1808       scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler,
1809       scic_sds_request_default_event_handler,
1810       scic_sds_request_default_frame_handler
1811    }
1812 };
1813 
1814 static
1815 void scic_sds_stp_request_started_pio_await_h2d_completion_enter(
1816    SCI_BASE_OBJECT_T *object
1817 )
1818 {
1819    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
1820 
1821    SET_STATE_HANDLER(
1822       this_request,
1823       scic_sds_stp_request_started_pio_substate_handler_table,
1824       SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
1825    );
1826 
1827    scic_sds_remote_device_set_working_request(
1828       this_request->target_device, this_request);
1829 }
1830 
1831 static
1832 void scic_sds_stp_request_started_pio_await_frame_enter(
1833    SCI_BASE_OBJECT_T *object
1834 )
1835 {
1836    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
1837 
1838    SET_STATE_HANDLER(
1839       this_request,
1840       scic_sds_stp_request_started_pio_substate_handler_table,
1841       SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1842    );
1843 }
1844 
1845 static
1846 void scic_sds_stp_request_started_pio_data_in_await_data_enter(
1847    SCI_BASE_OBJECT_T *object
1848 )
1849 {
1850    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
1851 
1852    SET_STATE_HANDLER(
1853       this_request,
1854       scic_sds_stp_request_started_pio_substate_handler_table,
1855       SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
1856    );
1857 }
1858 
1859 static
1860 void scic_sds_stp_request_started_pio_data_out_transmit_data_enter(
1861    SCI_BASE_OBJECT_T *object
1862 )
1863 {
1864    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
1865 
1866    SET_STATE_HANDLER(
1867       this_request,
1868       scic_sds_stp_request_started_pio_substate_handler_table,
1869       SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
1870    );
1871 }
1872 
1873 // ---------------------------------------------------------------------------
1874 
1875 SCI_BASE_STATE_T
1876    scic_sds_stp_request_started_pio_substate_table
1877       [SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES] =
1878 {
1879    {
1880       SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE,
1881       scic_sds_stp_request_started_pio_await_h2d_completion_enter,
1882       NULL
1883    },
1884    {
1885       SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE,
1886       scic_sds_stp_request_started_pio_await_frame_enter,
1887       NULL
1888    },
1889    {
1890       SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE,
1891       scic_sds_stp_request_started_pio_data_in_await_data_enter,
1892       NULL
1893    },
1894    {
1895       SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE,
1896       scic_sds_stp_request_started_pio_data_out_transmit_data_enter,
1897       NULL
1898    }
1899 };
1900 
1901 //******************************************************************************
1902 //* UDMA REQUEST STATE MACHINE
1903 //******************************************************************************
1904 
1905 static
1906 void scic_sds_stp_request_udma_complete_request(
1907    SCIC_SDS_REQUEST_T * this_request,
1908    U32                  scu_status,
1909    SCI_STATUS           sci_status
1910 )
1911 {
1912    scic_sds_request_set_status(
1913       this_request, scu_status, sci_status
1914    );
1915 
1916    sci_base_state_machine_change_state(
1917       &this_request->parent.state_machine,
1918       SCI_BASE_REQUEST_STATE_COMPLETED
1919    );
1920 }
1921 
1922 /**
1923  *
1924  *
1925  * @param[in] this_request
1926  * @param[in] frame_index
1927  *
1928  * @return SCI_STATUS
1929  */
1930 static
1931 SCI_STATUS scic_sds_stp_request_udma_general_frame_handler(
1932    SCIC_SDS_REQUEST_T * this_request,
1933    U32                  frame_index
1934 )
1935 {
1936    SCI_STATUS          status;
1937    SATA_FIS_HEADER_T * frame_header;
1938    U32               * frame_buffer;
1939 
1940    SCIC_LOG_TRACE((
1941       sci_base_object_get_logger(this_request),
1942       SCIC_LOG_OBJECT_STP_IO_REQUEST,
1943       "scic_sds_stp_pio_request_data_in_await_frame_frame_handler(0x%x, 0x%x) enter\n",
1944       this_request, frame_index
1945    ));
1946 
1947    status = scic_sds_unsolicited_frame_control_get_header(
1948       &this_request->owning_controller->uf_control,
1949       frame_index,
1950       (void**) &frame_header
1951    );
1952 
1953    if (
1954          (status == SCI_SUCCESS)
1955       && (frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
1956       )
1957    {
1958       scic_sds_unsolicited_frame_control_get_buffer(
1959          &this_request->owning_controller->uf_control,
1960          frame_index,
1961          (void**) &frame_buffer
1962       );
1963 
1964       scic_sds_controller_copy_sata_response(
1965          &((SCIC_SDS_STP_REQUEST_T *)this_request)->d2h_reg_fis,
1966          (U32 *)frame_header,
1967          frame_buffer
1968       );
1969    }
1970 
1971    scic_sds_controller_release_frame(
1972       this_request->owning_controller, frame_index);
1973 
1974    return status;
1975 }
1976 
1977 /**
1978  * @brief This method process TC completions while in the state where
1979  *        we are waiting for TC completions.
1980  *
1981  * @param[in] this_request
1982  * @param[in] completion_code
1983  *
1984  * @return SCI_STATUS
1985  */
1986 static
1987 SCI_STATUS scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler(
1988    SCIC_SDS_REQUEST_T * request,
1989    U32                  completion_code
1990 )
1991 {
1992    SCI_STATUS               status = SCI_SUCCESS;
1993    SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
1994 
1995    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
1996    {
1997    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
1998       scic_sds_stp_request_udma_complete_request(
1999          &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
2000       );
2001    break;
2002 
2003    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS):
2004    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR):
2005       // We must check ther response buffer to see if the D2H Register FIS was
2006       // received before we got the TC completion.
2007       if (this_request->d2h_reg_fis.fis_type == SATA_FIS_TYPE_REGD2H)
2008       {
2009          scic_sds_remote_device_suspend(
2010             this_request->parent.target_device,
2011             SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))
2012          );
2013 
2014          scic_sds_stp_request_udma_complete_request(
2015             &this_request->parent,
2016             SCU_TASK_DONE_CHECK_RESPONSE,
2017             SCI_FAILURE_IO_RESPONSE_VALID
2018          );
2019       }
2020       else
2021       {
2022          // If we have an error completion status for the TC then we can expect a
2023          // D2H register FIS from the device so we must change state to wait for it
2024          sci_base_state_machine_change_state(
2025             &this_request->parent.started_substate_machine,
2026             SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
2027          );
2028       }
2029    break;
2030 
2031    /// @todo Check to see if any of these completion status need to wait for
2032    ///       the device to host register fis.
2033    /// @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0
2034    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN):
2035    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
2036    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
2037    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
2038    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR):
2039       scic_sds_remote_device_suspend(
2040          this_request->parent.target_device,
2041          SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))
2042       );
2043       // Fall through to the default case
2044    default:
2045       // All other completion status cause the IO to be complete.
2046       SCIC_LOG_ERROR((
2047          sci_base_object_get_logger(&this_request->parent),
2048          SCIC_LOG_OBJECT_STP_IO_REQUEST,
2049          "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n",
2050          &this_request->parent, completion_code
2051       ));
2052       scic_sds_stp_request_udma_complete_request(
2053          &this_request->parent,
2054          SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
2055          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2056       );
2057       break;
2058    }
2059 
2060    return status;
2061 }
2062 
2063 static
2064 SCI_STATUS scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler(
2065    SCIC_SDS_REQUEST_T * this_request,
2066    U32                  frame_index
2067 )
2068 {
2069    SCI_STATUS status;
2070 
2071    // Use the general frame handler to copy the resposne data
2072    status = scic_sds_stp_request_udma_general_frame_handler(this_request, frame_index);
2073 
2074    if (status == SCI_SUCCESS)
2075    {
2076       scic_sds_stp_request_udma_complete_request(
2077          this_request,
2078          SCU_TASK_DONE_CHECK_RESPONSE,
2079          SCI_FAILURE_IO_RESPONSE_VALID
2080       );
2081    }
2082 
2083    return status;
2084 }
2085 
2086 // ---------------------------------------------------------------------------
2087 
2088 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
2089    scic_sds_stp_request_started_udma_substate_handler_table
2090       [SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES] =
2091 {
2092    // SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
2093    {
2094       {
2095          scic_sds_request_default_start_handler,
2096          scic_sds_request_started_state_abort_handler,
2097          scic_sds_request_default_complete_handler,
2098          scic_sds_request_default_destruct_handler
2099       },
2100       scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler,
2101       scic_sds_request_default_event_handler,
2102       scic_sds_stp_request_udma_general_frame_handler
2103    },
2104    // SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
2105    {
2106       {
2107          scic_sds_request_default_start_handler,
2108          scic_sds_request_started_state_abort_handler,
2109          scic_sds_request_default_complete_handler,
2110          scic_sds_request_default_destruct_handler
2111       },
2112       scic_sds_request_default_tc_completion_handler,
2113       scic_sds_request_default_event_handler,
2114       scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler
2115    }
2116 };
2117 
2118 /**
2119  *
2120  *
2121  * @param[in] object
2122  */
2123 static
2124 void scic_sds_stp_request_started_udma_await_tc_completion_enter(
2125    SCI_BASE_OBJECT_T *object
2126 )
2127 {
2128    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2129 
2130    SET_STATE_HANDLER(
2131       this_request,
2132       scic_sds_stp_request_started_udma_substate_handler_table,
2133       SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
2134    );
2135 }
2136 
2137 /**
2138  * This state is entered when there is an TC completion failure.  The hardware
2139  * received an unexpected condition while processing the IO request and now
2140  * will UF the D2H register FIS to complete the IO.
2141  *
2142  * @param[in] object
2143  */
2144 static
2145 void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter(
2146    SCI_BASE_OBJECT_T *object
2147 )
2148 {
2149    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2150 
2151    SET_STATE_HANDLER(
2152       this_request,
2153       scic_sds_stp_request_started_udma_substate_handler_table,
2154       SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
2155    );
2156 }
2157 
2158 // ---------------------------------------------------------------------------
2159 
2160 SCI_BASE_STATE_T
2161    scic_sds_stp_request_started_udma_substate_table
2162       [SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES] =
2163 {
2164    {
2165       SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE,
2166       scic_sds_stp_request_started_udma_await_tc_completion_enter,
2167       NULL
2168    },
2169    {
2170       SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE,
2171       scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter,
2172       NULL
2173    }
2174 };
2175 
2176 //******************************************************************************
2177 //* STP SOFT RESET STATE MACHINE
2178 //******************************************************************************
2179 
2180 /**
2181  * This method processes a TC completion.  The expected TC completion is
2182  * for the transmission of the H2D register FIS containing the SATA/STP
2183  * non-data request.
2184  *
2185  * @param[in] this_request
2186  * @param[in] completion_code
2187  *
2188  * @return This method always successfully processes the TC completion.
2189  * @retval SCI_SUCCESS This value is always returned.
2190  */
2191 static
2192 SCI_STATUS scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler(
2193    SCIC_SDS_REQUEST_T * this_request,
2194    U32                  completion_code
2195 )
2196 {
2197    SCIC_LOG_TRACE((
2198       sci_base_object_get_logger(this_request),
2199       SCIC_LOG_OBJECT_STP_IO_REQUEST,
2200       "scic_sds_stp_request_soft_reset_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n",
2201       this_request, completion_code
2202    ));
2203 
2204    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
2205    {
2206    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
2207       scic_sds_request_set_status(
2208          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
2209       );
2210 
2211       sci_base_state_machine_change_state(
2212          &this_request->started_substate_machine,
2213          SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
2214       );
2215       break;
2216 
2217    default:
2218       // All other completion status cause the IO to be complete.  If a NAK
2219       // was received, then it is up to the user to retry the request.
2220       scic_sds_request_set_status(
2221          this_request,
2222          SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
2223          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2224       );
2225 
2226       sci_base_state_machine_change_state(
2227          &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
2228       );
2229       break;
2230    }
2231 
2232    return SCI_SUCCESS;
2233 }
2234 
2235 /**
2236  * This method processes a TC completion.  The expected TC completion is
2237  * for the transmission of the H2D register FIS containing the SATA/STP
2238  * non-data request.
2239  *
2240  * @param[in] this_request
2241  * @param[in] completion_code
2242  *
2243  * @return This method always successfully processes the TC completion.
2244  * @retval SCI_SUCCESS This value is always returned.
2245  */
2246 static
2247 SCI_STATUS scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler(
2248    SCIC_SDS_REQUEST_T * this_request,
2249    U32                  completion_code
2250 )
2251 {
2252    SCIC_LOG_TRACE((
2253       sci_base_object_get_logger(this_request),
2254       SCIC_LOG_OBJECT_STP_IO_REQUEST,
2255       "scic_sds_stp_request_soft_reset_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n",
2256       this_request, completion_code
2257    ));
2258 
2259    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
2260    {
2261    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
2262       scic_sds_request_set_status(
2263          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
2264       );
2265 
2266       sci_base_state_machine_change_state(
2267          &this_request->started_substate_machine,
2268          SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
2269       );
2270       break;
2271 
2272    default:
2273       // All other completion status cause the IO to be complete.  If a NAK
2274       // was received, then it is up to the user to retry the request.
2275       scic_sds_request_set_status(
2276          this_request,
2277          SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
2278          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2279       );
2280 
2281       sci_base_state_machine_change_state(
2282          &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
2283       );
2284       break;
2285    }
2286 
2287    return SCI_SUCCESS;
2288 }
2289 
2290 /**
2291  * This method processes frames received from the target while waiting
2292  * for a device to host register FIS.  If a non-register FIS is received
2293  * during this time, it is treated as a protocol violation from an
2294  * IO perspective.
2295  *
2296  * @param[in] request This parameter specifies the request for which a
2297  *            frame has been received.
2298  * @param[in] frame_index This parameter specifies the index of the frame
2299  *            that has been received.
2300  *
2301  * @return Indicate if the received frame was processed successfully.
2302  */
2303 static
2304 SCI_STATUS scic_sds_stp_request_soft_reset_await_d2h_frame_handler(
2305    SCIC_SDS_REQUEST_T * request,
2306    U32                  frame_index
2307 )
2308 {
2309    SCI_STATUS               status;
2310    SATA_FIS_HEADER_T      * frame_header;
2311    U32                    * frame_buffer;
2312    SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
2313 
2314    // Save off the controller, so that we do not touch the request after it
2315    //  is completed.
2316    SCIC_SDS_CONTROLLER_T  * owning_controller = this_request->parent.owning_controller;
2317 
2318    SCIC_LOG_TRACE((
2319       sci_base_object_get_logger(this_request),
2320       SCIC_LOG_OBJECT_STP_IO_REQUEST,
2321       "scic_sds_stp_request_soft_reset_await_d2h_frame_handler(0x%x, 0x%x) enter\n",
2322       this_request, frame_index
2323    ));
2324 
2325    status = scic_sds_unsolicited_frame_control_get_header(
2326                &(owning_controller->uf_control),
2327                frame_index,
2328                (void**) &frame_header
2329             );
2330 
2331    if (status == SCI_SUCCESS)
2332    {
2333       switch (frame_header->fis_type)
2334       {
2335       case SATA_FIS_TYPE_REGD2H:
2336          scic_sds_unsolicited_frame_control_get_buffer(
2337             &(owning_controller->uf_control),
2338             frame_index,
2339             (void**) &frame_buffer
2340          );
2341 
2342          scic_sds_controller_copy_sata_response(
2343             &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
2344          );
2345 
2346          // The command has completed with error
2347          scic_sds_request_set_status(
2348             &this_request->parent,
2349             SCU_TASK_DONE_CHECK_RESPONSE,
2350             SCI_FAILURE_IO_RESPONSE_VALID
2351          );
2352          break;
2353 
2354       default:
2355          SCIC_LOG_WARNING((
2356             sci_base_object_get_logger(this_request),
2357             SCIC_LOG_OBJECT_STP_IO_REQUEST,
2358             "IO Request:0x%x Frame Id:%d protocol violation occurred\n",
2359             this_request, frame_index
2360          ));
2361 
2362          scic_sds_request_set_status(
2363             &this_request->parent,
2364             SCU_TASK_DONE_UNEXP_FIS,
2365             SCI_FAILURE_PROTOCOL_VIOLATION
2366          );
2367          break;
2368       }
2369 
2370       sci_base_state_machine_change_state(
2371          &this_request->parent.parent.state_machine,
2372          SCI_BASE_REQUEST_STATE_COMPLETED
2373       );
2374 
2375       // Frame has been decoded return it to the controller
2376       scic_sds_controller_release_frame(
2377          owning_controller, frame_index
2378       );
2379    }
2380    else
2381    {
2382       SCIC_LOG_ERROR((
2383          sci_base_object_get_logger(this_request),
2384          SCIC_LOG_OBJECT_STP_IO_REQUEST,
2385          "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
2386          this_request, frame_index, status
2387       ));
2388    }
2389 
2390    return status;
2391 }
2392 
2393 // ---------------------------------------------------------------------------
2394 
2395 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
2396    scic_sds_stp_request_started_soft_reset_substate_handler_table
2397       [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES] =
2398 {
2399    // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
2400    {
2401       {
2402          scic_sds_request_default_start_handler,
2403          scic_sds_request_started_state_abort_handler,
2404          scic_sds_request_default_complete_handler,
2405          scic_sds_request_default_destruct_handler
2406       },
2407       scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler,
2408       scic_sds_request_default_event_handler,
2409       scic_sds_request_default_frame_handler
2410    },
2411    // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
2412    {
2413       {
2414          scic_sds_request_default_start_handler,
2415          scic_sds_request_started_state_abort_handler,
2416          scic_sds_request_default_complete_handler,
2417          scic_sds_request_default_destruct_handler
2418       },
2419       scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler,
2420       scic_sds_request_default_event_handler,
2421       scic_sds_request_default_frame_handler
2422    },
2423    // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
2424    {
2425       {
2426          scic_sds_request_default_start_handler,
2427          scic_sds_request_started_state_abort_handler,
2428          scic_sds_request_default_complete_handler,
2429          scic_sds_request_default_destruct_handler
2430       },
2431       scic_sds_request_default_tc_completion_handler,
2432       scic_sds_request_default_event_handler,
2433       scic_sds_stp_request_soft_reset_await_d2h_frame_handler
2434    }
2435 };
2436 
2437 static
2438 void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(
2439    SCI_BASE_OBJECT_T *object
2440 )
2441 {
2442    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2443 
2444    SET_STATE_HANDLER(
2445       this_request,
2446       scic_sds_stp_request_started_soft_reset_substate_handler_table,
2447       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
2448    );
2449 
2450    scic_sds_remote_device_set_working_request(
2451       this_request->target_device, this_request
2452    );
2453 }
2454 
2455 static
2456 void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(
2457    SCI_BASE_OBJECT_T *object
2458 )
2459 {
2460    SCI_STATUS status;
2461    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2462    SATA_FIS_REG_H2D_T *h2d_fis;
2463    SCU_TASK_CONTEXT_T *task_context;
2464 
2465    // Clear the SRST bit
2466    h2d_fis = scic_stp_io_request_get_h2d_reg_address(this_request);
2467    h2d_fis->control = 0;
2468 
2469    // Clear the TC control bit
2470    task_context = scic_sds_controller_get_task_context_buffer(
2471                         this_request->owning_controller, this_request->io_tag);
2472    task_context->control_frame = 0;
2473 
2474    status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
2475       &this_request->owning_controller->parent,
2476       &this_request->target_device->parent,
2477       &this_request->parent
2478    );
2479 
2480    if (status == SCI_SUCCESS)
2481    {
2482       SET_STATE_HANDLER(
2483          this_request,
2484          scic_sds_stp_request_started_soft_reset_substate_handler_table,
2485          SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
2486       );
2487    }
2488 }
2489 
2490 static
2491 void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter(
2492    SCI_BASE_OBJECT_T *object
2493 )
2494 {
2495    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2496 
2497    SET_STATE_HANDLER(
2498       this_request,
2499       scic_sds_stp_request_started_soft_reset_substate_handler_table,
2500       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
2501    );
2502 }
2503 
2504 // ---------------------------------------------------------------------------
2505 
2506 SCI_BASE_STATE_T
2507    scic_sds_stp_request_started_soft_reset_substate_table
2508       [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES] =
2509 {
2510    {
2511       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE,
2512       scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter,
2513       NULL
2514    },
2515    {
2516       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE,
2517       scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter,
2518       NULL
2519    },
2520    {
2521       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE,
2522       scic_sds_stp_request_started_soft_reset_await_d2h_response_enter,
2523       NULL
2524    }
2525 };
2526 
2527 // ---------------------------------------------------------------------------
2528 
2529 SCI_STATUS scic_io_request_construct_basic_sata(
2530    SCI_IO_REQUEST_HANDLE_T  scic_io_request
2531 )
2532 {
2533    SCI_STATUS           status;
2534    SCIC_SDS_REQUEST_T * request = (SCIC_SDS_REQUEST_T *)scic_io_request;
2535 
2536    SCIC_LOG_TRACE((
2537       sci_base_object_get_logger(scic_io_request),
2538       SCIC_LOG_OBJECT_STP_IO_REQUEST,
2539       "scic_io_request_construct_basic_sata(0x%x) enter\n",
2540       scic_io_request
2541    ));
2542 
2543    status = scic_sds_io_request_construct_sata(
2544                request,
2545                scic_cb_request_get_sat_protocol(request->user_request),
2546                scic_cb_io_request_get_transfer_length(request->user_request),
2547                scic_cb_io_request_get_data_direction(request->user_request),
2548                scic_cb_io_request_do_copy_rx_frames(request->user_request),
2549                TRUE
2550             );
2551 
2552    return status;
2553 }
2554 
2555 // ---------------------------------------------------------------------------
2556 
2557 SCI_STATUS scic_io_request_construct_advanced_sata(
2558    SCI_IO_REQUEST_HANDLE_T     scic_io_request,
2559    SCIC_IO_SATA_PARAMETERS_T * io_parameters
2560 )
2561 {
2562    SCI_STATUS           status;
2563    SCIC_SDS_REQUEST_T * request = (SCIC_SDS_REQUEST_T *)scic_io_request;
2564 
2565    SCIC_LOG_TRACE((
2566       sci_base_object_get_logger(scic_io_request),
2567       SCIC_LOG_OBJECT_STP_IO_REQUEST,
2568       "scic_io_request_construct_basic_sata(0x%x) enter\n",
2569       scic_io_request
2570    ));
2571 
2572    status = scic_sds_io_request_construct_sata(
2573                request,
2574                scic_cb_request_get_sat_protocol(request->user_request),
2575                scic_sds_request_get_sgl_element_pair(request, 0)->A.length,
2576                scic_cb_io_request_get_data_direction(request->user_request),
2577                scic_cb_io_request_do_copy_rx_frames(request->user_request),
2578                io_parameters->do_translate_sgl
2579             );
2580 
2581    return status;
2582 }
2583 
2584