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