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