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 implementation of the
62 *        SCIC_SDS_REMOTE_NODE_TABLE public, protected, and private methods.
63 */
64
65#include <dev/isci/scil/scic_sds_remote_node_table.h>
66#include <dev/isci/scil/scic_sds_remote_node_context.h>
67
68/**
69 * This routine will find the bit position in absolute bit terms of the next
70 * available bit for selection.  The absolute bit is index * 32 + bit
71 * position.  If there are available bits in the first U32 then it is just bit
72 * position.
73 *  @param[in] remote_node_table This is the remote node index table from
74 *       which the selection will be made.
75 * @param[in] group_table_index This is the index to the group table from
76 *       which to search for an available selection.
77 *
78 * @return U32 This is the absolute bit position for an available group.
79 */
80static
81U32 scic_sds_remote_node_table_get_group_index(
82   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
83   U32                        group_table_index
84)
85{
86   U32   dword_index;
87   U32 * group_table;
88   U32   bit_index;
89
90   group_table = remote_node_table->remote_node_groups[group_table_index];
91
92   for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++)
93   {
94      if (group_table[dword_index] != 0)
95      {
96         for (bit_index = 0; bit_index < 32; bit_index++)
97         {
98            if ((group_table[dword_index] & (1 << bit_index)) != 0)
99            {
100               return (dword_index * 32) + bit_index;
101            }
102         }
103      }
104   }
105
106   return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX;
107}
108
109/**
110 * This method will clear the group index entry in the specified group index
111 * table.
112 *
113 * @param[in out] remote_node_table This the remote node table in which to
114 *       clear the selector.
115 * @param[in] set_index This is the remote node selector in which the change
116 *       will be made.
117 * @param[in] group_index This is the bit index in the table to be modified.
118 *
119 * @return none
120 */
121static
122void scic_sds_remote_node_table_clear_group_index(
123   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
124   U32                        group_table_index,
125   U32                        group_index
126)
127{
128   U32   dword_index;
129   U32   bit_index;
130   U32 * group_table;
131
132   ASSERT(group_table_index < SCU_STP_REMOTE_NODE_COUNT);
133   ASSERT(group_index < (U32)(remote_node_table->group_array_size * 32));
134
135   dword_index = group_index / 32;
136   bit_index   = group_index % 32;
137   group_table = remote_node_table->remote_node_groups[group_table_index];
138
139   group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index);
140}
141
142/**
143 * This method will set the group index bit entry in the specified group index
144 * table.
145 *
146 * @param[in out] remote_node_table This the remote node table in which to set
147 *       the selector.
148 * @param[in] group_table_index This is the remote node selector in which the
149 *       change will be made.
150 * @param[in] group_index This is the bit position in the table to be
151 *       modified.
152 *
153 * @return none
154 */
155static
156void scic_sds_remote_node_table_set_group_index(
157   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
158   U32                        group_table_index,
159   U32                        group_index
160)
161{
162   U32   dword_index;
163   U32   bit_index;
164   U32 * group_table;
165
166   ASSERT(group_table_index < SCU_STP_REMOTE_NODE_COUNT);
167   ASSERT(group_index < (U32)(remote_node_table->group_array_size * 32));
168
169   dword_index = group_index / 32;
170   bit_index   = group_index % 32;
171   group_table = remote_node_table->remote_node_groups[group_table_index];
172
173   group_table[dword_index] = group_table[dword_index] | (1 << bit_index);
174}
175
176/**
177 * This method will set the remote to available in the remote node allocation
178 * table.
179 *
180 * @param[in out] remote_node_table This is the remote node table in which to
181 *       modify the remote node availability.
182 * @param[in] remote_node_index This is the remote node index that is being
183 *       returned to the table.
184 *
185 * @return none
186 */
187static
188void scic_sds_remote_node_table_set_node_index(
189   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
190   U32                        remote_node_index
191)
192{
193   U32 dword_location;
194   U32 dword_remainder;
195   U32 slot_normalized;
196   U32 slot_position;
197
198   ASSERT(
199        (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
200      > (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
201   );
202
203   dword_location  = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
204   dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
205   slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(U32);
206   slot_position   = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
207
208   remote_node_table->available_remote_nodes[dword_location] |=
209      1 << (slot_normalized + slot_position);
210}
211
212/**
213 * This method clears the remote node index from the table of available remote
214 * nodes.
215 *
216 * @param[in out] remote_node_table This is the remote node table from which
217 *       to clear the available remote node bit.
218 * @param[in] remote_node_index This is the remote node index which is to be
219 *       cleared from the table.
220 *
221 * @return none
222 */
223static
224void scic_sds_remote_node_table_clear_node_index(
225   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
226   U32                        remote_node_index
227)
228{
229   U32 dword_location;
230   U32 dword_remainder;
231   U32 slot_position;
232   U32 slot_normalized;
233
234   ASSERT(
235        (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
236      > (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
237   );
238
239   dword_location  = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
240   dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
241   slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(U32);
242   slot_position   = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
243
244   remote_node_table->available_remote_nodes[dword_location] &=
245      ~(1 << (slot_normalized + slot_position));
246}
247
248/**
249 * This method clears the entire table slot at the specified slot index.
250 *
251 * @param[in out] remote_node_table The remote node table from which the slot
252 *       will be cleared.
253 * @param[in] group_index The index for the slot that is to be cleared.
254 *
255 * @return none
256 */
257static
258void scic_sds_remote_node_table_clear_group(
259   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
260   U32                        group_index
261)
262{
263   U32 dword_location;
264   U32 dword_remainder;
265   U32 dword_value;
266
267   ASSERT(
268        (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
269      > (group_index / SCU_STP_REMOTE_NODE_COUNT)
270   );
271
272   dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
273   dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
274
275   dword_value = remote_node_table->available_remote_nodes[dword_location];
276   dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
277   remote_node_table->available_remote_nodes[dword_location] = dword_value;
278}
279
280/**
281 * THis method sets an entire remote node group in the remote node table.
282 *
283 * @param[in] remote_node_table
284 * @param[in] group_index
285 */
286static
287void scic_sds_remote_node_table_set_group(
288   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
289   U32                        group_index
290)
291{
292   U32 dword_location;
293   U32 dword_remainder;
294   U32 dword_value;
295
296   ASSERT(
297        (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
298      > (group_index / SCU_STP_REMOTE_NODE_COUNT)
299   );
300
301   dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
302   dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
303
304   dword_value = remote_node_table->available_remote_nodes[dword_location];
305   dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
306   remote_node_table->available_remote_nodes[dword_location] = dword_value;
307}
308
309/**
310 * This method will return the group value for the specified group index.
311 *
312 * @param[in] remote_node_table This is the remote node table that for which
313 *       the group value is to be returned.
314 * @param[in] group_index This is the group index to use to find the group
315 *       value.
316 *
317 * @return The bit values at the specified remote node group index.
318 */
319static
320U8 scic_sds_remote_node_table_get_group_value(
321   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
322   U32                        group_index
323)
324{
325   U32 dword_location;
326   U32 dword_remainder;
327   U32 dword_value;
328
329   dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
330   dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
331
332   dword_value = remote_node_table->available_remote_nodes[dword_location];
333   dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
334   dword_value = dword_value >> (dword_remainder * 4);
335
336   return (U8)dword_value;
337}
338
339/**
340 * This method will initialize the remote node table for use.
341 *
342 * @param[in out] remote_node_table The remote that which is to be
343 *       initialized.
344 * @param[in] remote_node_entries The number of entries to put in the table.
345 *
346 * @return none
347 */
348void scic_sds_remote_node_table_initialize(
349   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
350   U32                        remote_node_entries
351)
352{
353   U32 index;
354
355   // Initialize the raw data we could improve the speed by only initializing
356   // those entries that we are actually going to be used
357   memset(
358      remote_node_table->available_remote_nodes,
359      0x00,
360      sizeof(remote_node_table->available_remote_nodes)
361   );
362
363   memset(
364      remote_node_table->remote_node_groups,
365      0x00,
366      sizeof(remote_node_table->remote_node_groups)
367   );
368
369   // Initialize the available remote node sets
370   remote_node_table->available_nodes_array_size = (U16)
371        (remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD)
372      + ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0);
373
374
375   // Initialize each full DWORD to a FULL SET of remote nodes
376   for (index = 0; index < remote_node_entries; index++)
377   {
378      scic_sds_remote_node_table_set_node_index(remote_node_table, index);
379   }
380
381   remote_node_table->group_array_size = (U16)
382        (remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32))
383      + ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0);
384
385   for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++)
386   {
387      // These are all guaranteed to be full slot values so fill them in the
388      // available sets of 3 remote nodes
389      scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index);
390   }
391
392   // Now fill in any remainders that we may find
393   if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2)
394   {
395      scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index);
396   }
397   else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1)
398   {
399      scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index);
400   }
401}
402
403/**
404 * This method will allocate a single RNi from the remote node table.  The
405 * table index will determine from which remote node group table to search.
406 * This search may fail and another group node table can be specified.  The
407 * function is designed to allow a serach of the available single remote node
408 * group up to the triple remote node group.  If an entry is found in the
409 * specified table the remote node is removed and the remote node groups are
410 * updated.
411 *
412 * @param[in out] remote_node_table The remote node table from which to
413 *       allocate a remote node.
414 * @param[in] table_index The group index that is to be used for the search.
415 *
416 * @return The RNi value or an invalid remote node context if an RNi can not
417 *         be found.
418 */
419static
420U16 scic_sds_remote_node_table_allocate_single_remote_node(
421   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
422   U32                        group_table_index
423)
424{
425   U8  index;
426   U8  group_value;
427   U32 group_index;
428   U16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
429
430   group_index = scic_sds_remote_node_table_get_group_index(
431                                             remote_node_table, group_table_index);
432
433   // We could not find an available slot in the table selector 0
434   if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX)
435   {
436      group_value = scic_sds_remote_node_table_get_group_value(
437                                    remote_node_table, group_index);
438
439      for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++)
440      {
441         if (((1 << index) & group_value) != 0)
442         {
443            // We have selected a bit now clear it
444            remote_node_index = (U16) (group_index * SCU_STP_REMOTE_NODE_COUNT
445                                       + index);
446
447            scic_sds_remote_node_table_clear_group_index(
448               remote_node_table, group_table_index, group_index
449            );
450
451            scic_sds_remote_node_table_clear_node_index(
452               remote_node_table, remote_node_index
453            );
454
455            if (group_table_index > 0)
456            {
457               scic_sds_remote_node_table_set_group_index(
458                  remote_node_table, group_table_index - 1, group_index
459               );
460            }
461
462            break;
463         }
464      }
465   }
466
467   return remote_node_index;
468}
469
470/**
471 * This method will allocate three consecutive remote node context entries. If
472 * there are no remaining triple entries the function will return a failure.
473 *
474 * @param[in] remote_node_table This is the remote node table from which to
475 *       allocate the remote node entries.
476 * @param[in] group_table_index THis is the group table index which must equal
477 *       two (2) for this operation.
478 *
479 * @return The remote node index that represents three consecutive remote node
480 *         entries or an invalid remote node context if none can be found.
481 */
482static
483U16 scic_sds_remote_node_table_allocate_triple_remote_node(
484   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
485   U32                        group_table_index
486)
487{
488   U32 group_index;
489   U16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
490
491   group_index = scic_sds_remote_node_table_get_group_index(
492                                             remote_node_table, group_table_index);
493
494   if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX)
495   {
496      remote_node_index = (U16) group_index * SCU_STP_REMOTE_NODE_COUNT;
497
498      scic_sds_remote_node_table_clear_group_index(
499         remote_node_table, group_table_index, group_index
500      );
501
502      scic_sds_remote_node_table_clear_group(
503         remote_node_table, group_index
504      );
505   }
506
507   return remote_node_index;
508}
509
510/**
511 * This method will allocate a remote node that mataches the remote node count
512 * specified by the caller.  Valid values for remote node count is
513 * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3).
514 *
515 * @param[in] remote_node_table This is the remote node table from which the
516 *       remote node allocation is to take place.
517 * @param[in] remote_node_count This is ther remote node count which is one of
518 *       SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3).
519 *
520 * @return U16 This is the remote node index that is returned or an invalid
521 *         remote node context.
522 */
523U16 scic_sds_remote_node_table_allocate_remote_node(
524   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
525   U32                        remote_node_count
526)
527{
528   U16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
529
530   if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT)
531   {
532      remote_node_index =
533         scic_sds_remote_node_table_allocate_single_remote_node(
534                                                         remote_node_table, 0);
535
536      if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
537      {
538         remote_node_index =
539            scic_sds_remote_node_table_allocate_single_remote_node(
540                                                         remote_node_table, 1);
541      }
542
543      if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
544      {
545         remote_node_index =
546            scic_sds_remote_node_table_allocate_single_remote_node(
547                                                         remote_node_table, 2);
548      }
549   }
550   else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT)
551   {
552      remote_node_index =
553         scic_sds_remote_node_table_allocate_triple_remote_node(
554                                                         remote_node_table, 2);
555   }
556
557   return remote_node_index;
558}
559
560/**
561 * This method will free a single remote node index back to the remote node
562 * table.  This routine will update the remote node groups
563 *
564 * @param[in] remote_node_table
565 * @param[in] remote_node_index
566 */
567static
568void scic_sds_remote_node_table_release_single_remote_node(
569   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
570   U16                        remote_node_index
571)
572{
573   U32 group_index;
574   U8  group_value;
575
576   group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
577
578   group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index);
579
580   // Assert that we are not trying to add an entry to a slot that is already
581   // full.
582   ASSERT(group_value != SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE);
583
584   if (group_value == 0x00)
585   {
586      // There are no entries in this slot so it must be added to the single
587      // slot table.
588      scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index);
589   }
590   else if ((group_value & (group_value -1)) == 0)
591   {
592      // There is only one entry in this slot so it must be moved from the
593      // single slot table to the dual slot table
594      scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index);
595      scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index);
596   }
597   else
598   {
599      // There are two entries in the slot so it must be moved from the dual
600      // slot table to the tripple slot table.
601      scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index);
602      scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index);
603   }
604
605   scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index);
606}
607
608/**
609 * This method will release a group of three consecutive remote nodes back to
610 * the free remote nodes.
611 *
612 * @param[in] remote_node_table This is the remote node table to which the
613 *       remote node index is to be freed.
614 * @param[in] remote_node_index This is the remote node index which is being
615 *       freed.
616 */
617static
618void scic_sds_remote_node_table_release_triple_remote_node(
619   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
620   U16                        remote_node_index
621)
622{
623   U32 group_index;
624
625   group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
626
627   scic_sds_remote_node_table_set_group_index(
628      remote_node_table, 2, group_index
629   );
630
631   scic_sds_remote_node_table_set_group(remote_node_table, group_index);
632}
633
634/**
635 * This method will release the remote node index back into the remote node
636 * table free pool.
637 *
638 * @param[in] remote_node_table The remote node table to which the remote node
639 *       index is to be freed.
640 * @param[in] remote_node_count This is the count of consecutive remote nodes
641 *       that are to be freed.
642 * @param[in] remote_node_index This is the remote node index of the start of
643 *       the number of remote nodes to be freed.
644 */
645void scic_sds_remote_node_table_release_remote_node_index(
646   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
647   U32                        remote_node_count,
648   U16                        remote_node_index
649)
650{
651   if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT)
652   {
653      scic_sds_remote_node_table_release_single_remote_node(
654                                       remote_node_table, remote_node_index);
655   }
656   else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT)
657   {
658      scic_sds_remote_node_table_release_triple_remote_node(
659                                       remote_node_table, remote_node_index);
660   }
661}
662
663