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 structures, constants, and prototypes
62 * associated with the remote node context in the silicon. It
63 * exists to model and manage the remote node context in the silicon.
64 */
65
66 #include <dev/isci/scil/sci_util.h>
67 #include <dev/isci/scil/scic_sds_logger.h>
68 #include <dev/isci/scil/scic_sds_controller.h>
69 #include <dev/isci/scil/scic_sds_remote_device.h>
70 #include <dev/isci/scil/scic_sds_remote_node_context.h>
71 #include <dev/isci/scil/sci_base_state_machine.h>
72 #include <dev/isci/scil/scic_remote_device.h>
73 #include <dev/isci/scil/scic_sds_port.h>
74 #include <dev/isci/scil/scu_event_codes.h>
75 #include <dev/isci/scil/scu_task_context.h>
76
77 /**
78 * @brief
79 */
80 void scic_sds_remote_node_context_construct(
81 SCIC_SDS_REMOTE_DEVICE_T * device,
82 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc,
83 U16 remote_node_index
84 )
85 {
86 memset (rnc, 0, sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T) );
87
88 rnc->remote_node_index = remote_node_index;
89 rnc->device = device;
90 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
91
92 rnc->parent.logger = device->parent.parent.logger;
93
94 sci_base_state_machine_construct(
95 &rnc->state_machine,
96 &rnc->parent,
97 scic_sds_remote_node_context_state_table,
98 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
99 );
100
101 sci_base_state_machine_start(&rnc->state_machine);
102
103 // State logging initialization takes place late for the remote node context
104 // see the resume state handler for the initial state.
105 }
106
107 /**
108 * This method will return TRUE if the RNC is not in the initial state. In
109 * all other states the RNC is considered active and this will return TRUE.
110 *
111 * @note The destroy request of the state machine drives the RNC back to the
112 * initial state. If the state machine changes then this routine will
113 * also have to be changed.
114 *
115 * @param[in] this_rnc The RNC for which the is posted request is being made.
116 *
117 * @return BOOL
118 * @retval TRUE if the state machine is not in the initial state
119 * @retval FALSE if the state machine is in the initial state
120 */
121 BOOL scic_sds_remote_node_context_is_initialized(
122 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
123 )
124 {
125 U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
126
127 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE)
128 {
129 return FALSE;
130 }
131
132 return TRUE;
133 }
134
135 /**
136 * This method will return TRUE if the remote node context is in a READY state
137 * otherwise it will return FALSE
138 *
139 * @param[in] this_rnc The state of the remote node context object to check.
140 *
141 * @return BOOL
142 * @retval TRUE if the remote node context is in the ready state.
143 * @retval FALSE if the remote node context is not in the ready state.
144 */
145 BOOL scic_sds_remote_node_context_is_ready(
146 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
147 )
148 {
149 U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
150
151 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE)
152 {
153 return TRUE;
154 }
155
156 return FALSE;
157 }
158
159 /**
160 * This method will construct the RNC buffer for this remote device object.
161 *
162 * @param[in] this_device The remote device to use to construct the RNC
163 * buffer.
164 * @param[in] rnc The buffer into which the remote device data will be copied.
165 *
166 * @return none
167 */
168 void scic_sds_remote_node_context_construct_buffer(
169 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
170 )
171 {
172 SCU_REMOTE_NODE_CONTEXT_T * rnc;
173 SCIC_SDS_CONTROLLER_T * the_controller;
174
175 the_controller = scic_sds_remote_device_get_controller(this_rnc->device);
176
177 rnc = scic_sds_controller_get_remote_node_context_buffer(
178 the_controller, this_rnc->remote_node_index);
179
180 memset(
181 rnc,
182 0x00,
183 sizeof(SCU_REMOTE_NODE_CONTEXT_T)
184 * scic_sds_remote_device_node_count(this_rnc->device)
185 );
186
187 rnc->ssp.remote_node_index = this_rnc->remote_node_index;
188 rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width;
189 rnc->ssp.logical_port_index =
190 scic_sds_remote_device_get_port_index(this_rnc->device);
191
192 rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high);
193 rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low);
194
195 rnc->ssp.nexus_loss_timer_enable = TRUE;
196 rnc->ssp.check_bit = FALSE;
197 rnc->ssp.is_valid = FALSE;
198 rnc->ssp.is_remote_node_context = TRUE;
199 rnc->ssp.function_number = 0;
200
201 rnc->ssp.arbitration_wait_time = 0;
202
203
204 if (
205 this_rnc->device->target_protocols.u.bits.attached_sata_device
206 || this_rnc->device->target_protocols.u.bits.attached_stp_target
207 )
208 {
209 rnc->ssp.connection_occupancy_timeout =
210 the_controller->user_parameters.sds1.stp_max_occupancy_timeout;
211 rnc->ssp.connection_inactivity_timeout =
212 the_controller->user_parameters.sds1.stp_inactivity_timeout;
213 }
214 else
215 {
216 rnc->ssp.connection_occupancy_timeout =
217 the_controller->user_parameters.sds1.ssp_max_occupancy_timeout;
218 rnc->ssp.connection_inactivity_timeout =
219 the_controller->user_parameters.sds1.ssp_inactivity_timeout;
220 }
221
222 rnc->ssp.initial_arbitration_wait_time = 0;
223
224 // Open Address Frame Parameters
225 rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate;
226 rnc->ssp.oaf_features = 0;
227 rnc->ssp.oaf_source_zone_group = 0;
228 rnc->ssp.oaf_more_compatibility_features = 0;
229 }
230
231 // ---------------------------------------------------------------------------
232
233 #ifdef SCI_LOGGING
234 /**
235 * This method will enable and turn on state transition logging for the remote
236 * node context object.
237 *
238 * @param[in] this_rnc The remote node context for which state transition
239 * logging is to be enabled.
240 *
241 * @return none
242 */
243 void scic_sds_remote_node_context_initialize_state_logging(
244 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
245 )
246 {
247 sci_base_state_machine_logger_initialize(
248 &this_rnc->state_machine_logger,
249 &this_rnc->state_machine,
250 &this_rnc->parent,
251 scic_cb_logger_log_states,
252 "SCIC_SDS_REMOTE_NODE_CONTEXT_T", "state machine",
253 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
254 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
255 SCIC_LOG_OBJECT_STP_REMOTE_TARGET
256 );
257 }
258
259 /**
260 * This method will stop the state machine logging for this object and should
261 * be called before the object is destroyed.
262 *
263 * @param[in] this_rnc The remote node context on which to stop logging state
264 * transitions.
265 *
266 * @return none
267 */
268 void scic_sds_remote_node_context_deinitialize_state_logging(
269 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
270 )
271 {
272 sci_base_state_machine_logger_deinitialize(
273 &this_rnc->state_machine_logger,
274 &this_rnc->state_machine
275 );
276 }
277 #endif
278
279 /**
280 * This method will setup the remote node context object so it will transition
281 * to its ready state. If the remote node context is already setup to
282 * transition to its final state then this function does nothing.
283 *
284 * @param[in] this_rnc
285 * @param[in] the_callback
286 * @param[in] callback_parameter
287 *
288 * @return none
289 */
290 static
291 void scic_sds_remote_node_context_setup_to_resume(
292 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
293 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
294 void * callback_parameter
295 )
296 {
297 if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
298 {
299 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY;
300 this_rnc->user_callback = the_callback;
301 this_rnc->user_cookie = callback_parameter;
302 }
303 }
304
305 /**
306 * This method will setup the remote node context object so it will
307 * transition to its final state.
308 *
309 * @param[in] this_rnc
310 * @param[in] the_callback
311 * @param[in] callback_parameter
312 *
313 * @return none
314 */
315 static
316 void scic_sds_remote_node_context_setup_to_destory(
317 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
318 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
319 void * callback_parameter
320 )
321 {
322 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL;
323 this_rnc->user_callback = the_callback;
324 this_rnc->user_cookie = callback_parameter;
325 }
326
327 /**
328 * This method will continue to resume a remote node context. This is used
329 * in the states where a resume is requested while a resume is in progress.
330 *
331 * @param[in] this_rnc
332 * @param[in] the_callback
333 * @param[in] callback_parameter
334 */
335 static
336 SCI_STATUS scic_sds_remote_node_context_continue_to_resume_handler(
337 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
338 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
339 void * callback_parameter
340 )
341 {
342 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
343 {
344 this_rnc->user_callback = the_callback;
345 this_rnc->user_cookie = callback_parameter;
346
347 return SCI_SUCCESS;
348 }
349
350 return SCI_FAILURE_INVALID_STATE;
351 }
352
353 //******************************************************************************
354 //* REMOTE NODE CONTEXT STATE MACHINE
355 //******************************************************************************
356
357 static
358 SCI_STATUS scic_sds_remote_node_context_default_destruct_handler(
359 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
360 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
361 void * callback_parameter
362 )
363 {
364 SCIC_LOG_WARNING((
365 sci_base_object_get_logger(this_rnc->device),
366 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
367 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
368 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
369 "SCIC Remote Node Context 0x%x requested to stop while in unexpected state %d\n",
370 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
371 ));
372
373 // We have decided that the destruct request on the remote node context can not fail
374 // since it is either in the initial/destroyed state or is can be destroyed.
375 return SCI_SUCCESS;
376 }
377
378 static
379 SCI_STATUS scic_sds_remote_node_context_default_suspend_handler(
380 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
381 U32 suspend_type,
382 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
383 void * callback_parameter
384 )
385 {
386 SCIC_LOG_WARNING((
387 sci_base_object_get_logger(this_rnc->device),
388 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
389 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
390 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
391 "SCIC Remote Node Context 0x%x requested to suspend while in wrong state %d\n",
392 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
393 ));
394
395 return SCI_FAILURE_INVALID_STATE;
396 }
397
398 static
399 SCI_STATUS scic_sds_remote_node_context_default_resume_handler(
400 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
401 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
402 void * callback_parameter
403 )
404 {
405 SCIC_LOG_WARNING((
406 sci_base_object_get_logger(this_rnc->device),
407 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
408 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
409 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
410 "SCIC Remote Node Context 0x%x requested to resume while in wrong state %d\n",
411 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
412 ));
413
414 return SCI_FAILURE_INVALID_STATE;
415 }
416
417 static
418 SCI_STATUS scic_sds_remote_node_context_default_start_io_handler(
419 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
420 struct SCIC_SDS_REQUEST * the_request
421 )
422 {
423 SCIC_LOG_WARNING((
424 sci_base_object_get_logger(this_rnc->device),
425 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
426 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
427 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
428 "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n",
429 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
430 ));
431
432 return SCI_FAILURE_INVALID_STATE;
433 }
434
435 static
436 SCI_STATUS scic_sds_remote_node_context_default_start_task_handler(
437 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
438 struct SCIC_SDS_REQUEST * the_request
439 )
440 {
441 SCIC_LOG_WARNING((
442 sci_base_object_get_logger(this_rnc->device),
443 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
444 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
445 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
446 "SCIC Remote Node Context 0x%x requested to start task 0x%x while in wrong state %d\n",
447 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
448 ));
449
450 return SCI_FAILURE;
451 }
452
453 static
454 SCI_STATUS scic_sds_remote_node_context_default_event_handler(
455 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
456 U32 event_code
457 )
458 {
459 SCIC_LOG_WARNING((
460 sci_base_object_get_logger(this_rnc->device),
461 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
462 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
463 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
464 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in wrong state %d\n",
465 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
466 ));
467
468 return SCI_FAILURE_INVALID_STATE;
469 }
470
471 /**
472 * This method determines if the task request can be started by the SCU
473 * hardware. When the RNC is in the ready state any task can be started.
474 *
475 * @param[in] this_rnc The rnc for which the task request is targeted.
476 * @param[in] the_request The request which is going to be started.
477 *
478 * @return SCI_STATUS
479 * @retval SCI_SUCCESS
480 */
481 static
482 SCI_STATUS scic_sds_remote_node_context_success_start_task_handler(
483 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
484 struct SCIC_SDS_REQUEST * the_request
485 )
486 {
487 return SCI_SUCCESS;
488 }
489
490 /**
491 * This method handles destruct calls from the various state handlers. The
492 * remote node context can be requested to destroy from any state. If there
493 * was a user callback it is always replaced with the request to destroy user
494 * callback.
495 *
496 * @param[in] this_rnc
497 * @param[in] the_callback
498 * @param[in] callback_parameter
499 *
500 * @return SCI_STATUS
501 */
502 static
503 SCI_STATUS scic_sds_remote_node_context_general_destruct_handler(
504 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
505 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
506 void * callback_parameter
507 )
508 {
509 scic_sds_remote_node_context_setup_to_destory(
510 this_rnc, the_callback, callback_parameter
511 );
512
513 sci_base_state_machine_change_state(
514 &this_rnc->state_machine,
515 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
516 );
517
518 return SCI_SUCCESS;
519 }
520 // ---------------------------------------------------------------------------
521 static
522 SCI_STATUS scic_sds_remote_node_context_reset_required_start_io_handler(
523 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
524 struct SCIC_SDS_REQUEST * the_request
525 )
526 {
527 SCIC_LOG_WARNING((
528 sci_base_object_get_logger(this_rnc->device),
529 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
530 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
531 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
532 "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n",
533 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
534 ));
535
536 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
537 }
538
539 // ---------------------------------------------------------------------------
540
541 static
542 SCI_STATUS scic_sds_remote_node_context_initial_state_resume_handler(
543 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
544 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
545 void * callback_parameter
546 )
547 {
548 if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
549 {
550 scic_sds_remote_node_context_setup_to_resume(
551 this_rnc, the_callback, callback_parameter
552 );
553
554 scic_sds_remote_node_context_construct_buffer(this_rnc);
555
556 #if defined (SCI_LOGGING)
557 // If a remote node context has a logger already, don't work on its state
558 // logging.
559 if (this_rnc->state_machine.previous_state_id
560 != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE)
561 scic_sds_remote_node_context_initialize_state_logging(this_rnc);
562 #endif
563
564 sci_base_state_machine_change_state(
565 &this_rnc->state_machine,
566 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
567 );
568
569 return SCI_SUCCESS;
570 }
571
572 return SCI_FAILURE_INVALID_STATE;
573 }
574
575 // ---------------------------------------------------------------------------
576
577 static
578 SCI_STATUS scic_sds_remote_node_context_posting_state_event_handler(
579 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
580 U32 event_code
581 )
582 {
583 SCI_STATUS status;
584
585 switch (scu_get_event_code(event_code))
586 {
587 case SCU_EVENT_POST_RNC_COMPLETE:
588 status = SCI_SUCCESS;
589
590 sci_base_state_machine_change_state(
591 &this_rnc->state_machine,
592 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
593 );
594 break;
595
596 default:
597 status = SCI_FAILURE;
598 SCIC_LOG_WARNING((
599 sci_base_object_get_logger(this_rnc->device),
600 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
601 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
602 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
603 "SCIC Remote Node Context 0x%x requested to process unexpected event 0x%x while in posting state\n",
604 this_rnc, event_code
605 ));
606 break;
607 }
608
609 return status;
610 }
611
612 // ---------------------------------------------------------------------------
613
614 static
615 SCI_STATUS scic_sds_remote_node_context_invalidating_state_destruct_handler(
616 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
617 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
618 void * callback_parameter
619 )
620 {
621 scic_sds_remote_node_context_setup_to_destory(
622 this_rnc, the_callback, callback_parameter
623 );
624
625 return SCI_SUCCESS;
626 }
627
628 static
629 SCI_STATUS scic_sds_remote_node_context_invalidating_state_event_handler(
630 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
631 U32 event_code
632 )
633 {
634 SCI_STATUS status;
635
636 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE)
637 {
638 status = SCI_SUCCESS;
639
640 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
641 {
642 sci_base_state_machine_change_state(
643 &this_rnc->state_machine,
644 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
645 );
646 }
647 else
648 {
649 sci_base_state_machine_change_state(
650 &this_rnc->state_machine,
651 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
652 );
653 }
654 }
655 else
656 {
657 switch (scu_get_event_type(event_code))
658 {
659 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
660 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
661 // We really dont care if the hardware is going to suspend
662 // the device since it's being invalidated anyway
663 SCIC_LOG_INFO((
664 sci_base_object_get_logger(this_rnc->device),
665 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
666 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
667 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
668 "SCIC Remote Node Context 0x%x was suspeneded by hardware while being invalidated.\n",
669 this_rnc
670 ));
671 status = SCI_SUCCESS;
672 break;
673
674 default:
675 SCIC_LOG_WARNING((
676 sci_base_object_get_logger(this_rnc->device),
677 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
678 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
679 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
680 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
681 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
682 ));
683 status = SCI_FAILURE;
684 break;
685 }
686 }
687
688 return status;
689 }
690
691 // ---------------------------------------------------------------------------
692
693 static
694 SCI_STATUS scic_sds_remote_node_context_resuming_state_event_handler(
695 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
696 U32 event_code
697 )
698 {
699 SCI_STATUS status;
700
701 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE)
702 {
703 status = SCI_SUCCESS;
704
705 sci_base_state_machine_change_state(
706 &this_rnc->state_machine,
707 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
708 );
709 }
710 else
711 {
712 switch (scu_get_event_type(event_code))
713 {
714 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
715 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
716 // We really dont care if the hardware is going to suspend
717 // the device since it's being resumed anyway
718 SCIC_LOG_INFO((
719 sci_base_object_get_logger(this_rnc->device),
720 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
721 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
722 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
723 "SCIC Remote Node Context 0x%x was suspeneded by hardware while being resumed.\n",
724 this_rnc
725 ));
726 status = SCI_SUCCESS;
727 break;
728
729 default:
730 SCIC_LOG_WARNING((
731 sci_base_object_get_logger(this_rnc->device),
732 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
733 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
734 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
735 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
736 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
737 ));
738 status = SCI_FAILURE;
739 break;
740 }
741 }
742
743 return status;
744 }
745
746 // ---------------------------------------------------------------------------
747
748 /**
749 * This method will handle the suspend requests from the ready state.
750 *
751 * @param[in] this_rnc The remote node context object being suspended.
752 * @param[in] the_callback The callback when the suspension is complete.
753 * @param[in] callback_parameter The parameter that is to be passed into the
754 * callback.
755 *
756 * @return SCI_SUCCESS
757 */
758 static
759 SCI_STATUS scic_sds_remote_node_context_ready_state_suspend_handler(
760 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
761 U32 suspend_type,
762 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
763 void * callback_parameter
764 )
765 {
766 this_rnc->user_callback = the_callback;
767 this_rnc->user_cookie = callback_parameter;
768 this_rnc->suspension_code = suspend_type;
769
770 if (suspend_type == SCI_SOFTWARE_SUSPENSION)
771 {
772 scic_sds_remote_device_post_request(
773 this_rnc->device,
774 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
775 );
776 }
777
778 sci_base_state_machine_change_state(
779 &this_rnc->state_machine,
780 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
781 );
782
783 return SCI_SUCCESS;
784 }
785
786 /**
787 * This method determines if the io request can be started by the SCU
788 * hardware. When the RNC is in the ready state any io request can be started.
789 *
790 * @param[in] this_rnc The rnc for which the io request is targeted.
791 * @param[in] the_request The request which is going to be started.
792 *
793 * @return SCI_STATUS
794 * @retval SCI_SUCCESS
795 */
796 static
797 SCI_STATUS scic_sds_remote_node_context_ready_state_start_io_handler(
798 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
799 struct SCIC_SDS_REQUEST * the_request
800 )
801 {
802 return SCI_SUCCESS;
803 }
804
805
806 static
807 SCI_STATUS scic_sds_remote_node_context_ready_state_event_handler(
808 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
809 U32 event_code
810 )
811 {
812 SCI_STATUS status;
813
814 switch (scu_get_event_type(event_code))
815 {
816 case SCU_EVENT_TL_RNC_SUSPEND_TX:
817 sci_base_state_machine_change_state(
818 &this_rnc->state_machine,
819 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
820 );
821
822 this_rnc->suspension_code = scu_get_event_specifier(event_code);
823 status = SCI_SUCCESS;
824 break;
825
826 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
827 sci_base_state_machine_change_state(
828 &this_rnc->state_machine,
829 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
830 );
831
832 this_rnc->suspension_code = scu_get_event_specifier(event_code);
833 status = SCI_SUCCESS;
834 break;
835
836 default:
837 SCIC_LOG_WARNING((
838 sci_base_object_get_logger(this_rnc->device),
839 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
840 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
841 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
842 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
843 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
844 ));
845
846 status = SCI_FAILURE;
847 break;
848 }
849
850 return status;
851 }
852
853 // ---------------------------------------------------------------------------
854
855 static
856 SCI_STATUS scic_sds_remote_node_context_tx_suspended_state_resume_handler(
857 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
858 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
859 void * callback_parameter
860 )
861 {
862 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
863
864 scic_sds_remote_node_context_setup_to_resume(
865 this_rnc, the_callback, callback_parameter
866 );
867
868 // If this is an expander attached SATA device we must invalidate
869 // and repost the RNC since this is the only way to clear the
870 // TCi to NCQ tag mapping table for the RNi
871 // All other device types we can just resume.
872 scic_remote_device_get_protocols(this_rnc->device, &protocols);
873
874 if (
875 (protocols.u.bits.attached_stp_target == 1)
876 && !(this_rnc->device->is_direct_attached)
877 )
878 {
879 sci_base_state_machine_change_state(
880 &this_rnc->state_machine,
881 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
882 );
883 }
884 else
885 {
886 sci_base_state_machine_change_state(
887 &this_rnc->state_machine,
888 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
889 );
890 }
891
892 return SCI_SUCCESS;
893 }
894
895 /**
896 * This method will report a success or failure attempt to start a new task
897 * request to the hardware. Since all task requests are sent on the high
898 * priority queue they can be sent when the RCN is in a TX suspend state.
899 *
900 * @param[in] this_rnc The remote node context which is to receive the task
901 * request.
902 * @param[in] the_request The task request to be transmitted to the remote
903 * target device.
904 *
905 * @return SCI_STATUS
906 * @retval SCI_SUCCESS
907 */
908 static
909 SCI_STATUS scic_sds_remote_node_context_suspended_start_task_handler(
910 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
911 struct SCIC_SDS_REQUEST * the_request
912 )
913 {
914 scic_sds_remote_node_context_resume(this_rnc, NULL, NULL);
915
916 return SCI_SUCCESS;
917 }
918
919 // ---------------------------------------------------------------------------
920
921 static
922 SCI_STATUS scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
923 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
924 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
925 void * callback_parameter
926 )
927 {
928 scic_sds_remote_node_context_setup_to_resume(
929 this_rnc, the_callback, callback_parameter
930 );
931
932 sci_base_state_machine_change_state(
933 &this_rnc->state_machine,
934 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
935 );
936
937 return SCI_FAILURE_INVALID_STATE;
938 }
939
940 // ---------------------------------------------------------------------------
941
942 /**
943 *
944 */
945 static
946 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_resume_handler(
947 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
948 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
949 void * callback_parameter
950 )
951 {
952 scic_sds_remote_node_context_setup_to_resume(
953 this_rnc, the_callback, callback_parameter
954 );
955
956 return SCI_SUCCESS;
957 }
958
959 /**
960 * This method will report a success or failure attempt to start a new task
961 * request to the hardware. Since all task requests are sent on the high
962 * priority queue they can be sent when the RCN is in a TX suspend state.
963 *
964 * @param[in] this_rnc The remote node context which is to receive the task
965 * request.
966 * @param[in] the_request The task request to be transmitted to the remote
967 * target device.
968 *
969 * @return SCI_STATUS
970 * @retval SCI_SUCCESS
971 */
972 static
973 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_start_task_handler(
974 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
975 struct SCIC_SDS_REQUEST * the_request
976 )
977 {
978 return SCI_SUCCESS;
979 }
980
981 static
982 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_event_handler(
983 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
984 U32 event_code
985 )
986 {
987 SCI_STATUS status;
988
989 switch (scu_get_event_type(event_code))
990 {
991 case SCU_EVENT_TL_RNC_SUSPEND_TX:
992 sci_base_state_machine_change_state(
993 &this_rnc->state_machine,
994 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
995 );
996
997 this_rnc->suspension_code = scu_get_event_specifier(event_code);
998 status = SCI_SUCCESS;
999 break;
1000
1001 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
1002 sci_base_state_machine_change_state(
1003 &this_rnc->state_machine,
1004 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1005 );
1006
1007 this_rnc->suspension_code = scu_get_event_specifier(event_code);
1008 status = SCI_SUCCESS;
1009 break;
1010
1011 default:
1012 SCIC_LOG_WARNING((
1013 sci_base_object_get_logger(this_rnc->device),
1014 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1015 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1016 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1017 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
1018 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
1019 ));
1020
1021 status = SCI_FAILURE;
1022 break;
1023 }
1024
1025 return status;
1026 }
1027
1028 // ---------------------------------------------------------------------------
1029
1030 SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS
1031 scic_sds_remote_node_context_state_handler_table[
1032 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
1033 {
1034 // SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1035 {
1036 scic_sds_remote_node_context_default_destruct_handler,
1037 scic_sds_remote_node_context_default_suspend_handler,
1038 scic_sds_remote_node_context_initial_state_resume_handler,
1039 scic_sds_remote_node_context_default_start_io_handler,
1040 scic_sds_remote_node_context_default_start_task_handler,
1041 scic_sds_remote_node_context_default_event_handler
1042 },
1043 // SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1044 {
1045 scic_sds_remote_node_context_general_destruct_handler,
1046 scic_sds_remote_node_context_default_suspend_handler,
1047 scic_sds_remote_node_context_continue_to_resume_handler,
1048 scic_sds_remote_node_context_default_start_io_handler,
1049 scic_sds_remote_node_context_default_start_task_handler,
1050 scic_sds_remote_node_context_posting_state_event_handler
1051 },
1052 // SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1053 {
1054 scic_sds_remote_node_context_invalidating_state_destruct_handler,
1055 scic_sds_remote_node_context_default_suspend_handler,
1056 scic_sds_remote_node_context_continue_to_resume_handler,
1057 scic_sds_remote_node_context_default_start_io_handler,
1058 scic_sds_remote_node_context_default_start_task_handler,
1059 scic_sds_remote_node_context_invalidating_state_event_handler
1060 },
1061 // SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1062 {
1063 scic_sds_remote_node_context_general_destruct_handler,
1064 scic_sds_remote_node_context_default_suspend_handler,
1065 scic_sds_remote_node_context_continue_to_resume_handler,
1066 scic_sds_remote_node_context_default_start_io_handler,
1067 scic_sds_remote_node_context_success_start_task_handler,
1068 scic_sds_remote_node_context_resuming_state_event_handler
1069 },
1070 // SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1071 {
1072 scic_sds_remote_node_context_general_destruct_handler,
1073 scic_sds_remote_node_context_ready_state_suspend_handler,
1074 scic_sds_remote_node_context_default_resume_handler,
1075 scic_sds_remote_node_context_ready_state_start_io_handler,
1076 scic_sds_remote_node_context_success_start_task_handler,
1077 scic_sds_remote_node_context_ready_state_event_handler
1078 },
1079 // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1080 {
1081 scic_sds_remote_node_context_general_destruct_handler,
1082 scic_sds_remote_node_context_default_suspend_handler,
1083 scic_sds_remote_node_context_tx_suspended_state_resume_handler,
1084 scic_sds_remote_node_context_reset_required_start_io_handler,
1085 scic_sds_remote_node_context_suspended_start_task_handler,
1086 scic_sds_remote_node_context_default_event_handler
1087 },
1088 // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1089 {
1090 scic_sds_remote_node_context_general_destruct_handler,
1091 scic_sds_remote_node_context_default_suspend_handler,
1092 scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler,
1093 scic_sds_remote_node_context_reset_required_start_io_handler,
1094 scic_sds_remote_node_context_suspended_start_task_handler,
1095 scic_sds_remote_node_context_default_event_handler
1096 },
1097 // SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1098 {
1099 scic_sds_remote_node_context_general_destruct_handler,
1100 scic_sds_remote_node_context_default_suspend_handler,
1101 scic_sds_remote_node_context_await_suspension_state_resume_handler,
1102 scic_sds_remote_node_context_reset_required_start_io_handler,
1103 scic_sds_remote_node_context_await_suspension_state_start_task_handler,
1104 scic_sds_remote_node_context_await_suspension_state_event_handler
1105 }
1106 };
1107
1108 //*****************************************************************************
1109 //* REMOTE NODE CONTEXT PRIVATE METHODS
1110 //*****************************************************************************
1111
1112 /**
1113 * This method just calls the user callback function and then resets the
1114 * callback.
1115 *
1116 * @param[in out] rnc
1117 */
1118 static
1119 void scic_sds_remote_node_context_notify_user(
1120 SCIC_SDS_REMOTE_NODE_CONTEXT_T *rnc
1121 )
1122 {
1123 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK local_user_callback = rnc->user_callback;
1124 void * local_user_cookie = rnc->user_cookie;
1125
1126 //we need to set the user_callback to NULL before it is called, because
1127 //the user callback's stack may eventually also set up a new set of
1128 //user callback. If we nullify the user_callback after it is called,
1129 //we are in the risk to lose the freshly set user callback.
1130 rnc->user_callback = NULL;
1131 rnc->user_cookie = NULL;
1132
1133 if (local_user_callback != NULL)
1134 {
1135 (*local_user_callback)(local_user_cookie);
1136 }
1137 }
1138
1139 /**
1140 * This method will continue the remote node context state machine by
1141 * requesting to resume the remote node context state machine from its current
1142 * state.
1143 *
1144 * @param[in] rnc
1145 */
1146 static
1147 void scic_sds_remote_node_context_continue_state_transitions(
1148 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc
1149 )
1150 {
1151 if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
1152 {
1153 rnc->state_handlers->resume_handler(
1154 rnc, rnc->user_callback, rnc->user_cookie
1155 );
1156 }
1157 }
1158
1159 /**
1160 * This method will mark the rnc buffer as being valid and post the request to
1161 * the hardware.
1162 *
1163 * @param[in] this_rnc The remote node context object that is to be
1164 * validated.
1165 *
1166 * @return none
1167 */
1168 static
1169 void scic_sds_remote_node_context_validate_context_buffer(
1170 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
1171 )
1172 {
1173 SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
1174
1175 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
1176 scic_sds_remote_device_get_controller(this_rnc->device),
1177 this_rnc->remote_node_index
1178 );
1179
1180 rnc_buffer->ssp.is_valid = TRUE;
1181
1182 if (
1183 !this_rnc->device->is_direct_attached
1184 && this_rnc->device->target_protocols.u.bits.attached_stp_target
1185 )
1186 {
1187 scic_sds_remote_device_post_request(
1188 this_rnc->device,
1189 SCU_CONTEXT_COMMAND_POST_RNC_96
1190 );
1191 }
1192 else
1193 {
1194 scic_sds_remote_device_post_request(
1195 this_rnc->device,
1196 SCU_CONTEXT_COMMAND_POST_RNC_32
1197 );
1198
1199 if (this_rnc->device->is_direct_attached)
1200 {
1201 scic_sds_port_setup_transports(
1202 this_rnc->device->owning_port,
1203 this_rnc->remote_node_index
1204 );
1205 }
1206 }
1207 }
1208
1209 /**
1210 * This method will update the RNC buffer and post the invalidate request.
1211 *
1212 * @param[in] this_rnc The remote node context object that is to be
1213 * invalidated.
1214 *
1215 * @return none
1216 */
1217 static
1218 void scic_sds_remote_node_context_invalidate_context_buffer(
1219 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
1220 )
1221 {
1222 SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
1223
1224 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
1225 scic_sds_remote_device_get_controller(this_rnc->device),
1226 this_rnc->remote_node_index
1227 );
1228
1229 rnc_buffer->ssp.is_valid = FALSE;
1230
1231 scic_sds_remote_device_post_request(
1232 this_rnc->device,
1233 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
1234 );
1235 }
1236
1237 //*****************************************************************************
1238 //* REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
1239 //*****************************************************************************
1240
1241 /**
1242 *
1243 *
1244 * @param[in] object
1245 */
1246 static
1247 void scic_sds_remote_node_context_initial_state_enter(
1248 SCI_BASE_OBJECT_T * object
1249 )
1250 {
1251 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1252 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1253
1254 SET_STATE_HANDLER(
1255 rnc,
1256 scic_sds_remote_node_context_state_handler_table,
1257 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1258 );
1259
1260 // Check to see if we have gotten back to the initial state because someone
1261 // requested to destroy the remote node context object.
1262 if (
1263 rnc->state_machine.previous_state_id
1264 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1265 )
1266 {
1267 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1268
1269 scic_sds_remote_node_context_notify_user(rnc);
1270
1271 // Since we are destroying the remote node context deinitialize the state logging
1272 // should we resume the remote node context the state logging will be reinitialized
1273 // on the resume handler.
1274 scic_sds_remote_node_context_deinitialize_state_logging(rnc);
1275 }
1276 }
1277
1278 /**
1279 *
1280 *
1281 * @param[in] object
1282 */
1283 static
1284 void scic_sds_remote_node_context_posting_state_enter(
1285 SCI_BASE_OBJECT_T * object
1286 )
1287 {
1288 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc;
1289 this_rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1290
1291 SET_STATE_HANDLER(
1292 this_rnc,
1293 scic_sds_remote_node_context_state_handler_table,
1294 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1295 );
1296
1297 scic_sds_remote_node_context_validate_context_buffer(this_rnc);
1298 }
1299
1300 /**
1301 *
1302 *
1303 * @param[in] object
1304 */
1305 static
1306 void scic_sds_remote_node_context_invalidating_state_enter(
1307 SCI_BASE_OBJECT_T * object
1308 )
1309 {
1310 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1311 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1312
1313 SET_STATE_HANDLER(
1314 rnc,
1315 scic_sds_remote_node_context_state_handler_table,
1316 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1317 );
1318
1319 scic_sds_remote_node_context_invalidate_context_buffer(rnc);
1320 }
1321
1322 /**
1323 *
1324 *
1325 * @param[in] object
1326 */
1327 static
1328 void scic_sds_remote_node_context_resuming_state_enter(
1329 SCI_BASE_OBJECT_T * object
1330 )
1331 {
1332 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1333 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
1334 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1335
1336 SET_STATE_HANDLER(
1337 rnc,
1338 scic_sds_remote_node_context_state_handler_table,
1339 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1340 );
1341
1342 // For direct attached SATA devices we need to clear the TLCR
1343 // NCQ to TCi tag mapping on the phy and in cases where we
1344 // resume because of a target reset we also need to update
1345 // the STPTLDARNI register with the RNi of the device
1346 scic_remote_device_get_protocols(rnc->device, &protocols);
1347
1348 if (
1349 (protocols.u.bits.attached_stp_target == 1)
1350 && (rnc->device->is_direct_attached)
1351 )
1352 {
1353 scic_sds_port_setup_transports(
1354 rnc->device->owning_port, rnc->remote_node_index
1355 );
1356 }
1357
1358 scic_sds_remote_device_post_request(
1359 rnc->device,
1360 SCU_CONTEXT_COMMAND_POST_RNC_RESUME
1361 );
1362 }
1363
1364 /**
1365 *
1366 *
1367 * @param[in] object
1368 */
1369 static
1370 void scic_sds_remote_node_context_ready_state_enter(
1371 SCI_BASE_OBJECT_T * object
1372 )
1373 {
1374 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1375 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1376
1377 SET_STATE_HANDLER(
1378 rnc,
1379 scic_sds_remote_node_context_state_handler_table,
1380 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1381 );
1382
1383 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1384
1385 if (rnc->user_callback != NULL)
1386 {
1387 scic_sds_remote_node_context_notify_user(rnc);
1388 }
1389 }
1390
1391 /**
1392 *
1393 *
1394 * @param[in] object
1395 */
1396 static
1397 void scic_sds_remote_node_context_tx_suspended_state_enter(
1398 SCI_BASE_OBJECT_T * object
1399 )
1400 {
1401 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1402 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1403
1404 SET_STATE_HANDLER(
1405 rnc,
1406 scic_sds_remote_node_context_state_handler_table,
1407 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1408 );
1409
1410 scic_sds_remote_node_context_continue_state_transitions(rnc);
1411 }
1412
1413 /**
1414 *
1415 *
1416 * @param[in] object
1417 */
1418 static
1419 void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
1420 SCI_BASE_OBJECT_T * object
1421 )
1422 {
1423 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1424 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1425
1426 SET_STATE_HANDLER(
1427 rnc,
1428 scic_sds_remote_node_context_state_handler_table,
1429 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1430 );
1431
1432 scic_sds_remote_node_context_continue_state_transitions(rnc);
1433 }
1434
1435 /**
1436 *
1437 *
1438 * @param[in] object
1439 */
1440 static
1441 void scic_sds_remote_node_context_await_suspension_state_enter(
1442 SCI_BASE_OBJECT_T * object
1443 )
1444 {
1445 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1446 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1447
1448 SET_STATE_HANDLER(
1449 rnc,
1450 scic_sds_remote_node_context_state_handler_table,
1451 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1452 );
1453 }
1454
1455 // ---------------------------------------------------------------------------
1456
1457 SCI_BASE_STATE_T
1458 scic_sds_remote_node_context_state_table[
1459 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
1460 {
1461 {
1462 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
1463 scic_sds_remote_node_context_initial_state_enter,
1464 NULL
1465 },
1466 {
1467 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
1468 scic_sds_remote_node_context_posting_state_enter,
1469 NULL
1470 },
1471 {
1472 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
1473 scic_sds_remote_node_context_invalidating_state_enter,
1474 NULL
1475 },
1476 {
1477 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
1478 scic_sds_remote_node_context_resuming_state_enter,
1479 NULL
1480 },
1481 {
1482 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
1483 scic_sds_remote_node_context_ready_state_enter,
1484 NULL
1485 },
1486 {
1487 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
1488 scic_sds_remote_node_context_tx_suspended_state_enter,
1489 NULL
1490 },
1491 {
1492 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
1493 scic_sds_remote_node_context_tx_rx_suspended_state_enter,
1494 NULL
1495 },
1496 {
1497 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
1498 scic_sds_remote_node_context_await_suspension_state_enter,
1499 NULL
1500 }
1501 };
1502
Cache object: 77b54381a81e958bac4c7c10f0cb7f15
|