📄 skgesirq.c
字号:
pPrt->PLinkModeStatus = SK_LMODE_STAT_FULL; } else { pPrt->PLinkModeStatus = SK_LMODE_STAT_HALF; } /* No flow control without autonegotiation */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE ; /* RX/TX enable */ SkXmRxTxEnable(pAC, IoC, Port); }}/****************************************************************************** * * SkMacParity - does everything to handle MAC parity errors correctly * */static void SkMacParity(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index of the port failed */{ SK_EVPARA Para; SK_GEPORT *pPrt; /* GIni Port struct pointer */ SK_U64 TxMax; /* TxMax Counter */ unsigned int Len; 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(Port)); if (TxMax > 0) { /* From now on check the parity */ pPrt->PCheckPar = SK_TRUE; }}/****************************************************************************** * * 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; if (HwStatus & IS_IRQ_STAT) { SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG) ; Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); } if (HwStatus & IS_IRQ_MST_ERR) { SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG) ; 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); }}/****************************************************************************** * * Interrupt service routine * * Description: * * Notes: */void SkGeSirqIsr(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */SK_U32 Istatus) /* Interrupt status word */{ SK_U32 RegVal32; /* Read register Value */ SK_EVPARA Para; 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) { /* May be a normal situation in a server with a slow network */ SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1) ; } if (Istatus & IS_PA_TO_TX2) { /* May be a normal situation in a server with a slow network */ SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2) ; } /* * 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; /* test IRQs from PHY */ for (i=0; i<pAC->GIni.GIMacsFound; i++) { switch (pAC->GIni.GP[i].PhyType) { case SK_PHY_XMAC: break; case SK_PHY_BCOM: if(pAC->GIni.GP[i].PState) { PHY_READ(IoC, &pAC->GIni.GP[i], i, PHY_BCOM_INT_STAT, &PhyInt); PHY_READ(IoC, &pAC->GIni.GP[i], i, PHY_BCOM_INT_MASK, &PhyIMsk); 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, (SK_U16) (PhyInt & (~PhyIMsk))); } } else { } break; case SK_PHY_LONE: PHY_READ(IoC, &pAC->GIni.GP[i], i, PHY_LONE_INT_STAT, &PhyInt); PHY_READ(IoC, &pAC->GIni.GP[i], 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, (SK_U16) (PhyInt & PhyIMsk)); } 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); }}/* * Define an array of RX counter which are checked * in AutoSense mode to check whether a link is not able to autonegotiate. */static const SK_U32 SkGeRxOids[]= { OID_SKGE_STAT_RX_64, OID_SKGE_STAT_RX_127, OID_SKGE_STAT_RX_255, OID_SKGE_STAT_RX_511, OID_SKGE_STAT_RX_1023, OID_SKGE_STAT_RX_MAX,} ;/****************************************************************************** * * SkGePortCheckShorts - Implementing of the Workaround Errata # 2 * * return: * 0 o.k. nothing needed * 1 Restart needed on this port */int SkGePortCheckShorts(SK_AC *pAC, /* Adapters 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 int 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(Port)); /* * 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(Port)); 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; /* 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(Port)); 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -