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