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

📄 skgesirq.c

📁 这是Marvell Technology Group Ltd. 4355 (rev 12)网卡在linux下的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	AutoNeg = pPrt->PLinkMode != SK_LMODE_HALF &&			  pPrt->PLinkMode != SK_LMODE_FULL;	Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);	return(Rtv);}	/* SkGePortCheckUp *//****************************************************************************** * * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY * * return: *	0	o.k. nothing needed *	1	Restart needed on this port *	2	Link came up */static int SkGePortCheckUpGmac(SK_AC	*pAC,		/* Adapter Context */SK_IOC	IoC,		/* I/O Context */int		Port,		/* Port Index (MAC_1 + n) */SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */{	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */	int			Done;	SK_U16		PhyStat;	/* PHY Status */	SK_U16		PhySpecStat;/* PHY Specific Status */	SK_U16		ResAb;		/* Master/Slave resolution */#ifndef SK_SLIM	SK_EVPARA	Para;	int			i;	SK_U16		Word;		/* I/O helper */	SK_U16		DspOffs;	/* DSP Register Offset */	SK_U16		DspCtrl;	/* DSP Control Value */	SK_U16		DspIncr;	/* Increment to access MDI pair */#ifdef DEBUG	SK_U16		LinkPartAb;	/* Link Partner Ability */#endif /* DEBUG */#endif /* !SK_SLIM */#ifdef xDEBUG	SK_U64	StartTime;#endif /* DEBUG */	pPrt = &pAC->GIni.GP[Port];	if (pPrt->PHWLinkUp) {		return(SK_HW_PS_NONE);	}	/* Read PHY Status */	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);	if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,			("Phy1000BT: 0x%04X, ", ResAb));		if ((ResAb & PHY_B_1000S_MSF) != 0) {			/* Error */			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,				("Master/Slave Fault, ResAb: 0x%04X\n", ResAb));			pPrt->PAutoNegFail = SK_TRUE;			pPrt->PMSStatus = SK_MS_STAT_FAULT;			return(SK_HW_PS_RESTART);		}	}	/* Read PHY Specific Status */	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,		("PhySpecStat: 0x%04X\n", PhySpecStat));#if (defined(DEBUG) && !defined(SK_SLIM))	/* Read PHY Auto-Negotiation Expansion */	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &LinkPartAb);	if ((LinkPartAb & PHY_ANE_RX_PG) != 0 ||		(PhySpecStat & PHY_M_PS_PAGE_REC) != 0)  {		/* Read PHY Next Page Link Partner */		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,			("Page received, NextPage: 0x%04X\n", Word));	}#endif /* DEBUG && !SK_SLIM */	if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {		/* Link down */		return(SK_HW_PS_NONE);	}#ifndef SK_SLIM	if (pAC->GIni.GICopperType) {#ifdef DEBUG		if ((LinkPartAb & PHY_ANE_LP_CAP) == 0) {			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,				("Link Partner is not AN able, AN Exp.: 0x%04X\n", Word));		}		if ((LinkPartAb & PHY_ANE_PAR_DF) != 0) {			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,				("Parallel Detection Fault, AN Exp.: 0x%04X\n", Word));		}#endif /* DEBUG */		if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {			if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0) {				/* Downshift detected */				Para.Para64 = Port;				SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,					("Downshift detected, PhySpecStat: 0x%04X\n", PhySpecStat));				SK_ERR_LOG(pAC, SK_ERRCL_INFO, SKERR_SIRQ_E025,					SKERR_SIRQ_E025MSG);			}			pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?				SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;		}		if ((PhySpecStat & PHY_M_PS_MDI_X_STAT) != 0) {			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,				("MDI Xover detected, PhyStat: 0x%04X\n", PhySpecStat));		}		if (HW_HAS_NEWER_PHY(pAC)) {			/* on PHY 88E1112 cable length is in Reg. 26, Page 5 */			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {#ifdef XXX				/* select page 5 to access VCT DSP distance register */				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 5);				/* get VCT DSP distance */				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL_2, &PhySpecStat);				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);				pPrt->PCableLen = (SK_U8)(PhySpecStat & PHY_M_EC2_FO_AM_MSK);#endif				DspOffs = 29;				DspCtrl = 0x8754;				DspIncr = 0x1000;			}			else {	/* CHIP_ID_YUKON_EC_U || CHIP_ID_YUKON_EX ||						CHIP_ID_YUKON_SUPR */				DspOffs = 19;				DspCtrl = 0x1018;				DspIncr = 0x0001;				/* select page 0xff to access VCT DSP distance register */				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0x00ff);			}			for (Word = 0, i = 0; i < 4; i++) {				/* select register for MDI pair 0..3 */				SkGmPhyWrite(pAC, IoC, Port, DspOffs, DspCtrl + i * DspIncr);				/* get length for MDI pair 0..3 */				SkGmPhyRead(pAC, IoC, Port, DspOffs + 2, &PhySpecStat);				Word += PhySpecStat;			}			pPrt->PCableLen = Word / 4;	/* calculate the average */			/* set page register back to 0 */			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);		}		else {	/* CHIP_ID_YUKON || CHIP_ID_YUKON_LITE || CHIP_ID_YUKON_EC */			/* on these PHYs the rough estimated cable length is in Reg. 17 */			pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);		}	}#ifdef xDEBUG	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,		("LinkUp Port %d, PHY register dump: 0x%04X\n", Port));	for (i = 0; i < PHY_MARV_PAGE_ADDR; i++) {		/* dump all PHY register */		SkGmPhyRead(pAC, IoC, Port, i, &Word);	}	StartTime = SkOsGetTime(pAC);	while (SkOsGetTime(pAC) - StartTime < SK_TICKS_PER_SEC / 2) {		/* dummy PHY read */		SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word);	}#endif /* DEBUG */#endif /* !SK_SLIM */	if (AutoNeg) {		/* Auto-Negotiation Complete ? */		if ((PhyStat & PHY_ST_AN_OVER) != 0) {			SkHWLinkUp(pAC, IoC, Port);			Done = SkMacAutoNegDone(pAC, IoC, Port);			if (Done != SK_AND_OK) {				return(SK_HW_PS_RESTART);			}			return(SK_HW_PS_LINK);		}	}	else {	/* !AutoNeg */#if (defined(DEBUG) && !defined(SK_SLIM))		if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) {			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,				("ERROR: LiPa auto detected on port %d\n", Port));		}#endif /* DEBUG && !SK_SLIM */		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,			("Link sync, Port %d\n", Port));		SkHWLinkUp(pAC, IoC, Port);		return(SK_HW_PS_LINK);	}	return(SK_HW_PS_NONE);}	/* SkGePortCheckUpGmac *//****************************************************************************** * *	SkGeSirqEvent() - Event Service Routine * * Description: * * Notes: */int	SkGeSirqEvent(SK_AC		*pAC,		/* Adapter Context */SK_IOC		IoC,		/* I/O Context */SK_U32		Event,		/* Module specific Event */SK_EVPARA	Para)		/* Event specific Parameter */{	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */	int			Port;	SK_U16		Word;	SK_U32		Val32;	int			PortStat;#ifndef SK_SLIM	SK_U8		Val8;#endif	Port = (int)Para.Para32[0];	pPrt = &pAC->GIni.GP[Port];	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,		("SIRQ HW Event: %u\n", Event));	switch (Event) {	case SK_HWEV_WATIM:		if (pPrt->PState == SK_PRT_RESET) {			PortStat = SK_HW_PS_NONE;		}		else {			/* Check whether port came up */			PortStat = SkGePortCheckUp(pAC, IoC, Port);		}		switch (PortStat) {		case SK_HW_PS_RESTART:			if (pPrt->PHWLinkUp) {				/* Set Link to down */				SkHWLinkDown(pAC, IoC, Port);				/*				 * Signal directly to RLMT to ensure correct				 * sequence of SWITCH and RESET event.				 */				SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);			}			/* Restart needed */			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);			break;		case SK_HW_PS_LINK:			/* Signal to RLMT */			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);			break;		}		/* Start again the check Timer */		if (pPrt->PHWLinkUp) {			Val32 = SK_WA_ACT_TIME;		}		else {			Val32 = SK_WA_INA_TIME * 5;		}		/* Start workaround Errata #2 timer */		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,			SKGE_HWAC, SK_HWEV_WATIM, Para);		break;	case SK_HWEV_PORT_START:#ifndef SK_SLIM		if (pPrt->PHWLinkUp) {			/*			 * Signal directly to RLMT to ensure correct			 * sequence of SWITCH and RESET event.			 */			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);		}#endif /* !SK_SLIM */		SkHWLinkDown(pAC, IoC, Port);		/* Schedule Port RESET */		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);		/* Start workaround Errata #2 timer */		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,			SKGE_HWAC, SK_HWEV_WATIM, Para);		break;	case SK_HWEV_PORT_STOP:#ifndef SK_SLIM		if (pPrt->PHWLinkUp) {			/*			 * Signal directly to RLMT to ensure correct			 * sequence of SWITCH and RESET event.			 */			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);		}#endif /* !SK_SLIM */		/* Stop Workaround Timer */		SkTimerStop(pAC, IoC, &pPrt->PWaTimer);		SkHWLinkDown(pAC, IoC, Port);		break;#ifndef SK_SLIM	case SK_HWEV_UPDATE_STAT:		/* We do NOT need to update any statistics */		break;	case SK_HWEV_CLEAR_STAT:		/* We do NOT need to clear any statistics */		for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {			pPrt->PPrevRx = 0;			pPrt->PPrevFcs = 0;			pPrt->PPrevShorts = 0;		}		break;	case SK_HWEV_SET_LMODE:		Val8 = (SK_U8)Para.Para32[1];		if (pPrt->PLinkModeConf != Val8) {			/* Set New link mode */			pPrt->PLinkModeConf = Val8;			/* Restart Port */			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);		}		break;	case SK_HWEV_SET_FLOWMODE:		Val8 = (SK_U8)Para.Para32[1];		if (pPrt->PFlowCtrlMode != Val8) {			/* Set New Flow Control mode */			pPrt->PFlowCtrlMode = Val8;			/* Restart Port */			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);		}		break;	case SK_HWEV_SET_ROLE:		/* not possible for fiber */		if (!pAC->GIni.GICopperType) {			break;		}		Val8 = (SK_U8)Para.Para32[1];		if (pPrt->PMSMode != Val8) {			/* Set New Role (Master/Slave) mode */			pPrt->PMSMode = Val8;			/* Restart Port */			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);		}		break;	case SK_HWEV_SET_SPEED:		if (pPrt->PhyType != SK_PHY_MARV_COPPER) {			break;		}		Val8 = (SK_U8)Para.Para32[1];		if (pPrt->PLinkSpeed != Val8) {			/* Set New Speed parameter */			pPrt->PLinkSpeed = Val8;			/* Restart Port */			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);		}		break;#endif /* !SK_SLIM */	case SK_HWEV_PAUSE_PACKET:		/* get Rx GMAC FIFO Write Level */		SK_IN16(IoC, RX_GMF_WLEV, &Word);		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,			("Rx GMAC FIFO Level: 0x%03X\n", Word));		if (Word > (SK_U16)SK_ECU_LLPP) {			/* to signal that a Pause ON Packet was sent */			pPrt->PPauseFlag = SK_FALSE;			/* send one Pause Packet */			GM_IN16(IoC, Port, GM_GP_CTRL, &Word);			/* this will generate also a Pause Packet IRQ */			GM_OUT16(IoC, Port, GM_GP_CTRL, Word | BIT_15S);			/* clear bit 15 to be able to re-send one Pause Packet */			GM_OUT16(IoC, Port, GM_GP_CTRL, Word);			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,				("Send a Pause Packet\n"));		}		break;	default:		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);		break;	}	return(0);}	/* SkGeSirqEvent *//****************************************************************************** * *	SkPhyIsrGmac() - PHY interrupt service routine * * Description: handles all interrupts from Marvell PHY * * Returns: N/A */static void SkPhyIsrGmac(SK_AC		*pAC,		/* Adapter Context */SK_IOC		IoC,		/* I/O Context */int			Port,		/* Port Index (MAC_1 + n) */SK_U16		IStatus)	/* Interrupt Status */{	SK_GEPORT	*pPrt;	/* GIni Port struct pointer */	SK_EVPARA	Para;#ifdef xDEBUG	int		i;	SK_U16		Word;	SK_U32		DWord;#endif /* DEBUG */	pPrt = &pAC->GIni.GP[Port];	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,		("Port %d PHY IRQ, PhyIsrc: 0x%04X\n", Port, IStatus));	if ((IStatus & PHY_M_IS_LST_CHANGE) != 0) {		Para.Para32[0] = (SK_U32)Port;		if (pPrt->PHWLinkUp) {#ifdef xDEBUG			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &Word);			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,				("Link Status changed, PhySpecStat: 0x%04X, ", Word));			/* read the GMAC Interrupt source register */			SK_IN16(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &Word);			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,				("GmacIrqSrc: 0x%02X\n", Word));			if (Word != 0 && (IStatus & PHY_M_IS_SYMB_ERROR) != 0) {				/* read all MIB Counters  */				for (i = 0; i < GM_MIB_CNT_SIZE; i++) {					GM_IN32(IoC, Port, GM_MIB_CNT_BASE + 8*i, &DWord);					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,						("MIB Addr 0x%04X: 0x%08X\n",						BASE_GMAC_1 + GM_MIB_CNT_BASE + 8*i, DWord));				}			}#endif /* DEBUG */			SkHWLinkDown(pAC, IoC, Port);#ifdef XXX			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,				("AutoNeg.Adv: 0x%04X\n", Word));			/* Set Auto-negotiation advertisement */			if (pAC->GIni.GIChipId != CHIP_ID_YUKON_FE &&				pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {				/* restore Asymmetric Pause bit */				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,					(SK_U16)(Word | PHY_M_AN_ASP));			}#endif /* XXX */			/* Signal to RLMT */			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);		}		else {			if ((IStatus & PHY_M_IS_AN_COMPL) != 0) {				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,					("Auto-Negotiation completed\n"));			}			if ((IStatus & PHY_M_IS_LSP_CHANGE) != 0) {				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,					("Link Speed changed\n"));			}			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_WATIM, Para);		}	}	if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {		/* the copper PHY makes 1 retry */		if (pAC->GIni.GICopperType) {			/* not logged as error, it might be the first attempt */			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,				("Auto-Negotiation Error\n"));		}		else {			/* Auto-Negotiation Error */			SK_ERR_LOG(pAC, SK_ERRCL_INFO, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);		}	}	if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {		/* FIFO Overflow/Underrun Error */		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);	}}	/* SkPhyIsrGmac *//* End of File */

⌨️ 快捷键说明

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