diff options
Diffstat (limited to 'drivers/net/fddi/skfp/cfm.c')
-rw-r--r-- | drivers/net/fddi/skfp/cfm.c | 627 |
1 files changed, 627 insertions, 0 deletions
diff --git a/drivers/net/fddi/skfp/cfm.c b/drivers/net/fddi/skfp/cfm.c new file mode 100644 index 000000000000..e395ace3120b --- /dev/null +++ b/drivers/net/fddi/skfp/cfm.c | |||
@@ -0,0 +1,627 @@ | |||
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[] = { | ||
77 | TNONE,TNONE,TNONE,TNONE,TNONE, | ||
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 | |||
146 | void all_selection_criteria(struct s_smc *smc) | ||
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 | |||
225 | all_selection_criteria (smc); | ||
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) | ||
257 | smt_srf_event(smc,SMT_COND_SMT_PEER_WRAP,0,cond) ; | ||
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) { | ||
268 | smt_srf_event(smc,SMT_EVENT_MAC_PATH_CHANGE,INDEX_MAC,0) ; | ||
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)) { | ||
307 | GO_STATE(SC11_C_WRAP_S) ; | ||
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) { | ||
313 | GO_STATE(SC9_C_WRAP_A) ; | ||
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) { | ||
319 | GO_STATE(SC10_C_WRAP_B) ; | ||
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 ) { | ||
347 | GO_STATE(SC0_ISOLATED) ; | ||
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 ; | ||
359 | GO_STATE(SC10_C_WRAP_B) ; | ||
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 ; | ||
371 | GO_STATE(SC4_THRU_A) ; | ||
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 ; | ||
384 | GO_STATE(SC5_THRU_B) ; | ||
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 ) { | ||
411 | GO_STATE(SC0_ISOLATED) ; | ||
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 ; | ||
418 | GO_STATE(SC9_C_WRAP_A) ; | ||
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 ; | ||
427 | GO_STATE(SC4_THRU_A) ; | ||
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 ; | ||
436 | GO_STATE(SC5_THRU_B) ; | ||
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 ; | ||
457 | GO_STATE(SC9_C_WRAP_A) ; | ||
458 | break ; | ||
459 | } | ||
460 | /*SC42*/ | ||
461 | else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) { | ||
462 | smc->y[PB].scrub = TRUE ; | ||
463 | GO_STATE(SC10_C_WRAP_B) ; | ||
464 | break ; | ||
465 | } | ||
466 | /*SC45*/ | ||
467 | else if (smc->s.attach_s) { | ||
468 | smc->y[PB].scrub = TRUE ; | ||
469 | GO_STATE(SC5_THRU_B) ; | ||
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 ; | ||
490 | GO_STATE(SC9_C_WRAP_A) ; | ||
491 | break ; | ||
492 | } | ||
493 | /*SC52*/ | ||
494 | else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) { | ||
495 | smc->y[PB].scrub = TRUE ; | ||
496 | GO_STATE(SC10_C_WRAP_B) ; | ||
497 | break ; | ||
498 | } | ||
499 | /*SC54*/ | ||
500 | else if (!smc->s.attach_s) { | ||
501 | smc->y[PA].scrub = TRUE ; | ||
502 | GO_STATE(SC4_THRU_A) ; | ||
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) { | ||
528 | GO_STATE(SC0_ISOLATED) ; | ||
529 | break ; | ||
530 | } | ||
531 | break ; | ||
532 | default: | ||
533 | SMT_PANIC(smc,SMT_E0106, SMT_E0106_MSG) ; | ||
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 | } | ||