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