11556Srgrimes/*-
21556Srgrimes * This file is provided under a dual BSD/GPLv2 license.  When using or
31556Srgrimes * redistributing this file, you may do so under either license.
41556Srgrimes *
51556Srgrimes * GPL LICENSE SUMMARY
61556Srgrimes *
71556Srgrimes * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
81556Srgrimes *
91556Srgrimes * This program is free software; you can redistribute it and/or modify
101556Srgrimes * it under the terms of version 2 of the GNU General Public License as
111556Srgrimes * published by the Free Software Foundation.
121556Srgrimes *
131556Srgrimes * This program is distributed in the hope that it will be useful, but
141556Srgrimes * WITHOUT ANY WARRANTY; without even the implied warranty of
151556Srgrimes * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
161556Srgrimes * General Public License for more details.
171556Srgrimes *
181556Srgrimes * You should have received a copy of the GNU General Public License
191556Srgrimes * along with this program; if not, write to the Free Software
201556Srgrimes * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
211556Srgrimes * The full GNU General Public License is included in this distribution
221556Srgrimes * in the file called LICENSE.GPL.
231556Srgrimes *
241556Srgrimes * BSD LICENSE
251556Srgrimes *
261556Srgrimes * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
271556Srgrimes * All rights reserved.
281556Srgrimes *
291556Srgrimes * Redistribution and use in source and binary forms, with or without
301556Srgrimes * modification, are permitted provided that the following conditions
311556Srgrimes * are met:
321556Srgrimes *
331556Srgrimes *   * Redistributions of source code must retain the above copyright
341556Srgrimes *     notice, this list of conditions and the following disclaimer.
351556Srgrimes *   * Redistributions in binary form must reproduce the above copyright
361556Srgrimes *     notice, this list of conditions and the following disclaimer in
371556Srgrimes *     the documentation and/or other materials provided with the
3827967Ssteve *     distribution.
3927967Ssteve *
4027967Ssteve * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4127958Ssteve * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4235373Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4327967Ssteve * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
441556Srgrimes * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
451556Srgrimes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
461556Srgrimes * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
471556Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
481556Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
491556Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
501556Srgrimes * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
511556Srgrimes */
521556Srgrimes
531556Srgrimes#include <sys/cdefs.h>
541556Srgrimes__FBSDID("$FreeBSD$");
551556Srgrimes
561556Srgrimes#include <dev/isci/scil/intel_sat.h>
571556Srgrimes#include <dev/isci/scil/intel_sata.h>
581556Srgrimes#include <dev/isci/scil/sci_types.h>
591556Srgrimes#include <dev/isci/scil/scic_remote_device.h>
601556Srgrimes#include <dev/isci/scil/scic_user_callback.h>
611556Srgrimes#include <dev/isci/scil/scic_sds_controller.h>
621556Srgrimes#include <dev/isci/scil/scic_sds_remote_device.h>
631556Srgrimes#include <dev/isci/scil/scic_sds_stp_request.h>
641556Srgrimes#include <dev/isci/scil/scic_sds_stp_pio_request.h>
651556Srgrimes#include <dev/isci/scil/scic_sds_logger.h>
661556Srgrimes#include <dev/isci/sci_environment.h>
671556Srgrimes#include <dev/isci/scil/sci_base_state_machine.h>
681556Srgrimes#include <dev/isci/scil/scu_task_context.h>
691556Srgrimes#include <dev/isci/scil/intel_ata.h>
701556Srgrimes#include <dev/isci/scil/sci_util.h>
711556Srgrimes#include <dev/isci/scil/scic_sds_logger.h>
721556Srgrimes#include <dev/isci/scil/scic_sds_request.h>
731556Srgrimes#include <dev/isci/scil/scic_sds_stp_request.h>
741556Srgrimes#include <dev/isci/scil/scu_completion_codes.h>
751556Srgrimes#include <dev/isci/scil/scu_event_codes.h>
761556Srgrimes#include <dev/isci/scil/sci_base_state.h>
771556Srgrimes#include <dev/isci/scil/scic_sds_unsolicited_frame_control.h>
781556Srgrimes#include <dev/isci/scil/scic_io_request.h>
791556Srgrimes
801556Srgrimes#if !defined(DISABLE_ATAPI)
811556Srgrimes#include <dev/isci/scil/scic_sds_stp_packet_request.h>
821556Srgrimes#endif
831556Srgrimes
841556Srgrimes/**
851556Srgrimes * This macro returns the address of the stp h2d reg fis buffer in the io
861556Srgrimes * request memory
871556Srgrimes */
881556Srgrimes#define scic_sds_stp_request_get_h2d_reg_buffer_unaligned(memory) \
891556Srgrimes   ((SATA_FIS_REG_H2D_T *)( \
901556Srgrimes      ((char *)(memory)) + sizeof(SCIC_SDS_STP_REQUEST_T) \
911556Srgrimes   ))
921556Srgrimes
931556Srgrimes/**
941556Srgrimes * This macro aligns the stp command buffer in DWORD alignment
951556Srgrimes*/
961556Srgrimes#define scic_sds_stp_request_align_h2d_reg_buffer(address) \
971556Srgrimes   ((SATA_FIS_REG_H2D_T *)( \
981556Srgrimes      (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
991556Srgrimes         & ~(sizeof(U32)- 1) \
1001556Srgrimes      ))
10120417Ssteve
1021556Srgrimes/**
1031556Srgrimes * This macro returns the DWORD-aligned stp command buffer
1041556Srgrimes*/
1051556Srgrimes#define scic_sds_stp_request_get_h2d_reg_buffer(memory) \
1061556Srgrimes   ((SATA_FIS_REG_H2D_T *)  \
1071556Srgrimes       ((char *)scic_sds_stp_request_align_h2d_reg_buffer( \
1081556Srgrimes       (char *) scic_sds_stp_request_get_h2d_reg_buffer_unaligned(memory) \
1091556Srgrimes   )))
1101556Srgrimes
1111556Srgrimes/**
1121556Srgrimes * This macro returns the address of the stp response buffer in the io
11313120Sjoerg * request memory
11413120Sjoerg */
11513120Sjoerg#define scic_sds_stp_request_get_response_buffer_unaligned(memory) \
11613120Sjoerg   ((SATA_FIS_REG_D2H_T *)( \
11713120Sjoerg         ((char *)(scic_sds_stp_request_get_h2d_reg_buffer(memory))) \
11813120Sjoerg       + sizeof(SATA_FIS_REG_H2D_T) \
1191556Srgrimes   ))
1201556Srgrimes
1211556Srgrimes
1221556Srgrimes/**
1231556Srgrimes * This macro aligns the stp response buffer in DWORD alignment
1241556Srgrimes*/
1251556Srgrimes#define scic_sds_stp_request_align_response_buffer(address) \
1261556Srgrimes   ((SATA_FIS_REG_D2H_T *)( \
1271556Srgrimes      (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
1281556Srgrimes         & ~(sizeof(U32)- 1) \
1291556Srgrimes   ))
13035373Sdes
13135373Sdes/**
1321556Srgrimes * This macro returns the DWORD-aligned stp response buffer
1331556Srgrimes*/
1341556Srgrimes#define scic_sds_stp_request_get_response_buffer(memory) \
1351556Srgrimes   ((SATA_FIS_REG_D2H_T *)  \
1361556Srgrimes      ((char *)scic_sds_stp_request_align_response_buffer( \
1371556Srgrimes         (char *)scic_sds_stp_request_get_response_buffer_unaligned(memory) \
1381556Srgrimes   )))
1391556Srgrimes
1401556Srgrimes
1411556Srgrimes/**
1421556Srgrimes * This macro returns the address of the task context buffer in the io
1431556Srgrimes * request memory
1441556Srgrimes */
1451556Srgrimes#define scic_sds_stp_request_get_task_context_buffer_unaligned(memory) \
1461556Srgrimes   ((SCU_TASK_CONTEXT_T *)( \
1471556Srgrimes        ((char *)(scic_sds_stp_request_get_response_buffer(memory))) \
1481556Srgrimes      + sizeof(SCI_SSP_RESPONSE_IU_T) \
1491556Srgrimes   ))
1501556Srgrimes
1511556Srgrimes/**
1521556Srgrimes * This macro returns the aligned task context buffer
1531556Srgrimes */
1541556Srgrimes#define scic_sds_stp_request_get_task_context_buffer(memory) \
1551556Srgrimes   ((SCU_TASK_CONTEXT_T *)( \
1561556Srgrimes      ((char *)scic_sds_request_align_task_context_buffer( \
1571556Srgrimes         (char *)scic_sds_stp_request_get_task_context_buffer_unaligned(memory)) \
1581556Srgrimes    )))
1591556Srgrimes
1601556Srgrimes/**
1611556Srgrimes * This macro returns the address of the sgl elment pairs in the io request
1621556Srgrimes * memory buffer
1631556Srgrimes */
1641556Srgrimes#define scic_sds_stp_request_get_sgl_element_buffer(memory) \
1651556Srgrimes   ((SCU_SGL_ELEMENT_PAIR_T *)( \
1661556Srgrimes        ((char *)(scic_sds_stp_request_get_task_context_buffer(memory))) \
1671556Srgrimes      + sizeof(SCU_TASK_CONTEXT_T) \
1681556Srgrimes    ))
1691556Srgrimes
1701556Srgrimes
1711556Srgrimes/**
1721556Srgrimes * This method return the memory space commonly required for STP IO and
1731556Srgrimes * task requests.
1741556Srgrimes *
1751556Srgrimes * @return U32
1761556Srgrimes */
1771556Srgrimesstatic
1781556SrgrimesU32 scic_sds_stp_common_request_get_object_size(void)
1791556Srgrimes{
1801556Srgrimes   return   sizeof(SCIC_SDS_STP_REQUEST_T)
1811556Srgrimes          + sizeof(SATA_FIS_REG_H2D_T)
1821556Srgrimes          + sizeof(U32)
1831556Srgrimes          + sizeof(SATA_FIS_REG_D2H_T)
1841556Srgrimes          + sizeof(U32)
1851556Srgrimes          + sizeof(SCU_TASK_CONTEXT_T)
1861556Srgrimes          + CACHE_LINE_SIZE;
1871556Srgrimes}
1881556Srgrimes
1891556Srgrimes
1901556Srgrimes/**
1911556Srgrimes * This method return the memory space required for STP PIO requests.
1921556Srgrimes *
1931556Srgrimes * @return U32
1941556Srgrimes */
1951556SrgrimesU32 scic_sds_stp_request_get_object_size(void)
1961556Srgrimes{
1977165Sjoerg   return   scic_sds_stp_common_request_get_object_size()
1981556Srgrimes          + sizeof(SCU_SGL_ELEMENT_PAIR_T) * SCU_MAX_SGL_ELEMENT_PAIRS;
1991556Srgrimes}
2001556Srgrimes
2011556Srgrimes
2021556Srgrimes/**
2031556Srgrimes * This method return the memory space required for STP task requests.
2041556Srgrimes *
2051556Srgrimes * @return U32
2061556Srgrimes */
2071556SrgrimesU32 scic_sds_stp_task_request_get_object_size(void)
2081556Srgrimes{
2091556Srgrimes   return scic_sds_stp_common_request_get_object_size();
2101556Srgrimes}
2111556Srgrimes
2121556Srgrimes
2131556Srgrimes/**
2141556Srgrimes *
2151556Srgrimes *
2161556Srgrimes * @param[in] this_request
2171556Srgrimes */
2181556Srgrimesvoid scic_sds_stp_request_assign_buffers(
2191556Srgrimes   SCIC_SDS_REQUEST_T * request
2201556Srgrimes)
2211556Srgrimes{
22220417Ssteve   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
2231556Srgrimes
2241556Srgrimes   this_request->parent.command_buffer =
2251556Srgrimes      scic_sds_stp_request_get_h2d_reg_buffer(this_request);
22635373Sdes   this_request->parent.response_buffer =
2271556Srgrimes      scic_sds_stp_request_get_response_buffer(this_request);
2281556Srgrimes   this_request->parent.sgl_element_pair_buffer =
2291556Srgrimes      scic_sds_stp_request_get_sgl_element_buffer(this_request);
2301556Srgrimes   this_request->parent.sgl_element_pair_buffer =
2311556Srgrimes      scic_sds_request_align_sgl_element_buffer(this_request->parent.sgl_element_pair_buffer);
2321556Srgrimes
2331556Srgrimes   if (this_request->parent.was_tag_assigned_by_user == FALSE)
2341556Srgrimes   {
2351556Srgrimes      this_request->parent.task_context_buffer =
2361556Srgrimes         scic_sds_stp_request_get_task_context_buffer(this_request);
2379991Sache   }
23821545Smpp}
2391556Srgrimes
24021545Smpp/**
24121545Smpp * @brief This method is will fill in the SCU Task Context for any type of
24221545Smpp *        SATA request.  This is called from the various SATA constructors.
2439991Sache *
2441556Srgrimes * @pre The general io request construction is complete.
2451556Srgrimes * @pre The buffer assignment for the command buffer is complete.
2461556Srgrimes *
2479987Swollman * @param[in] this_request The general IO request object which is to be used
2481556Srgrimes *       in constructing the SCU task context.
2491556Srgrimes * @param[in] task_context The buffer pointer for the SCU task context which
2501556Srgrimes *       is being constructed.
25121545Smpp *
2521556Srgrimes * @return none
2531556Srgrimes *
2541556Srgrimes * @todo Revisit task context construction to determine what is common for
2551556Srgrimes *       SSP/SMP/STP task context structures.
2561556Srgrimes */
2571556Srgrimesvoid scu_sata_reqeust_construct_task_context(
2581556Srgrimes   SCIC_SDS_REQUEST_T * this_request,
2591556Srgrimes   SCU_TASK_CONTEXT_T * task_context
2601556Srgrimes)
2611556Srgrimes{
2621556Srgrimes   SCI_PHYSICAL_ADDRESS      physical_address;
2631556Srgrimes   SCIC_SDS_CONTROLLER_T    *owning_controller;
2641556Srgrimes   SCIC_SDS_REMOTE_DEVICE_T *target_device;
2651556Srgrimes   SCIC_SDS_PORT_T          *target_port;
2661556Srgrimes
2671556Srgrimes   owning_controller = scic_sds_request_get_controller(this_request);
2681556Srgrimes   target_device = scic_sds_request_get_device(this_request);
2691556Srgrimes   target_port = scic_sds_request_get_port(this_request);
2701556Srgrimes
2711556Srgrimes   // Fill in the TC with the its required data
2721556Srgrimes   task_context->abort = 0;
2731556Srgrimes   task_context->priority = SCU_TASK_PRIORITY_NORMAL;
2741556Srgrimes   task_context->initiator_request = 1;
2751556Srgrimes   task_context->connection_rate =
2761556Srgrimes      scic_remote_device_get_connection_rate(target_device);
2771556Srgrimes   task_context->protocol_engine_index =
2781556Srgrimes      scic_sds_controller_get_protocol_engine_group(owning_controller);
27920417Ssteve   task_context->logical_port_index =
28020417Ssteve      scic_sds_port_get_index(target_port);
28120417Ssteve   task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP;
2821556Srgrimes   task_context->valid = SCU_TASK_CONTEXT_VALID;
2831556Srgrimes   task_context->context_type = SCU_TASK_CONTEXT_TYPE;
2841556Srgrimes
2851556Srgrimes   task_context->remote_node_index =
2861556Srgrimes      scic_sds_remote_device_get_index(this_request->target_device);
2871556Srgrimes   task_context->command_code = 0;
2881556Srgrimes
2891556Srgrimes   task_context->link_layer_control = 0;
2901556Srgrimes   task_context->do_not_dma_ssp_good_response = 1;
2911556Srgrimes   task_context->strict_ordering = 0;
2921556Srgrimes   task_context->control_frame = 0;
2931556Srgrimes   task_context->timeout_enable = 0;
2941556Srgrimes   task_context->block_guard_enable = 0;
2951556Srgrimes
2961556Srgrimes   task_context->address_modifier = 0;
2971556Srgrimes   task_context->task_phase = 0x01;
2981556Srgrimes
2998855Srgrimes   task_context->ssp_command_iu_length =
3001556Srgrimes      (sizeof(SATA_FIS_REG_H2D_T) - sizeof(U32)) / sizeof(U32);
3011556Srgrimes
3021556Srgrimes   // Set the first word of the H2D REG FIS
3031556Srgrimes   task_context->type.words[0] = *(U32 *)this_request->command_buffer;
3041556Srgrimes
3051556Srgrimes   if (this_request->was_tag_assigned_by_user)
3061556Srgrimes   {
30735373Sdes      // Build the task context now since we have already read the data
30835373Sdes      this_request->post_context = (
30935373Sdes           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
31035373Sdes         | (
31135373Sdes                scic_sds_controller_get_protocol_engine_group(owning_controller)
3121556Srgrimes             << 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