📄 skgesirq.c
字号:
pPrt = &pAC->GIni.GP[Port]; /* Clear IRQ */ SK_OUT16(IoC, MR_ADDR(Port,TX_MFF_CTRL1), MFF_CLR_PERR); if (pPrt->PCheckPar) { if (Port == MAC_1) { SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG); } else { SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG); } Para.Para64 = Port; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = Port; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); return; } /* Check whether frames with a size of 1k were sent */ Len = sizeof(SK_U64); SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_MAX, (char *)&TxMax, &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), pAC->Rlmt.Port[Port].Net->NetNumber); if (TxMax > 0) { /* From now on check the parity */ pPrt->PCheckPar = SK_TRUE; }} /* SkMacParity *//****************************************************************************** * * Hardware Error service routine * * Description: * * Notes: */static void SkGeHwErr(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */SK_U32 HwStatus) /* Interrupt status word */{ SK_EVPARA Para; SK_U16 Word; if ((HwStatus & IS_IRQ_MST_ERR) || (HwStatus & IS_IRQ_STAT)) { if (HwStatus & IS_IRQ_STAT) { SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG); } else { SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG); } /* Reset all bits in the PCI STATUS register */ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); } if (HwStatus & IS_NO_STAT_M1) { /* Ignore it */ /* This situation is also indicated in the descriptor */ SK_OUT16(IoC, MR_ADDR(MAC_1,RX_MFF_CTRL1), MFF_CLR_INSTAT); } if (HwStatus & IS_NO_STAT_M2) { /* Ignore it */ /* This situation is also indicated in the descriptor */ SK_OUT16(IoC, MR_ADDR(MAC_2,RX_MFF_CTRL1), MFF_CLR_INSTAT); } if (HwStatus & IS_NO_TIST_M1) { /* Ignore it */ /* This situation is also indicated in the descriptor */ SK_OUT16(IoC, MR_ADDR(MAC_1,RX_MFF_CTRL1), MFF_CLR_INTIST); } if (HwStatus & IS_NO_TIST_M2) { /* Ignore it */ /* This situation is also indicated in the descriptor */ SK_OUT16(IoC, MR_ADDR(MAC_2,RX_MFF_CTRL1), MFF_CLR_INTIST); } if (HwStatus & IS_RAM_RD_PAR) { SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR); SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG); Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); } if (HwStatus & IS_RAM_WR_PAR) { SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR); SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG); Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); } if (HwStatus & IS_M1_PAR_ERR) { SkMacParity(pAC, IoC, MAC_1); } if (HwStatus & IS_M2_PAR_ERR) { SkMacParity(pAC, IoC, MAC_2); } if (HwStatus & IS_R1_PAR_ERR) { /* Clear IRQ */ SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P); SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG); 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 (HwStatus & IS_R2_PAR_ERR) { /* Clear IRQ */ SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P); SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG); 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); }} /* SkGeHwErr *//****************************************************************************** * * Interrupt service routine * * Description: * * Notes: */void SkGeSirqIsr(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */SK_U32 Istatus) /* Interrupt status word */{ SK_EVPARA Para; SK_U32 RegVal32; /* Read register Value */ SK_U16 XmIsr; if (Istatus & IS_HW_ERR) { SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); SkGeHwErr(pAC, IoC, RegVal32); } /* * Packet Timeout interrupts */ /* Check whether XMACs are correctly initialized */ if ((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) && !pAC->GIni.GP[MAC_1].PState) { /* XMAC was not initialized but Packet timeout occured */ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004, SKERR_SIRQ_E004MSG); } if ((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) && !pAC->GIni.GP[MAC_2].PState) { /* XMAC was not initialized but Packet timeout occured */ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005, SKERR_SIRQ_E005MSG); } if (Istatus & IS_PA_TO_RX1) { /* Means network is filling us up */ SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002, SKERR_SIRQ_E002MSG); SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1); } if (Istatus & IS_PA_TO_RX2) { /* Means network is filling us up */ SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003, SKERR_SIRQ_E003MSG); SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2); } if (Istatus & IS_PA_TO_TX1) { unsigned int Len; SK_U64 Octets; SK_GEPORT *pPrt = &pAC->GIni.GP[0]; /* May be a normal situation in a server with a slow network */ SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1); /* * workaround: if in half duplex mode, check for tx hangup. * Read number of TX'ed bytes, wait for 10 ms, then compare * the number with current value. If nothing changed, we * assume that tx is hanging and do a FIFO flush (see event * routine). */ if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && !pPrt->HalfDupTimerActive) { /* * many more pack. arb. timeouts may come in between, * we ignore those */ 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, 0), pAC->Rlmt.Port[0].Net->NetNumber); pPrt->LastOctets = Octets; Para.Para32[0] = 0; SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); } } if (Istatus & IS_PA_TO_TX2) { unsigned int Len; SK_U64 Octets; SK_GEPORT *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) { /* 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) { /* 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) { /* 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) { /* 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) { /* 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) { /* 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) { SK_U16 PhyInt; SK_U16 PhyIMsk; int i; SK_GEPORT *pPrt; /* GIni Port struct pointer */ /* Test IRQs from PHY. */ for (i = 0; i < pAC->GIni.GIMacsFound; i++) { pPrt = &pAC->GIni.GP[i]; switch (pPrt->PhyType) { case SK_PHY_XMAC: break; case SK_PHY_BCOM: if (pPrt->PState) { PHY_READ(IoC, pPrt, i, PHY_BCOM_INT_STAT, &PhyInt); PHY_READ(IoC, pPrt, i, PHY_BCOM_INT_MASK, &PhyIMsk);#ifdef xDEBUG if (PhyInt & PhyIMsk) { CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "SirqIsr - Stat: %x", (void *)PhyInt, (void *)NULL); }#endif /* DEBUG */ if (PhyInt & ~PhyIMsk) { SK_DBG_MSG( pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Port %d Bcom Int: %x Mask: %x\n", i, PhyInt, PhyIMsk)); SkPhyIsrBcom(pAC, IoC, i, PhyInt); } } break; case SK_PHY_LONE: PHY_READ(IoC, pPrt, i, PHY_LONE_INT_STAT, &PhyInt); PHY_READ(IoC, pPrt, i, PHY_LONE_INT_ENAB, &PhyIMsk); if (PhyInt & PhyIMsk) { SK_DBG_MSG( pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Port %d Lone Int: %x Mask: %x\n", i, PhyInt, PhyIMsk)); SkPhyIsrLone(pAC, IoC, i, PhyInt); } break; case SK_PHY_NAT: /* todo: National */ break; } } } /* * I2C Ready interrupt */ if (Istatus & IS_I2C_READY) { SkI2cIsr(pAC, IoC); } if (Istatus & IS_LNK_SYNC_M1) { /* * 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) { XM_IN16(IoC, MAC_1, XM_ISRC, &XmIsr); SkXmIrq(pAC, IoC, MAC_1, XmIsr); } if (Istatus & IS_LNK_SYNC_M2) { /* * 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) { XM_IN16(IoC, MAC_2, XM_ISRC, &XmIsr); SkXmIrq(pAC, IoC, MAC_2, XmIsr); } /* * Timer interrupt * To be served last */ if (Istatus & IS_TIMINT) { SkHwtIsr(pAC, IoC); }} /* SkGeSirqIsr *//****************************************************************************** * * SkGePortCheckShorts - Implementing of the Workaround Errata # 2 * * return: * 0 o.k. nothing needed * 1 Restart needed on this port */int SkGePortCheckShorts(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ SK_U64 Shorts; /* Short Event Counter */ SK_U64 CheckShorts; /* Check value for Short Event Counter */ SK_U64 RxCts; /* RX Counter (packets on network) */ SK_U64 RxTmp; /* RX temp. Counter */ SK_U64 FcsErrCts; /* FCS Error Counter */ SK_GEPORT *pPrt; /* GIni Port struct pointer */ unsigned Len; int Rtv; /* Return value */ int i; pPrt = &pAC->GIni.GP[Port]; /* Default: no action */ Rtv = SK_HW_PS_NONE; /* * Extra precaution: check for short Event counter */ Len = sizeof(SK_U64); SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_RX_SHORTS, (char *)&Shorts, &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), pAC->Rlmt.Port[Port].Net->NetNumber); /* * Read RX counter (packets seen on the network and not neccesarily * really received. */ Len = sizeof(SK_U64); RxCts = 0; for (i = 0; i < sizeof(SkGeRxOids)/sizeof(SK_U32); i++) { SkPnmiGetVar(pAC, IoC, SkGeRxOids[i], (char *)&RxTmp, &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), pAC->Rlmt.Port[Port].Net->NetNumber); RxCts += RxTmp; } /* On default: check shorts against zero */ CheckShorts = 0; /* * Extra 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; Len = sizeof(SK_U64); SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_RX_FCS, (char *)&FcsErrCts, &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), pAC->Rlmt.Port[Port].Net->NetNumber); 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*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -