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

📄 smsc9118.c

📁 基于pxa270的linux下smsc9118的网卡驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			goto DONE;
		}
	}
	
	if(!Platform_RequestIRQ(platformData,irq,Smsc9118_ISR,privateData)) {
		result=-ENODEV;
		goto DONE;
	}
	acquired_isr=TRUE;

	//must now test the IRQ connection to the ISR
	SMSC_TRACE("Testing ISR using IRQ %ld",Platform_CurrentIRQ(platformData));
	{
		DWORD dwTimeOut=100000;
		Lan_SignalSoftwareInterrupt(privateData);
		do {
			udelay(10);
			dwTimeOut--;
		} while((dwTimeOut)&&(!(privateData->SoftwareInterruptSignal)));
		if(!(privateData->SoftwareInterruptSignal)) {
			SMSC_WARNING("ISR failed signaling test");
			result=-ENODEV;
			goto DONE;
		}
	}
	SMSC_TRACE("ISR passed test using IRQ %ld",Platform_CurrentIRQ(platformData));

	if(!Mac_Initialize(privateData)) {
		SMSC_WARNING("Failed Mac_Initialize");
		result=-ENODEV;
		goto DONE;
	}
	{//get mac address
		DWORD dwHigh16=0;
		DWORD dwLow32=0;
		DWORD dwIntFlags=0;
		VL_KEY keyCode=Vl_WaitForLock(&(privateData->MacPhyLock),&dwIntFlags);
		if(mac_addr_hi16==0xFFFFFFFF) {
			dwHigh16=Mac_GetRegDW(privateData,ADDRH,keyCode);
			dwLow32=Mac_GetRegDW(privateData,ADDRL,keyCode);
			if((dwHigh16==0x0000FFFFUL)&&(dwLow32==0xFFFFFFFF))
			{
				dwHigh16=0x00000070UL;
				dwLow32=0x110F8000UL;
				Mac_SetRegDW(privateData,ADDRH,dwHigh16,keyCode);
				Mac_SetRegDW(privateData,ADDRL,dwLow32,keyCode);
				SMSC_TRACE("Mac Address is set by default to 0x%04lX%08lX",
					dwHigh16,dwLow32);
			} else {
				SMSC_TRACE("Mac Address is read from LAN9118 as 0x%04lX%08lX",
					dwHigh16,dwLow32);
			}
		} else {
			//SMSC_ASSERT((mac_addr_hi16&0xFFFF8000UL)==0);
			dwHigh16=mac_addr_hi16;
			dwLow32=mac_addr_lo32;
			Mac_SetRegDW(privateData,ADDRH,dwHigh16,keyCode);
			Mac_SetRegDW(privateData,ADDRL,dwLow32,keyCode);
			SMSC_TRACE("Mac Address is set by parameter to 0x%04lX%08lX",
				dwHigh16,dwLow32);
		}
		Vl_ReleaseLock(&(privateData->MacPhyLock),keyCode,&dwIntFlags);
		dev->dev_addr[0]=LOBYTE(LOWORD(dwLow32));
		dev->dev_addr[1]=HIBYTE(LOWORD(dwLow32));
		dev->dev_addr[2]=LOBYTE(HIWORD(dwLow32));
		dev->dev_addr[3]=HIBYTE(HIWORD(dwLow32));
		dev->dev_addr[4]=LOBYTE(LOWORD(dwHigh16));
		dev->dev_addr[5]=HIBYTE(LOWORD(dwHigh16));
	}

	privateData->MulticastUpdatePending = FALSE;

#ifdef USE_PHY_WORK_AROUND
	netif_carrier_off(dev);
	if(!Phy_Initialize(
		privateData,
		phy_addr,
		link_mode))
	{
		SMSC_WARNING("Failed to initialize Phy");
		result=-ENODEV;
		goto DONE;
	}
