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