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
Cache object: 34c73fe43dd0762e82b510fa35d198cf
|