📄 skgesirq.c
字号:
} if ((DWord & (PEX_FATAL_ERRORS | PEX_POIS_TLP)) != 0) { /* * Stop only, if the uncorrectable error is fatal or * Poisoned TLP occurred */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Header Log:")); for (i = 0; i < 4; i++) { /* get TLP Header from Log Registers */ SK_IN32(IoC, PCI_C(pAC, PEX_HEADER_LOG + i*4), &TlpHead[i]); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, (" 0x%08lX", TlpHead[i])); } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("\n")); /* check for vendor defined broadcast message */ if (TlpHead[0] == 0x73004001 && (SK_U8)TlpHead[1] == 0x7f) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Vendor defined broadcast message\n")); } else { Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); pAC->GIni.GIValHwIrqMask &= ~Y2_IS_PCI_EXP; /* Rewrite HW IRQ mask */ SK_OUT32(IoC, B0_HWE_IMSK, pAC->GIni.GIValHwIrqMask); } } /* clear any PEX errors */ SK_TST_MODE_ON(IoC); SK_OUT32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), 0xffffffffUL); SK_TST_MODE_OFF(IoC); SK_IN32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), &DWord); if ((DWord & PEX_RX_OV) != 0) { /* Dev #4.205 occurred */ pAC->GIni.GIValHwIrqMask &= ~Y2_IS_PCI_EXP; pAC->GIni.GIValIrqMask &= ~Y2_IS_HW_ERR; } } for (i = 0; i < pAC->GIni.GIMacsFound; i++) { SkYuk2HwPortErr(pAC, IoC, HwStatus, i); }} /* SkYuk2HwErr */#endif /* YUK2 *//****************************************************************************** * * SkGeSirqIsr() - Wrapper for Special Interrupt Service Routine * * Description: calls the preselected special ISR (slow path) * * Returns: N/A */void SkGeSirqIsr(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O context */SK_U32 Istatus) /* Interrupt status word */{ pAC->GIni.GIFunc.pSkGeSirqIsr(pAC, IoC, Istatus);}#ifndef DISABLE_YUKON_I/****************************************************************************** * * SkGeYuSirqIsr() - Special Interrupt Service Routine * * Description: handles all non data transfer specific interrupts (slow path) * * Returns: N/A */void SkGeYuSirqIsr(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 Istatus) /* Interrupt status word */{ SK_EVPARA Para; SK_U32 RegVal32; /* Read register value */ SK_GEPORT *pPrt; /* GIni Port struct pointer */ SK_U16 PhyInt; int i; int Rtv; if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) { /* read the HW Error Interrupt source */ SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); SkGeYuHwErr(pAC, IoC, RegVal32); } /* * Packet Timeout interrupts */ /* Check whether MACs are correctly initialized */ if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) && pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) { /* MAC 1 was not initialized but Packet timeout occurred */ 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)) != 0) && pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) { /* MAC 2 was not initialized but Packet timeout occurred */ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005, SKERR_SIRQ_E005MSG); } if ((Istatus & IS_PA_TO_RX1) != 0) { /* 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) != 0) { /* 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) != 0) { pPrt = &pAC->GIni.GP[MAC_1]; /* 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) != 0) { pPrt = &pAC->GIni.GP[MAC_2]; /* 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) != 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; } /* Read PHY Interrupt Status */ Rtv = SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt); if (Rtv == 0 && (PhyInt & PHY_M_DEF_MSK) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Port %d PHY Int: 0x%04X\n", i, PhyInt)); SkPhyIsrGmac(pAC, IoC, i, PhyInt); } } } /* TWSI Ready interrupt */ if ((Istatus & IS_I2C_READY) != 0) {#ifdef SK_SLIM /* clear TWSI IRQ */ SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);#else /* SK_SLIM */ SkI2cIsr(pAC, IoC);#endif /* !SK_SLIM */ } /* 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 * only a link going down. */ /* clear interrupt */ SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LNK_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), LNK_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); SkGeYuHwErr(pAC, IoC, RegVal32); } SkHwtIsr(pAC, IoC); }} /* SkGeYuSirqIsr */#endif /* !DISABLE_YUKON_I */#ifdef YUK2/****************************************************************************** * * SkYuk2PortSirq() - Service HW Errors for specified port (Yukon-2 only) * * Description: handles the HW Error interrupts for a specific port. * * Returns: N/A */static void SkYuk2PortSirq(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 IStatus, /* Interrupt status word */int Port) /* Port Index (MAC_1 + n) */{ SK_EVPARA Para; int Queue; int Rtv; SK_U16 PhyInt; if (Port == MAC_2) { IStatus >>= 8; } /* Interrupt from PHY */ if ((IStatus & Y2_IS_IRQ_PHY1) != 0 && pAC->GIni.GP[Port].PState != SK_PRT_RESET) { /* Read PHY Interrupt Status */ Rtv = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyInt); if (Rtv == 0 && (PhyInt & PHY_M_DEF_MSK) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Port %d PHY Int: 0x%04X\n", Port, PhyInt)); SkPhyIsrGmac(pAC, IoC, Port, PhyInt); } } /* Interrupt from MAC */ if ((IStatus & Y2_IS_IRQ_MAC1) != 0) { SkMacIrq(pAC, IoC, Port); } if ((IStatus & (Y2_IS_CHK_RX1 | Y2_IS_CHK_TXS1 | Y2_IS_CHK_TXA1)) != 0) { if ((IStatus & Y2_IS_CHK_RX1) != 0) { if (Port == MAC_1) { Queue = Q_R1; SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E006, SKERR_SIRQ_E006MSG); } else { Queue = Q_R2; SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E007, SKERR_SIRQ_E007MSG); } /* Clear IRQ */ SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK); } if ((IStatus & Y2_IS_CHK_TXS1) != 0) { if (Port == MAC_1) { Queue = Q_XS1; SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E008, SKERR_SIRQ_E008MSG); } else { Queue = Q_XS2; SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E010, SKERR_SIRQ_E010MSG); } /* Clear IRQ */ SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK); } if ((IStatus & Y2_IS_CHK_TXA1) != 0) { if (Port == MAC_1) { Queue = Q_XA1; SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E009, SKERR_SIRQ_E009MSG); } else { Queue = Q_XA2; SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E011, SKERR_SIRQ_E011MSG); } /* Clear IRQ */ SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK); } 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); }} /* SkYuk2PortSirq */#endif /* YUK2 *//****************************************************************************** * * SkYuk2SirqIsr() - Special Interrupt Service Routine (Yukon-2 only) * * Description: handles all non data transfer specific interrupts (slow path) * * Returns: N/A */void SkYuk2SirqIsr(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 Istatus) /* Interrupt status word */{#ifdef YUK2 SK_GEPORT *pPrt; /* GIni Port struct pointer */ SK_EVPARA Para; SK_U8 Byte; SK_U16 Word; SK_U32 DWord; SK_U32 RegVal32; /* Read register value */ pPrt = &pAC->GIni.GP[MAC_1]; /* HW Error indicated ? */ if (((Istatus & Y2_IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) { /* read the HW Error Interrupt source */ SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); SkYuk2HwErr(pAC, IoC, RegVal32); } /* Interrupt from ASF Subsystem */ if ((Istatus & Y2_IS_ASF) != 0) { /* clear IRQ */ /* later on clearing should be done in ASF ISR handler */ SK_IN8(IoC, B28_Y2_ASF_STAT_CMD, &Byte); SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, Byte | Y2_ASF_CLR_HSTI); /* Call IRQ handler in ASF Module */ /* TBD */ } /* check IRQ from polling unit */ if ((Istatus & Y2_IS_POLL_CHK) != 0) { /* Clear IRQ */ SK_OUT8(IoC, POLL_CTRL, PC_CLR_IRQ_CHK); SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E036, SKERR_SIRQ_E036MSG); Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); } /* TWSI Ready interrupt */ if ((Istatus & Y2_IS_TWSI_RDY) != 0) { /* clear TWSI IRQ */ SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); /* TWSI IRQ is Pause Packet IRQ */ if (HW_FEATURE(pAC, HWF_NEW_FLOW_CONTROL) && pPrt->PLinkSpeedUsed == (SK_U8)SK_LSPEED_STAT_1000MBPS) { /* get number of Xmitted Pause Packets */ (void)SkGmMacStatistic(pAC, IoC, MAC_1, GM_TXF_MPAUSE, &DWord); Word = (SK_U16)(DWord - pPrt->PPauseTxCnt); /* save the value */ pPrt->PPauseTxCnt = DWord;#ifdef DEBUG if (Word != 1) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Pause Packets ON & OFF, %u\n", Word)); }#endif /* DEBUG */ if ((Word % 2) == 1) { /* toggle Pause Packet (On/Off) */ pPrt->PPauseFlag ^= SK_TRUE; } /* get Rx GMAC FIFO Write Level */ SK_IN16(IoC, RX_GMF_WLEV, &Word); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Pause Packet IRQ, Level: 0x%03X, Cnt = %u, Pause %s\n", Word, DWord, pPrt->PPauseFlag ? "ON" : "off")); if (pPrt->PPauseFlag) { /* check if a stopped 30ms timer IRQ is pending */ if ((Istatus & Y2_IS_TIMINT) != 0) { /* clear timer IRQ */ SK_OUT8(IoC, B2_TI_CTRL, TIM_CLR_IRQ); /* to avoid handling this timer IRQ */ Istatus &= ~Y2_IS_TIMINT; } if (Word > (SK_U16)SK_ECU_LLPP) { /* start a 30 ms timer */ Para.Para32[0] = 0; SkTimerStart(pAC, IoC, &pPrt->PPauseTimer, SK_PAUSE_PKT_TIME, SKGE_HWAC, SK_HWEV_PAUSE_PACKET, Para); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("start timer\n")); } } else if (pPrt->PPauseTimer.TmActive) { /* stop the 30 ms timer */ SkTimerStop(pAC, IoC, &pPrt->PPauseTimer); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("stop timer\n")); } }#ifndef SK_SLIM else { SkI2cIsr(pAC, IoC); }#endif } /* SW forced interrupt */ if ((Istatus & Y2_IS_IRQ_SW) != 0) { /* clear the software IRQ */ SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ); } if ((Istatus & Y2_IS_L1_MASK) != 0) { SkYuk2PortSirq(pAC, IoC, Istatus, MAC_1); } if ((Istatus & Y2_IS_L2_MASK) != 0) { SkYuk2PortSirq(pAC, IoC, Istatus, MAC_2); } /* Timer interrupt (served last) */ if ((Istatus & Y2_IS_TIMINT) != 0) { if (((Istatus & Y2_IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) { /* read the HW Error Interrupt source */ SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); /* otherwise we would generate error log entries periodically */ RegVal32 &= pAC->GIni.GIValHwIrqMask; if (RegVal32 != 0) { SkYuk2HwErr(pAC, IoC, RegVal32); } } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Timer Int: 0x%08lX\n", Istatus)); SkHwtIsr(pAC, IoC); }#endif /* YUK2 */} /* SkYuk2SirqIsr *//****************************************************************************** * * 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, /* I/O Context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ int Rtv; /* Return value */ Rtv = SK_HW_PS_NONE; pPrt = &pAC->GIni.GP[Port];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -