1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include "h/types.h"
46#include "h/fddi.h"
47#include "h/smc.h"
48
49#define KERNEL
50#include "h/smtstate.h"
51
52#ifndef lint
53static const char ID_sccs[] = "@(#)rmt.c 2.13 99/07/02 (C) SK " ;
54#endif
55
56
57
58
59#define AFLAG 0x10
60#define GO_STATE(x) (smc->mib.m[MAC0].fddiMACRMTState = (x)|AFLAG)
61#define ACTIONS_DONE() (smc->mib.m[MAC0].fddiMACRMTState &= ~AFLAG)
62#define ACTIONS(x) (x|AFLAG)
63
64#define RM0_ISOLATED 0
65#define RM1_NON_OP 1
66#define RM2_RING_OP 2
67#define RM3_DETECT 3
68#define RM4_NON_OP_DUP 4
69#define RM5_RING_OP_DUP 5
70#define RM6_DIRECTED 6
71#define RM7_TRACE 7
72
73
74
75
76static const char * const rmt_states[] = {
77 "RM0_ISOLATED","RM1_NON_OP","RM2_RING_OP","RM3_DETECT",
78 "RM4_NON_OP_DUP","RM5_RING_OP_DUP","RM6_DIRECTED",
79 "RM7_TRACE"
80} ;
81
82
83
84
85static const char * const rmt_events[] = {
86 "NONE","RM_RING_OP","RM_RING_NON_OP","RM_MY_BEACON",
87 "RM_OTHER_BEACON","RM_MY_CLAIM","RM_TRT_EXP","RM_VALID_CLAIM",
88 "RM_JOIN","RM_LOOP","RM_DUP_ADDR","RM_ENABLE_FLAG",
89 "RM_TIMEOUT_NON_OP","RM_TIMEOUT_T_STUCK",
90 "RM_TIMEOUT_ANNOUNCE","RM_TIMEOUT_T_DIRECT",
91 "RM_TIMEOUT_D_MAX","RM_TIMEOUT_POLL","RM_TX_STATE_CHANGE"
92} ;
93
94
95
96
97
98
99
100
101
102
103static void rmt_fsm(struct s_smc *smc, int cmd);
104static void start_rmt_timer0(struct s_smc *smc, u_long value, int event);
105static void start_rmt_timer1(struct s_smc *smc, u_long value, int event);
106static void start_rmt_timer2(struct s_smc *smc, u_long value, int event);
107static void stop_rmt_timer0(struct s_smc *smc);
108static void stop_rmt_timer1(struct s_smc *smc);
109static void stop_rmt_timer2(struct s_smc *smc);
110static void rmt_dup_actions(struct s_smc *smc);
111static void rmt_reinsert_actions(struct s_smc *smc);
112static void rmt_leave_actions(struct s_smc *smc);
113static void rmt_new_dup_actions(struct s_smc *smc);
114
115#ifndef SUPERNET_3
116extern void restart_trt_for_dbcn() ;
117#endif
118
119
120
121
122
123void rmt_init(struct s_smc *smc)
124{
125 smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ;
126 smc->r.dup_addr_test = DA_NONE ;
127 smc->r.da_flag = 0 ;
128 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
129 smc->r.sm_ma_avail = FALSE ;
130 smc->r.loop_avail = 0 ;
131 smc->r.bn_flag = 0 ;
132 smc->r.jm_flag = 0 ;
133 smc->r.no_flag = TRUE ;
134}
135
136
137
138
139
140
141
142
143
144
145void rmt(struct s_smc *smc, int event)
146{
147 int state ;
148
149 do {
150 DB_RMT("RMT : state %s%s event %s",
151 smc->mib.m[MAC0].fddiMACRMTState & AFLAG ? "ACTIONS " : "",
152 rmt_states[smc->mib.m[MAC0].fddiMACRMTState & ~AFLAG],
153 rmt_events[event]);
154 state = smc->mib.m[MAC0].fddiMACRMTState ;
155 rmt_fsm(smc,event) ;
156 event = 0 ;
157 } while (state != smc->mib.m[MAC0].fddiMACRMTState) ;
158 rmt_state_change(smc,(int)smc->mib.m[MAC0].fddiMACRMTState) ;
159}
160
161
162
163
164static void rmt_fsm(struct s_smc *smc, int cmd)
165{
166
167
168
169 if (!smc->r.rm_join && !smc->r.rm_loop &&
170 smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) &&
171 smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) {
172 RS_SET(smc,RS_NORINGOP) ;
173 rmt_indication(smc,0) ;
174 GO_STATE(RM0_ISOLATED) ;
175 return ;
176 }
177
178 switch(smc->mib.m[MAC0].fddiMACRMTState) {
179 case ACTIONS(RM0_ISOLATED) :
180 stop_rmt_timer0(smc) ;
181 stop_rmt_timer1(smc) ;
182 stop_rmt_timer2(smc) ;
183
184
185
186
187 sm_ma_control(smc,MA_OFFLINE) ;
188 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
189 smc->r.loop_avail = FALSE ;
190 smc->r.sm_ma_avail = FALSE ;
191 smc->r.no_flag = TRUE ;
192 DB_RMTN(1, "RMT : ISOLATED");
193 ACTIONS_DONE() ;
194 break ;
195 case RM0_ISOLATED :
196
197 if (smc->r.rm_join || smc->r.rm_loop) {
198
199
200
201
202
203
204 sm_ma_control(smc,MA_RESET) ;
205 GO_STATE(RM1_NON_OP) ;
206 break ;
207 }
208 break ;
209 case ACTIONS(RM1_NON_OP) :
210 start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ;
211 stop_rmt_timer1(smc) ;
212 stop_rmt_timer2(smc) ;
213 sm_ma_control(smc,MA_BEACON) ;
214 DB_RMTN(1, "RMT : RING DOWN");
215 RS_SET(smc,RS_NORINGOP) ;
216 smc->r.sm_ma_avail = FALSE ;
217 rmt_indication(smc,0) ;
218 ACTIONS_DONE() ;
219 break ;
220 case RM1_NON_OP :
221
222 if (cmd == RM_RING_OP) {
223 RS_SET(smc,RS_RINGOPCHANGE) ;
224 GO_STATE(RM2_RING_OP) ;
225 break ;
226 }
227
228 else if (cmd == RM_TIMEOUT_NON_OP) {
229 smc->r.bn_flag = FALSE ;
230 smc->r.no_flag = TRUE ;
231 GO_STATE(RM3_DETECT) ;
232 break ;
233 }
234 break ;
235 case ACTIONS(RM2_RING_OP) :
236 stop_rmt_timer0(smc) ;
237 stop_rmt_timer1(smc) ;
238 stop_rmt_timer2(smc) ;
239 smc->r.no_flag = FALSE ;
240 if (smc->r.rm_loop)
241 smc->r.loop_avail = TRUE ;
242 if (smc->r.rm_join) {
243 smc->r.sm_ma_avail = TRUE ;
244 if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
245 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
246 else
247 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
248 }
249 DB_RMTN(1, "RMT : RING UP");
250 RS_CLEAR(smc,RS_NORINGOP) ;
251 RS_SET(smc,RS_RINGOPCHANGE) ;
252 rmt_indication(smc,1) ;
253 smt_stat_counter(smc,0) ;
254 ACTIONS_DONE() ;
255 break ;
256 case RM2_RING_OP :
257
258 if (cmd == RM_RING_NON_OP) {
259 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
260 smc->r.loop_avail = FALSE ;
261 RS_SET(smc,RS_RINGOPCHANGE) ;
262 GO_STATE(RM1_NON_OP) ;
263 break ;
264 }
265
266 else if (cmd == RM_ENABLE_FLAG) {
267 if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
268 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
269 else
270 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
271 }
272
273 else if (smc->r.dup_addr_test == DA_FAILED) {
274 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
275 smc->r.loop_avail = FALSE ;
276 smc->r.da_flag = TRUE ;
277 GO_STATE(RM5_RING_OP_DUP) ;
278 break ;
279 }
280 break ;
281 case ACTIONS(RM3_DETECT) :
282 start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ;
283 start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
284 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
285 sm_mac_check_beacon_claim(smc) ;
286 DB_RMTN(1, "RMT : RM3_DETECT");
287 ACTIONS_DONE() ;
288 break ;
289 case RM3_DETECT :
290 if (cmd == RM_TIMEOUT_POLL) {
291 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
292 sm_mac_check_beacon_claim(smc) ;
293 break ;
294 }
295 if (cmd == RM_TIMEOUT_D_MAX) {
296 smc->r.timer0_exp = TRUE ;
297 }
298
299
300
301
302
303
304 if (cmd == RM_TX_STATE_CHANGE) {
305 start_rmt_timer0(smc,
306 smc->s.mac_d_max*2,
307 RM_TIMEOUT_D_MAX) ;
308 }
309
310 if (cmd == RM_RING_OP) {
311 GO_STATE(RM2_RING_OP) ;
312 break ;
313 }
314
315 else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON)
316 && smc->r.bn_flag) {
317 smc->r.bn_flag = FALSE ;
318 }
319
320 else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
321 int tx ;
322
323
324
325
326
327 if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
328 DB_RMTN(2, "RMT : DETECT && TRT_EXPIRED && T4/T5");
329 smc->r.bn_flag = TRUE ;
330
331
332
333
334
335
336 start_rmt_timer1(smc,smc->s.rmt_t_stuck,
337 RM_TIMEOUT_T_STUCK) ;
338 }
339
340
341
342
343
344
345 DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)",
346 tx, smc->r.bn_flag);
347 }
348
349 else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) {
350 rmt_new_dup_actions(smc) ;
351 GO_STATE(RM4_NON_OP_DUP) ;
352 break ;
353 }
354
355 else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) {
356 rmt_new_dup_actions(smc) ;
357 GO_STATE(RM4_NON_OP_DUP) ;
358 break ;
359 }
360
361 else if (cmd == RM_VALID_CLAIM) {
362 rmt_new_dup_actions(smc) ;
363 GO_STATE(RM4_NON_OP_DUP) ;
364 break ;
365 }
366
367 else if (cmd == RM_TIMEOUT_T_STUCK &&
368 smc->r.rm_join && smc->r.bn_flag) {
369 GO_STATE(RM6_DIRECTED) ;
370 break ;
371 }
372 break ;
373 case ACTIONS(RM4_NON_OP_DUP) :
374 start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE);
375 start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
376 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
377 sm_mac_check_beacon_claim(smc) ;
378 DB_RMTN(1, "RMT : RM4_NON_OP_DUP");
379 ACTIONS_DONE() ;
380 break ;
381 case RM4_NON_OP_DUP :
382 if (cmd == RM_TIMEOUT_POLL) {
383 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
384 sm_mac_check_beacon_claim(smc) ;
385 break ;
386 }
387
388 if (!smc->r.da_flag) {
389 GO_STATE(RM1_NON_OP) ;
390 break ;
391 }
392
393 else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
394 smc->r.bn_flag) {
395 smc->r.bn_flag = FALSE ;
396 }
397
398 else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
399 int tx ;
400
401
402
403
404
405 if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
406 DB_RMTN(2, "RMT : NOPDUP && TRT_EXPIRED && T4/T5");
407 smc->r.bn_flag = TRUE ;
408
409
410
411
412
413
414 start_rmt_timer1(smc,smc->s.rmt_t_stuck,
415 RM_TIMEOUT_T_STUCK) ;
416 }
417
418
419
420
421
422
423 DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)",
424 tx, smc->r.bn_flag);
425 }
426
427 else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) {
428 rmt_dup_actions(smc) ;
429 }
430
431 else if (cmd == RM_RING_OP) {
432 smc->r.no_flag = FALSE ;
433 GO_STATE(RM5_RING_OP_DUP) ;
434 break ;
435 }
436
437 else if (cmd == RM_TIMEOUT_T_STUCK &&
438 smc->r.rm_join && smc->r.bn_flag) {
439 GO_STATE(RM6_DIRECTED) ;
440 break ;
441 }
442 break ;
443 case ACTIONS(RM5_RING_OP_DUP) :
444 stop_rmt_timer0(smc) ;
445 stop_rmt_timer1(smc) ;
446 stop_rmt_timer2(smc) ;
447 DB_RMTN(1, "RMT : RM5_RING_OP_DUP");
448 ACTIONS_DONE() ;
449 break;
450 case RM5_RING_OP_DUP :
451
452 if (smc->r.dup_addr_test == DA_PASSED) {
453 smc->r.da_flag = FALSE ;
454 GO_STATE(RM2_RING_OP) ;
455 break ;
456 }
457
458 else if (cmd == RM_RING_NON_OP) {
459 smc->r.jm_flag = FALSE ;
460 smc->r.bn_flag = FALSE ;
461 GO_STATE(RM4_NON_OP_DUP) ;
462 break ;
463 }
464 break ;
465 case ACTIONS(RM6_DIRECTED) :
466 start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ;
467 stop_rmt_timer1(smc) ;
468 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
469 sm_ma_control(smc,MA_DIRECTED) ;
470 RS_SET(smc,RS_BEACON) ;
471 DB_RMTN(1, "RMT : RM6_DIRECTED");
472 ACTIONS_DONE() ;
473 break ;
474 case RM6_DIRECTED :
475
476 if (cmd == RM_TIMEOUT_POLL) {
477 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
478 sm_mac_check_beacon_claim(smc) ;
479#ifndef SUPERNET_3
480
481
482
483
484
485 restart_trt_for_dbcn(smc) ;
486#endif
487 break ;
488 }
489 if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
490 !smc->r.da_flag) {
491 smc->r.bn_flag = FALSE ;
492 GO_STATE(RM3_DETECT) ;
493 break ;
494 }
495
496 else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
497 smc->r.da_flag) {
498 smc->r.bn_flag = FALSE ;
499 GO_STATE(RM4_NON_OP_DUP) ;
500 break ;
501 }
502
503 else if (cmd == RM_TIMEOUT_T_DIRECT) {
504 GO_STATE(RM7_TRACE) ;
505 break ;
506 }
507 break ;
508 case ACTIONS(RM7_TRACE) :
509 stop_rmt_timer0(smc) ;
510 stop_rmt_timer1(smc) ;
511 stop_rmt_timer2(smc) ;
512 smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ;
513 queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
514 DB_RMTN(1, "RMT : RM7_TRACE");
515 ACTIONS_DONE() ;
516 break ;
517 case RM7_TRACE :
518 break ;
519 default:
520 SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ;
521 break;
522 }
523}
524
525
526
527
528
529static void rmt_dup_actions(struct s_smc *smc)
530{
531 if (smc->r.jm_flag) {
532 }
533 else {
534 if (smc->s.rmt_dup_mac_behavior) {
535 SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
536 rmt_reinsert_actions(smc) ;
537 }
538 else {
539 SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
540 rmt_leave_actions(smc) ;
541 }
542 }
543}
544
545
546
547
548static void rmt_reinsert_actions(struct s_smc *smc)
549{
550 queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
551 queue_event(smc,EVENT_ECM,EC_CONNECT) ;
552}
553
554
555
556
557static void rmt_new_dup_actions(struct s_smc *smc)
558{
559 smc->r.da_flag = TRUE ;
560 smc->r.bn_flag = FALSE ;
561 smc->r.jm_flag = FALSE ;
562
563
564
565
566
567
568 if (smc->s.rmt_dup_mac_behavior) {
569 SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
570 rmt_reinsert_actions(smc) ;
571 }
572 else {
573 SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
574 rmt_leave_actions(smc) ;
575 }
576}
577
578
579
580
581
582static void rmt_leave_actions(struct s_smc *smc)
583{
584 queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
585
586
587
588
589}
590
591
592
593
594
595static void start_rmt_timer0(struct s_smc *smc, u_long value, int event)
596{
597 smc->r.timer0_exp = FALSE ;
598 smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event));
599}
600
601
602
603
604
605static void start_rmt_timer1(struct s_smc *smc, u_long value, int event)
606{
607 smc->r.timer1_exp = FALSE ;
608 smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event));
609}
610
611
612
613
614
615static void start_rmt_timer2(struct s_smc *smc, u_long value, int event)
616{
617 smc->r.timer2_exp = FALSE ;
618 smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event));
619}
620
621
622
623
624
625static void stop_rmt_timer0(struct s_smc *smc)
626{
627 if (smc->r.rmt_timer0.tm_active)
628 smt_timer_stop(smc,&smc->r.rmt_timer0) ;
629}
630
631
632
633
634
635static void stop_rmt_timer1(struct s_smc *smc)
636{
637 if (smc->r.rmt_timer1.tm_active)
638 smt_timer_stop(smc,&smc->r.rmt_timer1) ;
639}
640
641
642
643
644
645static void stop_rmt_timer2(struct s_smc *smc)
646{
647 if (smc->r.rmt_timer2.tm_active)
648 smt_timer_stop(smc,&smc->r.rmt_timer2) ;
649}
650
651