1/*-
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.
4*
5* GPL LICENSE SUMMARY
6*
7* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8*
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.
12*
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.
17*
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.
23*
24* BSD LICENSE
25*
26* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27* All rights reserved.
28*
29* Redistribution and use in source and binary forms, with or without
30* modification, are permitted provided that the following conditions
31* are met:
32*
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
38*     distribution.
39*
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.
51 */
52
53#include <sys/cdefs.h>
54__FBSDID("$FreeBSD$");
55
56/**
57* @file
58*
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.
62*/
63
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>
74
75/**
76* @brief
77*/
78   void scic_sds_remote_node_context_construct(
79   SCIC_SDS_REMOTE_DEVICE_T       * device,
80   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc,
81   U16                              remote_node_index
82      )
83{
84   memset (rnc, 0, sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T) );
85
86   rnc->remote_node_index = remote_node_index;
87   rnc->device            = device;
88   rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
89
90   rnc->parent.logger = device->parent.parent.logger;
91
92   sci_base_state_machine_construct(
93      &rnc->state_machine,
94      &rnc->parent,
95      scic_sds_remote_node_context_state_table,
96      SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
97         );
98
99   sci_base_state_machine_start(&rnc->state_machine);
100
101   // State logging initialization takes place late for the remote node context
102   // see the resume state handler for the initial state.
103}
104
105/**
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.
108*
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.
112*
113* @param[in] this_rnc The RNC for which the is posted request is being made.
114*
115* @return BOOL
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
118*/
119   BOOL scic_sds_remote_node_context_is_initialized(
120   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
121      )
122{
123   U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
124
125   if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE)
126   {
127      return FALSE;
128   }
129
130   return TRUE;
131}
132
133/**
134* This method will return TRUE if the remote node context is in a READY state
135* otherwise it will return FALSE
136*
137* @param[in] this_rnc The state of the remote node context object to check.
138*
139* @return BOOL
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.
142*/
143   BOOL scic_sds_remote_node_context_is_ready(
144   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
145      )
146{
147   U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
148
149   if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE)
150   {
151      return TRUE;
152   }
153
154   return FALSE;
155}
156
157/**
158* This method will construct the RNC buffer for this remote device object.
159*
160* @param[in] this_device The remote device to use to construct the RNC
161*       buffer.
162* @param[in] rnc The buffer into which the remote device data will be copied.
163*
164* @return none
165*/
166   void scic_sds_remote_node_context_construct_buffer(
167   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
168      )
169{
170   SCU_REMOTE_NODE_CONTEXT_T * rnc;
171   SCIC_SDS_CONTROLLER_T     * the_controller;
172
173   the_controller = scic_sds_remote_device_get_controller(this_rnc->device);
174
175   rnc = scic_sds_controller_get_remote_node_context_buffer(
176      the_controller, this_rnc->remote_node_index);
177
178   memset(
179      rnc,
180      0x00,
181      sizeof(SCU_REMOTE_NODE_CONTEXT_T)
182         * scic_sds_remote_device_node_count(this_rnc->device)
183         );
184
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);
189
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);
192
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;
198
199   rnc->ssp.arbitration_wait_time = 0;
200
201
202   if (
203      this_rnc->device->target_protocols.u.bits.attached_sata_device
204         || this_rnc->device->target_protocols.u.bits.attached_stp_target
205         )
206   {
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;
211   }
212   else
213   {
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;
218   }
219
220   rnc->ssp.initial_arbitration_wait_time = 0;
221
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;
227}
228
229// ---------------------------------------------------------------------------
230
231#ifdef SCI_LOGGING
232/**
233* This method will enable and turn on state transition logging for the remote
234* node context object.
235*
236* @param[in] this_rnc The remote node context for which state transition
237*       logging is to be enabled.
238*
239* @return none
240*/
241   void scic_sds_remote_node_context_initialize_state_logging(
242   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
243      )
244{
245   sci_base_state_machine_logger_initialize(
246      &this_rnc->state_machine_logger,
247      &this_rnc->state_machine,
248      &this_rnc->parent,
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
254         );
255}
256
257/**
258* This method will stop the state machine logging for this object and should
259* be called before the object is destroyed.
260*
261* @param[in] this_rnc The remote node context on which to stop logging state
262*       transitions.
263*
264* @return none
265*/
266   void scic_sds_remote_node_context_deinitialize_state_logging(
267   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
268      )
269{
270   sci_base_state_machine_logger_deinitialize(
271      &this_rnc->state_machine_logger,
272      &this_rnc->state_machine
273         );
274}
275#endif
276
277/**
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.
281*
282* @param[in] this_rnc
283* @param[in] the_callback
284* @param[in] callback_parameter
285*
286* @return none
287*/
288static
289void 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
293)
294{
295   if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
296   {
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;
300   }
301}
302
303/**
304* This method will setup the remote node context object so it will
305* transistion to its final state.
306*
307* @param[in] this_rnc
308* @param[in] the_callback
309* @param[in] callback_parameter
310*
311* @return none
312*/
313static
314void 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
318)
319{
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;
323}
324
325/**
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.
328*
329* @param[in] this_rnc
330* @param[in] the_callback
331* @param[in] callback_parameter
332*/
333static
334SCI_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
338)
339{
340   if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
341   {
342      this_rnc->user_callback = the_callback;
343      this_rnc->user_cookie   = callback_parameter;
344
345      return SCI_SUCCESS;
346   }
347
348   return SCI_FAILURE_INVALID_STATE;
349}
350
351//******************************************************************************
352//* REMOTE NODE CONTEXT STATE MACHINE
353//******************************************************************************
354
355static
356SCI_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
360)
361{
362   SCIC_LOG_WARNING((
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)
369         ));
370
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.
373   return SCI_SUCCESS;
374}
375
376static
377SCI_STATUS scic_sds_remote_node_context_default_suspend_handler(
378   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
379   U32                                      suspend_type,
380   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
381   void                                   * callback_parameter
382)
383{
384   SCIC_LOG_WARNING((
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)
391         ));
392
393   return SCI_FAILURE_INVALID_STATE;
394}
395
396static
397SCI_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
401)
402{
403   SCIC_LOG_WARNING((
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)
410         ));
411
412   return SCI_FAILURE_INVALID_STATE;
413}
414
415static
416SCI_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
419)
420{
421   SCIC_LOG_WARNING((
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)
428         ));
429
430   return SCI_FAILURE_INVALID_STATE;
431}
432
433static
434SCI_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
437)
438{
439   SCIC_LOG_WARNING((
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)
446         ));
447
448   return SCI_FAILURE;
449}
450
451static
452SCI_STATUS scic_sds_remote_node_context_default_event_handler(
453   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
454   U32                                   event_code
455)
456{
457   SCIC_LOG_WARNING((
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)
464         ));
465
466   return SCI_FAILURE_INVALID_STATE;
467}
468
469/**
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.
472*
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.
475*
476* @return SCI_STATUS
477* @retval SCI_SUCCESS
478*/
479static
480SCI_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
483)
484{
485   return SCI_SUCCESS;
486}
487
488/**
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
492* callback.
493*
494* @param[in] this_rnc
495* @param[in] the_callback
496* @param[in] callback_parameter
497*
498* @return SCI_STATUS
499*/
500static
501SCI_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
505)
506{
507   scic_sds_remote_node_context_setup_to_destory(
508      this_rnc, the_callback, callback_parameter
509         );
510
511   sci_base_state_machine_change_state(
512      &this_rnc->state_machine,
513      SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
514         );
515
516   return SCI_SUCCESS;
517}
518// ---------------------------------------------------------------------------
519static
520SCI_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
523)
524{
525   SCIC_LOG_WARNING((
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)
532         ));
533
534   return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
535}
536
537// ---------------------------------------------------------------------------
538
539static
540SCI_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
544)
545{
546   if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
547   {
548      scic_sds_remote_node_context_setup_to_resume(
549         this_rnc, the_callback, callback_parameter
550            );
551
552      scic_sds_remote_node_context_construct_buffer(this_rnc);
553
554#if defined (SCI_LOGGING)
555      // If a remote node context has a logger already, don't work on its state
556      // logging.
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);
560#endif
561
562      sci_base_state_machine_change_state(
563         &this_rnc->state_machine,
564         SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
565            );
566
567      return SCI_SUCCESS;
568   }
569
570   return SCI_FAILURE_INVALID_STATE;
571}
572
573// ---------------------------------------------------------------------------
574
575static
576SCI_STATUS scic_sds_remote_node_context_posting_state_event_handler(
577   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
578   U32                                   event_code
579)
580{
581   SCI_STATUS status;
582
583   switch (scu_get_event_code(event_code))
584   {
585      case SCU_EVENT_POST_RNC_COMPLETE:
586         status = SCI_SUCCESS;
587
588         sci_base_state_machine_change_state(
589            &this_rnc->state_machine,
590            SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
591               );
592         break;
593
594      default:
595         status = SCI_FAILURE;
596         SCIC_LOG_WARNING((
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",
602            this_rnc, event_code
603               ));
604         break;
605   }
606
607   return status;
608}
609
610// ---------------------------------------------------------------------------
611
612static
613SCI_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
617)
618{
619   scic_sds_remote_node_context_setup_to_destory(
620      this_rnc, the_callback, callback_parameter
621         );
622
623   return SCI_SUCCESS;
624}
625
626static
627SCI_STATUS scic_sds_remote_node_context_invalidating_state_event_handler(
628   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
629   U32                              event_code
630)
631{
632   SCI_STATUS status;
633
634   if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE)
635   {
636      status = SCI_SUCCESS;
637
638      if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
639      {
640         sci_base_state_machine_change_state(
641            &this_rnc->state_machine,
642            SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
643               );
644      }
645      else
646      {
647         sci_base_state_machine_change_state(
648            &this_rnc->state_machine,
649            SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
650               );
651      }
652   }
653   else
654   {
655      switch (scu_get_event_type(event_code))
656      {
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
661            SCIC_LOG_INFO((
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",
667               this_rnc
668                  ));
669            status = SCI_SUCCESS;
670            break;
671
672         default:
673            SCIC_LOG_WARNING((
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)
680                  ));
681            status = SCI_FAILURE;
682            break;
683      }
684   }
685
686   return status;
687}
688
689// ---------------------------------------------------------------------------
690
691static
692SCI_STATUS scic_sds_remote_node_context_resuming_state_event_handler(
693   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
694   U32                                   event_code
695)
696{
697   SCI_STATUS status;
698
699   if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE)
700   {
701      status = SCI_SUCCESS;
702
703      sci_base_state_machine_change_state(
704         &this_rnc->state_machine,
705         SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
706            );
707   }
708   else
709   {
710      switch (scu_get_event_type(event_code))
711      {
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
716            SCIC_LOG_INFO((
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",
722               this_rnc
723                  ));
724            status = SCI_SUCCESS;
725            break;
726
727         default:
728            SCIC_LOG_WARNING((
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)
735                  ));
736            status = SCI_FAILURE;
737            break;
738      }
739   }
740
741   return status;
742}
743
744// ---------------------------------------------------------------------------
745
746/**
747* This method will handle the suspend requests from the ready state.
748*
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
752*       callback.
753*
754* @return SCI_SUCCESS
755*/
756static
757SCI_STATUS scic_sds_remote_node_context_ready_state_suspend_handler(
758   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
759   U32                                      suspend_type,
760   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
761   void                                   * callback_parameter
762)
763{
764   this_rnc->user_callback   = the_callback;
765   this_rnc->user_cookie     = callback_parameter;
766   this_rnc->suspension_code = suspend_type;
767
768   if (suspend_type == SCI_SOFTWARE_SUSPENSION)
769   {
770      scic_sds_remote_device_post_request(
771         this_rnc->device,
772         SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
773            );
774   }
775
776   sci_base_state_machine_change_state(
777      &this_rnc->state_machine,
778      SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
779         );
780
781   return SCI_SUCCESS;
782}
783
784/**
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.
787*
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.
790*
791* @return SCI_STATUS
792* @retval SCI_SUCCESS
793*/
794static
795SCI_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
798)
799{
800   return SCI_SUCCESS;
801}
802
803
804static
805SCI_STATUS scic_sds_remote_node_context_ready_state_event_handler(
806   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
807   U32                                   event_code
808)
809{
810   SCI_STATUS status;
811
812   switch (scu_get_event_type(event_code))
813   {
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
818               );
819
820         this_rnc->suspension_code = scu_get_event_specifier(event_code);
821         status = SCI_SUCCESS;
822         break;
823
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
828               );
829
830         this_rnc->suspension_code = scu_get_event_specifier(event_code);
831         status = SCI_SUCCESS;
832         break;
833
834      default:
835         SCIC_LOG_WARNING((
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)
842               ));
843
844         status = SCI_FAILURE;
845         break;
846   }
847
848   return status;
849}
850
851// ---------------------------------------------------------------------------
852
853static
854SCI_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
858)
859{
860   SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
861
862   scic_sds_remote_node_context_setup_to_resume(
863      this_rnc, the_callback, callback_parameter
864         );
865
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);
871
872   if (
873      (protocols.u.bits.attached_stp_target == 1)
874         && !(this_rnc->device->is_direct_attached)
875         )
876   {
877      sci_base_state_machine_change_state(
878         &this_rnc->state_machine,
879         SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
880            );
881   }
882   else
883   {
884      sci_base_state_machine_change_state(
885         &this_rnc->state_machine,
886         SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
887            );
888   }
889
890   return SCI_SUCCESS;
891}
892
893/**
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.
897*
898* @param[in] this_rnc The remote node context which is to receive the task
899*       request.
900* @param[in] the_request The task request to be transmitted to to the remote
901*       target device.
902*
903* @return SCI_STATUS
904* @retval SCI_SUCCESS
905*/
906static
907SCI_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
910)
911{
912   scic_sds_remote_node_context_resume(this_rnc, NULL, NULL);
913
914   return SCI_SUCCESS;
915}
916
917// ---------------------------------------------------------------------------
918
919static
920SCI_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
924)
925{
926   scic_sds_remote_node_context_setup_to_resume(
927      this_rnc, the_callback, callback_parameter
928         );
929
930   sci_base_state_machine_change_state(
931      &this_rnc->state_machine,
932      SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
933         );
934
935   return SCI_FAILURE_INVALID_STATE;
936}
937
938// ---------------------------------------------------------------------------
939
940/**
941*
942*/
943static
944SCI_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
948)
949{
950   scic_sds_remote_node_context_setup_to_resume(
951      this_rnc, the_callback, callback_parameter
952         );
953
954   return SCI_SUCCESS;
955}
956
957/**
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.
961*
962* @param[in] this_rnc The remote node context which is to receive the task
963*       request.
964* @param[in] the_request The task request to be transmitted to to the remote
965*       target device.
966*
967* @return SCI_STATUS
968* @retval SCI_SUCCESS
969*/
970static
971SCI_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
974)
975{
976   return SCI_SUCCESS;
977}
978
979static
980SCI_STATUS scic_sds_remote_node_context_await_suspension_state_event_handler(
981   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
982   U32                                   event_code
983)
984{
985   SCI_STATUS status;
986
987   switch (scu_get_event_type(event_code))
988   {
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
993               );
994
995         this_rnc->suspension_code = scu_get_event_specifier(event_code);
996         status = SCI_SUCCESS;
997         break;
998
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
1003               );
1004
1005         this_rnc->suspension_code = scu_get_event_specifier(event_code);
1006         status = SCI_SUCCESS;
1007         break;
1008
1009      default:
1010         SCIC_LOG_WARNING((
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)
1017               ));
1018
1019         status = SCI_FAILURE;
1020         break;
1021   }
1022
1023   return status;
1024}
1025
1026// ---------------------------------------------------------------------------
1027
1028   SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS
1029   scic_sds_remote_node_context_state_handler_table[
1030   SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
1031{
1032   // SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1033   {
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
1040   },
1041   // SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1042   {
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
1049   },
1050   // SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1051   {
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
1058   },
1059   // SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1060   {
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
1067   },
1068   // SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1069   {
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
1076   },
1077   // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1078   {
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
1085   },
1086   // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1087   {
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
1094   },
1095   // SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1096   {
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
1103   }
1104};
1105
1106//*****************************************************************************
1107//* REMOTE NODE CONTEXT PRIVATE METHODS
1108//*****************************************************************************
1109
1110/**
1111* This method just calls the user callback function and then resets the
1112* callback.
1113*
1114* @param[in out] rnc
1115*/
1116static
1117void scic_sds_remote_node_context_notify_user(
1118   SCIC_SDS_REMOTE_NODE_CONTEXT_T *rnc
1119)
1120{
1121   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK local_user_callback = rnc->user_callback;
1122   void * local_user_cookie = rnc->user_cookie;
1123
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;
1130
1131   if (local_user_callback != NULL)
1132   {
1133      (*local_user_callback)(local_user_cookie);
1134   }
1135}
1136
1137/**
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
1140* state.
1141*
1142* @param[in] rnc
1143*/
1144static
1145void scic_sds_remote_node_context_continue_state_transitions(
1146   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc
1147)
1148{
1149   if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
1150   {
1151      rnc->state_handlers->resume_handler(
1152         rnc, rnc->user_callback, rnc->user_cookie
1153            );
1154   }
1155}
1156
1157/**
1158* This method will mark the rnc buffer as being valid and post the request to
1159* the hardware.
1160*
1161* @param[in] this_rnc The remote node context object that is to be
1162*            validated.
1163*
1164* @return none
1165*/
1166static
1167void scic_sds_remote_node_context_validate_context_buffer(
1168   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
1169)
1170{
1171   SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
1172
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
1176         );
1177
1178   rnc_buffer->ssp.is_valid = TRUE;
1179
1180   if (
1181      !this_rnc->device->is_direct_attached
1182         && this_rnc->device->target_protocols.u.bits.attached_stp_target
1183         )
1184   {
1185      scic_sds_remote_device_post_request(
1186         this_rnc->device,
1187         SCU_CONTEXT_COMMAND_POST_RNC_96
1188            );
1189   }
1190   else
1191   {
1192      scic_sds_remote_device_post_request(
1193         this_rnc->device,
1194         SCU_CONTEXT_COMMAND_POST_RNC_32
1195            );
1196
1197      if (this_rnc->device->is_direct_attached)
1198      {
1199         scic_sds_port_setup_transports(
1200            this_rnc->device->owning_port,
1201            this_rnc->remote_node_index
1202               );
1203      }
1204   }
1205}
1206
1207/**
1208* This method will update the RNC buffer and post the invalidate request.
1209*
1210* @param[in] this_rnc The remote node context object that is to be
1211*       invalidated.
1212*
1213* @return none
1214*/
1215static
1216void scic_sds_remote_node_context_invalidate_context_buffer(
1217   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
1218)
1219{
1220   SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
1221
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
1225         );
1226
1227   rnc_buffer->ssp.is_valid = FALSE;
1228
1229   scic_sds_remote_device_post_request(
1230      this_rnc->device,
1231      SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
1232         );
1233}
1234
1235//*****************************************************************************
1236//* REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
1237//*****************************************************************************
1238
1239/**
1240*
1241*
1242* @param[in] object
1243*/
1244static
1245void scic_sds_remote_node_context_initial_state_enter(
1246   SCI_BASE_OBJECT_T * object
1247)
1248{
1249   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1250   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
1251
1252   SET_STATE_HANDLER(
1253      rnc,
1254      scic_sds_remote_node_context_state_handler_table,
1255      SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1256         );
1257
1258   // Check to see if we have gotten back to the initial state because someone
1259   // requested to destroy the remote node context object.
1260   if (
1261      rnc->state_machine.previous_state_id
1262         == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1263         )
1264   {
1265      rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1266
1267      scic_sds_remote_node_context_notify_user(rnc);
1268
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);
1273   }
1274}
1275
1276/**
1277*
1278*
1279* @param[in] object
1280*/
1281static
1282void scic_sds_remote_node_context_posting_state_enter(
1283   SCI_BASE_OBJECT_T * object
1284)
1285{
1286   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc;
1287   this_rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
1288
1289   SET_STATE_HANDLER(
1290      this_rnc,
1291      scic_sds_remote_node_context_state_handler_table,
1292      SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1293         );
1294
1295   scic_sds_remote_node_context_validate_context_buffer(this_rnc);
1296}
1297
1298/**
1299*
1300*
1301* @param[in] object
1302*/
1303static
1304void scic_sds_remote_node_context_invalidating_state_enter(
1305   SCI_BASE_OBJECT_T * object
1306)
1307{
1308   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1309   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
1310
1311   SET_STATE_HANDLER(
1312      rnc,
1313      scic_sds_remote_node_context_state_handler_table,
1314      SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1315         );
1316
1317   scic_sds_remote_node_context_invalidate_context_buffer(rnc);
1318}
1319
1320/**
1321*
1322*
1323* @param[in] object
1324*/
1325static
1326void scic_sds_remote_node_context_resuming_state_enter(
1327   SCI_BASE_OBJECT_T * object
1328)
1329{
1330   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1331   SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
1332   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
1333
1334   SET_STATE_HANDLER(
1335      rnc,
1336      scic_sds_remote_node_context_state_handler_table,
1337      SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1338         );
1339
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);
1345
1346   if (
1347      (protocols.u.bits.attached_stp_target == 1)
1348         && (rnc->device->is_direct_attached)
1349         )
1350   {
1351      scic_sds_port_setup_transports(
1352         rnc->device->owning_port, rnc->remote_node_index
1353            );
1354   }
1355
1356   scic_sds_remote_device_post_request(
1357      rnc->device,
1358      SCU_CONTEXT_COMMAND_POST_RNC_RESUME
1359         );
1360}
1361
1362/**
1363*
1364*
1365* @param[in] object
1366*/
1367static
1368void scic_sds_remote_node_context_ready_state_enter(
1369   SCI_BASE_OBJECT_T * object
1370)
1371{
1372   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1373   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
1374
1375   SET_STATE_HANDLER(
1376      rnc,
1377      scic_sds_remote_node_context_state_handler_table,
1378      SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1379         );
1380
1381   rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1382
1383   if (rnc->user_callback != NULL)
1384   {
1385      scic_sds_remote_node_context_notify_user(rnc);
1386   }
1387}
1388
1389/**
1390*
1391*
1392* @param[in] object
1393*/
1394static
1395void scic_sds_remote_node_context_tx_suspended_state_enter(
1396   SCI_BASE_OBJECT_T * object
1397)
1398{
1399   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1400   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
1401
1402   SET_STATE_HANDLER(
1403      rnc,
1404      scic_sds_remote_node_context_state_handler_table,
1405      SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1406         );
1407
1408   scic_sds_remote_node_context_continue_state_transitions(rnc);
1409}
1410
1411/**
1412*
1413*
1414* @param[in] object
1415*/
1416static
1417void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
1418   SCI_BASE_OBJECT_T * object
1419)
1420{
1421   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1422   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
1423
1424   SET_STATE_HANDLER(
1425      rnc,
1426      scic_sds_remote_node_context_state_handler_table,
1427      SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1428         );
1429
1430   scic_sds_remote_node_context_continue_state_transitions(rnc);
1431}
1432
1433/**
1434*
1435*
1436* @param[in] object
1437*/
1438static
1439void scic_sds_remote_node_context_await_suspension_state_enter(
1440   SCI_BASE_OBJECT_T * object
1441)
1442{
1443   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1444   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
1445
1446   SET_STATE_HANDLER(
1447      rnc,
1448      scic_sds_remote_node_context_state_handler_table,
1449      SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1450         );
1451}
1452
1453// ---------------------------------------------------------------------------
1454
1455   SCI_BASE_STATE_T
1456   scic_sds_remote_node_context_state_table[
1457   SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
1458{
1459   {
1460      SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
1461      scic_sds_remote_node_context_initial_state_enter,
1462      NULL
1463   },
1464   {
1465      SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
1466      scic_sds_remote_node_context_posting_state_enter,
1467      NULL
1468   },
1469   {
1470      SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
1471      scic_sds_remote_node_context_invalidating_state_enter,
1472      NULL
1473   },
1474   {
1475      SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
1476      scic_sds_remote_node_context_resuming_state_enter,
1477      NULL
1478   },
1479   {
1480      SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
1481      scic_sds_remote_node_context_ready_state_enter,
1482      NULL
1483   },
1484   {
1485      SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
1486      scic_sds_remote_node_context_tx_suspended_state_enter,
1487      NULL
1488   },
1489   {
1490      SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
1491      scic_sds_remote_node_context_tx_rx_suspended_state_enter,
1492      NULL
1493   },
1494   {
1495      SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
1496      scic_sds_remote_node_context_await_suspension_state_enter,
1497      NULL
1498   }
1499};
1500
1501