133f810b2SJeff Kirsher /****************************************************************************** 233f810b2SJeff Kirsher * 333f810b2SJeff Kirsher * (C)Copyright 1998,1999 SysKonnect, 433f810b2SJeff Kirsher * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 533f810b2SJeff Kirsher * 633f810b2SJeff Kirsher * See the file "skfddi.c" for further information. 733f810b2SJeff Kirsher * 833f810b2SJeff Kirsher * This program is free software; you can redistribute it and/or modify 933f810b2SJeff Kirsher * it under the terms of the GNU General Public License as published by 1033f810b2SJeff Kirsher * the Free Software Foundation; either version 2 of the License, or 1133f810b2SJeff Kirsher * (at your option) any later version. 1233f810b2SJeff Kirsher * 1333f810b2SJeff Kirsher * The information in this file is provided "AS IS" without warranty. 1433f810b2SJeff Kirsher * 1533f810b2SJeff Kirsher ******************************************************************************/ 1633f810b2SJeff Kirsher 1733f810b2SJeff Kirsher /* 1833f810b2SJeff Kirsher SMT RMT 1933f810b2SJeff Kirsher Ring Management 2033f810b2SJeff Kirsher */ 2133f810b2SJeff Kirsher 2233f810b2SJeff Kirsher /* 2333f810b2SJeff Kirsher * Hardware independent state machine implemantation 2433f810b2SJeff Kirsher * The following external SMT functions are referenced : 2533f810b2SJeff Kirsher * 2633f810b2SJeff Kirsher * queue_event() 2733f810b2SJeff Kirsher * smt_timer_start() 2833f810b2SJeff Kirsher * smt_timer_stop() 2933f810b2SJeff Kirsher * 3033f810b2SJeff Kirsher * The following external HW dependent functions are referenced : 3133f810b2SJeff Kirsher * sm_ma_control() 3233f810b2SJeff Kirsher * sm_mac_check_beacon_claim() 3333f810b2SJeff Kirsher * 3433f810b2SJeff Kirsher * The following HW dependent events are required : 3533f810b2SJeff Kirsher * RM_RING_OP 3633f810b2SJeff Kirsher * RM_RING_NON_OP 3733f810b2SJeff Kirsher * RM_MY_BEACON 3833f810b2SJeff Kirsher * RM_OTHER_BEACON 3933f810b2SJeff Kirsher * RM_MY_CLAIM 4033f810b2SJeff Kirsher * RM_TRT_EXP 4133f810b2SJeff Kirsher * RM_VALID_CLAIM 4233f810b2SJeff Kirsher * 4333f810b2SJeff Kirsher */ 4433f810b2SJeff Kirsher 4533f810b2SJeff Kirsher #include "h/types.h" 4633f810b2SJeff Kirsher #include "h/fddi.h" 4733f810b2SJeff Kirsher #include "h/smc.h" 4833f810b2SJeff Kirsher 4933f810b2SJeff Kirsher #define KERNEL 5033f810b2SJeff Kirsher #include "h/smtstate.h" 5133f810b2SJeff Kirsher 5233f810b2SJeff Kirsher #ifndef lint 5333f810b2SJeff Kirsher static const char ID_sccs[] = "@(#)rmt.c 2.13 99/07/02 (C) SK " ; 5433f810b2SJeff Kirsher #endif 5533f810b2SJeff Kirsher 5633f810b2SJeff Kirsher /* 5733f810b2SJeff Kirsher * FSM Macros 5833f810b2SJeff Kirsher */ 5933f810b2SJeff Kirsher #define AFLAG 0x10 6033f810b2SJeff Kirsher #define GO_STATE(x) (smc->mib.m[MAC0].fddiMACRMTState = (x)|AFLAG) 6133f810b2SJeff Kirsher #define ACTIONS_DONE() (smc->mib.m[MAC0].fddiMACRMTState &= ~AFLAG) 6233f810b2SJeff Kirsher #define ACTIONS(x) (x|AFLAG) 6333f810b2SJeff Kirsher 6433f810b2SJeff Kirsher #define RM0_ISOLATED 0 6533f810b2SJeff Kirsher #define RM1_NON_OP 1 /* not operational */ 6633f810b2SJeff Kirsher #define RM2_RING_OP 2 /* ring operational */ 6733f810b2SJeff Kirsher #define RM3_DETECT 3 /* detect dupl addresses */ 6833f810b2SJeff Kirsher #define RM4_NON_OP_DUP 4 /* dupl. addr detected */ 6933f810b2SJeff Kirsher #define RM5_RING_OP_DUP 5 /* ring oper. with dupl. addr */ 7033f810b2SJeff Kirsher #define RM6_DIRECTED 6 /* sending directed beacons */ 7133f810b2SJeff Kirsher #define RM7_TRACE 7 /* trace initiated */ 7233f810b2SJeff Kirsher 7333f810b2SJeff Kirsher /* 7433f810b2SJeff Kirsher * symbolic state names 7533f810b2SJeff Kirsher */ 7633f810b2SJeff Kirsher static const char * const rmt_states[] = { 7733f810b2SJeff Kirsher "RM0_ISOLATED","RM1_NON_OP","RM2_RING_OP","RM3_DETECT", 7833f810b2SJeff Kirsher "RM4_NON_OP_DUP","RM5_RING_OP_DUP","RM6_DIRECTED", 7933f810b2SJeff Kirsher "RM7_TRACE" 8033f810b2SJeff Kirsher } ; 8133f810b2SJeff Kirsher 8233f810b2SJeff Kirsher /* 8333f810b2SJeff Kirsher * symbolic event names 8433f810b2SJeff Kirsher */ 8533f810b2SJeff Kirsher static const char * const rmt_events[] = { 8633f810b2SJeff Kirsher "NONE","RM_RING_OP","RM_RING_NON_OP","RM_MY_BEACON", 8733f810b2SJeff Kirsher "RM_OTHER_BEACON","RM_MY_CLAIM","RM_TRT_EXP","RM_VALID_CLAIM", 8833f810b2SJeff Kirsher "RM_JOIN","RM_LOOP","RM_DUP_ADDR","RM_ENABLE_FLAG", 8933f810b2SJeff Kirsher "RM_TIMEOUT_NON_OP","RM_TIMEOUT_T_STUCK", 9033f810b2SJeff Kirsher "RM_TIMEOUT_ANNOUNCE","RM_TIMEOUT_T_DIRECT", 9133f810b2SJeff Kirsher "RM_TIMEOUT_D_MAX","RM_TIMEOUT_POLL","RM_TX_STATE_CHANGE" 9233f810b2SJeff Kirsher } ; 9333f810b2SJeff Kirsher 9433f810b2SJeff Kirsher /* 9533f810b2SJeff Kirsher * Globals 9633f810b2SJeff Kirsher * in struct s_rmt 9733f810b2SJeff Kirsher */ 9833f810b2SJeff Kirsher 9933f810b2SJeff Kirsher 10033f810b2SJeff Kirsher /* 10133f810b2SJeff Kirsher * function declarations 10233f810b2SJeff Kirsher */ 10333f810b2SJeff Kirsher static void rmt_fsm(struct s_smc *smc, int cmd); 10433f810b2SJeff Kirsher static void start_rmt_timer0(struct s_smc *smc, u_long value, int event); 10533f810b2SJeff Kirsher static void start_rmt_timer1(struct s_smc *smc, u_long value, int event); 10633f810b2SJeff Kirsher static void start_rmt_timer2(struct s_smc *smc, u_long value, int event); 10733f810b2SJeff Kirsher static void stop_rmt_timer0(struct s_smc *smc); 10833f810b2SJeff Kirsher static void stop_rmt_timer1(struct s_smc *smc); 10933f810b2SJeff Kirsher static void stop_rmt_timer2(struct s_smc *smc); 11033f810b2SJeff Kirsher static void rmt_dup_actions(struct s_smc *smc); 11133f810b2SJeff Kirsher static void rmt_reinsert_actions(struct s_smc *smc); 11233f810b2SJeff Kirsher static void rmt_leave_actions(struct s_smc *smc); 11333f810b2SJeff Kirsher static void rmt_new_dup_actions(struct s_smc *smc); 11433f810b2SJeff Kirsher 11533f810b2SJeff Kirsher #ifndef SUPERNET_3 11633f810b2SJeff Kirsher extern void restart_trt_for_dbcn() ; 11733f810b2SJeff Kirsher #endif /*SUPERNET_3*/ 11833f810b2SJeff Kirsher 11933f810b2SJeff Kirsher /* 12033f810b2SJeff Kirsher init RMT state machine 12133f810b2SJeff Kirsher clear all RMT vars and flags 12233f810b2SJeff Kirsher */ 12333f810b2SJeff Kirsher void rmt_init(struct s_smc *smc) 12433f810b2SJeff Kirsher { 12533f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ; 12633f810b2SJeff Kirsher smc->r.dup_addr_test = DA_NONE ; 12733f810b2SJeff Kirsher smc->r.da_flag = 0 ; 12833f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 12933f810b2SJeff Kirsher smc->r.sm_ma_avail = FALSE ; 13033f810b2SJeff Kirsher smc->r.loop_avail = 0 ; 13133f810b2SJeff Kirsher smc->r.bn_flag = 0 ; 13233f810b2SJeff Kirsher smc->r.jm_flag = 0 ; 13333f810b2SJeff Kirsher smc->r.no_flag = TRUE ; 13433f810b2SJeff Kirsher } 13533f810b2SJeff Kirsher 13633f810b2SJeff Kirsher /* 13733f810b2SJeff Kirsher RMT state machine 13833f810b2SJeff Kirsher called by dispatcher 13933f810b2SJeff Kirsher 14033f810b2SJeff Kirsher do 14133f810b2SJeff Kirsher display state change 14233f810b2SJeff Kirsher process event 14333f810b2SJeff Kirsher until SM is stable 14433f810b2SJeff Kirsher */ 14533f810b2SJeff Kirsher void rmt(struct s_smc *smc, int event) 14633f810b2SJeff Kirsher { 14733f810b2SJeff Kirsher int state ; 14833f810b2SJeff Kirsher 14933f810b2SJeff Kirsher do { 150*5671e8c1SJoe Perches DB_RMT("RMT : state %s%s event %s", 151*5671e8c1SJoe Perches smc->mib.m[MAC0].fddiMACRMTState & AFLAG ? "ACTIONS " : "", 152*5671e8c1SJoe Perches rmt_states[smc->mib.m[MAC0].fddiMACRMTState & ~AFLAG], 153*5671e8c1SJoe Perches rmt_events[event]); 15433f810b2SJeff Kirsher state = smc->mib.m[MAC0].fddiMACRMTState ; 15533f810b2SJeff Kirsher rmt_fsm(smc,event) ; 15633f810b2SJeff Kirsher event = 0 ; 15733f810b2SJeff Kirsher } while (state != smc->mib.m[MAC0].fddiMACRMTState) ; 15833f810b2SJeff Kirsher rmt_state_change(smc,(int)smc->mib.m[MAC0].fddiMACRMTState) ; 15933f810b2SJeff Kirsher } 16033f810b2SJeff Kirsher 16133f810b2SJeff Kirsher /* 16233f810b2SJeff Kirsher process RMT event 16333f810b2SJeff Kirsher */ 16433f810b2SJeff Kirsher static void rmt_fsm(struct s_smc *smc, int cmd) 16533f810b2SJeff Kirsher { 16633f810b2SJeff Kirsher /* 16733f810b2SJeff Kirsher * RM00-RM70 : from all states 16833f810b2SJeff Kirsher */ 16933f810b2SJeff Kirsher if (!smc->r.rm_join && !smc->r.rm_loop && 17033f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) && 17133f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) { 17233f810b2SJeff Kirsher RS_SET(smc,RS_NORINGOP) ; 17333f810b2SJeff Kirsher rmt_indication(smc,0) ; 17433f810b2SJeff Kirsher GO_STATE(RM0_ISOLATED) ; 17533f810b2SJeff Kirsher return ; 17633f810b2SJeff Kirsher } 17733f810b2SJeff Kirsher 17833f810b2SJeff Kirsher switch(smc->mib.m[MAC0].fddiMACRMTState) { 17933f810b2SJeff Kirsher case ACTIONS(RM0_ISOLATED) : 18033f810b2SJeff Kirsher stop_rmt_timer0(smc) ; 18133f810b2SJeff Kirsher stop_rmt_timer1(smc) ; 18233f810b2SJeff Kirsher stop_rmt_timer2(smc) ; 18333f810b2SJeff Kirsher 18433f810b2SJeff Kirsher /* 18533f810b2SJeff Kirsher * Disable MAC. 18633f810b2SJeff Kirsher */ 18733f810b2SJeff Kirsher sm_ma_control(smc,MA_OFFLINE) ; 18833f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 18933f810b2SJeff Kirsher smc->r.loop_avail = FALSE ; 19033f810b2SJeff Kirsher smc->r.sm_ma_avail = FALSE ; 19133f810b2SJeff Kirsher smc->r.no_flag = TRUE ; 192*5671e8c1SJoe Perches DB_RMTN(1, "RMT : ISOLATED"); 19333f810b2SJeff Kirsher ACTIONS_DONE() ; 19433f810b2SJeff Kirsher break ; 19533f810b2SJeff Kirsher case RM0_ISOLATED : 19633f810b2SJeff Kirsher /*RM01*/ 19733f810b2SJeff Kirsher if (smc->r.rm_join || smc->r.rm_loop) { 19833f810b2SJeff Kirsher /* 19933f810b2SJeff Kirsher * According to the standard the MAC must be reset 20033f810b2SJeff Kirsher * here. The FORMAC will be initialized and Claim 20133f810b2SJeff Kirsher * and Beacon Frames will be uploaded to the MAC. 20233f810b2SJeff Kirsher * So any change of Treq will take effect NOW. 20333f810b2SJeff Kirsher */ 20433f810b2SJeff Kirsher sm_ma_control(smc,MA_RESET) ; 20533f810b2SJeff Kirsher GO_STATE(RM1_NON_OP) ; 20633f810b2SJeff Kirsher break ; 20733f810b2SJeff Kirsher } 20833f810b2SJeff Kirsher break ; 20933f810b2SJeff Kirsher case ACTIONS(RM1_NON_OP) : 21033f810b2SJeff Kirsher start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ; 21133f810b2SJeff Kirsher stop_rmt_timer1(smc) ; 21233f810b2SJeff Kirsher stop_rmt_timer2(smc) ; 21333f810b2SJeff Kirsher sm_ma_control(smc,MA_BEACON) ; 214*5671e8c1SJoe Perches DB_RMTN(1, "RMT : RING DOWN"); 21533f810b2SJeff Kirsher RS_SET(smc,RS_NORINGOP) ; 21633f810b2SJeff Kirsher smc->r.sm_ma_avail = FALSE ; 21733f810b2SJeff Kirsher rmt_indication(smc,0) ; 21833f810b2SJeff Kirsher ACTIONS_DONE() ; 21933f810b2SJeff Kirsher break ; 22033f810b2SJeff Kirsher case RM1_NON_OP : 22133f810b2SJeff Kirsher /*RM12*/ 22233f810b2SJeff Kirsher if (cmd == RM_RING_OP) { 22333f810b2SJeff Kirsher RS_SET(smc,RS_RINGOPCHANGE) ; 22433f810b2SJeff Kirsher GO_STATE(RM2_RING_OP) ; 22533f810b2SJeff Kirsher break ; 22633f810b2SJeff Kirsher } 22733f810b2SJeff Kirsher /*RM13*/ 22833f810b2SJeff Kirsher else if (cmd == RM_TIMEOUT_NON_OP) { 22933f810b2SJeff Kirsher smc->r.bn_flag = FALSE ; 23033f810b2SJeff Kirsher smc->r.no_flag = TRUE ; 23133f810b2SJeff Kirsher GO_STATE(RM3_DETECT) ; 23233f810b2SJeff Kirsher break ; 23333f810b2SJeff Kirsher } 23433f810b2SJeff Kirsher break ; 23533f810b2SJeff Kirsher case ACTIONS(RM2_RING_OP) : 23633f810b2SJeff Kirsher stop_rmt_timer0(smc) ; 23733f810b2SJeff Kirsher stop_rmt_timer1(smc) ; 23833f810b2SJeff Kirsher stop_rmt_timer2(smc) ; 23933f810b2SJeff Kirsher smc->r.no_flag = FALSE ; 24033f810b2SJeff Kirsher if (smc->r.rm_loop) 24133f810b2SJeff Kirsher smc->r.loop_avail = TRUE ; 24233f810b2SJeff Kirsher if (smc->r.rm_join) { 24333f810b2SJeff Kirsher smc->r.sm_ma_avail = TRUE ; 24433f810b2SJeff Kirsher if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable) 24533f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ; 24633f810b2SJeff Kirsher else 24733f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 24833f810b2SJeff Kirsher } 249*5671e8c1SJoe Perches DB_RMTN(1, "RMT : RING UP"); 25033f810b2SJeff Kirsher RS_CLEAR(smc,RS_NORINGOP) ; 25133f810b2SJeff Kirsher RS_SET(smc,RS_RINGOPCHANGE) ; 25233f810b2SJeff Kirsher rmt_indication(smc,1) ; 25333f810b2SJeff Kirsher smt_stat_counter(smc,0) ; 25433f810b2SJeff Kirsher ACTIONS_DONE() ; 25533f810b2SJeff Kirsher break ; 25633f810b2SJeff Kirsher case RM2_RING_OP : 25733f810b2SJeff Kirsher /*RM21*/ 25833f810b2SJeff Kirsher if (cmd == RM_RING_NON_OP) { 25933f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 26033f810b2SJeff Kirsher smc->r.loop_avail = FALSE ; 26133f810b2SJeff Kirsher RS_SET(smc,RS_RINGOPCHANGE) ; 26233f810b2SJeff Kirsher GO_STATE(RM1_NON_OP) ; 26333f810b2SJeff Kirsher break ; 26433f810b2SJeff Kirsher } 26533f810b2SJeff Kirsher /*RM22a*/ 26633f810b2SJeff Kirsher else if (cmd == RM_ENABLE_FLAG) { 26733f810b2SJeff Kirsher if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable) 26833f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ; 26933f810b2SJeff Kirsher else 27033f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 27133f810b2SJeff Kirsher } 27233f810b2SJeff Kirsher /*RM25*/ 27333f810b2SJeff Kirsher else if (smc->r.dup_addr_test == DA_FAILED) { 27433f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 27533f810b2SJeff Kirsher smc->r.loop_avail = FALSE ; 27633f810b2SJeff Kirsher smc->r.da_flag = TRUE ; 27733f810b2SJeff Kirsher GO_STATE(RM5_RING_OP_DUP) ; 27833f810b2SJeff Kirsher break ; 27933f810b2SJeff Kirsher } 28033f810b2SJeff Kirsher break ; 28133f810b2SJeff Kirsher case ACTIONS(RM3_DETECT) : 28233f810b2SJeff Kirsher start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ; 28333f810b2SJeff Kirsher start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ; 28433f810b2SJeff Kirsher start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; 28533f810b2SJeff Kirsher sm_mac_check_beacon_claim(smc) ; 286*5671e8c1SJoe Perches DB_RMTN(1, "RMT : RM3_DETECT"); 28733f810b2SJeff Kirsher ACTIONS_DONE() ; 28833f810b2SJeff Kirsher break ; 28933f810b2SJeff Kirsher case RM3_DETECT : 29033f810b2SJeff Kirsher if (cmd == RM_TIMEOUT_POLL) { 29133f810b2SJeff Kirsher start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); 29233f810b2SJeff Kirsher sm_mac_check_beacon_claim(smc) ; 29333f810b2SJeff Kirsher break ; 29433f810b2SJeff Kirsher } 29533f810b2SJeff Kirsher if (cmd == RM_TIMEOUT_D_MAX) { 29633f810b2SJeff Kirsher smc->r.timer0_exp = TRUE ; 29733f810b2SJeff Kirsher } 29833f810b2SJeff Kirsher /* 29933f810b2SJeff Kirsher *jd(22-Feb-1999) 30033f810b2SJeff Kirsher * We need a time ">= 2*mac_d_max" since we had finished 30133f810b2SJeff Kirsher * Claim or Beacon state. So we will restart timer0 at 30233f810b2SJeff Kirsher * every state change. 30333f810b2SJeff Kirsher */ 30433f810b2SJeff Kirsher if (cmd == RM_TX_STATE_CHANGE) { 30533f810b2SJeff Kirsher start_rmt_timer0(smc, 30633f810b2SJeff Kirsher smc->s.mac_d_max*2, 30733f810b2SJeff Kirsher RM_TIMEOUT_D_MAX) ; 30833f810b2SJeff Kirsher } 30933f810b2SJeff Kirsher /*RM32*/ 31033f810b2SJeff Kirsher if (cmd == RM_RING_OP) { 31133f810b2SJeff Kirsher GO_STATE(RM2_RING_OP) ; 31233f810b2SJeff Kirsher break ; 31333f810b2SJeff Kirsher } 31433f810b2SJeff Kirsher /*RM33a*/ 31533f810b2SJeff Kirsher else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) 31633f810b2SJeff Kirsher && smc->r.bn_flag) { 31733f810b2SJeff Kirsher smc->r.bn_flag = FALSE ; 31833f810b2SJeff Kirsher } 31933f810b2SJeff Kirsher /*RM33b*/ 32033f810b2SJeff Kirsher else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) { 32133f810b2SJeff Kirsher int tx ; 32233f810b2SJeff Kirsher /* 32333f810b2SJeff Kirsher * set bn_flag only if in state T4 or T5: 32433f810b2SJeff Kirsher * only if we're the beaconer should we start the 32533f810b2SJeff Kirsher * trace ! 32633f810b2SJeff Kirsher */ 32733f810b2SJeff Kirsher if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) { 328*5671e8c1SJoe Perches DB_RMTN(2, "RMT : DETECT && TRT_EXPIRED && T4/T5"); 32933f810b2SJeff Kirsher smc->r.bn_flag = TRUE ; 33033f810b2SJeff Kirsher /* 33133f810b2SJeff Kirsher * If one of the upstream stations beaconed 33233f810b2SJeff Kirsher * and the link to the upstream neighbor is 33333f810b2SJeff Kirsher * lost we need to restart the stuck timer to 33433f810b2SJeff Kirsher * check the "stuck beacon" condition. 33533f810b2SJeff Kirsher */ 33633f810b2SJeff Kirsher start_rmt_timer1(smc,smc->s.rmt_t_stuck, 33733f810b2SJeff Kirsher RM_TIMEOUT_T_STUCK) ; 33833f810b2SJeff Kirsher } 33933f810b2SJeff Kirsher /* 34033f810b2SJeff Kirsher * We do NOT need to clear smc->r.bn_flag in case of 34133f810b2SJeff Kirsher * not being in state T4 or T5, because the flag 34233f810b2SJeff Kirsher * must be cleared in order to get in this condition. 34333f810b2SJeff Kirsher */ 34433f810b2SJeff Kirsher 345*5671e8c1SJoe Perches DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)", 34633f810b2SJeff Kirsher tx, smc->r.bn_flag); 34733f810b2SJeff Kirsher } 34833f810b2SJeff Kirsher /*RM34a*/ 34933f810b2SJeff Kirsher else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) { 35033f810b2SJeff Kirsher rmt_new_dup_actions(smc) ; 35133f810b2SJeff Kirsher GO_STATE(RM4_NON_OP_DUP) ; 35233f810b2SJeff Kirsher break ; 35333f810b2SJeff Kirsher } 35433f810b2SJeff Kirsher /*RM34b*/ 35533f810b2SJeff Kirsher else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) { 35633f810b2SJeff Kirsher rmt_new_dup_actions(smc) ; 35733f810b2SJeff Kirsher GO_STATE(RM4_NON_OP_DUP) ; 35833f810b2SJeff Kirsher break ; 35933f810b2SJeff Kirsher } 36033f810b2SJeff Kirsher /*RM34c*/ 36133f810b2SJeff Kirsher else if (cmd == RM_VALID_CLAIM) { 36233f810b2SJeff Kirsher rmt_new_dup_actions(smc) ; 36333f810b2SJeff Kirsher GO_STATE(RM4_NON_OP_DUP) ; 36433f810b2SJeff Kirsher break ; 36533f810b2SJeff Kirsher } 36633f810b2SJeff Kirsher /*RM36*/ 36733f810b2SJeff Kirsher else if (cmd == RM_TIMEOUT_T_STUCK && 36833f810b2SJeff Kirsher smc->r.rm_join && smc->r.bn_flag) { 36933f810b2SJeff Kirsher GO_STATE(RM6_DIRECTED) ; 37033f810b2SJeff Kirsher break ; 37133f810b2SJeff Kirsher } 37233f810b2SJeff Kirsher break ; 37333f810b2SJeff Kirsher case ACTIONS(RM4_NON_OP_DUP) : 37433f810b2SJeff Kirsher start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE); 37533f810b2SJeff Kirsher start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ; 37633f810b2SJeff Kirsher start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; 37733f810b2SJeff Kirsher sm_mac_check_beacon_claim(smc) ; 378*5671e8c1SJoe Perches DB_RMTN(1, "RMT : RM4_NON_OP_DUP"); 37933f810b2SJeff Kirsher ACTIONS_DONE() ; 38033f810b2SJeff Kirsher break ; 38133f810b2SJeff Kirsher case RM4_NON_OP_DUP : 38233f810b2SJeff Kirsher if (cmd == RM_TIMEOUT_POLL) { 38333f810b2SJeff Kirsher start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); 38433f810b2SJeff Kirsher sm_mac_check_beacon_claim(smc) ; 38533f810b2SJeff Kirsher break ; 38633f810b2SJeff Kirsher } 38733f810b2SJeff Kirsher /*RM41*/ 38833f810b2SJeff Kirsher if (!smc->r.da_flag) { 38933f810b2SJeff Kirsher GO_STATE(RM1_NON_OP) ; 39033f810b2SJeff Kirsher break ; 39133f810b2SJeff Kirsher } 39233f810b2SJeff Kirsher /*RM44a*/ 39333f810b2SJeff Kirsher else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && 39433f810b2SJeff Kirsher smc->r.bn_flag) { 39533f810b2SJeff Kirsher smc->r.bn_flag = FALSE ; 39633f810b2SJeff Kirsher } 39733f810b2SJeff Kirsher /*RM44b*/ 39833f810b2SJeff Kirsher else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) { 39933f810b2SJeff Kirsher int tx ; 40033f810b2SJeff Kirsher /* 40133f810b2SJeff Kirsher * set bn_flag only if in state T4 or T5: 40233f810b2SJeff Kirsher * only if we're the beaconer should we start the 40333f810b2SJeff Kirsher * trace ! 40433f810b2SJeff Kirsher */ 40533f810b2SJeff Kirsher if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) { 406*5671e8c1SJoe Perches DB_RMTN(2, "RMT : NOPDUP && TRT_EXPIRED && T4/T5"); 40733f810b2SJeff Kirsher smc->r.bn_flag = TRUE ; 40833f810b2SJeff Kirsher /* 40933f810b2SJeff Kirsher * If one of the upstream stations beaconed 41033f810b2SJeff Kirsher * and the link to the upstream neighbor is 41133f810b2SJeff Kirsher * lost we need to restart the stuck timer to 41233f810b2SJeff Kirsher * check the "stuck beacon" condition. 41333f810b2SJeff Kirsher */ 41433f810b2SJeff Kirsher start_rmt_timer1(smc,smc->s.rmt_t_stuck, 41533f810b2SJeff Kirsher RM_TIMEOUT_T_STUCK) ; 41633f810b2SJeff Kirsher } 41733f810b2SJeff Kirsher /* 41833f810b2SJeff Kirsher * We do NOT need to clear smc->r.bn_flag in case of 41933f810b2SJeff Kirsher * not being in state T4 or T5, because the flag 42033f810b2SJeff Kirsher * must be cleared in order to get in this condition. 42133f810b2SJeff Kirsher */ 42233f810b2SJeff Kirsher 423*5671e8c1SJoe Perches DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)", 42433f810b2SJeff Kirsher tx, smc->r.bn_flag); 42533f810b2SJeff Kirsher } 42633f810b2SJeff Kirsher /*RM44c*/ 42733f810b2SJeff Kirsher else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) { 42833f810b2SJeff Kirsher rmt_dup_actions(smc) ; 42933f810b2SJeff Kirsher } 43033f810b2SJeff Kirsher /*RM45*/ 43133f810b2SJeff Kirsher else if (cmd == RM_RING_OP) { 43233f810b2SJeff Kirsher smc->r.no_flag = FALSE ; 43333f810b2SJeff Kirsher GO_STATE(RM5_RING_OP_DUP) ; 43433f810b2SJeff Kirsher break ; 43533f810b2SJeff Kirsher } 43633f810b2SJeff Kirsher /*RM46*/ 43733f810b2SJeff Kirsher else if (cmd == RM_TIMEOUT_T_STUCK && 43833f810b2SJeff Kirsher smc->r.rm_join && smc->r.bn_flag) { 43933f810b2SJeff Kirsher GO_STATE(RM6_DIRECTED) ; 44033f810b2SJeff Kirsher break ; 44133f810b2SJeff Kirsher } 44233f810b2SJeff Kirsher break ; 44333f810b2SJeff Kirsher case ACTIONS(RM5_RING_OP_DUP) : 44433f810b2SJeff Kirsher stop_rmt_timer0(smc) ; 44533f810b2SJeff Kirsher stop_rmt_timer1(smc) ; 44633f810b2SJeff Kirsher stop_rmt_timer2(smc) ; 447*5671e8c1SJoe Perches DB_RMTN(1, "RMT : RM5_RING_OP_DUP"); 44833f810b2SJeff Kirsher ACTIONS_DONE() ; 44933f810b2SJeff Kirsher break; 45033f810b2SJeff Kirsher case RM5_RING_OP_DUP : 45133f810b2SJeff Kirsher /*RM52*/ 45233f810b2SJeff Kirsher if (smc->r.dup_addr_test == DA_PASSED) { 45333f810b2SJeff Kirsher smc->r.da_flag = FALSE ; 45433f810b2SJeff Kirsher GO_STATE(RM2_RING_OP) ; 45533f810b2SJeff Kirsher break ; 45633f810b2SJeff Kirsher } 45733f810b2SJeff Kirsher /*RM54*/ 45833f810b2SJeff Kirsher else if (cmd == RM_RING_NON_OP) { 45933f810b2SJeff Kirsher smc->r.jm_flag = FALSE ; 46033f810b2SJeff Kirsher smc->r.bn_flag = FALSE ; 46133f810b2SJeff Kirsher GO_STATE(RM4_NON_OP_DUP) ; 46233f810b2SJeff Kirsher break ; 46333f810b2SJeff Kirsher } 46433f810b2SJeff Kirsher break ; 46533f810b2SJeff Kirsher case ACTIONS(RM6_DIRECTED) : 46633f810b2SJeff Kirsher start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ; 46733f810b2SJeff Kirsher stop_rmt_timer1(smc) ; 46833f810b2SJeff Kirsher start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; 46933f810b2SJeff Kirsher sm_ma_control(smc,MA_DIRECTED) ; 47033f810b2SJeff Kirsher RS_SET(smc,RS_BEACON) ; 471*5671e8c1SJoe Perches DB_RMTN(1, "RMT : RM6_DIRECTED"); 47233f810b2SJeff Kirsher ACTIONS_DONE() ; 47333f810b2SJeff Kirsher break ; 47433f810b2SJeff Kirsher case RM6_DIRECTED : 47533f810b2SJeff Kirsher /*RM63*/ 47633f810b2SJeff Kirsher if (cmd == RM_TIMEOUT_POLL) { 47733f810b2SJeff Kirsher start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); 47833f810b2SJeff Kirsher sm_mac_check_beacon_claim(smc) ; 47933f810b2SJeff Kirsher #ifndef SUPERNET_3 48033f810b2SJeff Kirsher /* Because of problems with the Supernet II chip set 48133f810b2SJeff Kirsher * sending of Directed Beacon will stop after 165ms 48233f810b2SJeff Kirsher * therefore restart_trt_for_dbcn(smc) will be called 48333f810b2SJeff Kirsher * to prevent this. 48433f810b2SJeff Kirsher */ 48533f810b2SJeff Kirsher restart_trt_for_dbcn(smc) ; 48633f810b2SJeff Kirsher #endif /*SUPERNET_3*/ 48733f810b2SJeff Kirsher break ; 48833f810b2SJeff Kirsher } 48933f810b2SJeff Kirsher if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && 49033f810b2SJeff Kirsher !smc->r.da_flag) { 49133f810b2SJeff Kirsher smc->r.bn_flag = FALSE ; 49233f810b2SJeff Kirsher GO_STATE(RM3_DETECT) ; 49333f810b2SJeff Kirsher break ; 49433f810b2SJeff Kirsher } 49533f810b2SJeff Kirsher /*RM64*/ 49633f810b2SJeff Kirsher else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && 49733f810b2SJeff Kirsher smc->r.da_flag) { 49833f810b2SJeff Kirsher smc->r.bn_flag = FALSE ; 49933f810b2SJeff Kirsher GO_STATE(RM4_NON_OP_DUP) ; 50033f810b2SJeff Kirsher break ; 50133f810b2SJeff Kirsher } 50233f810b2SJeff Kirsher /*RM67*/ 50333f810b2SJeff Kirsher else if (cmd == RM_TIMEOUT_T_DIRECT) { 50433f810b2SJeff Kirsher GO_STATE(RM7_TRACE) ; 50533f810b2SJeff Kirsher break ; 50633f810b2SJeff Kirsher } 50733f810b2SJeff Kirsher break ; 50833f810b2SJeff Kirsher case ACTIONS(RM7_TRACE) : 50933f810b2SJeff Kirsher stop_rmt_timer0(smc) ; 51033f810b2SJeff Kirsher stop_rmt_timer1(smc) ; 51133f810b2SJeff Kirsher stop_rmt_timer2(smc) ; 51233f810b2SJeff Kirsher smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ; 51333f810b2SJeff Kirsher queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ; 514*5671e8c1SJoe Perches DB_RMTN(1, "RMT : RM7_TRACE"); 51533f810b2SJeff Kirsher ACTIONS_DONE() ; 51633f810b2SJeff Kirsher break ; 51733f810b2SJeff Kirsher case RM7_TRACE : 51833f810b2SJeff Kirsher break ; 51933f810b2SJeff Kirsher default: 52033f810b2SJeff Kirsher SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ; 52133f810b2SJeff Kirsher break; 52233f810b2SJeff Kirsher } 52333f810b2SJeff Kirsher } 52433f810b2SJeff Kirsher 52533f810b2SJeff Kirsher /* 52633f810b2SJeff Kirsher * (jd) RMT duplicate address actions 52733f810b2SJeff Kirsher * leave the ring or reinsert just as configured 52833f810b2SJeff Kirsher */ 52933f810b2SJeff Kirsher static void rmt_dup_actions(struct s_smc *smc) 53033f810b2SJeff Kirsher { 53133f810b2SJeff Kirsher if (smc->r.jm_flag) { 53233f810b2SJeff Kirsher } 53333f810b2SJeff Kirsher else { 53433f810b2SJeff Kirsher if (smc->s.rmt_dup_mac_behavior) { 53533f810b2SJeff Kirsher SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ; 53633f810b2SJeff Kirsher rmt_reinsert_actions(smc) ; 53733f810b2SJeff Kirsher } 53833f810b2SJeff Kirsher else { 53933f810b2SJeff Kirsher SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ; 54033f810b2SJeff Kirsher rmt_leave_actions(smc) ; 54133f810b2SJeff Kirsher } 54233f810b2SJeff Kirsher } 54333f810b2SJeff Kirsher } 54433f810b2SJeff Kirsher 54533f810b2SJeff Kirsher /* 54633f810b2SJeff Kirsher * Reconnect to the Ring 54733f810b2SJeff Kirsher */ 54833f810b2SJeff Kirsher static void rmt_reinsert_actions(struct s_smc *smc) 54933f810b2SJeff Kirsher { 55033f810b2SJeff Kirsher queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; 55133f810b2SJeff Kirsher queue_event(smc,EVENT_ECM,EC_CONNECT) ; 55233f810b2SJeff Kirsher } 55333f810b2SJeff Kirsher 55433f810b2SJeff Kirsher /* 55533f810b2SJeff Kirsher * duplicate address detected 55633f810b2SJeff Kirsher */ 55733f810b2SJeff Kirsher static void rmt_new_dup_actions(struct s_smc *smc) 55833f810b2SJeff Kirsher { 55933f810b2SJeff Kirsher smc->r.da_flag = TRUE ; 56033f810b2SJeff Kirsher smc->r.bn_flag = FALSE ; 56133f810b2SJeff Kirsher smc->r.jm_flag = FALSE ; 56233f810b2SJeff Kirsher /* 56333f810b2SJeff Kirsher * we have three options : change address, jam or leave 56433f810b2SJeff Kirsher * we leave the ring as default 56533f810b2SJeff Kirsher * Optionally it's possible to reinsert after leaving the Ring 56633f810b2SJeff Kirsher * but this will not conform with SMT Spec. 56733f810b2SJeff Kirsher */ 56833f810b2SJeff Kirsher if (smc->s.rmt_dup_mac_behavior) { 56933f810b2SJeff Kirsher SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ; 57033f810b2SJeff Kirsher rmt_reinsert_actions(smc) ; 57133f810b2SJeff Kirsher } 57233f810b2SJeff Kirsher else { 57333f810b2SJeff Kirsher SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ; 57433f810b2SJeff Kirsher rmt_leave_actions(smc) ; 57533f810b2SJeff Kirsher } 57633f810b2SJeff Kirsher } 57733f810b2SJeff Kirsher 57833f810b2SJeff Kirsher 57933f810b2SJeff Kirsher /* 58033f810b2SJeff Kirsher * leave the ring 58133f810b2SJeff Kirsher */ 58233f810b2SJeff Kirsher static void rmt_leave_actions(struct s_smc *smc) 58333f810b2SJeff Kirsher { 58433f810b2SJeff Kirsher queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; 58533f810b2SJeff Kirsher /* 58633f810b2SJeff Kirsher * Note: Do NOT try again later. (with please reconnect) 58733f810b2SJeff Kirsher * The station must be left from the ring! 58833f810b2SJeff Kirsher */ 58933f810b2SJeff Kirsher } 59033f810b2SJeff Kirsher 59133f810b2SJeff Kirsher /* 59233f810b2SJeff Kirsher * SMT timer interface 59333f810b2SJeff Kirsher * start RMT timer 0 59433f810b2SJeff Kirsher */ 59533f810b2SJeff Kirsher static void start_rmt_timer0(struct s_smc *smc, u_long value, int event) 59633f810b2SJeff Kirsher { 59733f810b2SJeff Kirsher smc->r.timer0_exp = FALSE ; /* clear timer event flag */ 59833f810b2SJeff Kirsher smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event)); 59933f810b2SJeff Kirsher } 60033f810b2SJeff Kirsher 60133f810b2SJeff Kirsher /* 60233f810b2SJeff Kirsher * SMT timer interface 60333f810b2SJeff Kirsher * start RMT timer 1 60433f810b2SJeff Kirsher */ 60533f810b2SJeff Kirsher static void start_rmt_timer1(struct s_smc *smc, u_long value, int event) 60633f810b2SJeff Kirsher { 60733f810b2SJeff Kirsher smc->r.timer1_exp = FALSE ; /* clear timer event flag */ 60833f810b2SJeff Kirsher smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event)); 60933f810b2SJeff Kirsher } 61033f810b2SJeff Kirsher 61133f810b2SJeff Kirsher /* 61233f810b2SJeff Kirsher * SMT timer interface 61333f810b2SJeff Kirsher * start RMT timer 2 61433f810b2SJeff Kirsher */ 61533f810b2SJeff Kirsher static void start_rmt_timer2(struct s_smc *smc, u_long value, int event) 61633f810b2SJeff Kirsher { 61733f810b2SJeff Kirsher smc->r.timer2_exp = FALSE ; /* clear timer event flag */ 61833f810b2SJeff Kirsher smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event)); 61933f810b2SJeff Kirsher } 62033f810b2SJeff Kirsher 62133f810b2SJeff Kirsher /* 62233f810b2SJeff Kirsher * SMT timer interface 62333f810b2SJeff Kirsher * stop RMT timer 0 62433f810b2SJeff Kirsher */ 62533f810b2SJeff Kirsher static void stop_rmt_timer0(struct s_smc *smc) 62633f810b2SJeff Kirsher { 62733f810b2SJeff Kirsher if (smc->r.rmt_timer0.tm_active) 62833f810b2SJeff Kirsher smt_timer_stop(smc,&smc->r.rmt_timer0) ; 62933f810b2SJeff Kirsher } 63033f810b2SJeff Kirsher 63133f810b2SJeff Kirsher /* 63233f810b2SJeff Kirsher * SMT timer interface 63333f810b2SJeff Kirsher * stop RMT timer 1 63433f810b2SJeff Kirsher */ 63533f810b2SJeff Kirsher static void stop_rmt_timer1(struct s_smc *smc) 63633f810b2SJeff Kirsher { 63733f810b2SJeff Kirsher if (smc->r.rmt_timer1.tm_active) 63833f810b2SJeff Kirsher smt_timer_stop(smc,&smc->r.rmt_timer1) ; 63933f810b2SJeff Kirsher } 64033f810b2SJeff Kirsher 64133f810b2SJeff Kirsher /* 64233f810b2SJeff Kirsher * SMT timer interface 64333f810b2SJeff Kirsher * stop RMT timer 2 64433f810b2SJeff Kirsher */ 64533f810b2SJeff Kirsher static void stop_rmt_timer2(struct s_smc *smc) 64633f810b2SJeff Kirsher { 64733f810b2SJeff Kirsher if (smc->r.rmt_timer2.tm_active) 64833f810b2SJeff Kirsher smt_timer_stop(smc,&smc->r.rmt_timer2) ; 64933f810b2SJeff Kirsher } 65033f810b2SJeff Kirsher 651