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 implementation of remote device, it's
60 *        methods and state machine.
61 */
62
63#include <dev/isci/scil/intel_sas.h>
64#include <dev/isci/scil/sci_util.h>
65#include <dev/isci/scil/scic_port.h>
66#include <dev/isci/scil/scic_phy.h>
67#include <dev/isci/scil/scic_remote_device.h>
68#include <dev/isci/scil/scic_sds_port.h>
69#include <dev/isci/scil/scic_sds_phy.h>
70#include <dev/isci/scil/scic_sds_remote_device.h>
71#include <dev/isci/scil/scic_sds_request.h>
72#include <dev/isci/scil/scic_sds_controller.h>
73#include <dev/isci/scil/scic_sds_logger.h>
74#include <dev/isci/scil/scic_user_callback.h>
75#include <dev/isci/scil/scic_controller.h>
76#include <dev/isci/scil/scic_sds_logger.h>
77#include <dev/isci/scil/scic_sds_remote_node_context.h>
78#include <dev/isci/scil/scu_event_codes.h>
79
80#define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT  (1000)
81
82//*****************************************************************************
83//*  CORE REMOTE DEVICE PUBLIC METHODS
84//*****************************************************************************
85
86U32 scic_remote_device_get_object_size(void)
87{
88   return   sizeof(SCIC_SDS_REMOTE_DEVICE_T)
89          + sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T);
90}
91
92// ---------------------------------------------------------------------------
93
94void scic_remote_device_construct(
95   SCI_PORT_HANDLE_T            port,
96   void                       * remote_device_memory,
97   SCI_REMOTE_DEVICE_HANDLE_T * new_remote_device_handle
98)
99{
100   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T*)
101                                           remote_device_memory;
102   SCIC_SDS_PORT_T          *the_port    = (SCIC_SDS_PORT_T*) port;
103
104   SCIC_LOG_TRACE((
105      sci_base_object_get_logger(the_port),
106      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
107      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
108      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
109      "scic_remote_device_construct(0x%x, 0x%x, 0x%x) enter\n",
110      port, remote_device_memory, new_remote_device_handle
111   ));
112
113   memset(remote_device_memory, 0, sizeof(SCIC_SDS_REMOTE_DEVICE_T));
114
115   *new_remote_device_handle          = this_device;
116   this_device->owning_port           = the_port;
117   this_device->started_request_count = 0;
118   this_device->rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)
119      ((char *)this_device + sizeof(SCIC_SDS_REMOTE_DEVICE_T));
120
121   sci_base_remote_device_construct(
122      &this_device->parent,
123      sci_base_object_get_logger(the_port),
124      scic_sds_remote_device_state_table
125   );
126
127   scic_sds_remote_node_context_construct(
128      this_device,
129      this_device->rnc,
130      SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
131   );
132
133   sci_object_set_association(this_device->rnc, this_device);
134
135   scic_sds_remote_device_initialize_state_logging(this_device);
136}
137
138// ---------------------------------------------------------------------------
139
140SCI_STATUS scic_remote_device_da_construct(
141   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
142)
143{
144   SCI_STATUS                status;
145   U16                       remote_node_index;
146   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T*)
147                                           remote_device;
148   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T  protocols;
149   SCIC_PORT_PROPERTIES_T  properties;
150
151   SCIC_LOG_TRACE((
152      sci_base_object_get_logger(this_device->owning_port),
153      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
154      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
155      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
156      "scic_remote_device_da_construct(0x%x) enter\n",
157      remote_device
158   ));
159
160   // This information is request to determine how many remote node context
161   // entries will be needed to store the remote node.
162   scic_sds_port_get_attached_protocols(this_device->owning_port,&protocols);
163   this_device->target_protocols.u.all = protocols.u.all;
164   this_device->is_direct_attached = TRUE;
165#if !defined(DISABLE_ATAPI)
166   this_device->is_atapi = scic_sds_remote_device_is_atapi(this_device);
167#endif
168
169   scic_port_get_properties(this_device->owning_port, &properties);
170   //Get accurate port width from port's phy mask for a DA device.
171   SCI_GET_BITS_SET_COUNT(properties.phy_mask, this_device->device_port_width);
172
173   status = scic_sds_controller_allocate_remote_node_context(
174               this_device->owning_port->owning_controller,
175               this_device,
176               &remote_node_index
177            );
178
179   if (status == SCI_SUCCESS)
180   {
181      scic_sds_remote_node_context_set_remote_node_index(
182         this_device->rnc, remote_node_index
183      );
184
185      scic_sds_port_get_attached_sas_address(
186         this_device->owning_port, &this_device->device_address
187      );
188
189      if (this_device->target_protocols.u.bits.attached_ssp_target)
190      {
191         this_device->has_ready_substate_machine = FALSE;
192      }
193      else if (this_device->target_protocols.u.bits.attached_stp_target)
194      {
195         this_device->has_ready_substate_machine = TRUE;
196
197         sci_base_state_machine_construct(
198            &this_device->ready_substate_machine,
199            &this_device->parent.parent,
200            scic_sds_stp_remote_device_ready_substate_table,
201            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
202         );
203      }
204      else if (this_device->target_protocols.u.bits.attached_smp_target)
205      {
206         this_device->has_ready_substate_machine = TRUE;
207
208         //add the SMP ready substate machine construction here
209         sci_base_state_machine_construct(
210            &this_device->ready_substate_machine,
211            &this_device->parent.parent,
212            scic_sds_smp_remote_device_ready_substate_table,
213            SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
214         );
215      }
216
217      this_device->connection_rate = scic_sds_port_get_max_allowed_speed(
218                                        this_device->owning_port
219                                     );
220
221      /// @todo Should I assign the port width by reading all of the phys on the port?
222      this_device->device_port_width = 1;
223   }
224
225   return status;
226}
227
228
229// ---------------------------------------------------------------------------
230
231void scic_sds_remote_device_get_info_from_smp_discover_response(
232   SCIC_SDS_REMOTE_DEVICE_T    * this_device,
233   SMP_RESPONSE_DISCOVER_T     * discover_response
234)
235{
236   // decode discover_response to set sas_address to this_device.
237   this_device->device_address.high =
238      discover_response->attached_sas_address.high;
239
240   this_device->device_address.low =
241      discover_response->attached_sas_address.low;
242
243   this_device->target_protocols.u.all = discover_response->protocols.u.all;
244}
245
246
247// ---------------------------------------------------------------------------
248
249SCI_STATUS scic_remote_device_ea_construct(
250   SCI_REMOTE_DEVICE_HANDLE_T    remote_device,
251   SMP_RESPONSE_DISCOVER_T     * discover_response
252)
253{
254   SCI_STATUS status;
255
256   SCIC_SDS_REMOTE_DEVICE_T *this_device;
257   SCIC_SDS_CONTROLLER_T    *the_controller;
258
259   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
260
261   SCIC_LOG_TRACE((
262      sci_base_object_get_logger(this_device->owning_port),
263      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
264      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
265      "scic_remote_device_ea_sas_construct0x%x, 0x%x) enter\n",
266      remote_device, discover_response
267   ));
268
269   the_controller = scic_sds_port_get_controller(this_device->owning_port);
270
271   scic_sds_remote_device_get_info_from_smp_discover_response(
272      this_device, discover_response
273   );
274
275   status = scic_sds_controller_allocate_remote_node_context(
276               the_controller,
277               this_device,
278               &this_device->rnc->remote_node_index
279            );
280
281   if (status == SCI_SUCCESS)
282   {
283      if (this_device->target_protocols.u.bits.attached_ssp_target)
284      {
285         this_device->has_ready_substate_machine = FALSE;
286      }
287      else if (this_device->target_protocols.u.bits.attached_smp_target)
288      {
289         this_device->has_ready_substate_machine = TRUE;
290
291         //add the SMP ready substate machine construction here
292         sci_base_state_machine_construct(
293            &this_device->ready_substate_machine,
294            &this_device->parent.parent,
295            scic_sds_smp_remote_device_ready_substate_table,
296            SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
297         );
298      }
299      else if (this_device->target_protocols.u.bits.attached_stp_target)
300      {
301         this_device->has_ready_substate_machine = TRUE;
302
303         sci_base_state_machine_construct(
304            &this_device->ready_substate_machine,
305            &this_device->parent.parent,
306            scic_sds_stp_remote_device_ready_substate_table,
307            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
308         );
309      }
310
311      // For SAS-2 the physical link rate is actually a logical link
312      // rate that incorporates multiplexing.  The SCU doesn't
313      // incorporate multiplexing and for the purposes of the
314      // connection the logical link rate is that same as the
315      // physical.  Furthermore, the SAS-2 and SAS-1.1 fields overlay
316      // one another, so this code works for both situations.
317      this_device->connection_rate = MIN(
318         scic_sds_port_get_max_allowed_speed( this_device->owning_port),
319         discover_response->u2.sas1_1.negotiated_physical_link_rate
320         );
321
322      /// @todo Should I assign the port width by reading all of the phys on the port?
323      this_device->device_port_width = 1;
324   }
325
326   return status;
327}
328
329// ---------------------------------------------------------------------------
330
331SCI_STATUS scic_remote_device_destruct(
332   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
333)
334{
335   SCIC_SDS_REMOTE_DEVICE_T *this_device;
336   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
337
338   SCIC_LOG_TRACE((
339      sci_base_object_get_logger(this_device),
340      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
341      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
342      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
343      "scic_remote_device_destruct(0x%x) enter\n",
344      remote_device
345   ));
346
347   return this_device->state_handlers->parent.destruct_handler(&this_device->parent);
348}
349
350// ---------------------------------------------------------------------------
351
352#if !defined(DISABLE_WIDE_PORTED_TARGETS)
353
354SCI_STATUS scic_remote_device_set_port_width(
355   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
356   U8                          new_port_width
357)
358{
359   SCIC_SDS_REMOTE_DEVICE_T *this_device;
360
361   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
362
363   SCIC_LOG_TRACE((
364      sci_base_object_get_logger(this_device),
365      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
366      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
367      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
368      "scic_remote_device_set_port_width(0x%x, 0x%x) enter\n",
369      remote_device, new_port_width
370   ));
371
372   if(new_port_width != 0)
373   {
374      this_device->device_port_width = new_port_width;
375
376      return SCI_SUCCESS;
377   }
378   else
379      return SCI_FAILURE;
380}
381
382// ---------------------------------------------------------------------------
383
384U8 scic_remote_device_get_port_width(
385   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
386)
387{
388   SCIC_SDS_REMOTE_DEVICE_T *this_device;
389
390   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
391
392   SCIC_LOG_TRACE((
393      sci_base_object_get_logger(this_device),
394      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
395      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
396      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
397      "scic_remote_device_get_port_width(0x%x) enter\n",
398      remote_device
399   ));
400
401   return (U8)this_device->device_port_width;
402}
403
404#endif // !defined(DISABLE_WIDE_PORTED_TARGETS)
405
406// ---------------------------------------------------------------------------
407
408SCI_STATUS scic_remote_device_start(
409   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
410   U32                         timeout
411)
412{
413   SCIC_SDS_REMOTE_DEVICE_T *this_device;
414   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
415
416   SCIC_LOG_TRACE((
417      sci_base_object_get_logger(this_device),
418      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
419      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
420      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
421      "scic_remote_device_start(0x%x, 0x%x) enter\n",
422      remote_device, timeout
423   ));
424
425   return this_device->state_handlers->parent.start_handler(&this_device->parent);
426}
427
428// ---------------------------------------------------------------------------
429
430SCI_STATUS scic_remote_device_stop(
431   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
432   U32                         timeout
433)
434{
435   SCIC_SDS_REMOTE_DEVICE_T *this_device;
436   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
437
438   SCIC_LOG_TRACE((
439      sci_base_object_get_logger(this_device),
440      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
441      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
442      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
443      "scic_remote_device_stop(0x%x, 0x%x) enter\n",
444      remote_device, timeout
445   ));
446
447   return this_device->state_handlers->parent.stop_handler(&this_device->parent);
448}
449
450/**
451 * This method invokes the remote device reset handler.
452 *
453 * @param[in] this_device The remote device for which the reset is being
454 *       requested.
455 *
456 * @return SCI_STATUS
457 */
458SCI_STATUS scic_remote_device_reset(
459   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
460)
461{
462   SCIC_SDS_REMOTE_DEVICE_T *this_device;
463   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
464
465   SCIC_LOG_TRACE((
466      sci_base_object_get_logger(this_device),
467      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
468      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
469      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
470      "scic_remote_device_reset(0x%x) enter\n",
471      remote_device
472   ));
473
474   return this_device->state_handlers->parent.reset_handler(&this_device->parent);
475}
476
477/**
478 * This method invokes the remote device reset handler.
479 *
480 * @param[in] this_device The remote device for which the reset is being
481 *       requested.
482 *
483 * @return SCI_STATUS
484 */
485SCI_STATUS scic_remote_device_reset_complete(
486   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
487)
488{
489   SCIC_SDS_REMOTE_DEVICE_T *this_device;
490   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
491
492   SCIC_LOG_TRACE((
493      sci_base_object_get_logger(this_device),
494      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
495      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
496      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
497      "scic_remote_device_reset_complete(0x%x) enter\n",
498      remote_device
499   ));
500
501   return this_device->state_handlers->parent.reset_complete_handler(&this_device->parent);
502}
503
504/**
505 * This method invokes the remote device reset handler.
506 *
507 * @param[in] this_device The remote device for which the reset is being
508 *       requested.
509 *
510 * @return SCI_STATUS
511 */
512U32 scic_remote_device_get_suggested_reset_timeout(
513   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
514)
515{
516   SCIC_SDS_REMOTE_DEVICE_T *this_device;
517   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
518
519   SCIC_LOG_TRACE((
520      sci_base_object_get_logger(this_device),
521      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
522      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
523      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
524      "scic_remote_device_get_suggested_reset_timeout(0x%x) enter\n",
525      remote_device
526   ));
527
528   if (this_device->target_protocols.u.bits.attached_stp_target)
529   {
530      return SCIC_SDS_SIGNATURE_FIS_TIMEOUT;
531   }
532
533   return SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT;
534}
535
536// ---------------------------------------------------------------------------
537
538SCI_STATUS scic_remote_device_set_max_connection_rate(
539   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
540   SCI_SAS_LINK_RATE           connection_rate
541)
542{
543   SCIC_SDS_REMOTE_DEVICE_T *this_device;
544   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
545
546   SCIC_LOG_TRACE((
547      sci_base_object_get_logger(this_device),
548      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
549      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
550      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
551      "scic_remote_device_set_max_connection_rate(0x%x, 0x%x) enter\n",
552      remote_device, connection_rate
553   ));
554
555   this_device->connection_rate = connection_rate;
556
557   return SCI_SUCCESS;
558}
559
560// ---------------------------------------------------------------------------
561
562SCI_SAS_LINK_RATE scic_remote_device_get_connection_rate(
563   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
564)
565{
566   SCIC_SDS_REMOTE_DEVICE_T *this_device;
567   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
568
569   SCIC_LOG_TRACE((
570      sci_base_object_get_logger(this_device),
571      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
572      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
573      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
574      "scic_remote_device_get_connection_rate(0x%x) enter\n",
575      remote_device
576   ));
577
578   return this_device->connection_rate;
579}
580
581// ---------------------------------------------------------------------------
582
583void scic_remote_device_get_protocols(
584   SCI_REMOTE_DEVICE_HANDLE_T          remote_device,
585   SMP_DISCOVER_RESPONSE_PROTOCOLS_T * protocols
586)
587{
588   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)
589                                            remote_device;
590
591   SCIC_LOG_TRACE((
592      sci_base_object_get_logger(this_device),
593      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
594      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
595      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
596      "scic_remote_device_get_protocols(0x%x) enter\n",
597      remote_device
598   ));
599
600   protocols->u.all = this_device->target_protocols.u.all;
601}
602
603// ---------------------------------------------------------------------------
604
605void scic_remote_device_get_sas_address(
606   SCI_REMOTE_DEVICE_HANDLE_T   remote_device,
607   SCI_SAS_ADDRESS_T          * sas_address
608)
609{
610   SCIC_SDS_REMOTE_DEVICE_T *this_device;
611   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
612
613   SCIC_LOG_TRACE((
614      sci_base_object_get_logger(this_device),
615      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
616      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
617      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
618      "scic_remote_device_get_sas_address(0x%x, 0x%x) enter\n",
619      remote_device, sas_address
620   ));
621
622   sas_address->low = this_device->device_address.low;
623   sas_address->high = this_device->device_address.high;
624}
625
626// ---------------------------------------------------------------------------
627#if !defined(DISABLE_ATAPI)
628BOOL scic_remote_device_is_atapi(
629   SCI_REMOTE_DEVICE_HANDLE_T device_handle
630)
631{
632  return ((SCIC_SDS_REMOTE_DEVICE_T *)device_handle)->is_atapi;
633}
634#endif
635
636
637//*****************************************************************************
638//*  SCU DRIVER STANDARD (SDS) REMOTE DEVICE IMPLEMENTATIONS
639//*****************************************************************************
640
641/**
642 * Remote device timer requirements
643 */
644#define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0)
645#define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES)
646
647/**
648 * @brief This method returns the minimum number of timers required for all
649 *        remote devices.
650 *
651 * @return U32
652 */
653U32 scic_sds_remote_device_get_min_timer_count(void)
654{
655   return SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT;
656}
657
658/**
659 * @brief This method returns the maximum number of timers requried for all
660 *        remote devices.
661 *
662 * @return U32
663 */
664U32 scic_sds_remote_device_get_max_timer_count(void)
665{
666   return SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT;
667}
668
669// ---------------------------------------------------------------------------
670
671#ifdef SCI_LOGGING
672/**
673 * This method will enable and turn on state transition logging for the remote
674 * device object.
675 *
676 * @param[in] this_device The device for which state transition logging is to
677 *       be enabled.
678 *
679 * @return Nothing
680 */
681void scic_sds_remote_device_initialize_state_logging(
682   SCIC_SDS_REMOTE_DEVICE_T *this_device
683)
684{
685   sci_base_state_machine_logger_initialize(
686      &this_device->parent.state_machine_logger,
687      &this_device->parent.state_machine,
688      &this_device->parent.parent,
689      scic_cb_logger_log_states,
690      "SCIC_SDS_REMOTE_DEVICE_T", "base state machine",
691      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
692      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
693      SCIC_LOG_OBJECT_STP_REMOTE_TARGET
694   );
695
696   if (this_device->has_ready_substate_machine)
697   {
698      sci_base_state_machine_logger_initialize(
699         &this_device->ready_substate_machine_logger,
700         &this_device->ready_substate_machine,
701         &this_device->parent.parent,
702         scic_cb_logger_log_states,
703         "SCIC_SDS_REMOTE_DEVICE_T", "ready substate machine",
704         SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
705         SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
706         SCIC_LOG_OBJECT_STP_REMOTE_TARGET
707      );
708   }
709}
710
711/**
712 * This method will stop the state machine logging for this object and should
713 * be called before the object is destroyed.
714 *
715 * @param[in] this_device The device on which to stop logging state
716 *       transitions.
717 *
718 * @return Nothing
719 */
720void scic_sds_remote_device_deinitialize_state_logging(
721   SCIC_SDS_REMOTE_DEVICE_T *this_device
722)
723{
724   sci_base_state_machine_logger_deinitialize(
725      &this_device->parent.state_machine_logger,
726      &this_device->parent.state_machine
727   );
728
729   if (this_device->has_ready_substate_machine)
730   {
731      sci_base_state_machine_logger_deinitialize(
732         &this_device->ready_substate_machine_logger,
733         &this_device->ready_substate_machine
734      );
735   }
736}
737#endif
738
739/**
740 * This method invokes the remote device suspend state handler.
741 *
742 * @param[in] this_device The remote device for which the suspend is being
743 *       requested.
744 *
745 * @return SCI_STATUS
746 */
747SCI_STATUS scic_sds_remote_device_suspend(
748   SCIC_SDS_REMOTE_DEVICE_T *this_device,
749   U32                       suspend_type
750)
751{
752   return this_device->state_handlers->suspend_handler(this_device, suspend_type);
753}
754
755/**
756 * This method invokes the remote device resume state handler.
757 *
758 * @param[in] this_device The remote device for which the resume is being
759 *       requested.
760 *
761 * @return SCI_STATUS
762 */
763SCI_STATUS scic_sds_remote_device_resume(
764   SCIC_SDS_REMOTE_DEVICE_T *this_device
765)
766{
767   return this_device->state_handlers->resume_handler(this_device);
768}
769
770/**
771 * This method invokes the frame handler for the remote device state machine
772 *
773 * @param[in] this_device The remote device for which the event handling is
774 *       being requested.
775 * @param[in] frame_index This is the frame index that is being processed.
776 *
777 * @return SCI_STATUS
778 */
779SCI_STATUS scic_sds_remote_device_frame_handler(
780   SCIC_SDS_REMOTE_DEVICE_T *this_device,
781   U32                       frame_index
782)
783{
784   return this_device->state_handlers->frame_handler(this_device, frame_index);
785}
786
787/**
788 * This method invokes the remote device event handler.
789 *
790 * @param[in] this_device The remote device for which the event handling is
791 *       being requested.
792 * @param[in] event_code This is the event code that is to be processed.
793 *
794 * @return SCI_STATUS
795 */
796SCI_STATUS scic_sds_remote_device_event_handler(
797   SCIC_SDS_REMOTE_DEVICE_T *this_device,
798   U32                       event_code
799)
800{
801   return this_device->state_handlers->event_handler(this_device, event_code);
802}
803
804/**
805 * This method invokes the remote device start io handler.
806 *
807 * @param[in] controller The controller that is starting the io request.
808 * @param[in] this_device The remote device for which the start io handling is
809 *       being requested.
810 * @param[in] io_request The io request that is being started.
811 *
812 * @return SCI_STATUS
813 */
814SCI_STATUS scic_sds_remote_device_start_io(
815   SCIC_SDS_CONTROLLER_T    *controller,
816   SCIC_SDS_REMOTE_DEVICE_T *this_device,
817   SCIC_SDS_REQUEST_T       *io_request
818)
819{
820   return this_device->state_handlers->parent.start_io_handler(
821                                 &this_device->parent, &io_request->parent);
822}
823
824/**
825 * This method invokes the remote device complete io handler.
826 *
827 * @param[in] controller The controller that is completing the io request.
828 * @param[in] this_device The remote device for which the complete io handling
829 *       is being requested.
830 * @param[in] io_request The io request that is being completed.
831 *
832 * @return SCI_STATUS
833 */
834SCI_STATUS scic_sds_remote_device_complete_io(
835   SCIC_SDS_CONTROLLER_T    *controller,
836   SCIC_SDS_REMOTE_DEVICE_T *this_device,
837   SCIC_SDS_REQUEST_T       *io_request
838)
839{
840   return this_device->state_handlers->parent.complete_io_handler(
841                                 &this_device->parent, &io_request->parent);
842}
843
844/**
845 * This method invokes the remote device start task handler.
846 *
847 * @param[in] controller The controller that is starting the task request.
848 * @param[in] this_device The remote device for which the start task handling
849 *       is being requested.
850 * @param[in] io_request The task request that is being started.
851 *
852 * @return SCI_STATUS
853 */
854SCI_STATUS scic_sds_remote_device_start_task(
855   SCIC_SDS_CONTROLLER_T    *controller,
856   SCIC_SDS_REMOTE_DEVICE_T *this_device,
857   SCIC_SDS_REQUEST_T       *io_request
858)
859{
860   return this_device->state_handlers->parent.start_task_handler(
861                                  &this_device->parent, &io_request->parent);
862}
863
864/**
865 * This method takes the request and bulids an appropriate SCU context for the
866 * request and then requests the controller to post the request.
867 *
868 * @param[in] this_device
869 * @param[in] request
870 *
871 * @return none
872 */
873void scic_sds_remote_device_post_request(
874   SCIC_SDS_REMOTE_DEVICE_T * this_device,
875   U32                        request
876)
877{
878   U32 context;
879
880   context = scic_sds_remote_device_build_command_context(this_device, request);
881
882   scic_sds_controller_post_request(
883      scic_sds_remote_device_get_controller(this_device),
884      context
885   );
886}
887
888#if !defined(DISABLE_ATAPI)
889/**
890 * This method check the signature fis of a stp device to decide whether
891 * a device is atapi or not.
892 *
893 * @param[in] this_device The device to be checked.
894 *
895 * @return TRUE if a device is atapi device. False if a device is not atapi.
896 */
897BOOL scic_sds_remote_device_is_atapi(
898   SCIC_SDS_REMOTE_DEVICE_T * this_device
899)
900{
901   if (!this_device->target_protocols.u.bits.attached_stp_target)
902      return FALSE;
903   else if (this_device->is_direct_attached)
904   {
905      SCIC_SDS_PHY_T * phy;
906      SCIC_SATA_PHY_PROPERTIES_T properties;
907      SATA_FIS_REG_D2H_T * signature_fis;
908      phy = scic_sds_port_get_a_connected_phy(this_device->owning_port);
909      scic_sata_phy_get_properties(phy, &properties);
910
911      //decode the signature fis.
912      signature_fis = &(properties.signature_fis);
913
914      if (   (signature_fis->sector_count  == 0x01)
915          && (signature_fis->lba_low       == 0x01)
916          && (signature_fis->lba_mid       == 0x14)
917          && (signature_fis->lba_high      == 0xEB)
918          && ( (signature_fis->device & 0x5F) == 0x00)
919         )
920      {
921         // An ATA device supporting the PACKET command set.
922         return TRUE;
923      }
924      else
925         return FALSE;
926   }
927   else
928   {
929      //Expander supported ATAPI device is not currently supported.
930      return FALSE;
931   }
932}
933
934#endif // !defined(DISABLE_ATAPI)
935
936//******************************************************************************
937//* REMOTE DEVICE STATE MACHINE
938//******************************************************************************
939
940/**
941 * This method is called once the remote node context is ready to be
942 * freed.  The remote device can now report that its stop operation is
943 * complete.
944 *
945 * @param[in] user_parameter This is cast to a remote device object.
946 *
947 * @return none
948 */
949static
950void scic_sds_cb_remote_device_rnc_destruct_complete(
951   void * user_parameter
952)
953{
954   SCIC_SDS_REMOTE_DEVICE_T * this_device;
955   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_parameter;
956
957   ASSERT(this_device->started_request_count == 0);
958
959   sci_base_state_machine_change_state(
960      scic_sds_remote_device_get_base_state_machine(this_device),
961      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
962   );
963}
964
965/**
966 * This method is called once the remote node context has transisitioned to a
967 * ready state.  This is the indication that the remote device object can also
968 * transition to ready.
969 *
970 * @param[in] user_parameter This is cast to a remote device object.
971 *
972 * @return none
973 */
974static
975void scic_sds_remote_device_resume_complete_handler(
976   void * user_parameter
977)
978{
979   SCIC_SDS_REMOTE_DEVICE_T * this_device;
980   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_parameter;
981
982   if (
983         sci_base_state_machine_get_state(&this_device->parent.state_machine)
984      != SCI_BASE_REMOTE_DEVICE_STATE_READY
985      )
986   {
987      sci_base_state_machine_change_state(
988         &this_device->parent.state_machine,
989         SCI_BASE_REMOTE_DEVICE_STATE_READY
990      );
991   }
992}
993
994/**
995 * This method will perform the STP request start processing common
996 * to IO requests and task requests of all types.
997 *
998 * @param[in] device This parameter specifies the device for which the
999 *            request is being started.
1000 * @param[in] request This parameter specifies the request being started.
1001 * @param[in] status This parameter specifies the current start operation
1002 *            status.
1003 *
1004 * @return none
1005 */
1006void scic_sds_remote_device_start_request(
1007   SCIC_SDS_REMOTE_DEVICE_T * this_device,
1008   SCIC_SDS_REQUEST_T       * the_request,
1009   SCI_STATUS                 status
1010)
1011{
1012   // We still have a fault in starting the io complete it on the port
1013   if (status == SCI_SUCCESS)
1014      scic_sds_remote_device_increment_request_count(this_device);
1015   else
1016   {
1017      this_device->owning_port->state_handlers->complete_io_handler(
1018         this_device->owning_port, this_device, the_request
1019      );
1020   }
1021}
1022
1023
1024/**
1025 * This method will continue to post tc for a STP request. This method usually
1026 * serves as a callback when RNC gets resumed during a task management sequence.
1027 *
1028 * @param[in] request This parameter specifies the request being continued.
1029 *
1030 * @return none
1031 */
1032void scic_sds_remote_device_continue_request(
1033   SCIC_SDS_REMOTE_DEVICE_T * this_device
1034)
1035{
1036   // we need to check if this request is still valid to continue.
1037   if (this_device->working_request != NULL)
1038   {
1039      SCIC_SDS_REQUEST_T * this_request = this_device->working_request;
1040
1041      this_request->owning_controller->state_handlers->parent.continue_io_handler(
1042         &this_request->owning_controller->parent,
1043         &this_request->target_device->parent,
1044         &this_request->parent
1045      );
1046   }
1047}
1048
1049/**
1050 * @brief This method will terminate all of the IO requests in the
1051 *        controllers IO request table that were targeted for this
1052 *        device.
1053 *
1054 * @param[in]  this_device This parameter specifies the remote device
1055 *             for which to attempt to terminate all requests.
1056 *
1057 * @return This method returns an indication as to whether all requests
1058 *         were successfully terminated.  If a single request fails to
1059 *         be terminated, then this method will return the failure.
1060 */
1061static
1062SCI_STATUS scic_sds_remote_device_terminate_requests(
1063   SCIC_SDS_REMOTE_DEVICE_T *this_device
1064)
1065{
1066    return scic_sds_terminate_reqests(
1067            this_device->owning_port->owning_controller,
1068            this_device,
1069            NULL);
1070}
1071
1072//*****************************************************************************
1073//*  DEFAULT STATE HANDLERS
1074//*****************************************************************************
1075
1076/**
1077 * This method is the default start handler.  It logs a warning and returns a
1078 * failure.
1079 *
1080 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1081 *       SCIC_SDS_REMOTE_DEVICE.
1082 *
1083 * @return SCI_STATUS
1084 * @retval SCI_FAILURE_INVALID_STATE
1085 */
1086SCI_STATUS scic_sds_remote_device_default_start_handler(
1087   SCI_BASE_REMOTE_DEVICE_T *device
1088)
1089{
1090   SCIC_LOG_WARNING((
1091      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
1092      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1093      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1094      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1095      "SCIC Remote Device requested to start while in wrong state %d\n",
1096      sci_base_state_machine_get_state(
1097         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
1098   ));
1099
1100   return SCI_FAILURE_INVALID_STATE;
1101}
1102
1103/**
1104 * This method is the default stop handler.  It logs a warning and returns a
1105 * failure.
1106 *
1107 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1108 *       SCIC_SDS_REMOTE_DEVICE.
1109 *
1110 * @return SCI_STATUS
1111 * @retval SCI_FAILURE_INVALID_STATE
1112 */
1113SCI_STATUS scic_sds_remote_device_default_stop_handler(
1114   SCI_BASE_REMOTE_DEVICE_T *device
1115)
1116{
1117   SCIC_LOG_WARNING((
1118      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
1119      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1120      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1121      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1122      "SCIC Remote Device requested to stop while in wrong state %d\n",
1123      sci_base_state_machine_get_state(
1124         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
1125   ));
1126
1127   return SCI_FAILURE_INVALID_STATE;
1128}
1129
1130/**
1131 * This method is the default fail handler.  It logs a warning and returns a
1132 * failure.
1133 *
1134 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1135 *       SCIC_SDS_REMOTE_DEVICE.
1136 *
1137 * @return SCI_STATUS
1138 * @retval SCI_FAILURE_INVALID_STATE
1139 */
1140SCI_STATUS scic_sds_remote_device_default_fail_handler(
1141   SCI_BASE_REMOTE_DEVICE_T *device
1142)
1143{
1144   SCIC_LOG_WARNING((
1145      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
1146      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1147      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1148      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1149      "SCIC Remote Device requested to fail while in wrong state %d\n",
1150      sci_base_state_machine_get_state(
1151         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
1152   ));
1153
1154   return SCI_FAILURE_INVALID_STATE;
1155}
1156
1157/**
1158 * This method is the default destruct handler.  It logs a warning and returns
1159 * a failure.
1160 *
1161 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1162 *       SCIC_SDS_REMOTE_DEVICE.
1163 *
1164 * @return SCI_STATUS
1165 * @retval SCI_FAILURE_INVALID_STATE
1166 */
1167SCI_STATUS scic_sds_remote_device_default_destruct_handler(
1168   SCI_BASE_REMOTE_DEVICE_T *device
1169)
1170{
1171   SCIC_LOG_WARNING((
1172      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
1173      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1174      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1175      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1176      "SCIC Remote Device requested to destroy while in wrong state %d\n",
1177      sci_base_state_machine_get_state(
1178         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
1179   ));
1180
1181   return SCI_FAILURE_INVALID_STATE;
1182}
1183
1184/**
1185 * This method is the default reset handler.  It logs a warning and returns a
1186 * failure.
1187 *
1188 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1189 *       SCIC_SDS_REMOTE_DEVICE.
1190 *
1191 * @return SCI_STATUS
1192 * @retval SCI_FAILURE_INVALID_STATE
1193 */
1194SCI_STATUS scic_sds_remote_device_default_reset_handler(
1195   SCI_BASE_REMOTE_DEVICE_T *device
1196)
1197{
1198   SCIC_LOG_WARNING((
1199      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
1200      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1201      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1202      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1203      "SCIC Remote Device requested to reset while in wrong state %d\n",
1204      sci_base_state_machine_get_state(
1205         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
1206   ));
1207
1208   return SCI_FAILURE_INVALID_STATE;
1209}
1210
1211/**
1212 * This method is the default reset complete handler.  It logs a warning and
1213 * returns a failure.
1214 *
1215 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1216 *       SCIC_SDS_REMOTE_DEVICE.
1217 *
1218 * @return SCI_STATUS
1219 * @retval SCI_FAILURE_INVALID_STATE
1220 */
1221SCI_STATUS scic_sds_remote_device_default_reset_complete_handler(
1222   SCI_BASE_REMOTE_DEVICE_T *device
1223)
1224{
1225   SCIC_LOG_WARNING((
1226      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
1227      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1228      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1229      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1230      "SCIC Remote Device requested to complete reset while in wrong state %d\n",
1231      sci_base_state_machine_get_state(
1232         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
1233   ));
1234
1235   return SCI_FAILURE_INVALID_STATE;
1236}
1237
1238/**
1239 * This method is the default suspend handler.  It logs a warning and returns
1240 * a failure.
1241 *
1242 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1243 *       SCIC_SDS_REMOTE_DEVICE.
1244 *
1245 * @return SCI_STATUS
1246 * @retval SCI_FAILURE_INVALID_STATE
1247 */
1248SCI_STATUS scic_sds_remote_device_default_suspend_handler(
1249   SCIC_SDS_REMOTE_DEVICE_T *this_device,
1250   U32                       suspend_type
1251)
1252{
1253   SCIC_LOG_WARNING((
1254      sci_base_object_get_logger(this_device),
1255      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1256      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1257      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1258      "SCIC Remote Device 0x%x requested to suspend %d while in wrong state %d\n",
1259      this_device, suspend_type,
1260      sci_base_state_machine_get_state(
1261         scic_sds_remote_device_get_base_state_machine(this_device))
1262   ));
1263
1264   return SCI_FAILURE_INVALID_STATE;
1265}
1266
1267/**
1268 * This method is the default resume handler.  It logs a warning and returns a
1269 * failure.
1270 *
1271 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1272 *       SCIC_SDS_REMOTE_DEVICE.
1273 *
1274 * @return SCI_STATUS
1275 * @retval SCI_FAILURE_INVALID_STATE
1276 */
1277SCI_STATUS scic_sds_remote_device_default_resume_handler(
1278   SCIC_SDS_REMOTE_DEVICE_T *this_device
1279)
1280{
1281   SCIC_LOG_WARNING((
1282      sci_base_object_get_logger(this_device),
1283      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1284      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1285      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1286      "SCIC Remote Device requested to resume while in wrong state %d\n",
1287      sci_base_state_machine_get_state(
1288         scic_sds_remote_device_get_base_state_machine(this_device))
1289   ));
1290
1291   return SCI_FAILURE_INVALID_STATE;
1292}
1293
1294#if defined(SCI_LOGGING)
1295/**
1296 *  This is a private method for emitting log messages related to events reported
1297 *  to the remote device from the controller object.
1298 *
1299 *  @param [in] this_device This is the device object that is receiving the
1300 *         event.
1301 *  @param [in] event_code The event code to process.
1302 *
1303 *  @return None
1304 */
1305static void scic_sds_emit_event_log_message(
1306   SCIC_SDS_REMOTE_DEVICE_T * this_device,
1307   U32                        event_code,
1308   char *                     message_guts,
1309   BOOL                       ready_state
1310   )
1311{
1312   SCIC_LOG_WARNING((
1313      sci_base_object_get_logger(this_device),
1314      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1315      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1316      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1317      "SCIC Remote device 0x%x (state %d) received %s %x while in the %sready %s%d\n",
1318      this_device,
1319      sci_base_state_machine_get_state(
1320               scic_sds_remote_device_get_base_state_machine(this_device)),
1321      message_guts, event_code,
1322      (ready_state)
1323        ? ""
1324        : "not ",
1325      (this_device->has_ready_substate_machine)
1326        ? "substate "
1327        : "",
1328      (this_device->has_ready_substate_machine)
1329        ? sci_base_state_machine_get_state(&this_device->ready_substate_machine)
1330        : 0
1331   ));
1332}
1333#else // defined(SCI_LOGGING)
1334#define scic_sds_emit_event_log_message(device, event_code, message, state)
1335#endif // defined(SCI_LOGGING)
1336
1337/**
1338 * This method is the default event handler.  It will call the RNC state
1339 * machine handler for any RNC events otherwise it will log a warning and
1340 * returns a failure.
1341 *
1342 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1343 *       SCIC_SDS_REMOTE_DEVICE.
1344 * @param[in] event_code The event code that the SCIC_SDS_CONTROLLER wants the
1345 *       device object to process.
1346 *
1347 * @return SCI_STATUS
1348 * @retval SCI_FAILURE_INVALID_STATE
1349 */
1350static
1351SCI_STATUS  scic_sds_remote_device_core_event_handler(
1352   SCIC_SDS_REMOTE_DEVICE_T *this_device,
1353   U32                       event_code,
1354   BOOL                      is_ready_state
1355)
1356{
1357   SCI_STATUS status;
1358
1359   switch (scu_get_event_type(event_code))
1360   {
1361   case SCU_EVENT_TYPE_RNC_OPS_MISC:
1362   case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
1363   case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
1364      status = scic_sds_remote_node_context_event_handler(this_device->rnc, event_code);
1365   break;
1366   case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
1367
1368       if( scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT )
1369       {
1370           status = SCI_SUCCESS;
1371
1372           // Suspend the associated RNC
1373           scic_sds_remote_node_context_suspend( this_device->rnc,
1374                                                 SCI_SOFTWARE_SUSPENSION,
1375                                                 NULL, NULL );
1376
1377           scic_sds_emit_event_log_message(
1378              this_device, event_code,
1379                   (is_ready_state)
1380            ? "I_T_Nexus_Timeout event"
1381            : "I_T_Nexus_Timeout event in wrong state",
1382                   is_ready_state );
1383
1384           break;
1385       }
1386       // Else, fall through and treat as unhandled...
1387
1388   default:
1389      scic_sds_emit_event_log_message( this_device, event_code,
1390                                       (is_ready_state)
1391                                          ? "unexpected event"
1392                                          : "unexpected event in wrong state",
1393                                       is_ready_state );
1394      status = SCI_FAILURE_INVALID_STATE;
1395   break;
1396   }
1397
1398   return status;
1399}
1400/**
1401 * This method is the default event handler.  It will call the RNC state
1402 * machine handler for any RNC events otherwise it will log a warning and
1403 * returns a failure.
1404 *
1405 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1406 *       SCIC_SDS_REMOTE_DEVICE.
1407 * @param[in] event_code The event code that the SCIC_SDS_CONTROLLER wants the
1408 *       device object to process.
1409 *
1410 * @return SCI_STATUS
1411 * @retval SCI_FAILURE_INVALID_STATE
1412 */
1413SCI_STATUS  scic_sds_remote_device_default_event_handler(
1414   SCIC_SDS_REMOTE_DEVICE_T *this_device,
1415   U32                       event_code
1416)
1417{
1418   return scic_sds_remote_device_core_event_handler( this_device,
1419                                                     event_code,
1420                                                     FALSE );
1421}
1422
1423/**
1424 * This method is the default unsolicited frame handler.  It logs a warning,
1425 * releases the frame and returns a failure.
1426 *
1427 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1428 *       SCIC_SDS_REMOTE_DEVICE.
1429 * @param[in] frame_index The frame index for which the SCIC_SDS_CONTROLLER
1430 *       wants this device object to process.
1431 *
1432 * @return SCI_STATUS
1433 * @retval SCI_FAILURE_INVALID_STATE
1434 */
1435SCI_STATUS scic_sds_remote_device_default_frame_handler(
1436   SCIC_SDS_REMOTE_DEVICE_T *this_device,
1437   U32                       frame_index
1438)
1439{
1440   SCIC_LOG_WARNING((
1441      sci_base_object_get_logger(this_device),
1442      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1443      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1444      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1445      "SCIC Remote Device requested to handle frame %x while in wrong state %d\n",
1446      frame_index,
1447      sci_base_state_machine_get_state(&this_device->parent.state_machine)
1448   ));
1449
1450   // Return the frame back to the controller
1451   scic_sds_controller_release_frame(
1452      scic_sds_remote_device_get_controller(this_device), frame_index
1453   );
1454
1455   return SCI_FAILURE_INVALID_STATE;
1456}
1457
1458/**
1459 * This method is the default start io handler.  It logs a warning and returns
1460 * a failure.
1461 *
1462 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1463 *       SCIC_SDS_REMOTE_DEVICE.
1464 * @param[in] request The SCI_BASE_REQUEST which is then cast into a
1465 *       SCIC_SDS_IO_REQUEST to start.
1466 *
1467 * @return SCI_STATUS
1468 * @retval SCI_FAILURE_INVALID_STATE
1469 */
1470SCI_STATUS scic_sds_remote_device_default_start_request_handler(
1471   SCI_BASE_REMOTE_DEVICE_T *device,
1472   SCI_BASE_REQUEST_T       *request
1473)
1474{
1475   SCIC_LOG_WARNING((
1476      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
1477      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1478      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1479      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1480      "SCIC Remote Device requested to start io request %x while in wrong state %d\n",
1481      request,
1482      sci_base_state_machine_get_state(
1483         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
1484   ));
1485
1486   return SCI_FAILURE_INVALID_STATE;
1487}
1488
1489/**
1490 * This method is the default complete io handler.  It logs a warning and
1491 * returns a failure.
1492 *
1493 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1494 *       SCIC_SDS_REMOTE_DEVICE.
1495 * @param[in] request The SCI_BASE_REQUEST which is then cast into a
1496 *       SCIC_SDS_IO_REQUEST to complete.
1497 *
1498 *
1499 * @return SCI_STATUS
1500 * @retval SCI_FAILURE_INVALID_STATE
1501 */
1502SCI_STATUS scic_sds_remote_device_default_complete_request_handler(
1503   SCI_BASE_REMOTE_DEVICE_T *device,
1504   SCI_BASE_REQUEST_T       *request
1505)
1506{
1507   SCIC_LOG_WARNING((
1508      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
1509      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1510      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1511      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1512      "SCIC Remote Device requested to complete io_request %x while in wrong state %d\n",
1513      request,
1514      sci_base_state_machine_get_state(
1515         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
1516   ));
1517
1518   return SCI_FAILURE_INVALID_STATE;
1519}
1520
1521/**
1522 * This method is the default continue io handler.  It logs a warning and
1523 * returns a failure.
1524 *
1525 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1526 *       SCIC_SDS_REMOTE_DEVICE.
1527 * @param[in] request The SCI_BASE_REQUEST which is then cast into a
1528 *       SCIC_SDS_IO_REQUEST to continue.
1529 *
1530 * @return SCI_STATUS
1531 * @retval SCI_FAILURE_INVALID_STATE
1532 */
1533SCI_STATUS scic_sds_remote_device_default_continue_request_handler(
1534   SCI_BASE_REMOTE_DEVICE_T *device,
1535   SCI_BASE_REQUEST_T       *request
1536)
1537{
1538   SCIC_LOG_WARNING((
1539      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
1540      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1541      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1542      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1543      "SCIC Remote Device requested to continue io request %x while in wrong state %d\n",
1544      request,
1545      sci_base_state_machine_get_state(
1546         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
1547   ));
1548
1549   return SCI_FAILURE_INVALID_STATE;
1550}
1551
1552/**
1553 * This method is the general suspend handler.
1554 *
1555 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1556 *       SCIC_SDS_REMOTE_DEVICE.
1557 *
1558 * @return SCI_STATUS
1559 * @retval SCI_FAILURE_INVALID_STATE
1560 */
1561static
1562SCI_STATUS scic_sds_remote_device_general_suspend_handler(
1563   SCIC_SDS_REMOTE_DEVICE_T *this_device,
1564   U32                       suspend_type
1565)
1566{
1567    return scic_sds_remote_node_context_suspend(this_device->rnc, suspend_type, NULL, NULL);
1568}
1569
1570/**
1571 * This method is the general suspend handler.  It logs a warning and returns
1572 * a failure.
1573 *
1574 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1575 *       SCIC_SDS_REMOTE_DEVICE.
1576 *
1577 * @return SCI_STATUS
1578 * @retval SCI_FAILURE_INVALID_STATE
1579 */
1580static
1581SCI_STATUS scic_sds_remote_device_general_resume_handler(
1582   SCIC_SDS_REMOTE_DEVICE_T *this_device
1583)
1584{
1585    return scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL);
1586}
1587
1588//*****************************************************************************
1589//*  NORMAL STATE HANDLERS
1590//*****************************************************************************
1591
1592/**
1593 * This method is a general ssp frame handler.  In most cases the device
1594 * object needs to route the unsolicited frame processing to the io request
1595 * object.  This method decodes the tag for the io request object and routes
1596 * the unsolicited frame to that object.
1597 *
1598 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
1599 *       SCIC_SDS_REMOTE_DEVICE.
1600 * @param[in] frame_index The frame index for which the SCIC_SDS_CONTROLLER
1601 *       wants this device object to process.
1602 *
1603 * @return SCI_STATUS
1604 * @retval SCI_FAILURE_INVALID_STATE
1605 */
1606SCI_STATUS scic_sds_remote_device_general_frame_handler(
1607   SCIC_SDS_REMOTE_DEVICE_T *this_device,
1608   U32                       frame_index
1609)
1610{
1611   SCI_STATUS result;
1612   SCI_SSP_FRAME_HEADER_T *frame_header;
1613   SCIC_SDS_REQUEST_T     *io_request;
1614
1615   result = scic_sds_unsolicited_frame_control_get_header(
1616      &(scic_sds_remote_device_get_controller(this_device)->uf_control),
1617      frame_index,
1618      (void **)&frame_header
1619   );
1620
1621   if (SCI_SUCCESS == result)
1622   {
1623      io_request = scic_sds_controller_get_io_request_from_tag(
1624         scic_sds_remote_device_get_controller(this_device), frame_header->tag);
1625
1626      if (  (io_request == SCI_INVALID_HANDLE)
1627         || (io_request->target_device != this_device) )
1628      {
1629         // We could not map this tag to a valid IO request
1630         // Just toss the frame and continue
1631         scic_sds_controller_release_frame(
1632            scic_sds_remote_device_get_controller(this_device), frame_index
1633         );
1634      }
1635      else
1636      {
1637         // The IO request is now in charge of releasing the frame
1638         result = io_request->state_handlers->frame_handler(
1639                                                    io_request, frame_index);
1640      }
1641   }
1642
1643   return result;
1644}
1645
1646/**
1647 *  This is a common method for handling events reported to the remote device
1648 *  from the controller object.
1649 *
1650 *  @param [in] this_device This is the device object that is receiving the
1651 *         event.
1652 *  @param [in] event_code The event code to process.
1653 *
1654 *  @return SCI_STATUS
1655 */
1656SCI_STATUS scic_sds_remote_device_general_event_handler(
1657   SCIC_SDS_REMOTE_DEVICE_T * this_device,
1658   U32                        event_code
1659)
1660{
1661   return scic_sds_remote_device_core_event_handler( this_device,
1662                                                     event_code,
1663                                                     TRUE );
1664}
1665
1666//*****************************************************************************
1667//*  STOPPED STATE HANDLERS
1668//*****************************************************************************
1669
1670/**
1671 * This method takes the SCIC_SDS_REMOTE_DEVICE from a stopped state and
1672 * attempts to start it.   The RNC buffer for the device is constructed and
1673 * the device state machine is transitioned to the
1674 * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING.
1675 *
1676 * @param[in] device
1677 *
1678 * @return SCI_STATUS
1679 * @retval SCI_SUCCESS if there is an RNC buffer available to construct the
1680 *         remote device.
1681 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer
1682 *         available in which to construct the remote device.
1683 */
1684static
1685SCI_STATUS scic_sds_remote_device_stopped_state_start_handler(
1686   SCI_BASE_REMOTE_DEVICE_T *device
1687)
1688{
1689   SCI_STATUS status;
1690   SCIC_SDS_REMOTE_DEVICE_T  *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
1691
1692   status = scic_sds_remote_node_context_resume(
1693               this_device->rnc,
1694               scic_sds_remote_device_resume_complete_handler,
1695               this_device
1696            );
1697
1698   if (status == SCI_SUCCESS)
1699   {
1700      sci_base_state_machine_change_state(
1701         scic_sds_remote_device_get_base_state_machine(this_device),
1702         SCI_BASE_REMOTE_DEVICE_STATE_STARTING
1703      );
1704   }
1705
1706   return status;
1707}
1708
1709/**
1710 * This method will stop a SCIC_SDS_REMOTE_DEVICE that is already in a stopped
1711 * state.  This is not considered an error since the device is already
1712 * stopped.
1713 *
1714 * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a
1715 *       SCIC_SDS_REMOTE_DEVICE.
1716 *
1717 * @return SCI_STATUS
1718 * @retval SCI_SUCCESS
1719 */
1720static
1721SCI_STATUS scic_sds_remote_device_stopped_state_stop_handler(
1722   SCI_BASE_REMOTE_DEVICE_T *this_device
1723)
1724{
1725   return SCI_SUCCESS;
1726}
1727
1728/**
1729 * This method will destruct a SCIC_SDS_REMOTE_DEVICE that is in a stopped
1730 * state.  This is the only state from which a destruct request will succeed.
1731 * The RNi for this SCIC_SDS_REMOTE_DEVICE is returned to the free pool and
1732 * the device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL.
1733 *
1734 * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a
1735 *       SCIC_SDS_REMOTE_DEVICE.
1736 *
1737 * @return SCI_STATUS
1738 * @retval SCI_SUCCESS
1739 */
1740static
1741SCI_STATUS scic_sds_remote_device_stopped_state_destruct_handler(
1742   SCI_BASE_REMOTE_DEVICE_T *device
1743)
1744{
1745   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
1746
1747   SCIC_SDS_CONTROLLER_T * the_controller =
1748      scic_sds_remote_device_get_controller(this_device);
1749
1750   the_controller->remote_device_sequence[this_device->rnc->remote_node_index]++;
1751
1752   scic_sds_controller_free_remote_node_context(
1753      the_controller,
1754      this_device,
1755      this_device->rnc->remote_node_index
1756   );
1757
1758   scic_sds_remote_node_context_set_remote_node_index(
1759      this_device->rnc,
1760      SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
1761   );
1762
1763   sci_base_state_machine_change_state(
1764      scic_sds_remote_device_get_base_state_machine(this_device),
1765      SCI_BASE_REMOTE_DEVICE_STATE_FINAL
1766   );
1767
1768   scic_sds_remote_device_deinitialize_state_logging(this_device);
1769
1770   return SCI_SUCCESS;
1771}
1772
1773//*****************************************************************************
1774//*  STARTING STATE HANDLERS
1775//*****************************************************************************
1776
1777static
1778SCI_STATUS scic_sds_remote_device_starting_state_stop_handler(
1779   SCI_BASE_REMOTE_DEVICE_T *device
1780)
1781{
1782   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
1783
1784   /*
1785    * This device has not yet started so there had better be no IO requests
1786    */
1787   ASSERT(this_device->started_request_count == 0);
1788
1789   /*
1790    * Destroy the remote node context
1791    */
1792   scic_sds_remote_node_context_destruct(
1793      this_device->rnc,
1794      scic_sds_cb_remote_device_rnc_destruct_complete,
1795      this_device
1796   );
1797
1798   /*
1799    * Transition to the stopping state and wait for the remote node to
1800    * complete being posted and invalidated.
1801    */
1802   sci_base_state_machine_change_state(
1803      scic_sds_remote_device_get_base_state_machine(this_device),
1804      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
1805   );
1806
1807   return SCI_SUCCESS;
1808}
1809
1810//*****************************************************************************
1811//*  INITIALIZING STATE HANDLERS
1812//*****************************************************************************
1813
1814/* There is nothing to do here for SSP devices */
1815
1816//*****************************************************************************
1817//*  READY STATE HANDLERS
1818//*****************************************************************************
1819
1820/**
1821 * This method is the default stop handler for the SCIC_SDS_REMOTE_DEVICE
1822 * ready substate machine. It will stop the current substate machine and
1823 * transition the base state machine to SCI_BASE_REMOTE_DEVICE_STATE_STOPPING.
1824 *
1825 * @param[in] device The SCI_BASE_REMOTE_DEVICE object which is cast to a
1826 *       SCIC_SDS_REMOTE_DEVICE object.
1827 *
1828 * @return SCI_STATUS
1829 * @retval SCI_SUCCESS
1830 */
1831SCI_STATUS scic_sds_remote_device_ready_state_stop_handler(
1832   SCI_BASE_REMOTE_DEVICE_T *device
1833)
1834{
1835   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
1836   SCI_STATUS                status      = SCI_SUCCESS;
1837
1838   // Request the parent state machine to transition to the stopping state
1839   sci_base_state_machine_change_state(
1840      scic_sds_remote_device_get_base_state_machine(this_device),
1841      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
1842   );
1843
1844   if (this_device->started_request_count == 0)
1845   {
1846      scic_sds_remote_node_context_destruct(
1847         this_device->rnc,
1848         scic_sds_cb_remote_device_rnc_destruct_complete,
1849         this_device
1850      );
1851   }
1852   else
1853      status = scic_sds_remote_device_terminate_requests(this_device);
1854
1855   return status;
1856}
1857
1858/**
1859 * This is the ready state device reset handler
1860 *
1861 * @param[in] device The SCI_BASE_REMOTE_DEVICE object which is cast to a
1862 *       SCIC_SDS_REMOTE_DEVICE object.
1863 *
1864 * @return SCI_STATUS
1865 */
1866SCI_STATUS scic_sds_remote_device_ready_state_reset_handler(
1867   SCI_BASE_REMOTE_DEVICE_T *device
1868)
1869{
1870   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
1871
1872   // Request the parent state machine to transition to the stopping state
1873   sci_base_state_machine_change_state(
1874      scic_sds_remote_device_get_base_state_machine(this_device),
1875      SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
1876   );
1877
1878   return SCI_SUCCESS;
1879}
1880
1881/**
1882 * This method will attempt to start a task request for this device object.
1883 * The remote device object will issue the start request for the task and if
1884 * successful it will start the request for the port object then increment its
1885 * own requet count.
1886 *
1887 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a
1888 *       SCIC_SDS_REMOTE_DEVICE for which the request is to be started.
1889 * @param[in] request The SCI_BASE_REQUEST which is cast to a
1890 *       SCIC_SDS_IO_REQUEST that is to be started.
1891 *
1892 * @return SCI_STATUS
1893 * @retval SCI_SUCCESS if the task request is started for this device object.
1894 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request object could
1895 *         not get the resources to start.
1896 */
1897static
1898SCI_STATUS scic_sds_remote_device_ready_state_start_task_handler(
1899   SCI_BASE_REMOTE_DEVICE_T *device,
1900   SCI_BASE_REQUEST_T       *request
1901)
1902{
1903   SCI_STATUS result;
1904   SCIC_SDS_REMOTE_DEVICE_T *this_device  = (SCIC_SDS_REMOTE_DEVICE_T *)device;
1905   SCIC_SDS_REQUEST_T       *task_request = (SCIC_SDS_REQUEST_T       *)request;
1906
1907   // See if the port is in a state where we can start the IO request
1908   result = scic_sds_port_start_io(
1909      scic_sds_remote_device_get_port(this_device), this_device, task_request);
1910
1911   if (result == SCI_SUCCESS)
1912   {
1913      result = scic_sds_remote_node_context_start_task(
1914                  this_device->rnc, task_request
1915               );
1916
1917      if (result == SCI_SUCCESS)
1918      {
1919         result = scic_sds_request_start(task_request);
1920      }
1921
1922      scic_sds_remote_device_start_request(this_device, task_request, result);
1923   }
1924
1925   return result;
1926}
1927
1928/**
1929 * This method will attempt to start an io request for this device object. The
1930 * remote device object will issue the start request for the io and if
1931 * successful it will start the request for the port object then increment its
1932 * own requet count.
1933 *
1934 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a
1935 *       SCIC_SDS_REMOTE_DEVICE for which the request is to be started.
1936 * @param[in] request The SCI_BASE_REQUEST which is cast to a
1937 *       SCIC_SDS_IO_REQUEST that is to be started.
1938 *
1939 * @return SCI_STATUS
1940 * @retval SCI_SUCCESS if the io request is started for this device object.
1941 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request object could
1942 *         not get the resources to start.
1943 */
1944static
1945SCI_STATUS scic_sds_remote_device_ready_state_start_io_handler(
1946   SCI_BASE_REMOTE_DEVICE_T *device,
1947   SCI_BASE_REQUEST_T       *request
1948)
1949{
1950   SCI_STATUS result;
1951   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
1952   SCIC_SDS_REQUEST_T       *io_request  = (SCIC_SDS_REQUEST_T       *)request;
1953
1954   // See if the port is in a state where we can start the IO request
1955   result = scic_sds_port_start_io(
1956      scic_sds_remote_device_get_port(this_device), this_device, io_request);
1957
1958   if (result == SCI_SUCCESS)
1959   {
1960      result = scic_sds_remote_node_context_start_io(
1961                  this_device->rnc, io_request
1962               );
1963
1964      if (result == SCI_SUCCESS)
1965      {
1966         result = scic_sds_request_start(io_request);
1967      }
1968
1969      scic_sds_remote_device_start_request(this_device, io_request, result);
1970   }
1971
1972   return result;
1973}
1974
1975/**
1976 * This method will complete the request for the remote device object.  The
1977 * method will call the completion handler for the request object and if
1978 * successful it will complete the request on the port object then decrement
1979 * its own started_request_count.
1980 *
1981 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a
1982 *       SCIC_SDS_REMOTE_DEVICE for which the request is to be completed.
1983 * @param[in] request The SCI_BASE_REQUEST which is cast to a
1984 *       SCIC_SDS_IO_REQUEST that is to be completed.
1985 *
1986 * @return SCI_STATUS
1987 */
1988static
1989SCI_STATUS scic_sds_remote_device_ready_state_complete_request_handler(
1990   SCI_BASE_REMOTE_DEVICE_T *device,
1991   SCI_BASE_REQUEST_T       *request
1992)
1993{
1994   SCI_STATUS result;
1995   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
1996   SCIC_SDS_REQUEST_T       *the_request = (SCIC_SDS_REQUEST_T       *)request;
1997
1998   result = scic_sds_request_complete(the_request);
1999
2000   if (result == SCI_SUCCESS)
2001   {
2002      // See if the port is in a state where we can start the IO request
2003      result = scic_sds_port_complete_io(
2004         scic_sds_remote_device_get_port(this_device), this_device, the_request);
2005
2006      if (result == SCI_SUCCESS)
2007      {
2008         scic_sds_remote_device_decrement_request_count(this_device);
2009      }
2010   }
2011
2012   return result;
2013}
2014
2015//*****************************************************************************
2016//*  STOPPING STATE HANDLERS
2017//*****************************************************************************
2018
2019/**
2020 * This method will stop a SCIC_SDS_REMOTE_DEVICE that is already in the
2021 * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an
2022 * error since we allow a stop request on a device that is alreay stopping or
2023 * stopped.
2024 *
2025 * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a
2026 *       SCIC_SDS_REMOTE_DEVICE.
2027 *
2028 * @return SCI_STATUS
2029 * @retval SCI_SUCCESS
2030 */
2031static
2032SCI_STATUS scic_sds_remote_device_stopping_state_stop_handler(
2033   SCI_BASE_REMOTE_DEVICE_T *device
2034)
2035{
2036   // All requests should have been terminated, but if there is an
2037   // attempt to stop a device already in the stopping state, then
2038   // try again to terminate.
2039   return scic_sds_remote_device_terminate_requests(
2040             (SCIC_SDS_REMOTE_DEVICE_T*)device);
2041}
2042
2043
2044/**
2045 * This method completes requests for this SCIC_SDS_REMOTE_DEVICE while it is
2046 * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the
2047 * complete method for the request object and if that is successful the port
2048 * object is called to complete the task request. Then the device object
2049 * itself completes the task request. If SCIC_SDS_REMOTE_DEVICE
2050 * started_request_count goes to 0 and the invalidate RNC request has
2051 * completed the device object can transition to the
2052 * SCI_BASE_REMOTE_DEVICE_STATE_STOPPED.
2053 *
2054 * @param[in] device The device object for which the request is completing.
2055 * @param[in] request The task request that is being completed.
2056 *
2057 * @return SCI_STATUS
2058 */
2059static
2060SCI_STATUS scic_sds_remote_device_stopping_state_complete_request_handler(
2061   SCI_BASE_REMOTE_DEVICE_T *device,
2062   SCI_BASE_REQUEST_T       *request
2063)
2064{
2065   SCI_STATUS                status = SCI_SUCCESS;
2066   SCIC_SDS_REQUEST_T       *this_request = (SCIC_SDS_REQUEST_T   *)request;
2067   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
2068
2069   status = scic_sds_request_complete(this_request);
2070   if (status == SCI_SUCCESS)
2071   {
2072      status = scic_sds_port_complete_io(
2073                  scic_sds_remote_device_get_port(this_device),
2074                  this_device,
2075                  this_request
2076               );
2077
2078      if (status == SCI_SUCCESS)
2079      {
2080         scic_sds_remote_device_decrement_request_count(this_device);
2081
2082         if (scic_sds_remote_device_get_request_count(this_device) == 0)
2083         {
2084            scic_sds_remote_node_context_destruct(
2085               this_device->rnc,
2086               scic_sds_cb_remote_device_rnc_destruct_complete,
2087               this_device
2088            );
2089         }
2090      }
2091   }
2092
2093   return status;
2094}
2095
2096//*****************************************************************************
2097//*  RESETTING STATE HANDLERS
2098//*****************************************************************************
2099
2100/**
2101 * This method will complete the reset operation when the device is in the
2102 * resetting state.
2103 *
2104 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is to be cast into a
2105 *       SCIC_SDS_REMOTE_DEVICE object.
2106 *
2107 * @return SCI_STATUS
2108 */
2109static
2110SCI_STATUS scic_sds_remote_device_resetting_state_reset_complete_handler(
2111   SCI_BASE_REMOTE_DEVICE_T * device
2112)
2113{
2114   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
2115
2116   sci_base_state_machine_change_state(
2117      &this_device->parent.state_machine,
2118      SCI_BASE_REMOTE_DEVICE_STATE_READY
2119   );
2120
2121   return SCI_SUCCESS;
2122}
2123
2124/**
2125 * This method will stop the remote device while in the resetting state.
2126 *
2127 * @param[in] device The SCI_BASE_REMOTE_DEVICE which is to be cast into a
2128 *       SCIC_SDS_REMOTE_DEVICE object.
2129 *
2130 * @return SCI_STATUS
2131 */
2132static
2133SCI_STATUS scic_sds_remote_device_resetting_state_stop_handler(
2134   SCI_BASE_REMOTE_DEVICE_T * device
2135)
2136{
2137   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
2138
2139   sci_base_state_machine_change_state(
2140      &this_device->parent.state_machine,
2141      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
2142   );
2143
2144   return SCI_SUCCESS;
2145}
2146
2147/**
2148 * This method completes requests for this SCIC_SDS_REMOTE_DEVICE while it is
2149 * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the
2150 * complete method for the request object and if that is successful the port
2151 * object is called to complete the task request. Then the device object
2152 * itself completes the task request.
2153 *
2154 * @param[in] device The device object for which the request is completing.
2155 * @param[in] request The task request that is being completed.
2156 *
2157 * @return SCI_STATUS
2158 */
2159static
2160SCI_STATUS scic_sds_remote_device_resetting_state_complete_request_handler(
2161   SCI_BASE_REMOTE_DEVICE_T *device,
2162   SCI_BASE_REQUEST_T       *request
2163)
2164{
2165   SCI_STATUS status = SCI_SUCCESS;
2166   SCIC_SDS_REQUEST_T       *this_request = (SCIC_SDS_REQUEST_T   *)request;
2167   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
2168
2169   status = scic_sds_request_complete(this_request);
2170
2171   if (status == SCI_SUCCESS)
2172   {
2173      status = scic_sds_port_complete_io(
2174         scic_sds_remote_device_get_port(this_device), this_device, this_request);
2175
2176      if (status == SCI_SUCCESS)
2177      {
2178         scic_sds_remote_device_decrement_request_count(this_device);
2179      }
2180   }
2181
2182   return status;
2183}
2184
2185//*****************************************************************************
2186//*  FAILED STATE HANDLERS
2187//*****************************************************************************
2188
2189SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
2190   scic_sds_remote_device_state_handler_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
2191{
2192   // SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
2193   {
2194      {
2195         scic_sds_remote_device_default_start_handler,
2196         scic_sds_remote_device_default_stop_handler,
2197         scic_sds_remote_device_default_fail_handler,
2198         scic_sds_remote_device_default_destruct_handler,
2199         scic_sds_remote_device_default_reset_handler,
2200         scic_sds_remote_device_default_reset_complete_handler,
2201         scic_sds_remote_device_default_start_request_handler,
2202         scic_sds_remote_device_default_complete_request_handler,
2203         scic_sds_remote_device_default_continue_request_handler,
2204         scic_sds_remote_device_default_start_request_handler,
2205         scic_sds_remote_device_default_complete_request_handler
2206      },
2207      scic_sds_remote_device_default_suspend_handler,
2208      scic_sds_remote_device_default_resume_handler,
2209      scic_sds_remote_device_default_event_handler,
2210      scic_sds_remote_device_default_frame_handler
2211   },
2212   // SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
2213   {
2214      {
2215         scic_sds_remote_device_stopped_state_start_handler,
2216         scic_sds_remote_device_stopped_state_stop_handler,
2217         scic_sds_remote_device_default_fail_handler,
2218         scic_sds_remote_device_stopped_state_destruct_handler,
2219         scic_sds_remote_device_default_reset_handler,
2220         scic_sds_remote_device_default_reset_complete_handler,
2221         scic_sds_remote_device_default_start_request_handler,
2222         scic_sds_remote_device_default_complete_request_handler,
2223         scic_sds_remote_device_default_continue_request_handler,
2224         scic_sds_remote_device_default_start_request_handler,
2225         scic_sds_remote_device_default_complete_request_handler
2226      },
2227      scic_sds_remote_device_default_suspend_handler,
2228      scic_sds_remote_device_default_resume_handler,
2229      scic_sds_remote_device_default_event_handler,
2230      scic_sds_remote_device_default_frame_handler
2231   },
2232   // SCI_BASE_REMOTE_DEVICE_STATE_STARTING
2233   {
2234      {
2235         scic_sds_remote_device_default_start_handler,
2236         scic_sds_remote_device_starting_state_stop_handler,
2237         scic_sds_remote_device_default_fail_handler,
2238         scic_sds_remote_device_default_destruct_handler,
2239         scic_sds_remote_device_default_reset_handler,
2240         scic_sds_remote_device_default_reset_complete_handler,
2241         scic_sds_remote_device_default_start_request_handler,
2242         scic_sds_remote_device_default_complete_request_handler,
2243         scic_sds_remote_device_default_continue_request_handler,
2244         scic_sds_remote_device_default_start_request_handler,
2245         scic_sds_remote_device_default_complete_request_handler
2246      },
2247      scic_sds_remote_device_default_suspend_handler,
2248      scic_sds_remote_device_default_resume_handler,
2249      scic_sds_remote_device_general_event_handler,
2250      scic_sds_remote_device_default_frame_handler
2251   },
2252   // SCI_BASE_REMOTE_DEVICE_STATE_READY
2253   {
2254      {
2255         scic_sds_remote_device_default_start_handler,
2256         scic_sds_remote_device_ready_state_stop_handler,
2257         scic_sds_remote_device_default_fail_handler,
2258         scic_sds_remote_device_default_destruct_handler,
2259         scic_sds_remote_device_ready_state_reset_handler,
2260         scic_sds_remote_device_default_reset_complete_handler,
2261         scic_sds_remote_device_ready_state_start_io_handler,
2262         scic_sds_remote_device_ready_state_complete_request_handler,
2263         scic_sds_remote_device_default_continue_request_handler,
2264         scic_sds_remote_device_ready_state_start_task_handler,
2265         scic_sds_remote_device_ready_state_complete_request_handler
2266      },
2267      scic_sds_remote_device_general_suspend_handler,
2268      scic_sds_remote_device_general_resume_handler,
2269      scic_sds_remote_device_general_event_handler,
2270      scic_sds_remote_device_general_frame_handler,
2271   },
2272   // SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
2273   {
2274      {
2275         scic_sds_remote_device_default_start_handler,
2276         scic_sds_remote_device_stopping_state_stop_handler,
2277         scic_sds_remote_device_default_fail_handler,
2278         scic_sds_remote_device_default_destruct_handler,
2279         scic_sds_remote_device_default_reset_handler,
2280         scic_sds_remote_device_default_reset_complete_handler,
2281         scic_sds_remote_device_default_start_request_handler,
2282         scic_sds_remote_device_stopping_state_complete_request_handler,
2283         scic_sds_remote_device_default_continue_request_handler,
2284         scic_sds_remote_device_default_start_request_handler,
2285         scic_sds_remote_device_stopping_state_complete_request_handler
2286      },
2287      scic_sds_remote_device_default_suspend_handler,
2288      scic_sds_remote_device_default_resume_handler,
2289      scic_sds_remote_device_general_event_handler,
2290      scic_sds_remote_device_general_frame_handler
2291   },
2292   // SCI_BASE_REMOTE_DEVICE_STATE_FAILED
2293   {
2294      {
2295         scic_sds_remote_device_default_start_handler,
2296         scic_sds_remote_device_default_stop_handler,
2297         scic_sds_remote_device_default_fail_handler,
2298         scic_sds_remote_device_default_destruct_handler,
2299         scic_sds_remote_device_default_reset_handler,
2300         scic_sds_remote_device_default_reset_complete_handler,
2301         scic_sds_remote_device_default_start_request_handler,
2302         scic_sds_remote_device_default_complete_request_handler,
2303         scic_sds_remote_device_default_continue_request_handler,
2304         scic_sds_remote_device_default_start_request_handler,
2305         scic_sds_remote_device_default_complete_request_handler
2306      },
2307      scic_sds_remote_device_default_suspend_handler,
2308      scic_sds_remote_device_default_resume_handler,
2309      scic_sds_remote_device_default_event_handler,
2310      scic_sds_remote_device_general_frame_handler
2311   },
2312   // SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
2313   {
2314      {
2315         scic_sds_remote_device_default_start_handler,
2316         scic_sds_remote_device_resetting_state_stop_handler,
2317         scic_sds_remote_device_default_fail_handler,
2318         scic_sds_remote_device_default_destruct_handler,
2319         scic_sds_remote_device_default_reset_handler,
2320         scic_sds_remote_device_resetting_state_reset_complete_handler,
2321         scic_sds_remote_device_default_start_request_handler,
2322         scic_sds_remote_device_resetting_state_complete_request_handler,
2323         scic_sds_remote_device_default_continue_request_handler,
2324         scic_sds_remote_device_default_start_request_handler,
2325         scic_sds_remote_device_resetting_state_complete_request_handler
2326      },
2327      scic_sds_remote_device_default_suspend_handler,
2328      scic_sds_remote_device_default_resume_handler,
2329      scic_sds_remote_device_default_event_handler,
2330      scic_sds_remote_device_general_frame_handler
2331   },
2332#if !defined(DISABLE_WIDE_PORTED_TARGETS)
2333   // SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH - unused by SCIC
2334   {
2335      {
2336         scic_sds_remote_device_default_start_handler,
2337         scic_sds_remote_device_default_stop_handler,
2338         scic_sds_remote_device_default_fail_handler,
2339         scic_sds_remote_device_default_destruct_handler,
2340         scic_sds_remote_device_default_reset_handler,
2341         scic_sds_remote_device_default_reset_complete_handler,
2342         scic_sds_remote_device_default_start_request_handler,
2343         scic_sds_remote_device_default_complete_request_handler,
2344         scic_sds_remote_device_default_continue_request_handler,
2345         scic_sds_remote_device_default_start_request_handler,
2346         scic_sds_remote_device_default_complete_request_handler
2347      },
2348      scic_sds_remote_device_default_suspend_handler,
2349      scic_sds_remote_device_default_resume_handler,
2350      scic_sds_remote_device_default_event_handler,
2351      scic_sds_remote_device_default_frame_handler
2352   },
2353#endif
2354   // SCI_BASE_REMOTE_DEVICE_STATE_FINAL
2355   {
2356      {
2357         scic_sds_remote_device_default_start_handler,
2358         scic_sds_remote_device_default_stop_handler,
2359         scic_sds_remote_device_default_fail_handler,
2360         scic_sds_remote_device_default_destruct_handler,
2361         scic_sds_remote_device_default_reset_handler,
2362         scic_sds_remote_device_default_reset_complete_handler,
2363         scic_sds_remote_device_default_start_request_handler,
2364         scic_sds_remote_device_default_complete_request_handler,
2365         scic_sds_remote_device_default_continue_request_handler,
2366         scic_sds_remote_device_default_start_request_handler,
2367         scic_sds_remote_device_default_complete_request_handler
2368      },
2369      scic_sds_remote_device_default_suspend_handler,
2370      scic_sds_remote_device_default_resume_handler,
2371      scic_sds_remote_device_default_event_handler,
2372      scic_sds_remote_device_default_frame_handler
2373   }
2374};
2375
2376/**
2377 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it
2378 * immediatly transitions the remote device object to the stopped state.
2379 *
2380 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
2381 *            SCIC_SDS_REMOTE_DEVICE.
2382 *
2383 * @return none
2384 */
2385static
2386void scic_sds_remote_device_initial_state_enter(
2387   SCI_BASE_OBJECT_T *object
2388)
2389{
2390   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
2391
2392   SET_STATE_HANDLER(
2393      this_device,
2394      scic_sds_remote_device_state_handler_table,
2395      SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
2396   );
2397
2398   // Initial state is a transitional state to the stopped state
2399   sci_base_state_machine_change_state(
2400      scic_sds_remote_device_get_base_state_machine(this_device),
2401      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
2402   );
2403}
2404
2405/**
2406 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it
2407 * sets the stopped state handlers and if this state is entered from the
2408 * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING then the SCI User is informed that
2409 * the device stop is complete.
2410 *
2411 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
2412 *       SCIC_SDS_REMOTE_DEVICE.
2413 *
2414 * @return none
2415 */
2416static
2417void scic_sds_remote_device_stopped_state_enter(
2418   SCI_BASE_OBJECT_T *object
2419)
2420{
2421   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
2422
2423   SET_STATE_HANDLER(
2424      this_device,
2425      scic_sds_remote_device_state_handler_table,
2426      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
2427   );
2428
2429   // If we are entering from the stopping state let the SCI User know that
2430   // the stop operation has completed.
2431   if (this_device->parent.state_machine.previous_state_id
2432       == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING)
2433   {
2434      scic_cb_remote_device_stop_complete(
2435         scic_sds_remote_device_get_controller(this_device),
2436         this_device,
2437         SCI_SUCCESS
2438      );
2439   }
2440
2441   scic_sds_controller_remote_device_stopped(
2442      scic_sds_remote_device_get_controller(this_device),
2443      this_device
2444   );
2445}
2446
2447/**
2448 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it
2449 * sets the starting state handlers, sets the device not ready, and posts the
2450 * remote node context to the hardware.
2451 *
2452 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
2453 *       SCIC_SDS_REMOTE_DEVICE.
2454 *
2455 * @return none
2456 */
2457static
2458void scic_sds_remote_device_starting_state_enter(
2459   SCI_BASE_OBJECT_T *object
2460)
2461{
2462   SCIC_SDS_CONTROLLER_T    * the_controller;
2463   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
2464
2465   the_controller = scic_sds_remote_device_get_controller(this_device);
2466
2467   SET_STATE_HANDLER(
2468      this_device,
2469      scic_sds_remote_device_state_handler_table,
2470      SCI_BASE_REMOTE_DEVICE_STATE_STARTING
2471   );
2472
2473   scic_cb_remote_device_not_ready(
2474      the_controller,
2475      this_device,
2476      SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED
2477   );
2478}
2479
2480
2481/**
2482 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets
2483 * the ready state handlers, and starts the ready substate machine.
2484 *
2485 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
2486 *       SCIC_SDS_REMOTE_DEVICE.
2487 *
2488 * @return none
2489 */
2490static
2491void scic_sds_remote_device_ready_state_enter(
2492   SCI_BASE_OBJECT_T *object
2493)
2494{
2495   SCIC_SDS_CONTROLLER_T    * the_controller;
2496   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
2497
2498   the_controller = scic_sds_remote_device_get_controller(this_device);
2499
2500   SET_STATE_HANDLER(
2501      this_device,
2502      scic_sds_remote_device_state_handler_table,
2503      SCI_BASE_REMOTE_DEVICE_STATE_READY
2504   );
2505
2506   /// @todo Check the device object for the proper return code for this
2507   ///       callback
2508   scic_cb_remote_device_start_complete(
2509      the_controller, this_device, SCI_SUCCESS
2510   );
2511
2512   scic_sds_controller_remote_device_started(
2513      the_controller, this_device
2514   );
2515
2516   if (this_device->has_ready_substate_machine)
2517   {
2518      sci_base_state_machine_start(&this_device->ready_substate_machine);
2519   }
2520   else
2521   {
2522      scic_cb_remote_device_ready(the_controller, this_device);
2523   }
2524}
2525
2526/**
2527 * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does
2528 * nothing.
2529 *
2530 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
2531 *       SCIC_SDS_REMOTE_DEVICE.
2532 *
2533 * @return none
2534 */
2535static
2536void scic_sds_remote_device_ready_state_exit(
2537   SCI_BASE_OBJECT_T *object
2538)
2539{
2540   SCIC_SDS_CONTROLLER_T    * the_controller;
2541   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
2542
2543   the_controller = scic_sds_remote_device_get_controller(this_device);
2544
2545   if (this_device->has_ready_substate_machine)
2546   {
2547      sci_base_state_machine_stop(&this_device->ready_substate_machine);
2548   }
2549   else
2550   {
2551      scic_cb_remote_device_not_ready(
2552         the_controller,
2553         this_device,
2554         SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED
2555      );
2556   }
2557}
2558
2559/**
2560 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING it
2561 * sets the stopping state handlers and posts an RNC invalidate request to the
2562 * SCU hardware.
2563 *
2564 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
2565 *       SCIC_SDS_REMOTE_DEVICE.
2566 *
2567 * @return none
2568 */
2569static
2570void scic_sds_remote_device_stopping_state_enter(
2571   SCI_BASE_OBJECT_T *object
2572)
2573{
2574   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
2575
2576   SET_STATE_HANDLER(
2577      this_device,
2578      scic_sds_remote_device_state_handler_table,
2579      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
2580   );
2581}
2582
2583/**
2584 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FAILED it
2585 * sets the stopping state handlers.
2586 *
2587 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
2588 *       SCIC_SDS_REMOTE_DEVICE.
2589 *
2590 * @return none
2591 */
2592static
2593void scic_sds_remote_device_failed_state_enter(
2594   SCI_BASE_OBJECT_T *object
2595)
2596{
2597   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
2598
2599   SET_STATE_HANDLER(
2600      this_device,
2601      scic_sds_remote_device_state_handler_table,
2602      SCI_BASE_REMOTE_DEVICE_STATE_FAILED
2603   );
2604}
2605
2606/**
2607 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it
2608 * sets the resetting state handlers.
2609 *
2610 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
2611 *       SCIC_SDS_REMOTE_DEVICE.
2612 *
2613 * @return none
2614 */
2615static
2616void scic_sds_remote_device_resetting_state_enter(
2617   SCI_BASE_OBJECT_T *object
2618)
2619{
2620   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
2621
2622   SET_STATE_HANDLER(
2623      this_device,
2624      scic_sds_remote_device_state_handler_table,
2625      SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
2626   );
2627
2628   scic_sds_remote_node_context_suspend(
2629      this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
2630}
2631
2632/**
2633 * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it
2634 * does nothing.
2635 *
2636 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
2637 *       SCIC_SDS_REMOTE_DEVICE.
2638 *
2639 * @return none
2640 */
2641static
2642void scic_sds_remote_device_resetting_state_exit(
2643   SCI_BASE_OBJECT_T *object
2644)
2645{
2646   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
2647
2648   scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL);
2649}
2650
2651/**
2652 * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FINAL it sets
2653 * the final state handlers.
2654 *
2655 * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
2656 *       SCIC_SDS_REMOTE_DEVICE.
2657 *
2658 * @return none
2659 */
2660static
2661void scic_sds_remote_device_final_state_enter(
2662   SCI_BASE_OBJECT_T *object
2663)
2664{
2665   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
2666
2667   SET_STATE_HANDLER(
2668      this_device,
2669      scic_sds_remote_device_state_handler_table,
2670      SCI_BASE_REMOTE_DEVICE_STATE_FINAL
2671   );
2672}
2673
2674// ---------------------------------------------------------------------------
2675
2676SCI_BASE_STATE_T
2677   scic_sds_remote_device_state_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
2678{
2679   {
2680      SCI_BASE_REMOTE_DEVICE_STATE_INITIAL,
2681      scic_sds_remote_device_initial_state_enter,
2682      NULL
2683   },
2684   {
2685      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED,
2686      scic_sds_remote_device_stopped_state_enter,
2687      NULL
2688   },
2689   {
2690      SCI_BASE_REMOTE_DEVICE_STATE_STARTING,
2691      scic_sds_remote_device_starting_state_enter,
2692      NULL
2693   },
2694   {
2695      SCI_BASE_REMOTE_DEVICE_STATE_READY,
2696      scic_sds_remote_device_ready_state_enter,
2697      scic_sds_remote_device_ready_state_exit
2698   },
2699   {
2700      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
2701      scic_sds_remote_device_stopping_state_enter,
2702      NULL
2703   },
2704   {
2705      SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
2706      scic_sds_remote_device_failed_state_enter,
2707      NULL
2708   },
2709   {
2710      SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
2711      scic_sds_remote_device_resetting_state_enter,
2712      scic_sds_remote_device_resetting_state_exit
2713   },
2714#if !defined(DISABLE_WIDE_PORTED_TARGETS)
2715   {  //Not used by SCIC
2716      SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH,
2717      NULL,
2718      NULL
2719   },
2720#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
2721   {
2722      SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
2723      scic_sds_remote_device_final_state_enter,
2724      NULL
2725   }
2726};
2727
2728