162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * (C)Copyright 1998,1999 SysKonnect, 562306a36Sopenharmony_ci * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * See the file "skfddi.c" for further information. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * The information in this file is provided "AS IS" without warranty. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci ******************************************************************************/ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci SMT RMT 1562306a36Sopenharmony_ci Ring Management 1662306a36Sopenharmony_ci*/ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * Hardware independent state machine implemantation 2062306a36Sopenharmony_ci * The following external SMT functions are referenced : 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * queue_event() 2362306a36Sopenharmony_ci * smt_timer_start() 2462306a36Sopenharmony_ci * smt_timer_stop() 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * The following external HW dependent functions are referenced : 2762306a36Sopenharmony_ci * sm_ma_control() 2862306a36Sopenharmony_ci * sm_mac_check_beacon_claim() 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * The following HW dependent events are required : 3162306a36Sopenharmony_ci * RM_RING_OP 3262306a36Sopenharmony_ci * RM_RING_NON_OP 3362306a36Sopenharmony_ci * RM_MY_BEACON 3462306a36Sopenharmony_ci * RM_OTHER_BEACON 3562306a36Sopenharmony_ci * RM_MY_CLAIM 3662306a36Sopenharmony_ci * RM_TRT_EXP 3762306a36Sopenharmony_ci * RM_VALID_CLAIM 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#include "h/types.h" 4262306a36Sopenharmony_ci#include "h/fddi.h" 4362306a36Sopenharmony_ci#include "h/smc.h" 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define KERNEL 4662306a36Sopenharmony_ci#include "h/smtstate.h" 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* 4962306a36Sopenharmony_ci * FSM Macros 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci#define AFLAG 0x10 5262306a36Sopenharmony_ci#define GO_STATE(x) (smc->mib.m[MAC0].fddiMACRMTState = (x)|AFLAG) 5362306a36Sopenharmony_ci#define ACTIONS_DONE() (smc->mib.m[MAC0].fddiMACRMTState &= ~AFLAG) 5462306a36Sopenharmony_ci#define ACTIONS(x) (x|AFLAG) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#define RM0_ISOLATED 0 5762306a36Sopenharmony_ci#define RM1_NON_OP 1 /* not operational */ 5862306a36Sopenharmony_ci#define RM2_RING_OP 2 /* ring operational */ 5962306a36Sopenharmony_ci#define RM3_DETECT 3 /* detect dupl addresses */ 6062306a36Sopenharmony_ci#define RM4_NON_OP_DUP 4 /* dupl. addr detected */ 6162306a36Sopenharmony_ci#define RM5_RING_OP_DUP 5 /* ring oper. with dupl. addr */ 6262306a36Sopenharmony_ci#define RM6_DIRECTED 6 /* sending directed beacons */ 6362306a36Sopenharmony_ci#define RM7_TRACE 7 /* trace initiated */ 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* 6662306a36Sopenharmony_ci * symbolic state names 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_cistatic const char * const rmt_states[] = { 6962306a36Sopenharmony_ci "RM0_ISOLATED","RM1_NON_OP","RM2_RING_OP","RM3_DETECT", 7062306a36Sopenharmony_ci "RM4_NON_OP_DUP","RM5_RING_OP_DUP","RM6_DIRECTED", 7162306a36Sopenharmony_ci "RM7_TRACE" 7262306a36Sopenharmony_ci} ; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* 7562306a36Sopenharmony_ci * symbolic event names 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_cistatic const char * const rmt_events[] = { 7862306a36Sopenharmony_ci "NONE","RM_RING_OP","RM_RING_NON_OP","RM_MY_BEACON", 7962306a36Sopenharmony_ci "RM_OTHER_BEACON","RM_MY_CLAIM","RM_TRT_EXP","RM_VALID_CLAIM", 8062306a36Sopenharmony_ci "RM_JOIN","RM_LOOP","RM_DUP_ADDR","RM_ENABLE_FLAG", 8162306a36Sopenharmony_ci "RM_TIMEOUT_NON_OP","RM_TIMEOUT_T_STUCK", 8262306a36Sopenharmony_ci "RM_TIMEOUT_ANNOUNCE","RM_TIMEOUT_T_DIRECT", 8362306a36Sopenharmony_ci "RM_TIMEOUT_D_MAX","RM_TIMEOUT_POLL","RM_TX_STATE_CHANGE" 8462306a36Sopenharmony_ci} ; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* 8762306a36Sopenharmony_ci * Globals 8862306a36Sopenharmony_ci * in struct s_rmt 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci/* 9362306a36Sopenharmony_ci * function declarations 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_cistatic void rmt_fsm(struct s_smc *smc, int cmd); 9662306a36Sopenharmony_cistatic void start_rmt_timer0(struct s_smc *smc, u_long value, int event); 9762306a36Sopenharmony_cistatic void start_rmt_timer1(struct s_smc *smc, u_long value, int event); 9862306a36Sopenharmony_cistatic void start_rmt_timer2(struct s_smc *smc, u_long value, int event); 9962306a36Sopenharmony_cistatic void stop_rmt_timer0(struct s_smc *smc); 10062306a36Sopenharmony_cistatic void stop_rmt_timer1(struct s_smc *smc); 10162306a36Sopenharmony_cistatic void stop_rmt_timer2(struct s_smc *smc); 10262306a36Sopenharmony_cistatic void rmt_dup_actions(struct s_smc *smc); 10362306a36Sopenharmony_cistatic void rmt_reinsert_actions(struct s_smc *smc); 10462306a36Sopenharmony_cistatic void rmt_leave_actions(struct s_smc *smc); 10562306a36Sopenharmony_cistatic void rmt_new_dup_actions(struct s_smc *smc); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci#ifndef SUPERNET_3 10862306a36Sopenharmony_ciextern void restart_trt_for_dbcn() ; 10962306a36Sopenharmony_ci#endif /*SUPERNET_3*/ 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* 11262306a36Sopenharmony_ci init RMT state machine 11362306a36Sopenharmony_ci clear all RMT vars and flags 11462306a36Sopenharmony_ci*/ 11562306a36Sopenharmony_civoid rmt_init(struct s_smc *smc) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ; 11862306a36Sopenharmony_ci smc->r.dup_addr_test = DA_NONE ; 11962306a36Sopenharmony_ci smc->r.da_flag = 0 ; 12062306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 12162306a36Sopenharmony_ci smc->r.sm_ma_avail = FALSE ; 12262306a36Sopenharmony_ci smc->r.loop_avail = 0 ; 12362306a36Sopenharmony_ci smc->r.bn_flag = 0 ; 12462306a36Sopenharmony_ci smc->r.jm_flag = 0 ; 12562306a36Sopenharmony_ci smc->r.no_flag = TRUE ; 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci/* 12962306a36Sopenharmony_ci RMT state machine 13062306a36Sopenharmony_ci called by dispatcher 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci do 13362306a36Sopenharmony_ci display state change 13462306a36Sopenharmony_ci process event 13562306a36Sopenharmony_ci until SM is stable 13662306a36Sopenharmony_ci*/ 13762306a36Sopenharmony_civoid rmt(struct s_smc *smc, int event) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci int state ; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci do { 14262306a36Sopenharmony_ci DB_RMT("RMT : state %s%s event %s", 14362306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACRMTState & AFLAG ? "ACTIONS " : "", 14462306a36Sopenharmony_ci rmt_states[smc->mib.m[MAC0].fddiMACRMTState & ~AFLAG], 14562306a36Sopenharmony_ci rmt_events[event]); 14662306a36Sopenharmony_ci state = smc->mib.m[MAC0].fddiMACRMTState ; 14762306a36Sopenharmony_ci rmt_fsm(smc,event) ; 14862306a36Sopenharmony_ci event = 0 ; 14962306a36Sopenharmony_ci } while (state != smc->mib.m[MAC0].fddiMACRMTState) ; 15062306a36Sopenharmony_ci rmt_state_change(smc,(int)smc->mib.m[MAC0].fddiMACRMTState) ; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* 15462306a36Sopenharmony_ci process RMT event 15562306a36Sopenharmony_ci*/ 15662306a36Sopenharmony_cistatic void rmt_fsm(struct s_smc *smc, int cmd) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci /* 15962306a36Sopenharmony_ci * RM00-RM70 : from all states 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_ci if (!smc->r.rm_join && !smc->r.rm_loop && 16262306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) && 16362306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) { 16462306a36Sopenharmony_ci RS_SET(smc,RS_NORINGOP) ; 16562306a36Sopenharmony_ci rmt_indication(smc,0) ; 16662306a36Sopenharmony_ci GO_STATE(RM0_ISOLATED) ; 16762306a36Sopenharmony_ci return ; 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci switch(smc->mib.m[MAC0].fddiMACRMTState) { 17162306a36Sopenharmony_ci case ACTIONS(RM0_ISOLATED) : 17262306a36Sopenharmony_ci stop_rmt_timer0(smc) ; 17362306a36Sopenharmony_ci stop_rmt_timer1(smc) ; 17462306a36Sopenharmony_ci stop_rmt_timer2(smc) ; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci /* 17762306a36Sopenharmony_ci * Disable MAC. 17862306a36Sopenharmony_ci */ 17962306a36Sopenharmony_ci sm_ma_control(smc,MA_OFFLINE) ; 18062306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 18162306a36Sopenharmony_ci smc->r.loop_avail = FALSE ; 18262306a36Sopenharmony_ci smc->r.sm_ma_avail = FALSE ; 18362306a36Sopenharmony_ci smc->r.no_flag = TRUE ; 18462306a36Sopenharmony_ci DB_RMTN(1, "RMT : ISOLATED"); 18562306a36Sopenharmony_ci ACTIONS_DONE() ; 18662306a36Sopenharmony_ci break ; 18762306a36Sopenharmony_ci case RM0_ISOLATED : 18862306a36Sopenharmony_ci /*RM01*/ 18962306a36Sopenharmony_ci if (smc->r.rm_join || smc->r.rm_loop) { 19062306a36Sopenharmony_ci /* 19162306a36Sopenharmony_ci * According to the standard the MAC must be reset 19262306a36Sopenharmony_ci * here. The FORMAC will be initialized and Claim 19362306a36Sopenharmony_ci * and Beacon Frames will be uploaded to the MAC. 19462306a36Sopenharmony_ci * So any change of Treq will take effect NOW. 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_ci sm_ma_control(smc,MA_RESET) ; 19762306a36Sopenharmony_ci GO_STATE(RM1_NON_OP) ; 19862306a36Sopenharmony_ci break ; 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci break ; 20162306a36Sopenharmony_ci case ACTIONS(RM1_NON_OP) : 20262306a36Sopenharmony_ci start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ; 20362306a36Sopenharmony_ci stop_rmt_timer1(smc) ; 20462306a36Sopenharmony_ci stop_rmt_timer2(smc) ; 20562306a36Sopenharmony_ci sm_ma_control(smc,MA_BEACON) ; 20662306a36Sopenharmony_ci DB_RMTN(1, "RMT : RING DOWN"); 20762306a36Sopenharmony_ci RS_SET(smc,RS_NORINGOP) ; 20862306a36Sopenharmony_ci smc->r.sm_ma_avail = FALSE ; 20962306a36Sopenharmony_ci rmt_indication(smc,0) ; 21062306a36Sopenharmony_ci ACTIONS_DONE() ; 21162306a36Sopenharmony_ci break ; 21262306a36Sopenharmony_ci case RM1_NON_OP : 21362306a36Sopenharmony_ci /*RM12*/ 21462306a36Sopenharmony_ci if (cmd == RM_RING_OP) { 21562306a36Sopenharmony_ci RS_SET(smc,RS_RINGOPCHANGE) ; 21662306a36Sopenharmony_ci GO_STATE(RM2_RING_OP) ; 21762306a36Sopenharmony_ci break ; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci /*RM13*/ 22062306a36Sopenharmony_ci else if (cmd == RM_TIMEOUT_NON_OP) { 22162306a36Sopenharmony_ci smc->r.bn_flag = FALSE ; 22262306a36Sopenharmony_ci smc->r.no_flag = TRUE ; 22362306a36Sopenharmony_ci GO_STATE(RM3_DETECT) ; 22462306a36Sopenharmony_ci break ; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci break ; 22762306a36Sopenharmony_ci case ACTIONS(RM2_RING_OP) : 22862306a36Sopenharmony_ci stop_rmt_timer0(smc) ; 22962306a36Sopenharmony_ci stop_rmt_timer1(smc) ; 23062306a36Sopenharmony_ci stop_rmt_timer2(smc) ; 23162306a36Sopenharmony_ci smc->r.no_flag = FALSE ; 23262306a36Sopenharmony_ci if (smc->r.rm_loop) 23362306a36Sopenharmony_ci smc->r.loop_avail = TRUE ; 23462306a36Sopenharmony_ci if (smc->r.rm_join) { 23562306a36Sopenharmony_ci smc->r.sm_ma_avail = TRUE ; 23662306a36Sopenharmony_ci if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable) 23762306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE; 23862306a36Sopenharmony_ci else 23962306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE; 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci DB_RMTN(1, "RMT : RING UP"); 24262306a36Sopenharmony_ci RS_CLEAR(smc,RS_NORINGOP) ; 24362306a36Sopenharmony_ci RS_SET(smc,RS_RINGOPCHANGE) ; 24462306a36Sopenharmony_ci rmt_indication(smc,1) ; 24562306a36Sopenharmony_ci smt_stat_counter(smc,0) ; 24662306a36Sopenharmony_ci ACTIONS_DONE() ; 24762306a36Sopenharmony_ci break ; 24862306a36Sopenharmony_ci case RM2_RING_OP : 24962306a36Sopenharmony_ci /*RM21*/ 25062306a36Sopenharmony_ci if (cmd == RM_RING_NON_OP) { 25162306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 25262306a36Sopenharmony_ci smc->r.loop_avail = FALSE ; 25362306a36Sopenharmony_ci RS_SET(smc,RS_RINGOPCHANGE) ; 25462306a36Sopenharmony_ci GO_STATE(RM1_NON_OP) ; 25562306a36Sopenharmony_ci break ; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci /*RM22a*/ 25862306a36Sopenharmony_ci else if (cmd == RM_ENABLE_FLAG) { 25962306a36Sopenharmony_ci if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable) 26062306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ; 26162306a36Sopenharmony_ci else 26262306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci /*RM25*/ 26562306a36Sopenharmony_ci else if (smc->r.dup_addr_test == DA_FAILED) { 26662306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 26762306a36Sopenharmony_ci smc->r.loop_avail = FALSE ; 26862306a36Sopenharmony_ci smc->r.da_flag = TRUE ; 26962306a36Sopenharmony_ci GO_STATE(RM5_RING_OP_DUP) ; 27062306a36Sopenharmony_ci break ; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci break ; 27362306a36Sopenharmony_ci case ACTIONS(RM3_DETECT) : 27462306a36Sopenharmony_ci start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ; 27562306a36Sopenharmony_ci start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ; 27662306a36Sopenharmony_ci start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; 27762306a36Sopenharmony_ci sm_mac_check_beacon_claim(smc) ; 27862306a36Sopenharmony_ci DB_RMTN(1, "RMT : RM3_DETECT"); 27962306a36Sopenharmony_ci ACTIONS_DONE() ; 28062306a36Sopenharmony_ci break ; 28162306a36Sopenharmony_ci case RM3_DETECT : 28262306a36Sopenharmony_ci if (cmd == RM_TIMEOUT_POLL) { 28362306a36Sopenharmony_ci start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); 28462306a36Sopenharmony_ci sm_mac_check_beacon_claim(smc) ; 28562306a36Sopenharmony_ci break ; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci if (cmd == RM_TIMEOUT_D_MAX) { 28862306a36Sopenharmony_ci smc->r.timer0_exp = TRUE ; 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci /* 29162306a36Sopenharmony_ci *jd(22-Feb-1999) 29262306a36Sopenharmony_ci * We need a time ">= 2*mac_d_max" since we had finished 29362306a36Sopenharmony_ci * Claim or Beacon state. So we will restart timer0 at 29462306a36Sopenharmony_ci * every state change. 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_ci if (cmd == RM_TX_STATE_CHANGE) { 29762306a36Sopenharmony_ci start_rmt_timer0(smc, 29862306a36Sopenharmony_ci smc->s.mac_d_max*2, 29962306a36Sopenharmony_ci RM_TIMEOUT_D_MAX) ; 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci /*RM32*/ 30262306a36Sopenharmony_ci if (cmd == RM_RING_OP) { 30362306a36Sopenharmony_ci GO_STATE(RM2_RING_OP) ; 30462306a36Sopenharmony_ci break ; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci /*RM33a*/ 30762306a36Sopenharmony_ci else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) 30862306a36Sopenharmony_ci && smc->r.bn_flag) { 30962306a36Sopenharmony_ci smc->r.bn_flag = FALSE ; 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci /*RM33b*/ 31262306a36Sopenharmony_ci else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) { 31362306a36Sopenharmony_ci int tx ; 31462306a36Sopenharmony_ci /* 31562306a36Sopenharmony_ci * set bn_flag only if in state T4 or T5: 31662306a36Sopenharmony_ci * only if we're the beaconer should we start the 31762306a36Sopenharmony_ci * trace ! 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_ci if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) { 32062306a36Sopenharmony_ci DB_RMTN(2, "RMT : DETECT && TRT_EXPIRED && T4/T5"); 32162306a36Sopenharmony_ci smc->r.bn_flag = TRUE ; 32262306a36Sopenharmony_ci /* 32362306a36Sopenharmony_ci * If one of the upstream stations beaconed 32462306a36Sopenharmony_ci * and the link to the upstream neighbor is 32562306a36Sopenharmony_ci * lost we need to restart the stuck timer to 32662306a36Sopenharmony_ci * check the "stuck beacon" condition. 32762306a36Sopenharmony_ci */ 32862306a36Sopenharmony_ci start_rmt_timer1(smc,smc->s.rmt_t_stuck, 32962306a36Sopenharmony_ci RM_TIMEOUT_T_STUCK) ; 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci /* 33262306a36Sopenharmony_ci * We do NOT need to clear smc->r.bn_flag in case of 33362306a36Sopenharmony_ci * not being in state T4 or T5, because the flag 33462306a36Sopenharmony_ci * must be cleared in order to get in this condition. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)", 33862306a36Sopenharmony_ci tx, smc->r.bn_flag); 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci /*RM34a*/ 34162306a36Sopenharmony_ci else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) { 34262306a36Sopenharmony_ci rmt_new_dup_actions(smc) ; 34362306a36Sopenharmony_ci GO_STATE(RM4_NON_OP_DUP) ; 34462306a36Sopenharmony_ci break ; 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci /*RM34b*/ 34762306a36Sopenharmony_ci else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) { 34862306a36Sopenharmony_ci rmt_new_dup_actions(smc) ; 34962306a36Sopenharmony_ci GO_STATE(RM4_NON_OP_DUP) ; 35062306a36Sopenharmony_ci break ; 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci /*RM34c*/ 35362306a36Sopenharmony_ci else if (cmd == RM_VALID_CLAIM) { 35462306a36Sopenharmony_ci rmt_new_dup_actions(smc) ; 35562306a36Sopenharmony_ci GO_STATE(RM4_NON_OP_DUP) ; 35662306a36Sopenharmony_ci break ; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci /*RM36*/ 35962306a36Sopenharmony_ci else if (cmd == RM_TIMEOUT_T_STUCK && 36062306a36Sopenharmony_ci smc->r.rm_join && smc->r.bn_flag) { 36162306a36Sopenharmony_ci GO_STATE(RM6_DIRECTED) ; 36262306a36Sopenharmony_ci break ; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci break ; 36562306a36Sopenharmony_ci case ACTIONS(RM4_NON_OP_DUP) : 36662306a36Sopenharmony_ci start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE); 36762306a36Sopenharmony_ci start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ; 36862306a36Sopenharmony_ci start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; 36962306a36Sopenharmony_ci sm_mac_check_beacon_claim(smc) ; 37062306a36Sopenharmony_ci DB_RMTN(1, "RMT : RM4_NON_OP_DUP"); 37162306a36Sopenharmony_ci ACTIONS_DONE() ; 37262306a36Sopenharmony_ci break ; 37362306a36Sopenharmony_ci case RM4_NON_OP_DUP : 37462306a36Sopenharmony_ci if (cmd == RM_TIMEOUT_POLL) { 37562306a36Sopenharmony_ci start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); 37662306a36Sopenharmony_ci sm_mac_check_beacon_claim(smc) ; 37762306a36Sopenharmony_ci break ; 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci /*RM41*/ 38062306a36Sopenharmony_ci if (!smc->r.da_flag) { 38162306a36Sopenharmony_ci GO_STATE(RM1_NON_OP) ; 38262306a36Sopenharmony_ci break ; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci /*RM44a*/ 38562306a36Sopenharmony_ci else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && 38662306a36Sopenharmony_ci smc->r.bn_flag) { 38762306a36Sopenharmony_ci smc->r.bn_flag = FALSE ; 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci /*RM44b*/ 39062306a36Sopenharmony_ci else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) { 39162306a36Sopenharmony_ci int tx ; 39262306a36Sopenharmony_ci /* 39362306a36Sopenharmony_ci * set bn_flag only if in state T4 or T5: 39462306a36Sopenharmony_ci * only if we're the beaconer should we start the 39562306a36Sopenharmony_ci * trace ! 39662306a36Sopenharmony_ci */ 39762306a36Sopenharmony_ci if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) { 39862306a36Sopenharmony_ci DB_RMTN(2, "RMT : NOPDUP && TRT_EXPIRED && T4/T5"); 39962306a36Sopenharmony_ci smc->r.bn_flag = TRUE ; 40062306a36Sopenharmony_ci /* 40162306a36Sopenharmony_ci * If one of the upstream stations beaconed 40262306a36Sopenharmony_ci * and the link to the upstream neighbor is 40362306a36Sopenharmony_ci * lost we need to restart the stuck timer to 40462306a36Sopenharmony_ci * check the "stuck beacon" condition. 40562306a36Sopenharmony_ci */ 40662306a36Sopenharmony_ci start_rmt_timer1(smc,smc->s.rmt_t_stuck, 40762306a36Sopenharmony_ci RM_TIMEOUT_T_STUCK) ; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci /* 41062306a36Sopenharmony_ci * We do NOT need to clear smc->r.bn_flag in case of 41162306a36Sopenharmony_ci * not being in state T4 or T5, because the flag 41262306a36Sopenharmony_ci * must be cleared in order to get in this condition. 41362306a36Sopenharmony_ci */ 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)", 41662306a36Sopenharmony_ci tx, smc->r.bn_flag); 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci /*RM44c*/ 41962306a36Sopenharmony_ci else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) { 42062306a36Sopenharmony_ci rmt_dup_actions(smc) ; 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci /*RM45*/ 42362306a36Sopenharmony_ci else if (cmd == RM_RING_OP) { 42462306a36Sopenharmony_ci smc->r.no_flag = FALSE ; 42562306a36Sopenharmony_ci GO_STATE(RM5_RING_OP_DUP) ; 42662306a36Sopenharmony_ci break ; 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci /*RM46*/ 42962306a36Sopenharmony_ci else if (cmd == RM_TIMEOUT_T_STUCK && 43062306a36Sopenharmony_ci smc->r.rm_join && smc->r.bn_flag) { 43162306a36Sopenharmony_ci GO_STATE(RM6_DIRECTED) ; 43262306a36Sopenharmony_ci break ; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci break ; 43562306a36Sopenharmony_ci case ACTIONS(RM5_RING_OP_DUP) : 43662306a36Sopenharmony_ci stop_rmt_timer0(smc) ; 43762306a36Sopenharmony_ci stop_rmt_timer1(smc) ; 43862306a36Sopenharmony_ci stop_rmt_timer2(smc) ; 43962306a36Sopenharmony_ci DB_RMTN(1, "RMT : RM5_RING_OP_DUP"); 44062306a36Sopenharmony_ci ACTIONS_DONE() ; 44162306a36Sopenharmony_ci break; 44262306a36Sopenharmony_ci case RM5_RING_OP_DUP : 44362306a36Sopenharmony_ci /*RM52*/ 44462306a36Sopenharmony_ci if (smc->r.dup_addr_test == DA_PASSED) { 44562306a36Sopenharmony_ci smc->r.da_flag = FALSE ; 44662306a36Sopenharmony_ci GO_STATE(RM2_RING_OP) ; 44762306a36Sopenharmony_ci break ; 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci /*RM54*/ 45062306a36Sopenharmony_ci else if (cmd == RM_RING_NON_OP) { 45162306a36Sopenharmony_ci smc->r.jm_flag = FALSE ; 45262306a36Sopenharmony_ci smc->r.bn_flag = FALSE ; 45362306a36Sopenharmony_ci GO_STATE(RM4_NON_OP_DUP) ; 45462306a36Sopenharmony_ci break ; 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci break ; 45762306a36Sopenharmony_ci case ACTIONS(RM6_DIRECTED) : 45862306a36Sopenharmony_ci start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ; 45962306a36Sopenharmony_ci stop_rmt_timer1(smc) ; 46062306a36Sopenharmony_ci start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; 46162306a36Sopenharmony_ci sm_ma_control(smc,MA_DIRECTED) ; 46262306a36Sopenharmony_ci RS_SET(smc,RS_BEACON) ; 46362306a36Sopenharmony_ci DB_RMTN(1, "RMT : RM6_DIRECTED"); 46462306a36Sopenharmony_ci ACTIONS_DONE() ; 46562306a36Sopenharmony_ci break ; 46662306a36Sopenharmony_ci case RM6_DIRECTED : 46762306a36Sopenharmony_ci /*RM63*/ 46862306a36Sopenharmony_ci if (cmd == RM_TIMEOUT_POLL) { 46962306a36Sopenharmony_ci start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); 47062306a36Sopenharmony_ci sm_mac_check_beacon_claim(smc) ; 47162306a36Sopenharmony_ci#ifndef SUPERNET_3 47262306a36Sopenharmony_ci /* Because of problems with the Supernet II chip set 47362306a36Sopenharmony_ci * sending of Directed Beacon will stop after 165ms 47462306a36Sopenharmony_ci * therefore restart_trt_for_dbcn(smc) will be called 47562306a36Sopenharmony_ci * to prevent this. 47662306a36Sopenharmony_ci */ 47762306a36Sopenharmony_ci restart_trt_for_dbcn(smc) ; 47862306a36Sopenharmony_ci#endif /*SUPERNET_3*/ 47962306a36Sopenharmony_ci break ; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && 48262306a36Sopenharmony_ci !smc->r.da_flag) { 48362306a36Sopenharmony_ci smc->r.bn_flag = FALSE ; 48462306a36Sopenharmony_ci GO_STATE(RM3_DETECT) ; 48562306a36Sopenharmony_ci break ; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci /*RM64*/ 48862306a36Sopenharmony_ci else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && 48962306a36Sopenharmony_ci smc->r.da_flag) { 49062306a36Sopenharmony_ci smc->r.bn_flag = FALSE ; 49162306a36Sopenharmony_ci GO_STATE(RM4_NON_OP_DUP) ; 49262306a36Sopenharmony_ci break ; 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci /*RM67*/ 49562306a36Sopenharmony_ci else if (cmd == RM_TIMEOUT_T_DIRECT) { 49662306a36Sopenharmony_ci GO_STATE(RM7_TRACE) ; 49762306a36Sopenharmony_ci break ; 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci break ; 50062306a36Sopenharmony_ci case ACTIONS(RM7_TRACE) : 50162306a36Sopenharmony_ci stop_rmt_timer0(smc) ; 50262306a36Sopenharmony_ci stop_rmt_timer1(smc) ; 50362306a36Sopenharmony_ci stop_rmt_timer2(smc) ; 50462306a36Sopenharmony_ci smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ; 50562306a36Sopenharmony_ci queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ; 50662306a36Sopenharmony_ci DB_RMTN(1, "RMT : RM7_TRACE"); 50762306a36Sopenharmony_ci ACTIONS_DONE() ; 50862306a36Sopenharmony_ci break ; 50962306a36Sopenharmony_ci case RM7_TRACE : 51062306a36Sopenharmony_ci break ; 51162306a36Sopenharmony_ci default: 51262306a36Sopenharmony_ci SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ; 51362306a36Sopenharmony_ci break; 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci/* 51862306a36Sopenharmony_ci * (jd) RMT duplicate address actions 51962306a36Sopenharmony_ci * leave the ring or reinsert just as configured 52062306a36Sopenharmony_ci */ 52162306a36Sopenharmony_cistatic void rmt_dup_actions(struct s_smc *smc) 52262306a36Sopenharmony_ci{ 52362306a36Sopenharmony_ci if (smc->r.jm_flag) { 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci else { 52662306a36Sopenharmony_ci if (smc->s.rmt_dup_mac_behavior) { 52762306a36Sopenharmony_ci SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ; 52862306a36Sopenharmony_ci rmt_reinsert_actions(smc) ; 52962306a36Sopenharmony_ci } 53062306a36Sopenharmony_ci else { 53162306a36Sopenharmony_ci SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ; 53262306a36Sopenharmony_ci rmt_leave_actions(smc) ; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci/* 53862306a36Sopenharmony_ci * Reconnect to the Ring 53962306a36Sopenharmony_ci */ 54062306a36Sopenharmony_cistatic void rmt_reinsert_actions(struct s_smc *smc) 54162306a36Sopenharmony_ci{ 54262306a36Sopenharmony_ci queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; 54362306a36Sopenharmony_ci queue_event(smc,EVENT_ECM,EC_CONNECT) ; 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci/* 54762306a36Sopenharmony_ci * duplicate address detected 54862306a36Sopenharmony_ci */ 54962306a36Sopenharmony_cistatic void rmt_new_dup_actions(struct s_smc *smc) 55062306a36Sopenharmony_ci{ 55162306a36Sopenharmony_ci smc->r.da_flag = TRUE ; 55262306a36Sopenharmony_ci smc->r.bn_flag = FALSE ; 55362306a36Sopenharmony_ci smc->r.jm_flag = FALSE ; 55462306a36Sopenharmony_ci /* 55562306a36Sopenharmony_ci * we have three options : change address, jam or leave 55662306a36Sopenharmony_ci * we leave the ring as default 55762306a36Sopenharmony_ci * Optionally it's possible to reinsert after leaving the Ring 55862306a36Sopenharmony_ci * but this will not conform with SMT Spec. 55962306a36Sopenharmony_ci */ 56062306a36Sopenharmony_ci if (smc->s.rmt_dup_mac_behavior) { 56162306a36Sopenharmony_ci SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ; 56262306a36Sopenharmony_ci rmt_reinsert_actions(smc) ; 56362306a36Sopenharmony_ci } 56462306a36Sopenharmony_ci else { 56562306a36Sopenharmony_ci SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ; 56662306a36Sopenharmony_ci rmt_leave_actions(smc) ; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci} 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci/* 57262306a36Sopenharmony_ci * leave the ring 57362306a36Sopenharmony_ci */ 57462306a36Sopenharmony_cistatic void rmt_leave_actions(struct s_smc *smc) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; 57762306a36Sopenharmony_ci /* 57862306a36Sopenharmony_ci * Note: Do NOT try again later. (with please reconnect) 57962306a36Sopenharmony_ci * The station must be left from the ring! 58062306a36Sopenharmony_ci */ 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci/* 58462306a36Sopenharmony_ci * SMT timer interface 58562306a36Sopenharmony_ci * start RMT timer 0 58662306a36Sopenharmony_ci */ 58762306a36Sopenharmony_cistatic void start_rmt_timer0(struct s_smc *smc, u_long value, int event) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci smc->r.timer0_exp = FALSE ; /* clear timer event flag */ 59062306a36Sopenharmony_ci smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event)); 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci/* 59462306a36Sopenharmony_ci * SMT timer interface 59562306a36Sopenharmony_ci * start RMT timer 1 59662306a36Sopenharmony_ci */ 59762306a36Sopenharmony_cistatic void start_rmt_timer1(struct s_smc *smc, u_long value, int event) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci smc->r.timer1_exp = FALSE ; /* clear timer event flag */ 60062306a36Sopenharmony_ci smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event)); 60162306a36Sopenharmony_ci} 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci/* 60462306a36Sopenharmony_ci * SMT timer interface 60562306a36Sopenharmony_ci * start RMT timer 2 60662306a36Sopenharmony_ci */ 60762306a36Sopenharmony_cistatic void start_rmt_timer2(struct s_smc *smc, u_long value, int event) 60862306a36Sopenharmony_ci{ 60962306a36Sopenharmony_ci smc->r.timer2_exp = FALSE ; /* clear timer event flag */ 61062306a36Sopenharmony_ci smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event)); 61162306a36Sopenharmony_ci} 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci/* 61462306a36Sopenharmony_ci * SMT timer interface 61562306a36Sopenharmony_ci * stop RMT timer 0 61662306a36Sopenharmony_ci */ 61762306a36Sopenharmony_cistatic void stop_rmt_timer0(struct s_smc *smc) 61862306a36Sopenharmony_ci{ 61962306a36Sopenharmony_ci if (smc->r.rmt_timer0.tm_active) 62062306a36Sopenharmony_ci smt_timer_stop(smc,&smc->r.rmt_timer0) ; 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci/* 62462306a36Sopenharmony_ci * SMT timer interface 62562306a36Sopenharmony_ci * stop RMT timer 1 62662306a36Sopenharmony_ci */ 62762306a36Sopenharmony_cistatic void stop_rmt_timer1(struct s_smc *smc) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci if (smc->r.rmt_timer1.tm_active) 63062306a36Sopenharmony_ci smt_timer_stop(smc,&smc->r.rmt_timer1) ; 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci/* 63462306a36Sopenharmony_ci * SMT timer interface 63562306a36Sopenharmony_ci * stop RMT timer 2 63662306a36Sopenharmony_ci */ 63762306a36Sopenharmony_cistatic void stop_rmt_timer2(struct s_smc *smc) 63862306a36Sopenharmony_ci{ 63962306a36Sopenharmony_ci if (smc->r.rmt_timer2.tm_active) 64062306a36Sopenharmony_ci smt_timer_stop(smc,&smc->r.rmt_timer2) ; 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 643