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

📄 smsc911x.c

📁 smsc911x 网卡驱动 This the users/programmers guide for the LAN911x Linux Driver The following sections
💻 C
📖 第 1 页 / 共 5 页
字号:
				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_);

	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("<--Smsc911x_open, result=%d",result);
	return result;
}

int Smsc911x_stop(struct net_device *dev)
{
	int result=0;
	PPRIVATE_DATA privateData=NULL;
	SMSC_TRACE("-->Smsc911x_stop(dev=0x%08lX)",(DWORD)dev);
	if(dev==NULL) {
		SMSC_WARNING("Smsc911x_stop(dev==NULL)");
		result=-EFAULT;
		goto DONE;
	}
	privateData=(PPRIVATE_DATA)(dev->priv);
	if(privateData==NULL) {
		SMSC_WARNING("Smsc911x_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];
		memcpy(ifName,privateData->ifName,SMSC_IF_NAME_SIZE);

		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);
	}

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

int Smsc911x_hard_start_xmit(
	struct sk_buff *skb, struct net_device * const dev)
{
	int result=0;
	PPRIVATE_DATA privateData=NULL;
//	SMSC_TRACE("-->Smsc911x_hard_start_xmit(skb=0x%08lX,dev=0x%08lX)",(DWORD)skb,(DWORD)dev);
	if(skb==NULL) {
		SMSC_WARNING("Smsc911x_hard_start_xmit(skb==NULL)");
		result=-EFAULT;
		goto DONE;
	}
	if(dev==NULL) {
		SMSC_WARNING("Smsc911x_hard_start_xmit(dev==NULL)");
		result=-EFAULT;
		goto DONE;
	}
	if(dev->priv==NULL) {
		SMSC_WARNING("Smsc911x_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("<--Smsc911x_hard_start_xmit, result=%d",result);
	return result;
}

struct net_device_stats * Smsc911x_get_stats(struct net_device * const dev)
{
	PPRIVATE_DATA privateData=NULL;
	if(dev==NULL) {
		SMSC_WARNING("Smsc911x_get_stats(dev==NULL)");
		return NULL;
	}
	if(dev->priv==NULL) {
		SMSC_WARNING("Smsc911x_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 Smsc911x_set_multicast_list(struct net_device *dev)
{
	SMSC_ASSERT(dev!=NULL);
	Rx_SetMulticastList(dev);
}

int Smsc911x_do_ioctl(
	struct net_device *dev, 
	struct ifreq *ifr,
	int cmd)
{
	PPRIVATE_DATA privateData=NULL;
	PSMSC911x_IOCTL_DATA ioctlData=NULL;
	BOOLEAN success=FALSE;
//	SMSC_TRACE("-->Smsc911x_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("Smsc911x_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("Smsc911x_do_ioctl(ifr->ifr_data==NULL)");
		goto DONE;
	}
	if(cmd!=((int)SMSC911x_IOCTL)) goto DONE;
	ioctlData=(PSMSC911x_IOCTL_DATA)(ifr->ifr_data);
	if(ioctlData->dwSignature!=SMSC911x_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.MaxThroughput+
					(privateData->RxFlowParameters.MaxPacketCount*
					privateData->RxFlowParameters.PacketCost);
			} else {
				privateData->RxFlowMaxWorkLoad=ioctlData->Data[6];
			}
			Lan_SetIntDeas(privateData,ioctlData->Data[7]);
			privateData->RxFlowBurstMaxWorkLoad=
				(privateData->RxFlowMaxWorkLoad*
				privateData->RxFlowParameters.BurstPeriod)/1000;
			success=TRUE;
		};break;
	case COMMAND_GET_CONFIGURATION:
		ioctlData->Data[0]=DRIVER_VERSION;
		ioctlData->Data[1]=lan_base;
		ioctlData->Data[2]=bus_width;
		ioctlData->Data[3]=link_mode;
		ioctlData->Data[4]=irq;
		ioctlData->Data[5]=int_deas;
		ioctlData->Data[6]=irq_pol;
		ioctlData->Data[7]=irq_type;
		ioctlData->Data[8]=rx_dma;
		ioctlData->Data[9]=tx_dma;
		ioctlData->Data[10]=dma_threshold;
		ioctlData->Data[11]=mac_addr_hi16;
		ioctlData->Data[12]=mac_addr_lo32;
		ioctlData->Data[13]=debug_mode;
		ioctlData->Data[14]=tx_fif_sz;
		ioctlData->Data[15]=afc_cfg;
		ioctlData->Data[16]=tasklets;
		ioctlData->Data[17]=max_throughput;
		ioctlData->Data[18]=max_packet_count;
		ioctlData->Data[19]=packet_cost;
		ioctlData->Data[20]=burst_period;
		ioctlData->Data[21]=max_work_load;
		ioctlData->Data[22]=privateData->dwIdRev;
		ioctlData->Data[23]=privateData->dwFpgaRev;
		ioctlData->Data[24]=1;
		ioctlData->Data[25]=privateData->dwPhyId;
		ioctlData->Data[26]=privateData->bPhyModel;
		ioctlData->Data[27]=privateData->bPhyRev;
		ioctlData->Data[28]=privateData->dwLinkSpeed;
		ioctlData->Data[29]=privateData->RxFlowMeasuredMaxThroughput;
		ioctlData->Data[30]=privateData->RxFlowMeasuredMaxPacketCount;
		ioctlData->Data[31]=privateData->RxFlowParameters.MaxThroughput;
		ioctlData->Data[32]=privateData->RxFlowParameters.MaxPacketCount;
		ioctlData->Data[33]=privateData->RxFlowParameters.PacketCost;
		ioctlData->Data[34]=privateData->RxFlowParameters.BurstPeriod;
		ioctlData->Data[35]=privateData->RxFlowMaxWorkLoad;
		sprintf(ioctlData->Strng1,"%s, %s",__DATE__,__TIME__);
		sprintf(ioctlData->Strng2,"%s",privateData->ifName);
		privateData->RxFlowMeasuredMaxThroughput=0;
		privateData->RxFlowMeasuredMaxPacketCount=0;
		success=TRUE;
		break;
	case COMMAND_LAN_GET_REG:
		if((ioctlData->Data[0]<LAN_REGISTER_EXTENT)&&
			((ioctlData->Data[0]&0x3UL)==0))
		{
			ioctlData->Data[1]=
				(*((volatile DWORD *)(privateData->dwLanBase+
						ioctlData->Data[0])));
			success=TRUE;
		} else {
			SMSC_WARNING("Reading LAN911x Mem Map Failed");
			goto MEM_MAP_ACCESS_FAILED;
		}
		break;
	case COMMAND_LAN_SET_REG:
		if((ioctlData->Data[0]<LAN_REGISTER_EXTENT)&&
			((ioctlData->Data[0]&0x3UL)==0))
		{
			(*((volatile DWORD *)(privateData->dwLanBase+
						ioctlData->Data[0])))=ioctlData->Data[1];
			success=TRUE;
		} else {
			SMSC_WARNING("Reading LAN911x Mem Map Failed");
MEM_MAP_ACCESS_FAILED:
			SMSC_WARNING("  Invalid offset == 0x%08lX",ioctlData->Data[0]);
			if(ioctlData->Data[0]>=LAN_REGISTER_EXTENT) {
				SMSC_WARNING("    Out of range");
			}
			if(ioctlData->Data[0]&0x3UL) {
				SMSC_WARNING("    Not DWORD aligned");
			}
		}
		break;
	case COMMAND_MAC_GET_REG:
		if((ioctlData->Data[0]<=0xC)&&(privateData->LanInitialized)) {
			DWORD dwIntFlags=0;
			VL_KEY keyCode=Vl_WaitForLock(&(privateData->MacPhyLock),&dwIntFlags);
			ioctlData->Data[1]=
				Mac_GetRegDW(privateData,ioctlData->Data[0],keyCode);
			Vl_ReleaseLock(&(privateData->MacPhyLock),keyCode,&dwIntFlags);
			success=TRUE;
		} else {
			SMSC_WARNING("Reading Mac Register Failed");
			goto MAC_ACCESS_FAILURE;
		}
		break;
	case COMMAND_MAC_SET_REG:
		if((ioctlData->Data[0]<=0xC)&&(privateData->LanInitialized)) {
			DWORD dwIntFlags=0;
			VL_KEY keyCode=Vl_WaitForLock(&(privateData->MacPhyLock),&dwIntFlags);
			Mac_SetRegDW(
				privateData,
				ioctlData->Data[0],
				ioctlData->Data[1],
				keyCode);
			Vl_ReleaseLock(&(privateData->MacPhyLock),keyCode,&dwIntFlags);
			success=TRUE;
		} else {
			SMSC_WARNING("Writing Mac Register Failed");
MAC_

⌨️ 快捷键说明

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