⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skgesirq.c

📁 这是Marvell Technology Group Ltd. 4355 (rev 12)网卡在linux下的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************** * * Name:	skgesirq.c * Project:	Gigabit Ethernet Adapters, Common Modules * Version:	$Revision: 2.42 $ * Date:	$Date: 2008/03/26 15:37:23 $ * Purpose:	Special IRQ module * ******************************************************************************//****************************************************************************** * *	LICENSE: *	(C)Copyright 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. *	/LICENSE * ******************************************************************************//* *	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. * */#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 variables ************************************************************/#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))static const char SysKonnectFileId[] =	"@(#) $Id: skgesirq.c,v 2.42 2008/03/26 15:37:23 rschmidt Exp $ (C) Marvell.";#endif/* local function prototypes */static int	SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);static void	SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);#ifdef __C2MAN__/* *	Special IRQ function * *	General Description: * */intro(){}#endif#ifndef SK_SLIM/****************************************************************************** * *	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,	/* I/O 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) {		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 */#endif/****************************************************************************** * *	SkHWLinkDown() - Link Down handling * * Description: handles the hardware link down signal * * Returns: N/A */void SkHWLinkDown(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 */	pPrt = &pAC->GIni.GP[Port];	/* Disable all MAC interrupts */	SkMacIrqDisable(pAC, IoC, Port);	/* Disable Receiver and Transmitter */	SkMacRxTxDisable(pAC, IoC, Port);#ifndef SK_SLIM	/* Init default sense mode */	SkHWInitDefSense(pAC, IoC, Port);#endif	if (!pPrt->PHWLinkUp) {		return;	}	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,		("Link down Port %d\n", Port));	/* Set Link to DOWN */	pPrt->PHWLinkUp = SK_FALSE;#ifndef SK_SLIM	/* 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;#endif /* !SK_SLIM */	/* 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,	/* I/O 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;#ifndef SK_SLIM	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)				((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) ?				 SK_LSPEED_STAT_1000MBPS : SK_LSPEED_STAT_100MBPS;			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 */		pPrt->PLinkModeStatus = (SK_U8)((pPrt->PLinkMode == SK_LMODE_FULL) ?			 SK_LMODE_STAT_FULL : SK_LMODE_STAT_HALF);		/* No flow control without auto-negotiation */		pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;#endif /* !SK_SLIM */		/* enable Rx/Tx */		(void)SkMacRxTxEnable(pAC, IoC, Port);#ifndef SK_SLIM	}#endif /* !SK_SLIM */}	/* 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,	/* I/O context */int		Port)	/* Port Index (MAC_1 + n) */{	SK_EVPARA	Para;	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */	SK_U32		TxMax;		/* Tx Max Size Counter */	TxMax = 0;	pPrt = &pAC->GIni.GP[Port];	/* clear IRQ Tx Parity Error */	/* 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));	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 */	(void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);	if (TxMax > 0) {		/* From now on check the parity */		pPrt->PCheckPar = SK_TRUE;	}}	/* SkMacParity */#ifndef DISABLE_YUKON_I/****************************************************************************** * *	SkGeYuHwErr() - Hardware Error service routine (Genesis and Yukon) * * Description: handles all HW Error interrupts * * Returns: N/A */static void SkGeYuHwErr(SK_AC	*pAC,		/* Adapter Context */SK_IOC	IoC,		/* I/O context */SK_U32	HwStatus)	/* Interrupt status word */{	SK_EVPARA	Para;	SK_U16		Word;	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,		("HW-Error Status: 0x%08lX\n", HwStatus));	if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {		/* PCI Errors occurred */		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(pAC, PCI_STATUS), &Word);		SK_TST_MODE_ON(IoC);		SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));		SK_TST_MODE_OFF(IoC);		Para.Para64 = 0;		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);	}	/* This is necessary only for Rx timing measurements */	if ((HwStatus & IS_IRQ_TIST_OV) != 0) {		/* increment Time Stamp Timer counter (high) */#ifndef SK_SLIM		pAC->GIni.GITimeStampCnt++;#endif		/* 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;		}	}	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);	}}	/* SkGeYuHwErr */#endif /* !DISABLE_YUKON_I */#ifdef YUK2/****************************************************************************** * *	SkYuk2HwPortErr() - Service HW Errors for specified port (Yukon-2 only) * * Description: handles the HW Error interrupts for a specific port. * * Returns: N/A */static void SkYuk2HwPortErr(SK_AC	*pAC,		/* Adapter Context */SK_IOC	IoC,		/* I/O Context */SK_U32	HwStatus,	/* Interrupt status word */int		Port)		/* Port Index (MAC_1 + n) */{	SK_EVPARA	Para;	int			Queue;	if (Port == MAC_2) {		HwStatus >>= 8;	}	if ((HwStatus & Y2_HWE_L1_MASK) == 0) {		return;	}	if ((HwStatus & Y2_IS_PAR_RD1) != 0) {		/* Clear IRQ */		SK_OUT16(IoC, SELECT_RAM_BUFFER(Port, B3_RI_CTRL), RI_CLR_RD_PERR);		if (Port == MAC_1) {			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E028, SKERR_SIRQ_E028MSG);		}		else {			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E030, SKERR_SIRQ_E030MSG);		}	}	if ((HwStatus & Y2_IS_PAR_WR1) != 0) {		/* Clear IRQ */		SK_OUT16(IoC, SELECT_RAM_BUFFER(Port, B3_RI_CTRL), RI_CLR_WR_PERR);		if (Port == MAC_1) {			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E029, SKERR_SIRQ_E029MSG);		}		else {			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E031, SKERR_SIRQ_E031MSG);		}	}	if ((HwStatus & Y2_IS_PAR_MAC1) != 0) {		/* Clear IRQ */		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), GMF_CLI_TX_PE);		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);		}	}	if ((HwStatus & Y2_IS_PAR_RX1) != 0) {		if (Port == MAC_1) {			Queue = Q_R1;			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);		}		else {			Queue = Q_R2;			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);		}		/* Clear IRQ */		SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_PAR);	}	if ((HwStatus & Y2_IS_TCP_TXS1) != 0) {		if (Port == MAC_1) {			Queue = Q_XS1;			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E033, SKERR_SIRQ_E033MSG);		}		else {			Queue = Q_XS2;			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E035, SKERR_SIRQ_E035MSG);		}		/* Clear IRQ */		SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_TCP);	}	if ((HwStatus & Y2_IS_TCP_TXA1) != 0) {		if (Port == MAC_1) {			Queue = Q_XA1;			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E032, SKERR_SIRQ_E032MSG);		}		else {			Queue = Q_XA2;			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E034, SKERR_SIRQ_E034MSG);		}		/* Clear IRQ */		SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_TCP);	}	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);}	/* SkYuk2HwPortErr *//****************************************************************************** * *	SkYuk2HwErr() - Hardware Error service routine (Yukon-2 only) * * Description: handles all HW Error interrupts * * Returns: N/A */static void SkYuk2HwErr(SK_AC	*pAC,		/* Adapter Context */SK_IOC	IoC,		/* I/O Context */SK_U32	HwStatus)	/* Interrupt status word */{	SK_EVPARA	Para;	SK_U16		Word;	SK_U32		DWord;	SK_U32		TlpHead[4];	int			i;	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,		("HW-Error Status: 0x%08lX\n", HwStatus));	/* This is necessary only for Rx timing measurements */	if ((HwStatus & Y2_IS_TIST_OV) != 0) {#ifndef SK_SLIM		/* increment Time Stamp Timer counter (high) */		pAC->GIni.GITimeStampCnt++;#endif		/* clear Time Stamp Timer IRQ */		SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);	}	/* Evaluate Y2_IS_PCI_NEXP before Y2_IS_MST_ERR or Y2_IS_IRQ_STAT */	if ((HwStatus & Y2_IS_PCI_NEXP) != 0) {		/*		 * This error is also mapped either to Master Abort (Y2_IS_MST_ERR)		 * or Target Abort (Y2_IS_IRQ_STAT) bit and can only be cleared there.		 * Therefore handle this event just by printing an error log entry.		 */		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E027, SKERR_SIRQ_E027MSG);	}	if ((HwStatus & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) != 0) {		/* PCI Errors occurred */		if ((HwStatus & Y2_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(pAC, PCI_STATUS), &Word);		SK_TST_MODE_ON(IoC);		SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));		SK_TST_MODE_OFF(IoC);		Para.Para64 = 0;		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);	}	/* check for PCI-Express Uncorrectable Error*/	if ((HwStatus & Y2_IS_PCI_EXP) != 0) {		/*		 * On PCI-Express bus bridges are called root complexes (RC).		 * PCI-Express errors are recognized by the root complex too,		 * which requests the system to handle the problem. After error		 * occurence it may be that no access to the adapter may be performed		 * any longer.		 */		/* Get uncorrectable error status */		SK_IN32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), &DWord);		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,			("PEX Uncorr.Error Status: 0x%08lX\n", DWord));		if (DWord != PEX_UNSUP_REQ) {			/* ignore Unsupported Request Errors */			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E026, SKERR_SIRQ_E026MSG);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -