/* * (jd) RMT duplicate address actions * leave the ring or reinsert just as configured */ static void rmt_dup_actions(struct s_smc *smc) { if (smc->r.jm_flag) { } else { if (smc->s.rmt_dup_mac_behavior) { SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ; rmt_reinsert_actions(smc) ; } else { SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ; rmt_leave_actions(smc) ; } } }
/* * duplicate address detected */ static void rmt_new_dup_actions(struct s_smc *smc) { smc->r.da_flag = TRUE ; smc->r.bn_flag = FALSE ; smc->r.jm_flag = FALSE ; /* * we have three options : change address, jam or leave * we leave the ring as default * Optionally it's possible to reinsert after leaving the Ring * but this will not conform with SMT Spec. */ if (smc->s.rmt_dup_mac_behavior) { SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ; rmt_reinsert_actions(smc) ; } else { SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ; rmt_leave_actions(smc) ; } }
/* * Interrupt actions for PLC & PCM events */ void plc_irq(struct s_smc *smc, int np, unsigned int cmd) /* int np; PHY index */ { struct s_phy *phy = &smc->y[np] ; struct s_plc *plc = &phy->plc ; int n ; #ifdef SUPERNET_3 int corr_mask ; #endif /* SUPERNET_3 */ int i ; if (np >= smc->s.numphys) { plc->soft_err++ ; return ; } if (cmd & PL_EBUF_ERR) { /* elastic buff. det. over-|underflow*/ /* * Check whether the SRF Condition occurred. */ if (!plc->ebuf_cont && phy->mib->fddiPORTPCMState == PC8_ACTIVE){ /* * This is the real Elasticity Error. * More than one in a row are treated as a * single one. * Only count this in the active state. */ phy->mib->fddiPORTEBError_Ct ++ ; } plc->ebuf_err++ ; if (plc->ebuf_cont <= 1000) { /* * Prevent counter from being wrapped after * hanging years in that interrupt. */ plc->ebuf_cont++ ; /* Ebuf continous error */ } #ifdef SUPERNET_3 if (plc->ebuf_cont == 1000 && ((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) == PLC_REV_SN3)) { /* * This interrupt remeained high for at least * 1000 consecutive interrupt calls. * * This is caused by a hardware error of the * ORION part of the Supernet III chipset. * * Disable this bit from the mask. */ corr_mask = (plc_imsk_na & ~PL_EBUF_ERR) ; outpw(PLC(np,PL_INTR_MASK),corr_mask); /* * Disconnect from the ring. * Call the driver with the reset indication. */ queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; /* * Make an error log entry. */ SMT_ERR_LOG(smc,SMT_E0136, SMT_E0136_MSG) ; /* * Indicate the Reset. */ drv_reset_indication(smc) ; } #endif /* SUPERNET_3 */ } else { /* Reset the continous error variable */ plc->ebuf_cont = 0 ; /* reset Ebuf continous error */ } if (cmd & PL_PHYINV) { /* physical layer invalid signal */ plc->phyinv++ ; } if (cmd & PL_VSYM_CTR) { /* violation symbol counter has incr.*/ plc->vsym_ctr++ ; } if (cmd & PL_MINI_CTR) { /* dep. on PLC_CNTRL_A's MINI_CTR_INT*/ plc->mini_ctr++ ; } if (cmd & PL_LE_CTR) { /* link error event counter */ int j ; /* * note: PL_LINK_ERR_CTR MUST be read to clear it */ j = inpw(PLC(np,PL_LE_THRESHOLD)) ; i = inpw(PLC(np,PL_LINK_ERR_CTR)) ; if (i < j) { /* wrapped around */ i += 256 ; } if (phy->lem.lem_on) { /* Note: Lem errors shall only be counted when * link is ACTIVE or LCT is active. */ phy->lem.lem_errors += i ; phy->mib->fddiPORTLem_Ct += i ; } } if (cmd & PL_TPC_EXPIRED) { /* TPC timer reached zero */ if (plc->p_state == PS_LCT) { /* * end of LCT */ ; } plc->tpc_exp++ ; } if (cmd & PL_LS_MATCH) { /* LS == LS in PLC_CNTRL_B's MATCH_LS*/ switch (inpw(PLC(np,PL_CNTRL_B)) & PL_MATCH_LS) { case PL_I_IDLE : phy->curr_ls = PC_ILS ; break ; case PL_I_HALT : phy->curr_ls = PC_HLS ; break ; case PL_I_MASTR : phy->curr_ls = PC_MLS ; break ; case PL_I_QUIET : phy->curr_ls = PC_QLS ; break ; } } if (cmd & PL_PCM_BREAK) { /* PCM has entered the BREAK state */ int reason; reason = inpw(PLC(np,PL_STATUS_B)) & PL_BREAK_REASON ; switch (reason) { case PL_B_PCS : plc->b_pcs++ ; break ; case PL_B_TPC : plc->b_tpc++ ; break ; case PL_B_TNE : plc->b_tne++ ; break ; case PL_B_QLS : plc->b_qls++ ; break ; case PL_B_ILS : plc->b_ils++ ; break ; case PL_B_HLS : plc->b_hls++ ; break ; } /*jd 05-Aug-1999 changed: Bug #10419 */ DB_PCMN(1,"PLC %d: MDcF = %x\n", np, smc->e.DisconnectFlag); if (smc->e.DisconnectFlag == FALSE) { DB_PCMN(1,"PLC %d: restart (reason %x)\n", np, reason); queue_event(smc,EVENT_PCM+np,PC_START) ; } else { DB_PCMN(1,"PLC %d: NO!! restart (reason %x)\n", np, reason); } return ; } /* * If both CODE & ENABLE are set ignore enable */ if (cmd & PL_PCM_CODE) { /* receive last sign.-bit | LCT complete */ queue_event(smc,EVENT_PCM+np,PC_SIGNAL) ; n = inpw(PLC(np,PL_RCV_VECTOR)) ; for (i = 0 ; i < plc->p_bits ; i++) { phy->r_val[plc->p_start+i] = n & 1 ; n >>= 1 ; } }