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