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