📄 skgesirq.c
字号:
} if ((Istatus & IS_PA_TO_TX2) != 0) { pPrt = &pAC->GIni.GP[1]; /* May be a normal situation in a server with a slow network */ SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2); /* workaround: see above */ if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && !pPrt->HalfDupTimerActive) { pPrt->HalfDupTimerActive = SK_TRUE; Len = sizeof(SK_U64); SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 1), pAC->Rlmt.Port[1].Net->NetNumber); pPrt->LastOctets = Octets; Para.Para32[0] = 1; SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); } } /* Check interrupts of the particular queues */ if ((Istatus & IS_R1_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C); SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006, SKERR_SIRQ_E006MSG); Para.Para64 = MAC_1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = MAC_1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } if ((Istatus & IS_R2_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C); SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007, SKERR_SIRQ_E007MSG); Para.Para64 = MAC_2; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = MAC_2; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } if ((Istatus & IS_XS1_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C); SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008, SKERR_SIRQ_E008MSG); Para.Para64 = MAC_1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = MAC_1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } if ((Istatus & IS_XA1_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C); SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009, SKERR_SIRQ_E009MSG); Para.Para64 = MAC_1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = MAC_1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } if ((Istatus & IS_XS2_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C); SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010, SKERR_SIRQ_E010MSG); Para.Para64 = MAC_2; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = MAC_2; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } if ((Istatus & IS_XA2_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C); SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011, SKERR_SIRQ_E011MSG); Para.Para64 = MAC_2; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = MAC_2; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } /* External reg interrupt */ if ((Istatus & IS_EXT_REG) != 0) { /* Test IRQs from PHY */ for (i = 0; i < pAC->GIni.GIMacsFound; i++) { pPrt = &pAC->GIni.GP[i]; if (pPrt->PState == SK_PRT_RESET) { continue; } if (pAC->GIni.GIGenesis) { switch (pPrt->PhyType) { case SK_PHY_XMAC: break; case SK_PHY_BCOM: SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt); if ((PhyInt & ~PHY_B_DEF_MSK) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Port %d Bcom Int: 0x%04X\n", i, PhyInt)); SkPhyIsrBcom(pAC, IoC, i, PhyInt); } break;#ifdef OTHER_PHY case SK_PHY_LONE: SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt); if ((PhyInt & PHY_L_DEF_MSK) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Port %d Lone Int: %x\n", i, PhyInt)); SkPhyIsrLone(pAC, IoC, i, PhyInt); } break;#endif /* OTHER_PHY */ } } else { SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt); if ((PhyInt & PHY_M_DEF_MSK) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Port %d Marv Int: 0x%04X\n", i, PhyInt)); SkPhyIsrGmac(pAC, IoC, i, PhyInt); } } } } /* I2C Ready interrupt */ if ((Istatus & IS_I2C_READY) != 0) { SkI2cIsr(pAC, IoC); } /* SW forced interrupt */ if ((Istatus & IS_IRQ_SW) != 0) { /* clear the software IRQ */ SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ); } if ((Istatus & IS_LNK_SYNC_M1) != 0) { /* * We do NOT need the Link Sync interrupt, because it shows * us only a link going down. */ /* clear interrupt */ SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ); } /* Check MAC after link sync counter */ if ((Istatus & IS_MAC1) != 0) { /* IRQ from MAC 1 */ SkMacIrq(pAC, IoC, MAC_1); } if ((Istatus & IS_LNK_SYNC_M2) != 0) { /* * We do NOT need the Link Sync interrupt, because it shows * us only a link going down. */ /* clear interrupt */ SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ); } /* Check MAC after link sync counter */ if ((Istatus & IS_MAC2) != 0) { /* IRQ from MAC 2 */ SkMacIrq(pAC, IoC, MAC_2); } /* Timer interrupt (served last) */ if ((Istatus & IS_TIMINT) != 0) { /* check for HW Errors */ if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) { /* read the HW Error Interrupt source */ SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); SkGeHwErr(pAC, IoC, RegVal32); } SkHwtIsr(pAC, IoC); }} /* SkGeSirqIsr *//****************************************************************************** * * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2 * * return: * 0 o.k. nothing needed * 1 Restart needed on this port */static int SkGePortCheckShorts(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ SK_U32 Shorts; /* Short Event Counter */ SK_U32 CheckShorts; /* Check value for Short Event Counter */ SK_U64 RxCts; /* Rx Counter (packets on network) */ SK_U32 RxTmp; /* Rx temp. Counter */ SK_U32 FcsErrCts; /* FCS Error Counter */ SK_GEPORT *pPrt; /* GIni Port struct pointer */ int Rtv; /* Return value */ int i; pPrt = &pAC->GIni.GP[Port]; /* Default: no action */ Rtv = SK_HW_PS_NONE; (void)SkXmUpdateStats(pAC, IoC, Port); /* Extra precaution: check for short Event counter */ (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); /* * Read Rx counter (packets seen on the network and not necessarily * really received. */ RxCts = 0; for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) { (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp); RxCts += (SK_U64)RxTmp; } /* On default: check shorts against zero */ CheckShorts = 0; /* Extra precaution on active links */ if (pPrt->PHWLinkUp) { /* Reset Link Restart counter */ pPrt->PLinkResCt = 0; pPrt->PAutoNegTOCt = 0; /* If link is up check for 2 */ CheckShorts = 2; (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts); if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN && (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL)) { /* * This is autosensing and we are in the fallback * manual full/half duplex mode. */ if (RxCts == pPrt->PPrevRx) { /* Nothing received, restart link */ pPrt->PPrevFcs = FcsErrCts; pPrt->PPrevShorts = Shorts; return(SK_HW_PS_RESTART); } else { pPrt->PLipaAutoNeg = SK_LIPA_MANUAL; } } if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) || (!(FcsErrCts - pPrt->PPrevFcs))) { /* * Note: The compare with zero above has to be done the way shown, * otherwise the Linux driver will have a problem. */ /* * We received a bunch of frames or no CRC error occured on the * network -> ok. */ pPrt->PPrevRx = RxCts; pPrt->PPrevFcs = FcsErrCts; pPrt->PPrevShorts = Shorts; return(SK_HW_PS_NONE); } pPrt->PPrevFcs = FcsErrCts; } if ((Shorts - pPrt->PPrevShorts) > CheckShorts) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Short Event Count Restart Port %d \n", Port)); Rtv = SK_HW_PS_RESTART; } pPrt->PPrevShorts = Shorts; pPrt->PPrevRx = RxCts; return(Rtv);} /* SkGePortCheckShorts *//****************************************************************************** * * SkGePortCheckUp() - Check if the link is up * * return: * 0 o.k. nothing needed * 1 Restart needed on this port * 2 Link came up */static int SkGePortCheckUp(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ if (pAC->GIni.GIGenesis) { switch (pAC->GIni.GP[Port].PhyType) { case SK_PHY_XMAC: return(SkGePortCheckUpXmac(pAC, IoC, Port)); case SK_PHY_BCOM: return(SkGePortCheckUpBcom(pAC, IoC, Port));#ifdef OTHER_PHY case SK_PHY_LONE: return(SkGePortCheckUpLone(pAC, IoC, Port)); case SK_PHY_NAT: return(SkGePortCheckUpNat(pAC, IoC, Port));#endif /* OTHER_PHY */ default: return(SK_HW_PS_NONE); } } else { return(SkGePortCheckUpGmac(pAC, IoC, Port)); }} /* SkGePortCheckUp *//****************************************************************************** * * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2 * * return: * 0 o.k. nothing needed * 1 Restart needed on this port * 2 Link came up */static int SkGePortCheckUpXmac(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ SK_U32 Shorts; /* Short Event Counter */ SK_GEPORT *pPrt; /* GIni Port struct pointer */ int Done; SK_U32 GpReg; /* General Purpose register value */ SK_U16 Isrc; /* Interrupt source register */ SK_U16 IsrcSum; /* Interrupt source register sum */ SK_U16 LpAb; /* Link Partner Ability */ SK_U16 ResAb; /* Resolved Ability */ SK_U16 ExtStat; /* Extended Status Register */ SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ SK_U8 NextMode; /* Next AutoSensing Mode */ pPrt = &pAC->GIni.GP[Port]; if (pPrt->PHWLinkUp) { if (pPrt->PhyType != SK_PHY_XMAC) { return(SK_HW_PS_NONE); } else { return(SkGePortCheckShorts(pAC, IoC, Port)); } } IsrcSum = pPrt->PIsave; pPrt->PIsave = 0; /* Now wait for each port's link */ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { AutoNeg = SK_FALSE; } else { AutoNeg = SK_TRUE; } if (pPrt->PLinkBroken) { /* Link was broken */ XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); if ((GpReg & XM_GP_INP_ASS) == 0) { /* The Link is in sync */ XM_IN16(IoC, Port, XM_ISRC, &Isrc); IsrcSum |= Isrc; SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); if ((Isrc & XM_IS_INP_ASS) == 0) { /* It has been in sync since last time */ /* Restart the PORT */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Link in sync Restart Port %d\n", Port)); (void)SkXmUpdateStats(pAC, IoC, Port); /* We now need to reinitialize the PrevShorts counter */ (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); pPrt->PPrevShorts = Shorts; pPrt->PLinkBroken = SK_FALSE; /* * Link Restart Workaround: * it may be possible that the other Link side * restarts its link as well an we detect * another LinkBroken. To prevent this * happening we check for a maximum number * of consecutive restart. If those happens, * we do NOT restart the active link and * check whether the link is now o.k. */ pPrt->PLinkResCt++; pPrt->PAutoNegTimeOut = 0; if (pPrt->PLinkResCt < SK_MAX_LRESTART) { return(SK_HW_PS_RESTART); } pPrt->PLinkResCt = 0; SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum)); } else { pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum)); /* Do nothing more if link is broken */ return(SK_HW_PS_NONE); } } else { /* Do nothing more if link is broken */ return(SK_HW_PS_NONE); } } else { /* Link was not broken, check if it is */ XM_IN16(IoC, Port, XM_ISRC, &Isrc); IsrcSum |= Isrc; if ((Isrc & XM_IS_INP_ASS) != 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -