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

📄 rhine_main.c

📁 联想网卡驱动 linux环境下编写 初写驱动的同志参考以下
💻 C
📖 第 1 页 / 共 5 页
字号:
static BOOL rhine_mii_read(PRHINE_INFO pInfo, U8 byIdx, PU16 pdata){    WORD    	ww;//    BYTE    	byOrgMIIAD;//    BYTE    	byOrgMIICR;	PMAC_REGS	pMacRegs=pInfo->pMacRegs;//	byOrgMIIAD=readb(&pMacRegs->byMIIAD);//	byOrgMIICR=readb(&pMacRegs->byMIICR);		    // disable MIICR_MAUTO, so that mii addr can be set normally    SafeDisableMiiAutoPoll(pInfo);    	writeb(byIdx,&pMacRegs->byMIIAD);		BYTE_REG_BITS_ON(MIICR_RCMD, &pMacRegs->byMIICR);			    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {    	if (!(readb(&pMacRegs->byMIICR) & MIICR_RCMD))     		break;    }    	*pdata=readw(&pMacRegs->wMIIDATA);	    // for VT3043 only    if (pInfo->chip_id==VT86C100A)		mdelay(1);		    // restore MIICR//    writeb(byOrgMIIAD, &pMacRegs->byMIIAD);//    writeb(byOrgMIICR, &pMacRegs->byMIICR);        EnableMiiAutoPoll(pMacRegs);            if (ww == W_MAX_TIMEOUT) {        return FALSE;    }    return TRUE;}static BOOL rhine_mii_write (PRHINE_INFO pInfo, BYTE byMiiAddr, WORD wData){    WORD    	ww;//    BYTE    	byOrgMIIAD;//    BYTE    	byOrgMIICR;   	PMAC_REGS	pMacRegs=pInfo->pMacRegs;    // keep original MIICR value//	byOrgMIIAD=readb(&pMacRegs->byMIIAD);//	byOrgMIICR=readb(&pMacRegs->byMIICR);    // disable MIICR_MAUTO, so that mii addr can be set normally    SafeDisableMiiAutoPoll(pInfo);    // MII reg offset    writeb(byMiiAddr, &pMacRegs->byMIIAD);    // set MII data    writew(wData,&pMacRegs->wMIIDATA);    // turn on MIICR_WCMD    BYTE_REG_BITS_ON(MIICR_WCMD, &pMacRegs->byMIICR);        // W_MAX_TIMEOUT is the timeout period    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {    	udelay(5);    	if (!(readb(&pMacRegs->byMIICR) & MIICR_WCMD))            break;    }        // for VT3043 only    if (pInfo->chip_id==VT86C100A)		mdelay(1);		    // restore MIICR//    writeb(byOrgMIIAD, &pMacRegs->byMIIAD);//    writeb(byOrgMIICR, &pMacRegs->byMIICR);        EnableMiiAutoPoll(pMacRegs);            if (ww == W_MAX_TIMEOUT) {        return FALSE;    }        return TRUE;}//// Get the media mode stored in EEPROM or module options//static U32 rhine_get_opt_media_mode(PRHINE_INFO pInfo) {	PMAC_REGS	pMacRegs=pInfo->pMacRegs;	U8			byRevId=pInfo->byRevId;	U32			status=0;		if (byRevId<REV_ID_VT6105_A0) {		if (BYTE_REG_BITS_IS_ON(CFGC_MEDEN,&pMacRegs->byCFGC)) {			if (!BYTE_REG_BITS_IS_ON(BCR0_MED2,&pMacRegs->byBCR0)) {							if (BYTE_REG_BITS_IS_ON(BCR1_MED1,&pMacRegs->byBCR1)) {					if (BYTE_REG_BITS_IS_ON(BCR1_MED0,&pMacRegs->byBCR1))						status=RHINE_SPEED_100|RHINE_DUPLEX_FULL;						else						status=RHINE_SPEED_10|RHINE_DUPLEX_FULL;						} else {					if (BYTE_REG_BITS_IS_ON(BCR1_MED0,&pMacRegs->byBCR1))						status=RHINE_SPEED_100;							else						status=RHINE_SPEED_10;				}				pInfo->mii_status=status;				return status;			} 			status=RHINE_AUTONEG_ENABLE;			pInfo->mii_status=status;			return status;		}	} 			switch (pInfo->sOpts.spd_dpx) {	case SPD_DPX_AUTO:		status=RHINE_AUTONEG_ENABLE;		break;	case SPD_DPX_100_FULL:		status=RHINE_SPEED_100|RHINE_DUPLEX_FULL;		break;	case SPD_DPX_10_FULL:		status=RHINE_SPEED_10|RHINE_DUPLEX_FULL;		break;	case SPD_DPX_100_HALF:		status=RHINE_SPEED_100;		break;			case SPD_DPX_10_HALF:		status=RHINE_SPEED_10;		break;	}	pInfo->mii_status=status;	return status;}static void mii_set_auto_on(PRHINE_INFO pInfo){                                                               		U32 		phy_id;			U8			byRevId=pInfo->byRevId;										rhine_mii_read(pInfo, MII_REG_PHYID2, (PU16) &phy_id);				rhine_mii_read(pInfo, MII_REG_PHYID1,	(PU16) &phy_id + 1);			if (byRevId>=REV_ID_VT6102_A) {		if ((byRevId>=REV_ID_VT6105_A0) ||			(((phy_id & 0xFFFFFFF0UL)==0x01018F20UL)			&& ((phy_id & 0xFUL)>4)))								    		MII_REG_BITS_OFF(1, MII_REG_MODCFG, pInfo);	        if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR ,pInfo))            MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR ,pInfo);        else 																	MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, pInfo);		    } else 														    	MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, pInfo);}static void mii_set_auto_off(PRHINE_INFO pInfo){                                                               	U32 phy_id;	U8	byRevId=pInfo->byRevId;	rhine_mii_read(pInfo, MII_REG_PHYID2, (PU16)&phy_id);    rhine_mii_read(pInfo, MII_REG_PHYID1, (PU16)&phy_id + 1);    if ((byRevId>=REV_ID_VT6105_A0) ||     	((byRevId>=REV_ID_VT6102_A) && 		((phy_id & 0xFFFFFFF0UL)==0x01018F20UL) &&		((phy_id & 0xFUL)>4))		)    	MII_REG_BITS_ON(1, MII_REG_MODCFG, pInfo);    MII_REG_BITS_OFF(BMCR_AUTO, MII_REG_BMCR, pInfo);}//// This function check if MAC operation at Full duplex mode//static BOOL rhine_is_full_duplex (PRHINE_INFO pInfo){	U8	byRevId=pInfo->byRevId;	PMAC_REGS	pMacRegs=pInfo->pMacRegs;    // if in AUTO-NEGO mode    if (byRevId>=REV_ID_VT6105_A0)    	return BYTE_REG_BITS_IS_ON(MIISR_N_FDX, &pMacRegs->byMIISR);    if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, pInfo)) {        // if my TX_FD on, check both TX_FD        if (MII_REG_BITS_IS_ON(ANAR_TXFD, MII_REG_ANAR, pInfo)) {            // partner's TX_FD            if (MII_REG_BITS_IS_ON(ANLPAR_TXFD, MII_REG_ANLPAR, pInfo))                return TRUE;        }        // if my T4 on, check both T4        if (MII_REG_BITS_IS_ON(ANAR_T4, MII_REG_ANAR, pInfo)) {            // partner's T4            if (MII_REG_BITS_IS_ON(ANLPAR_T4, MII_REG_ANLPAR, pInfo))                return FALSE;        }        // if my TX_HD on, check both TX_HD        if (MII_REG_BITS_IS_ON(ANAR_TX, MII_REG_ANAR, pInfo)) {            // partner's TX_HD            if (MII_REG_BITS_IS_ON(ANLPAR_TX, MII_REG_ANLPAR, pInfo))                return FALSE;        }        // if my 10_FD on, check both 10_FD        if (MII_REG_BITS_IS_ON(ANAR_10FD, MII_REG_ANAR, pInfo)) {            // partner's 10_FD            if (MII_REG_BITS_IS_ON(ANLPAR_10FD, MII_REG_ANLPAR, pInfo))                return TRUE;        }        // if all above is not, then it would be 10_HD or no link        // both case will be half duplex        return FALSE;    }    // if in force mode    else {        if (!MII_REG_BITS_IS_ON(BMCR_FDX, MII_REG_BMCR, pInfo))            return FALSE;    }    return TRUE;}static void rhine_set_media_mode(PRHINE_INFO pInfo, U32 mii_status) {	U8			byRevId=pInfo->byRevId;	U32			curr_status;	/*	if (pInfo->mii_status & RHINE_AUTONEG_ENABLE) {		MII_REG_BITS_ON(BMCR_RESET, MII_REG_BMCR,pInfo);	}*/	curr_status=rhine_check_media_mode(pInfo) & (~RHINE_LINK_FAIL);	//Enable or Disable PAUSE in ANAR	if (byRevId>=REV_ID_VT6102_A) {		if (pInfo->sOpts.flow_cntl==2) 			MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, pInfo); 				else if (pInfo->sOpts.flow_cntl==3)			MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, pInfo);		}				//Check if new status is consisent with current status    if (((mii_status & curr_status) & RHINE_AUTONEG_ENABLE)     	|| (mii_status==curr_status)) {		pInfo->mii_status=rhine_check_media_mode(pInfo);      	return;    }    	// if connection type is AUTO        if (mii_status & RHINE_AUTONEG_ENABLE) {        // set duplex mode of MAC according to duplex mode of MII        if (rhine_is_full_duplex(pInfo))            rhine_set_duplex(pInfo, TRUE);        else            rhine_set_duplex(pInfo,  FALSE);            		MII_REG_BITS_ON(ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10, 						MII_REG_ANAR, pInfo);		// enable AUTO-NEGO mode		mii_set_auto_on(pInfo);    }    // if not, then    // 1). turn off AUTO-NEGO    // 2). set USER-FORCED speed (10/100) & duplex (half/full) mode of MII and MAC    else if (byRevId<REV_ID_VT6102_A) {		U16    wBMCR;            // turn off AUTO-NEGO		mii_set_auto_off(pInfo);	        // set loopback in MII to un-link in 100M mode,        // in 10M mode set this bit cannot make it un-link        // but it doesn't matter        MII_REG_BITS_ON(BMCR_LBK, MII_REG_BMCR, pInfo);        // read the original value of BMCR register        rhine_mii_read(pInfo,MII_REG_BMCR, &wBMCR);                // mask off AUTO-NEGO        wBMCR &= ~(BMCR_AUTO);                if (mii_status & RHINE_DUPLEX_FULL) {        	wBMCR |=BMCR_FDX;        	rhine_set_duplex(pInfo, TRUE);        }		else {			wBMCR &=(~BMCR_FDX);			rhine_set_duplex(pInfo, FALSE);		}			if (mii_status & RHINE_SPEED_100) 			wBMCR |=BMCR_SPEED;		else			wBMCR &=(~BMCR_SPEED);        	        // write the setting to BMCR register        rhine_mii_write(pInfo,	MII_REG_BMCR, wBMCR);        // delay to avoid link down from force-10M to force-100M (only for 3065 in Win95/Win98)        if (byRevId >= REV_ID_VT6102_A)			mdelay(200);        // unset MII loopback to re-link        MII_REG_BITS_OFF(BMCR_LBK, MII_REG_BMCR, pInfo);		    }    //For VT6105 & VT6102    else {    	WORD	wANAR;		mii_set_auto_off(pInfo);		rhine_mii_read(pInfo, MII_REG_ANAR, &wANAR);		wANAR &= (~(ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10));	        if (mii_status & RHINE_SPEED_100) {        	if (mii_status & RHINE_DUPLEX_FULL) {	        	wANAR |=ANAR_TXFD;	        	rhine_set_duplex(pInfo, TRUE);				}			else {				wANAR |=ANAR_TX;	        	rhine_set_duplex(pInfo, FALSE);					}        }		else {        	if (mii_status & RHINE_DUPLEX_FULL) {	        	wANAR |=ANAR_10FD;	        	rhine_set_duplex(pInfo, TRUE);				}			else {				wANAR |=ANAR_10;	        	rhine_set_duplex(pInfo, FALSE);					}			}			rhine_mii_write(pInfo,MII_REG_ANAR, wANAR);        if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, pInfo))            MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, pInfo);        else            MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, pInfo);    }    mdelay(3000);    pInfo->mii_status=rhine_check_media_mode(pInfo);        }U32 rhine_check_media_mode(PRHINE_INFO pInfo) {	PMAC_REGS			pMacRegs=pInfo->pMacRegs;	U32					status=0;		if (BYTE_REG_BITS_IS_ON(MIISR_LNKFL, &pMacRegs->byMIISR))		status|=RHINE_LINK_FAIL;	    if (BYTE_REG_BITS_IS_ON(MIISR_SPEED, &pMacRegs->byMIISR))        status|=RHINE_SPEED_10;    else         status|=RHINE_SPEED_100;            /* check duplex mode*/        /* if VT6105, check N_FDX bit in MII Status Register directly */    if (rhine_is_full_duplex(pInfo)) {    	rhine_set_duplex(pInfo,TRUE);    	status|=RHINE_DUPLEX_FULL;    }	    else {	   	rhine_set_duplex(pInfo,FALSE);	}	   		if (MII_REG_BITS_IS_ON(BMCR_AUTO,MII_REG_BMCR,pInfo)) {		U16	w;		rhine_mii_read(pInfo, MII_REG_ANAR, &w);		if ((w & (ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10))			==(ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10)) {			status|=RHINE_AUTONEG_ENABLE;		}	}    	    return status;}static void enable_flow_control_ability(PRHINE_INFO pInfo) {	PMAC_REGS	pMacRegs=pInfo->pMacRegs;	U16			wANAR,wANLPAR;	U8			byFlowCR;	if (pInfo->byRevId<REV_ID_VT6102_A)		return;		rhine_mii_read(pInfo,MII_REG_ANAR,&wANAR);	rhine_mii_read(pInfo,MII_REG_ANLPAR,&wANLPAR);	if (pInfo->byRevId<REV_ID_VT6105_A0)		byFlowCR=readb(&pMacRegs->byMISCCR0);	else		byFlowCR=readb(&pMacRegs->byFlowCR1);		if (!(pInfo->mii_status & RHINE_DUPLEX_FULL)) {		//Half duplex mode		if (pInfo->byRevId<REV_ID_VT6105_A0) {			byFlowCR&=~MISC_CR0_FDXRFEN;		}		else {			byFlowCR&=~FLOWCR1_FDXTFCEN;			byFlowCR&=~FLOWCR1_FDXRFCEN;					}			} else {		//Full duplxe mode				if (((wANAR & (ANAR_ASMDIR|ANAR_PAUSE))==ANAR_ASMDIR)			&& ((wANLPAR & (ANLPAR_ASMDIR|ANLPAR_PAUSE))			==(ANLPAR_ASMDIR|ANLPAR_PAUSE))) {							if (pInfo->byRevId<REV_ID_VT6105_A0) {				byFlowCR&=~MISC_CR0_FDXRFEN;			} 			else {				byFlowCR|=FLOWCR1_FDXTFCEN;				byFlowCR&=~FLOWCR1_FDXRFCEN;				}										}			else if ((wANAR & ANAR_PAUSE) && (wANLPAR & ANLPAR_PAUSE)) {			if (pInfo->byRevId<REV_ID_VT6105_A0) 				byFlowCR|=MISC_CR0_FDXRFEN;			else 				byFlowCR|=(FLOWCR1_FDXTFCEN|FLOWCR1_FDXRFCEN);		}		else if (((wANAR & (ANAR_ASMDIR|ANAR_PAUSE))==(ANAR_ASMDIR|ANAR_PAUSE))			&& ((wANLPAR & (ANLPAR_ASMDIR|ANLPAR_PAUSE)) ==ANLPAR_ASMDIR)) {			if (pInfo->byRevId<REV_ID_VT6105_A0)				byFlowCR|=MISC_CR0_FDXRFEN;			else {				byFlowCR&=~FLOWCR1_FDXTFCEN;				byFlowCR|=FLOWCR1_FDXRFCEN;				}				}		else {			if (pInfo->byRevId<REV_ID_VT6105_A0) 				byFlowCR&=~MISC_CR0_FDXRFEN;			else 				byFlowCR&=~(FLOWCR1_FDXTFCEN|FLOWCR1_FDXRFCEN);		}	}	if (pInfo->byRevId< REV_ID_VT6105_A0) {		byFlowCR &=~(MISC_CR0_HDXFEN|MISC_CR0_FDXTFEN); 		writeb(byFlowCR,&pMacRegs->byMISCCR0);	} 	else {		byFlowCR &=~FLOWCR1_HDXFCEN;		writeb(byFlowCR,&pMacRegs->byFlowCR1);	}}/****************************************************************************    ETHTOOL ioctl support routine****************************************************************************/#ifdef RHINE_ETHTOOL_IOCTL_SUPPORTstatic int 	rhine_ethtool_ioctl(struct net_device* dev, struct ifreq* ifr) {	struct ethtool_cmd	ecmd;	PRHINE_INFO		pInfo=(PRHINE_INFO) dev->priv;	PMAC_REGS			pMacRegs=pInfo->pMacRegs;	if (copy_fr

⌨️ 快捷键说明

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