📄 pcmplc.c
字号:
plc_go_state(smc,np,PL_PCM_STOP) ; mib->fddiPORTConnectState = PCM_DISABLED ; SETMASK(PLC(np,PL_CNTRL_B),PL_MAINT,PL_MAINT) ; sm_ph_linestate(smc,np,(int) MIB2LS(mib->fddiPORTMaint_LS)) ; outpw(PLC(np,PL_CNTRL_A),PL_SC_BYPASS) ; ACTIONS_DONE() ; break ; case PC9_MAINT : DB_PCMN(1,"PCM %c : MAINT\n",phy->phy_name,0) ; /*PC90*/ if (cmd == PC_ENABLE) { GO_STATE(PC0_OFF) ; break ; } break ; default: SMT_PANIC(smc,SMT_E0118, SMT_E0118_MSG) ; break ; }}/* * force line state on a PHY output (only in MAINT state) */static void sm_ph_linestate(struct s_smc *smc, int phy, int ls){ int cntrl ; SK_UNUSED(smc) ; cntrl = (inpw(PLC(phy,PL_CNTRL_B)) & ~PL_MAINT_LS) | PL_PCM_STOP | PL_MAINT ; switch(ls) { case PC_QLS: /* Force Quiet */ cntrl |= PL_M_QUI0 ; break ; case PC_MLS: /* Force Master */ cntrl |= PL_M_MASTR ; break ; case PC_HLS: /* Force Halt */ cntrl |= PL_M_HALT ; break ; default : case PC_ILS: /* Force Idle */ cntrl |= PL_M_IDLE ; break ; case PC_LS_PDR: /* Enable repeat filter */ cntrl |= PL_M_TPDR ; break ; } outpw(PLC(phy,PL_CNTRL_B),cntrl) ;}static void reset_lem_struct(struct s_phy *phy){ struct lem_counter *lem = &phy->lem ; phy->mib->fddiPORTLer_Estimate = 15 ; lem->lem_float_ber = 15 * 100 ;}/* * link error monitor */static void lem_evaluate(struct s_smc *smc, struct s_phy *phy){ int ber ; u_long errors ; struct lem_counter *lem = &phy->lem ; struct fddi_mib_p *mib ; int cond ; mib = phy->mib ; if (!lem->lem_on) return ; errors = inpw(PLC(((int) phy->np),PL_LINK_ERR_CTR)) ; lem->lem_errors += errors ; mib->fddiPORTLem_Ct += errors ; errors = lem->lem_errors ; /* * calculation is called on a intervall of 8 seconds * -> this means, that one error in 8 sec. is one of 8*125*10E6 * the same as BER = 10E-9 * Please note: * -> 9 errors in 8 seconds mean: * BER = 9 * 10E-9 and this is * < 10E-8, so the limit of 10E-8 is not reached! */ if (!errors) ber = 15 ; else if (errors <= 9) ber = 9 ; else if (errors <= 99) ber = 8 ; else if (errors <= 999) ber = 7 ; else if (errors <= 9999) ber = 6 ; else if (errors <= 99999) ber = 5 ; else if (errors <= 999999) ber = 4 ; else if (errors <= 9999999) ber = 3 ; else if (errors <= 99999999) ber = 2 ; else if (errors <= 999999999) ber = 1 ; else ber = 0 ; /* * weighted average */ ber *= 100 ; lem->lem_float_ber = lem->lem_float_ber * 7 + ber * 3 ; lem->lem_float_ber /= 10 ; mib->fddiPORTLer_Estimate = lem->lem_float_ber / 100 ; if (mib->fddiPORTLer_Estimate < 4) { mib->fddiPORTLer_Estimate = 4 ; } if (lem->lem_errors) { DB_PCMN(1,"LEM %c :\n",phy->np == PB? 'B' : 'A',0) ; DB_PCMN(1,"errors : %ld\n",lem->lem_errors,0) ; DB_PCMN(1,"sum_errors : %ld\n",mib->fddiPORTLem_Ct,0) ; DB_PCMN(1,"current BER : 10E-%d\n",ber/100,0) ; DB_PCMN(1,"float BER : 10E-(%d/100)\n",lem->lem_float_ber,0) ; DB_PCMN(1,"avg. BER : 10E-%d\n", mib->fddiPORTLer_Estimate,0) ; } lem->lem_errors = 0L ;#ifndef SLIM_SMT cond = (mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Alarm) ? TRUE : FALSE ;#ifdef SMT_EXT_CUTOFF smt_ler_alarm_check(smc,phy,cond) ;#endif /* nSMT_EXT_CUTOFF */ if (cond != mib->fddiPORTLerFlag) { smt_srf_event(smc,SMT_COND_PORT_LER, (int) (INDEX_PORT+ phy->np) ,cond) ; }#endif if ( mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Cutoff) { phy->pc_lem_fail = TRUE ; /* flag */ mib->fddiPORTLem_Reject_Ct++ ; /* * "forgive 10e-2" if we cutoff so we can come * up again .. */ lem->lem_float_ber += 2*100 ; /*PC81b*/#ifdef CONCENTRATOR DB_PCMN(1,"PCM: LER cutoff on port %d cutoff %d\n", phy->np, mib->fddiPORTLer_Cutoff) ;#endif#ifdef SMT_EXT_CUTOFF smt_port_off_event(smc,phy->np);#else /* nSMT_EXT_CUTOFF */ queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;#endif /* nSMT_EXT_CUTOFF */ }}/* * called by SMT to calculate LEM bit error rate */void sm_lem_evaluate(struct s_smc *smc){ int np ; for (np = 0 ; np < NUMPHYS ; np++) lem_evaluate(smc,&smc->y[np]) ;}static void lem_check_lct(struct s_smc *smc, struct s_phy *phy){ struct lem_counter *lem = &phy->lem ; struct fddi_mib_p *mib ; int errors ; mib = phy->mib ; phy->pc_lem_fail = FALSE ; /* flag */ errors = inpw(PLC(((int)phy->np),PL_LINK_ERR_CTR)) ; lem->lem_errors += errors ; mib->fddiPORTLem_Ct += errors ; if (lem->lem_errors) { switch(phy->lc_test) { case LC_SHORT: if (lem->lem_errors >= smc->s.lct_short) phy->pc_lem_fail = TRUE ; break ; case LC_MEDIUM: if (lem->lem_errors >= smc->s.lct_medium) phy->pc_lem_fail = TRUE ; break ; case LC_LONG: if (lem->lem_errors >= smc->s.lct_long) phy->pc_lem_fail = TRUE ; break ; case LC_EXTENDED: if (lem->lem_errors >= smc->s.lct_extended) phy->pc_lem_fail = TRUE ; break ; } DB_PCMN(1," >>errors : %d\n",lem->lem_errors,0) ; } if (phy->pc_lem_fail) { mib->fddiPORTLCTFail_Ct++ ; mib->fddiPORTLem_Reject_Ct++ ; } else mib->fddiPORTLCTFail_Ct = 0 ;}/* * LEM functions */static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold){ struct lem_counter *lem = &smc->y[np].lem ; lem->lem_on = 1 ; lem->lem_errors = 0L ; /* Do NOT reset mib->fddiPORTLer_Estimate here. It is called too * often. */ outpw(PLC(np,PL_LE_THRESHOLD),threshold) ; (void)inpw(PLC(np,PL_LINK_ERR_CTR)) ; /* clear error counter */ /* enable LE INT */ SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ;}static void sm_ph_lem_stop(struct s_smc *smc, int np){ struct lem_counter *lem = &smc->y[np].lem ; lem->lem_on = 0 ; CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ;}/* ARGSUSED */void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off)/* int on_off; en- or disable ident. ls */{ SK_UNUSED(smc) ; phy = phy ; on_off = on_off ;}/* * PCM pseudo code * receive actions are called AFTER the bit n is received, * i.e. if pc_rcode_actions(5) is called, bit 6 is the next bit to be received *//* * PCM pseudo code 5.1 .. 6.1 */static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy){ struct fddi_mib_p *mib ; mib = phy->mib ; DB_PCMN(1,"SIG rec %x %x: \n", bit,phy->r_val[bit] ) ; bit++ ; switch(bit) { case 0: case 1: case 2: break ; case 3 : if (phy->r_val[1] == 0 && phy->r_val[2] == 0) mib->fddiPORTNeighborType = TA ; else if (phy->r_val[1] == 0 && phy->r_val[2] == 1) mib->fddiPORTNeighborType = TB ; else if (phy->r_val[1] == 1 && phy->r_val[2] == 0) mib->fddiPORTNeighborType = TS ; else if (phy->r_val[1] == 1 && phy->r_val[2] == 1) mib->fddiPORTNeighborType = TM ; break ; case 4: if (mib->fddiPORTMy_Type == TM && mib->fddiPORTNeighborType == TM) { DB_PCMN(1,"PCM %c : E100 withhold M-M\n", phy->phy_name,0) ; mib->fddiPORTPC_Withhold = PC_WH_M_M ; RS_SET(smc,RS_EVENT) ; } else if (phy->t_val[3] || phy->r_val[3]) { mib->fddiPORTPC_Withhold = PC_WH_NONE ; if (mib->fddiPORTMy_Type == TM || mib->fddiPORTNeighborType == TM) phy->pc_mode = PM_TREE ; else phy->pc_mode = PM_PEER ; /* reevaluate the selection criteria (wc_flag) */ all_selection_criteria (smc); if (phy->wc_flag) { mib->fddiPORTPC_Withhold = PC_WH_PATH ; } } else { mib->fddiPORTPC_Withhold = PC_WH_OTHER ; RS_SET(smc,RS_EVENT) ; DB_PCMN(1,"PCM %c : E101 withhold other\n", phy->phy_name,0) ; } phy->twisted = ((mib->fddiPORTMy_Type != TS) && (mib->fddiPORTMy_Type != TM) && (mib->fddiPORTNeighborType == mib->fddiPORTMy_Type)) ; if (phy->twisted) { DB_PCMN(1,"PCM %c : E102 !!! TWISTED !!!\n", phy->phy_name,0) ; } break ; case 5 : break ; case 6: if (phy->t_val[4] || phy->r_val[4]) { if ((phy->t_val[4] && phy->t_val[5]) || (phy->r_val[4] && phy->r_val[5]) ) phy->lc_test = LC_EXTENDED ; else phy->lc_test = LC_LONG ; } else if (phy->t_val[5] || phy->r_val[5]) phy->lc_test = LC_MEDIUM ; else phy->lc_test = LC_SHORT ; switch (phy->lc_test) { case LC_SHORT : /* 50ms */ outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LENGTH ) ; phy->t_next[7] = smc->s.pcm_lc_short ; break ; case LC_MEDIUM : /* 500ms */ outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LONGLN ) ; phy->t_next[7] = smc->s.pcm_lc_medium ; break ; case LC_LONG : SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ; phy->t_next[7] = smc->s.pcm_lc_long ; break ; case LC_EXTENDED : SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ; phy->t_next[7] = smc->s.pcm_lc_extended ; break ; } if (phy->t_next[7] > smc->s.pcm_lc_medium) { start_pcm_timer0(smc,phy->t_next[7],PC_TIMEOUT_LCT,phy); } DB_PCMN(1,"LCT timer = %ld us\n", phy->t_next[7], 0) ; phy->t_next[9] = smc->s.pcm_t_next_9 ; break ; case 7: if (phy->t_val[6]) { phy->cf_loop = TRUE ; } phy->td_flag = TRUE ; break ; case 8: if (phy->t_val[7] || phy->r_val[7]) { DB_PCMN(1,"PCM %c : E103 LCT fail %s\n", phy->phy_name,phy->t_val[7]? "local":"remote") ; queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ; } break ; case 9: if (phy->t_val[8] || phy->r_val[8]) { if (phy->t_val[8]) phy->cf_loop = TRUE ; phy->td_flag = TRUE ; } break ; case 10: if (phy->r_val[9]) { /* neighbor intends to have MAC on output */ ; mib->fddiPORTMacIndicated.R_val = TRUE ; } else { /* neighbor does not intend to have MAC on output */ ; mib->fddiPORTMacIndicated.R_val = FALSE ; } break ; }}/* * PCM pseudo code 5.1 .. 6.1 */static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy){ int np = phy->np ; struct fddi_mib_p *mib ; mib = phy->mib ; switch(bit) { case 0: phy->t_val[0] = 0 ; /* no escape used */ break ; case 1: if (mib->fddiPORTMy_Type == TS || mib->fddiPORTMy_Type == TM) phy->t_val[1] = 1 ; else phy->t_val[1] = 0 ; break ; case 2 : if (mib->fddiPORTMy_Type == TB || mib->fddiPORTMy_Type == TM) phy->t_val[2] = 1 ; else phy->t_val[2] = 0 ; break ; case 3: { int type,ne ; int policy ; type = mib->fddiPORTMy_Type ; ne = mib->fddiPORTNeighborType ; policy = smc->mib.fddiSMTConnectionPolicy ; phy->t_val[3] = 1 ; /* Accept connection */ switch (type) { case TA : if ( ((policy & POLICY_AA) && ne == TA) || ((policy & POLICY_AB) && ne == TB) || ((policy & POLICY_AS) && ne == TS) || ((policy & POLICY_AM) && ne == TM) ) phy->t_val[3] = 0 ; /* Reject */ break ; case TB : if ( ((policy & POLICY_BA) && ne == TA) || ((policy & POLICY_BB) && ne == TB) || ((policy & POLICY_BS) && ne == TS) || ((policy & POLICY_BM) && ne == TM) ) phy->t_val[3] = 0 ; /* Reject */ break ; case TS : if ( ((policy & POLICY_SA) && ne == TA) || ((policy & POLICY_SB) && ne == TB) || ((policy & POLICY_SS) && ne == TS) || ((policy & POLICY_SM) && ne == TM) ) phy->t_val[3] = 0 ; /* Reject */ break ; case TM : if ( ne == TM || ((policy & POLICY_MA) && ne == TA) || ((policy & POLICY_MB) && ne == TB) || ((policy & POLICY_MS) && ne == TS) || ((policy & POLICY_MM) && ne == TM) ) phy->t_val[3] = 0 ; /* Reject */ break ; }#ifndef SLIM_SMT /* * detect undesirable connection attempt event */ if ( (type == TA && ne == TA ) || (type == TA && ne == TS ) || (type == TB && ne == TB ) || (type == TB && ne == TS ) || (type == TS && ne == TA ) || (type == TS && ne == TB ) ) { smt_srf_event(smc,SMT_EVENT_PORT_CONNECTION, (int) (INDEX_PORT+ phy->np) ,0) ; }#endif } break ; case 4: if (mib->fddiPORTPC_Withhold == PC_WH_NONE) { if (phy->pc_lem_fail) { phy->t_val[4] = 1 ; /* long */ phy->t_val[5] = 0 ; } else { phy->t_val[4] = 0 ; if (mib->fddiPORTLCTFail_Ct > 0) phy->t_val[5] = 1 ; /* medium */ else phy->t_val[5] = 0 ; /* short */ /* * Implementers choice: use medium * instead of short when undesired * connection attempt is made. */ if (phy->wc_flag) phy->t_val[5] = 1 ; /* medium */ } mib->fddiPORTConnectState = PCM_CONNECTING ; } else { mib->fddiPORTConnectState = PCM_STANDBY ; phy->t_val[4] = 1 ; /* extended */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -