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

📄 eth_smsc911x.c

📁 Hermit-at-1.1.3,一款bootloader
💻 C
📖 第 1 页 / 共 3 页
字号:
	Platform_WriteFifo(		privateData->dwLanBase,		(DWORD *)(((DWORD)(LoopBackTxPacket))&0xFFFFFFFCUL),		(((DWORD)(MIN_PACKET_SIZE))+3+		(((DWORD)(LoopBackTxPacket))&0x03UL))>>2);	/* wait till transmit is done */	dwLoopCount=60;	while((dwLoopCount>0) &&((dwStatus=Phy_LBT_GetTxStatus(privateData))==0)) {		udelay(5);		dwLoopCount--;	}	if(dwStatus==0) {		SMSC_WARNING("Failed to Transmit during Packet Test");		goto DONE;	}	if(dwStatus&0x00008000UL) {		SMSC_WARNING("Transmit encountered errors during Packet Test");		goto DONE;	}DONE:	return result;}#endif/************************************************************************* * *************************************************************************/static void Phy_GetLinkMode(PPRIVATE_DATA privateData){	DWORD result=LINK_OFF;	WORD wRegVal=0;	WORD wRegBSR=Phy_GetRegW(		privateData,		PHY_BSR);	privateData->dwLinkSettings=LINK_OFF;	if(wRegBSR&PHY_BSR_LINK_STATUS_) {		wRegVal=Phy_GetRegW(			privateData,			PHY_BCR);		if(wRegVal&PHY_BCR_AUTO_NEG_ENABLE_) {			DWORD linkSettings=LINK_AUTO_NEGOTIATE;			WORD wRegADV=privateData->wLastADVatRestart;			WORD wRegLPA=Phy_GetRegW(				privateData,				PHY_ANEG_LPA);			if(wRegADV&PHY_ANEG_ADV_ASYMP_) {				linkSettings|=LINK_ASYMMETRIC_PAUSE;			}			if(wRegADV&PHY_ANEG_ADV_SYMP_) {				linkSettings|=LINK_SYMMETRIC_PAUSE;			}			if(wRegADV&PHY_ANEG_LPA_100FDX_) {				linkSettings|=LINK_SPEED_100FD;			}			if(wRegADV&PHY_ANEG_LPA_100HDX_) {				linkSettings|=LINK_SPEED_100HD;			}			if(wRegADV&PHY_ANEG_LPA_10FDX_) {				linkSettings|=LINK_SPEED_10FD;			}			if(wRegADV&PHY_ANEG_LPA_10HDX_) {				linkSettings|=LINK_SPEED_10HD;			}			privateData->dwLinkSettings=linkSettings;			wRegLPA&=wRegADV;			if(wRegLPA&PHY_ANEG_LPA_100FDX_) {				result=LINK_SPEED_100FD;			} else if(wRegLPA&PHY_ANEG_LPA_100HDX_) {				result=LINK_SPEED_100HD;			} else if(wRegLPA&PHY_ANEG_LPA_10FDX_) {				result=LINK_SPEED_10FD;			} else if(wRegLPA&PHY_ANEG_LPA_10HDX_) {				result=LINK_SPEED_10HD;			}		} else {			if(wRegVal&PHY_BCR_SPEED_SELECT_) {				if(wRegVal&PHY_BCR_DUPLEX_MODE_) {					privateData->dwLinkSettings=result=LINK_SPEED_100FD;				} else {					privateData->dwLinkSettings=result=LINK_SPEED_100HD;				}			} else {				if(wRegVal&PHY_BCR_DUPLEX_MODE_) {					privateData->dwLinkSettings=result=LINK_SPEED_10FD;				} else {					privateData->dwLinkSettings=result=LINK_SPEED_10HD;				}			}		}	}	privateData->dwLinkSpeed=result;}/************************************************************************* * *************************************************************************/static int Phy_UpdateLinkMode(PPRIVATE_DATA privateData){	Phy_GetLinkMode(privateData);	if(privateData->dwLinkSpeed!=LINK_OFF) {		DWORD dwRegVal=0;		switch(privateData->dwLinkSpeed) {		case LINK_SPEED_10HD:			SMSC_TRACE("Link is now UP at 10Mbps HD");			break;		case LINK_SPEED_10FD:			SMSC_TRACE("Link is now UP at 10Mbps FD");			break;		case LINK_SPEED_100HD:			SMSC_TRACE("Link is now UP at 100Mbps HD");			break;		case LINK_SPEED_100FD:			SMSC_TRACE("Link is now UP at 100Mbps FD");			break;		default:			SMSC_WARNING("Link is now UP at Unknown Link Speed, dwLinkSpeed=0x%08lX",				     privateData->dwLinkSpeed);			break;		}				dwRegVal=Mac_GetRegDW(privateData,MAC_CR);		dwRegVal&=~(MAC_CR_FDPX_|MAC_CR_RCVOWN_);		switch(privateData->dwLinkSpeed) {		case LINK_SPEED_10HD:		case LINK_SPEED_100HD:			dwRegVal|=MAC_CR_RCVOWN_;			break;		case LINK_SPEED_10FD:		case LINK_SPEED_100FD:			dwRegVal|=MAC_CR_FDPX_;			break;		default:			break;/* make lint happy */		}				Mac_SetRegDW(privateData,MAC_CR,dwRegVal);		if(privateData->dwLinkSettings&LINK_AUTO_NEGOTIATE) {			WORD linkPartner=0;			WORD localLink=0;			localLink=Phy_GetRegW(privateData,4);			linkPartner=Phy_GetRegW(privateData,5);			switch(privateData->dwLinkSpeed) {			case LINK_SPEED_10FD:			case LINK_SPEED_100FD:				if(((localLink&linkPartner)&((WORD)0x0400U)) != ((WORD)0U)) {					/* Enable PAUSE receive and transmit */					Mac_SetRegDW(privateData,FLOW,0xFFFF0002UL);					Lan_SetBitsDW(AFC_CFG,0x00000000UL);				} else if(((localLink&((WORD)0x0C00U))==((WORD)0x0C00U)) &&					  ((linkPartner&((WORD)0x0C00U))==((WORD)0x0800U)))					{						/* Enable PAUSE receive, disable PAUSE transmit */						Mac_SetRegDW(privateData,FLOW,0xFFFF0002UL);						Lan_ClrBitsDW(AFC_CFG,0x0000000FUL);					} else {						/* Disable PAUSE receive and transmit */						Mac_SetRegDW(privateData,FLOW,0UL);						Lan_ClrBitsDW(AFC_CFG,0x0000000FUL);					};				break;			case LINK_SPEED_10HD:			case LINK_SPEED_100HD:				Mac_SetRegDW(privateData,FLOW,0UL);				Lan_SetBitsDW(AFC_CFG,0x0000000FUL);				break;			default:				break;/* make lint happy */			}			SMSC_TRACE("LAN911x: %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 ":"     ");						SMSC_TRACE("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 ":"     ");		} else {			switch(privateData->dwLinkSpeed) {			case LINK_SPEED_10HD:			case LINK_SPEED_100HD:				Mac_SetRegDW(privateData,FLOW,0x0UL);				Lan_SetBitsDW(AFC_CFG,0x0000000FUL);				break;			default:				Mac_SetRegDW(privateData,FLOW,0x0UL);				Lan_ClrBitsDW(AFC_CFG,0x0000000FUL);				break;			}		}	} else {		SMSC_TRACE("Link is now DOWN");		Mac_SetRegDW(privateData,FLOW,0UL);		Lan_ClrBitsDW(AFC_CFG,0x0000000FUL);				return -1;	}	return 0;}/************************************************************************* * *************************************************************************/static int Phy_CheckLink(unsigned long ptr){	PPRIVATE_DATA privateData=(PPRIVATE_DATA)ptr;	if(privateData==NULL) {		SMSC_WARNING("Phy_CheckLink(ptr==0)");		return -1;	}	/* must call this twice */	return Phy_UpdateLinkMode(privateData);}/************************************************************************* * *************************************************************************/static int Phy_SetLink(PPRIVATE_DATA privateData,DWORD dwLinkRequest) {	if(dwLinkRequest&LINK_AUTO_NEGOTIATE) {		WORD wTemp;		wTemp=Phy_GetRegW(privateData,			PHY_ANEG_ADV);		wTemp&=~PHY_ANEG_ADV_PAUSE_;		if(dwLinkRequest&LINK_ASYMMETRIC_PAUSE) {			wTemp|=PHY_ANEG_ADV_ASYMP_;		} 		if(dwLinkRequest&LINK_SYMMETRIC_PAUSE) {			wTemp|=PHY_ANEG_ADV_SYMP_;		}		wTemp&=~PHY_ANEG_ADV_SPEED_;		if(dwLinkRequest&LINK_SPEED_10HD) {			wTemp|=PHY_ANEG_ADV_10H_;		}		if(dwLinkRequest&LINK_SPEED_10FD) {			wTemp|=PHY_ANEG_ADV_10F_;		}		if(dwLinkRequest&LINK_SPEED_100HD) {			wTemp|=PHY_ANEG_ADV_100H_;		}		if(dwLinkRequest&LINK_SPEED_100FD) {			wTemp|=PHY_ANEG_ADV_100F_;		}		Phy_SetRegW(privateData,PHY_ANEG_ADV,wTemp);		/* begin to establish link */		privateData->dwRemoteFaultCount=0;		Phy_SetRegW(privateData,			PHY_BCR,			PHY_BCR_AUTO_NEG_ENABLE_|			PHY_BCR_RESTART_AUTO_NEG_);		{			int timeout=5000;			while(timeout--){				DWORD reg = Phy_GetRegW(privateData, PHY_BSR);				if(reg & 0x20) break;				mdelay(1);				timeout--;			}			if(timeout <=0) return -1;		}	} else {		WORD wTemp=0;		if(dwLinkRequest&(LINK_SPEED_100FD)) {			dwLinkRequest=LINK_SPEED_100FD;		} else if(dwLinkRequest&(LINK_SPEED_100HD)) {			dwLinkRequest=LINK_SPEED_100HD;		} else if(dwLinkRequest&(LINK_SPEED_10FD)) {			dwLinkRequest=LINK_SPEED_10FD;		} else if(dwLinkRequest&(LINK_SPEED_10HD)) {			dwLinkRequest=LINK_SPEED_10HD;		}		if(dwLinkRequest&(LINK_SPEED_10FD|LINK_SPEED_100FD)) {			wTemp|=PHY_BCR_DUPLEX_MODE_;		}		if(dwLinkRequest&(LINK_SPEED_100HD|LINK_SPEED_100FD)) {			wTemp|=PHY_BCR_SPEED_SELECT_;		}		Phy_SetRegW(privateData,PHY_BCR,wTemp);	}	return 0;}/************************************************************************* * *************************************************************************/static BOOLEAN Phy_Initialize(PPRIVATE_DATA privateData,	       DWORD dwPhyAddr,	       DWORD dwLinkRequest){	BOOLEAN result=FALSE;	DWORD dwTemp=0;	WORD wTemp=0;	DWORD dwLoopCount=0;	SMSC_TRACE("-->Phy_Initialize");	SMSC_ASSERT(privateData!=NULL);	SMSC_ASSERT(privateData->dwLanBase!=0);	SMSC_ASSERT(dwLinkRequest<=0x7FUL);	if(dwPhyAddr!=0xFFFFFFFFUL) {		switch(privateData->dwIdRev&0xFFFF0000) {		case 0x01170000UL:		case 0x01150000UL:			if(privateData->dwIdRev&0x0000FFFF) {				DWORD dwHwCfg=Lan_GetRegDW(HW_CFG);				if(dwHwCfg&HW_CFG_EXT_PHY_DET_) {					/* External phy is requested, supported, and detected */					/* Attempt to switch */					/* NOTE: Assuming Rx and Tx are stopped */					/* because Phy_Initialize is called before  */					/* Rx_Initialize and Tx_Initialize */					WORD wPhyId1=0;					WORD wPhyId2=0;					/* Disable phy clocks to the mac */					dwHwCfg&= (~HW_CFG_PHY_CLK_SEL_);					dwHwCfg|= HW_CFG_PHY_CLK_SEL_CLK_DIS_;					Lan_SetRegDW(HW_CFG,dwHwCfg);					udelay(10);/* wait for clocks to acutally stop */					dwHwCfg|=HW_CFG_EXT_PHY_EN_;					Lan_SetRegDW(HW_CFG,dwHwCfg);					dwHwCfg&= (~HW_CFG_PHY_CLK_SEL_);					dwHwCfg|= HW_CFG_PHY_CLK_SEL_EXT_PHY_;					Lan_SetRegDW(HW_CFG,dwHwCfg);					udelay(10);/* wait for clocks to actually start */					dwHwCfg|=HW_CFG_SMI_SEL_;					Lan_SetRegDW(HW_CFG,dwHwCfg);					{						if(dwPhyAddr<=31) {							/* only check the phy address specified */							privateData->dwPhyAddress=dwPhyAddr;							wPhyId1=Phy_GetRegW(privateData,PHY_ID_1);							wPhyId2=Phy_GetRegW(privateData,PHY_ID_2);						} else {							/* auto detect phy */							DWORD address=0;							for(address=0;address<=31;address++) {								privateData->dwPhyAddress=address;								if((wPhyId1!=0xFFFFU)||(wPhyId2!=0xFFFFU)) {									SMSC_TRACE("Detected Phy at address = 0x%02lX = %ld",										address,address);									break;								}							}							if(address>=32) {								SMSC_WARNING("Failed to auto detect external phy");							}						}					}					if((wPhyId1==0xFFFFU)&&(wPhyId2==0xFFFFU)) {						SMSC_WARNING("External Phy is not accessable");						SMSC_WARNING("  using internal phy instead");						/* revert back to interal phy settings. */						/* Disable phy clocks to the mac */						dwHwCfg&= (~HW_CFG_PHY_CLK_SEL_);						dwHwCfg|= HW_CFG_PHY_CLK_SEL_CLK_DIS_;						Lan_SetRegDW(HW_CFG,dwHwCfg);						udelay(10);/* wait for clocks to actually stop */						dwHwCfg&=(~HW_CFG_EXT_PHY_EN_);						Lan_SetRegDW(HW_CFG,dwHwCfg);							dwHwCfg&= (~HW_CFG_PHY_CLK_SEL_);						dwHwCfg|= HW_CFG_PHY_CLK_SEL_INT_PHY_;						Lan_SetRegDW(HW_CFG,dwHwCfg);						udelay(10);/* wait for clocks to actually start */						dwHwCfg&=(~HW_CFG_SMI_SEL_);						Lan_SetRegDW(HW_CFG,dwHwCfg);						goto USE_INTERNAL_PHY;					} else {						SMSC_TRACE("Successfully switched to external phy");					}				} else {					SMSC_WARNING("No External Phy Detected");					SMSC_WARNING("  using internal phy instead");					goto USE_INTERNAL_PHY;				}			} else {				SMSC_WARNING("External Phy is not supported");				SMSC_WARNING("  using internal phy instead");				goto USE_INTERNAL_PHY;			};break;		default:			SMSC_WARNING("External Phy is not supported");			SMSC_WARNING("  using internal phy instead");			goto USE_INTERNAL_PHY;		}	} else {USE_INTERNAL_PHY:		privateData->dwPhyAddress=1;	}		dwTemp=Phy_GetRegW(privateData,PHY_ID_2);	privateData->bPhyRev=((BYTE)(dwTemp&(0x0FUL)));	privateData->bPhyModel=((BYTE)((dwTemp>>4)&(0x3FUL)));	privateData->dwPhyId=((dwTemp&(0xFC00UL))<<8);	dwTemp=Phy_GetRegW(privateData,PHY_ID_1);	privateData->dwPhyId|=((dwTemp&(0x0000FFFFUL))<<2);		SMSC_TRACE("dwPhyId==%p,bPhyModel==%p,bPhyRev==%p",		   privateData->dwPhyId,		   privateData->bPhyModel,		   privateData->bPhyRev);		privateData->dwLinkSpeed=LINK_OFF;	privateData->dwLinkSettings=LINK_OFF;	/* reset the PHY */	Phy_SetRegW(privateData,PHY_BCR,PHY_BCR_RESET_);	dwLoopCount=100000;	do {		udelay(10);		wTemp=Phy_GetRegW(privateData,PHY_BCR);		dwLoopCount--;	} while((dwLoopCount>0) && (wTemp&PHY_BCR_RESET_));	if(wTemp&PHY_BCR_RESET_) {		SMSC_WARNING("PHY reset failed to complete.");		goto DONE;	}		if(Phy_SetLink(privateData,dwLinkRequest)<0)	  return -1;	result=TRUE;DONE:	SMSC_TRACE("<--Phy_Initialize, result=%s",result?"TRUE":"FALSE");	return result;}/************************************************************************* * *************************************************************************/static void Rx_ReceiverOn(PPRIVATE_DATA privateData){	if(privateData->dwRxOffCount>0) {		privateData->dwRxOffCount--;		if(privateData->dwRxOffCount==0) {			DWORD dwMacCr=Mac_GetRegDW(privateData,MAC_CR);			if(dwMacCr&MAC_CR_RXEN_) {				SMSC_WARNING("Rx_ReceiverOn: Receiver is already on");			}			dwMacCr|=MAC_CR_RXEN_;			Mac_SetRegDW(privateData,MAC_CR,dwMacCr);		}	} else {		SMSC_ASSERT(FALSE);	}}/************************************************************************* * *************************************************************************/static int smsc911x_eth_tx_init(void){	DWORD dwRegVal=0;	DWORD dwMacCr;	dwRegVal=Lan_GetRegDW(HW_CFG);	dwRegVal&=(HW_CFG_TX_FIF_SZ_|0x00000FFFUL);		dwRegVal|=HW_CFG_SF_;	Lan_SetRegDW(HW_CFG,dwRegVal);	dwMacCr=Mac_GetRegDW(privateData,MAC_CR);	dwMacCr|=(MAC_CR_TXEN_|MAC_CR_HBDIS_);	Mac_SetRegDW(privateData,MAC_CR,dwMacCr);	Lan_SetRegDW(TX_CFG,TX_CFG_TX_ON_ | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_);	return 0;}/************************************************************************* * *************************************************************************/int smsc911x_eth_send(const eth_frame *ethfr,		  const void *pfr,		  const unsigned int pfrlen){	DWORD dwTxCmdA;	DWORD dwTxCmdB;	int bufptr=0;	DWORD dwStatus = 0;	int dwLoopCount;	memcpy(EthTxBuffer, ethfr, bufptr = ETH_FRAME_LEN);	memcpy(&EthTxBuffer[bufptr], pfr, pfrlen);	bufptr+=pfrlen;	if(bufptr < 60){		memset(&EthTxBuffer[bufptr], 0, 60-bufptr);		bufptr=60;	}	dwTxCmdA=	  ((((DWORD)(EthTxBuffer))&0x03UL)<<16) | /* DWORD alignment adjustment */

⌨️ 快捷键说明

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