Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cfm.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * (C)Copyright 1998,1999 SysKonnect,
4  * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
5  *
6  * See the file "skfddi.c" for further information.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * The information in this file is provided "AS IS" without warranty.
14  *
15  ******************************************************************************/
16 
17 /*
18  SMT CFM
19  Configuration Management
20  DAS with single MAC
21 */
22 
23 /*
24  * Hardware independent state machine implemantation
25  * The following external SMT functions are referenced :
26  *
27  * queue_event()
28  *
29  * The following external HW dependent functions are referenced :
30  * config_mux()
31  *
32  * The following HW dependent events are required :
33  * NONE
34  */
35 
36 #include "h/types.h"
37 #include "h/fddi.h"
38 #include "h/smc.h"
39 
40 #define KERNEL
41 #include "h/smtstate.h"
42 
43 #ifndef lint
44 static const char ID_sccs[] = "@(#)cfm.c 2.18 98/10/06 (C) SK " ;
45 #endif
46 
47 /*
48  * FSM Macros
49  */
50 #define AFLAG 0x10
51 #define GO_STATE(x) (smc->mib.fddiSMTCF_State = (x)|AFLAG)
52 #define ACTIONS_DONE() (smc->mib.fddiSMTCF_State &= ~AFLAG)
53 #define ACTIONS(x) (x|AFLAG)
54 
55 #ifdef DEBUG
56 /*
57  * symbolic state names
58  */
59 static const char * const cfm_states[] = {
60  "SC0_ISOLATED","CF1","CF2","CF3","CF4",
61  "SC1_WRAP_A","SC2_WRAP_B","SC5_TRHU_B","SC7_WRAP_S",
62  "SC9_C_WRAP_A","SC10_C_WRAP_B","SC11_C_WRAP_S","SC4_THRU_A"
63 } ;
64 
65 /*
66  * symbolic event names
67  */
68 static const char * const cfm_events[] = {
69  "NONE","CF_LOOP_A","CF_LOOP_B","CF_JOIN_A","CF_JOIN_B"
70 } ;
71 #endif
72 
73 /*
74  * map from state to downstream port type
75  */
76 static const unsigned char cf_to_ptype[] = {
78  TNONE,TB,TB,TS,
79  TA,TB,TS,TB
80 } ;
81 
82 /*
83  * CEM port states
84  */
85 #define CEM_PST_DOWN 0
86 #define CEM_PST_UP 1
87 #define CEM_PST_HOLD 2
88 /* define portstate array only for A and B port */
89 /* Do this within the smc structure (use in multiple cards) */
90 
91 /*
92  * all Globals are defined in smc.h
93  * struct s_cfm
94  */
95 
96 /*
97  * function declarations
98  */
99 static void cfm_fsm(struct s_smc *smc, int cmd);
100 
101 /*
102  init CFM state machine
103  clear all CFM vars and flags
104 */
105 void cfm_init(struct s_smc *smc)
106 {
107  smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ;
108  smc->r.rm_join = 0 ;
109  smc->r.rm_loop = 0 ;
110  smc->y[PA].scrub = 0 ;
111  smc->y[PB].scrub = 0 ;
112  smc->y[PA].cem_pst = CEM_PST_DOWN ;
113  smc->y[PB].cem_pst = CEM_PST_DOWN ;
114 }
115 
116 /* Some terms conditions used by the selection criteria */
117 #define THRU_ENABLED(smc) (smc->y[PA].pc_mode != PM_TREE && \
118  smc->y[PB].pc_mode != PM_TREE)
119 /* Selection criteria for the ports */
120 static void selection_criteria (struct s_smc *smc, struct s_phy *phy)
121 {
122 
123  switch (phy->mib->fddiPORTMy_Type) {
124  case TA:
125  if ( !THRU_ENABLED(smc) && smc->y[PB].cf_join ) {
126  phy->wc_flag = TRUE ;
127  } else {
128  phy->wc_flag = FALSE ;
129  }
130 
131  break;
132  case TB:
133  /* take precedence over PA */
134  phy->wc_flag = FALSE ;
135  break;
136  case TS:
137  phy->wc_flag = FALSE ;
138  break;
139  case TM:
140  phy->wc_flag = FALSE ;
141  break;
142  }
143 
144 }
145 
147 {
148  struct s_phy *phy ;
149  int p ;
150 
151  for ( p = 0,phy = smc->y ; p < NUMPHYS; p++, phy++ ) {
152  /* Do the selection criteria */
153  selection_criteria (smc,phy);
154  }
155 }
156 
157 static void cem_priv_state(struct s_smc *smc, int event)
158 /* State machine for private PORT states: used to optimize dual homing */
159 {
160  int np; /* Number of the port */
161  int i;
162 
163  /* Do this only in a DAS */
164  if (smc->s.sas != SMT_DAS )
165  return ;
166 
167  np = event - CF_JOIN;
168 
169  if (np != PA && np != PB) {
170  return ;
171  }
172  /* Change the port state according to the event (portnumber) */
173  if (smc->y[np].cf_join) {
174  smc->y[np].cem_pst = CEM_PST_UP ;
175  } else if (!smc->y[np].wc_flag) {
176  /* set the port to done only if it is not withheld */
177  smc->y[np].cem_pst = CEM_PST_DOWN ;
178  }
179 
180  /* Don't set an hold port to down */
181 
182  /* Check all ports of restart conditions */
183  for (i = 0 ; i < 2 ; i ++ ) {
184  /* Check all port for PORT is on hold and no withhold is done */
185  if ( smc->y[i].cem_pst == CEM_PST_HOLD && !smc->y[i].wc_flag ) {
186  smc->y[i].cem_pst = CEM_PST_DOWN;
187  queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
188  }
189  if ( smc->y[i].cem_pst == CEM_PST_UP && smc->y[i].wc_flag ) {
190  smc->y[i].cem_pst = CEM_PST_HOLD;
191  queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
192  }
193  if ( smc->y[i].cem_pst == CEM_PST_DOWN && smc->y[i].wc_flag ) {
194  /*
195  * The port must be restarted when the wc_flag
196  * will be reset. So set the port on hold.
197  */
198  smc->y[i].cem_pst = CEM_PST_HOLD;
199  }
200  }
201  return ;
202 }
203 
204 /*
205  CFM state machine
206  called by dispatcher
207 
208  do
209  display state change
210  process event
211  until SM is stable
212 */
213 void cfm(struct s_smc *smc, int event)
214 {
215  int state ; /* remember last state */
216  int cond ;
217  int oldstate ;
218 
219  /* We will do the following: */
220  /* - compute the variable WC_Flag for every port (This is where */
221  /* we can extend the requested path checking !!) */
222  /* - do the old (SMT 6.2 like) state machine */
223  /* - do the resulting station states */
224 
226 
227  /* We will check now whether a state transition is allowed or not */
228  /* - change the portstates */
229  cem_priv_state (smc, event);
230 
231  oldstate = smc->mib.fddiSMTCF_State ;
232  do {
233  DB_CFM("CFM : state %s%s",
234  (smc->mib.fddiSMTCF_State & AFLAG) ? "ACTIONS " : "",
235  cfm_states[smc->mib.fddiSMTCF_State & ~AFLAG]) ;
236  DB_CFM(" event %s\n",cfm_events[event],0) ;
237  state = smc->mib.fddiSMTCF_State ;
238  cfm_fsm(smc,event) ;
239  event = 0 ;
240  } while (state != smc->mib.fddiSMTCF_State) ;
241 
242 #ifndef SLIM_SMT
243  /*
244  * check peer wrap condition
245  */
246  cond = FALSE ;
247  if ( (smc->mib.fddiSMTCF_State == SC9_C_WRAP_A &&
248  smc->y[PA].pc_mode == PM_PEER) ||
249  (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B &&
250  smc->y[PB].pc_mode == PM_PEER) ||
251  (smc->mib.fddiSMTCF_State == SC11_C_WRAP_S &&
252  smc->y[PS].pc_mode == PM_PEER &&
253  smc->y[PS].mib->fddiPORTNeighborType != TS ) ) {
254  cond = TRUE ;
255  }
256  if (cond != smc->mib.fddiSMTPeerWrapFlag)
258 
259 #if 0
260  /*
261  * Don't send ever MAC_PATH_CHANGE events. Our MAC is hard-wired
262  * to the primary path.
263  */
264  /*
265  * path change
266  */
267  if (smc->mib.fddiSMTCF_State != oldstate) {
269  }
270 #endif
271 #endif /* no SLIM_SMT */
272 
273  /*
274  * set MAC port type
275  */
276  smc->mib.m[MAC0].fddiMACDownstreamPORTType =
277  cf_to_ptype[smc->mib.fddiSMTCF_State] ;
278  cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ;
279 }
280 
281 /*
282  process CFM event
283 */
284 /*ARGSUSED1*/
285 static void cfm_fsm(struct s_smc *smc, int cmd)
286 {
287  switch(smc->mib.fddiSMTCF_State) {
288  case ACTIONS(SC0_ISOLATED) :
289  smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
290  smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
291  smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
292  smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
293  smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ;
294  config_mux(smc,MUX_ISOLATE) ; /* configure PHY Mux */
295  smc->r.rm_loop = FALSE ;
296  smc->r.rm_join = FALSE ;
297  queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
298  /* Don't do the WC-Flag changing here */
299  ACTIONS_DONE() ;
300  DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
301  break;
302  case SC0_ISOLATED :
303  /*SC07*/
304  /*SAS port can be PA or PB ! */
305  if (smc->s.sas && (smc->y[PA].cf_join || smc->y[PA].cf_loop ||
306  smc->y[PB].cf_join || smc->y[PB].cf_loop)) {
308  break ;
309  }
310  /*SC01*/
311  if ((smc->y[PA].cem_pst == CEM_PST_UP && smc->y[PA].cf_join &&
312  !smc->y[PA].wc_flag) || smc->y[PA].cf_loop) {
314  break ;
315  }
316  /*SC02*/
317  if ((smc->y[PB].cem_pst == CEM_PST_UP && smc->y[PB].cf_join &&
318  !smc->y[PB].wc_flag) || smc->y[PB].cf_loop) {
320  break ;
321  }
322  break ;
323  case ACTIONS(SC9_C_WRAP_A) :
324  smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
325  smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
326  smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
327  smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
328  smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
329  config_mux(smc,MUX_WRAPA) ; /* configure PHY mux */
330  if (smc->y[PA].cf_loop) {
331  smc->r.rm_join = FALSE ;
332  smc->r.rm_loop = TRUE ;
333  queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
334  }
335  if (smc->y[PA].cf_join) {
336  smc->r.rm_loop = FALSE ;
337  smc->r.rm_join = TRUE ;
338  queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
339  }
340  ACTIONS_DONE() ;
341  DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
342  break ;
343  case SC9_C_WRAP_A :
344  /*SC10*/
345  if ( (smc->y[PA].wc_flag || !smc->y[PA].cf_join) &&
346  !smc->y[PA].cf_loop ) {
348  break ;
349  }
350  /*SC12*/
351  else if ( (smc->y[PB].cf_loop && smc->y[PA].cf_join &&
352  smc->y[PA].cem_pst == CEM_PST_UP) ||
353  ((smc->y[PB].cf_loop ||
354  (smc->y[PB].cf_join &&
355  smc->y[PB].cem_pst == CEM_PST_UP)) &&
356  (smc->y[PA].pc_mode == PM_TREE ||
357  smc->y[PB].pc_mode == PM_TREE))) {
358  smc->y[PA].scrub = TRUE ;
360  break ;
361  }
362  /*SC14*/
363  else if (!smc->s.attach_s &&
364  smc->y[PA].cf_join &&
365  smc->y[PA].cem_pst == CEM_PST_UP &&
366  smc->y[PA].pc_mode == PM_PEER && smc->y[PB].cf_join &&
367  smc->y[PB].cem_pst == CEM_PST_UP &&
368  smc->y[PB].pc_mode == PM_PEER) {
369  smc->y[PA].scrub = TRUE ;
370  smc->y[PB].scrub = TRUE ;
372  break ;
373  }
374  /*SC15*/
375  else if ( smc->s.attach_s &&
376  smc->y[PA].cf_join &&
377  smc->y[PA].cem_pst == CEM_PST_UP &&
378  smc->y[PA].pc_mode == PM_PEER &&
379  smc->y[PB].cf_join &&
380  smc->y[PB].cem_pst == CEM_PST_UP &&
381  smc->y[PB].pc_mode == PM_PEER) {
382  smc->y[PA].scrub = TRUE ;
383  smc->y[PB].scrub = TRUE ;
385  break ;
386  }
387  break ;
388  case ACTIONS(SC10_C_WRAP_B) :
389  smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
390  smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
391  smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
392  smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
393  smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
394  config_mux(smc,MUX_WRAPB) ; /* configure PHY mux */
395  if (smc->y[PB].cf_loop) {
396  smc->r.rm_join = FALSE ;
397  smc->r.rm_loop = TRUE ;
398  queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
399  }
400  if (smc->y[PB].cf_join) {
401  smc->r.rm_loop = FALSE ;
402  smc->r.rm_join = TRUE ;
403  queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
404  }
405  ACTIONS_DONE() ;
406  DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
407  break ;
408  case SC10_C_WRAP_B :
409  /*SC20*/
410  if ( !smc->y[PB].cf_join && !smc->y[PB].cf_loop ) {
412  break ;
413  }
414  /*SC21*/
415  else if ( smc->y[PA].cf_loop && smc->y[PA].pc_mode == PM_PEER &&
416  smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
417  smc->y[PB].scrub = TRUE ;
419  break ;
420  }
421  /*SC24*/
422  else if (!smc->s.attach_s &&
423  smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
424  smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
425  smc->y[PA].scrub = TRUE ;
426  smc->y[PB].scrub = TRUE ;
428  break ;
429  }
430  /*SC25*/
431  else if ( smc->s.attach_s &&
432  smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
433  smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
434  smc->y[PA].scrub = TRUE ;
435  smc->y[PB].scrub = TRUE ;
437  break ;
438  }
439  break ;
440  case ACTIONS(SC4_THRU_A) :
441  smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
442  smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
443  smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
444  smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
445  smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
446  config_mux(smc,MUX_THRUA) ; /* configure PHY mux */
447  smc->r.rm_loop = FALSE ;
448  smc->r.rm_join = TRUE ;
449  queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
450  ACTIONS_DONE() ;
451  DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
452  break ;
453  case SC4_THRU_A :
454  /*SC41*/
455  if (smc->y[PB].wc_flag || !smc->y[PB].cf_join) {
456  smc->y[PA].scrub = TRUE ;
458  break ;
459  }
460  /*SC42*/
461  else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
462  smc->y[PB].scrub = TRUE ;
464  break ;
465  }
466  /*SC45*/
467  else if (smc->s.attach_s) {
468  smc->y[PB].scrub = TRUE ;
470  break ;
471  }
472  break ;
473  case ACTIONS(SC5_THRU_B) :
474  smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
475  smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
476  smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
477  smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
478  smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
479  config_mux(smc,MUX_THRUB) ; /* configure PHY mux */
480  smc->r.rm_loop = FALSE ;
481  smc->r.rm_join = TRUE ;
482  queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
483  ACTIONS_DONE() ;
484  DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
485  break ;
486  case SC5_THRU_B :
487  /*SC51*/
488  if (!smc->y[PB].cf_join || smc->y[PB].wc_flag) {
489  smc->y[PA].scrub = TRUE ;
491  break ;
492  }
493  /*SC52*/
494  else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
495  smc->y[PB].scrub = TRUE ;
497  break ;
498  }
499  /*SC54*/
500  else if (!smc->s.attach_s) {
501  smc->y[PA].scrub = TRUE ;
503  break ;
504  }
505  break ;
506  case ACTIONS(SC11_C_WRAP_S) :
507  smc->mib.p[PS].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
508  smc->mib.p[PS].fddiPORTMACPlacement = INDEX_MAC ;
509  smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
510  config_mux(smc,MUX_WRAPS) ; /* configure PHY mux */
511  if (smc->y[PA].cf_loop || smc->y[PB].cf_loop) {
512  smc->r.rm_join = FALSE ;
513  smc->r.rm_loop = TRUE ;
514  queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
515  }
516  if (smc->y[PA].cf_join || smc->y[PB].cf_join) {
517  smc->r.rm_loop = FALSE ;
518  smc->r.rm_join = TRUE ;
519  queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
520  }
521  ACTIONS_DONE() ;
522  DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
523  break ;
524  case SC11_C_WRAP_S :
525  /*SC70*/
526  if ( !smc->y[PA].cf_join && !smc->y[PA].cf_loop &&
527  !smc->y[PB].cf_join && !smc->y[PB].cf_loop) {
529  break ;
530  }
531  break ;
532  default:
534  break;
535  }
536 }
537 
538 /*
539  * get MAC's input Port
540  * return :
541  * PA or PB
542  */
543 int cfm_get_mac_input(struct s_smc *smc)
544 {
545  return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
546  smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA;
547 }
548 
549 /*
550  * get MAC's output Port
551  * return :
552  * PA or PB
553  */
554 int cfm_get_mac_output(struct s_smc *smc)
555 {
556  return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
557  smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA;
558 }
559 
560 static char path_iso[] = {
561  0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_ISO,
562  0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO,
563  0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_ISO
564 } ;
565 
566 static char path_wrap_a[] = {
567  0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_PRIM,
568  0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
569  0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_ISO
570 } ;
571 
572 static char path_wrap_b[] = {
573  0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_PRIM,
574  0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
575  0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_ISO
576 } ;
577 
578 static char path_thru[] = {
579  0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_PRIM,
580  0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
581  0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_PRIM
582 } ;
583 
584 static char path_wrap_s[] = {
585  0,0, 0,RES_PORT, 0,PS + INDEX_PORT, 0,PATH_PRIM,
586  0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
587 } ;
588 
589 static char path_iso_s[] = {
590  0,0, 0,RES_PORT, 0,PS + INDEX_PORT, 0,PATH_ISO,
591  0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO,
592 } ;
593 
594 int cem_build_path(struct s_smc *smc, char *to, int path_index)
595 {
596  char *path ;
597  int len ;
598 
599  switch (smc->mib.fddiSMTCF_State) {
600  default :
601  case SC0_ISOLATED :
602  path = smc->s.sas ? path_iso_s : path_iso ;
603  len = smc->s.sas ? sizeof(path_iso_s) : sizeof(path_iso) ;
604  break ;
605  case SC9_C_WRAP_A :
606  path = path_wrap_a ;
607  len = sizeof(path_wrap_a) ;
608  break ;
609  case SC10_C_WRAP_B :
610  path = path_wrap_b ;
611  len = sizeof(path_wrap_b) ;
612  break ;
613  case SC4_THRU_A :
614  path = path_thru ;
615  len = sizeof(path_thru) ;
616  break ;
617  case SC11_C_WRAP_S :
618  path = path_wrap_s ;
619  len = sizeof(path_wrap_s) ;
620  break ;
621  }
622  memcpy(to,path,len) ;
623 
624  LINT_USE(path_index);
625 
626  return len;
627 }