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