📄 skgesirq.c
字号:
/****************************************************************************** * * Name: skgesirq.c * Project: Gigabit Ethernet Adapters, Common Modules * Version: $Revision: 1.92 $ * Date: $Date: 2003/09/16 14:37:07 $ * Purpose: Special IRQ module * ******************************************************************************//****************************************************************************** * * (C)Copyright 1998-2002 SysKonnect. * (C)Copyright 2002-2003 Marvell. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. * ******************************************************************************//* * Special Interrupt handler * * The following abstract should show how this module is included * in the driver path: * * In the ISR of the driver the bits for frame transmission complete and * for receive complete are checked and handled by the driver itself. * The bits of the slow path mask are checked after that and then the * entry into the so-called "slow path" is prepared. It is an implementors * decision whether this is executed directly or just scheduled by * disabling the mask. In the interrupt service routine some events may be * generated, so it would be a good idea to call the EventDispatcher * right after this ISR. * * The Interrupt source register of the adapter is NOT read by this module. * SO if the drivers implementor needs a while loop around the * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for * each loop entered. * * However, the MAC Interrupt status registers are read in a while loop. * */#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))static const char SysKonnectFileId[] = "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";#endif#include "h/skdrv1st.h" /* Driver Specific Definitions */#ifndef SK_SLIM#include "h/skgepnmi.h" /* PNMI Definitions */#include "h/skrlmt.h" /* RLMT Definitions */#endif#include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. *//* local function prototypes */#ifdef GENESISstatic int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);#endif /* GENESIS */#ifdef YUKONstatic int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);#endif /* YUKON */#ifdef OTHER_PHYstatic int SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);#endif /* OTHER_PHY */#ifdef GENESIS/* * array of Rx counter from XMAC which are checked * in AutoSense mode to check whether a link is not able to auto-negotiate. */static const SK_U16 SkGeRxRegs[]= { XM_RXF_64B, XM_RXF_127B, XM_RXF_255B, XM_RXF_511B, XM_RXF_1023B, XM_RXF_MAX_SZ} ;#endif /* GENESIS */#ifdef __C2MAN__/* * Special IRQ function * * General Description: * */intro(){}#endif/****************************************************************************** * * SkHWInitDefSense() - Default Autosensing mode initialization * * Description: sets the PLinkMode for HWInit * * Returns: N/A */static void SkHWInitDefSense(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ pPrt = &pAC->GIni.GP[Port]; pPrt->PAutoNegTimeOut = 0; if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { pPrt->PLinkMode = pPrt->PLinkModeConf; return; } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("AutoSensing: First mode %d on Port %d\n", (int)SK_LMODE_AUTOFULL, Port)); pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL; return;} /* SkHWInitDefSense */#ifdef GENESIS/****************************************************************************** * * SkHWSenseGetNext() - Get Next Autosensing Mode * * Description: gets the appropriate next mode * * Note: * */static SK_U8 SkHWSenseGetNext(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ pPrt = &pAC->GIni.GP[Port]; pPrt->PAutoNegTimeOut = 0; if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { /* Leave all as configured */ return(pPrt->PLinkModeConf); } if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) { /* Return next mode AUTOBOTH */ return ((SK_U8)SK_LMODE_AUTOBOTH); } /* Return default autofull */ return ((SK_U8)SK_LMODE_AUTOFULL);} /* SkHWSenseGetNext *//****************************************************************************** * * SkHWSenseSetNext() - Autosensing Set next mode * * Description: sets the appropriate next mode * * Returns: N/A */static void SkHWSenseSetNext(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port, /* Port Index (MAC_1 + n) */SK_U8 NewMode) /* New Mode to be written in sense mode */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ pPrt = &pAC->GIni.GP[Port]; pPrt->PAutoNegTimeOut = 0; if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { return; } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("AutoSensing: next mode %d on Port %d\n", (int)NewMode, Port)); pPrt->PLinkMode = NewMode; return;} /* SkHWSenseSetNext */#endif /* GENESIS *//****************************************************************************** * * SkHWLinkDown() - Link Down handling * * Description: handles the hardware link down signal * * Returns: N/A */void SkHWLinkDown(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ pPrt = &pAC->GIni.GP[Port]; /* Disable all MAC interrupts */ SkMacIrqDisable(pAC, IoC, Port); /* Disable Receiver and Transmitter */ SkMacRxTxDisable(pAC, IoC, Port); /* Init default sense mode */ SkHWInitDefSense(pAC, IoC, Port); if (pPrt->PHWLinkUp == SK_FALSE) { return; } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Link down Port %d\n", Port)); /* Set Link to DOWN */ pPrt->PHWLinkUp = SK_FALSE; /* Reset Port stati */ pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED; /* Re-init Phy especially when the AutoSense default is set now */ SkMacInitPhy(pAC, IoC, Port, SK_FALSE); /* GP0: used for workaround of Rev. C Errata 2 */ /* Do NOT signal to RLMT */ /* Do NOT start the timer here */} /* SkHWLinkDown *//****************************************************************************** * * SkHWLinkUp() - Link Up handling * * Description: handles the hardware link up signal * * Returns: N/A */void SkHWLinkUp(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ pPrt = &pAC->GIni.GP[Port]; if (pPrt->PHWLinkUp) { /* We do NOT need to proceed on active link */ return; } pPrt->PHWLinkUp = SK_TRUE; pPrt->PAutoNegFail = SK_FALSE; pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF && pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL && pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) { /* Link is up and no Auto-negotiation should be done */ /* Link speed should be the configured one */ switch (pPrt->PLinkSpeed) { case SK_LSPEED_AUTO: /* default is 1000 Mbps */ case SK_LSPEED_1000MBPS: pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; break; case SK_LSPEED_100MBPS: pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; break; case SK_LSPEED_10MBPS: pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; break; } /* Set Link Mode Status */ if (pPrt->PLinkMode == SK_LMODE_FULL) { pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL; } else { pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF; } /* No flow control without auto-negotiation */ pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; /* enable Rx/Tx */ (void)SkMacRxTxEnable(pAC, IoC, Port); }} /* SkHWLinkUp *//****************************************************************************** * * SkMacParity() - MAC parity workaround * * Description: handles MAC parity errors correctly * * Returns: N/A */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_U32 TxMax; /* Tx Max Size Counter */ pPrt = &pAC->GIni.GP[Port]; /* Clear IRQ Tx Parity Error */#ifdef GENESIS if (pAC->GIni.GIGenesis) { SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR); }#endif /* GENESIS */ #ifdef YUKON if (pAC->GIni.GIYukon) { /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE)); }#endif /* YUKON */ 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 */#ifdef GENESIS if (pAC->GIni.GIGenesis) { /* Snap statistic counters */ (void)SkXmUpdateStats(pAC, IoC, Port); (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax); }#endif /* GENESIS */ #ifdef YUKON if (pAC->GIni.GIYukon) { (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax); }#endif /* YUKON */ if (TxMax > 0) { /* From now on check the parity */ pPrt->PCheckPar = SK_TRUE; }} /* SkMacParity *//****************************************************************************** * * SkGeHwErr() - Hardware Error service routine * * Description: handles all HW Error interrupts * * Returns: N/A */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 | IS_IRQ_STAT)) != 0) { /* PCI Errors occured */ if ((HwStatus & IS_IRQ_STAT) != 0) { 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_IN16(IoC, PCI_C(PCI_STATUS), &Word); SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(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); }#ifdef GENESIS if (pAC->GIni.GIGenesis) { if ((HwStatus & IS_NO_STAT_M1) != 0) { /* 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) != 0) { /* 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) != 0) { /* 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) != 0) { /* Ignore it */ /* This situation is also indicated in the descriptor */ SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST); } }#endif /* GENESIS */ #ifdef YUKON if (pAC->GIni.GIYukon) { /* This is necessary only for Rx timing measurements */ if ((HwStatus & IS_IRQ_TIST_OV) != 0) { /* increment Time Stamp Timer counter (high) */ pAC->GIni.GITimeStampCnt++; /* Clear Time Stamp Timer IRQ */ SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ); } if ((HwStatus & IS_IRQ_SENSOR) != 0) { /* no sensors on 32-bit Yukon */ if (pAC->GIni.GIYukon32Bit) { /* disable HW Error IRQ */ pAC->GIni.GIValIrqMask &= ~IS_HW_ERR; } } }#endif /* YUKON */ if ((HwStatus & IS_RAM_RD_PAR) != 0) { 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) != 0) { 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) != 0) { SkMacParity(pAC, IoC, MAC_1); } if ((HwStatus & IS_M2_PAR_ERR) != 0) { SkMacParity(pAC, IoC, MAC_2); } if ((HwStatus & IS_R1_PAR_ERR) != 0) { /* 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) != 0) { /* 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 *//****************************************************************************** * * SkGeSirqIsr() - Special Interrupt Service Routine * * Description: handles all non data transfer specific interrupts (slow path) * * Returns: N/A */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_GEPORT *pPrt; /* GIni Port struct pointer */ SK_U16 PhyInt; int i; 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); } /* * Packet Timeout interrupts */ /* Check whether MACs are correctly initialized */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -