1230557Sjimharris/*-
2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license.  When using or
3230557Sjimharris * redistributing this file, you may do so under either license.
4230557Sjimharris *
5230557Sjimharris * GPL LICENSE SUMMARY
6230557Sjimharris *
7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8230557Sjimharris *
9230557Sjimharris * This program is free software; you can redistribute it and/or modify
10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as
11230557Sjimharris * published by the Free Software Foundation.
12230557Sjimharris *
13230557Sjimharris * This program is distributed in the hope that it will be useful, but
14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of
15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16230557Sjimharris * General Public License for more details.
17230557Sjimharris *
18230557Sjimharris * You should have received a copy of the GNU General Public License
19230557Sjimharris * along with this program; if not, write to the Free Software
20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21230557Sjimharris * The full GNU General Public License is included in this distribution
22230557Sjimharris * in the file called LICENSE.GPL.
23230557Sjimharris *
24230557Sjimharris * BSD LICENSE
25230557Sjimharris *
26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27230557Sjimharris * All rights reserved.
28230557Sjimharris *
29230557Sjimharris * Redistribution and use in source and binary forms, with or without
30230557Sjimharris * modification, are permitted provided that the following conditions
31230557Sjimharris * are met:
32230557Sjimharris *
33230557Sjimharris *   * Redistributions of source code must retain the above copyright
34230557Sjimharris *     notice, this list of conditions and the following disclaimer.
35230557Sjimharris *   * Redistributions in binary form must reproduce the above copyright
36230557Sjimharris *     notice, this list of conditions and the following disclaimer in
37230557Sjimharris *     the documentation and/or other materials provided with the
38230557Sjimharris *     distribution.
39230557Sjimharris *
40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51230557Sjimharris */
52230557Sjimharris
53230557Sjimharris#include <sys/cdefs.h>
54230557Sjimharris__FBSDID("$FreeBSD$");
55230557Sjimharris
56230557Sjimharris#if !defined(DISABLE_ATAPI)
57230557Sjimharris
58230557Sjimharris#include <dev/isci/scil/scic_sds_stp_packet_request.h>
59230557Sjimharris#include <dev/isci/scil/scic_sds_logger.h>
60230557Sjimharris#include <dev/isci/scil/scic_sds_controller.h>
61230557Sjimharris#include <dev/isci/scil/scic_sds_remote_device.h>
62230557Sjimharris#include <dev/isci/scil/scic_remote_device.h>
63230557Sjimharris#include <dev/isci/scil/sci_util.h>
64230557Sjimharris#include <dev/isci/scil/intel_sas.h>
65230557Sjimharris#include <dev/isci/scil/intel_ata.h>
66230557Sjimharris#include <dev/isci/scil/intel_sata.h>
67230557Sjimharris#include <dev/isci/scil/scic_user_callback.h>
68230557Sjimharris#include <dev/isci/sci_environment.h>
69230557Sjimharris#include <dev/isci/scil/intel_sat.h>
70230557Sjimharris#include <dev/isci/scil/scic_sds_request.h>
71230557Sjimharris#include <dev/isci/scil/scic_controller.h>
72230557Sjimharris#include <dev/isci/scil/scu_completion_codes.h>
73230557Sjimharris#include <dev/isci/scil/scu_task_context.h>
74230557Sjimharris#include <dev/isci/scil/scic_sds_stp_packet_request.h>
75230557Sjimharris#include <dev/isci/scil/sci_base_state.h>
76230557Sjimharris
77230557Sjimharris/**
78230557Sjimharris * @brief This method will fill in the SCU Task Context for a PACKET fis. And
79230557Sjimharris *           construct the request STARTED sub-state machine for Packet Protocol
80230557Sjimharris *           IO.
81230557Sjimharris *
82230557Sjimharris * @param[in] this_request This parameter specifies the stp packet request object
83230557Sjimharris *            being constructed.
84230557Sjimharris *
85230557Sjimharris * @return none
86230557Sjimharris */
87230557SjimharrisSCI_STATUS scic_sds_stp_packet_request_construct(
88230557Sjimharris   SCIC_SDS_REQUEST_T *this_request
89230557Sjimharris)
90230557Sjimharris{
91230557Sjimharris   SATA_FIS_REG_H2D_T * h2d_fis =
92230557Sjimharris      scic_stp_io_request_get_h2d_reg_address(
93230557Sjimharris         this_request
94230557Sjimharris      );
95230557Sjimharris
96230557Sjimharris   // Work around, we currently only support PACKET DMA protocol, so we
97230557Sjimharris   // need to make change to Packet Fis features field.
98230557Sjimharris   h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA;
99230557Sjimharris
100230557Sjimharris   scic_sds_stp_non_ncq_request_construct(this_request);
101230557Sjimharris
102230557Sjimharris   // Build the Packet Fis task context structure
103230557Sjimharris   scu_stp_raw_request_construct_task_context(
104230557Sjimharris      (SCIC_SDS_STP_REQUEST_T*) this_request,
105230557Sjimharris      this_request->task_context_buffer
106230557Sjimharris   );
107230557Sjimharris
108230557Sjimharris   sci_base_state_machine_construct(
109230557Sjimharris      &this_request->started_substate_machine,
110230557Sjimharris      &this_request->parent.parent,
111230557Sjimharris      scic_sds_stp_packet_request_started_substate_table,
112230557Sjimharris      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
113230557Sjimharris   );
114230557Sjimharris
115230557Sjimharris   return SCI_SUCCESS;
116230557Sjimharris}
117230557Sjimharris
118230557Sjimharris
119230557Sjimharris/**
120230557Sjimharris * @brief This method will fill in the SCU Task Context for a Packet request
121230557Sjimharris *        command phase in PACKET DMA DATA (IN/OUT) type. The following
122230557Sjimharris *        important settings are utilized:
123230557Sjimharris *
124230557Sjimharris *          -# task_type == SCU_TASK_TYPE_PACKET_DMA.  This simply indicates
125230557Sjimharris *             that a normal request type (i.e. non-raw frame) is being
126230557Sjimharris *             utilized to perform task management.
127230557Sjimharris *          -# control_frame == 1.  This ensures that the proper endianess
128230557Sjimharris *             is set so that the bytes are transmitted in the right order
129230557Sjimharris *             for a smp request frame.
130230557Sjimharris *
131230557Sjimharris * @param[in] this_request This parameter specifies the smp request object
132230557Sjimharris *            being constructed.
133230557Sjimharris * @param[in] task_context The task_context to be reconstruct for packet
134230557Sjimharris *            request command phase.
135230557Sjimharris * @return none
136230557Sjimharris */
137230557Sjimharrisvoid scu_stp_packet_request_command_phase_construct_task_context(
138230557Sjimharris   SCIC_SDS_REQUEST_T * this_request,
139230557Sjimharris   SCU_TASK_CONTEXT_T * task_context
140230557Sjimharris)
141230557Sjimharris{
142230557Sjimharris   void * atapi_cdb;
143230557Sjimharris   U32 atapi_cdb_length;
144230557Sjimharris   SCIC_SDS_STP_REQUEST_T * stp_request = (SCIC_SDS_STP_REQUEST_T *)this_request;
145230557Sjimharris
146230557Sjimharris   // reference: SSTL 1.13.4.2
147230557Sjimharris   // task_type, sata_direction
148230557Sjimharris   if ( scic_cb_io_request_get_data_direction(this_request->user_request)
149230557Sjimharris           == SCI_IO_REQUEST_DATA_OUT )
150230557Sjimharris   {
151230557Sjimharris      task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
152230557Sjimharris      task_context->sata_direction = 0;
153230557Sjimharris   }
154230557Sjimharris   else // todo: for NO_DATA command, we need to send out raw frame.
155230557Sjimharris   {
156230557Sjimharris      task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
157230557Sjimharris      task_context->sata_direction = 1;
158230557Sjimharris   }
159230557Sjimharris
160230557Sjimharris   // sata header
161230557Sjimharris   memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
162230557Sjimharris   task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
163230557Sjimharris
164230557Sjimharris   // Copy in the command IU with CDB so that the commandIU address doesn't
165230557Sjimharris   // change.
166230557Sjimharris   memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
167230557Sjimharris
168230557Sjimharris   atapi_cdb =
169230557Sjimharris      scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
170230557Sjimharris
171230557Sjimharris   atapi_cdb_length =
172230557Sjimharris      scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
173230557Sjimharris
174230557Sjimharris   memcpy(((U8 *)this_request->command_buffer+sizeof(U32)), atapi_cdb, atapi_cdb_length);
175230557Sjimharris
176230557Sjimharris   atapi_cdb_length =
177230557Sjimharris      MAX(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length);
178230557Sjimharris
179230557Sjimharris   task_context->ssp_command_iu_length =
180230557Sjimharris      ((atapi_cdb_length % 4) == 0) ?
181230557Sjimharris       (atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1);
182230557Sjimharris
183230557Sjimharris   // task phase is set to TX_CMD
184230557Sjimharris   task_context->task_phase = 0x1;
185230557Sjimharris
186230557Sjimharris   // retry counter
187230557Sjimharris   task_context->stp_retry_count = 0;
188230557Sjimharris
189230557Sjimharris   if (scic_cb_request_is_initial_construction(this_request->user_request))
190230557Sjimharris   {
191230557Sjimharris      // data transfer size.
192230557Sjimharris      task_context->transfer_length_bytes =
193230557Sjimharris         scic_cb_io_request_get_transfer_length(this_request->user_request);
194230557Sjimharris
195230792Sjimharris      // sgls were already built when request was constructed, so don't need to
196230792Sjimharris      //  to do it here
197230557Sjimharris   }
198230557Sjimharris   else
199230557Sjimharris   {
200230557Sjimharris      // data transfer size, need to be 4 bytes aligned.
201230557Sjimharris      task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2);
202230557Sjimharris
203230557Sjimharris      scic_sds_stp_packet_internal_request_sense_build_sgl(this_request);
204230557Sjimharris   }
205230557Sjimharris}
206230557Sjimharris
207230557Sjimharris/**
208230557Sjimharris * @brief This method will fill in the SCU Task Context for a DATA fis
209230557Sjimharris *        containing CDB in Raw Frame type. The TC for previous Packet
210230557Sjimharris *        fis was already there, we only need to change the H2D fis content.
211230557Sjimharris *
212230557Sjimharris * @param[in] this_request This parameter specifies the smp request object
213230557Sjimharris *            being constructed.
214230557Sjimharris * @param[in] task_context The task_context to be reconstruct for packet
215230557Sjimharris *            request command phase.
216230557Sjimharris * @return none
217230557Sjimharris */
218230557Sjimharrisvoid scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
219230557Sjimharris   SCIC_SDS_REQUEST_T * this_request,
220230557Sjimharris   SCU_TASK_CONTEXT_T * task_context
221230557Sjimharris)
222230557Sjimharris{
223230557Sjimharris   void * atapi_cdb =
224230557Sjimharris      scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
225230557Sjimharris
226230557Sjimharris   U32 atapi_cdb_length =
227230557Sjimharris      scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
228230557Sjimharris
229230557Sjimharris   memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
230230557Sjimharris   memcpy( ((U8 *)this_request->command_buffer+sizeof(U32)), atapi_cdb, atapi_cdb_length);
231230557Sjimharris
232230557Sjimharris   memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
233230557Sjimharris   task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
234230557Sjimharris
235230557Sjimharris   //Note the data send out has to be 4 bytes aligned. Or else out hardware will
236230557Sjimharris   //patch non-zero bytes and cause the target device unhappy.
237230557Sjimharris   task_context->transfer_length_bytes = 12;
238230557Sjimharris}
239230557Sjimharris
240230557Sjimharris
241230557Sjimharris/*
242230557Sjimharris *@brief This methods decode the D2H status FIS and retrieve the sense data,
243230557Sjimharris *          then pass the sense data to user request.
244230557Sjimharris *
245230557Sjimharris *@param[in] this_request The request receive D2H status FIS.
246230557Sjimharris *@param[in] status_fis The D2H status fis to be processed.
247230557Sjimharris *
248230557Sjimharris */
249230557SjimharrisSCI_STATUS scic_sds_stp_packet_request_process_status_fis(
250230557Sjimharris   SCIC_SDS_REQUEST_T * this_request,
251230557Sjimharris   SATA_FIS_REG_D2H_T * status_fis
252230557Sjimharris)
253230557Sjimharris{
254230557Sjimharris   SCI_STATUS status = SCI_SUCCESS;
255230557Sjimharris
256230557Sjimharris   //TODO: Process the error status fis, retrieve sense data.
257230557Sjimharris   if (status_fis->status & ATA_STATUS_REG_ERROR_BIT)
258230557Sjimharris      status = SCI_FAILURE_IO_RESPONSE_VALID;
259230557Sjimharris
260230557Sjimharris   return status;
261230557Sjimharris}
262230557Sjimharris
263230557Sjimharris/*
264230557Sjimharris *@brief This methods builds sgl for internal REQUEST SENSE stp packet
265230557Sjimharris *          command using this request response buffer, only one sge is
266230557Sjimharris *          needed.
267230557Sjimharris *
268230557Sjimharris *@param[in] this_request The request receive request sense data.
269230557Sjimharris *
270230557Sjimharris */
271230557Sjimharrisvoid scic_sds_stp_packet_internal_request_sense_build_sgl(
272230557Sjimharris   SCIC_SDS_REQUEST_T * this_request
273230557Sjimharris)
274230557Sjimharris{
275230557Sjimharris   void                   *sge;
276230557Sjimharris   SCU_SGL_ELEMENT_PAIR_T *scu_sgl_list   = NULL;
277230557Sjimharris   SCU_TASK_CONTEXT_T     *task_context;
278230557Sjimharris   SCI_PHYSICAL_ADDRESS    physical_address;
279230557Sjimharris
280230557Sjimharris   SCI_SSP_RESPONSE_IU_T * rsp_iu =
281230557Sjimharris      (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
282230557Sjimharris   sge =  (void*)&rsp_iu->data[0];
283230557Sjimharris
284230557Sjimharris   task_context = (SCU_TASK_CONTEXT_T *)this_request->task_context_buffer;
285230557Sjimharris   scu_sgl_list = &task_context->sgl_pair_ab;
286230557Sjimharris
287230557Sjimharris   scic_cb_io_request_get_physical_address(
288230557Sjimharris      scic_sds_request_get_controller(this_request),
289230557Sjimharris      this_request,
290230557Sjimharris      ((char *)sge),
291230557Sjimharris      &physical_address
292230557Sjimharris   );
293230557Sjimharris
294230557Sjimharris   scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address);
295230557Sjimharris   scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address);
296230557Sjimharris   scu_sgl_list->A.length = task_context->transfer_length_bytes;
297230557Sjimharris   scu_sgl_list->A.address_modifier = 0;
298230557Sjimharris
299230557Sjimharris   SCU_SGL_ZERO(scu_sgl_list->B);
300230557Sjimharris}
301230557Sjimharris
302230557Sjimharris//******************************************************************************
303230557Sjimharris//* STP PACKET REQUEST STATE MACHINES
304230557Sjimharris//******************************************************************************
305230557Sjimharris
306230557Sjimharris/**
307230557Sjimharris* @brief This method processes the completions transport layer (TL) status
308230557Sjimharris*        to determine if the Packet FIS was sent successfully. If the Packet
309230557Sjimharris*        FIS was sent successfully, then the state for the Packet request
310230557Sjimharris*        transits to waiting for a PIO SETUP frame.
311230557Sjimharris*
312230557Sjimharris* @param[in] this_request This parameter specifies the request for which
313230557Sjimharris*            the TC completion was received.
314230557Sjimharris* @param[in] completion_code This parameter indicates the completion status
315230557Sjimharris*            information for the TC.
316230557Sjimharris*
317230557Sjimharris* @return Indicate if the tc completion handler was successful.
318230557Sjimharris* @retval SCI_SUCCESS currently this method always returns success.
319230557Sjimharris*/
320230557Sjimharrisstatic
321230557SjimharrisSCI_STATUS scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(
322230557Sjimharris   SCIC_SDS_REQUEST_T * this_request,
323230557Sjimharris   U32                  completion_code
324230557Sjimharris)
325230557Sjimharris{
326230557Sjimharris   SCI_STATUS status = SCI_SUCCESS;
327230557Sjimharris
328230557Sjimharris   SCIC_LOG_TRACE((
329230557Sjimharris      sci_base_object_get_logger(this_request),
330230557Sjimharris      SCIC_LOG_OBJECT_STP_IO_REQUEST,
331230557Sjimharris      "scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
332230557Sjimharris      this_request, completion_code
333230557Sjimharris   ));
334230557Sjimharris
335230557Sjimharris   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
336230557Sjimharris   {
337230557Sjimharris   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
338230557Sjimharris      scic_sds_request_set_status(
339230557Sjimharris         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
340230557Sjimharris      );
341230557Sjimharris
342230557Sjimharris      sci_base_state_machine_change_state(
343230557Sjimharris         &this_request->started_substate_machine,
344230557Sjimharris         SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
345230557Sjimharris      );
346230557Sjimharris      break;
347230557Sjimharris
348230557Sjimharris   default:
349230557Sjimharris      // All other completion status cause the IO to be complete.  If a NAK
350230557Sjimharris      // was received, then it is up to the user to retry the request.
351230557Sjimharris      scic_sds_request_set_status(
352230557Sjimharris         this_request,
353230557Sjimharris         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
354230557Sjimharris         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
355230557Sjimharris      );
356230557Sjimharris
357230557Sjimharris      sci_base_state_machine_change_state(
358230557Sjimharris         &this_request->parent.state_machine,
359230557Sjimharris         SCI_BASE_REQUEST_STATE_COMPLETED
360230557Sjimharris      );
361230557Sjimharris      break;
362230557Sjimharris   }
363230557Sjimharris
364230557Sjimharris   return status;
365230557Sjimharris}
366230557Sjimharris
367230557Sjimharris
368230557Sjimharris/**
369230557Sjimharris * @brief This method processes an unsolicited frame while the Packet request
370230557Sjimharris *        is waiting for a PIO SETUP FIS.  It will release
371230557Sjimharris *        the unsolicited frame, and transition the request to the
372230557Sjimharris *        COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE state.
373230557Sjimharris *
374230557Sjimharris * @param[in] this_request This parameter specifies the request for which
375230557Sjimharris *            the unsolicited frame was received.
376230557Sjimharris * @param[in] frame_index This parameter indicates the unsolicited frame
377230557Sjimharris *            index that should contain the response.
378230557Sjimharris *
379230557Sjimharris * @return This method returns an indication of whether the pio setup
380230557Sjimharris *         frame was handled successfully or not.
381230557Sjimharris * @retval SCI_SUCCESS Currently this value is always returned and indicates
382230557Sjimharris *         successful processing of the TC response.
383230557Sjimharris *
384230557Sjimharris */
385230557Sjimharrisstatic
386230557SjimharrisSCI_STATUS scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(
387230557Sjimharris   SCIC_SDS_REQUEST_T * request,
388230557Sjimharris   U32                  frame_index
389230557Sjimharris)
390230557Sjimharris{
391230557Sjimharris   SCI_STATUS               status;
392230557Sjimharris   SATA_FIS_HEADER_T      * frame_header;
393230557Sjimharris   U32                    * frame_buffer;
394230557Sjimharris   SCIC_SDS_STP_REQUEST_T * this_request;
395230557Sjimharris
396230557Sjimharris   this_request = (SCIC_SDS_STP_REQUEST_T *)request;
397230557Sjimharris
398230557Sjimharris   SCIC_LOG_TRACE((
399230557Sjimharris      sci_base_object_get_logger(this_request),
400230557Sjimharris      SCIC_LOG_OBJECT_STP_IO_REQUEST,
401230557Sjimharris      "scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(0x%x, 0x%x) enter\n",
402230557Sjimharris      this_request, frame_index
403230557Sjimharris   ));
404230557Sjimharris
405230557Sjimharris   status = scic_sds_unsolicited_frame_control_get_header(
406230557Sjimharris      &(this_request->parent.owning_controller->uf_control),
407230557Sjimharris      frame_index,
408230557Sjimharris      (void**) &frame_header
409230557Sjimharris   );
410230557Sjimharris
411230557Sjimharris   if (status == SCI_SUCCESS)
412230557Sjimharris   {
413230557Sjimharris      ASSERT(frame_header->fis_type == SATA_FIS_TYPE_PIO_SETUP);
414230557Sjimharris
415230557Sjimharris      // Get from the frame buffer the PIO Setup Data, although we don't need
416230557Sjimharris      // any info from this pio setup fis.
417230557Sjimharris      scic_sds_unsolicited_frame_control_get_buffer(
418230557Sjimharris         &(this_request->parent.owning_controller->uf_control),
419230557Sjimharris         frame_index,
420230557Sjimharris         (void**) &frame_buffer
421230557Sjimharris      );
422230557Sjimharris
423230557Sjimharris      // Get the data from the PIO Setup
424230557Sjimharris      // The SCU Hardware returns first word in the frame_header and the rest
425230557Sjimharris      // of the data is in the frame buffer so we need to back up one dword
426230557Sjimharris      this_request->type.packet.device_preferred_cdb_length =
427230557Sjimharris         (U16)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->transfter_count;
428230557Sjimharris
429230557Sjimharris      // Frame has been decoded return it to the controller
430230557Sjimharris      scic_sds_controller_release_frame(
431230557Sjimharris         this_request->parent.owning_controller, frame_index
432230557Sjimharris      );
433230557Sjimharris
434230557Sjimharris      sci_base_state_machine_change_state(
435230557Sjimharris         &this_request->parent.started_substate_machine,
436230557Sjimharris         SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
437230557Sjimharris      );
438230557Sjimharris   }
439230557Sjimharris   else
440230557Sjimharris   {
441230557Sjimharris      SCIC_LOG_ERROR((
442230557Sjimharris         sci_base_object_get_logger(this_request),
443230557Sjimharris         SCIC_LOG_OBJECT_STP_IO_REQUEST,
444230557Sjimharris         "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
445230557Sjimharris         this_request, frame_index, status
446230557Sjimharris      ));
447230557Sjimharris   }
448230557Sjimharris
449230557Sjimharris   return status;
450230557Sjimharris}
451230557Sjimharris
452230557Sjimharris
453230557Sjimharris/**
454230557Sjimharris * @brief This method processes the completions transport layer (TL) status
455230557Sjimharris *        to determine if the PACKET command data FIS was sent successfully.
456230557Sjimharris *        If successfully, then the state for the packet request
457230557Sjimharris *        transits to COMPLETE state. If not successfuly, the request transits
458230557Sjimharris *        to COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE.
459230557Sjimharris *
460230557Sjimharris * @param[in] this_request This parameter specifies the request for which
461230557Sjimharris *            the TC completion was received.
462230557Sjimharris * @param[in] completion_code This parameter indicates the completion status
463230557Sjimharris *            information for the TC.
464230557Sjimharris *
465230557Sjimharris * @return Indicate if the tc completion handler was successful.
466230557Sjimharris * @retval SCI_SUCCESS currently this method always returns success.
467230557Sjimharris */
468230557Sjimharrisstatic
469230557SjimharrisSCI_STATUS scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(
470230557Sjimharris   SCIC_SDS_REQUEST_T * this_request,
471230557Sjimharris   U32                  completion_code
472230557Sjimharris)
473230557Sjimharris{
474230557Sjimharris   SCI_STATUS status = SCI_SUCCESS;
475230557Sjimharris   U8 sat_packet_protocol = this_request->sat_protocol;
476230557Sjimharris
477230557Sjimharris   SCIC_LOG_TRACE((
478230557Sjimharris      sci_base_object_get_logger(this_request),
479230557Sjimharris      SCIC_LOG_OBJECT_STP_IO_REQUEST,
480230557Sjimharris      "scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
481230557Sjimharris      this_request, completion_code
482230557Sjimharris   ));
483230557Sjimharris
484230557Sjimharris   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
485230557Sjimharris   {
486230557Sjimharris   case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
487230557Sjimharris      scic_sds_request_set_status(
488230557Sjimharris         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
489230557Sjimharris      );
490230557Sjimharris
491230557Sjimharris      if ( sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN
492230557Sjimharris          || sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT
493230557Sjimharris         )
494230557Sjimharris         sci_base_state_machine_change_state(
495230557Sjimharris            &this_request->parent.state_machine,
496230557Sjimharris            SCI_BASE_REQUEST_STATE_COMPLETED
497230557Sjimharris         );
498230557Sjimharris      else
499230557Sjimharris         sci_base_state_machine_change_state(
500230557Sjimharris            &this_request->started_substate_machine,
501230557Sjimharris            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
502230557Sjimharris         );
503230557Sjimharris   break;
504230557Sjimharris
505230557Sjimharris   case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT):
506230557Sjimharris      if (scic_io_request_get_number_of_bytes_transferred(this_request) <
507230557Sjimharris          scic_cb_io_request_get_transfer_length(this_request->user_request))
508230557Sjimharris      {
509230557Sjimharris         scic_sds_request_set_status(
510230557Sjimharris            this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
511230557Sjimharris         );
512230557Sjimharris
513230557Sjimharris         sci_base_state_machine_change_state(
514230557Sjimharris            &this_request->started_substate_machine,
515230557Sjimharris            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
516230557Sjimharris         );
517230557Sjimharris
518230557Sjimharris         //change the device state to ATAPI_ERROR.
519230557Sjimharris         sci_base_state_machine_change_state(
520230557Sjimharris            &this_request->target_device->ready_substate_machine,
521230557Sjimharris            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
522230557Sjimharris         );
523230557Sjimharris
524230557Sjimharris         status = this_request->sci_status;
525230557Sjimharris      }
526230557Sjimharris   break;
527230557Sjimharris
528230557Sjimharris   case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
529230557Sjimharris      //In this case, there is no UF coming after. compelte the IO now.
530230557Sjimharris      scic_sds_request_set_status(
531230557Sjimharris         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
532230557Sjimharris      );
533230557Sjimharris
534230557Sjimharris      sci_base_state_machine_change_state(
535230557Sjimharris         &this_request->parent.state_machine,
536230557Sjimharris         SCI_BASE_REQUEST_STATE_COMPLETED
537230557Sjimharris      );
538230557Sjimharris
539230557Sjimharris   break;
540230557Sjimharris
541230557Sjimharris   default:
542230557Sjimharris      if (this_request->sci_status != SCI_SUCCESS)
543230557Sjimharris      {  //The io status was set already. This means an UF for the status
544230557Sjimharris         //fis was received already.
545230557Sjimharris
546230557Sjimharris         //A device suspension event is expected, we need to have the device
547230557Sjimharris         //coming out of suspension, then complete the IO.
548230557Sjimharris         sci_base_state_machine_change_state(
549230557Sjimharris            &this_request->started_substate_machine,
550230557Sjimharris            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
551230557Sjimharris         );
552230557Sjimharris
553230557Sjimharris         //change the device state to ATAPI_ERROR.
554230557Sjimharris         sci_base_state_machine_change_state(
555230557Sjimharris            &this_request->target_device->ready_substate_machine,
556230557Sjimharris            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
557230557Sjimharris         );
558230557Sjimharris
559230557Sjimharris         status = this_request->sci_status;
560230557Sjimharris      }
561230557Sjimharris      else
562230557Sjimharris      {  //If receiving any non-sucess TC status, no UF received yet, then an UF for
563230557Sjimharris         //the status fis is coming after.
564230557Sjimharris         scic_sds_request_set_status(
565230557Sjimharris            this_request,
566230557Sjimharris            SCU_TASK_DONE_CHECK_RESPONSE,
567230557Sjimharris            SCI_FAILURE_IO_RESPONSE_VALID
568230557Sjimharris         );
569230557Sjimharris
570230557Sjimharris         sci_base_state_machine_change_state(
571230557Sjimharris            &this_request->started_substate_machine,
572230557Sjimharris            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
573230557Sjimharris         );
574230557Sjimharris      }
575230557Sjimharris   break;
576230557Sjimharris   }
577230557Sjimharris
578230557Sjimharris   return status;
579230557Sjimharris}
580230557Sjimharris
581230557Sjimharris
582230557Sjimharris/**
583230557Sjimharris* @brief This method processes an unsolicited frame.
584230557Sjimharris*
585230557Sjimharris* @param[in] this_request This parameter specifies the request for which
586230557Sjimharris*            the unsolicited frame was received.
587230557Sjimharris* @param[in] frame_index This parameter indicates the unsolicited frame
588230557Sjimharris*            index that should contain the response.
589230557Sjimharris*
590230557Sjimharris* @return This method returns an indication of whether the UF
591230557Sjimharris*         frame was handled successfully or not.
592230557Sjimharris* @retval SCI_SUCCESS Currently this value is always returned and indicates
593230557Sjimharris*         successful processing of the TC response.
594230557Sjimharris*
595230557Sjimharris*/
596230557Sjimharrisstatic
597230557SjimharrisSCI_STATUS scic_sds_stp_packet_request_command_phase_common_frame_handler(
598230557Sjimharris   SCIC_SDS_REQUEST_T * request,
599230557Sjimharris   U32                  frame_index
600230557Sjimharris)
601230557Sjimharris{
602230557Sjimharris   SCI_STATUS               status;
603230557Sjimharris   SATA_FIS_HEADER_T      * frame_header;
604230557Sjimharris   U32                    * frame_buffer;
605230557Sjimharris   SCIC_SDS_STP_REQUEST_T * this_request;
606230557Sjimharris
607230557Sjimharris   this_request = (SCIC_SDS_STP_REQUEST_T *)request;
608230557Sjimharris
609230557Sjimharris   SCIC_LOG_TRACE((
610230557Sjimharris      sci_base_object_get_logger(this_request),
611230557Sjimharris      SCIC_LOG_OBJECT_STP_IO_REQUEST,
612230557Sjimharris      "scic_sds_stp_packet_request_command_phase_await_d2h_frame_handler(0x%x, 0x%x) enter\n",
613230557Sjimharris      this_request, frame_index
614230557Sjimharris   ));
615230557Sjimharris
616230557Sjimharris   status = scic_sds_unsolicited_frame_control_get_header(
617230557Sjimharris      &(this_request->parent.owning_controller->uf_control),
618230557Sjimharris      frame_index,
619230557Sjimharris      (void**) &frame_header
620230557Sjimharris   );
621230557Sjimharris
622230557Sjimharris   if (status == SCI_SUCCESS)
623230557Sjimharris   {
624230557Sjimharris      ASSERT(frame_header->fis_type == SATA_FIS_TYPE_REGD2H);
625230557Sjimharris
626230557Sjimharris      // Get from the frame buffer the PIO Setup Data, although we don't need
627230557Sjimharris      // any info from this pio setup fis.
628230557Sjimharris      scic_sds_unsolicited_frame_control_get_buffer(
629230557Sjimharris         &(this_request->parent.owning_controller->uf_control),
630230557Sjimharris         frame_index,
631230557Sjimharris         (void**) &frame_buffer
632230557Sjimharris      );
633230557Sjimharris
634230557Sjimharris      scic_sds_controller_copy_sata_response(
635230557Sjimharris         &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
636230557Sjimharris      );
637230557Sjimharris
638230557Sjimharris      // Frame has been decoded return it to the controller
639230557Sjimharris      scic_sds_controller_release_frame(
640230557Sjimharris         this_request->parent.owning_controller, frame_index
641230557Sjimharris      );
642230557Sjimharris   }
643230557Sjimharris
644230557Sjimharris   return status;
645230557Sjimharris}
646230557Sjimharris
647230557Sjimharris/**
648230557Sjimharris* @brief This method processes an unsolicited frame while the packet request is
649230557Sjimharris*        expecting TC completion. It will process the FIS and construct sense
650230557Sjimharris*        data.
651230557Sjimharris*
652230557Sjimharris* @param[in] this_request This parameter specifies the request for which
653230557Sjimharris*            the unsolicited frame was received.
654230557Sjimharris* @param[in] frame_index This parameter indicates the unsolicited frame
655230557Sjimharris*            index that should contain the response.
656230557Sjimharris*
657230557Sjimharris* @return This method returns an indication of whether the UF
658230557Sjimharris*         frame was handled successfully or not.
659230557Sjimharris* @retval SCI_SUCCESS Currently this value is always returned and indicates
660230557Sjimharris*         successful processing of the TC response.
661230557Sjimharris*
662230557Sjimharris*/
663230557Sjimharrisstatic
664230557SjimharrisSCI_STATUS scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler(
665230557Sjimharris   SCIC_SDS_REQUEST_T * request,
666230557Sjimharris   U32                  frame_index
667230557Sjimharris)
668230557Sjimharris{
669230557Sjimharris   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
670230557Sjimharris
671230557Sjimharris   SCI_STATUS status =
672230557Sjimharris      scic_sds_stp_packet_request_command_phase_common_frame_handler(
673230557Sjimharris         request, frame_index);
674230557Sjimharris
675230557Sjimharris   if (status == SCI_SUCCESS)
676230557Sjimharris   {
677230557Sjimharris      // The command has completed with error status from target device.
678230557Sjimharris      status = scic_sds_stp_packet_request_process_status_fis(
679230557Sjimharris         request, &this_request->d2h_reg_fis);
680230557Sjimharris
681230557Sjimharris      if (status != SCI_SUCCESS)
682230557Sjimharris      {
683230557Sjimharris         scic_sds_request_set_status(
684230557Sjimharris            &this_request->parent,
685230557Sjimharris            SCU_TASK_DONE_CHECK_RESPONSE,
686230557Sjimharris            status
687230557Sjimharris         );
688230557Sjimharris      }
689230557Sjimharris      else
690230557Sjimharris         scic_sds_request_set_status(
691230557Sjimharris            &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
692230557Sjimharris         );
693230557Sjimharris   }
694230557Sjimharris
695230557Sjimharris   return status;
696230557Sjimharris}
697230557Sjimharris
698230557Sjimharris
699230557Sjimharris/**
700230557Sjimharris* @brief This method processes an unsolicited frame while the packet request is
701230557Sjimharris*        expecting TC completion. It will process the FIS and construct sense
702230557Sjimharris*        data.
703230557Sjimharris*
704230557Sjimharris* @param[in] this_request This parameter specifies the request for which
705230557Sjimharris*            the unsolicited frame was received.
706230557Sjimharris* @param[in] frame_index This parameter indicates the unsolicited frame
707230557Sjimharris*            index that should contain the response.
708230557Sjimharris*
709230557Sjimharris* @return This method returns an indication of whether the UF
710230557Sjimharris*         frame was handled successfully or not.
711230557Sjimharris* @retval SCI_SUCCESS Currently this value is always returned and indicates
712230557Sjimharris*         successful processing of the TC response.
713230557Sjimharris*
714230557Sjimharris*/
715230557Sjimharrisstatic
716230557SjimharrisSCI_STATUS scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler(
717230557Sjimharris   SCIC_SDS_REQUEST_T * request,
718230557Sjimharris   U32                  frame_index
719230557Sjimharris)
720230557Sjimharris{
721230557Sjimharris   SCI_STATUS status =
722230557Sjimharris      scic_sds_stp_packet_request_command_phase_common_frame_handler(
723230557Sjimharris         request, frame_index);
724230557Sjimharris
725230557Sjimharris   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
726230557Sjimharris
727230557Sjimharris   if (status == SCI_SUCCESS)
728230557Sjimharris   {
729230557Sjimharris       // The command has completed with error status from target device.
730230557Sjimharris      status = scic_sds_stp_packet_request_process_status_fis(
731230557Sjimharris         request, &this_request->d2h_reg_fis);
732230557Sjimharris
733230557Sjimharris      if (status != SCI_SUCCESS)
734230557Sjimharris      {
735230557Sjimharris         scic_sds_request_set_status(
736230557Sjimharris            request,
737230557Sjimharris            SCU_TASK_DONE_CHECK_RESPONSE,
738230557Sjimharris            status
739230557Sjimharris         );
740230557Sjimharris      }
741230557Sjimharris      else
742230557Sjimharris         scic_sds_request_set_status(
743230557Sjimharris            request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
744230557Sjimharris         );
745230557Sjimharris
746230557Sjimharris      //Always complete the NON_DATA command right away, no need to delay completion
747230557Sjimharris      //even an error status fis came from target device.
748230557Sjimharris      sci_base_state_machine_change_state(
749230557Sjimharris         &request->parent.state_machine,
750230557Sjimharris         SCI_BASE_REQUEST_STATE_COMPLETED
751230557Sjimharris      );
752230557Sjimharris   }
753230557Sjimharris
754230557Sjimharris   return status;
755230557Sjimharris}
756230557Sjimharris
757230557Sjimharrisstatic
758230557SjimharrisSCI_STATUS scic_sds_stp_packet_request_started_completion_delay_complete_handler(
759230557Sjimharris   SCI_BASE_REQUEST_T *request
760230557Sjimharris)
761230557Sjimharris{
762230557Sjimharris   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)request;
763230557Sjimharris
764230557Sjimharris   sci_base_state_machine_change_state(
765230557Sjimharris      &this_request->parent.state_machine,
766230557Sjimharris      SCI_BASE_REQUEST_STATE_COMPLETED
767230557Sjimharris   );
768230557Sjimharris
769230557Sjimharris   return this_request->sci_status;
770230557Sjimharris}
771230557Sjimharris
772230557Sjimharris// ---------------------------------------------------------------------------
773230557Sjimharris
774230557SjimharrisSCIC_SDS_IO_REQUEST_STATE_HANDLER_T
775230557Sjimharrisscic_sds_stp_packet_request_started_substate_handler_table
776230557Sjimharris[SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES] =
777230557Sjimharris{
778230557Sjimharris   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
779230557Sjimharris   {
780230557Sjimharris      {
781230557Sjimharris         scic_sds_request_default_start_handler,
782230557Sjimharris         scic_sds_request_started_state_abort_handler,
783230557Sjimharris         scic_sds_request_default_complete_handler,
784230557Sjimharris         scic_sds_request_default_destruct_handler
785230557Sjimharris      },
786230557Sjimharris      scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler,
787230557Sjimharris      scic_sds_request_default_event_handler,
788230557Sjimharris      scic_sds_request_default_frame_handler
789230557Sjimharris   },
790230557Sjimharris   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
791230557Sjimharris   {
792230557Sjimharris      {
793230557Sjimharris         scic_sds_request_default_start_handler,
794230557Sjimharris         scic_sds_request_started_state_abort_handler,
795230557Sjimharris         scic_sds_request_default_complete_handler,
796230557Sjimharris         scic_sds_request_default_destruct_handler
797230557Sjimharris      },
798230557Sjimharris      scic_sds_request_default_tc_completion_handler,
799230557Sjimharris      scic_sds_request_default_event_handler,
800230557Sjimharris      scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler
801230557Sjimharris   },
802230557Sjimharris   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
803230557Sjimharris   {
804230557Sjimharris      {
805230557Sjimharris         scic_sds_request_default_start_handler,
806230557Sjimharris         scic_sds_request_started_state_abort_handler,
807230557Sjimharris         scic_sds_request_default_complete_handler,
808230557Sjimharris         scic_sds_request_default_destruct_handler
809230557Sjimharris      },
810230557Sjimharris      scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler,
811230557Sjimharris      scic_sds_request_default_event_handler,
812230557Sjimharris      scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler
813230557Sjimharris   },
814230557Sjimharris   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
815230557Sjimharris   {
816230557Sjimharris      {
817230557Sjimharris         scic_sds_request_default_start_handler,
818230557Sjimharris         scic_sds_request_started_state_abort_handler,
819230557Sjimharris         scic_sds_request_default_complete_handler,
820230557Sjimharris         scic_sds_request_default_destruct_handler
821230557Sjimharris      },
822230557Sjimharris      scic_sds_request_default_tc_completion_handler,
823230557Sjimharris      scic_sds_request_default_event_handler,
824230557Sjimharris      scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler
825230557Sjimharris   },
826230557Sjimharris   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
827230557Sjimharris   {
828230557Sjimharris      {
829230557Sjimharris         scic_sds_request_default_start_handler,
830230557Sjimharris         scic_sds_request_started_state_abort_handler,
831230557Sjimharris         scic_sds_stp_packet_request_started_completion_delay_complete_handler,
832230557Sjimharris         scic_sds_request_default_destruct_handler
833230557Sjimharris      },
834230557Sjimharris      scic_sds_request_default_tc_completion_handler,
835230557Sjimharris      scic_sds_request_default_event_handler,
836230557Sjimharris      scic_sds_request_default_frame_handler
837230557Sjimharris   }
838230557Sjimharris};
839230557Sjimharris
840230557Sjimharris/**
841230557Sjimharris * @file
842230557Sjimharris *
843230557Sjimharris * @brief This file contains the Packet IO started substate machine
844230557Sjimharris *        for the SCIC_SDS_IO_REQUEST object.
845230557Sjimharris */
846230557Sjimharrisstatic
847230557Sjimharrisvoid scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter(
848230557Sjimharris   SCI_BASE_OBJECT_T *object
849230557Sjimharris)
850230557Sjimharris{
851230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
852230557Sjimharris
853230557Sjimharris   SET_STATE_HANDLER(
854230557Sjimharris      this_request,
855230557Sjimharris      scic_sds_stp_packet_request_started_substate_handler_table,
856230557Sjimharris      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
857230557Sjimharris   );
858230557Sjimharris
859230557Sjimharris   scic_sds_remote_device_set_working_request(
860230557Sjimharris      this_request->target_device, this_request
861230557Sjimharris   );
862230557Sjimharris}
863230557Sjimharris
864230557Sjimharrisstatic
865230557Sjimharrisvoid scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter(
866230557Sjimharris   SCI_BASE_OBJECT_T *object
867230557Sjimharris)
868230557Sjimharris{
869230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
870230557Sjimharris
871230557Sjimharris   SET_STATE_HANDLER(
872230557Sjimharris      this_request,
873230557Sjimharris      scic_sds_stp_packet_request_started_substate_handler_table,
874230557Sjimharris      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
875230557Sjimharris   );
876230557Sjimharris}
877230557Sjimharris
878230557Sjimharrisstatic
879230557Sjimharrisvoid scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter(
880230557Sjimharris   SCI_BASE_OBJECT_T *object
881230557Sjimharris)
882230557Sjimharris{
883230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
884230557Sjimharris   U8 sat_packet_protocol = this_request->sat_protocol;
885230557Sjimharris
886230557Sjimharris   SCU_TASK_CONTEXT_T *task_context;
887230557Sjimharris   SCI_STATUS status;
888230557Sjimharris
889230557Sjimharris   // Recycle the TC and reconstruct it for sending out data fis containing
890230557Sjimharris   // CDB.
891230557Sjimharris   task_context = scic_sds_controller_get_task_context_buffer(
892230557Sjimharris                        this_request->owning_controller, this_request->io_tag);
893230557Sjimharris
894230557Sjimharris   if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA)
895230557Sjimharris      scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
896230557Sjimharris         this_request, task_context);
897230557Sjimharris   else
898230557Sjimharris      scu_stp_packet_request_command_phase_construct_task_context(
899230557Sjimharris         this_request, task_context);
900230557Sjimharris
901230557Sjimharris   // send the new TC out.
902230557Sjimharris   status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
903230557Sjimharris      &this_request->owning_controller->parent,
904230557Sjimharris      &this_request->target_device->parent,
905230557Sjimharris      &this_request->parent
906230557Sjimharris   );
907230557Sjimharris
908230557Sjimharris   if (status == SCI_SUCCESS)
909230557Sjimharris      SET_STATE_HANDLER(
910230557Sjimharris         this_request,
911230557Sjimharris         scic_sds_stp_packet_request_started_substate_handler_table,
912230557Sjimharris         SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
913230557Sjimharris      );
914230557Sjimharris}
915230557Sjimharris
916230557Sjimharrisstatic
917230557Sjimharrisvoid scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter(
918230557Sjimharris   SCI_BASE_OBJECT_T *object
919230557Sjimharris)
920230557Sjimharris{
921230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
922230557Sjimharris
923230557Sjimharris   SET_STATE_HANDLER(
924230557Sjimharris      this_request,
925230557Sjimharris      scic_sds_stp_packet_request_started_substate_handler_table,
926230557Sjimharris      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
927230557Sjimharris   );
928230557Sjimharris}
929230557Sjimharris
930230557Sjimharrisstatic
931230557Sjimharrisvoid scic_sds_stp_packet_request_started_completion_delay_enter(
932230557Sjimharris   SCI_BASE_OBJECT_T *object
933230557Sjimharris)
934230557Sjimharris{
935230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
936230557Sjimharris
937230557Sjimharris   SET_STATE_HANDLER(
938230557Sjimharris      this_request,
939230557Sjimharris      scic_sds_stp_packet_request_started_substate_handler_table,
940230557Sjimharris      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
941230557Sjimharris   );
942230557Sjimharris}
943230557Sjimharris
944230557Sjimharris
945230557Sjimharris// ---------------------------------------------------------------------------
946230557SjimharrisSCI_BASE_STATE_T
947230557Sjimharris   scic_sds_stp_packet_request_started_substate_table
948230557Sjimharris      [SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES] =
949230557Sjimharris{
950230557Sjimharris   {
951230557Sjimharris      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
952230557Sjimharris      scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter,
953230557Sjimharris      NULL
954230557Sjimharris   },
955230557Sjimharris   {
956230557Sjimharris      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE,
957230557Sjimharris      scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter,
958230557Sjimharris      NULL
959230557Sjimharris   },
960230557Sjimharris   {
961230557Sjimharris      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
962230557Sjimharris      scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter,
963230557Sjimharris      NULL
964230557Sjimharris   },
965230557Sjimharris   {
966230557Sjimharris      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE,
967230557Sjimharris      scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter,
968230557Sjimharris      NULL
969230557Sjimharris   },
970230557Sjimharris   {
971230557Sjimharris      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE,
972230557Sjimharris      scic_sds_stp_packet_request_started_completion_delay_enter,
973230557Sjimharris      NULL
974230557Sjimharris   }
975230557Sjimharris};
976230557Sjimharris
977230557Sjimharris#endif //#if !defined(DISABLE_ATAPI)
978230557Sjimharris
979