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