rmt.c 16 KB

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