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