#endif

	{
		DWORD dwRxDmaCh=rx_dma;
		DWORD dwTxDmaCh=tx_dma;
		privateData->RxDmaChReserved=FALSE;


		if(rx_dma==TRANSFER_REQUEST_DMA) {
			dwRxDmaCh=Platform_RequestDmaChannel(&(privateData->PlatformData));
			SMSC_ASSERT(dwRxDmaCh!=TRANSFER_REQUEST_DMA);
			if(dwRxDmaCh<TRANSFER_REQUEST_DMA) {
				privateData->RxDmaChReserved=TRUE;
			}
		}
		privateData->TxDmaChReserved=FALSE;
		if(tx_dma==TRANSFER_REQUEST_DMA) {
			dwTxDmaCh=Platform_RequestDmaChannel(&(privateData->PlatformData));
			SMSC_ASSERT(dwTxDmaCh!=TRANSFER_REQUEST_DMA);
			if(dwTxDmaCh<TRANSFER_REQUEST_DMA) {
				privateData->TxDmaChReserved=TRUE;
			}
		}
		Tx_Initialize(privateData,dwTxDmaCh,dma_threshold);
		Rx_Initialize(privateData,dwRxDmaCh,dma_threshold);
	}

#ifndef LINUX_2_6_OR_NEWER
	MOD_INC_USE_COUNT;
#endif
	privateData->Running=TRUE;
	netif_start_queue(dev);
	Tx_StopQueue(privateData,0x01UL);


	spin_lock_init(&(privateData->GpTimerLock));
	Lan_EnableInterrupt(privateData,INT_EN_GPT_INT_EN_);
#ifndef USE_PHY_WORK_AROUND
	netif_carrier_off(dev);
	if(!Phy_Initialize(
		privateData,
		phy_addr,
		link_mode))
	{
		SMSC_WARNING("Failed to initialize Phy");
		result=-ENODEV;
		goto DONE;
	}
#endif

	result=0;

DONE:
	if(result!=0) {
#ifndef LINUX_2_6_OR_NEWER
		MOD_DEC_USE_COUNT;
#endif
		if(privateData!=NULL) {
			if(privateData->TxDmaChReserved) {
				Platform_ReleaseDmaChannel(platformData,
					privateData->dwTxDmaCh);
				privateData->TxDmaChReserved=FALSE;
			}
			if(privateData->RxDmaChReserved) {
				Platform_ReleaseDmaChannel(platformData,
					privateData->dwRxDmaCh);
				privateData->RxDmaChReserved=FALSE;
			}
			if(acquired_isr) {
				Platform_FreeIRQ(platformData);
			}
			if(acquired_mem_region) {
				release_mem_region(
					privateData->dwLanBase,
					LAN_REGISTER_EXTENT);
			}
		}
	}
	SMSC_TRACE("<--Smsc9118_open, result=%d",result);
	return result;
}

int Smsc9118_stop(struct net_device *dev)
{
	int result=0;
	PPRIVATE_DATA privateData=NULL;
	SMSC_TRACE("-->Smsc9118_stop(dev=0x%08lX)",(DWORD)dev);
	if(dev==NULL) {
		SMSC_WARNING("Smsc9118_stop(dev==NULL)");
		result=-EFAULT;
		goto DONE;
	}
	privateData=(PPRIVATE_DATA)(dev->priv);
	if(privateData==NULL) {
		SMSC_WARNING("Smsc9118_stop(privateData==NULL)");
		result=-EFAULT;
		goto DONE;
	}

	privateData->StopLinkPolling=TRUE;
	del_timer_sync(&(privateData->LinkPollingTimer));

	Lan_DisableInterrupt(privateData,INT_EN_GPT_INT_EN_);

	Tx_UpdateTxCounters(privateData);
	privateData->Running=FALSE;
	Lan_DisableIRQ(privateData);

	Tx_CompleteDma(privateData);

	Tx_StopQueue(privateData,0x01UL);

#ifndef LINUX_2_6_OR_NEWER
	MOD_DEC_USE_COUNT;
#endif

	if(privateData->TxDmaChReserved) {
		Platform_ReleaseDmaChannel(
			&(privateData->PlatformData),
			privateData->dwTxDmaCh);
		privateData->TxDmaChReserved=FALSE;
	}
	if(privateData->RxDmaChReserved) {
		Platform_ReleaseDmaChannel(
			&(privateData->PlatformData),
			privateData->dwRxDmaCh);
		privateData->RxDmaChReserved=FALSE;
	}

	Platform_FreeIRQ(&(privateData->PlatformData));
	release_mem_region(privateData->dwLanBase,LAN_REGISTER_EXTENT);

	{
		const DWORD dwLanBase=privateData->dwLanBase;
		const DWORD dwIdRev=privateData->dwIdRev;
		const DWORD dwFpgaRev=privateData->dwFpgaRev;
		struct net_device * const tempDev=privateData->dev;
		char ifName[SMSC_IF_NAME_SIZE];
		PLATFORM_DATA platformDataBackup;
		memcpy(ifName,privateData->ifName,SMSC_IF_NAME_SIZE);
		memcpy(&platformDataBackup,&(privateData->PlatformData),sizeof(PLATFORM_DATA));

		memset(privateData,0,sizeof(PRIVATE_DATA));

		privateData->dwLanBase=dwLanBase;
		privateData->dwIdRev=dwIdRev;
		privateData->dwFpgaRev=dwFpgaRev;
		privateData->dev=tempDev;
		memcpy(privateData->ifName,ifName,SMSC_IF_NAME_SIZE);
		memcpy(&(privateData->PlatformData),&platformDataBackup,sizeof(PLATFORM_DATA));
	}

DONE:
	SMSC_TRACE("<--Smsc9118_stop, result=%d",result);
	return result;
}

