]>
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 RMT | |
15 | Ring Management | |
16 | */ | |
17 | ||
18 | /* | |
19 | * Hardware independent state machine implemantation | |
20 | * The following external SMT functions are referenced : | |
21 | * | |
22 | * queue_event() | |
23 | * smt_timer_start() | |
24 | * smt_timer_stop() | |
25 | * | |
26 | * The following external HW dependent functions are referenced : | |
27 | * sm_ma_control() | |
28 | * sm_mac_check_beacon_claim() | |
29 | * | |
30 | * The following HW dependent events are required : | |
31 | * RM_RING_OP | |
32 | * RM_RING_NON_OP | |
33 | * RM_MY_BEACON | |
34 | * RM_OTHER_BEACON | |
35 | * RM_MY_CLAIM | |
36 | * RM_TRT_EXP | |
37 | * RM_VALID_CLAIM | |
38 | * | |
39 | */ | |
40 | ||
41 | #include "h/types.h" | |
42 | #include "h/fddi.h" | |
43 | #include "h/smc.h" | |
44 | ||
45 | #define KERNEL | |
46 | #include "h/smtstate.h" | |
47 | ||
48 | #ifndef lint | |
49 | static const char ID_sccs[] = "@(#)rmt.c 2.13 99/07/02 (C) SK " ; | |
50 | #endif | |
51 | ||
52 | /* | |
53 | * FSM Macros | |
54 | */ | |
55 | #define AFLAG 0x10 | |
56 | #define GO_STATE(x) (smc->mib.m[MAC0].fddiMACRMTState = (x)|AFLAG) | |
57 | #define ACTIONS_DONE() (smc->mib.m[MAC0].fddiMACRMTState &= ~AFLAG) | |
58 | #define ACTIONS(x) (x|AFLAG) | |
59 | ||
60 | #define RM0_ISOLATED 0 | |
61 | #define RM1_NON_OP 1 /* not operational */ | |
62 | #define RM2_RING_OP 2 /* ring operational */ | |
63 | #define RM3_DETECT 3 /* detect dupl addresses */ | |
64 | #define RM4_NON_OP_DUP 4 /* dupl. addr detected */ | |
65 | #define RM5_RING_OP_DUP 5 /* ring oper. with dupl. addr */ | |
66 | #define RM6_DIRECTED 6 /* sending directed beacons */ | |
67 | #define RM7_TRACE 7 /* trace initiated */ | |
68 | ||
1da177e4 LT |
69 | /* |
70 | * symbolic state names | |
71 | */ | |
72 | static const char * const rmt_states[] = { | |
73 | "RM0_ISOLATED","RM1_NON_OP","RM2_RING_OP","RM3_DETECT", | |
74 | "RM4_NON_OP_DUP","RM5_RING_OP_DUP","RM6_DIRECTED", | |
75 | "RM7_TRACE" | |
76 | } ; | |
77 | ||
78 | /* | |
79 | * symbolic event names | |
80 | */ | |
81 | static const char * const rmt_events[] = { | |
82 | "NONE","RM_RING_OP","RM_RING_NON_OP","RM_MY_BEACON", | |
83 | "RM_OTHER_BEACON","RM_MY_CLAIM","RM_TRT_EXP","RM_VALID_CLAIM", | |
84 | "RM_JOIN","RM_LOOP","RM_DUP_ADDR","RM_ENABLE_FLAG", | |
85 | "RM_TIMEOUT_NON_OP","RM_TIMEOUT_T_STUCK", | |
86 | "RM_TIMEOUT_ANNOUNCE","RM_TIMEOUT_T_DIRECT", | |
87 | "RM_TIMEOUT_D_MAX","RM_TIMEOUT_POLL","RM_TX_STATE_CHANGE" | |
88 | } ; | |
1da177e4 LT |
89 | |
90 | /* | |
91 | * Globals | |
92 | * in struct s_rmt | |
93 | */ | |
94 | ||
95 | ||
96 | /* | |
97 | * function declarations | |
98 | */ | |
99 | static void rmt_fsm(struct s_smc *smc, int cmd); | |
100 | static void start_rmt_timer0(struct s_smc *smc, u_long value, int event); | |
101 | static void start_rmt_timer1(struct s_smc *smc, u_long value, int event); | |
102 | static void start_rmt_timer2(struct s_smc *smc, u_long value, int event); | |
103 | static void stop_rmt_timer0(struct s_smc *smc); | |
104 | static void stop_rmt_timer1(struct s_smc *smc); | |
105 | static void stop_rmt_timer2(struct s_smc *smc); | |
106 | static void rmt_dup_actions(struct s_smc *smc); | |
107 | static void rmt_reinsert_actions(struct s_smc *smc); | |
108 | static void rmt_leave_actions(struct s_smc *smc); | |
109 | static void rmt_new_dup_actions(struct s_smc *smc); | |
110 | ||
111 | #ifndef SUPERNET_3 | |
112 | extern void restart_trt_for_dbcn() ; | |
113 | #endif /*SUPERNET_3*/ | |
114 | ||
115 | /* | |
116 | init RMT state machine | |
117 | clear all RMT vars and flags | |
118 | */ | |
119 | void rmt_init(struct s_smc *smc) | |
120 | { | |
121 | smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ; | |
122 | smc->r.dup_addr_test = DA_NONE ; | |
123 | smc->r.da_flag = 0 ; | |
124 | smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; | |
125 | smc->r.sm_ma_avail = FALSE ; | |
126 | smc->r.loop_avail = 0 ; | |
127 | smc->r.bn_flag = 0 ; | |
128 | smc->r.jm_flag = 0 ; | |
129 | smc->r.no_flag = TRUE ; | |
130 | } | |
131 | ||
132 | /* | |
133 | RMT state machine | |
134 | called by dispatcher | |
135 | ||
136 | do | |
137 | display state change | |
138 | process event | |
139 | until SM is stable | |
140 | */ | |
141 | void rmt(struct s_smc *smc, int event) | |
142 | { | |
143 | int state ; | |
144 | ||
145 | do { | |
5671e8c1 JP |
146 | DB_RMT("RMT : state %s%s event %s", |
147 | smc->mib.m[MAC0].fddiMACRMTState & AFLAG ? "ACTIONS " : "", | |
148 | rmt_states[smc->mib.m[MAC0].fddiMACRMTState & ~AFLAG], | |
149 | rmt_events[event]); | |
1da177e4 LT |
150 | state = smc->mib.m[MAC0].fddiMACRMTState ; |
151 | rmt_fsm(smc,event) ; | |
152 | event = 0 ; | |
153 | } while (state != smc->mib.m[MAC0].fddiMACRMTState) ; | |
154 | rmt_state_change(smc,(int)smc->mib.m[MAC0].fddiMACRMTState) ; | |
155 | } | |
156 | ||
157 | /* | |
158 | process RMT event | |
159 | */ | |
160 | static void rmt_fsm(struct s_smc *smc, int cmd) | |
161 | { | |
162 | /* | |
163 | * RM00-RM70 : from all states | |
164 | */ | |
165 | if (!smc->r.rm_join && !smc->r.rm_loop && | |
166 | smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) && | |
167 | smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) { | |
168 | RS_SET(smc,RS_NORINGOP) ; | |
169 | rmt_indication(smc,0) ; | |
170 | GO_STATE(RM0_ISOLATED) ; | |
171 | return ; | |
172 | } | |
173 | ||
174 | switch(smc->mib.m[MAC0].fddiMACRMTState) { | |
175 | case ACTIONS(RM0_ISOLATED) : | |
176 | stop_rmt_timer0(smc) ; | |
177 | stop_rmt_timer1(smc) ; | |
178 | stop_rmt_timer2(smc) ; | |
179 | ||
180 | /* | |
181 | * Disable MAC. | |
182 | */ | |
183 | sm_ma_control(smc,MA_OFFLINE) ; | |
184 | smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; | |
185 | smc->r.loop_avail = FALSE ; | |
186 | smc->r.sm_ma_avail = FALSE ; | |
187 | smc->r.no_flag = TRUE ; | |
5671e8c1 | 188 | DB_RMTN(1, "RMT : ISOLATED"); |
1da177e4 LT |
189 | ACTIONS_DONE() ; |
190 | break ; | |
191 | case RM0_ISOLATED : | |
192 | /*RM01*/ | |
193 | if (smc->r.rm_join || smc->r.rm_loop) { | |
194 | /* | |
195 | * According to the standard the MAC must be reset | |
196 | * here. The FORMAC will be initialized and Claim | |
197 | * and Beacon Frames will be uploaded to the MAC. | |
198 | * So any change of Treq will take effect NOW. | |
199 | */ | |
200 | sm_ma_control(smc,MA_RESET) ; | |
201 | GO_STATE(RM1_NON_OP) ; | |
202 | break ; | |
203 | } | |
204 | break ; | |
205 | case ACTIONS(RM1_NON_OP) : | |
206 | start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ; | |
207 | stop_rmt_timer1(smc) ; | |
208 | stop_rmt_timer2(smc) ; | |
209 | sm_ma_control(smc,MA_BEACON) ; | |
5671e8c1 | 210 | DB_RMTN(1, "RMT : RING DOWN"); |
1da177e4 LT |
211 | RS_SET(smc,RS_NORINGOP) ; |
212 | smc->r.sm_ma_avail = FALSE ; | |
213 | rmt_indication(smc,0) ; | |
214 | ACTIONS_DONE() ; | |
215 | break ; | |
216 | case RM1_NON_OP : | |
217 | /*RM12*/ | |
218 | if (cmd == RM_RING_OP) { | |
219 | RS_SET(smc,RS_RINGOPCHANGE) ; | |
220 | GO_STATE(RM2_RING_OP) ; | |
221 | break ; | |
222 | } | |
223 | /*RM13*/ | |
224 | else if (cmd == RM_TIMEOUT_NON_OP) { | |
225 | smc->r.bn_flag = FALSE ; | |
226 | smc->r.no_flag = TRUE ; | |
227 | GO_STATE(RM3_DETECT) ; | |
228 | break ; | |
229 | } | |
230 | break ; | |
231 | case ACTIONS(RM2_RING_OP) : | |
232 | stop_rmt_timer0(smc) ; | |
233 | stop_rmt_timer1(smc) ; | |
234 | stop_rmt_timer2(smc) ; | |
235 | smc->r.no_flag = FALSE ; | |
236 | if (smc->r.rm_loop) | |
237 | smc->r.loop_avail = TRUE ; | |
238 | if (smc->r.rm_join) { | |
239 | smc->r.sm_ma_avail = TRUE ; | |
240 | if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable) | |
241 | smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ; | |
242 | else | |
243 | smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; | |
244 | } | |
5671e8c1 | 245 | DB_RMTN(1, "RMT : RING UP"); |
1da177e4 LT |
246 | RS_CLEAR(smc,RS_NORINGOP) ; |
247 | RS_SET(smc,RS_RINGOPCHANGE) ; | |
248 | rmt_indication(smc,1) ; | |
249 | smt_stat_counter(smc,0) ; | |
250 | ACTIONS_DONE() ; | |
251 | break ; | |
252 | case RM2_RING_OP : | |
253 | /*RM21*/ | |
254 | if (cmd == RM_RING_NON_OP) { | |
255 | smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; | |
256 | smc->r.loop_avail = FALSE ; | |
257 | RS_SET(smc,RS_RINGOPCHANGE) ; | |
258 | GO_STATE(RM1_NON_OP) ; | |
259 | break ; | |
260 | } | |
261 | /*RM22a*/ | |
262 | else if (cmd == RM_ENABLE_FLAG) { | |
263 | if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable) | |
264 | smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ; | |
265 | else | |
266 | smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; | |
267 | } | |
268 | /*RM25*/ | |
269 | else if (smc->r.dup_addr_test == DA_FAILED) { | |
270 | smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; | |
271 | smc->r.loop_avail = FALSE ; | |
272 | smc->r.da_flag = TRUE ; | |
273 | GO_STATE(RM5_RING_OP_DUP) ; | |
274 | break ; | |
275 | } | |
276 | break ; | |
277 | case ACTIONS(RM3_DETECT) : | |
278 | start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ; | |
279 | start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ; | |
280 | start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; | |
281 | sm_mac_check_beacon_claim(smc) ; | |
5671e8c1 | 282 | DB_RMTN(1, "RMT : RM3_DETECT"); |
1da177e4 LT |
283 | ACTIONS_DONE() ; |
284 | break ; | |
285 | case RM3_DETECT : | |
286 | if (cmd == RM_TIMEOUT_POLL) { | |
287 | start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); | |
288 | sm_mac_check_beacon_claim(smc) ; | |
289 | break ; | |
290 | } | |
291 | if (cmd == RM_TIMEOUT_D_MAX) { | |
292 | smc->r.timer0_exp = TRUE ; | |
293 | } | |
294 | /* | |
295 | *jd(22-Feb-1999) | |
296 | * We need a time ">= 2*mac_d_max" since we had finished | |
297 | * Claim or Beacon state. So we will restart timer0 at | |
298 | * every state change. | |
299 | */ | |
300 | if (cmd == RM_TX_STATE_CHANGE) { | |
301 | start_rmt_timer0(smc, | |
302 | smc->s.mac_d_max*2, | |
303 | RM_TIMEOUT_D_MAX) ; | |
304 | } | |
305 | /*RM32*/ | |
306 | if (cmd == RM_RING_OP) { | |
307 | GO_STATE(RM2_RING_OP) ; | |
308 | break ; | |
309 | } | |
310 | /*RM33a*/ | |
311 | else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) | |
312 | && smc->r.bn_flag) { | |
313 | smc->r.bn_flag = FALSE ; | |
314 | } | |
315 | /*RM33b*/ | |
316 | else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) { | |
317 | int tx ; | |
318 | /* | |
319 | * set bn_flag only if in state T4 or T5: | |
320 | * only if we're the beaconer should we start the | |
321 | * trace ! | |
322 | */ | |
323 | if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) { | |
5671e8c1 | 324 | DB_RMTN(2, "RMT : DETECT && TRT_EXPIRED && T4/T5"); |
1da177e4 LT |
325 | smc->r.bn_flag = TRUE ; |
326 | /* | |
327 | * If one of the upstream stations beaconed | |
328 | * and the link to the upstream neighbor is | |
329 | * lost we need to restart the stuck timer to | |
330 | * check the "stuck beacon" condition. | |
331 | */ | |
332 | start_rmt_timer1(smc,smc->s.rmt_t_stuck, | |
333 | RM_TIMEOUT_T_STUCK) ; | |
334 | } | |
335 | /* | |
336 | * We do NOT need to clear smc->r.bn_flag in case of | |
337 | * not being in state T4 or T5, because the flag | |
338 | * must be cleared in order to get in this condition. | |
339 | */ | |
340 | ||
5671e8c1 JP |
341 | DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)", |
342 | tx, smc->r.bn_flag); | |
1da177e4 LT |
343 | } |
344 | /*RM34a*/ | |
345 | else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) { | |
346 | rmt_new_dup_actions(smc) ; | |
347 | GO_STATE(RM4_NON_OP_DUP) ; | |
348 | break ; | |
349 | } | |
350 | /*RM34b*/ | |
351 | else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) { | |
352 | rmt_new_dup_actions(smc) ; | |
353 | GO_STATE(RM4_NON_OP_DUP) ; | |
354 | break ; | |
355 | } | |
356 | /*RM34c*/ | |
357 | else if (cmd == RM_VALID_CLAIM) { | |
358 | rmt_new_dup_actions(smc) ; | |
359 | GO_STATE(RM4_NON_OP_DUP) ; | |
360 | break ; | |
361 | } | |
362 | /*RM36*/ | |
363 | else if (cmd == RM_TIMEOUT_T_STUCK && | |
364 | smc->r.rm_join && smc->r.bn_flag) { | |
365 | GO_STATE(RM6_DIRECTED) ; | |
366 | break ; | |
367 | } | |
368 | break ; | |
369 | case ACTIONS(RM4_NON_OP_DUP) : | |
370 | start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE); | |
371 | start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ; | |
372 | start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; | |
373 | sm_mac_check_beacon_claim(smc) ; | |
5671e8c1 | 374 | DB_RMTN(1, "RMT : RM4_NON_OP_DUP"); |
1da177e4 LT |
375 | ACTIONS_DONE() ; |
376 | break ; | |
377 | case RM4_NON_OP_DUP : | |
378 | if (cmd == RM_TIMEOUT_POLL) { | |
379 | start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); | |
380 | sm_mac_check_beacon_claim(smc) ; | |
381 | break ; | |
382 | } | |
383 | /*RM41*/ | |
384 | if (!smc->r.da_flag) { | |
385 | GO_STATE(RM1_NON_OP) ; | |
386 | break ; | |
387 | } | |
388 | /*RM44a*/ | |
389 | else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && | |
390 | smc->r.bn_flag) { | |
391 | smc->r.bn_flag = FALSE ; | |
392 | } | |
393 | /*RM44b*/ | |
394 | else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) { | |
395 | int tx ; | |
396 | /* | |
397 | * set bn_flag only if in state T4 or T5: | |
398 | * only if we're the beaconer should we start the | |
399 | * trace ! | |
400 | */ | |
401 | if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) { | |
5671e8c1 | 402 | DB_RMTN(2, "RMT : NOPDUP && TRT_EXPIRED && T4/T5"); |
1da177e4 LT |
403 | smc->r.bn_flag = TRUE ; |
404 | /* | |
405 | * If one of the upstream stations beaconed | |
406 | * and the link to the upstream neighbor is | |
407 | * lost we need to restart the stuck timer to | |
408 | * check the "stuck beacon" condition. | |
409 | */ | |
410 | start_rmt_timer1(smc,smc->s.rmt_t_stuck, | |
411 | RM_TIMEOUT_T_STUCK) ; | |
412 | } | |
413 | /* | |
414 | * We do NOT need to clear smc->r.bn_flag in case of | |
415 | * not being in state T4 or T5, because the flag | |
416 | * must be cleared in order to get in this condition. | |
417 | */ | |
418 | ||
5671e8c1 JP |
419 | DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)", |
420 | tx, smc->r.bn_flag); | |
1da177e4 LT |
421 | } |
422 | /*RM44c*/ | |
423 | else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) { | |
424 | rmt_dup_actions(smc) ; | |
425 | } | |
426 | /*RM45*/ | |
427 | else if (cmd == RM_RING_OP) { | |
428 | smc->r.no_flag = FALSE ; | |
429 | GO_STATE(RM5_RING_OP_DUP) ; | |
430 | break ; | |
431 | } | |
432 | /*RM46*/ | |
433 | else if (cmd == RM_TIMEOUT_T_STUCK && | |
434 | smc->r.rm_join && smc->r.bn_flag) { | |
435 | GO_STATE(RM6_DIRECTED) ; | |
436 | break ; | |
437 | } | |
438 | break ; | |
439 | case ACTIONS(RM5_RING_OP_DUP) : | |
440 | stop_rmt_timer0(smc) ; | |
441 | stop_rmt_timer1(smc) ; | |
442 | stop_rmt_timer2(smc) ; | |
5671e8c1 | 443 | DB_RMTN(1, "RMT : RM5_RING_OP_DUP"); |
1da177e4 LT |
444 | ACTIONS_DONE() ; |
445 | break; | |
446 | case RM5_RING_OP_DUP : | |
447 | /*RM52*/ | |
448 | if (smc->r.dup_addr_test == DA_PASSED) { | |
449 | smc->r.da_flag = FALSE ; | |
450 | GO_STATE(RM2_RING_OP) ; | |
451 | break ; | |
452 | } | |
453 | /*RM54*/ | |
454 | else if (cmd == RM_RING_NON_OP) { | |
455 | smc->r.jm_flag = FALSE ; | |
456 | smc->r.bn_flag = FALSE ; | |
457 | GO_STATE(RM4_NON_OP_DUP) ; | |
458 | break ; | |
459 | } | |
460 | break ; | |
461 | case ACTIONS(RM6_DIRECTED) : | |
462 | start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ; | |
463 | stop_rmt_timer1(smc) ; | |
464 | start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; | |
465 | sm_ma_control(smc,MA_DIRECTED) ; | |
466 | RS_SET(smc,RS_BEACON) ; | |
5671e8c1 | 467 | DB_RMTN(1, "RMT : RM6_DIRECTED"); |
1da177e4 LT |
468 | ACTIONS_DONE() ; |
469 | break ; | |
470 | case RM6_DIRECTED : | |
471 | /*RM63*/ | |
472 | if (cmd == RM_TIMEOUT_POLL) { | |
473 | start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); | |
474 | sm_mac_check_beacon_claim(smc) ; | |
475 | #ifndef SUPERNET_3 | |
476 | /* Because of problems with the Supernet II chip set | |
477 | * sending of Directed Beacon will stop after 165ms | |
478 | * therefore restart_trt_for_dbcn(smc) will be called | |
479 | * to prevent this. | |
480 | */ | |
481 | restart_trt_for_dbcn(smc) ; | |
482 | #endif /*SUPERNET_3*/ | |
483 | break ; | |
484 | } | |
485 | if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && | |
486 | !smc->r.da_flag) { | |
487 | smc->r.bn_flag = FALSE ; | |
488 | GO_STATE(RM3_DETECT) ; | |
489 | break ; | |
490 | } | |
491 | /*RM64*/ | |
492 | else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && | |
493 | smc->r.da_flag) { | |
494 | smc->r.bn_flag = FALSE ; | |
495 | GO_STATE(RM4_NON_OP_DUP) ; | |
496 | break ; | |
497 | } | |
498 | /*RM67*/ | |
499 | else if (cmd == RM_TIMEOUT_T_DIRECT) { | |
500 | GO_STATE(RM7_TRACE) ; | |
501 | break ; | |
502 | } | |
503 | break ; | |
504 | case ACTIONS(RM7_TRACE) : | |
505 | stop_rmt_timer0(smc) ; | |
506 | stop_rmt_timer1(smc) ; | |
507 | stop_rmt_timer2(smc) ; | |
508 | smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ; | |
509 | queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ; | |
5671e8c1 | 510 | DB_RMTN(1, "RMT : RM7_TRACE"); |
1da177e4 LT |
511 | ACTIONS_DONE() ; |
512 | break ; | |
513 | case RM7_TRACE : | |
514 | break ; | |
515 | default: | |
516 | SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ; | |
517 | break; | |
518 | } | |
519 | } | |
520 | ||
521 | /* | |
522 | * (jd) RMT duplicate address actions | |
523 | * leave the ring or reinsert just as configured | |
524 | */ | |
525 | static void rmt_dup_actions(struct s_smc *smc) | |
526 | { | |
527 | if (smc->r.jm_flag) { | |
528 | } | |
529 | else { | |
530 | if (smc->s.rmt_dup_mac_behavior) { | |
531 | SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ; | |
532 | rmt_reinsert_actions(smc) ; | |
533 | } | |
534 | else { | |
535 | SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ; | |
536 | rmt_leave_actions(smc) ; | |
537 | } | |
538 | } | |
539 | } | |
540 | ||
541 | /* | |
542 | * Reconnect to the Ring | |
543 | */ | |
544 | static void rmt_reinsert_actions(struct s_smc *smc) | |
545 | { | |
546 | queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; | |
547 | queue_event(smc,EVENT_ECM,EC_CONNECT) ; | |
548 | } | |
549 | ||
550 | /* | |
551 | * duplicate address detected | |
552 | */ | |
553 | static void rmt_new_dup_actions(struct s_smc *smc) | |
554 | { | |
555 | smc->r.da_flag = TRUE ; | |
556 | smc->r.bn_flag = FALSE ; | |
557 | smc->r.jm_flag = FALSE ; | |
558 | /* | |
559 | * we have three options : change address, jam or leave | |
560 | * we leave the ring as default | |
561 | * Optionally it's possible to reinsert after leaving the Ring | |
562 | * but this will not conform with SMT Spec. | |
563 | */ | |
564 | if (smc->s.rmt_dup_mac_behavior) { | |
565 | SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ; | |
566 | rmt_reinsert_actions(smc) ; | |
567 | } | |
568 | else { | |
569 | SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ; | |
570 | rmt_leave_actions(smc) ; | |
571 | } | |
572 | } | |
573 | ||
574 | ||
575 | /* | |
576 | * leave the ring | |
577 | */ | |
578 | static void rmt_leave_actions(struct s_smc *smc) | |
579 | { | |
580 | queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; | |
581 | /* | |
582 | * Note: Do NOT try again later. (with please reconnect) | |
583 | * The station must be left from the ring! | |
584 | */ | |
585 | } | |
586 | ||
587 | /* | |
588 | * SMT timer interface | |
589 | * start RMT timer 0 | |
590 | */ | |
591 | static void start_rmt_timer0(struct s_smc *smc, u_long value, int event) | |
592 | { | |
593 | smc->r.timer0_exp = FALSE ; /* clear timer event flag */ | |
594 | smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event)); | |
595 | } | |
596 | ||
597 | /* | |
598 | * SMT timer interface | |
599 | * start RMT timer 1 | |
600 | */ | |
601 | static void start_rmt_timer1(struct s_smc *smc, u_long value, int event) | |
602 | { | |
603 | smc->r.timer1_exp = FALSE ; /* clear timer event flag */ | |
604 | smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event)); | |
605 | } | |
606 | ||
607 | /* | |
608 | * SMT timer interface | |
609 | * start RMT timer 2 | |
610 | */ | |
611 | static void start_rmt_timer2(struct s_smc *smc, u_long value, int event) | |
612 | { | |
613 | smc->r.timer2_exp = FALSE ; /* clear timer event flag */ | |
614 | smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event)); | |
615 | } | |
616 | ||
617 | /* | |
618 | * SMT timer interface | |
619 | * stop RMT timer 0 | |
620 | */ | |
621 | static void stop_rmt_timer0(struct s_smc *smc) | |
622 | { | |
623 | if (smc->r.rmt_timer0.tm_active) | |
624 | smt_timer_stop(smc,&smc->r.rmt_timer0) ; | |
625 | } | |
626 | ||
627 | /* | |
628 | * SMT timer interface | |
629 | * stop RMT timer 1 | |
630 | */ | |
631 | static void stop_rmt_timer1(struct s_smc *smc) | |
632 | { | |
633 | if (smc->r.rmt_timer1.tm_active) | |
634 | smt_timer_stop(smc,&smc->r.rmt_timer1) ; | |
635 | } | |
636 | ||
637 | /* | |
638 | * SMT timer interface | |
639 | * stop RMT timer 2 | |
640 | */ | |
641 | static void stop_rmt_timer2(struct s_smc *smc) | |
642 | { | |
643 | if (smc->r.rmt_timer2.tm_active) | |
644 | smt_timer_stop(smc,&smc->r.rmt_timer2) ; | |
645 | } | |
646 |