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