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