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 */
177static
178U32 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 */
195U32 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 */
207U32 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 */
218void 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 */
257void 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 */
367void 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 */
388static
389void 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 */
433void 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 */
457SCI_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
480SCI_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 */
516SCI_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
627void 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
642void * 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
653void * 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 */
677SCU_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 */
734SCI_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 */
798static
799SCI_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 */
855static
856SCI_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
947SCIC_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
977static
978void 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
995static
996void 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
1011SCI_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 */
1041static
1042SCI_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 */
1091static
1092SCI_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 */
1163static
1164SCI_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 */
1243static
1244SCI_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 */
1291static
1292SCI_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 */
1346static
1347SCI_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 */
1500static
1501SCI_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 */
1635static
1636SCI_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 */
1716static
1717SCI_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
1755SCIC_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
1811static
1812void 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
1828static
1829void 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
1842static
1843void 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
1856static
1857void 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
1872SCI_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
1902static
1903void 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 */
1927static
1928SCI_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 */
1983static
1984SCI_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
2060static
2061SCI_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
2085SCIC_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 */
2120static
2121void 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 */
2141static
2142void 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
2157SCI_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 */
2188static
2189SCI_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 */
2243static
2244SCI_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 */
2300static
2301SCI_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
2392SCIC_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
2434static
2435void 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
2452static
2453void 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
2487static
2488void 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
2503SCI_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
2526SCI_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
2554SCI_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
2581