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 /**
59 * @file
60 *
61 * @brief This file contains the methods and state machines for SATA/STP
62 * remote devices.
63 */
64
65 #include <dev/isci/scil/intel_sat.h>
66 #include <dev/isci/scil/intel_ata.h>
67 #include <dev/isci/scil/intel_sata.h>
68 #include <dev/isci/scil/scic_remote_device.h>
69 #include <dev/isci/scil/scic_user_callback.h>
70 #include <dev/isci/scil/scic_sds_logger.h>
71 #include <dev/isci/scil/scic_sds_controller.h>
72 #include <dev/isci/scil/scic_sds_port.h>
73 #include <dev/isci/scil/scic_sds_remote_device.h>
74 #include <dev/isci/scil/scic_sds_request.h>
75 #include <dev/isci/scil/scu_event_codes.h>
76 #include <dev/isci/scil/scu_completion_codes.h>
77 #include <dev/isci/scil/sci_base_state.h>
78
79 /**
80 * This method will perform the STP request completion processing common
81 * to IO requests and task requests of all types
82 *
83 * @param[in] device This parameter specifies the device for which the
84 * request is being completed.
85 * @param[in] request This parameter specifies the request being completed.
86 *
87 * @return This method returns an indication as to whether the request
88 * processing completed successfully.
89 */
90 static
91 SCI_STATUS scic_sds_stp_remote_device_complete_request(
92 SCI_BASE_REMOTE_DEVICE_T * device,
93 SCI_BASE_REQUEST_T * request
94 )
95 {
96 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
97 SCIC_SDS_REQUEST_T * the_request = (SCIC_SDS_REQUEST_T *)request;
98 SCI_STATUS status;
99
100 status = scic_sds_io_request_complete(the_request);
101
102 if (status == SCI_SUCCESS)
103 {
104 status = scic_sds_port_complete_io(
105 this_device->owning_port, this_device, the_request
106 );
107
108 if (status == SCI_SUCCESS)
109 {
110 scic_sds_remote_device_decrement_request_count(this_device);
111 if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED)
112 {
113 //This request causes hardware error, device needs to be Lun Reset.
114 //So here we force the state machine to IDLE state so the rest IOs
115 //can reach RNC state handler, these IOs will be completed by RNC with
116 //status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE".
117 sci_base_state_machine_change_state(
118 &this_device->ready_substate_machine,
119 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
120 );
121 }
122 else if (scic_sds_remote_device_get_request_count(this_device) == 0)
123 {
124 sci_base_state_machine_change_state(
125 &this_device->ready_substate_machine,
126 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
127 );
128 }
129 }
130 }
131
132 if (status != SCI_SUCCESS)
133 {
134 SCIC_LOG_ERROR((
135 sci_base_object_get_logger(this_device),
136 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
137 "Port:0x%x Device:0x%x Request:0x%x Status:0x%x could not complete\n",
138 this_device->owning_port, this_device, the_request, status
139 ));
140 }
141
142 return status;
143 }
144
145 //*****************************************************************************
146 //* STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS
147 //*****************************************************************************
148
149 /**
150 * This is the READY NCQ substate handler to start task management request. In this
151 * routine, we suspend and resume the RNC.
152 *
153 * @param[in] device The target device a task management request towards to.
154 * @param[in] request The task request.
155 *
156 * @return SCI_STATUS Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status
157 * to let controller_start_task_handler know that the controller can't post TC for
158 * task request yet, instead, when RNC gets resumed, a controller_continue_task
159 * callback will be called.
160 */
161 static
162 SCI_STATUS scic_sds_stp_remote_device_ready_substate_start_request_handler(
163 SCI_BASE_REMOTE_DEVICE_T * device,
164 SCI_BASE_REQUEST_T * request
165 )
166 {
167 SCI_STATUS status;
168 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
169 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)request;
170
171 // Will the port allow the io request to start?
172 status = this_device->owning_port->state_handlers->start_io_handler(
173 this_device->owning_port,
174 this_device,
175 this_request
176 );
177
178 if (SCI_SUCCESS == status)
179 {
180 status =
181 scic_sds_remote_node_context_start_task(this_device->rnc, this_request);
182
183 if (SCI_SUCCESS == status)
184 {
185 status = this_request->state_handlers->parent.start_handler(request);
186 }
187
188 if (status == SCI_SUCCESS)
189 {
190 /// @note If the remote device state is not IDLE this will replace
191 /// the request that probably resulted in the task management
192 /// request.
193 this_device->working_request = this_request;
194
195 sci_base_state_machine_change_state(
196 &this_device->ready_substate_machine,
197 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
198 );
199
200 //The remote node context must cleanup the TCi to NCQ mapping table.
201 //The only way to do this correctly is to either write to the TLCR
202 //register or to invalidate and repost the RNC. In either case the
203 //remote node context state machine will take the correct action when
204 //the remote node context is suspended and later resumed.
205 scic_sds_remote_node_context_suspend(
206 this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
207
208 scic_sds_remote_node_context_resume(
209 this_device->rnc,
210 (SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK)
211 scic_sds_remote_device_continue_request,
212 this_device);
213 }
214
215 scic_sds_remote_device_start_request(this_device,this_request,status);
216
217 //We need to let the controller start request handler know that it can't
218 //post TC yet. We will provide a callback function to post TC when RNC gets
219 //resumed.
220 return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS;
221 }
222
223 return status;
224 }
225
226 //*****************************************************************************
227 //* STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
228 //*****************************************************************************
229
230 /**
231 * This method will handle the start io operation for a sata device that is in
232 * the command idle state.
233 * - Evalute the type of IO request to be started
234 * - If its an NCQ request change to NCQ substate
235 * - If its any other command change to the CMD substate
236 *
237 * @note If this is a softreset we may want to have a different substate.
238 *
239 * @param [in] device
240 * @param [in] request
241 *
242 * @return SCI_STATUS
243 */
244 static
245 SCI_STATUS scic_sds_stp_remote_device_ready_idle_substate_start_io_handler(
246 SCI_BASE_REMOTE_DEVICE_T * device,
247 SCI_BASE_REQUEST_T * request
248 )
249 {
250 SCI_STATUS status;
251 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
252 SCIC_SDS_REQUEST_T * io_request = (SCIC_SDS_REQUEST_T *)request;
253
254
255 // Will the port allow the io request to start?
256 status = this_device->owning_port->state_handlers->start_io_handler(
257 this_device->owning_port,
258 this_device,
259 io_request
260 );
261
262 if (status == SCI_SUCCESS)
263 {
264 status =
265 scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
266
267 if (status == SCI_SUCCESS)
268 {
269 status = io_request->state_handlers->parent.start_handler(request);
270 }
271
272 if (status == SCI_SUCCESS)
273 {
274 if (io_request->sat_protocol == SAT_PROTOCOL_FPDMA)
275 {
276 sci_base_state_machine_change_state(
277 &this_device->ready_substate_machine,
278 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
279 );
280 }
281 else
282 {
283 this_device->working_request = io_request;
284
285 sci_base_state_machine_change_state(
286 &this_device->ready_substate_machine,
287 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
288 );
289 }
290 }
291
292 scic_sds_remote_device_start_request(this_device, io_request, status);
293 }
294
295 return status;
296 }
297
298
299 /**
300 * This method will handle the event for a sata device that is in
301 * the idle state. We pick up suspension events to handle specifically
302 * to this state. We resume the RNC right away.
303 *
304 * @param [in] device The device received event.
305 * @param [in] event_code The event code.
306 *
307 * @return SCI_STATUS
308 */
309 static
310 SCI_STATUS scic_sds_stp_remote_device_ready_idle_substate_event_handler(
311 SCIC_SDS_REMOTE_DEVICE_T * this_device,
312 U32 event_code
313 )
314 {
315 SCI_STATUS status;
316
317 status = scic_sds_remote_device_general_event_handler(this_device, event_code);
318
319 if (status == SCI_SUCCESS)
320 {
321 if ((scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
322 || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX)
323 && (this_device->rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY))
324 {
325 status = scic_sds_remote_node_context_resume(
326 this_device->rnc, NULL, NULL);
327 }
328 }
329
330 return status;
331 }
332
333
334 //*****************************************************************************
335 //* STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
336 //*****************************************************************************
337
338 /**
339 *
340 */
341 static
342 SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler(
343 SCI_BASE_REMOTE_DEVICE_T * device,
344 SCI_BASE_REQUEST_T * request
345 )
346 {
347 SCI_STATUS status;
348 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
349 SCIC_SDS_REQUEST_T * io_request = (SCIC_SDS_REQUEST_T *)request;
350
351 if (io_request->sat_protocol == SAT_PROTOCOL_FPDMA)
352 {
353 status = this_device->owning_port->state_handlers->start_io_handler(
354 this_device->owning_port,
355 this_device,
356 io_request
357 );
358
359 if (status == SCI_SUCCESS)
360 {
361 status = scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
362
363 if (status == SCI_SUCCESS)
364 {
365 status = io_request->state_handlers->parent.start_handler(request);
366 }
367
368 scic_sds_remote_device_start_request(this_device, io_request, status);
369 }
370 }
371 else
372 {
373 status = SCI_FAILURE_INVALID_STATE;
374 }
375
376 return status;
377 }
378
379 /**
380 * This method will handle events received while the STP device is in the
381 * ready command substate.
382 *
383 * @param [in] this_device This is the device object that is receiving the
384 * event.
385 * @param [in] event_code The event code to process.
386 *
387 * @return SCI_STATUS
388 */
389 static
390 SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_event_handler(
391 SCIC_SDS_REMOTE_DEVICE_T * this_device,
392 U32 event_code
393 )
394 {
395 SCI_STATUS status;
396
397 status = scic_sds_remote_device_general_event_handler(this_device, event_code);
398
399 switch (scu_get_event_code(event_code))
400 {
401 case SCU_EVENT_TL_RNC_SUSPEND_TX:
402 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
403 /// @todo We need to decode and understand why the hardware suspended the device.
404 /// The suspension reason was probably due to an SDB error FIS received.
405 break;
406
407 case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_DATA_LEN_ERR:
408 case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_OFFSET_ERR:
409 case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_DMASETUP_DIERR:
410 case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_XFERCNT_ERR:
411 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX_DONE_PLD_LEN_ERR:
412 this_device->not_ready_reason =
413 SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
414
415 sci_base_state_machine_change_state(
416 &this_device->ready_substate_machine,
417 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
418 );
419
420 // We have a notification that the driver requested a suspend operation
421 // this should not happen.
422 SCIC_LOG_WARNING((
423 sci_base_object_get_logger(this_device),
424 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
425 "SCIC Remote device 0x%x received driver suspend event %x while in ncq ready substate %d\n",
426 this_device, event_code, sci_base_state_machine_get_state(&this_device->ready_substate_machine)
427 ));
428
429 // Since we didn't expect to get here start the device again.
430 status = scic_sds_remote_device_resume(this_device);
431 break;
432
433 case SCU_EVENT_POST_RCN_RELEASE:
434 /// @todo Do we need to store the suspend state on the device?
435 SCIC_LOG_INFO((
436 sci_base_object_get_logger(this_device),
437 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
438 "SCIC Remote device 0x%x received driver release event %x while in the ready substate %d\n",
439 this_device, event_code, sci_base_state_machine_get_state(&this_device->ready_substate_machine)
440 ));
441 break;
442
443 default:
444 // Some other event just log it and continue
445 SCIC_LOG_WARNING((
446 sci_base_object_get_logger(this_device),
447 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
448 "SCIC Remote device 0x%x received driver unexpected event %x while in the ready substate %d\n",
449 this_device, event_code, sci_base_state_machine_get_state(&this_device->ready_substate_machine)
450 ));
451
452 status = SCI_FAILURE_INVALID_STATE;
453 break;
454 }
455
456 return status;
457 }
458
459 /**
460 *
461 *
462 * @param[in] this_device
463 * @param[in] frame_index
464 *
465 * @return SCI_STATUS
466 */
467 static
468 SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(
469 SCIC_SDS_REMOTE_DEVICE_T * this_device,
470 U32 frame_index
471 )
472 {
473 SCI_STATUS status;
474 SATA_FIS_HEADER_T * frame_header;
475
476 status = scic_sds_unsolicited_frame_control_get_header(
477 &(scic_sds_remote_device_get_controller(this_device)->uf_control),
478 frame_index,
479 (void **)&frame_header
480 );
481
482 if (status == SCI_SUCCESS)
483 {
484 if (
485 (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS)
486 && (frame_header->status & ATA_STATUS_REG_ERROR_BIT)
487 )
488 {
489 this_device->not_ready_reason =
490 SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
491
492 /** @todo Check sactive and complete associated IO if any. */
493
494 sci_base_state_machine_change_state(
495 &this_device->ready_substate_machine,
496 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
497 );
498 }
499 else if (
500 (frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
501 && (frame_header->status & ATA_STATUS_REG_ERROR_BIT)
502 )
503 {
504 // Some devices return D2H FIS when an NCQ error is detected.
505 // Treat this like an SDB error FIS ready reason.
506 this_device->not_ready_reason =
507 SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
508
509 sci_base_state_machine_change_state(
510 &this_device->ready_substate_machine,
511 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
512 );
513 }
514 else
515 {
516 status = SCI_FAILURE;
517 }
518
519 scic_sds_controller_release_frame(
520 scic_sds_remote_device_get_controller(this_device), frame_index
521 );
522 }
523
524 return status;
525 }
526
527 //*****************************************************************************
528 //* STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS
529 //*****************************************************************************
530
531 /**
532 * This device is already handling a command it can not accept new commands
533 * until this one is complete.
534 *
535 * @param[in] device
536 * @param[in] request
537 *
538 * @return SCI_STATUS
539 */
540 static
541 SCI_STATUS scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler(
542 SCI_BASE_REMOTE_DEVICE_T * device,
543 SCI_BASE_REQUEST_T * request
544 )
545 {
546 return SCI_FAILURE_INVALID_STATE;
547 }
548
549 static
550 SCI_STATUS scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler(
551 SCIC_SDS_REMOTE_DEVICE_T * this_device,
552 U32 suspend_type
553 )
554 {
555 SCI_STATUS status;
556
557 status = scic_sds_remote_node_context_suspend(
558 this_device->rnc, suspend_type, NULL, NULL
559 );
560
561 return status;
562 }
563
564 /**
565 *
566 *
567 * @param[in] this_device
568 * @param[in] frame_index
569 *
570 * @return SCI_STATUS
571 */
572 static
573 SCI_STATUS scic_sds_stp_remote_device_ready_cmd_substate_frame_handler(
574 SCIC_SDS_REMOTE_DEVICE_T * this_device,
575 U32 frame_index
576 )
577 {
578 SCI_STATUS status;
579
580 /// The device doe not process any UF received from the hardware while
581 /// in this state. All unsolicited frames are forwarded to the io request
582 /// object.
583 status = scic_sds_io_request_frame_handler(
584 this_device->working_request,
585 frame_index
586 );
587
588 return status;
589 }
590
591
592 //*****************************************************************************
593 //* STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
594 //*****************************************************************************
595
596
597 //*****************************************************************************
598 //* STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS
599 //*****************************************************************************
600 static
601 SCI_STATUS scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler(
602 SCI_BASE_REMOTE_DEVICE_T * device,
603 SCI_BASE_REQUEST_T * request
604 )
605 {
606 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
607 }
608
609
610
611 /**
612 * This method will perform the STP request (both io or task) completion
613 * processing for await reset state.
614 *
615 * @param[in] device This parameter specifies the device for which the
616 * request is being completed.
617 * @param[in] request This parameter specifies the request being completed.
618 *
619 * @return This method returns an indication as to whether the request
620 * processing completed successfully.
621 */
622 static
623 SCI_STATUS scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler(
624 SCI_BASE_REMOTE_DEVICE_T * device,
625 SCI_BASE_REQUEST_T * request
626 )
627 {
628 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
629 SCIC_SDS_REQUEST_T * the_request = (SCIC_SDS_REQUEST_T *)request;
630 SCI_STATUS status;
631
632 status = scic_sds_io_request_complete(the_request);
633
634 if (status == SCI_SUCCESS)
635 {
636 status = scic_sds_port_complete_io(
637 this_device->owning_port, this_device, the_request
638 );
639
640 if (status == SCI_SUCCESS)
641 scic_sds_remote_device_decrement_request_count(this_device);
642 }
643
644 if (status != SCI_SUCCESS)
645 {
646 SCIC_LOG_ERROR((
647 sci_base_object_get_logger(this_device),
648 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
649 "Port:0x%x Device:0x%x Request:0x%x Status:0x%x could not complete\n",
650 this_device->owning_port, this_device, the_request, status
651 ));
652 }
653
654 return status;
655 }
656
657 #if !defined(DISABLE_ATAPI)
658 //*****************************************************************************
659 //* STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS
660 //*****************************************************************************
661
662 /**
663 * This method will handle the event for a ATAPI device that is in
664 * the ATAPI ERROR state. We pick up suspension events to handle specifically
665 * to this state. We resume the RNC right away. We then complete the outstanding
666 * IO to this device.
667 *
668 * @param [in] device The device received event.
669 * @param [in] event_code The event code.
670 *
671 * @return SCI_STATUS
672 */
673 static
674 SCI_STATUS scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler(
675 SCIC_SDS_REMOTE_DEVICE_T * this_device,
676 U32 event_code
677 )
678 {
679 SCI_STATUS status;
680
681 status = scic_sds_remote_device_general_event_handler(this_device, event_code);
682
683 if (status == SCI_SUCCESS)
684 {
685 if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
686 || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX)
687 {
688 status = scic_sds_remote_node_context_resume(
689 this_device->rnc,
690 (SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK)
691 this_device->working_request->state_handlers->parent.complete_handler,
692 (void *)this_device->working_request
693 );
694 }
695 }
696
697 return status;
698 }
699 #endif // !defined(DISABLE_ATAPI)
700
701 // ---------------------------------------------------------------------------
702
703 SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
704 scic_sds_stp_remote_device_ready_substate_handler_table[
705 SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
706 {
707 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
708 {
709 {
710 scic_sds_remote_device_default_start_handler,
711 scic_sds_remote_device_ready_state_stop_handler,
712 scic_sds_remote_device_default_fail_handler,
713 scic_sds_remote_device_default_destruct_handler,
714 scic_sds_remote_device_ready_state_reset_handler,
715 scic_sds_remote_device_default_reset_complete_handler,
716 scic_sds_stp_remote_device_ready_idle_substate_start_io_handler,
717 scic_sds_remote_device_default_complete_request_handler,
718 scic_sds_remote_device_default_continue_request_handler,
719 scic_sds_stp_remote_device_ready_substate_start_request_handler,
720 scic_sds_remote_device_default_complete_request_handler
721 },
722 scic_sds_remote_device_default_suspend_handler,
723 scic_sds_remote_device_default_resume_handler,
724 scic_sds_stp_remote_device_ready_idle_substate_event_handler,
725 scic_sds_remote_device_default_frame_handler
726 },
727 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
728 {
729 {
730 scic_sds_remote_device_default_start_handler,
731 scic_sds_remote_device_ready_state_stop_handler,
732 scic_sds_remote_device_default_fail_handler,
733 scic_sds_remote_device_default_destruct_handler,
734 scic_sds_remote_device_ready_state_reset_handler,
735 scic_sds_remote_device_default_reset_complete_handler,
736 scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler,
737 scic_sds_stp_remote_device_complete_request,
738 scic_sds_remote_device_default_continue_request_handler,
739 scic_sds_stp_remote_device_ready_substate_start_request_handler,
740 scic_sds_stp_remote_device_complete_request,
741 },
742 scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler,
743 scic_sds_remote_device_default_resume_handler,
744 scic_sds_remote_device_general_event_handler,
745 scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
746 },
747 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
748 {
749 {
750 scic_sds_remote_device_default_start_handler,
751 scic_sds_remote_device_ready_state_stop_handler,
752 scic_sds_remote_device_default_fail_handler,
753 scic_sds_remote_device_default_destruct_handler,
754 scic_sds_remote_device_ready_state_reset_handler,
755 scic_sds_remote_device_default_reset_complete_handler,
756 scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler,
757 scic_sds_stp_remote_device_complete_request,
758 scic_sds_remote_device_default_continue_request_handler,
759 scic_sds_stp_remote_device_ready_substate_start_request_handler,
760 scic_sds_stp_remote_device_complete_request
761 },
762 scic_sds_remote_device_default_suspend_handler,
763 scic_sds_remote_device_default_resume_handler,
764 scic_sds_stp_remote_device_ready_ncq_substate_event_handler,
765 scic_sds_stp_remote_device_ready_ncq_substate_frame_handler
766 },
767 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
768 {
769 {
770 scic_sds_remote_device_default_start_handler,
771 scic_sds_remote_device_ready_state_stop_handler,
772 scic_sds_remote_device_default_fail_handler,
773 scic_sds_remote_device_default_destruct_handler,
774 scic_sds_remote_device_ready_state_reset_handler,
775 scic_sds_remote_device_default_reset_complete_handler,
776 scic_sds_remote_device_default_start_request_handler,
777 scic_sds_stp_remote_device_complete_request,
778 scic_sds_remote_device_default_continue_request_handler,
779 scic_sds_stp_remote_device_ready_substate_start_request_handler,
780 scic_sds_stp_remote_device_complete_request
781 },
782 scic_sds_remote_device_default_suspend_handler,
783 scic_sds_remote_device_default_resume_handler,
784 scic_sds_remote_device_general_event_handler,
785 scic_sds_remote_device_general_frame_handler
786 },
787 #if !defined(DISABLE_ATAPI)
788 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
789 {
790 {
791 scic_sds_remote_device_default_start_handler,
792 scic_sds_remote_device_ready_state_stop_handler,
793 scic_sds_remote_device_default_fail_handler,
794 scic_sds_remote_device_default_destruct_handler,
795 scic_sds_remote_device_ready_state_reset_handler,
796 scic_sds_remote_device_default_reset_complete_handler,
797 scic_sds_remote_device_default_start_request_handler,
798 scic_sds_stp_remote_device_complete_request,
799 scic_sds_remote_device_default_continue_request_handler,
800 scic_sds_stp_remote_device_ready_substate_start_request_handler,
801 scic_sds_stp_remote_device_complete_request
802 },
803 scic_sds_remote_device_default_suspend_handler,
804 scic_sds_remote_device_default_resume_handler,
805 scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler,
806 scic_sds_remote_device_general_frame_handler
807 },
808 #endif
809 // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
810 {
811 {
812 scic_sds_remote_device_default_start_handler,
813 scic_sds_remote_device_ready_state_stop_handler,
814 scic_sds_remote_device_default_fail_handler,
815 scic_sds_remote_device_default_destruct_handler,
816 scic_sds_remote_device_ready_state_reset_handler,
817 scic_sds_remote_device_default_reset_complete_handler,
818 scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler,
819 scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler,
820 scic_sds_remote_device_default_continue_request_handler,
821 scic_sds_stp_remote_device_ready_substate_start_request_handler,
822 scic_sds_stp_remote_device_complete_request
823 },
824 scic_sds_remote_device_default_suspend_handler,
825 scic_sds_remote_device_default_resume_handler,
826 scic_sds_remote_device_general_event_handler,
827 scic_sds_remote_device_general_frame_handler
828 }
829 };
830
831 //*****************************************************************************
832 //* STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS
833 //*****************************************************************************
834
835 static
836 void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
837 void * user_cookie
838 )
839 {
840 SCIC_SDS_REMOTE_DEVICE_T * this_device;
841 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_cookie;
842
843 // For NCQ operation we do not issue a
844 // scic_cb_remote_device_not_ready(). As a result, avoid sending
845 // the ready notification.
846 if (this_device->ready_substate_machine.previous_state_id
847 != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ)
848 {
849 scic_cb_remote_device_ready(
850 scic_sds_remote_device_get_controller(this_device), this_device
851 );
852 }
853 }
854
855 //*****************************************************************************
856 //* STP REMOTE DEVICE READY IDLE SUBSTATE
857 //*****************************************************************************
858
859 /**
860 *
861 * @param[in] device This is the SCI base object which is cast into a
862 * SCIC_SDS_REMOTE_DEVICE object.
863 *
864 * @return none
865 */
866 static
867 void scic_sds_stp_remote_device_ready_idle_substate_enter(
868 SCI_BASE_OBJECT_T * device
869 )
870 {
871 SCIC_SDS_REMOTE_DEVICE_T * this_device;
872
873 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
874
875 SET_STATE_HANDLER(
876 this_device,
877 scic_sds_stp_remote_device_ready_substate_handler_table,
878 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
879 );
880
881 this_device->working_request = NULL;
882
883 if (scic_sds_remote_node_context_is_ready(this_device->rnc))
884 {
885 // Since the RNC is ready, it's alright to finish completion
886 // processing (e.g. signal the remote device is ready).
887 scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
888 this_device
889 );
890 }
891 else
892 {
893 scic_sds_remote_node_context_resume(
894 this_device->rnc,
895 scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler,
896 this_device
897 );
898 }
899 }
900
901 //*****************************************************************************
902 //* STP REMOTE DEVICE READY CMD SUBSTATE
903 //*****************************************************************************
904
905 /**
906 *
907 *
908 * @param[in] device This is the SCI base object which is cast into a
909 * SCIC_SDS_REMOTE_DEVICE object.
910 *
911 * @return none
912 */
913 static
914 void scic_sds_stp_remote_device_ready_cmd_substate_enter(
915 SCI_BASE_OBJECT_T * device
916 )
917 {
918 SCIC_SDS_REMOTE_DEVICE_T * this_device;
919
920 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
921
922 ASSERT(this_device->working_request != NULL);
923
924 SET_STATE_HANDLER(
925 this_device,
926 scic_sds_stp_remote_device_ready_substate_handler_table,
927 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
928 );
929
930 scic_cb_remote_device_not_ready(
931 scic_sds_remote_device_get_controller(this_device),
932 this_device,
933 SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED
934 );
935 }
936
937 //*****************************************************************************
938 //* STP REMOTE DEVICE READY NCQ SUBSTATE
939 //*****************************************************************************
940
941 /**
942 *
943 *
944 * @param[in] device This is the SCI base object which is cast into a
945 * SCIC_SDS_REMOTE_DEVICE object.
946 *
947 * @return none
948 */
949 static
950 void scic_sds_stp_remote_device_ready_ncq_substate_enter(
951 SCI_BASE_OBJECT_T * device
952 )
953 {
954 SCIC_SDS_REMOTE_DEVICE_T * this_device;
955
956 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
957
958 SET_STATE_HANDLER(
959 this_device,
960 scic_sds_stp_remote_device_ready_substate_handler_table,
961 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
962 );
963 }
964
965 //*****************************************************************************
966 //* STP REMOTE DEVICE READY NCQ ERROR SUBSTATE
967 //*****************************************************************************
968
969 /**
970 *
971 *
972 * @param[in] device This is the SCI base object which is cast into a
973 * SCIC_SDS_REMOTE_DEVICE object.
974 *
975 * @return none
976 */
977 static
978 void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(
979 SCI_BASE_OBJECT_T * device
980 )
981 {
982 SCIC_SDS_REMOTE_DEVICE_T * this_device;
983
984 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
985
986 SET_STATE_HANDLER(
987 this_device,
988 scic_sds_stp_remote_device_ready_substate_handler_table,
989 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
990 );
991
992 if(this_device->not_ready_reason ==
993 SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED)
994 {
995 scic_cb_remote_device_not_ready(
996 scic_sds_remote_device_get_controller(this_device),
997 this_device,
998 this_device->not_ready_reason
999 );
1000 }
1001 }
1002
1003 //*****************************************************************************
1004 //* STP REMOTE DEVICE READY AWAIT RESET SUBSTATE
1005 //*****************************************************************************
1006
1007 /**
1008 * @brief The enter routine to READY AWAIT RESET substate.
1009 *
1010 * @param[in] device This is the SCI base object which is cast into a
1011 * SCIC_SDS_REMOTE_DEVICE object.
1012 *
1013 * @return none
1014 */
1015 static
1016 void scic_sds_stp_remote_device_ready_await_reset_substate_enter(
1017 SCI_BASE_OBJECT_T * device
1018 )
1019 {
1020 SCIC_SDS_REMOTE_DEVICE_T * this_device;
1021
1022 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
1023
1024 SET_STATE_HANDLER(
1025 this_device,
1026 scic_sds_stp_remote_device_ready_substate_handler_table,
1027 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
1028 );
1029 }
1030
1031 #if !defined(DISABLE_ATAPI)
1032 //*****************************************************************************
1033 //* STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE
1034 //*****************************************************************************
1035
1036 /**
1037 * @brief The enter routine to READY ATAPI ERROR substate.
1038 *
1039 * @param[in] device This is the SCI base object which is cast into a
1040 * SCIC_SDS_REMOTE_DEVICE object.
1041 *
1042 * @return none
1043 */
1044 static
1045 void scic_sds_stp_remote_device_ready_atapi_error_substate_enter(
1046 SCI_BASE_OBJECT_T * device
1047 )
1048 {
1049 SCIC_SDS_REMOTE_DEVICE_T * this_device;
1050
1051 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
1052
1053 SET_STATE_HANDLER(
1054 this_device,
1055 scic_sds_stp_remote_device_ready_substate_handler_table,
1056 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
1057 );
1058 }
1059 #endif // !defined(DISABLE_ATAPI)
1060
1061 // ---------------------------------------------------------------------------
1062
1063 SCI_BASE_STATE_T
1064 scic_sds_stp_remote_device_ready_substate_table[
1065 SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
1066 {
1067 {
1068 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
1069 scic_sds_stp_remote_device_ready_idle_substate_enter,
1070 NULL
1071 },
1072 {
1073 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
1074 scic_sds_stp_remote_device_ready_cmd_substate_enter,
1075 NULL
1076 },
1077 {
1078 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ,
1079 scic_sds_stp_remote_device_ready_ncq_substate_enter,
1080 NULL
1081 },
1082 {
1083 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR,
1084 scic_sds_stp_remote_device_ready_ncq_error_substate_enter,
1085 NULL
1086 },
1087 #if !defined(DISABLE_ATAPI)
1088 {
1089 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR,
1090 scic_sds_stp_remote_device_ready_atapi_error_substate_enter,
1091 NULL
1092 },
1093 #endif
1094 {
1095 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET,
1096 scic_sds_stp_remote_device_ready_await_reset_substate_enter,
1097 NULL
1098 }
1099 };
1100
Cache object: ce0f4af754da1ee4dd2a519b67382f67
|