rmt.c 16 KB

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