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

📄 lan9118.c

📁 Lan9118以太网芯片linux驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:


	/* wait for read to complete w/ timeout
 */
	for(i = 0U; i < 100U; i++) {

		/* see if MII is finished yet
 */
		if ((Lan_GetMacRegDW(dwLanBase, MII_ACC) & MII_ACC_MII_BUSY_) == 0UL)

		{

			/* get the read data from the MAC & return i
 */
			result=((NGushort)Lan_GetMacRegDW(dwLanBase, MII_DATA));

			goto DONE;

		}

	}

#ifdef SMC_DEBUG
	OS_TEXT_OUT ("timeout waiting for MII write to finish\n");

#endif


DONE:

	ngOSIntrCtl(ictrl);
	return result;

}

/* Phy_SetRegW () writes a 16-bit phy register values */
void Phy_SetRegW(
	const NGifnet * const netp,
	const DWORD dwRegIndex, NGushort wVal)
{
	PLAN9118_DATA pLan9118Data;
	DWORD dwLanBase;
	int ictrl;	/* save previous interrupt state */
	DWORD dwAddr=0UL;
	NGuint i=0U;

	dwLanBase = (DWORD) NG_ETHIF_DATA(((void *) netp), eif_base);
	pLan9118Data = (PLAN9118_DATA) netp->if_devptr1;

	ictrl = ngOSIntrCtl(NG_INTRCTL_DISABLE);

	if(dwRegIndex==0UL) {

		if((wVal&0x1200)==0x1200) {

			pLan9118Data->wLastADVatRestart=pLan9118Data->wLastADV;

		}

	}

	if(dwRegIndex==4UL) {

		pLan9118Data->wLastADV=wVal;

	}



	/* confirm MII not busy
 */
	if ((Lan_GetMacRegDW(dwLanBase, MII_ACC) & MII_ACC_MII_BUSY_) != 0UL)

	{

#ifdef SMC_DEBUG
		OS_TEXT_OUT ("MII is busy in Phy_SetRegW???\n");

#endif
		goto DONE;

	}



	/* put the data to write in the MAC
 */
	Lan_SetMacRegDW(dwLanBase, MII_DATA, (DWORD)wVal);



	/* set the address, index & direction (write to PHY)
 */
	dwAddr = ((pLan9118Data->dwPhyAddress&0x1FUL)<<11) | ((dwRegIndex & 0x1FUL)<<6) | MII_ACC_MII_WRITE_;

	Lan_SetMacRegDW(dwLanBase, MII_ACC, dwAddr);



	/* wait for write to complete w/ timeout
 */
	for(i = 0U; i < 100U; i++) {

		/* see if MII is finished yet
 */
		if ((Lan_GetMacRegDW(dwLanBase, MII_ACC) & MII_ACC_MII_BUSY_) == 0UL)

		{

			goto DONE;

		}

	}

#ifdef SMC_DEBUG
	OS_TEXT_OUT ("timeout waiting for MII write to finish\n");

#endif
DONE:

	ngOSIntrCtl(ictrl);
}


#ifdef SMC_DEBUG
typedef struct _SHOW_REG
{
	NGubyte  szName[20];
	DWORD dwOffset;
} SHOW_REG;

