scic_sds_stp_remote_device.c revision 230557
1/*-
2 * This file is provided under a dual BSD/GPLv2 license.  When using or
3 * redistributing this file, you may do so under either license.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * BSD LICENSE
25 *
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 *   * Redistributions of source code must retain the above copyright
34 *     notice, this list of conditions and the following disclaimer.
35 *   * Redistributions in binary form must reproduce the above copyright
36 *     notice, this list of conditions and the following disclaimer in
37 *     the documentation and/or other materials provided with the
38 *     distribution.
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 */
52
53#include <sys/cdefs.h>
54__FBSDID("$FreeBSD$");
55
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 */
88static
89SCI_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 */
159static
160SCI_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 */
242static
243SCI_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 */
307static
308SCI_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 */
339static
340SCI_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 */
387static
388SCI_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 didnt 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 */
465static
466SCI_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 */
538static
539SCI_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
547static
548SCI_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 */
570static
571SCI_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//*****************************************************************************
598static
599SCI_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 */
620static
621SCI_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 */
671static
672SCI_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
701SCIC_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
833static
834void 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 */
864static
865void 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 */
911static
912void 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 */
947static
948void 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 */
975static
976void 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 */
1013static
1014void 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 */
1042static
1043void 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
1061SCI_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