Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /******************************************************************************
0003  *
0004  *  (C)Copyright 1998,1999 SysKonnect,
0005  *  a business unit of Schneider & Koch & Co. Datensysteme GmbH.
0006  *
0007  *  See the file "skfddi.c" for further information.
0008  *
0009  *  The information in this file is provided "AS IS" without warranty.
0010  *
0011  ******************************************************************************/
0012 
0013 /*
0014     SMT RMT
0015     Ring Management
0016 */
0017 
0018 /*
0019  * Hardware independent state machine implemantation
0020  * The following external SMT functions are referenced :
0021  *
0022  *      queue_event()
0023  *      smt_timer_start()
0024  *      smt_timer_stop()
0025  *
0026  *  The following external HW dependent functions are referenced :
0027  *      sm_ma_control()
0028  *      sm_mac_check_beacon_claim()
0029  *
0030  *  The following HW dependent events are required :
0031  *      RM_RING_OP
0032  *      RM_RING_NON_OP
0033  *      RM_MY_BEACON
0034  *      RM_OTHER_BEACON
0035  *      RM_MY_CLAIM
0036  *      RM_TRT_EXP
0037  *      RM_VALID_CLAIM
0038  *
0039  */
0040 
0041 #include "h/types.h"
0042 #include "h/fddi.h"
0043 #include "h/smc.h"
0044 
0045 #define KERNEL
0046 #include "h/smtstate.h"
0047 
0048 /*
0049  * FSM Macros
0050  */
0051 #define AFLAG   0x10
0052 #define GO_STATE(x) (smc->mib.m[MAC0].fddiMACRMTState = (x)|AFLAG)
0053 #define ACTIONS_DONE()  (smc->mib.m[MAC0].fddiMACRMTState &= ~AFLAG)
0054 #define ACTIONS(x)  (x|AFLAG)
0055 
0056 #define RM0_ISOLATED    0
0057 #define RM1_NON_OP  1       /* not operational */
0058 #define RM2_RING_OP 2       /* ring operational */
0059 #define RM3_DETECT  3       /* detect dupl addresses */
0060 #define RM4_NON_OP_DUP  4       /* dupl. addr detected */
0061 #define RM5_RING_OP_DUP 5       /* ring oper. with dupl. addr */
0062 #define RM6_DIRECTED    6       /* sending directed beacons */
0063 #define RM7_TRACE   7       /* trace initiated */
0064 
0065 /*
0066  * symbolic state names
0067  */
0068 static const char * const rmt_states[] = {
0069     "RM0_ISOLATED","RM1_NON_OP","RM2_RING_OP","RM3_DETECT",
0070     "RM4_NON_OP_DUP","RM5_RING_OP_DUP","RM6_DIRECTED",
0071     "RM7_TRACE"
0072 } ;
0073 
0074 /*
0075  * symbolic event names
0076  */
0077 static const char * const rmt_events[] = {
0078     "NONE","RM_RING_OP","RM_RING_NON_OP","RM_MY_BEACON",
0079     "RM_OTHER_BEACON","RM_MY_CLAIM","RM_TRT_EXP","RM_VALID_CLAIM",
0080     "RM_JOIN","RM_LOOP","RM_DUP_ADDR","RM_ENABLE_FLAG",
0081     "RM_TIMEOUT_NON_OP","RM_TIMEOUT_T_STUCK",
0082     "RM_TIMEOUT_ANNOUNCE","RM_TIMEOUT_T_DIRECT",
0083     "RM_TIMEOUT_D_MAX","RM_TIMEOUT_POLL","RM_TX_STATE_CHANGE"
0084 } ;
0085 
0086 /*
0087  * Globals
0088  * in struct s_rmt
0089  */
0090 
0091 
0092 /*
0093  * function declarations
0094  */
0095 static void rmt_fsm(struct s_smc *smc, int cmd);
0096 static void start_rmt_timer0(struct s_smc *smc, u_long value, int event);
0097 static void start_rmt_timer1(struct s_smc *smc, u_long value, int event);
0098 static void start_rmt_timer2(struct s_smc *smc, u_long value, int event);
0099 static void stop_rmt_timer0(struct s_smc *smc);
0100 static void stop_rmt_timer1(struct s_smc *smc);
0101 static void stop_rmt_timer2(struct s_smc *smc);
0102 static void rmt_dup_actions(struct s_smc *smc);
0103 static void rmt_reinsert_actions(struct s_smc *smc);
0104 static void rmt_leave_actions(struct s_smc *smc);
0105 static void rmt_new_dup_actions(struct s_smc *smc);
0106 
0107 #ifndef SUPERNET_3
0108 extern void restart_trt_for_dbcn() ;
0109 #endif /*SUPERNET_3*/
0110 
0111 /*
0112     init RMT state machine
0113     clear all RMT vars and flags
0114 */
0115 void rmt_init(struct s_smc *smc)
0116 {
0117     smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ;
0118     smc->r.dup_addr_test = DA_NONE ;
0119     smc->r.da_flag = 0 ;
0120     smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
0121     smc->r.sm_ma_avail = FALSE ;
0122     smc->r.loop_avail = 0 ;
0123     smc->r.bn_flag = 0 ;
0124     smc->r.jm_flag = 0 ;
0125     smc->r.no_flag = TRUE ;
0126 }
0127 
0128 /*
0129     RMT state machine
0130     called by dispatcher
0131 
0132     do
0133         display state change
0134         process event
0135     until SM is stable
0136 */
0137 void rmt(struct s_smc *smc, int event)
0138 {
0139     int state ;
0140 
0141     do {
0142         DB_RMT("RMT : state %s%s event %s",
0143                smc->mib.m[MAC0].fddiMACRMTState & AFLAG ? "ACTIONS " : "",
0144                rmt_states[smc->mib.m[MAC0].fddiMACRMTState & ~AFLAG],
0145                rmt_events[event]);
0146         state = smc->mib.m[MAC0].fddiMACRMTState ;
0147         rmt_fsm(smc,event) ;
0148         event = 0 ;
0149     } while (state != smc->mib.m[MAC0].fddiMACRMTState) ;
0150     rmt_state_change(smc,(int)smc->mib.m[MAC0].fddiMACRMTState) ;
0151 }
0152 
0153 /*
0154     process RMT event
0155 */
0156 static void rmt_fsm(struct s_smc *smc, int cmd)
0157 {
0158     /*
0159      * RM00-RM70 : from all states
0160      */
0161     if (!smc->r.rm_join && !smc->r.rm_loop &&
0162         smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) &&
0163         smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) {
0164         RS_SET(smc,RS_NORINGOP) ;
0165         rmt_indication(smc,0) ;
0166         GO_STATE(RM0_ISOLATED) ;
0167         return ;
0168     }
0169 
0170     switch(smc->mib.m[MAC0].fddiMACRMTState) {
0171     case ACTIONS(RM0_ISOLATED) :
0172         stop_rmt_timer0(smc) ;
0173         stop_rmt_timer1(smc) ;
0174         stop_rmt_timer2(smc) ;
0175 
0176         /*
0177          * Disable MAC.
0178          */
0179         sm_ma_control(smc,MA_OFFLINE) ;
0180         smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
0181         smc->r.loop_avail = FALSE ;
0182         smc->r.sm_ma_avail = FALSE ;
0183         smc->r.no_flag = TRUE ;
0184         DB_RMTN(1, "RMT : ISOLATED");
0185         ACTIONS_DONE() ;
0186         break ;
0187     case RM0_ISOLATED :
0188         /*RM01*/
0189         if (smc->r.rm_join || smc->r.rm_loop) {
0190             /*
0191              * According to the standard the MAC must be reset
0192              * here. The FORMAC will be initialized and Claim
0193              * and Beacon Frames will be uploaded to the MAC.
0194              * So any change of Treq will take effect NOW.
0195              */
0196             sm_ma_control(smc,MA_RESET) ;
0197             GO_STATE(RM1_NON_OP) ;
0198             break ;
0199         }
0200         break ;
0201     case ACTIONS(RM1_NON_OP) :
0202         start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ;
0203         stop_rmt_timer1(smc) ;
0204         stop_rmt_timer2(smc) ;
0205         sm_ma_control(smc,MA_BEACON) ;
0206         DB_RMTN(1, "RMT : RING DOWN");
0207         RS_SET(smc,RS_NORINGOP) ;
0208         smc->r.sm_ma_avail = FALSE ;
0209         rmt_indication(smc,0) ;
0210         ACTIONS_DONE() ;
0211         break ;
0212     case RM1_NON_OP :
0213         /*RM12*/
0214         if (cmd == RM_RING_OP) {
0215             RS_SET(smc,RS_RINGOPCHANGE) ;
0216             GO_STATE(RM2_RING_OP) ;
0217             break ;
0218         }
0219         /*RM13*/
0220         else if (cmd == RM_TIMEOUT_NON_OP) {
0221             smc->r.bn_flag = FALSE ;
0222             smc->r.no_flag = TRUE ;
0223             GO_STATE(RM3_DETECT) ;
0224             break ;
0225         }
0226         break ;
0227     case ACTIONS(RM2_RING_OP) :
0228         stop_rmt_timer0(smc) ;
0229         stop_rmt_timer1(smc) ;
0230         stop_rmt_timer2(smc) ;
0231         smc->r.no_flag = FALSE ;
0232         if (smc->r.rm_loop)
0233             smc->r.loop_avail = TRUE ;
0234         if (smc->r.rm_join) {
0235             smc->r.sm_ma_avail = TRUE ;
0236             if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
0237             smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
0238                 else
0239             smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
0240         }
0241         DB_RMTN(1, "RMT : RING UP");
0242         RS_CLEAR(smc,RS_NORINGOP) ;
0243         RS_SET(smc,RS_RINGOPCHANGE) ;
0244         rmt_indication(smc,1) ;
0245         smt_stat_counter(smc,0) ;
0246         ACTIONS_DONE() ;
0247         break ;
0248     case RM2_RING_OP :
0249         /*RM21*/
0250         if (cmd == RM_RING_NON_OP) {
0251             smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
0252             smc->r.loop_avail = FALSE ;
0253             RS_SET(smc,RS_RINGOPCHANGE) ;
0254             GO_STATE(RM1_NON_OP) ;
0255             break ;
0256         }
0257         /*RM22a*/
0258         else if (cmd == RM_ENABLE_FLAG) {
0259             if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
0260             smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
0261                 else
0262             smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
0263         }
0264         /*RM25*/
0265         else if (smc->r.dup_addr_test == DA_FAILED) {
0266             smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
0267             smc->r.loop_avail = FALSE ;
0268             smc->r.da_flag = TRUE ;
0269             GO_STATE(RM5_RING_OP_DUP) ;
0270             break ;
0271         }
0272         break ;
0273     case ACTIONS(RM3_DETECT) :
0274         start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ;
0275         start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
0276         start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
0277         sm_mac_check_beacon_claim(smc) ;
0278         DB_RMTN(1, "RMT : RM3_DETECT");
0279         ACTIONS_DONE() ;
0280         break ;
0281     case RM3_DETECT :
0282         if (cmd == RM_TIMEOUT_POLL) {
0283             start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
0284             sm_mac_check_beacon_claim(smc) ;
0285             break ;
0286         }
0287         if (cmd == RM_TIMEOUT_D_MAX) {
0288             smc->r.timer0_exp = TRUE ;
0289         }
0290         /*
0291          *jd(22-Feb-1999)
0292          * We need a time ">= 2*mac_d_max" since we had finished
0293          * Claim or Beacon state. So we will restart timer0 at
0294          * every state change.
0295          */
0296         if (cmd == RM_TX_STATE_CHANGE) {
0297             start_rmt_timer0(smc,
0298                      smc->s.mac_d_max*2,
0299                      RM_TIMEOUT_D_MAX) ;
0300         }
0301         /*RM32*/
0302         if (cmd == RM_RING_OP) {
0303             GO_STATE(RM2_RING_OP) ;
0304             break ;
0305         }
0306         /*RM33a*/
0307         else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON)
0308             && smc->r.bn_flag) {
0309             smc->r.bn_flag = FALSE ;
0310         }
0311         /*RM33b*/
0312         else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
0313             int tx ;
0314             /*
0315              * set bn_flag only if in state T4 or T5:
0316              * only if we're the beaconer should we start the
0317              * trace !
0318              */
0319             if ((tx =  sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
0320             DB_RMTN(2, "RMT : DETECT && TRT_EXPIRED && T4/T5");
0321                 smc->r.bn_flag = TRUE ;
0322                 /*
0323                  * If one of the upstream stations beaconed
0324                  * and the link to the upstream neighbor is
0325                  * lost we need to restart the stuck timer to
0326                  * check the "stuck beacon" condition.
0327                  */
0328                 start_rmt_timer1(smc,smc->s.rmt_t_stuck,
0329                     RM_TIMEOUT_T_STUCK) ;
0330             }
0331             /*
0332              * We do NOT need to clear smc->r.bn_flag in case of
0333              * not being in state T4 or T5, because the flag
0334              * must be cleared in order to get in this condition.
0335              */
0336 
0337             DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)",
0338                 tx, smc->r.bn_flag);
0339         }
0340         /*RM34a*/
0341         else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) {
0342             rmt_new_dup_actions(smc) ;
0343             GO_STATE(RM4_NON_OP_DUP) ;
0344             break ;
0345         }
0346         /*RM34b*/
0347         else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) {
0348             rmt_new_dup_actions(smc) ;
0349             GO_STATE(RM4_NON_OP_DUP) ;
0350             break ;
0351         }
0352         /*RM34c*/
0353         else if (cmd == RM_VALID_CLAIM) {
0354             rmt_new_dup_actions(smc) ;
0355             GO_STATE(RM4_NON_OP_DUP) ;
0356             break ;
0357         }
0358         /*RM36*/
0359         else if (cmd == RM_TIMEOUT_T_STUCK &&
0360             smc->r.rm_join && smc->r.bn_flag) {
0361             GO_STATE(RM6_DIRECTED) ;
0362             break ;
0363         }
0364         break ;
0365     case ACTIONS(RM4_NON_OP_DUP) :
0366         start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE);
0367         start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
0368         start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
0369         sm_mac_check_beacon_claim(smc) ;
0370         DB_RMTN(1, "RMT : RM4_NON_OP_DUP");
0371         ACTIONS_DONE() ;
0372         break ;
0373     case RM4_NON_OP_DUP :
0374         if (cmd == RM_TIMEOUT_POLL) {
0375             start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
0376             sm_mac_check_beacon_claim(smc) ;
0377             break ;
0378         }
0379         /*RM41*/
0380         if (!smc->r.da_flag) {
0381             GO_STATE(RM1_NON_OP) ;
0382             break ;
0383         }
0384         /*RM44a*/
0385         else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
0386             smc->r.bn_flag) {
0387             smc->r.bn_flag = FALSE ;
0388         }
0389         /*RM44b*/
0390         else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
0391             int tx ;
0392             /*
0393              * set bn_flag only if in state T4 or T5:
0394              * only if we're the beaconer should we start the
0395              * trace !
0396              */
0397             if ((tx =  sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
0398             DB_RMTN(2, "RMT : NOPDUP && TRT_EXPIRED && T4/T5");
0399                 smc->r.bn_flag = TRUE ;
0400                 /*
0401                  * If one of the upstream stations beaconed
0402                  * and the link to the upstream neighbor is
0403                  * lost we need to restart the stuck timer to
0404                  * check the "stuck beacon" condition.
0405                  */
0406                 start_rmt_timer1(smc,smc->s.rmt_t_stuck,
0407                     RM_TIMEOUT_T_STUCK) ;
0408             }
0409             /*
0410              * We do NOT need to clear smc->r.bn_flag in case of
0411              * not being in state T4 or T5, because the flag
0412              * must be cleared in order to get in this condition.
0413              */
0414 
0415             DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)",
0416                 tx, smc->r.bn_flag);
0417         }
0418         /*RM44c*/
0419         else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) {
0420             rmt_dup_actions(smc) ;
0421         }
0422         /*RM45*/
0423         else if (cmd == RM_RING_OP) {
0424             smc->r.no_flag = FALSE ;
0425             GO_STATE(RM5_RING_OP_DUP) ;
0426             break ;
0427         }
0428         /*RM46*/
0429         else if (cmd == RM_TIMEOUT_T_STUCK &&
0430             smc->r.rm_join && smc->r.bn_flag) {
0431             GO_STATE(RM6_DIRECTED) ;
0432             break ;
0433         }
0434         break ;
0435     case ACTIONS(RM5_RING_OP_DUP) :
0436         stop_rmt_timer0(smc) ;
0437         stop_rmt_timer1(smc) ;
0438         stop_rmt_timer2(smc) ;
0439         DB_RMTN(1, "RMT : RM5_RING_OP_DUP");
0440         ACTIONS_DONE() ;
0441         break;
0442     case RM5_RING_OP_DUP :
0443         /*RM52*/
0444         if (smc->r.dup_addr_test == DA_PASSED) {
0445             smc->r.da_flag = FALSE ;
0446             GO_STATE(RM2_RING_OP) ;
0447             break ;
0448         }
0449         /*RM54*/
0450         else if (cmd == RM_RING_NON_OP) {
0451             smc->r.jm_flag = FALSE ;
0452             smc->r.bn_flag = FALSE ;
0453             GO_STATE(RM4_NON_OP_DUP) ;
0454             break ;
0455         }
0456         break ;
0457     case ACTIONS(RM6_DIRECTED) :
0458         start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ;
0459         stop_rmt_timer1(smc) ;
0460         start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
0461         sm_ma_control(smc,MA_DIRECTED) ;
0462         RS_SET(smc,RS_BEACON) ;
0463         DB_RMTN(1, "RMT : RM6_DIRECTED");
0464         ACTIONS_DONE() ;
0465         break ;
0466     case RM6_DIRECTED :
0467         /*RM63*/
0468         if (cmd == RM_TIMEOUT_POLL) {
0469             start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
0470             sm_mac_check_beacon_claim(smc) ;
0471 #ifndef SUPERNET_3
0472             /* Because of problems with the Supernet II chip set
0473              * sending of Directed Beacon will stop after 165ms
0474              * therefore restart_trt_for_dbcn(smc) will be called
0475              * to prevent this.
0476              */
0477             restart_trt_for_dbcn(smc) ;
0478 #endif /*SUPERNET_3*/
0479             break ;
0480         }
0481         if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
0482             !smc->r.da_flag) {
0483             smc->r.bn_flag = FALSE ;
0484             GO_STATE(RM3_DETECT) ;
0485             break ;
0486         }
0487         /*RM64*/
0488         else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
0489             smc->r.da_flag) {
0490             smc->r.bn_flag = FALSE ;
0491             GO_STATE(RM4_NON_OP_DUP) ;
0492             break ;
0493         }
0494         /*RM67*/
0495         else if (cmd == RM_TIMEOUT_T_DIRECT) {
0496             GO_STATE(RM7_TRACE) ;
0497             break ;
0498         }
0499         break ;
0500     case ACTIONS(RM7_TRACE) :
0501         stop_rmt_timer0(smc) ;
0502         stop_rmt_timer1(smc) ;
0503         stop_rmt_timer2(smc) ;
0504         smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ;
0505         queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
0506         DB_RMTN(1, "RMT : RM7_TRACE");
0507         ACTIONS_DONE() ;
0508         break ;
0509     case RM7_TRACE :
0510         break ;
0511     default:
0512         SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ;
0513         break;
0514     }
0515 }
0516 
0517 /*
0518  * (jd) RMT duplicate address actions
0519  * leave the ring or reinsert just as configured
0520  */
0521 static void rmt_dup_actions(struct s_smc *smc)
0522 {
0523     if (smc->r.jm_flag) {
0524     }
0525     else {
0526         if (smc->s.rmt_dup_mac_behavior) {
0527             SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
0528                         rmt_reinsert_actions(smc) ;
0529         }
0530         else {
0531             SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
0532             rmt_leave_actions(smc) ;
0533         }
0534     }
0535 }
0536 
0537 /*
0538  * Reconnect to the Ring
0539  */
0540 static void rmt_reinsert_actions(struct s_smc *smc)
0541 {
0542     queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
0543     queue_event(smc,EVENT_ECM,EC_CONNECT) ;
0544 }
0545 
0546 /*
0547  * duplicate address detected
0548  */
0549 static void rmt_new_dup_actions(struct s_smc *smc)
0550 {
0551     smc->r.da_flag = TRUE ;
0552     smc->r.bn_flag = FALSE ;
0553     smc->r.jm_flag = FALSE ;
0554     /*
0555      * we have three options : change address, jam or leave
0556      * we leave the ring as default 
0557      * Optionally it's possible to reinsert after leaving the Ring
0558      * but this will not conform with SMT Spec.
0559      */
0560     if (smc->s.rmt_dup_mac_behavior) {
0561         SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
0562         rmt_reinsert_actions(smc) ;
0563     }
0564     else {
0565         SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
0566         rmt_leave_actions(smc) ;
0567     }
0568 }
0569 
0570 
0571 /*
0572  * leave the ring
0573  */
0574 static void rmt_leave_actions(struct s_smc *smc)
0575 {
0576     queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
0577     /*
0578      * Note: Do NOT try again later. (with please reconnect)
0579      * The station must be left from the ring!
0580      */
0581 }
0582 
0583 /*
0584  * SMT timer interface
0585  *  start RMT timer 0
0586  */
0587 static void start_rmt_timer0(struct s_smc *smc, u_long value, int event)
0588 {
0589     smc->r.timer0_exp = FALSE ;     /* clear timer event flag */
0590     smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event));
0591 }
0592 
0593 /*
0594  * SMT timer interface
0595  *  start RMT timer 1
0596  */
0597 static void start_rmt_timer1(struct s_smc *smc, u_long value, int event)
0598 {
0599     smc->r.timer1_exp = FALSE ; /* clear timer event flag */
0600     smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event));
0601 }
0602 
0603 /*
0604  * SMT timer interface
0605  *  start RMT timer 2
0606  */
0607 static void start_rmt_timer2(struct s_smc *smc, u_long value, int event)
0608 {
0609     smc->r.timer2_exp = FALSE ;     /* clear timer event flag */
0610     smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event));
0611 }
0612 
0613 /*
0614  * SMT timer interface
0615  *  stop RMT timer 0
0616  */
0617 static void stop_rmt_timer0(struct s_smc *smc)
0618 {
0619     if (smc->r.rmt_timer0.tm_active)
0620         smt_timer_stop(smc,&smc->r.rmt_timer0) ;
0621 }
0622 
0623 /*
0624  * SMT timer interface
0625  *  stop RMT timer 1
0626  */
0627 static void stop_rmt_timer1(struct s_smc *smc)
0628 {
0629     if (smc->r.rmt_timer1.tm_active)
0630         smt_timer_stop(smc,&smc->r.rmt_timer1) ;
0631 }
0632 
0633 /*
0634  * SMT timer interface
0635  *  stop RMT timer 2
0636  */
0637 static void stop_rmt_timer2(struct s_smc *smc)
0638 {
0639     if (smc->r.rmt_timer2.tm_active)
0640         smt_timer_stop(smc,&smc->r.rmt_timer2) ;
0641 }
0642