/*
FUNCTION: Lan_ShowRegs
    This function is used to display the registers. 
	Except the phy.
*/
void Lan_ShowRegs(const DWORD dwLanBase)
{
	/*	Make these const struct's static to keep them off the stack.
		Otherwise, gcc will try to use _memcpy() to initialize them,
		which will *NOT* work in our RunTime environment.
	*/
	static const SHOW_REG sysCsr[] = {
		{ "ID_REV",		ID_REV		},
		{ "INT_CFG",		INT_CFG		},
		{ "INT_STS",		INT_STS		},
		{ "INT_EN",		INT_EN		},
		{ "BYTE_TEST",		BYTE_TEST	},
		{ "FIFO_INT",		FIFO_INT	},
		{ "RX_CFG",		RX_CFG		},
		{ "TX_CFG",		TX_CFG		},
		{ "HW_CFG",		HW_CFG		},
		{ "RX_DP_CTL",		RX_DP_CTRL	},
		{ "RX_FIFO_INF",	RX_FIFO_INF	},
		{ "TX_FIFO_INF",	TX_FIFO_INF	},
		{ "PMT_CTRL",		PMT_CTRL	},
		{ "GPIO_CFG",		GPIO_CFG	},
		{ "GPT_CFG",		GPT_CFG		},
		{ "GPT_CNT",		GPT_CNT		},
		{ "ENDIAN",		ENDIAN		},
		{ "FREE_RUN",		FREE_RUN	},
		{ "RX_DROP",		RX_DROP		},
		{ "MAC_CSR_CMD",	MAC_CSR_CMD	},
		{ "MAC_CSR_DATA",	MAC_CSR_DATA},
		{ "AFC_CFG",		AFC_CFG		},
		{ "E2P_CMD",		E2P_CMD		},
		{ "E2P_DATA",		E2P_DATA	},
		{ "TEST_REG_A",		TEST_REG_A	}};

	static const SHOW_REG macCsr[] = {
		{ "MAC_CR",		MAC_CR		},
		{ "ADDRH",		ADDRH		},
		{ "ADDRL",		ADDRL		},
		{ "HASHH",		HASHH		},
		{ "HASHL",		HASHL		},
		{ "MII_ACC",		MII_ACC		},
		{ "MII_DATA",		MII_DATA	},
		{ "FLOW",		FLOW		},
		{ "VLAN1",		VLAN1		},
		{ "VLAN2",		VLAN2		},
		{ "WUFF",		WUFF		},
		{ "WUCSR",		WUCSR		}};

	NGuint i, iNumSysRegs, iNumMacRegs;
	DWORD dwOldMacCmdReg, dwOldMacDataReg;
	char buf [256];

	iNumSysRegs = (sizeof(sysCsr) / sizeof(SHOW_REG));
	iNumMacRegs = (sizeof(macCsr) / sizeof(SHOW_REG));

	/* preserve MAC cmd/data reg's */
	dwOldMacCmdReg = GetRegDW(dwLanBase, MAC_CSR_CMD);
	dwOldMacDataReg = GetRegDW(dwLanBase, MAC_CSR_DATA);

	OS_TEXT_OUT ("\n");
	OS_TEXT_OUT ("               LAN91C118 CSR's\n");
	OS_TEXT_OUT ("                     SYS CSR's                     MAC CSR's\n");

	for (i = 0U; i < iNumMacRegs; i++)
	{
		sprintf (buf,	
			"%16s (0x%02lX) = 0x%08lX, %8s (0x%02lX) + 0x%08lX\n",
			sysCsr[i].szName, 
			sysCsr[i].dwOffset, 
			GetRegDW(dwLanBase, sysCsr[i].dwOffset),
			macCsr[i].szName, 
			macCsr[i].dwOffset, 
			Lan_GetMacRegDW(dwLanBase, macCsr[i].dwOffset));
		OS_TEXT_OUT (buf);

		/* restore original mac cmd/data reg's after each usage */
		SetRegDW(dwLanBase, MAC_CSR_CMD, dwOldMacCmdReg);
		SetRegDW(dwLanBase, MAC_CSR_DATA, dwOldMacDataReg);
	}

	for (i=iNumMacRegs; i<iNumSysRegs; i++)
	{
		sprintf (buf, "%16s (0x%02lX) = 0x%08lX\n", 
			sysCsr[i].szName, 
			sysCsr[i].dwOffset, 
			GetRegDW(dwLanBase, sysCsr[i].dwOffset));
		OS_TEXT_OUT (buf);
	}
}
#endif

