xref: /freebsd/sys/dev/isci/scil/scic_sds_stp_request.c (revision b7c60aadbbd5c846a250c05791fe7406d6d78bf4)
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    // transfered 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 transfered
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 
1128             //update the current sgl, sgl_offset and save for future
1129             current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_sds_stp_request);
1130             sgl_offset = 0;
1131          }
1132       }
1133       else if (this_sds_stp_request->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl )
1134       {
1135          //recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes
1136          scic_sds_stp_request_pio_data_out_trasmit_data_frame (this_sds_request, this_sds_stp_request->type.pio.pio_transfer_bytes);
1137 
1138          if (status == SCI_SUCCESS)
1139          {
1140             //Sgl offset will be adjusted and saved for future
1141             sgl_offset += this_sds_stp_request->type.pio.pio_transfer_bytes;
1142             current_sgl->address_lower += this_sds_stp_request->type.pio.pio_transfer_bytes;
1143             this_sds_stp_request->type.pio.pio_transfer_bytes = 0;
1144          }
1145       }
1146    }
1147 
1148    if (status == SCI_SUCCESS)
1149    {
1150       this_sds_stp_request->type.pio.request_current.sgl_offset = sgl_offset;
1151    }
1152 
1153    return status;
1154 }
1155 
1156 /**
1157  * Copy the data from the buffer for the length specified to the IO reqeust
1158  * SGL specified data region.
1159  *
1160  * @param[in] this_request The request that is used for the SGL processing.
1161  * @param[in] data_buffer The buffer of data to be copied.
1162  * @param[in] length  The length of the data transfer.
1163  *
1164  * @return SCI_STATUS
1165  */
1166 static
1167 SCI_STATUS scic_sds_stp_request_pio_data_in_copy_data_buffer(
1168    SCIC_SDS_STP_REQUEST_T * this_request,
1169    U8                     * data_buffer,
1170    U32                      length
1171 )
1172 {
1173    SCI_STATUS          status;
1174    SCU_SGL_ELEMENT_T * current_sgl;
1175    U32                 sgl_offset;
1176    U32                 data_offset;
1177    U8                * source_address;
1178 
1179    // Initial setup to get the current working SGL and the offset within the buffer
1180    current_sgl =
1181       (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) ?
1182          &(this_request->type.pio.request_current.sgl_pair->A) :
1183          &(this_request->type.pio.request_current.sgl_pair->B) ;
1184 
1185    sgl_offset = this_request->type.pio.request_current.sgl_offset;
1186 
1187    source_address = data_buffer;
1188    data_offset = this_request->type.pio.current_transfer_bytes;
1189    status = SCI_SUCCESS;
1190 
1191    // While we are still doing Ok and there is more data to transfer
1192    while (
1193             (length > 0)
1194          && (status == SCI_SUCCESS)
1195          )
1196    {
1197       if (current_sgl->length == sgl_offset)
1198       {
1199          // This SGL has been exauhasted so we need to get the next SGL
1200          current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_request);
1201 
1202          if (current_sgl == NULL)
1203             status = SCI_FAILURE;
1204          else
1205             sgl_offset = 0;
1206       }
1207       else
1208       {
1209 #ifdef ENABLE_OSSL_COPY_BUFFER
1210          scic_cb_io_request_copy_buffer(this_request, data_buffer, data_offset, length);
1211          length = 0;
1212 #else
1213          U8 * destination_address;
1214          U32  copy_length;
1215 
1216          destination_address = (U8 *)scic_cb_io_request_get_virtual_address_from_sgl(
1217             this_request,
1218             data_offset
1219          );
1220 
1221          copy_length = MIN(length, current_sgl->length - sgl_offset);
1222 
1223          memcpy(destination_address, source_address, copy_length);
1224 
1225          length -= copy_length;
1226          sgl_offset += copy_length;
1227          data_offset += copy_length;
1228 #endif
1229       }
1230    }
1231 
1232    this_request->type.pio.request_current.sgl_offset = sgl_offset;
1233 
1234    return status;
1235 }
1236 
1237 /**
1238  * Copy the data buffer to the io request data region.
1239  *
1240  * @param[in] this_request The PIO DATA IN request that is to receive the
1241  *       data.
1242  * @param[in] data_buffer The buffer to copy from.
1243  *
1244  * @return SCI_STATUS
1245  */
1246 static
1247 SCI_STATUS scic_sds_stp_request_pio_data_in_copy_data(
1248    SCIC_SDS_STP_REQUEST_T * this_request,
1249    U8                     * data_buffer
1250 )
1251 {
1252    SCI_STATUS status;
1253 
1254    // If there is less than 1K remaining in the transfer request
1255    // copy just the data for the transfer
1256    if (this_request->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE)
1257    {
1258       status = scic_sds_stp_request_pio_data_in_copy_data_buffer(
1259          this_request,data_buffer,this_request->type.pio.pio_transfer_bytes);
1260 
1261       if (status == SCI_SUCCESS)
1262       {
1263          // All data for this PIO request has now been copied, so we don't
1264          //  technically need to update current_transfer_bytes here - just
1265          //  doing it for completeness.
1266          this_request->type.pio.current_transfer_bytes += this_request->type.pio.pio_transfer_bytes;
1267          this_request->type.pio.pio_transfer_bytes = 0;
1268       }
1269    }
1270    else
1271    {
1272       // We are transfering the whole frame so copy
1273       status = scic_sds_stp_request_pio_data_in_copy_data_buffer(
1274          this_request, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE);
1275 
1276       if (status == SCI_SUCCESS)
1277       {
1278          this_request->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE;
1279          this_request->type.pio.current_transfer_bytes += SCU_MAX_FRAME_BUFFER_SIZE;
1280       }
1281    }
1282 
1283    return status;
1284 }
1285 
1286 /**
1287  *
1288  *
1289  * @param[in] this_request
1290  * @param[in] completion_code
1291  *
1292  * @return SCI_STATUS
1293  */
1294 static
1295 SCI_STATUS scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler(
1296    SCIC_SDS_REQUEST_T * this_request,
1297    U32                  completion_code
1298 )
1299 {
1300    SCI_STATUS status = SCI_SUCCESS;
1301 
1302    SCIC_LOG_TRACE((
1303       sci_base_object_get_logger(this_request),
1304       SCIC_LOG_OBJECT_STP_IO_REQUEST,
1305       "scic_sds_stp_request_pio_data_in_await_h2d_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
1306       this_request, completion_code
1307    ));
1308 
1309    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
1310    {
1311    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
1312       scic_sds_request_set_status(
1313          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
1314       );
1315 
1316       sci_base_state_machine_change_state(
1317          &this_request->started_substate_machine,
1318          SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1319       );
1320       break;
1321 
1322    default:
1323       // All other completion status cause the IO to be complete.  If a NAK
1324       // was received, then it is up to the user to retry the request.
1325       scic_sds_request_set_status(
1326          this_request,
1327          SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
1328          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
1329       );
1330 
1331       sci_base_state_machine_change_state(
1332          &this_request->parent.state_machine,
1333          SCI_BASE_REQUEST_STATE_COMPLETED
1334       );
1335       break;
1336    }
1337 
1338    return status;
1339 }
1340 
1341 /**
1342  *
1343  *
1344  * @param[in] this_request
1345  * @param[in] frame_index
1346  *
1347  * @return SCI_STATUS
1348  */
1349 static
1350 SCI_STATUS scic_sds_stp_request_pio_await_frame_frame_handler(
1351    SCIC_SDS_REQUEST_T * request,
1352    U32                  frame_index
1353 )
1354 {
1355    SCI_STATUS               status;
1356    SATA_FIS_HEADER_T      * frame_header;
1357    U32                    * frame_buffer;
1358    SCIC_SDS_STP_REQUEST_T * this_request;
1359    SCIC_SDS_CONTROLLER_T  * owning_controller;
1360 
1361    this_request = (SCIC_SDS_STP_REQUEST_T *)request;
1362 
1363    // Save off the controller, so that we do not touch the request after it
1364    //  is completed.
1365    owning_controller = this_request->parent.owning_controller;
1366 
1367    SCIC_LOG_TRACE((
1368       sci_base_object_get_logger(this_request),
1369       SCIC_LOG_OBJECT_STP_IO_REQUEST,
1370       "scic_sds_stp_request_pio_data_in_await_frame_frame_handler(0x%x, 0x%x) enter\n",
1371       this_request, frame_index
1372    ));
1373 
1374    status = scic_sds_unsolicited_frame_control_get_header(
1375       &(owning_controller->uf_control),
1376       frame_index,
1377       (void**) &frame_header
1378    );
1379 
1380    if (status == SCI_SUCCESS)
1381    {
1382       switch (frame_header->fis_type)
1383       {
1384       case SATA_FIS_TYPE_PIO_SETUP:
1385          // Get from the frame buffer the PIO Setup Data
1386          scic_sds_unsolicited_frame_control_get_buffer(
1387             &(owning_controller->uf_control),
1388             frame_index,
1389             (void**) &frame_buffer
1390          );
1391 
1392          // Get the data from the PIO Setup
1393          // The SCU Hardware returns first word in the frame_header and the rest
1394          // of the data is in the frame buffer so we need to back up one dword
1395          this_request->type.pio.pio_transfer_bytes =
1396             (U16)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->transfter_count;
1397          this_request->type.pio.ending_status =
1398             (U8)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->ending_status;
1399 
1400          scic_sds_controller_copy_sata_response(
1401             &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
1402          );
1403 
1404          this_request->d2h_reg_fis.status =
1405             this_request->type.pio.ending_status;
1406 
1407          //The next state is dependent on whether the request was PIO Data-in or Data out
1408          if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_IN)
1409          {
1410          sci_base_state_machine_change_state(
1411             &this_request->parent.started_substate_machine,
1412             SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
1413             );
1414          }
1415          else if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT)
1416          {
1417             //Transmit data
1418             status = scic_sds_stp_request_pio_data_out_transmit_data ( request);
1419             if (status == SCI_SUCCESS)
1420             {
1421                sci_base_state_machine_change_state(
1422                   &this_request->parent.started_substate_machine,
1423                   SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
1424                );
1425             }
1426          }
1427       break;
1428 
1429       case SATA_FIS_TYPE_SETDEVBITS:
1430          sci_base_state_machine_change_state(
1431             &this_request->parent.started_substate_machine,
1432             SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1433             );
1434       break;
1435 
1436       case SATA_FIS_TYPE_REGD2H:
1437          if ( (frame_header->status & ATA_STATUS_REG_BSY_BIT) == 0)
1438          {
1439             scic_sds_unsolicited_frame_control_get_buffer(
1440                &(owning_controller->uf_control),
1441                frame_index,
1442                (void**) &frame_buffer
1443             );
1444 
1445             scic_sds_controller_copy_sata_response(
1446                &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer);
1447 
1448             scic_sds_request_set_status(
1449                &this_request->parent,
1450                SCU_TASK_DONE_CHECK_RESPONSE,
1451                SCI_FAILURE_IO_RESPONSE_VALID
1452             );
1453 
1454             sci_base_state_machine_change_state(
1455                &this_request->parent.parent.state_machine,
1456                SCI_BASE_REQUEST_STATE_COMPLETED
1457             );
1458          }
1459          else
1460          {
1461             // Now why is the drive sending a D2H Register FIS when it is still busy?
1462             // Do nothing since we are still in the right state.
1463             SCIC_LOG_INFO((
1464                sci_base_object_get_logger(this_request),
1465                SCIC_LOG_OBJECT_STP_IO_REQUEST,
1466                "SCIC PIO Request 0x%x received D2H Register FIS with BSY status 0x%x\n",
1467                this_request, frame_header->status
1468             ));
1469          }
1470          break;
1471 
1472          default:
1473          break;
1474          }
1475 
1476       // Frame is decoded return it to the controller
1477       scic_sds_controller_release_frame(
1478          owning_controller,
1479          frame_index
1480       );
1481    }
1482    else
1483    {
1484       SCIC_LOG_ERROR((
1485          sci_base_object_get_logger(this_request),
1486          SCIC_LOG_OBJECT_STP_IO_REQUEST,
1487          "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
1488          this_request, frame_index, status
1489       ));
1490    }
1491 
1492    return status;
1493 }
1494 
1495 /**
1496  *
1497  *
1498  * @param[in] this_request
1499  * @param[in] frame_index
1500  *
1501  * @return SCI_STATUS
1502  */
1503 static
1504 SCI_STATUS scic_sds_stp_request_pio_data_in_await_data_frame_handler(
1505    SCIC_SDS_REQUEST_T * request,
1506    U32                  frame_index
1507 )
1508 {
1509    SCI_STATUS               status;
1510    SATA_FIS_HEADER_T      * frame_header;
1511    SATA_FIS_DATA_T        * frame_buffer;
1512    SCIC_SDS_STP_REQUEST_T * this_request;
1513    SCIC_SDS_CONTROLLER_T  * owning_controller;
1514 
1515    this_request = (SCIC_SDS_STP_REQUEST_T *)request;
1516 
1517    // Save off the controller, so that we do not touch the request after it
1518    //  is completed.
1519    owning_controller = this_request->parent.owning_controller;
1520 
1521    SCIC_LOG_TRACE((
1522       sci_base_object_get_logger(this_request),
1523       SCIC_LOG_OBJECT_STP_IO_REQUEST,
1524       "scic_sds_stp_request_pio_data_in_await_data_frame_handler(0x%x, 0x%x) enter\n",
1525       this_request, frame_index
1526    ));
1527 
1528    status = scic_sds_unsolicited_frame_control_get_header(
1529       &(owning_controller->uf_control),
1530       frame_index,
1531       (void**) &frame_header
1532    );
1533 
1534    if (status == SCI_SUCCESS)
1535    {
1536       if (frame_header->fis_type == SATA_FIS_TYPE_DATA)
1537       {
1538          if (this_request->type.pio.request_current.sgl_pair == NULL)
1539          {
1540             this_request->parent.saved_rx_frame_index = frame_index;
1541             this_request->type.pio.pio_transfer_bytes = 0;
1542          }
1543          else
1544          {
1545             status = scic_sds_unsolicited_frame_control_get_buffer(
1546                &(owning_controller->uf_control),
1547                frame_index,
1548                (void**) &frame_buffer
1549             );
1550 
1551             status = scic_sds_stp_request_pio_data_in_copy_data(this_request, (U8 *)frame_buffer);
1552 
1553             // Frame is decoded return it to the controller
1554             scic_sds_controller_release_frame(
1555                owning_controller,
1556                frame_index
1557             );
1558          }
1559 
1560          // Check for the end of the transfer, are there more bytes remaining
1561          // for this data transfer
1562          if (
1563                (status == SCI_SUCCESS)
1564             && (this_request->type.pio.pio_transfer_bytes == 0)
1565             )
1566          {
1567             if ((this_request->type.pio.ending_status & ATA_STATUS_REG_BSY_BIT) == 0)
1568             {
1569                scic_sds_request_set_status(
1570                   &this_request->parent,
1571                   SCU_TASK_DONE_CHECK_RESPONSE,
1572                   SCI_FAILURE_IO_RESPONSE_VALID
1573                );
1574 
1575                sci_base_state_machine_change_state(
1576                   &this_request->parent.parent.state_machine,
1577                   SCI_BASE_REQUEST_STATE_COMPLETED
1578                );
1579             }
1580             else
1581             {
1582                sci_base_state_machine_change_state(
1583                   &this_request->parent.started_substate_machine,
1584                   SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1585                );
1586             }
1587          }
1588       }
1589       else
1590       {
1591          SCIC_LOG_ERROR((
1592             sci_base_object_get_logger(this_request),
1593             SCIC_LOG_OBJECT_STP_IO_REQUEST,
1594             "SCIC PIO Request 0x%x received frame %d with fis type 0x%02x when expecting a data fis.\n",
1595             this_request, frame_index, frame_header->fis_type
1596          ));
1597 
1598          scic_sds_request_set_status(
1599             &this_request->parent,
1600             SCU_TASK_DONE_GOOD,
1601             SCI_FAILURE_IO_REQUIRES_SCSI_ABORT
1602          );
1603 
1604          sci_base_state_machine_change_state(
1605             &this_request->parent.parent.state_machine,
1606             SCI_BASE_REQUEST_STATE_COMPLETED
1607          );
1608 
1609          // Frame is decoded return it to the controller
1610          scic_sds_controller_release_frame(
1611             owning_controller,
1612             frame_index
1613          );
1614       }
1615    }
1616    else
1617    {
1618       SCIC_LOG_ERROR((
1619          sci_base_object_get_logger(this_request),
1620          SCIC_LOG_OBJECT_STP_IO_REQUEST,
1621          "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
1622          this_request, frame_index, status
1623       ));
1624    }
1625 
1626    return status;
1627 }
1628 
1629 
1630 /**
1631  *
1632  *
1633  * @param[in] this_request
1634  * @param[in] completion_code
1635  *
1636  * @return SCI_STATUS
1637  */
1638 static
1639 SCI_STATUS scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler(
1640 
1641    SCIC_SDS_REQUEST_T * this_request,
1642    U32                  completion_code
1643 )
1644 {
1645    SCI_STATUS  status                     = SCI_SUCCESS;
1646    BOOL        all_frames_transferred     = FALSE;
1647 
1648    SCIC_SDS_STP_REQUEST_T *this_scic_sds_stp_request = (SCIC_SDS_STP_REQUEST_T *) this_request;
1649 
1650    SCIC_LOG_TRACE((
1651       sci_base_object_get_logger(this_request),
1652       SCIC_LOG_OBJECT_STP_IO_REQUEST,
1653       "scic_sds_stp_request_pio_data_in_await_h2d_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
1654       this_request, completion_code
1655    ));
1656 
1657    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
1658    {
1659       case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
1660          //Transmit data
1661          if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes != 0)
1662          {
1663             status = scic_sds_stp_request_pio_data_out_transmit_data ( this_request);
1664             if (status == SCI_SUCCESS)
1665             {
1666                if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0)
1667                all_frames_transferred = TRUE;
1668             }
1669          }
1670          else if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0)
1671          {
1672             //this will happen if the all data is written at the first time after the pio setup fis is recieved
1673             all_frames_transferred  = TRUE;
1674          }
1675 
1676          //all data transferred.
1677          if (all_frames_transferred)
1678          {
1679             //Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE
1680             //and wait for PIO_SETUP fis / or D2H REg fis.
1681             sci_base_state_machine_change_state(
1682                &this_request->started_substate_machine,
1683                SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1684             );
1685          }
1686          break;
1687 
1688       default:
1689          // All other completion status cause the IO to be complete.  If a NAK
1690          // was received, then it is up to the user to retry the request.
1691          scic_sds_request_set_status(
1692             this_request,
1693             SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
1694             SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
1695          );
1696 
1697          sci_base_state_machine_change_state(
1698             &this_request->parent.state_machine,
1699             SCI_BASE_REQUEST_STATE_COMPLETED
1700          );
1701          break;
1702    }
1703 
1704    return status;
1705 }
1706 
1707 /**
1708  * This method will handle any link layer events while waiting for the data
1709  * frame.
1710  *
1711  * @param[in] request This is the request which is receiving the event.
1712  * @param[in] event_code This is the event code that the request on which the
1713  *       request is expected to take action.
1714  *
1715  * @return SCI_STATUS
1716  * @retval SCI_SUCCESS
1717  * @retval SCI_FAILURE
1718  */
1719 static
1720 SCI_STATUS scic_sds_stp_request_pio_data_in_await_data_event_handler(
1721    SCIC_SDS_REQUEST_T * request,
1722    U32                  event_code
1723 )
1724 {
1725    SCI_STATUS status;
1726 
1727    switch (scu_get_event_specifier(event_code))
1728    {
1729    case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT:
1730       // We are waiting for data and the SCU has R_ERR the data frame.
1731       // Go back to waiting for the D2H Register FIS
1732       sci_base_state_machine_change_state(
1733          &request->started_substate_machine,
1734          SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1735       );
1736 
1737       status = SCI_SUCCESS;
1738       break;
1739 
1740    default:
1741       SCIC_LOG_ERROR((
1742          sci_base_object_get_logger(request),
1743          SCIC_LOG_OBJECT_STP_IO_REQUEST,
1744          "SCIC PIO Request 0x%x received unexpected event 0x%08x\n",
1745          request, event_code
1746       ));
1747 
1748       /// @todo Should we fail the PIO request when we get an unexpected event?
1749       status = SCI_FAILURE;
1750       break;
1751    }
1752 
1753    return status;
1754 }
1755 
1756 // ---------------------------------------------------------------------------
1757 
1758 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
1759    scic_sds_stp_request_started_pio_substate_handler_table
1760       [SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES] =
1761 {
1762    // SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
1763    {
1764       {
1765          scic_sds_request_default_start_handler,
1766          scic_sds_request_started_state_abort_handler,
1767          scic_sds_request_default_complete_handler,
1768          scic_sds_request_default_destruct_handler
1769       },
1770       scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler,
1771       scic_sds_request_default_event_handler,
1772       scic_sds_request_default_frame_handler
1773    },
1774    // SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1775    {
1776       {
1777          scic_sds_request_default_start_handler,
1778          //scic_sds_stp_pio_request_data_in_await_frame_abort_handler,
1779          scic_sds_request_started_state_abort_handler,
1780          scic_sds_request_default_complete_handler,
1781          scic_sds_request_default_destruct_handler
1782       },
1783       scic_sds_request_default_tc_completion_handler,
1784       scic_sds_request_default_event_handler,
1785       scic_sds_stp_request_pio_await_frame_frame_handler
1786    },
1787    // SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
1788    {
1789       {
1790          scic_sds_request_default_start_handler,
1791          //scic_sds_stp_pio_request_data_in_await_data_abort_handler,
1792          scic_sds_request_started_state_abort_handler,
1793          scic_sds_request_default_complete_handler,
1794          scic_sds_request_default_destruct_handler
1795       },
1796       scic_sds_request_default_tc_completion_handler,
1797       scic_sds_stp_request_pio_data_in_await_data_event_handler,
1798       scic_sds_stp_request_pio_data_in_await_data_frame_handler
1799    },
1800    //SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
1801    {
1802       {
1803          scic_sds_request_default_start_handler,
1804          scic_sds_request_started_state_abort_handler,
1805          scic_sds_request_default_complete_handler,
1806          scic_sds_request_default_destruct_handler
1807       },
1808       scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler,
1809       scic_sds_request_default_event_handler,
1810       scic_sds_request_default_frame_handler
1811    }
1812 };
1813 
1814 static
1815 void scic_sds_stp_request_started_pio_await_h2d_completion_enter(
1816    SCI_BASE_OBJECT_T *object
1817 )
1818 {
1819    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
1820 
1821    SET_STATE_HANDLER(
1822       this_request,
1823       scic_sds_stp_request_started_pio_substate_handler_table,
1824       SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
1825    );
1826 
1827    scic_sds_remote_device_set_working_request(
1828       this_request->target_device, this_request);
1829 }
1830 
1831 static
1832 void scic_sds_stp_request_started_pio_await_frame_enter(
1833    SCI_BASE_OBJECT_T *object
1834 )
1835 {
1836    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
1837 
1838    SET_STATE_HANDLER(
1839       this_request,
1840       scic_sds_stp_request_started_pio_substate_handler_table,
1841       SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1842    );
1843 }
1844 
1845 static
1846 void scic_sds_stp_request_started_pio_data_in_await_data_enter(
1847    SCI_BASE_OBJECT_T *object
1848 )
1849 {
1850    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
1851 
1852    SET_STATE_HANDLER(
1853       this_request,
1854       scic_sds_stp_request_started_pio_substate_handler_table,
1855       SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
1856    );
1857 }
1858 
1859 static
1860 void scic_sds_stp_request_started_pio_data_out_transmit_data_enter(
1861    SCI_BASE_OBJECT_T *object
1862 )
1863 {
1864    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
1865 
1866    SET_STATE_HANDLER(
1867       this_request,
1868       scic_sds_stp_request_started_pio_substate_handler_table,
1869       SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
1870    );
1871 }
1872 
1873 // ---------------------------------------------------------------------------
1874 
1875 SCI_BASE_STATE_T
1876    scic_sds_stp_request_started_pio_substate_table
1877       [SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES] =
1878 {
1879    {
1880       SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE,
1881       scic_sds_stp_request_started_pio_await_h2d_completion_enter,
1882       NULL
1883    },
1884    {
1885       SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE,
1886       scic_sds_stp_request_started_pio_await_frame_enter,
1887       NULL
1888    },
1889    {
1890       SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE,
1891       scic_sds_stp_request_started_pio_data_in_await_data_enter,
1892       NULL
1893    },
1894    {
1895       SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE,
1896       scic_sds_stp_request_started_pio_data_out_transmit_data_enter,
1897       NULL
1898    }
1899 };
1900 
1901 //******************************************************************************
1902 //* UDMA REQUEST STATE MACHINE
1903 //******************************************************************************
1904 
1905 static
1906 void scic_sds_stp_request_udma_complete_request(
1907    SCIC_SDS_REQUEST_T * this_request,
1908    U32                  scu_status,
1909    SCI_STATUS           sci_status
1910 )
1911 {
1912    scic_sds_request_set_status(
1913       this_request, scu_status, sci_status
1914    );
1915 
1916    sci_base_state_machine_change_state(
1917       &this_request->parent.state_machine,
1918       SCI_BASE_REQUEST_STATE_COMPLETED
1919    );
1920 }
1921 
1922 /**
1923  *
1924  *
1925  * @param[in] this_request
1926  * @param[in] frame_index
1927  *
1928  * @return SCI_STATUS
1929  */
1930 static
1931 SCI_STATUS scic_sds_stp_request_udma_general_frame_handler(
1932    SCIC_SDS_REQUEST_T * this_request,
1933    U32                  frame_index
1934 )
1935 {
1936    SCI_STATUS          status;
1937    SATA_FIS_HEADER_T * frame_header;
1938    U32               * frame_buffer;
1939 
1940    SCIC_LOG_TRACE((
1941       sci_base_object_get_logger(this_request),
1942       SCIC_LOG_OBJECT_STP_IO_REQUEST,
1943       "scic_sds_stp_pio_request_data_in_await_frame_frame_handler(0x%x, 0x%x) enter\n",
1944       this_request, frame_index
1945    ));
1946 
1947    status = scic_sds_unsolicited_frame_control_get_header(
1948       &this_request->owning_controller->uf_control,
1949       frame_index,
1950       (void**) &frame_header
1951    );
1952 
1953    if (
1954          (status == SCI_SUCCESS)
1955       && (frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
1956       )
1957    {
1958       scic_sds_unsolicited_frame_control_get_buffer(
1959          &this_request->owning_controller->uf_control,
1960          frame_index,
1961          (void**) &frame_buffer
1962       );
1963 
1964       scic_sds_controller_copy_sata_response(
1965          &((SCIC_SDS_STP_REQUEST_T *)this_request)->d2h_reg_fis,
1966          (U32 *)frame_header,
1967          frame_buffer
1968       );
1969    }
1970 
1971    scic_sds_controller_release_frame(
1972       this_request->owning_controller, frame_index);
1973 
1974    return status;
1975 }
1976 
1977 /**
1978  * @brief This method process TC completions while in the state where
1979  *        we are waiting for TC completions.
1980  *
1981  * @param[in] this_request
1982  * @param[in] completion_code
1983  *
1984  * @return SCI_STATUS
1985  */
1986 static
1987 SCI_STATUS scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler(
1988    SCIC_SDS_REQUEST_T * request,
1989    U32                  completion_code
1990 )
1991 {
1992    SCI_STATUS               status = SCI_SUCCESS;
1993    SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
1994 
1995    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
1996    {
1997    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
1998       scic_sds_stp_request_udma_complete_request(
1999          &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
2000       );
2001    break;
2002 
2003    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS):
2004    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR):
2005       // We must check ther response buffer to see if the D2H Register FIS was
2006       // received before we got the TC completion.
2007       if (this_request->d2h_reg_fis.fis_type == SATA_FIS_TYPE_REGD2H)
2008       {
2009          scic_sds_remote_device_suspend(
2010             this_request->parent.target_device,
2011             SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))
2012          );
2013 
2014          scic_sds_stp_request_udma_complete_request(
2015             &this_request->parent,
2016             SCU_TASK_DONE_CHECK_RESPONSE,
2017             SCI_FAILURE_IO_RESPONSE_VALID
2018          );
2019       }
2020       else
2021       {
2022          // If we have an error completion status for the TC then we can expect a
2023          // D2H register FIS from the device so we must change state to wait for it
2024          sci_base_state_machine_change_state(
2025             &this_request->parent.started_substate_machine,
2026             SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
2027          );
2028       }
2029    break;
2030 
2031    /// @todo Check to see if any of these completion status need to wait for
2032    ///       the device to host register fis.
2033    /// @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0
2034    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN):
2035    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
2036    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
2037    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
2038    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR):
2039       scic_sds_remote_device_suspend(
2040          this_request->parent.target_device,
2041          SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))
2042       );
2043       // Fall through to the default case
2044    default:
2045       // All other completion status cause the IO to be complete.
2046       SCIC_LOG_ERROR((
2047          sci_base_object_get_logger(&this_request->parent),
2048          SCIC_LOG_OBJECT_STP_IO_REQUEST,
2049          "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n",
2050          &this_request->parent, completion_code
2051       ));
2052       scic_sds_stp_request_udma_complete_request(
2053          &this_request->parent,
2054          SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
2055          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2056       );
2057       break;
2058    }
2059 
2060    return status;
2061 }
2062 
2063 static
2064 SCI_STATUS scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler(
2065    SCIC_SDS_REQUEST_T * this_request,
2066    U32                  frame_index
2067 )
2068 {
2069    SCI_STATUS status;
2070 
2071    // Use the general frame handler to copy the resposne data
2072    status = scic_sds_stp_request_udma_general_frame_handler(this_request, frame_index);
2073 
2074    if (status == SCI_SUCCESS)
2075    {
2076       scic_sds_stp_request_udma_complete_request(
2077          this_request,
2078          SCU_TASK_DONE_CHECK_RESPONSE,
2079          SCI_FAILURE_IO_RESPONSE_VALID
2080       );
2081    }
2082 
2083    return status;
2084 }
2085 
2086 // ---------------------------------------------------------------------------
2087 
2088 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
2089    scic_sds_stp_request_started_udma_substate_handler_table
2090       [SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES] =
2091 {
2092    // SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
2093    {
2094       {
2095          scic_sds_request_default_start_handler,
2096          scic_sds_request_started_state_abort_handler,
2097          scic_sds_request_default_complete_handler,
2098          scic_sds_request_default_destruct_handler
2099       },
2100       scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler,
2101       scic_sds_request_default_event_handler,
2102       scic_sds_stp_request_udma_general_frame_handler
2103    },
2104    // SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
2105    {
2106       {
2107          scic_sds_request_default_start_handler,
2108          scic_sds_request_started_state_abort_handler,
2109          scic_sds_request_default_complete_handler,
2110          scic_sds_request_default_destruct_handler
2111       },
2112       scic_sds_request_default_tc_completion_handler,
2113       scic_sds_request_default_event_handler,
2114       scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler
2115    }
2116 };
2117 
2118 /**
2119  *
2120  *
2121  * @param[in] object
2122  */
2123 static
2124 void scic_sds_stp_request_started_udma_await_tc_completion_enter(
2125    SCI_BASE_OBJECT_T *object
2126 )
2127 {
2128    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2129 
2130    SET_STATE_HANDLER(
2131       this_request,
2132       scic_sds_stp_request_started_udma_substate_handler_table,
2133       SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
2134    );
2135 }
2136 
2137 /**
2138  * This state is entered when there is an TC completion failure.  The hardware
2139  * received an unexpected condition while processing the IO request and now
2140  * will UF the D2H register FIS to complete the IO.
2141  *
2142  * @param[in] object
2143  */
2144 static
2145 void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter(
2146    SCI_BASE_OBJECT_T *object
2147 )
2148 {
2149    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2150 
2151    SET_STATE_HANDLER(
2152       this_request,
2153       scic_sds_stp_request_started_udma_substate_handler_table,
2154       SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
2155    );
2156 }
2157 
2158 // ---------------------------------------------------------------------------
2159 
2160 SCI_BASE_STATE_T
2161    scic_sds_stp_request_started_udma_substate_table
2162       [SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES] =
2163 {
2164    {
2165       SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE,
2166       scic_sds_stp_request_started_udma_await_tc_completion_enter,
2167       NULL
2168    },
2169    {
2170       SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE,
2171       scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter,
2172       NULL
2173    }
2174 };
2175 
2176 //******************************************************************************
2177 //* STP SOFT RESET STATE MACHINE
2178 //******************************************************************************
2179 
2180 /**
2181  * This method processes a TC completion.  The expected TC completion is
2182  * for the transmission of the H2D register FIS containing the SATA/STP
2183  * non-data request.
2184  *
2185  * @param[in] this_request
2186  * @param[in] completion_code
2187  *
2188  * @return This method always successfully processes the TC completion.
2189  * @retval SCI_SUCCESS This value is always returned.
2190  */
2191 static
2192 SCI_STATUS scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler(
2193    SCIC_SDS_REQUEST_T * this_request,
2194    U32                  completion_code
2195 )
2196 {
2197    SCIC_LOG_TRACE((
2198       sci_base_object_get_logger(this_request),
2199       SCIC_LOG_OBJECT_STP_IO_REQUEST,
2200       "scic_sds_stp_request_soft_reset_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n",
2201       this_request, completion_code
2202    ));
2203 
2204    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
2205    {
2206    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
2207       scic_sds_request_set_status(
2208          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
2209       );
2210 
2211       sci_base_state_machine_change_state(
2212          &this_request->started_substate_machine,
2213          SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
2214       );
2215       break;
2216 
2217    default:
2218       // All other completion status cause the IO to be complete.  If a NAK
2219       // was received, then it is up to the user to retry the request.
2220       scic_sds_request_set_status(
2221          this_request,
2222          SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
2223          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2224       );
2225 
2226       sci_base_state_machine_change_state(
2227          &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
2228       );
2229       break;
2230    }
2231 
2232    return SCI_SUCCESS;
2233 }
2234 
2235 /**
2236  * This method processes a TC completion.  The expected TC completion is
2237  * for the transmission of the H2D register FIS containing the SATA/STP
2238  * non-data request.
2239  *
2240  * @param[in] this_request
2241  * @param[in] completion_code
2242  *
2243  * @return This method always successfully processes the TC completion.
2244  * @retval SCI_SUCCESS This value is always returned.
2245  */
2246 static
2247 SCI_STATUS scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler(
2248    SCIC_SDS_REQUEST_T * this_request,
2249    U32                  completion_code
2250 )
2251 {
2252    SCIC_LOG_TRACE((
2253       sci_base_object_get_logger(this_request),
2254       SCIC_LOG_OBJECT_STP_IO_REQUEST,
2255       "scic_sds_stp_request_soft_reset_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n",
2256       this_request, completion_code
2257    ));
2258 
2259    switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
2260    {
2261    case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
2262       scic_sds_request_set_status(
2263          this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
2264       );
2265 
2266       sci_base_state_machine_change_state(
2267          &this_request->started_substate_machine,
2268          SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
2269       );
2270       break;
2271 
2272    default:
2273       // All other completion status cause the IO to be complete.  If a NAK
2274       // was received, then it is up to the user to retry the request.
2275       scic_sds_request_set_status(
2276          this_request,
2277          SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
2278          SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2279       );
2280 
2281       sci_base_state_machine_change_state(
2282          &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
2283       );
2284       break;
2285    }
2286 
2287    return SCI_SUCCESS;
2288 }
2289 
2290 /**
2291  * This method processes frames received from the target while waiting
2292  * for a device to host register FIS.  If a non-register FIS is received
2293  * during this time, it is treated as a protocol violation from an
2294  * IO perspective.
2295  *
2296  * @param[in] request This parameter specifies the request for which a
2297  *            frame has been received.
2298  * @param[in] frame_index This parameter specifies the index of the frame
2299  *            that has been received.
2300  *
2301  * @return Indicate if the received frame was processed successfully.
2302  */
2303 static
2304 SCI_STATUS scic_sds_stp_request_soft_reset_await_d2h_frame_handler(
2305    SCIC_SDS_REQUEST_T * request,
2306    U32                  frame_index
2307 )
2308 {
2309    SCI_STATUS               status;
2310    SATA_FIS_HEADER_T      * frame_header;
2311    U32                    * frame_buffer;
2312    SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
2313 
2314    // Save off the controller, so that we do not touch the request after it
2315    //  is completed.
2316    SCIC_SDS_CONTROLLER_T  * owning_controller = this_request->parent.owning_controller;
2317 
2318    SCIC_LOG_TRACE((
2319       sci_base_object_get_logger(this_request),
2320       SCIC_LOG_OBJECT_STP_IO_REQUEST,
2321       "scic_sds_stp_request_soft_reset_await_d2h_frame_handler(0x%x, 0x%x) enter\n",
2322       this_request, frame_index
2323    ));
2324 
2325    status = scic_sds_unsolicited_frame_control_get_header(
2326                &(owning_controller->uf_control),
2327                frame_index,
2328                (void**) &frame_header
2329             );
2330 
2331    if (status == SCI_SUCCESS)
2332    {
2333       switch (frame_header->fis_type)
2334       {
2335       case SATA_FIS_TYPE_REGD2H:
2336          scic_sds_unsolicited_frame_control_get_buffer(
2337             &(owning_controller->uf_control),
2338             frame_index,
2339             (void**) &frame_buffer
2340          );
2341 
2342          scic_sds_controller_copy_sata_response(
2343             &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
2344          );
2345 
2346          // The command has completed with error
2347          scic_sds_request_set_status(
2348             &this_request->parent,
2349             SCU_TASK_DONE_CHECK_RESPONSE,
2350             SCI_FAILURE_IO_RESPONSE_VALID
2351          );
2352          break;
2353 
2354       default:
2355          SCIC_LOG_WARNING((
2356             sci_base_object_get_logger(this_request),
2357             SCIC_LOG_OBJECT_STP_IO_REQUEST,
2358             "IO Request:0x%x Frame Id:%d protocol violation occurred\n",
2359             this_request, frame_index
2360          ));
2361 
2362          scic_sds_request_set_status(
2363             &this_request->parent,
2364             SCU_TASK_DONE_UNEXP_FIS,
2365             SCI_FAILURE_PROTOCOL_VIOLATION
2366          );
2367          break;
2368       }
2369 
2370       sci_base_state_machine_change_state(
2371          &this_request->parent.parent.state_machine,
2372          SCI_BASE_REQUEST_STATE_COMPLETED
2373       );
2374 
2375       // Frame has been decoded return it to the controller
2376       scic_sds_controller_release_frame(
2377          owning_controller, frame_index
2378       );
2379    }
2380    else
2381    {
2382       SCIC_LOG_ERROR((
2383          sci_base_object_get_logger(this_request),
2384          SCIC_LOG_OBJECT_STP_IO_REQUEST,
2385          "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
2386          this_request, frame_index, status
2387       ));
2388    }
2389 
2390    return status;
2391 }
2392 
2393 // ---------------------------------------------------------------------------
2394 
2395 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
2396    scic_sds_stp_request_started_soft_reset_substate_handler_table
2397       [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES] =
2398 {
2399    // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
2400    {
2401       {
2402          scic_sds_request_default_start_handler,
2403          scic_sds_request_started_state_abort_handler,
2404          scic_sds_request_default_complete_handler,
2405          scic_sds_request_default_destruct_handler
2406       },
2407       scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler,
2408       scic_sds_request_default_event_handler,
2409       scic_sds_request_default_frame_handler
2410    },
2411    // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
2412    {
2413       {
2414          scic_sds_request_default_start_handler,
2415          scic_sds_request_started_state_abort_handler,
2416          scic_sds_request_default_complete_handler,
2417          scic_sds_request_default_destruct_handler
2418       },
2419       scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler,
2420       scic_sds_request_default_event_handler,
2421       scic_sds_request_default_frame_handler
2422    },
2423    // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
2424    {
2425       {
2426          scic_sds_request_default_start_handler,
2427          scic_sds_request_started_state_abort_handler,
2428          scic_sds_request_default_complete_handler,
2429          scic_sds_request_default_destruct_handler
2430       },
2431       scic_sds_request_default_tc_completion_handler,
2432       scic_sds_request_default_event_handler,
2433       scic_sds_stp_request_soft_reset_await_d2h_frame_handler
2434    }
2435 };
2436 
2437 static
2438 void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(
2439    SCI_BASE_OBJECT_T *object
2440 )
2441 {
2442    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2443 
2444    SET_STATE_HANDLER(
2445       this_request,
2446       scic_sds_stp_request_started_soft_reset_substate_handler_table,
2447       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
2448    );
2449 
2450    scic_sds_remote_device_set_working_request(
2451       this_request->target_device, this_request
2452    );
2453 }
2454 
2455 static
2456 void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(
2457    SCI_BASE_OBJECT_T *object
2458 )
2459 {
2460    SCI_STATUS status;
2461    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2462    SATA_FIS_REG_H2D_T *h2d_fis;
2463    SCU_TASK_CONTEXT_T *task_context;
2464 
2465    // Clear the SRST bit
2466    h2d_fis = scic_stp_io_request_get_h2d_reg_address(this_request);
2467    h2d_fis->control = 0;
2468 
2469    // Clear the TC control bit
2470    task_context = scic_sds_controller_get_task_context_buffer(
2471                         this_request->owning_controller, this_request->io_tag);
2472    task_context->control_frame = 0;
2473 
2474    status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
2475       &this_request->owning_controller->parent,
2476       &this_request->target_device->parent,
2477       &this_request->parent
2478    );
2479 
2480    if (status == SCI_SUCCESS)
2481    {
2482       SET_STATE_HANDLER(
2483          this_request,
2484          scic_sds_stp_request_started_soft_reset_substate_handler_table,
2485          SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
2486       );
2487    }
2488 }
2489 
2490 static
2491 void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter(
2492    SCI_BASE_OBJECT_T *object
2493 )
2494 {
2495    SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2496 
2497    SET_STATE_HANDLER(
2498       this_request,
2499       scic_sds_stp_request_started_soft_reset_substate_handler_table,
2500       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
2501    );
2502 }
2503 
2504 // ---------------------------------------------------------------------------
2505 
2506 SCI_BASE_STATE_T
2507    scic_sds_stp_request_started_soft_reset_substate_table
2508       [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES] =
2509 {
2510    {
2511       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE,
2512       scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter,
2513       NULL
2514    },
2515    {
2516       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE,
2517       scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter,
2518       NULL
2519    },
2520    {
2521       SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE,
2522       scic_sds_stp_request_started_soft_reset_await_d2h_response_enter,
2523       NULL
2524    }
2525 };
2526 
2527 // ---------------------------------------------------------------------------
2528 
2529 SCI_STATUS scic_io_request_construct_basic_sata(
2530    SCI_IO_REQUEST_HANDLE_T  scic_io_request
2531 )
2532 {
2533    SCI_STATUS           status;
2534    SCIC_SDS_REQUEST_T * request = (SCIC_SDS_REQUEST_T *)scic_io_request;
2535 
2536    SCIC_LOG_TRACE((
2537       sci_base_object_get_logger(scic_io_request),
2538       SCIC_LOG_OBJECT_STP_IO_REQUEST,
2539       "scic_io_request_construct_basic_sata(0x%x) enter\n",
2540       scic_io_request
2541    ));
2542 
2543    status = scic_sds_io_request_construct_sata(
2544                request,
2545                scic_cb_request_get_sat_protocol(request->user_request),
2546                scic_cb_io_request_get_transfer_length(request->user_request),
2547                scic_cb_io_request_get_data_direction(request->user_request),
2548                scic_cb_io_request_do_copy_rx_frames(request->user_request),
2549                TRUE
2550             );
2551 
2552    return status;
2553 }
2554 
2555 // ---------------------------------------------------------------------------
2556 
2557 SCI_STATUS scic_io_request_construct_advanced_sata(
2558    SCI_IO_REQUEST_HANDLE_T     scic_io_request,
2559    SCIC_IO_SATA_PARAMETERS_T * io_parameters
2560 )
2561 {
2562    SCI_STATUS           status;
2563    SCIC_SDS_REQUEST_T * request = (SCIC_SDS_REQUEST_T *)scic_io_request;
2564 
2565    SCIC_LOG_TRACE((
2566       sci_base_object_get_logger(scic_io_request),
2567       SCIC_LOG_OBJECT_STP_IO_REQUEST,
2568       "scic_io_request_construct_basic_sata(0x%x) enter\n",
2569       scic_io_request
2570    ));
2571 
2572    status = scic_sds_io_request_construct_sata(
2573                request,
2574                scic_cb_request_get_sat_protocol(request->user_request),
2575                scic_sds_request_get_sgl_element_pair(request, 0)->A.length,
2576                scic_cb_io_request_get_data_direction(request->user_request),
2577                scic_cb_io_request_do_copy_rx_frames(request->user_request),
2578                io_parameters->do_translate_sgl
2579             );
2580 
2581    return status;
2582 }
2583 
2584