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