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