rmt.c 16 KB

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