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*/
290static
291void 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*/
315static
316void 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*/
335static
336SCI_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
357static
358SCI_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
378static
379SCI_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
398static
399SCI_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
417static
418SCI_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
435static
436SCI_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
453static
454SCI_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*/
481static
482SCI_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*/
502static
503SCI_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// ---------------------------------------------------------------------------
521static
522SCI_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
541static
542SCI_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
577static
578SCI_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
614static
615SCI_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
628static
629SCI_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
693static
694SCI_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*/
758static
759SCI_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*/
796static
797SCI_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
806static
807SCI_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
855static
856SCI_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*/
908static
909SCI_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
921static
922SCI_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*/
945static
946SCI_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 to the remote
967*       target device.
968*
969* @return SCI_STATUS
970* @retval SCI_SUCCESS
971*/
972static
973SCI_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
981static
982SCI_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*/
1118static
1119void 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*/
1146static
1147void 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*/
1168static
1169void 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*/
1217static
1218void 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*/
1246static
1247void 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*/
1283static
1284void 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*/
1305static
1306void 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*/
1327static
1328void 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*/
1369static
1370void 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*/
1396static
1397void 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*/
1418static
1419void 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*/
1440static
1441void 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
1503