1/*-
2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3 *
4 * This file is provided under a dual BSD/GPLv2 license.  When using or
5 * redistributing this file, you may do so under either license.
6 *
7 * GPL LICENSE SUMMARY
8 *
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23 * The full GNU General Public License is included in this distribution
24 * in the file called LICENSE.GPL.
25 *
26 * BSD LICENSE
27 *
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 *
35 *   * Redistributions of source code must retain the above copyright
36 *     notice, this list of conditions and the following disclaimer.
37 *   * Redistributions in binary form must reproduce the above copyright
38 *     notice, this list of conditions and the following disclaimer in
39 *     the documentation and/or other materials provided with the
40 *     distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */
54
55#include <sys/cdefs.h>
56__FBSDID("$FreeBSD$");
57
58#if !defined(DISABLE_ATAPI)
59
60#include <dev/isci/scil/scic_sds_stp_packet_request.h>
61#include <dev/isci/scil/scic_sds_logger.h>
62#include <dev/isci/scil/scic_sds_controller.h>
63#include <dev/isci/scil/scic_sds_remote_device.h>
64#include <dev/isci/scil/scic_remote_device.h>
65#include <dev/isci/scil/sci_util.h>
66#include <dev/isci/scil/intel_sas.h>
67#include <dev/isci/scil/intel_ata.h>
68#include <dev/isci/scil/intel_sata.h>
69#include <dev/isci/scil/scic_user_callback.h>
70#include <dev/isci/sci_environment.h>
71#include <dev/isci/scil/intel_sat.h>
72#include <dev/isci/scil/scic_sds_request.h>
73#include <dev/isci/scil/scic_controller.h>
74#include <dev/isci/scil/scu_completion_codes.h>
75#include <dev/isci/scil/scu_task_context.h>
76#include <dev/isci/scil/scic_sds_stp_packet_request.h>
77#include <dev/isci/scil/sci_base_state.h>
78
79/**
80 * @brief This method will fill in the SCU Task Context for a PACKET fis. And
81 *           construct the request STARTED sub-state machine for Packet Protocol
82 *           IO.
83 *
84 * @param[in] this_request This parameter specifies the stp packet request object
85 *            being constructed.
86 *
87 * @return none
88 */
89SCI_STATUS scic_sds_stp_packet_request_construct(
90   SCIC_SDS_REQUEST_T *this_request
91)
92{
93   SATA_FIS_REG_H2D_T * h2d_fis =
94      scic_stp_io_request_get_h2d_reg_address(
95         this_request
96      );
97
98   // Work around, we currently only support PACKET DMA protocol, so we
99   // need to make change to Packet Fis features field.
100   h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA;
101
102   scic_sds_stp_non_ncq_request_construct(this_request);
103
104   // Build the Packet Fis task context structure
105   scu_stp_raw_request_construct_task_context(
106      (SCIC_SDS_STP_REQUEST_T*) this_request,
107      this_request->task_context_buffer
108   );
109
110   sci_base_state_machine_construct(
111      &this_request->started_substate_machine,
112      &this_request->parent.parent,
113      scic_sds_stp_packet_request_started_substate_table,
114      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
115   );
116
117   return SCI_SUCCESS;
118}
119
120
121/**
122 * @brief This method will fill in the SCU Task Context for a Packet request
123 *        command phase in PACKET DMA DATA (IN/OUT) type. The following
124 *        important settings are utilized:
125 *
126 *          -# task_type == SCU_TASK_TYPE_PACKET_DMA.  This simply indicates
127 *             that a normal request type (i.e. non-raw frame) is being
128 *             utilized to perform task management.
129 *          -# control_frame == 1.  This ensures that the proper endianness
130 *             is set so that the bytes are transmitted in the right order
131 *             for a smp request frame.
132 *
133 * @param[in] this_request This parameter specifies the smp request object
134 *            being constructed.
135 * @param[in] task_context The task_context to be reconstruct for packet
136 *            request command phase.
137 * @return none
138 */
139void scu_stp_packet_request_command_phase_construct_task_context(
140   SCIC_SDS_REQUEST_T * this_request,
141   SCU_TASK_CONTEXT_T * task_context
142)
143{
144   void * atapi_cdb;
145   U32 atapi_cdb_length;
146   SCIC_SDS_STP_REQUEST_T * stp_request = (SCIC_SDS_STP_REQUEST_T *)this_request;
147
148   // reference: SSTL 1.13.4.2
149   // task_type, sata_direction
150   if ( scic_cb_io_request_get_data_direction(this_request->user_request)
151           == SCI_IO_REQUEST_DATA_OUT )
152   {
153      task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
154      task_context->sata_direction = 0;
155   }
156   else // todo: for NO_DATA command, we need to send out raw frame.
157   {
158      task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
159      task_context->sata_direction = 1;
160   }
161
162   // sata header
163   memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
164   task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
165
166   // Copy in the command IU with CDB so that the commandIU address doesn't
167   // change.
168   memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
169
170   atapi_cdb =
171      scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
172
173   atapi_cdb_length =
174      scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
175
176   memcpy(((U8 *)this_request->command_buffer+sizeof(U32)), atapi_cdb, atapi_cdb_length);
177
178   atapi_cdb_length =
179      MAX(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length);
180
181   task_context->ssp_command_iu_length =
182      ((atapi_cdb_length % 4) == 0) ?
183       (atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1);
184
185   // task phase is set to TX_CMD
186   task_context->task_phase = 0x1;
187
188   // retry counter
189   task_context->stp_retry_count = 0;
190
191   if (scic_cb_request_is_initial_construction(this_request->user_request))
192   {
193      // data transfer size.
194      task_context->transfer_length_bytes =
195         scic_cb_io_request_get_transfer_length(this_request->user_request);
196
197      // sgls were already built when request was constructed, so don't need to
198      //  to do it here
199   }
200   else
201   {
202      // data transfer size, need to be 4 bytes aligned.
203      task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2);
204
205      scic_sds_stp_packet_internal_request_sense_build_sgl(this_request);
206   }
207}
208
209/**
210 * @brief This method will fill in the SCU Task Context for a DATA fis
211 *        containing CDB in Raw Frame type. The TC for previous Packet
212 *        fis was already there, we only need to change the H2D fis content.
213 *
214 * @param[in] this_request This parameter specifies the smp request object
215 *            being constructed.
216 * @param[in] task_context The task_context to be reconstruct for packet
217 *            request command phase.
218 * @return none
219 */
220void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
221   SCIC_SDS_REQUEST_T * this_request,
222   SCU_TASK_CONTEXT_T * task_context
223)
224{
225   void * atapi_cdb =
226      scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
227
228   U32 atapi_cdb_length =
229      scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
230
231   memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
232   memcpy( ((U8 *)this_request->command_buffer+sizeof(U32)), atapi_cdb, atapi_cdb_length);
233
234   memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
235   task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
236
237   //Note the data send out has to be 4 bytes aligned. Or else out hardware will
238   //patch non-zero bytes and cause the target device unhappy.
239   task_context->transfer_length_bytes = 12;
240}
241
242
243/*
244 *@brief This methods decode the D2H status FIS and retrieve the sense data,
245 *          then pass the sense data to user request.
246 *
247 *@param[in] this_request The request receive D2H status FIS.
248 *@param[in] status_fis The D2H status fis to be processed.
249 *
250 */
251SCI_STATUS scic_sds_stp_packet_request_process_status_fis(
252   SCIC_SDS_REQUEST_T * this_request,
253   SATA_FIS_REG_D2H_T * status_fis
254)
255{
256   SCI_STATUS status = SCI_SUCCESS;
257
258   //TODO: Process the error status fis, retrieve sense data.
259   if (status_fis->status & ATA_STATUS_REG_ERROR_BIT)
260      status = SCI_FAILURE_IO_RESPONSE_VALID;
261
262   return status;
263}
264
265/*
266 *@brief This methods builds sgl for internal REQUEST SENSE stp packet
267 *          command using this request response buffer, only one sge is
268 *          needed.
269 *
270 *@param[in] this_request The request receive request sense data.
271 *
272 */
273void scic_sds_stp_packet_internal_request_sense_build_sgl(
274   SCIC_SDS_REQUEST_T * this_request
275)
276{
277   void                   *sge;
278   SCU_SGL_ELEMENT_PAIR_T *scu_sgl_list   = NULL;
279   SCU_TASK_CONTEXT_T     *task_context;
280   SCI_PHYSICAL_ADDRESS    physical_address;
281
282   SCI_SSP_RESPONSE_IU_T * rsp_iu =
283      (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
284   sge =  (void*)&rsp_iu->data[0];
285
286   task_context = (SCU_TASK_CONTEXT_T *)this_request->task_context_buffer;
287   scu_sgl_list = &task_context->sgl_pair_ab;
288
289   scic_cb_io_request_get_physical_address(
290      scic_sds_request_get_controller(this_request),
291      this_request,
292      ((char *)sge),
293      &physical_address
294   );
295
296   scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address);
297   scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address);
298   scu_sgl_list->A.length = task_context->transfer_length_bytes;
299   scu_sgl_list->A.address_modifier = 0;
300
301   SCU_SGL_ZERO(scu_sgl_list->B);
302}
303
304//******************************************************************************
305//* STP PACKET REQUEST STATE MACHINES
306//******************************************************************************
307
308/**
309* @brief This method processes the completions transport layer (TL) status
310*        to determine if the Packet FIS was sent successfully. If the Packet
311*        FIS was sent successfully, then the state for the Packet request
312*        transits to waiting for a PIO SETUP frame.
313*
314* @param[in] this_request This parameter specifies the request for which
315*            the TC completion was received.
316* @param[in] completion_code This parameter indicates the completion status
317*            information for the TC.
318*
319* @return Indicate if the tc completion handler was successful.
320* @retval SCI_SUCCESS currently this method always returns success.
321*/
322static
323SCI_STATUS scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(
324   SCIC_SDS_REQUEST_T * this_request,
325   U32                  completion_code
326)
327{
328   SCI_STATUS status = SCI_SUCCESS;
329
330   SCIC_LOG_TRACE((
331      sci_base_object_get_logger(this_request),
332      SCIC_LOG_OBJECT_STP_IO_REQUEST,
333      "scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
334      this_request, completion_code
335   ));
336
337   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
338   {
339   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
340      scic_sds_request_set_status(
341         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
342      );
343
344      sci_base_state_machine_change_state(
345         &this_request->started_substate_machine,
346         SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
347      );
348      break;
349
350   default:
351      // All other completion status cause the IO to be complete.  If a NAK
352      // was received, then it is up to the user to retry the request.
353      scic_sds_request_set_status(
354         this_request,
355         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
356         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
357      );
358
359      sci_base_state_machine_change_state(
360         &this_request->parent.state_machine,
361         SCI_BASE_REQUEST_STATE_COMPLETED
362      );
363      break;
364   }
365
366   return status;
367}
368
369
370/**
371 * @brief This method processes an unsolicited frame while the Packet request
372 *        is waiting for a PIO SETUP FIS.  It will release
373 *        the unsolicited frame, and transition the request to the
374 *        COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE state.
375 *
376 * @param[in] this_request This parameter specifies the request for which
377 *            the unsolicited frame was received.
378 * @param[in] frame_index This parameter indicates the unsolicited frame
379 *            index that should contain the response.
380 *
381 * @return This method returns an indication of whether the pio setup
382 *         frame was handled successfully or not.
383 * @retval SCI_SUCCESS Currently this value is always returned and indicates
384 *         successful processing of the TC response.
385 *
386 */
387static
388SCI_STATUS scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(
389   SCIC_SDS_REQUEST_T * request,
390   U32                  frame_index
391)
392{
393   SCI_STATUS               status;
394   SATA_FIS_HEADER_T      * frame_header;
395   U32                    * frame_buffer;
396   SCIC_SDS_STP_REQUEST_T * this_request;
397
398   this_request = (SCIC_SDS_STP_REQUEST_T *)request;
399
400   SCIC_LOG_TRACE((
401      sci_base_object_get_logger(this_request),
402      SCIC_LOG_OBJECT_STP_IO_REQUEST,
403      "scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(0x%x, 0x%x) enter\n",
404      this_request, frame_index
405   ));
406
407   status = scic_sds_unsolicited_frame_control_get_header(
408      &(this_request->parent.owning_controller->uf_control),
409      frame_index,
410      (void**) &frame_header
411   );
412
413   if (status == SCI_SUCCESS)
414   {
415      ASSERT(frame_header->fis_type == SATA_FIS_TYPE_PIO_SETUP);
416
417      // Get from the frame buffer the PIO Setup Data, although we don't need
418      // any info from this pio setup fis.
419      scic_sds_unsolicited_frame_control_get_buffer(
420         &(this_request->parent.owning_controller->uf_control),
421         frame_index,
422         (void**) &frame_buffer
423      );
424
425      // Get the data from the PIO Setup
426      // The SCU Hardware returns first word in the frame_header and the rest
427      // of the data is in the frame buffer so we need to back up one dword
428      this_request->type.packet.device_preferred_cdb_length =
429         (U16)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->transfter_count;
430
431      // Frame has been decoded return it to the controller
432      scic_sds_controller_release_frame(
433         this_request->parent.owning_controller, frame_index
434      );
435
436      sci_base_state_machine_change_state(
437         &this_request->parent.started_substate_machine,
438         SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
439      );
440   }
441   else
442   {
443      SCIC_LOG_ERROR((
444         sci_base_object_get_logger(this_request),
445         SCIC_LOG_OBJECT_STP_IO_REQUEST,
446         "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
447         this_request, frame_index, status
448      ));
449   }
450
451   return status;
452}
453
454
455/**
456 * @brief This method processes the completions transport layer (TL) status
457 *        to determine if the PACKET command data FIS was sent successfully.
458 *        If successfully, then the state for the packet request
459 *        transits to COMPLETE state. If not successfully, the request transits
460 *        to COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE.
461 *
462 * @param[in] this_request This parameter specifies the request for which
463 *            the TC completion was received.
464 * @param[in] completion_code This parameter indicates the completion status
465 *            information for the TC.
466 *
467 * @return Indicate if the tc completion handler was successful.
468 * @retval SCI_SUCCESS currently this method always returns success.
469 */
470static
471SCI_STATUS scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(
472   SCIC_SDS_REQUEST_T * this_request,
473   U32                  completion_code
474)
475{
476   SCI_STATUS status = SCI_SUCCESS;
477   U8 sat_packet_protocol = this_request->sat_protocol;
478
479   SCIC_LOG_TRACE((
480      sci_base_object_get_logger(this_request),
481      SCIC_LOG_OBJECT_STP_IO_REQUEST,
482      "scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
483      this_request, completion_code
484   ));
485
486   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
487   {
488   case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
489      scic_sds_request_set_status(
490         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
491      );
492
493      if ( sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN
494          || sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT
495         )
496         sci_base_state_machine_change_state(
497            &this_request->parent.state_machine,
498            SCI_BASE_REQUEST_STATE_COMPLETED
499         );
500      else
501         sci_base_state_machine_change_state(
502            &this_request->started_substate_machine,
503            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
504         );
505   break;
506
507   case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT):
508      if (scic_io_request_get_number_of_bytes_transferred(this_request) <
509          scic_cb_io_request_get_transfer_length(this_request->user_request))
510      {
511         scic_sds_request_set_status(
512            this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
513         );
514
515         sci_base_state_machine_change_state(
516            &this_request->started_substate_machine,
517            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
518         );
519
520         //change the device state to ATAPI_ERROR.
521         sci_base_state_machine_change_state(
522            &this_request->target_device->ready_substate_machine,
523            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
524         );
525
526         status = this_request->sci_status;
527      }
528   break;
529
530   case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
531      //In this case, there is no UF coming after. compelte the IO now.
532      scic_sds_request_set_status(
533         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
534      );
535
536      sci_base_state_machine_change_state(
537         &this_request->parent.state_machine,
538         SCI_BASE_REQUEST_STATE_COMPLETED
539      );
540
541   break;
542
543   default:
544      if (this_request->sci_status != SCI_SUCCESS)
545      {  //The io status was set already. This means an UF for the status
546         //fis was received already.
547
548         //A device suspension event is expected, we need to have the device
549         //coming out of suspension, then complete the IO.
550         sci_base_state_machine_change_state(
551            &this_request->started_substate_machine,
552            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
553         );
554
555         //change the device state to ATAPI_ERROR.
556         sci_base_state_machine_change_state(
557            &this_request->target_device->ready_substate_machine,
558            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
559         );
560
561         status = this_request->sci_status;
562      }
563      else
564      {  //If receiving any non-sucess TC status, no UF received yet, then an UF for
565         //the status fis is coming after.
566         scic_sds_request_set_status(
567            this_request,
568            SCU_TASK_DONE_CHECK_RESPONSE,
569            SCI_FAILURE_IO_RESPONSE_VALID
570         );
571
572         sci_base_state_machine_change_state(
573            &this_request->started_substate_machine,
574            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
575         );
576      }
577   break;
578   }
579
580   return status;
581}
582
583
584/**
585* @brief This method processes an unsolicited frame.
586*
587* @param[in] this_request This parameter specifies the request for which
588*            the unsolicited frame was received.
589* @param[in] frame_index This parameter indicates the unsolicited frame
590*            index that should contain the response.
591*
592* @return This method returns an indication of whether the UF
593*         frame was handled successfully or not.
594* @retval SCI_SUCCESS Currently this value is always returned and indicates
595*         successful processing of the TC response.
596*
597*/
598static
599SCI_STATUS scic_sds_stp_packet_request_command_phase_common_frame_handler(
600   SCIC_SDS_REQUEST_T * request,
601   U32                  frame_index
602)
603{
604   SCI_STATUS               status;
605   SATA_FIS_HEADER_T      * frame_header;
606   U32                    * frame_buffer;
607   SCIC_SDS_STP_REQUEST_T * this_request;
608
609   this_request = (SCIC_SDS_STP_REQUEST_T *)request;
610
611   SCIC_LOG_TRACE((
612      sci_base_object_get_logger(this_request),
613      SCIC_LOG_OBJECT_STP_IO_REQUEST,
614      "scic_sds_stp_packet_request_command_phase_await_d2h_frame_handler(0x%x, 0x%x) enter\n",
615      this_request, frame_index
616   ));
617
618   status = scic_sds_unsolicited_frame_control_get_header(
619      &(this_request->parent.owning_controller->uf_control),
620      frame_index,
621      (void**) &frame_header
622   );
623
624   if (status == SCI_SUCCESS)
625   {
626      ASSERT(frame_header->fis_type == SATA_FIS_TYPE_REGD2H);
627
628      // Get from the frame buffer the PIO Setup Data, although we don't need
629      // any info from this pio setup fis.
630      scic_sds_unsolicited_frame_control_get_buffer(
631         &(this_request->parent.owning_controller->uf_control),
632         frame_index,
633         (void**) &frame_buffer
634      );
635
636      scic_sds_controller_copy_sata_response(
637         &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
638      );
639
640      // Frame has been decoded return it to the controller
641      scic_sds_controller_release_frame(
642         this_request->parent.owning_controller, frame_index
643      );
644   }
645
646   return status;
647}
648
649/**
650* @brief This method processes an unsolicited frame while the packet request is
651*        expecting TC completion. It will process the FIS and construct sense
652*        data.
653*
654* @param[in] this_request This parameter specifies the request for which
655*            the unsolicited frame was received.
656* @param[in] frame_index This parameter indicates the unsolicited frame
657*            index that should contain the response.
658*
659* @return This method returns an indication of whether the UF
660*         frame was handled successfully or not.
661* @retval SCI_SUCCESS Currently this value is always returned and indicates
662*         successful processing of the TC response.
663*
664*/
665static
666SCI_STATUS scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler(
667   SCIC_SDS_REQUEST_T * request,
668   U32                  frame_index
669)
670{
671   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
672
673   SCI_STATUS status =
674      scic_sds_stp_packet_request_command_phase_common_frame_handler(
675         request, frame_index);
676
677   if (status == SCI_SUCCESS)
678   {
679      // The command has completed with error status from target device.
680      status = scic_sds_stp_packet_request_process_status_fis(
681         request, &this_request->d2h_reg_fis);
682
683      if (status != SCI_SUCCESS)
684      {
685         scic_sds_request_set_status(
686            &this_request->parent,
687            SCU_TASK_DONE_CHECK_RESPONSE,
688            status
689         );
690      }
691      else
692         scic_sds_request_set_status(
693            &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
694         );
695   }
696
697   return status;
698}
699
700
701/**
702* @brief This method processes an unsolicited frame while the packet request is
703*        expecting TC completion. It will process the FIS and construct sense
704*        data.
705*
706* @param[in] this_request This parameter specifies the request for which
707*            the unsolicited frame was received.
708* @param[in] frame_index This parameter indicates the unsolicited frame
709*            index that should contain the response.
710*
711* @return This method returns an indication of whether the UF
712*         frame was handled successfully or not.
713* @retval SCI_SUCCESS Currently this value is always returned and indicates
714*         successful processing of the TC response.
715*
716*/
717static
718SCI_STATUS scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler(
719   SCIC_SDS_REQUEST_T * request,
720   U32                  frame_index
721)
722{
723   SCI_STATUS status =
724      scic_sds_stp_packet_request_command_phase_common_frame_handler(
725         request, frame_index);
726
727   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
728
729   if (status == SCI_SUCCESS)
730   {
731       // The command has completed with error status from target device.
732      status = scic_sds_stp_packet_request_process_status_fis(
733         request, &this_request->d2h_reg_fis);
734
735      if (status != SCI_SUCCESS)
736      {
737         scic_sds_request_set_status(
738            request,
739            SCU_TASK_DONE_CHECK_RESPONSE,
740            status
741         );
742      }
743      else
744         scic_sds_request_set_status(
745            request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
746         );
747
748      //Always complete the NON_DATA command right away, no need to delay completion
749      //even an error status fis came from target device.
750      sci_base_state_machine_change_state(
751         &request->parent.state_machine,
752         SCI_BASE_REQUEST_STATE_COMPLETED
753      );
754   }
755
756   return status;
757}
758
759static
760SCI_STATUS scic_sds_stp_packet_request_started_completion_delay_complete_handler(
761   SCI_BASE_REQUEST_T *request
762)
763{
764   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)request;
765
766   sci_base_state_machine_change_state(
767      &this_request->parent.state_machine,
768      SCI_BASE_REQUEST_STATE_COMPLETED
769   );
770
771   return this_request->sci_status;
772}
773
774// ---------------------------------------------------------------------------
775
776SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
777scic_sds_stp_packet_request_started_substate_handler_table
778[SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES] =
779{
780   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
781   {
782      {
783         scic_sds_request_default_start_handler,
784         scic_sds_request_started_state_abort_handler,
785         scic_sds_request_default_complete_handler,
786         scic_sds_request_default_destruct_handler
787      },
788      scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler,
789      scic_sds_request_default_event_handler,
790      scic_sds_request_default_frame_handler
791   },
792   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
793   {
794      {
795         scic_sds_request_default_start_handler,
796         scic_sds_request_started_state_abort_handler,
797         scic_sds_request_default_complete_handler,
798         scic_sds_request_default_destruct_handler
799      },
800      scic_sds_request_default_tc_completion_handler,
801      scic_sds_request_default_event_handler,
802      scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler
803   },
804   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
805   {
806      {
807         scic_sds_request_default_start_handler,
808         scic_sds_request_started_state_abort_handler,
809         scic_sds_request_default_complete_handler,
810         scic_sds_request_default_destruct_handler
811      },
812      scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler,
813      scic_sds_request_default_event_handler,
814      scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler
815   },
816   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
817   {
818      {
819         scic_sds_request_default_start_handler,
820         scic_sds_request_started_state_abort_handler,
821         scic_sds_request_default_complete_handler,
822         scic_sds_request_default_destruct_handler
823      },
824      scic_sds_request_default_tc_completion_handler,
825      scic_sds_request_default_event_handler,
826      scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler
827   },
828   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
829   {
830      {
831         scic_sds_request_default_start_handler,
832         scic_sds_request_started_state_abort_handler,
833         scic_sds_stp_packet_request_started_completion_delay_complete_handler,
834         scic_sds_request_default_destruct_handler
835      },
836      scic_sds_request_default_tc_completion_handler,
837      scic_sds_request_default_event_handler,
838      scic_sds_request_default_frame_handler
839   }
840};
841
842/**
843 * @file
844 *
845 * @brief This file contains the Packet IO started substate machine
846 *        for the SCIC_SDS_IO_REQUEST object.
847 */
848static
849void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter(
850   SCI_BASE_OBJECT_T *object
851)
852{
853   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
854
855   SET_STATE_HANDLER(
856      this_request,
857      scic_sds_stp_packet_request_started_substate_handler_table,
858      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
859   );
860
861   scic_sds_remote_device_set_working_request(
862      this_request->target_device, this_request
863   );
864}
865
866static
867void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter(
868   SCI_BASE_OBJECT_T *object
869)
870{
871   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
872
873   SET_STATE_HANDLER(
874      this_request,
875      scic_sds_stp_packet_request_started_substate_handler_table,
876      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
877   );
878}
879
880static
881void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter(
882   SCI_BASE_OBJECT_T *object
883)
884{
885   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
886   U8 sat_packet_protocol = this_request->sat_protocol;
887
888   SCU_TASK_CONTEXT_T *task_context;
889   SCI_STATUS status;
890
891   // Recycle the TC and reconstruct it for sending out data fis containing
892   // CDB.
893   task_context = scic_sds_controller_get_task_context_buffer(
894                        this_request->owning_controller, this_request->io_tag);
895
896   if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA)
897      scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
898         this_request, task_context);
899   else
900      scu_stp_packet_request_command_phase_construct_task_context(
901         this_request, task_context);
902
903   // send the new TC out.
904   status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
905      &this_request->owning_controller->parent,
906      &this_request->target_device->parent,
907      &this_request->parent
908   );
909
910   if (status == SCI_SUCCESS)
911      SET_STATE_HANDLER(
912         this_request,
913         scic_sds_stp_packet_request_started_substate_handler_table,
914         SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
915      );
916}
917
918static
919void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter(
920   SCI_BASE_OBJECT_T *object
921)
922{
923   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
924
925   SET_STATE_HANDLER(
926      this_request,
927      scic_sds_stp_packet_request_started_substate_handler_table,
928      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
929   );
930}
931
932static
933void scic_sds_stp_packet_request_started_completion_delay_enter(
934   SCI_BASE_OBJECT_T *object
935)
936{
937   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
938
939   SET_STATE_HANDLER(
940      this_request,
941      scic_sds_stp_packet_request_started_substate_handler_table,
942      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
943   );
944}
945
946
947// ---------------------------------------------------------------------------
948SCI_BASE_STATE_T
949   scic_sds_stp_packet_request_started_substate_table
950      [SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES] =
951{
952   {
953      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
954      scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter,
955      NULL
956   },
957   {
958      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE,
959      scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter,
960      NULL
961   },
962   {
963      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
964      scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter,
965      NULL
966   },
967   {
968      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE,
969      scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter,
970      NULL
971   },
972   {
973      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE,
974      scic_sds_stp_packet_request_started_completion_delay_enter,
975      NULL
976   }
977};
978
979#endif //#if !defined(DISABLE_ATAPI)
980
981