xref: /freebsd/sys/dev/isci/scil/scic_sds_stp_remote_device.c (revision 6829dae12bb055451fa467da4589c43bd03b1e64)
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 
1101