/*
FUNCTION: Lan_Initialize
  This function should be the first Lan_xxx function called
  It begins to initialize the LAN9118_DATA structure.
  It reads some ID values from the chip.
  It resets the chip.

RETURN VALUE:
	returns TRUE on Success,
	returns FALSE on Failure,
*/
BOOLEAN Lan_Initialize(const NGifnet * const netp)
{
	PLAN9118_DATA pLan9118Data;
	BOOLEAN result=FALSE;
	DWORD dwIdRev=0UL;
	DWORD dwTimeout;
	DWORD dwTemp;
	DWORD dwLanBase;
#ifdef SMC_DEBUG
	char buf [256];
#endif

	pLan9118Data = (PLAN9118_DATA) netp->if_devptr1;
	dwLanBase = (DWORD) NG_ETHIF_DATA(((void *) netp), eif_base);
#ifdef SMC_DEBUG
	sprintf (buf, "-->Lan_Initialize(dwLanBase=0x%08lX,pLan9118Data=0x%08lX)\n",
		dwLanBase,(DWORD)pLan9118Data);
	OS_TEXT_OUT (buf);
#endif

	if(pLan9118Data==NULL) {
		goto DONE;
	}

	ngMemSet ((void *) pLan9118Data, 0, sizeof(LAN9118_DATA));

	dwIdRev=GetRegDW(dwLanBase,ID_REV);

	SetRegDW(dwLanBase,HW_CFG,HW_CFG_SRST_);
	dwTimeout=1000UL;
	do {
		dwTemp=GetRegDW(dwLanBase,HW_CFG);
		dwTimeout--;
	} while((dwTimeout > 0UL) && (dwTemp & HW_CFG_SRST_));
	if(dwTemp&HW_CFG_SRST_) {
#ifdef SMC_DEBUG
		OS_TEXT_OUT("  Failed to complete reset.\n");
#endif
		goto DONE;
	}

	pLan9118Data->dwIdRev=dwIdRev;
	pLan9118Data->GpioSetting=0x00170700UL;

	SetRegDW(dwLanBase,HW_CFG,0x00050000UL);
	SetRegDW(dwLanBase,AFC_CFG,0x006E3740UL);

	result=TRUE;
DONE:
#ifdef SMC_DEBUG
	sprintf (buf,"<--Lan_Initialize, result=%s\n",result?"TRUE":"FALSE");
	OS_TEXT_OUT (buf);
#endif
    return result;
}

/* Phy_SetLink(netp) does link management settings */
void Phy_SetLink(const NGifnet * const netp)
{
	if(NG_ETHIF_DATA(((void *) netp), eif_flags) & NG_ETHIFF_AUTONEG) {
		NGushort wTemp;
		NGushort eif_linkadv;

		wTemp=Phy_GetRegW(netp, PHY_ANEG_ADV);
		wTemp = (NGushort) (wTemp & (~PHY_ANEG_ADV_PAUSE_));
		wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_ASYMP_);
		wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_SYMP_);
		wTemp= (NGushort) (wTemp & (~PHY_ANEG_ADV_SPEED_));
		eif_linkadv = GetLinkAdv (netp);
		if(eif_linkadv & NG_ETHIF_AUTONEG_10BASET) {
			wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_10H_);
		}
		if(eif_linkadv & NG_ETHIF_AUTONEG_10BASET_FD) {
			wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_10F_);
		}
		if(eif_linkadv & NG_ETHIF_AUTONEG_100BASETX) {
			wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_100H_);
		}
		if(eif_linkadv & NG_ETHIF_AUTONEG_100BASETX_FD) {
			wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_100F_);
		}
		Phy_SetRegW(netp,PHY_ANEG_ADV,wTemp);

		/* begin to establish link */
		Phy_SetRegW(netp, PHY_BCR,
			(NGushort) (PHY_BCR_AUTO_NEG_ENABLE_|
			PHY_BCR_RESTART_AUTO_NEG_));
	} else {	// non-autonegotiate
		NGubyte eif_linkcfg;
		NGushort wTemp=(NGushort) 0;

		eif_linkcfg = GetLinkCfg (netp);
		if((eif_linkcfg == NG_ETHIF_LINK_10BASET_FD) || (eif_linkcfg == NG_ETHIF_LINK_100BASETX_FD)) {
			wTemp=(NGushort) (wTemp | PHY_BCR_DUPLEX_MODE_);
		}
		if((eif_linkcfg == NG_ETHIF_LINK_100BASETX) || (eif_linkcfg == NG_ETHIF_LINK_100BASETX_FD)) {
			wTemp=(NGushort) (wTemp | PHY_BCR_SPEED_SELECT_);
		}
        	Phy_SetRegW(netp,PHY_BCR,wTemp);
	}
}

