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