rmt.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:16k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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