/* Phy_GetLinkMode(netp) reads the current link settings */
void Phy_GetLinkMode(const NGifnet * const netp)
{
	const LAN9118_DATA *pLan9118Data;
	NGushort wRegVal=(NGushort) 0;
	const NGushort wRegBSR=Phy_GetRegW(netp, PHY_BSR);

	pLan9118Data = (PLAN9118_DATA) netp->if_devptr1;

	SetLink (netp, (NGubyte) NG_ETHIF_LINK_DOWN);
	if(wRegBSR&PHY_BSR_LINK_STATUS_) {
		wRegVal=Phy_GetRegW(netp, PHY_BCR);
		if(wRegVal&PHY_BCR_AUTO_NEG_ENABLE_) {
			const NGushort wRegADV=pLan9118Data->wLastADVatRestart;
			NGushort wRegLPA=Phy_GetRegW(netp, PHY_ANEG_LPA);

			wRegLPA=(NGushort) (wRegLPA & wRegADV);
			if(wRegLPA&PHY_ANEG_LPA_100FDX_) {
				SetLink (netp, (NGubyte) NG_ETHIF_LINK_100BASETX_FD);
			} else if(wRegLPA&PHY_ANEG_LPA_100HDX_) {
				SetLink (netp, (NGubyte) NG_ETHIF_LINK_100BASETX);
			} else if(wRegLPA&PHY_ANEG_LPA_10FDX_) {
				SetLink (netp, (NGubyte) NG_ETHIF_LINK_10BASET_FD);
			} else if(wRegLPA&PHY_ANEG_LPA_10HDX_) {
				SetLink (netp, (NGubyte) NG_ETHIF_LINK_10BASET);
			}
			else {
			}
		} else {
			if(wRegVal&PHY_BCR_SPEED_SELECT_) {
				if(wRegVal&PHY_BCR_DUPLEX_MODE_) {
					SetLink (netp, (NGubyte) NG_ETHIF_LINK_100BASETX_FD);
				} else {
					SetLink (netp, (NGubyte) NG_ETHIF_LINK_100BASETX);
				}
			} else {
				if(wRegVal&PHY_BCR_DUPLEX_MODE_) {
					SetLink (netp, (NGubyte) NG_ETHIF_LINK_10BASET_FD);
				} else {
					SetLink (netp, (NGubyte) NG_ETHIF_LINK_10BASET);
				}
			}
		}
	}
}

