2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 #include <sys/cdefs.h>
54 __FBSDID("$FreeBSD$");
59 * @brief This file contains the structures, constants, and prototypes
60 * associated with the remote node context in the silicon. It
61 * exists to model and manage the remote node context in the silicon.
64 #include <dev/isci/scil/sci_util.h>
65 #include <dev/isci/scil/scic_sds_logger.h>
66 #include <dev/isci/scil/scic_sds_controller.h>
67 #include <dev/isci/scil/scic_sds_remote_device.h>
68 #include <dev/isci/scil/scic_sds_remote_node_context.h>
69 #include <dev/isci/scil/sci_base_state_machine.h>
70 #include <dev/isci/scil/scic_remote_device.h>
71 #include <dev/isci/scil/scic_sds_port.h>
72 #include <dev/isci/scil/scu_event_codes.h>
73 #include <dev/isci/scil/scu_task_context.h>
78 void scic_sds_remote_node_context_construct(
79 SCIC_SDS_REMOTE_DEVICE_T * device,
80 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc,
84 memset (rnc, 0, sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T) );
86 rnc->remote_node_index = remote_node_index;
88 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
90 rnc->parent.logger = device->parent.parent.logger;
92 sci_base_state_machine_construct(
95 scic_sds_remote_node_context_state_table,
96 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
99 sci_base_state_machine_start(&rnc->state_machine);
101 // State logging initialization takes place late for the remote node context
102 // see the resume state handler for the initial state.
106 * This method will return TRUE if the RNC is not in the initial state. In
107 * all other states the RNC is considered active and this will return TRUE.
109 * @note The destroy request of the state machine drives the RNC back to the
110 * initial state. If the state machine changes then this routine will
111 * also have to be changed.
113 * @param[in] this_rnc The RNC for which the is posted request is being made.
116 * @retval TRUE if the state machine is not in the initial state
117 * @retval FALSE if the state machine is in the initial state
119 BOOL scic_sds_remote_node_context_is_initialized(
120 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
123 U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
125 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE)
134 * This method will return TRUE if the remote node context is in a READY state
135 * otherwise it will return FALSE
137 * @param[in] this_rnc The state of the remote node context object to check.
140 * @retval TRUE if the remote node context is in the ready state.
141 * @retval FALSE if the remote node context is not in the ready state.
143 BOOL scic_sds_remote_node_context_is_ready(
144 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
147 U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
149 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE)
158 * This method will construct the RNC buffer for this remote device object.
160 * @param[in] this_device The remote device to use to construct the RNC
162 * @param[in] rnc The buffer into which the remote device data will be copied.
166 void scic_sds_remote_node_context_construct_buffer(
167 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
170 SCU_REMOTE_NODE_CONTEXT_T * rnc;
171 SCIC_SDS_CONTROLLER_T * the_controller;
173 the_controller = scic_sds_remote_device_get_controller(this_rnc->device);
175 rnc = scic_sds_controller_get_remote_node_context_buffer(
176 the_controller, this_rnc->remote_node_index);
181 sizeof(SCU_REMOTE_NODE_CONTEXT_T)
182 * scic_sds_remote_device_node_count(this_rnc->device)
185 rnc->ssp.remote_node_index = this_rnc->remote_node_index;
186 rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width;
187 rnc->ssp.logical_port_index =
188 scic_sds_remote_device_get_port_index(this_rnc->device);
190 rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high);
191 rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low);
193 rnc->ssp.nexus_loss_timer_enable = TRUE;
194 rnc->ssp.check_bit = FALSE;
195 rnc->ssp.is_valid = FALSE;
196 rnc->ssp.is_remote_node_context = TRUE;
197 rnc->ssp.function_number = 0;
199 rnc->ssp.arbitration_wait_time = 0;
203 this_rnc->device->target_protocols.u.bits.attached_sata_device
204 || this_rnc->device->target_protocols.u.bits.attached_stp_target
207 rnc->ssp.connection_occupancy_timeout =
208 the_controller->user_parameters.sds1.stp_max_occupancy_timeout;
209 rnc->ssp.connection_inactivity_timeout =
210 the_controller->user_parameters.sds1.stp_inactivity_timeout;
214 rnc->ssp.connection_occupancy_timeout =
215 the_controller->user_parameters.sds1.ssp_max_occupancy_timeout;
216 rnc->ssp.connection_inactivity_timeout =
217 the_controller->user_parameters.sds1.ssp_inactivity_timeout;
220 rnc->ssp.initial_arbitration_wait_time = 0;
222 // Open Address Frame Parameters
223 rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate;
224 rnc->ssp.oaf_features = 0;
225 rnc->ssp.oaf_source_zone_group = 0;
226 rnc->ssp.oaf_more_compatibility_features = 0;
229 // ---------------------------------------------------------------------------
233 * This method will enable and turn on state transition logging for the remote
234 * node context object.
236 * @param[in] this_rnc The remote node context for which state transition
237 * logging is to be enabled.
241 void scic_sds_remote_node_context_initialize_state_logging(
242 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
245 sci_base_state_machine_logger_initialize(
246 &this_rnc->state_machine_logger,
247 &this_rnc->state_machine,
249 scic_cb_logger_log_states,
250 "SCIC_SDS_REMOTE_NODE_CONTEXT_T", "state machine",
251 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
252 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
253 SCIC_LOG_OBJECT_STP_REMOTE_TARGET
258 * This method will stop the state machine logging for this object and should
259 * be called before the object is destroyed.
261 * @param[in] this_rnc The remote node context on which to stop logging state
266 void scic_sds_remote_node_context_deinitialize_state_logging(
267 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
270 sci_base_state_machine_logger_deinitialize(
271 &this_rnc->state_machine_logger,
272 &this_rnc->state_machine
278 * This method will setup the remote node context object so it will transition
279 * to its ready state. If the remote node context is already setup to
280 * transition to its final state then this function does nothing.
282 * @param[in] this_rnc
283 * @param[in] the_callback
284 * @param[in] callback_parameter
289 void scic_sds_remote_node_context_setup_to_resume(
290 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
291 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
292 void * callback_parameter
295 if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
297 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY;
298 this_rnc->user_callback = the_callback;
299 this_rnc->user_cookie = callback_parameter;
304 * This method will setup the remote node context object so it will
305 * transition to its final state.
307 * @param[in] this_rnc
308 * @param[in] the_callback
309 * @param[in] callback_parameter
314 void scic_sds_remote_node_context_setup_to_destory(
315 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
316 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
317 void * callback_parameter
320 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL;
321 this_rnc->user_callback = the_callback;
322 this_rnc->user_cookie = callback_parameter;
326 * This method will continue to resume a remote node context. This is used
327 * in the states where a resume is requested while a resume is in progress.
329 * @param[in] this_rnc
330 * @param[in] the_callback
331 * @param[in] callback_parameter
334 SCI_STATUS scic_sds_remote_node_context_continue_to_resume_handler(
335 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
336 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
337 void * callback_parameter
340 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
342 this_rnc->user_callback = the_callback;
343 this_rnc->user_cookie = callback_parameter;
348 return SCI_FAILURE_INVALID_STATE;
351 //******************************************************************************
352 //* REMOTE NODE CONTEXT STATE MACHINE
353 //******************************************************************************
356 SCI_STATUS scic_sds_remote_node_context_default_destruct_handler(
357 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
358 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
359 void * callback_parameter
363 sci_base_object_get_logger(this_rnc->device),
364 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
365 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
366 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
367 "SCIC Remote Node Context 0x%x requested to stop while in unexpected state %d\n",
368 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
371 // We have decided that the destruct request on the remote node context can not fail
372 // since it is either in the initial/destroyed state or is can be destroyed.
377 SCI_STATUS scic_sds_remote_node_context_default_suspend_handler(
378 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
380 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
381 void * callback_parameter
385 sci_base_object_get_logger(this_rnc->device),
386 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
387 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
388 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
389 "SCIC Remote Node Context 0x%x requested to suspend while in wrong state %d\n",
390 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
393 return SCI_FAILURE_INVALID_STATE;
397 SCI_STATUS scic_sds_remote_node_context_default_resume_handler(
398 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
399 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
400 void * callback_parameter
404 sci_base_object_get_logger(this_rnc->device),
405 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
406 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
407 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
408 "SCIC Remote Node Context 0x%x requested to resume while in wrong state %d\n",
409 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
412 return SCI_FAILURE_INVALID_STATE;
416 SCI_STATUS scic_sds_remote_node_context_default_start_io_handler(
417 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
418 struct SCIC_SDS_REQUEST * the_request
422 sci_base_object_get_logger(this_rnc->device),
423 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
424 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
425 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
426 "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n",
427 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
430 return SCI_FAILURE_INVALID_STATE;
434 SCI_STATUS scic_sds_remote_node_context_default_start_task_handler(
435 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
436 struct SCIC_SDS_REQUEST * the_request
440 sci_base_object_get_logger(this_rnc->device),
441 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
442 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
443 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
444 "SCIC Remote Node Context 0x%x requested to start task 0x%x while in wrong state %d\n",
445 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
452 SCI_STATUS scic_sds_remote_node_context_default_event_handler(
453 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
458 sci_base_object_get_logger(this_rnc->device),
459 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
460 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
461 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
462 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in wrong state %d\n",
463 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
466 return SCI_FAILURE_INVALID_STATE;
470 * This method determines if the task request can be started by the SCU
471 * hardware. When the RNC is in the ready state any task can be started.
473 * @param[in] this_rnc The rnc for which the task request is targeted.
474 * @param[in] the_request The request which is going to be started.
477 * @retval SCI_SUCCESS
480 SCI_STATUS scic_sds_remote_node_context_success_start_task_handler(
481 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
482 struct SCIC_SDS_REQUEST * the_request
489 * This method handles destruct calls from the various state handlers. The
490 * remote node context can be requested to destroy from any state. If there
491 * was a user callback it is always replaced with the request to destroy user
494 * @param[in] this_rnc
495 * @param[in] the_callback
496 * @param[in] callback_parameter
501 SCI_STATUS scic_sds_remote_node_context_general_destruct_handler(
502 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
503 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
504 void * callback_parameter
507 scic_sds_remote_node_context_setup_to_destory(
508 this_rnc, the_callback, callback_parameter
511 sci_base_state_machine_change_state(
512 &this_rnc->state_machine,
513 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
518 // ---------------------------------------------------------------------------
520 SCI_STATUS scic_sds_remote_node_context_reset_required_start_io_handler(
521 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
522 struct SCIC_SDS_REQUEST * the_request
526 sci_base_object_get_logger(this_rnc->device),
527 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
528 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
529 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
530 "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n",
531 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
534 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
537 // ---------------------------------------------------------------------------
540 SCI_STATUS scic_sds_remote_node_context_initial_state_resume_handler(
541 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
542 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
543 void * callback_parameter
546 if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
548 scic_sds_remote_node_context_setup_to_resume(
549 this_rnc, the_callback, callback_parameter
552 scic_sds_remote_node_context_construct_buffer(this_rnc);
554 #if defined (SCI_LOGGING)
555 // If a remote node context has a logger already, don't work on its state
557 if (this_rnc->state_machine.previous_state_id
558 != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE)
559 scic_sds_remote_node_context_initialize_state_logging(this_rnc);
562 sci_base_state_machine_change_state(
563 &this_rnc->state_machine,
564 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
570 return SCI_FAILURE_INVALID_STATE;
573 // ---------------------------------------------------------------------------
576 SCI_STATUS scic_sds_remote_node_context_posting_state_event_handler(
577 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
583 switch (scu_get_event_code(event_code))
585 case SCU_EVENT_POST_RNC_COMPLETE:
586 status = SCI_SUCCESS;
588 sci_base_state_machine_change_state(
589 &this_rnc->state_machine,
590 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
595 status = SCI_FAILURE;
597 sci_base_object_get_logger(this_rnc->device),
598 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
599 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
600 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
601 "SCIC Remote Node Context 0x%x requested to process unexpected event 0x%x while in posting state\n",
610 // ---------------------------------------------------------------------------
613 SCI_STATUS scic_sds_remote_node_context_invalidating_state_destruct_handler(
614 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
615 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
616 void * callback_parameter
619 scic_sds_remote_node_context_setup_to_destory(
620 this_rnc, the_callback, callback_parameter
627 SCI_STATUS scic_sds_remote_node_context_invalidating_state_event_handler(
628 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
634 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE)
636 status = SCI_SUCCESS;
638 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
640 sci_base_state_machine_change_state(
641 &this_rnc->state_machine,
642 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
647 sci_base_state_machine_change_state(
648 &this_rnc->state_machine,
649 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
655 switch (scu_get_event_type(event_code))
657 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
658 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
659 // We really dont care if the hardware is going to suspend
660 // the device since it's being invalidated anyway
662 sci_base_object_get_logger(this_rnc->device),
663 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
664 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
665 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
666 "SCIC Remote Node Context 0x%x was suspeneded by hardware while being invalidated.\n",
669 status = SCI_SUCCESS;
674 sci_base_object_get_logger(this_rnc->device),
675 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
676 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
677 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
678 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
679 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
681 status = SCI_FAILURE;
689 // ---------------------------------------------------------------------------
692 SCI_STATUS scic_sds_remote_node_context_resuming_state_event_handler(
693 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
699 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE)
701 status = SCI_SUCCESS;
703 sci_base_state_machine_change_state(
704 &this_rnc->state_machine,
705 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
710 switch (scu_get_event_type(event_code))
712 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
713 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
714 // We really dont care if the hardware is going to suspend
715 // the device since it's being resumed anyway
717 sci_base_object_get_logger(this_rnc->device),
718 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
719 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
720 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
721 "SCIC Remote Node Context 0x%x was suspeneded by hardware while being resumed.\n",
724 status = SCI_SUCCESS;
729 sci_base_object_get_logger(this_rnc->device),
730 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
731 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
732 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
733 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
734 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
736 status = SCI_FAILURE;
744 // ---------------------------------------------------------------------------
747 * This method will handle the suspend requests from the ready state.
749 * @param[in] this_rnc The remote node context object being suspended.
750 * @param[in] the_callback The callback when the suspension is complete.
751 * @param[in] callback_parameter The parameter that is to be passed into the
754 * @return SCI_SUCCESS
757 SCI_STATUS scic_sds_remote_node_context_ready_state_suspend_handler(
758 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
760 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
761 void * callback_parameter
764 this_rnc->user_callback = the_callback;
765 this_rnc->user_cookie = callback_parameter;
766 this_rnc->suspension_code = suspend_type;
768 if (suspend_type == SCI_SOFTWARE_SUSPENSION)
770 scic_sds_remote_device_post_request(
772 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
776 sci_base_state_machine_change_state(
777 &this_rnc->state_machine,
778 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
785 * This method determines if the io request can be started by the SCU
786 * hardware. When the RNC is in the ready state any io request can be started.
788 * @param[in] this_rnc The rnc for which the io request is targeted.
789 * @param[in] the_request The request which is going to be started.
792 * @retval SCI_SUCCESS
795 SCI_STATUS scic_sds_remote_node_context_ready_state_start_io_handler(
796 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
797 struct SCIC_SDS_REQUEST * the_request
805 SCI_STATUS scic_sds_remote_node_context_ready_state_event_handler(
806 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
812 switch (scu_get_event_type(event_code))
814 case SCU_EVENT_TL_RNC_SUSPEND_TX:
815 sci_base_state_machine_change_state(
816 &this_rnc->state_machine,
817 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
820 this_rnc->suspension_code = scu_get_event_specifier(event_code);
821 status = SCI_SUCCESS;
824 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
825 sci_base_state_machine_change_state(
826 &this_rnc->state_machine,
827 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
830 this_rnc->suspension_code = scu_get_event_specifier(event_code);
831 status = SCI_SUCCESS;
836 sci_base_object_get_logger(this_rnc->device),
837 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
838 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
839 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
840 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
841 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
844 status = SCI_FAILURE;
851 // ---------------------------------------------------------------------------
854 SCI_STATUS scic_sds_remote_node_context_tx_suspended_state_resume_handler(
855 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
856 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
857 void * callback_parameter
860 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
862 scic_sds_remote_node_context_setup_to_resume(
863 this_rnc, the_callback, callback_parameter
866 // If this is an expander attached SATA device we must invalidate
867 // and repost the RNC since this is the only way to clear the
868 // TCi to NCQ tag mapping table for the RNi
869 // All other device types we can just resume.
870 scic_remote_device_get_protocols(this_rnc->device, &protocols);
873 (protocols.u.bits.attached_stp_target == 1)
874 && !(this_rnc->device->is_direct_attached)
877 sci_base_state_machine_change_state(
878 &this_rnc->state_machine,
879 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
884 sci_base_state_machine_change_state(
885 &this_rnc->state_machine,
886 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
894 * This method will report a success or failure attempt to start a new task
895 * request to the hardware. Since all task requests are sent on the high
896 * priority queue they can be sent when the RCN is in a TX suspend state.
898 * @param[in] this_rnc The remote node context which is to receive the task
900 * @param[in] the_request The task request to be transmitted to to the remote
904 * @retval SCI_SUCCESS
907 SCI_STATUS scic_sds_remote_node_context_suspended_start_task_handler(
908 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
909 struct SCIC_SDS_REQUEST * the_request
912 scic_sds_remote_node_context_resume(this_rnc, NULL, NULL);
917 // ---------------------------------------------------------------------------
920 SCI_STATUS scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
921 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
922 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
923 void * callback_parameter
926 scic_sds_remote_node_context_setup_to_resume(
927 this_rnc, the_callback, callback_parameter
930 sci_base_state_machine_change_state(
931 &this_rnc->state_machine,
932 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
935 return SCI_FAILURE_INVALID_STATE;
938 // ---------------------------------------------------------------------------
944 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_resume_handler(
945 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
946 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
947 void * callback_parameter
950 scic_sds_remote_node_context_setup_to_resume(
951 this_rnc, the_callback, callback_parameter
958 * This method will report a success or failure attempt to start a new task
959 * request to the hardware. Since all task requests are sent on the high
960 * priority queue they can be sent when the RCN is in a TX suspend state.
962 * @param[in] this_rnc The remote node context which is to receive the task
964 * @param[in] the_request The task request to be transmitted to to the remote
968 * @retval SCI_SUCCESS
971 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_start_task_handler(
972 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
973 struct SCIC_SDS_REQUEST * the_request
980 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_event_handler(
981 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
987 switch (scu_get_event_type(event_code))
989 case SCU_EVENT_TL_RNC_SUSPEND_TX:
990 sci_base_state_machine_change_state(
991 &this_rnc->state_machine,
992 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
995 this_rnc->suspension_code = scu_get_event_specifier(event_code);
996 status = SCI_SUCCESS;
999 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
1000 sci_base_state_machine_change_state(
1001 &this_rnc->state_machine,
1002 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1005 this_rnc->suspension_code = scu_get_event_specifier(event_code);
1006 status = SCI_SUCCESS;
1011 sci_base_object_get_logger(this_rnc->device),
1012 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1013 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1014 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1015 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
1016 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
1019 status = SCI_FAILURE;
1026 // ---------------------------------------------------------------------------
1028 SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS
1029 scic_sds_remote_node_context_state_handler_table[
1030 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
1032 // SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1034 scic_sds_remote_node_context_default_destruct_handler,
1035 scic_sds_remote_node_context_default_suspend_handler,
1036 scic_sds_remote_node_context_initial_state_resume_handler,
1037 scic_sds_remote_node_context_default_start_io_handler,
1038 scic_sds_remote_node_context_default_start_task_handler,
1039 scic_sds_remote_node_context_default_event_handler
1041 // SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1043 scic_sds_remote_node_context_general_destruct_handler,
1044 scic_sds_remote_node_context_default_suspend_handler,
1045 scic_sds_remote_node_context_continue_to_resume_handler,
1046 scic_sds_remote_node_context_default_start_io_handler,
1047 scic_sds_remote_node_context_default_start_task_handler,
1048 scic_sds_remote_node_context_posting_state_event_handler
1050 // SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1052 scic_sds_remote_node_context_invalidating_state_destruct_handler,
1053 scic_sds_remote_node_context_default_suspend_handler,
1054 scic_sds_remote_node_context_continue_to_resume_handler,
1055 scic_sds_remote_node_context_default_start_io_handler,
1056 scic_sds_remote_node_context_default_start_task_handler,
1057 scic_sds_remote_node_context_invalidating_state_event_handler
1059 // SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1061 scic_sds_remote_node_context_general_destruct_handler,
1062 scic_sds_remote_node_context_default_suspend_handler,
1063 scic_sds_remote_node_context_continue_to_resume_handler,
1064 scic_sds_remote_node_context_default_start_io_handler,
1065 scic_sds_remote_node_context_success_start_task_handler,
1066 scic_sds_remote_node_context_resuming_state_event_handler
1068 // SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1070 scic_sds_remote_node_context_general_destruct_handler,
1071 scic_sds_remote_node_context_ready_state_suspend_handler,
1072 scic_sds_remote_node_context_default_resume_handler,
1073 scic_sds_remote_node_context_ready_state_start_io_handler,
1074 scic_sds_remote_node_context_success_start_task_handler,
1075 scic_sds_remote_node_context_ready_state_event_handler
1077 // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1079 scic_sds_remote_node_context_general_destruct_handler,
1080 scic_sds_remote_node_context_default_suspend_handler,
1081 scic_sds_remote_node_context_tx_suspended_state_resume_handler,
1082 scic_sds_remote_node_context_reset_required_start_io_handler,
1083 scic_sds_remote_node_context_suspended_start_task_handler,
1084 scic_sds_remote_node_context_default_event_handler
1086 // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1088 scic_sds_remote_node_context_general_destruct_handler,
1089 scic_sds_remote_node_context_default_suspend_handler,
1090 scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler,
1091 scic_sds_remote_node_context_reset_required_start_io_handler,
1092 scic_sds_remote_node_context_suspended_start_task_handler,
1093 scic_sds_remote_node_context_default_event_handler
1095 // SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1097 scic_sds_remote_node_context_general_destruct_handler,
1098 scic_sds_remote_node_context_default_suspend_handler,
1099 scic_sds_remote_node_context_await_suspension_state_resume_handler,
1100 scic_sds_remote_node_context_reset_required_start_io_handler,
1101 scic_sds_remote_node_context_await_suspension_state_start_task_handler,
1102 scic_sds_remote_node_context_await_suspension_state_event_handler
1106 //*****************************************************************************
1107 //* REMOTE NODE CONTEXT PRIVATE METHODS
1108 //*****************************************************************************
1111 * This method just calls the user callback function and then resets the
1114 * @param[in out] rnc
1117 void scic_sds_remote_node_context_notify_user(
1118 SCIC_SDS_REMOTE_NODE_CONTEXT_T *rnc
1121 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK local_user_callback = rnc->user_callback;
1122 void * local_user_cookie = rnc->user_cookie;
1124 //we need to set the user_callback to NULL before it is called, because
1125 //the user callback's stack may eventually also set up a new set of
1126 //user callback. If we nullify the user_callback after it is called,
1127 //we are in the risk to lose the freshly set user callback.
1128 rnc->user_callback = NULL;
1129 rnc->user_cookie = NULL;
1131 if (local_user_callback != NULL)
1133 (*local_user_callback)(local_user_cookie);
1138 * This method will continue the remote node context state machine by
1139 * requesting to resume the remote node context state machine from its current
1145 void scic_sds_remote_node_context_continue_state_transitions(
1146 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc
1149 if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
1151 rnc->state_handlers->resume_handler(
1152 rnc, rnc->user_callback, rnc->user_cookie
1158 * This method will mark the rnc buffer as being valid and post the request to
1161 * @param[in] this_rnc The remote node context object that is to be
1167 void scic_sds_remote_node_context_validate_context_buffer(
1168 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
1171 SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
1173 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
1174 scic_sds_remote_device_get_controller(this_rnc->device),
1175 this_rnc->remote_node_index
1178 rnc_buffer->ssp.is_valid = TRUE;
1181 !this_rnc->device->is_direct_attached
1182 && this_rnc->device->target_protocols.u.bits.attached_stp_target
1185 scic_sds_remote_device_post_request(
1187 SCU_CONTEXT_COMMAND_POST_RNC_96
1192 scic_sds_remote_device_post_request(
1194 SCU_CONTEXT_COMMAND_POST_RNC_32
1197 if (this_rnc->device->is_direct_attached)
1199 scic_sds_port_setup_transports(
1200 this_rnc->device->owning_port,
1201 this_rnc->remote_node_index
1208 * This method will update the RNC buffer and post the invalidate request.
1210 * @param[in] this_rnc The remote node context object that is to be
1216 void scic_sds_remote_node_context_invalidate_context_buffer(
1217 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
1220 SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
1222 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
1223 scic_sds_remote_device_get_controller(this_rnc->device),
1224 this_rnc->remote_node_index
1227 rnc_buffer->ssp.is_valid = FALSE;
1229 scic_sds_remote_device_post_request(
1231 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
1235 //*****************************************************************************
1236 //* REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
1237 //*****************************************************************************
1245 void scic_sds_remote_node_context_initial_state_enter(
1246 SCI_BASE_OBJECT_T * object
1249 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1250 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1254 scic_sds_remote_node_context_state_handler_table,
1255 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1258 // Check to see if we have gotten back to the initial state because someone
1259 // requested to destroy the remote node context object.
1261 rnc->state_machine.previous_state_id
1262 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1265 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1267 scic_sds_remote_node_context_notify_user(rnc);
1269 // Since we are destroying the remote node context deinitialize the state logging
1270 // should we resume the remote node context the state logging will be reinitialized
1271 // on the resume handler.
1272 scic_sds_remote_node_context_deinitialize_state_logging(rnc);
1282 void scic_sds_remote_node_context_posting_state_enter(
1283 SCI_BASE_OBJECT_T * object
1286 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc;
1287 this_rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1291 scic_sds_remote_node_context_state_handler_table,
1292 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1295 scic_sds_remote_node_context_validate_context_buffer(this_rnc);
1304 void scic_sds_remote_node_context_invalidating_state_enter(
1305 SCI_BASE_OBJECT_T * object
1308 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1309 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1313 scic_sds_remote_node_context_state_handler_table,
1314 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1317 scic_sds_remote_node_context_invalidate_context_buffer(rnc);
1326 void scic_sds_remote_node_context_resuming_state_enter(
1327 SCI_BASE_OBJECT_T * object
1330 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1331 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
1332 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1336 scic_sds_remote_node_context_state_handler_table,
1337 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1340 // For direct attached SATA devices we need to clear the TLCR
1341 // NCQ to TCi tag mapping on the phy and in cases where we
1342 // resume because of a target reset we also need to update
1343 // the STPTLDARNI register with the RNi of the device
1344 scic_remote_device_get_protocols(rnc->device, &protocols);
1347 (protocols.u.bits.attached_stp_target == 1)
1348 && (rnc->device->is_direct_attached)
1351 scic_sds_port_setup_transports(
1352 rnc->device->owning_port, rnc->remote_node_index
1356 scic_sds_remote_device_post_request(
1358 SCU_CONTEXT_COMMAND_POST_RNC_RESUME
1368 void scic_sds_remote_node_context_ready_state_enter(
1369 SCI_BASE_OBJECT_T * object
1372 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1373 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1377 scic_sds_remote_node_context_state_handler_table,
1378 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1381 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1383 if (rnc->user_callback != NULL)
1385 scic_sds_remote_node_context_notify_user(rnc);
1395 void scic_sds_remote_node_context_tx_suspended_state_enter(
1396 SCI_BASE_OBJECT_T * object
1399 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1400 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1404 scic_sds_remote_node_context_state_handler_table,
1405 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1408 scic_sds_remote_node_context_continue_state_transitions(rnc);
1417 void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
1418 SCI_BASE_OBJECT_T * object
1421 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1422 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1426 scic_sds_remote_node_context_state_handler_table,
1427 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1430 scic_sds_remote_node_context_continue_state_transitions(rnc);
1439 void scic_sds_remote_node_context_await_suspension_state_enter(
1440 SCI_BASE_OBJECT_T * object
1443 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1444 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1448 scic_sds_remote_node_context_state_handler_table,
1449 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1453 // ---------------------------------------------------------------------------
1456 scic_sds_remote_node_context_state_table[
1457 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
1460 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
1461 scic_sds_remote_node_context_initial_state_enter,
1465 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
1466 scic_sds_remote_node_context_posting_state_enter,
1470 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
1471 scic_sds_remote_node_context_invalidating_state_enter,
1475 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
1476 scic_sds_remote_node_context_resuming_state_enter,
1480 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
1481 scic_sds_remote_node_context_ready_state_enter,
1485 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
1486 scic_sds_remote_node_context_tx_suspended_state_enter,
1490 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
1491 scic_sds_remote_node_context_tx_rx_suspended_state_enter,
1495 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
1496 scic_sds_remote_node_context_await_suspension_state_enter,