xref: /freebsd/sys/dev/isci/scil/scic_sds_stp_packet_request.c (revision b0d29bc47dba79f6f38e67eabadfb4b32ffd9390)
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  */
89 SCI_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  */
139 void 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  */
220 void 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  */
251 SCI_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  */
273 void 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 */
322 static
323 SCI_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  */
387 static
388 SCI_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  */
470 static
471 SCI_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 */
598 static
599 SCI_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 */
665 static
666 SCI_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 */
717 static
718 SCI_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 
759 static
760 SCI_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 
776 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
777 scic_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  */
848 static
849 void 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 
866 static
867 void 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 
880 static
881 void 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 
918 static
919 void 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 
932 static
933 void 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 // ---------------------------------------------------------------------------
948 SCI_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