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

📄 eth_smsc911x.c

📁 Hermit-at-1.1.3,一款bootloader
💻 C
📖 第 1 页 / 共 3 页
字号:
	  TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ | 	  ((DWORD)(bufptr));	dwTxCmdB=	  (((DWORD)(bufptr))<<16) |	  ((DWORD)(bufptr));	Lan_SetRegDW(TX_DATA_FIFO,dwTxCmdA);	Lan_SetRegDW(TX_DATA_FIFO,dwTxCmdB);	Platform_WriteFifo(privateData->dwLanBase,			   (DWORD *)(((DWORD)(EthTxBuffer))&0xFFFFFFFCUL),			   (((DWORD)(bufptr))+3+			    (((DWORD)(EthTxBuffer))&0x03UL))>>2);	dwLoopCount=bufptr;	while((dwLoopCount>0) && ((dwStatus=Phy_LBT_GetTxStatus(privateData))==0)) {		dwLoopCount--;	}	if(dwStatus==0) {		SMSC_WARNING("Failed to Transmit during Packet Test");		return -1;	}	if(dwStatus&0x00008000UL) {		SMSC_WARNING("Transmit encountered errors during Packet Test");		return -1;	}		return 0;}/************************************************************************* * *************************************************************************/static int smsc911x_eth_rx_init(void){	DWORD tmp;	privateData->dwRxOffCount=1;	Lan_SetRegDW(RX_CFG,0x0);	tmp = Lan_GetRegDW(FIFO_INT) & 0xffff00ff;	Lan_SetRegDW(FIFO_INT, tmp | (0x18 << 8));	Rx_ReceiverOn(privateData);	return 0;}/************************************************************************* * *************************************************************************/static void Rx_FastForward(PPRIVATE_DATA privateData,DWORD dwDwordCount){	privateData->RxFastForwardCount++;	if((dwDwordCount>=4)		&& (			(((privateData->dwIdRev&0x0000FFFFUL)==0x00000000UL)				&& (privateData->dwFpgaRev>=0x36))			||			((privateData->dwIdRev&0x0000FFFFUL)!=0UL)			)		)	{		DWORD dwTimeOut=500;		Lan_SetRegDW(RX_DP_CTRL,(dwDwordCount|RX_DP_CTRL_FFWD_BUSY_));		while((dwTimeOut)&&(Lan_GetRegDW(RX_DP_CTRL)&				RX_DP_CTRL_FFWD_BUSY_))		{			udelay(1);			dwTimeOut--;		}		if(dwTimeOut==0) {			SMSC_WARNING("timed out waiting for RX FFWD to finish, RX_DP_CTRL=0x%08lX",				Lan_GetRegDW(RX_DP_CTRL));		}	} else {		while(dwDwordCount) {			DWORD dwTemp=Lan_GetRegDW(RX_DATA_FIFO);			dwTemp=dwTemp;			dwDwordCount--;		}	}}/************************************************************************* * *************************************************************************/static DWORD Rx_PopRxStatus(PPRIVATE_DATA privateData){	DWORD result=Lan_GetRegDW(RX_FIFO_INF);	if((privateData->RxCongested==FALSE)||		((privateData->RxCongested==TRUE)&&((result&0x00FF0000UL)==0UL)))	{		if(result&0x00FF0000UL) {			DWORD dwIntSts=Lan_GetRegDW(INT_STS);			if(IS_REV_A(privateData)) {				if(dwIntSts&INT_STS_RDFL_) {				  SMSC_WARNING("%s(): INT_STS_RDFL_\n",__FUNCTION__);					Lan_SetRegDW(INT_STS,INT_STS_RDFL_);				}			} else {				if(dwIntSts&INT_STS_RDFO_) {				  SMSC_WARNING("%s(): INT_STS_RDFD_\n",__FUNCTION__);					Lan_SetRegDW(INT_STS,INT_STS_RDFO_);				}			}			if(dwIntSts&INT_STS_RXE_){			  SMSC_WARNING("%s(): INT_STS_RXE_\n",__FUNCTION__);			  Lan_SetRegDW(INT_STS, INT_STS_RXE_);			}			if(dwIntSts&INT_STS_TXE_){			  SMSC_WARNING("%s(): INT_STS_TXE_\n",__FUNCTION__);			  Lan_SetRegDW(INT_STS, INT_STS_TXE_);			}			if(dwIntSts&0xff8){			  SMSC_WARNING("%s(): INT_STS: %p\n", __FUNCTION__, dwIntSts);			  Lan_SetRegDW(INT_STS, 0xff8);			}			if((privateData->RxFlowControlActive==FALSE)||				((privateData->RxFlowControlActive==TRUE)&&				 (privateData->RxFlowBurstActive==TRUE)))			{				/* Rx status is available, read it */				result=Lan_GetRegDW(RX_STATUS_FIFO);				privateData->RxStatusDWReadCount++;				privateData->LastRxStatus3=					privateData->LastRxStatus2;				privateData->LastRxStatus2=					privateData->LastRxStatus1;				privateData->LastRxStatus1=result;	            				if(privateData->RxOverrun) {					DWORD dwPacketLength=((result&0x3FFF0000UL)>>16);					DWORD dwByteCount=((dwPacketLength+2+3)&0xFFFFFFFCUL);					if((privateData->RxUnloadProgress+dwByteCount)>=						((privateData->RxMaxDataFifoSize)-16))					{						/* This is the packet that crosses the corruption point */						/* so just ignore it and complete the overrun processing. */						result=0;						goto FINISH_OVERRUN_PROCESSING;					}					privateData->RxUnloadProgress+=dwByteCount;					privateData->RxUnloadPacketProgress++;				}								privateData->RxFlowCurrentThroughput+=						((((result&0x3FFF0000UL)>>16)-4UL));				privateData->RxFlowCurrentPacketCount++;				privateData->RxFlowCurrentWorkLoad+=						((((result&0x3FFF0000UL)>>16)-4UL)+privateData->RxFlowParameters.PacketCost);				if(privateData->RxFlowControlActive) {					privateData->RxFlowBurstWorkLoad+=						((((result&0x3FFF0000UL)>>16)-4UL)+privateData->RxFlowParameters.PacketCost);					if(privateData->RxFlowBurstWorkLoad>=						privateData->RxFlowBurstMaxWorkLoad) 					{						privateData->RxFlowBurstActive=FALSE;					}				}			} else {				result=0;			}		} 		else 		{			if(privateData->RxOverrun) {				DWORD timeOut;				DWORD temp;FINISH_OVERRUN_PROCESSING:				SMSC_WARNING("rx overrun\n");				temp=0;				{					timeOut=2000;					while((timeOut>0)&&(!(Lan_GetRegDW(INT_STS)&(INT_STS_RXSTOP_INT_)))) {						udelay(1);						timeOut--;					}					if(timeOut==0) {						SMSC_WARNING("Timed out waiting for Rx to Stop\n");					}					Lan_SetRegDW(INT_STS,INT_STS_RXSTOP_INT_);				}							temp=Lan_GetRegDW(RX_CFG);				Lan_SetRegDW(RX_CFG,(temp&0x3FFFFFFFUL));				timeOut=10000000;				Lan_SetBitsDW(RX_CFG,RX_CFG_RX_DUMP_);				while((timeOut>0)&&(Lan_GetRegDW(RX_CFG)&(RX_CFG_RX_DUMP_))) {					udelay(1);					timeOut--;				}				if(timeOut==0) {					SMSC_WARNING("Timed out waiting for Rx Dump to complete\n");				}				Lan_SetRegDW(RX_CFG,temp);				privateData->RxDumpCount++;				Lan_SetRegDW(INT_STS,INT_STS_RDFL_);				Rx_ReceiverOn(privateData);				privateData->RxOverrun=FALSE;			}			result=0;			privateData->LastReasonForReleasingCPU=1;/* Status FIFO Empty */		}	} else {		/* disable and reenable the INT_EN */		/* This will allow the deassertion interval to begin */		DWORD temp=Lan_GetRegDW(INT_EN);		Lan_SetRegDW(INT_EN,0);		Lan_SetRegDW(INT_EN,temp);		result=0;		privateData->LastReasonForReleasingCPU=2;/* High Congestion */	}	return result;}/************************************************************************* * *************************************************************************/static void Rx_CountErrors(PPRIVATE_DATA privateData,DWORD dwRxStatus) {}/************************************************************************* * *************************************************************************/int smsc911x_eth_recv(const unsigned char *mac, eth_frame **ethfr,		  void **pbuf, unsigned int *pbuflen, int *timeout){	DWORD dwRxStatus=0;	PPLATFORM_DATA platformData=NULL;	privateData->RxCongested=FALSE;	platformData=&(privateData->PlatformData);	Lan_SetRegDW(RX_CFG,0x0);	while(1){		if((dwRxStatus=Rx_PopRxStatus(privateData))==0){ 			timeout--;			if(timeout<0){				SMSC_WARNING("recv timeout\n");				return -1;			}			udelay(1);			continue;		}		DWORD dwPacketLength=((dwRxStatus&0x3FFF0000UL)>>16);		Rx_CountErrors(privateData,dwRxStatus);		if((dwRxStatus&RX_STS_ES_)==0) {			Platform_ReadFifo(privateData->dwLanBase,					  ((DWORD *)EthRxBuffer),					  (dwPacketLength+3)>>2);	      			*ethfr = (eth_frame *)(EthRxBuffer);			*pbuf = (void *)(EthRxBuffer + ETH_FRAME_LEN);			*pbuflen = (dwPacketLength - 4) - ETH_FRAME_LEN;			return 0;		}		/* if we get here then the packet is to be read */		/* out of the fifo and discarded */		dwPacketLength+=(2+3);		dwPacketLength>>=2;		Rx_FastForward(privateData,dwPacketLength);	}	return -1;}/************************************************************************* * *************************************************************************/int smsc911x_eth_rxbuf_free(const int idx){	return 0;}/************************************************************************* * *************************************************************************/static BOOLEAN Lan_Initialize(PPRIVATE_DATA privateData,	       DWORD dwIntCfg,	       DWORD dwTxFifSz,	       DWORD dwAfcCfg){	BOOLEAN result=FALSE;	DWORD dwTimeOut=0;	DWORD dwTemp=0;	DWORD dwResetCount=3;	SMSC_TRACE("-->Lan_Initialize");	/* Reset the LAN911x */	dwResetCount=1;	while(dwResetCount>0) {		Lan_SetRegDW(HW_CFG,HW_CFG_SRST_);		dwTimeOut=1000000;		do {			dwTemp=Lan_GetRegDW(HW_CFG);			dwTimeOut--;		} while((dwTimeOut>0)&&(dwTemp&HW_CFG_SRST_));		if(dwTemp&HW_CFG_SRST_) {			SMSC_WARNING("  Failed to complete reset.");			goto DONE;		}		dwResetCount--;	}	SMSC_ASSERT(dwTxFifSz>=0x00020000UL);	SMSC_ASSERT(dwTxFifSz<=0x000E0000UL);	SMSC_ASSERT((dwTxFifSz&(~HW_CFG_TX_FIF_SZ_))==0);	dwTxFifSz = 0x00040000UL;	Lan_SetRegDW(HW_CFG,dwTxFifSz);	privateData->RxMaxDataFifoSize=0;	switch(dwTxFifSz>>16) {	case 2:privateData->RxMaxDataFifoSize=13440;break;	case 3:privateData->RxMaxDataFifoSize=12480;break;	case 4:privateData->RxMaxDataFifoSize=11520;break;	case 5:privateData->RxMaxDataFifoSize=10560;break;	case 6:privateData->RxMaxDataFifoSize=9600;break;	case 7:privateData->RxMaxDataFifoSize=8640;break;	case 8:privateData->RxMaxDataFifoSize=7680;break;	case 9:privateData->RxMaxDataFifoSize=6720;break;	case 10:privateData->RxMaxDataFifoSize=5760;break;	case 11:privateData->RxMaxDataFifoSize=4800;break;	case 12:privateData->RxMaxDataFifoSize=3840;break;	case 13:privateData->RxMaxDataFifoSize=2880;break;	case 14:privateData->RxMaxDataFifoSize=1920;break;	default:SMSC_ASSERT(FALSE);break;	}	if(dwAfcCfg==0xFFFFFFFF) {		switch(dwTxFifSz) {		/* AFC_HI is about ((Rx Data Fifo Size)*2/3)/64 */		/* AFC_LO is AFC_HI/2 */		/* BACK_DUR is about 5uS*(AFC_LO) rounded down */		case 0x00020000UL:/* 13440 Rx Data Fifo Size */			dwAfcCfg=0x008C46AF;break;		case 0x00030000UL:/* 12480 Rx Data Fifo Size */			dwAfcCfg=0x0082419F;break;		case 0x00040000UL:/* 11520 Rx Data Fifo Size */			dwAfcCfg=0x00783C9F;break;		case 0x00050000UL:/* 10560 Rx Data Fifo Size */			dwAfcCfg=0x006E374F;break;		case 0x00060000UL:/* 9600 Rx Data Fifo Size */			dwAfcCfg=0x0064328F;break;		case 0x00070000UL:/* 8640 Rx Data Fifo Size */			dwAfcCfg=0x005A2D7F;break;		case 0x00080000UL:/* 7680 Rx Data Fifo Size */			dwAfcCfg=0x0050287F;break;		case 0x00090000UL:/* 6720 Rx Data Fifo Size */			dwAfcCfg=0x0046236F;break;		case 0x000A0000UL:/* 5760 Rx Data Fifo Size */			dwAfcCfg=0x003C1E6F;break;		case 0x000B0000UL:/* 4800 Rx Data Fifo Size */			dwAfcCfg=0x0032195F;break;		/* AFC_HI is ~1520 bytes less than RX Data Fifo Size */		/* AFC_LO is AFC_HI/2 */		/* BACK_DUR is about 5uS*(AFC_LO) rounded down */		case 0x000C0000UL:/* 3840 Rx Data Fifo Size */			dwAfcCfg=0x0024124F;break;		case 0x000D0000UL:/* 2880 Rx Data Fifo Size */			dwAfcCfg=0x0015073F;break;		case 0x000E0000UL:/* 1920 Rx Data Fifo Size */			dwAfcCfg=0x0006032F;break;		default:SMSC_ASSERT(FALSE);break;		}	}	Lan_SetRegDW(AFC_CFG,(dwAfcCfg&0xFFFFFFF0UL));	/* make sure EEPROM has finished loading before setting GPIO_CFG */	dwTimeOut=1000;	while((dwTimeOut>0)&&(Lan_GetRegDW(E2P_CMD)&E2P_CMD_EPC_BUSY_)) {		dwTimeOut--;	}	if(dwTimeOut==0) {		SMSC_WARNING("Lan_Initialize: Timed out waiting for EEPROM busy bit to clear\n");	}	Lan_SetRegDW(GPIO_CFG,0x70000000UL);	/* initialize interrupts */	Lan_SetRegDW(INT_EN,0);	Lan_SetRegDW(INT_STS,0xFFFFFFFFUL);	result=TRUE;DONE:	SMSC_TRACE("<--Lan_Initialize");	return result;}/************************************************************************* * *************************************************************************/static int smsc911x_open(PPRIVATE_DATA privateData){	if(!Lan_Initialize(privateData,0,0x00050000,0xFFFFFFFF)) {	  	SMSC_WARNING("Failed Lan_Initialize");		return -ENODEV;	}	SMSC_TRACE("<--Smsc911x_open");	return 0;}/************************************************************************* * *************************************************************************/void smsc911x_enable_phy_module(void){}/************************************************************************* * *************************************************************************/void smsc911x_disable_phy_module(void){}/************************************************************************* * *************************************************************************/int arch_get_mac(unsigned char *mac){	int i;	unsigned long mac_hi, mac_low;	privateData->dwLanBase=LAN_CSBASE;	mac_hi  = Mac_GetRegDW(privateData,ADDRH);	mac_low = Mac_GetRegDW(privateData,ADDRL);	if((mac_hi == 0x0000ffff) && (mac_low == 0xffffffff)){		SMSC_WARNING("Error: read MAC addr."			     "using default 00:01:02:03:04:05.\n");		for(i=0;i<6;i++)			mac[i] = i;	}else{		mac[0] = (mac_low >>  0) & 0xff;		mac[1] = (mac_low >>  8) & 0xff;		mac[2] = (mac_low >> 16) & 0xff;		mac[3] = (mac_low >> 24) & 0xff;		mac[4] = (mac_hi  >>  0) & 0xff;		mac[5] = (mac_hi  >>  8) & 0xff;	}	return 0;}/************************************************************************* * *************************************************************************/int smsc911x_eth_init(const unsigned char *ipaddr){	hwif_eth hwif;	DWORD dwLanBase=0UL;	DWORD dwIdRev=0UL;	DWORD dwFpgaRev=0UL;	int result=-ENODEV;	int ret;	memzero(&_privateData, sizeof(_platformData));	memzero(&_platformData, sizeof(_platformData));  	dwLanBase=Platform_Initialize(platformData, 0, 16);	privateData->dwLanBase=dwLanBase;	dwIdRev=Lan_GetRegDW(ID_REV);	if(HIWORD(dwIdRev)==LOWORD(dwIdRev)) {		/* this may mean the chip is set for 32 bit  */		/* while the bus is reading as 16 bit */		SMSC_WARNING("  LAN911x NOT Identified, dwIdRev==%p",dwIdRev);		result=-ENODEV;		return -1;	}	SMSC_TRACE("  LAN911x identified, dwIdRev==%p", dwIdRev);	dwFpgaRev=Lan_GetRegDW(FPGA_REV);	SMSC_TRACE("  FPGA_REV == %p",dwFpgaRev);	ret = Phy_Initialize(privateData, 0xffffffff,0x7f );	ret = smsc911x_open(privateData);		ret = Phy_CheckLink((unsigned long)privateData);	if(ret < 0){		return -1;	}	safe_memset(&hwif, 0, sizeof(hwif_eth));	hwif.enable_phy_module = smsc911x_enable_phy_module;	hwif.disable_phy_module = smsc911x_disable_phy_module;	hwif.eth_send = smsc911x_eth_send;	hwif.eth_recv = smsc911x_eth_recv;	hwif.eth_rxbuf_free = smsc911x_eth_rxbuf_free;	safe_memcpy(&hwif.eth_ipaddr, ipaddr, 4);	arch_get_mac(hwif.eth_mac);		register_hwif_eth(&hwif);	smsc911x_eth_rx_init();	smsc911x_eth_tx_init();		Lan_SetRegDW(FIFO_INT, 0x48ff2020);	/* Interrupt Status Clear */	Lan_SetRegDW(INT_STS, 0xffffffff);		return 0;}

⌨️ 快捷键说明

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