2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
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.
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
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.
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.
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.
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
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
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.
55 #include <sys/cdefs.h>
56 __FBSDID("$FreeBSD$");
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.
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>
80 void scic_sds_remote_node_context_construct(
81 SCIC_SDS_REMOTE_DEVICE_T * device,
82 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc,
86 memset (rnc, 0, sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T) );
88 rnc->remote_node_index = remote_node_index;
90 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
92 rnc->parent.logger = device->parent.parent.logger;
94 sci_base_state_machine_construct(
97 scic_sds_remote_node_context_state_table,
98 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
101 sci_base_state_machine_start(&rnc->state_machine);
103 // State logging initialization takes place late for the remote node context
104 // see the resume state handler for the initial state.
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.
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.
115 * @param[in] this_rnc The RNC for which the is posted request is being made.
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
121 BOOL scic_sds_remote_node_context_is_initialized(
122 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
125 U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
127 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE)
136 * This method will return TRUE if the remote node context is in a READY state
137 * otherwise it will return FALSE
139 * @param[in] this_rnc The state of the remote node context object to check.
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.
145 BOOL scic_sds_remote_node_context_is_ready(
146 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
149 U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
151 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE)
160 * This method will construct the RNC buffer for this remote device object.
162 * @param[in] this_device The remote device to use to construct the RNC
164 * @param[in] rnc The buffer into which the remote device data will be copied.
168 void scic_sds_remote_node_context_construct_buffer(
169 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
172 SCU_REMOTE_NODE_CONTEXT_T * rnc;
173 SCIC_SDS_CONTROLLER_T * the_controller;
175 the_controller = scic_sds_remote_device_get_controller(this_rnc->device);
177 rnc = scic_sds_controller_get_remote_node_context_buffer(
178 the_controller, this_rnc->remote_node_index);
183 sizeof(SCU_REMOTE_NODE_CONTEXT_T)
184 * scic_sds_remote_device_node_count(this_rnc->device)
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);
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);
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;
201 rnc->ssp.arbitration_wait_time = 0;
205 this_rnc->device->target_protocols.u.bits.attached_sata_device
206 || this_rnc->device->target_protocols.u.bits.attached_stp_target
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;
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;
222 rnc->ssp.initial_arbitration_wait_time = 0;
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;
231 // ---------------------------------------------------------------------------
235 * This method will enable and turn on state transition logging for the remote
236 * node context object.
238 * @param[in] this_rnc The remote node context for which state transition
239 * logging is to be enabled.
243 void scic_sds_remote_node_context_initialize_state_logging(
244 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
247 sci_base_state_machine_logger_initialize(
248 &this_rnc->state_machine_logger,
249 &this_rnc->state_machine,
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
260 * This method will stop the state machine logging for this object and should
261 * be called before the object is destroyed.
263 * @param[in] this_rnc The remote node context on which to stop logging state
268 void scic_sds_remote_node_context_deinitialize_state_logging(
269 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
272 sci_base_state_machine_logger_deinitialize(
273 &this_rnc->state_machine_logger,
274 &this_rnc->state_machine
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.
284 * @param[in] this_rnc
285 * @param[in] the_callback
286 * @param[in] callback_parameter
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
297 if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
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;
306 * This method will setup the remote node context object so it will
307 * transition to its final state.
309 * @param[in] this_rnc
310 * @param[in] the_callback
311 * @param[in] callback_parameter
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
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;
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.
331 * @param[in] this_rnc
332 * @param[in] the_callback
333 * @param[in] callback_parameter
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
342 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
344 this_rnc->user_callback = the_callback;
345 this_rnc->user_cookie = callback_parameter;
350 return SCI_FAILURE_INVALID_STATE;
353 //******************************************************************************
354 //* REMOTE NODE CONTEXT STATE MACHINE
355 //******************************************************************************
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
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)
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.
379 SCI_STATUS scic_sds_remote_node_context_default_suspend_handler(
380 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
382 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
383 void * callback_parameter
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)
395 return SCI_FAILURE_INVALID_STATE;
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
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)
414 return SCI_FAILURE_INVALID_STATE;
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
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)
432 return SCI_FAILURE_INVALID_STATE;
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
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)
454 SCI_STATUS scic_sds_remote_node_context_default_event_handler(
455 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
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)
468 return SCI_FAILURE_INVALID_STATE;
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.
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.
479 * @retval SCI_SUCCESS
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
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
496 * @param[in] this_rnc
497 * @param[in] the_callback
498 * @param[in] callback_parameter
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
509 scic_sds_remote_node_context_setup_to_destory(
510 this_rnc, the_callback, callback_parameter
513 sci_base_state_machine_change_state(
514 &this_rnc->state_machine,
515 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
520 // ---------------------------------------------------------------------------
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
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)
536 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
539 // ---------------------------------------------------------------------------
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
548 if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
550 scic_sds_remote_node_context_setup_to_resume(
551 this_rnc, the_callback, callback_parameter
554 scic_sds_remote_node_context_construct_buffer(this_rnc);
556 #if defined (SCI_LOGGING)
557 // If a remote node context has a logger already, don't work on its state
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);
564 sci_base_state_machine_change_state(
565 &this_rnc->state_machine,
566 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
572 return SCI_FAILURE_INVALID_STATE;
575 // ---------------------------------------------------------------------------
578 SCI_STATUS scic_sds_remote_node_context_posting_state_event_handler(
579 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
585 switch (scu_get_event_code(event_code))
587 case SCU_EVENT_POST_RNC_COMPLETE:
588 status = SCI_SUCCESS;
590 sci_base_state_machine_change_state(
591 &this_rnc->state_machine,
592 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
597 status = SCI_FAILURE;
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",
612 // ---------------------------------------------------------------------------
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
621 scic_sds_remote_node_context_setup_to_destory(
622 this_rnc, the_callback, callback_parameter
629 SCI_STATUS scic_sds_remote_node_context_invalidating_state_event_handler(
630 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
636 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE)
638 status = SCI_SUCCESS;
640 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
642 sci_base_state_machine_change_state(
643 &this_rnc->state_machine,
644 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
649 sci_base_state_machine_change_state(
650 &this_rnc->state_machine,
651 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
657 switch (scu_get_event_type(event_code))
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
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",
671 status = SCI_SUCCESS;
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)
683 status = SCI_FAILURE;
691 // ---------------------------------------------------------------------------
694 SCI_STATUS scic_sds_remote_node_context_resuming_state_event_handler(
695 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
701 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE)
703 status = SCI_SUCCESS;
705 sci_base_state_machine_change_state(
706 &this_rnc->state_machine,
707 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
712 switch (scu_get_event_type(event_code))
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
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",
726 status = SCI_SUCCESS;
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)
738 status = SCI_FAILURE;
746 // ---------------------------------------------------------------------------
749 * This method will handle the suspend requests from the ready state.
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
756 * @return SCI_SUCCESS
759 SCI_STATUS scic_sds_remote_node_context_ready_state_suspend_handler(
760 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
762 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
763 void * callback_parameter
766 this_rnc->user_callback = the_callback;
767 this_rnc->user_cookie = callback_parameter;
768 this_rnc->suspension_code = suspend_type;
770 if (suspend_type == SCI_SOFTWARE_SUSPENSION)
772 scic_sds_remote_device_post_request(
774 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
778 sci_base_state_machine_change_state(
779 &this_rnc->state_machine,
780 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
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.
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.
794 * @retval SCI_SUCCESS
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
807 SCI_STATUS scic_sds_remote_node_context_ready_state_event_handler(
808 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
814 switch (scu_get_event_type(event_code))
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
822 this_rnc->suspension_code = scu_get_event_specifier(event_code);
823 status = SCI_SUCCESS;
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
832 this_rnc->suspension_code = scu_get_event_specifier(event_code);
833 status = SCI_SUCCESS;
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)
846 status = SCI_FAILURE;
853 // ---------------------------------------------------------------------------
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
862 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
864 scic_sds_remote_node_context_setup_to_resume(
865 this_rnc, the_callback, callback_parameter
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);
875 (protocols.u.bits.attached_stp_target == 1)
876 && !(this_rnc->device->is_direct_attached)
879 sci_base_state_machine_change_state(
880 &this_rnc->state_machine,
881 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
886 sci_base_state_machine_change_state(
887 &this_rnc->state_machine,
888 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
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.
900 * @param[in] this_rnc The remote node context which is to receive the task
902 * @param[in] the_request The task request to be transmitted to the remote
906 * @retval SCI_SUCCESS
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
914 scic_sds_remote_node_context_resume(this_rnc, NULL, NULL);
919 // ---------------------------------------------------------------------------
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
928 scic_sds_remote_node_context_setup_to_resume(
929 this_rnc, the_callback, callback_parameter
932 sci_base_state_machine_change_state(
933 &this_rnc->state_machine,
934 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
937 return SCI_FAILURE_INVALID_STATE;
940 // ---------------------------------------------------------------------------
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
952 scic_sds_remote_node_context_setup_to_resume(
953 this_rnc, the_callback, callback_parameter
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.
964 * @param[in] this_rnc The remote node context which is to receive the task
966 * @param[in] the_request The task request to be transmitted to to the remote
970 * @retval SCI_SUCCESS
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
982 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_event_handler(
983 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
989 switch (scu_get_event_type(event_code))
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
997 this_rnc->suspension_code = scu_get_event_specifier(event_code);
998 status = SCI_SUCCESS;
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
1007 this_rnc->suspension_code = scu_get_event_specifier(event_code);
1008 status = SCI_SUCCESS;
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)
1021 status = SCI_FAILURE;
1028 // ---------------------------------------------------------------------------
1030 SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS
1031 scic_sds_remote_node_context_state_handler_table[
1032 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
1034 // SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
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
1043 // SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
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
1052 // SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
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
1061 // SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
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
1070 // SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
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
1079 // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
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
1088 // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
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
1097 // SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
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
1108 //*****************************************************************************
1109 //* REMOTE NODE CONTEXT PRIVATE METHODS
1110 //*****************************************************************************
1113 * This method just calls the user callback function and then resets the
1116 * @param[in out] rnc
1119 void scic_sds_remote_node_context_notify_user(
1120 SCIC_SDS_REMOTE_NODE_CONTEXT_T *rnc
1123 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK local_user_callback = rnc->user_callback;
1124 void * local_user_cookie = rnc->user_cookie;
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;
1133 if (local_user_callback != NULL)
1135 (*local_user_callback)(local_user_cookie);
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
1147 void scic_sds_remote_node_context_continue_state_transitions(
1148 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc
1151 if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
1153 rnc->state_handlers->resume_handler(
1154 rnc, rnc->user_callback, rnc->user_cookie
1160 * This method will mark the rnc buffer as being valid and post the request to
1163 * @param[in] this_rnc The remote node context object that is to be
1169 void scic_sds_remote_node_context_validate_context_buffer(
1170 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
1173 SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
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
1180 rnc_buffer->ssp.is_valid = TRUE;
1183 !this_rnc->device->is_direct_attached
1184 && this_rnc->device->target_protocols.u.bits.attached_stp_target
1187 scic_sds_remote_device_post_request(
1189 SCU_CONTEXT_COMMAND_POST_RNC_96
1194 scic_sds_remote_device_post_request(
1196 SCU_CONTEXT_COMMAND_POST_RNC_32
1199 if (this_rnc->device->is_direct_attached)
1201 scic_sds_port_setup_transports(
1202 this_rnc->device->owning_port,
1203 this_rnc->remote_node_index
1210 * This method will update the RNC buffer and post the invalidate request.
1212 * @param[in] this_rnc The remote node context object that is to be
1218 void scic_sds_remote_node_context_invalidate_context_buffer(
1219 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
1222 SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
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
1229 rnc_buffer->ssp.is_valid = FALSE;
1231 scic_sds_remote_device_post_request(
1233 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
1237 //*****************************************************************************
1238 //* REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
1239 //*****************************************************************************
1247 void scic_sds_remote_node_context_initial_state_enter(
1248 SCI_BASE_OBJECT_T * object
1251 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1252 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1256 scic_sds_remote_node_context_state_handler_table,
1257 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1260 // Check to see if we have gotten back to the initial state because someone
1261 // requested to destroy the remote node context object.
1263 rnc->state_machine.previous_state_id
1264 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1267 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1269 scic_sds_remote_node_context_notify_user(rnc);
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);
1284 void scic_sds_remote_node_context_posting_state_enter(
1285 SCI_BASE_OBJECT_T * object
1288 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc;
1289 this_rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1293 scic_sds_remote_node_context_state_handler_table,
1294 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1297 scic_sds_remote_node_context_validate_context_buffer(this_rnc);
1306 void scic_sds_remote_node_context_invalidating_state_enter(
1307 SCI_BASE_OBJECT_T * object
1310 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1311 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1315 scic_sds_remote_node_context_state_handler_table,
1316 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1319 scic_sds_remote_node_context_invalidate_context_buffer(rnc);
1328 void scic_sds_remote_node_context_resuming_state_enter(
1329 SCI_BASE_OBJECT_T * object
1332 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1333 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
1334 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1338 scic_sds_remote_node_context_state_handler_table,
1339 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
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);
1349 (protocols.u.bits.attached_stp_target == 1)
1350 && (rnc->device->is_direct_attached)
1353 scic_sds_port_setup_transports(
1354 rnc->device->owning_port, rnc->remote_node_index
1358 scic_sds_remote_device_post_request(
1360 SCU_CONTEXT_COMMAND_POST_RNC_RESUME
1370 void scic_sds_remote_node_context_ready_state_enter(
1371 SCI_BASE_OBJECT_T * object
1374 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1375 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1379 scic_sds_remote_node_context_state_handler_table,
1380 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1383 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1385 if (rnc->user_callback != NULL)
1387 scic_sds_remote_node_context_notify_user(rnc);
1397 void scic_sds_remote_node_context_tx_suspended_state_enter(
1398 SCI_BASE_OBJECT_T * object
1401 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1402 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1406 scic_sds_remote_node_context_state_handler_table,
1407 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1410 scic_sds_remote_node_context_continue_state_transitions(rnc);
1419 void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
1420 SCI_BASE_OBJECT_T * object
1423 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1424 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1428 scic_sds_remote_node_context_state_handler_table,
1429 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1432 scic_sds_remote_node_context_continue_state_transitions(rnc);
1441 void scic_sds_remote_node_context_await_suspension_state_enter(
1442 SCI_BASE_OBJECT_T * object
1445 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1446 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1450 scic_sds_remote_node_context_state_handler_table,
1451 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1455 // ---------------------------------------------------------------------------
1458 scic_sds_remote_node_context_state_table[
1459 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
1462 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
1463 scic_sds_remote_node_context_initial_state_enter,
1467 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
1468 scic_sds_remote_node_context_posting_state_enter,
1472 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
1473 scic_sds_remote_node_context_invalidating_state_enter,
1477 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
1478 scic_sds_remote_node_context_resuming_state_enter,
1482 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
1483 scic_sds_remote_node_context_ready_state_enter,
1487 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
1488 scic_sds_remote_node_context_tx_suspended_state_enter,
1492 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
1493 scic_sds_remote_node_context_tx_rx_suspended_state_enter,
1497 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
1498 scic_sds_remote_node_context_await_suspension_state_enter,