/* Phy_UpdateLinkMode(netp) detects any link changes */
void Phy_UpdateLinkMode(const NGifnet * const netp)
{
#ifdef SMC_DEBUG
	char buffer [256];
#endif
	DWORD dwLanBase;
	DWORD dwTemp;
 	NGubyte bOldLink, bNewLink;

	dwLanBase = (DWORD) NG_ETHIF_DATA(((void *) netp), eif_base);

	bOldLink = GetLink (netp);
	Phy_GetLinkMode(netp);
	bNewLink = GetLink (netp);

	if(bOldLink != bNewLink) {
		if(bNewLink != NG_ETHIF_LINK_DOWN) {
			DWORD dwRegVal=0UL;
			switch(bNewLink) {
			case NG_ETHIF_LINK_10BASET:
#ifdef SMC_DEBUG
				OS_TEXT_OUT ("Link is now UP at 10Mbps HD\n");
#endif
				break;
			case NG_ETHIF_LINK_10BASET_FD:
#ifdef SMC_DEBUG
				OS_TEXT_OUT ("Link is now UP at 10Mbps FD\n");
#endif
				break;
			case NG_ETHIF_LINK_100BASETX:
#ifdef SMC_DEBUG
				OS_TEXT_OUT ("Link is now UP at 100Mbps HD\n");
#endif
				break;
			case NG_ETHIF_LINK_100BASETX_FD:
#ifdef SMC_DEBUG
				OS_TEXT_OUT ("Link is now UP at 100Mbps FD\n");
#endif
				break;
			default:
#ifdef SMC_DEBUG
				sprintf (buffer, "Link is now UP at Unknown Link Speed, eif_link=0x%08lX\n",
					bNewLink);
				OS_TEXT_OUT (buffer);
#endif
				break;
			}

			dwRegVal=Lan_GetMacRegDW(dwLanBase,MAC_CR);
			dwRegVal&=~(MAC_CR_FDPX_|MAC_CR_RCVOWN_);
			switch(bNewLink) {
			  case NG_ETHIF_LINK_10BASET:
			  case NG_ETHIF_LINK_100BASETX:
				dwRegVal|=MAC_CR_RCVOWN_;
				break;
			  case NG_ETHIF_LINK_10BASET_FD:
			  case NG_ETHIF_LINK_100BASETX_FD:
				dwRegVal|=MAC_CR_FDPX_;
				break;
			  default:	
				break;
			}

			Lan_SetMacRegDW(dwLanBase, MAC_CR,dwRegVal);

			if(NG_ETHIF_DATA(((void *) netp), eif_flags) & NG_ETHIFF_AUTONEG) {
				NGushort linkPartner=(NGushort) 0;
				NGushort localLink=(NGushort) 0;
				localLink=Phy_GetRegW(netp,4UL);
				linkPartner=Phy_GetRegW(netp,5UL);
				switch(bNewLink) {
			  	case NG_ETHIF_LINK_10BASET_FD:
			  	case NG_ETHIF_LINK_100BASETX_FD:
					if(((localLink&linkPartner)&((NGushort)0x0400U)) != ((NGushort)0U)) {
						/* Enable PAUSE receive and transmit
 */
						Lan_SetMacRegDW(dwLanBase,FLOW,0xFFFF0002UL);
						dwTemp = GetRegDW(dwLanBase,AFC_CFG);
						dwTemp |= 0x0000000FUL;
						SetRegDW(dwLanBase,AFC_CFG,dwTemp);
					} else if(((localLink&((NGushort)0x0C00U))==((NGushort)0x0C00U)) &&
							((linkPartner&((NGushort)0x0C00U))==((NGushort)0x0800U)))
					{
						/* Enable PAUSE receive, disable PAUSE transmit
 */
						Lan_SetMacRegDW(dwLanBase,FLOW,0xFFFF0002UL);

						dwTemp = GetRegDW(dwLanBase,AFC_CFG);
						dwTemp&=0xFFFFFFF0UL;

						SetRegDW(dwLanBase,AFC_CFG,dwTemp);
					} else {

						/* Disable PAUSE receive and transmit
 */
						Lan_SetMacRegDW(dwLanBase,FLOW,0UL);

						dwTemp = GetRegDW(dwLanBase,AFC_CFG);
						dwTemp&=0xFFFFFFF0UL;

						SetRegDW(dwLanBase,AFC_CFG,dwTemp);
					};break;

			  	case NG_ETHIF_LINK_10BASET:
			  	case NG_ETHIF_LINK_100BASETX:
					Lan_SetMacRegDW(dwLanBase,FLOW,0UL);

					dwTemp = GetRegDW(dwLanBase,AFC_CFG);
					dwTemp|=0x0000000FUL;

					SetRegDW(dwLanBase,AFC_CFG,dwTemp);
					break;

				default:
					break;

				}

#ifdef SMC_DEBUG
				sprintf (buffer, "LAN9118: %s,%s,%s,%s,%s,%s",


					(localLink&PHY_ANEG_ADV_ASYMP_)?"ASYMP":"     ",

					(localLink&PHY_ANEG_ADV_SYMP_)?"SYMP ":"     ",

					(localLink&PHY_ANEG_ADV_100F_)?"100FD":"     ",

					(localLink&PHY_ANEG_ADV_100H_)?"100HD":"     ",

					(localLink&PHY_ANEG_ADV_10F_)?"10FD ":"     ",

					(localLink&PHY_ANEG_ADV_10H_)?"10HD ":"     ");

				OS_TEXT_OUT (buffer);
	

				sprintf (buffer, "Partner: %s,%s,%s,%s,%s,%s",

					(linkPartner&PHY_ANEG_LPA_ASYMP_)?"ASYMP":"     ",

					(linkPartner&PHY_ANEG_LPA_SYMP_)?"SYMP ":"     ",

					(linkPartner&PHY_ANEG_LPA_100FDX_)?"100FD":"     ",

					(linkPartner&PHY_ANEG_LPA_100HDX_)?"100HD":"     ",

					(linkPartner&PHY_ANEG_LPA_10FDX_)?"10FD ":"     ",

					(linkPartner&PHY_ANEG_LPA_10HDX_)?"10HD ":"     ");

				OS_TEXT_OUT (buffer);
#endif

⌨️ 快捷键说明

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