int Smsc9118_hard_start_xmit(
	struct sk_buff *skb, struct net_device * const dev)
{
	int result=0;
	PPRIVATE_DATA privateData=NULL;
//	SMSC_TRACE("-->Smsc9118_hard_start_xmit(skb=0x%08lX,dev=0x%08lX)",(DWORD)skb,(DWORD)dev);
	if(skb==NULL) {
		SMSC_WARNING("Smsc9118_hard_start_xmit(skb==NULL)");
		result=-EFAULT;
		goto DONE;
	}
	if(dev==NULL) {
		SMSC_WARNING("Smsc9118_hard_start_xmit(dev==NULL)");
		result=-EFAULT;
		goto DONE;
	}
	if(dev->priv==NULL) {
		SMSC_WARNING("Smsc9118_hard_start_xmit(dev->priv==NULL)");
		result=-EFAULT;
		goto DONE;
	}
	privateData=(PPRIVATE_DATA)(dev->priv);
//	SET_GPIO(GP_TX);

	Tx_SendSkb(privateData,skb);

//	CLEAR_GPIO(GP_TX);
DONE:
//	SMSC_TRACE("<--Smsc9118_hard_start_xmit, result=%d",result);
	return result;
}

struct net_device_stats * Smsc9118_get_stats(struct net_device * const dev)
{
	PPRIVATE_DATA privateData=NULL;
	if(dev==NULL) {
		SMSC_WARNING("Smsc9118_get_stats(dev==NULL)");
		return NULL;
	}
	if(dev->priv==NULL) {
	//	SMSC_WARNING("Smsc9118_get_stats(dev->priv==NULL)");
		return NULL;
	}

	privateData=(PPRIVATE_DATA)(dev->priv);
	if(privateData->Running) {
		privateData->stats.rx_dropped+=Lan_GetRegDW(RX_DROP);
		Tx_UpdateTxCounters(privateData);
	}
	return &(privateData->stats);
}

void Smsc9118_set_multicast_list(struct net_device *dev)
{
	SMSC_ASSERT(dev!=NULL);
	Rx_SetMulticastList(dev);
}

int Smsc9118_do_ioctl(
	struct net_device *dev, 
	struct ifreq *ifr,
	int cmd)
{
	PPRIVATE_DATA privateData=NULL;
	PSMSC9118_IOCTL_DATA ioctlData=NULL;
	BOOLEAN success=FALSE;
//	SMSC_TRACE("-->Smsc9118_do_ioctl");
//	SMSC_TRACE("cmd=%d,SIOCGMIIPHY=%d,SIOCDEVPRIVATE=%d",
//		cmd,SIOCGMIIPHY,SIOCDEVPRIVATE);
	SMSC_ASSERT(dev!=NULL);
	SMSC_ASSERT(dev->priv!=NULL);
	privateData=((PPRIVATE_DATA)dev->priv);
	if(ifr==NULL) {
//		SMSC_WARNING("Smsc9118_do_ioctl(ifr==NULL)");
		goto DONE;
	}

	if(privateData->LanInitialized) {
		// standard MII IOC's
		struct mii_ioctl_data * const data=
			(struct mii_ioctl_data *) & ifr->ifr_data;
		switch(cmd) {
		case SIOCGMIIPHY:

		case SIOCDEVPRIVATE:
			data->phy_id=1;
//			SMSC_TRACE("SIOCGMIIPHY: phy_id set to 0x%04X",data->phy_id);
			return 0;
		case SIOCGMIIREG:
		case SIOCDEVPRIVATE+1:
			{
				DWORD dwIntFlags=0;
				VL_KEY keyCode=Vl_WaitForLock(&(privateData->MacPhyLock),&dwIntFlags);
				data->val_out=Phy_GetRegW(
					privateData,data->reg_num,keyCode);
				Vl_ReleaseLock(&(privateData->MacPhyLock),keyCode,&dwIntFlags);
			}
//			SMSC_TRACE("SIOCGMIIREG: phy_id=0x%04X, reg_num=0x%04X, val_out set to 0x%04X",
//				data->phy_id,data->reg_num,data->val_out);
			return 0;
		case SIOCSMIIREG:
		case SIOCDEVPRIVATE+2:
//			SMSC_TRACE("SIOCSMIIREG: phy_id=0x%04X, reg_num=0x%04X, val_in=0x%04X",
//				data->phy_id,data->reg_num,data->val_in);
			{
				DWORD dwIntFlags=0;
				VL_KEY keyCode=Vl_WaitForLock(&(privateData->MacPhyLock),&dwIntFlags);
				Phy_SetRegW(
					privateData,data->reg_num,((WORD)(data->val_in)),keyCode);
				Vl_ReleaseLock(&(privateData->MacPhyLock),keyCode,&dwIntFlags);
			}
			return 0;
		default:break;//make lint happy
		}
	}
	if(ifr->ifr_data==NULL) {
//		SMSC_WARNING("Smsc9118_do_ioctl(ifr->ifr_data==NULL)");
		goto DONE;
	}
	if(cmd!=((int)SMSC9118_IOCTL)) goto DONE;
	ioctlData=(PSMSC9118_IOCTL_DATA)(ifr->ifr_data);
	if(ioctlData->dwSignature!=SMSC9118_APP_SIGNATURE) {
		goto DONE;
	}

	switch(ioctlData->dwCommand) {
	case COMMAND_GET_SIGNATURE:
		success=TRUE;
		break;
	case COMMAND_GET_FLOW_PARAMS:
		ioctlData->Data[0]=privateData->RxFlowMeasuredMaxThroughput;
		ioctlData->Data[1]=privateData->RxFlowMeasuredMaxPacketCount;
		ioctlData->Data[2]=privateData->RxFlowParameters.MaxThroughput;
		ioctlData->Data[3]=privateData->RxFlowParameters.MaxPacketCount;
		ioctlData->Data[4]=privateData->RxFlowParameters.PacketCost;
		ioctlData->Data[5]=privateData->RxFlowParameters.BurstPeriod;
		ioctlData->Data[6]=privateData->RxFlowMaxWorkLoad;
		ioctlData->Data[7]=Lan_GetRegDW(INT_CFG)>>24;
		privateData->RxFlowMeasuredMaxThroughput=0;
		privateData->RxFlowMeasuredMaxPacketCount=0;
		success=TRUE;
		break;
	case COMMAND_SET_FLOW_PARAMS:
		if(!(privateData->RxFlowControlActive)) {
			privateData->RxFlowParameters.MaxThroughput=ioctlData->Data[2];
			privateData->RxFlowParameters.MaxPacketCount=ioctlData->Data[3];
			privateData->RxFlowParameters.PacketCost=ioctlData->Data[4];
			privateData->RxFlowParameters.BurstPeriod=ioctlData->Data[5];
			if(ioctlData->Data[6]==0xFFFFFFFFUL) {
				privateData->RxFlowMaxWorkLoad=
					privateData->RxFlowParameters.MaxThroughpu

⌨️ 快捷键说明

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