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

📄 smsc911x.c

📁 smsc911x 网卡驱动 This the users/programmers guide for the LAN911x Linux Driver The following sections
💻 C
📖 第 1 页 / 共 5 页
字号:
		SMSC_TRACE("  irq_pol          = %ld, IRQ output is active high",irq_pol);
	} else {
		SMSC_TRACE("  irq_pol          = %ld, IRQ output is active low",irq_pol);
	}
	if(irq_type) {
		SMSC_TRACE("  irq_type         = %ld, IRQ output is Push-Pull driver",irq_type);
	} else {
		SMSC_TRACE("  irq_type         = %ld, IRQ output is Open-Drain buffer",irq_type);
	}
	if(rx_dma<TRANSFER_REQUEST_DMA) {
		if(Platform_IsValidDmaChannel(rx_dma)) {
			SMSC_TRACE(
				   "  rx_dma           = %ld, DMA Channel %ld",rx_dma,rx_dma);
		} else {
			SMSC_WARNING("  rx_dma        = %ld, Invalid Dma Channel",rx_dma);
			rx_dma=TRANSFER_PIO;
			SMSC_WARNING("    resetting rx_dma to %ld, RX will use PIO",rx_dma);
		}
	} else if(rx_dma==TRANSFER_REQUEST_DMA) {
		SMSC_TRACE("  rx_dma           = %ld, RX will try to find available channel",rx_dma);
	} else {
		SMSC_TRACE("  rx_dma           = %ld, RX will use PIO",rx_dma);
	}
	if(tx_dma<TRANSFER_REQUEST_DMA) {
		if(Platform_IsValidDmaChannel(tx_dma)) {
			if(tx_dma!=rx_dma) {
				SMSC_TRACE(
				   "  tx_dma           = %ld, DMA Channel %ld",tx_dma,tx_dma);
			} else {
				SMSC_WARNING("  tx_dma == rx_dma");
				tx_dma=TRANSFER_PIO;
				SMSC_WARNING("    resetting tx_dma to %ld, TX will use PIO",tx_dma);
			}
		} else {
			SMSC_WARNING("  tx_dma        = %ld, Invalid Dma Channel",tx_dma);
			tx_dma=TRANSFER_PIO;
			SMSC_WARNING("    resetting tx_dma to %ld, TX will use PIO",tx_dma);
		}
	} else if(tx_dma==TRANSFER_REQUEST_DMA) {
		SMSC_TRACE("  tx_dma           = %ld, TX will try to find available channel",tx_dma);
	} else {
		SMSC_TRACE("  tx_dma           = %ld, TX will use PIO",tx_dma);
	}
	SMSC_TRACE(    "  dma_threshold    = %ld",dma_threshold);

	if(mac_addr_hi16==0xFFFFFFFFUL) {
		SMSC_TRACE("  mac_addr_hi16    = 0x%08lX, will attempt to read from LAN911x",mac_addr_hi16);
		SMSC_TRACE("  mac_addr_lo32    = 0x%08lX, will attempt to read from LAN911x",mac_addr_lo32);
	} else {
		if(mac_addr_hi16&0xFFFF0000UL) {
			//The high word is reserved
			SMSC_WARNING("  mac_addr_hi16 = 0x%08lX, reserved bits are high.",mac_addr_hi16);
			mac_addr_hi16&=0x0000FFFFUL;
			SMSC_WARNING("    reseting to mac_addr_hi16 = 0x%08lX",mac_addr_hi16);
		}
		if(mac_addr_lo32&0x00000001UL) {
			//bit 0 is the I/G bit
			SMSC_WARNING("  mac_addr_lo32 = 0x%08lX, I/G bit is set.",mac_addr_lo32);
			mac_addr_lo32&=0xFFFFFFFEUL;
			SMSC_WARNING("    reseting to mac_addr_lo32 = 0x%08lX",mac_addr_lo32);			
		}
		SMSC_TRACE("  mac_addr_hi16    = 0x%08lX",mac_addr_hi16);
		SMSC_TRACE("  mac_addr_lo32    = 0x%08lX",mac_addr_lo32);
	}
	SMSC_TRACE(    "  debug_mode       = 0x%08lX",debug_mode);
	if(tx_fif_sz&(~HW_CFG_TX_FIF_SZ_)) {
		SMSC_WARNING("tx_fif_sz = 0x%08lX is invalid",tx_fif_sz);
		tx_fif_sz&=HW_CFG_TX_FIF_SZ_;
		SMSC_WARNING("  resetting tx_fif_sz to 0x%08lX",tx_fif_sz);
	}
	if(tx_fif_sz>0x000E0000UL) {
		SMSC_WARNING("tx_fif_sz = 0x%08lX is too high",tx_fif_sz);
		tx_fif_sz=0x000E0000UL;
		SMSC_WARNING(" resetting tx_fif_sz to 0x%08lX",tx_fif_sz);
	}
	if(tx_fif_sz<0x00020000UL) {
		SMSC_WARNING("tx_fif_sz = 0x%08lX is too low",tx_fif_sz);
		tx_fif_sz=0x00020000UL;
		SMSC_WARNING(" resetting tx_fif_sz to 0x%08lX",tx_fif_sz);
	}
	SMSC_TRACE(    "  tx_fif_sz        = 0x%08lX",tx_fif_sz);
	if(afc_cfg==0xFFFFFFFFUL) {
		SMSC_TRACE("  afc_cfg          = 0x%08lX, driver will decide",afc_cfg);
	} else {
		if(afc_cfg&0xFF000000UL) {
			SMSC_WARNING("afc_cfg = 0x%08lX is invalid",afc_cfg);
			afc_cfg&=0xFFFFFFFFUL;
			SMSC_WARNING(" resetting to afc_cfg = 0x%08lX, driver will decide",afc_cfg);
		} else {
			SMSC_TRACE(
				   "  afc_cfg          = 0x%08lX",afc_cfg);
		}
	}
	if(tasklets) {
		SMSC_TRACE("  tasklets         = 0x%08lX, Tasklets enabled",tasklets);
	} else {
		SMSC_TRACE("  tasklets         = 0, Tasklets disabled");
	}
	if(phy_addr==0xFFFFFFFFUL) {
		SMSC_TRACE("  phy_addr         = 0xFFFFFFFF, Use internal phy");
	} else if(phy_addr<=31UL) {
		SMSC_TRACE("  phy_addr         = 0x%08lX, use this address for external phy",phy_addr);
	} else {
		SMSC_TRACE("  phy_addr         = 0x%08lX, auto detect external phy",phy_addr);
	}
	if(max_throughput) {
		SMSC_TRACE("  max_throughput   = 0x%08lX, Use platform default",max_throughput);
	} else {
		SMSC_TRACE("  max_throughput   = 0x%08lX",max_throughput);
	}
	if(max_packet_count) {
		SMSC_TRACE("  max_packet_count = 0x%08lX, Use platform default",max_packet_count);
	} else {
		SMSC_TRACE("  max_packet_count = 0x%08lX",max_packet_count);
	}
	if(packet_cost) {
		SMSC_TRACE("  packet_cost      = 0x%08lX, Use platform default",packet_cost);
	} else {
		SMSC_TRACE("  packet_cost      = 0x%08lX",packet_cost);
	}
	if(burst_period) {
		SMSC_TRACE("  burst_period     = 0x%08lX, Use platform default",burst_period);
	} else {
		SMSC_TRACE("  burst_period     = 0x%08lX",burst_period);
	}
	if(max_work_load) {
		SMSC_TRACE("  max_work_load    = 0x%08lX, Use platform default",max_work_load);
	} else {
		SMSC_TRACE("  max_work_load    = 0x%08lX",max_work_load);
	}

	strcpy(SMSC911x.name,"eth%d");

	result=register_netdev(&SMSC911x);
	if(result) {
		SMSC_WARNING("error %i registering device",result);
	} else {
		device_present=1;
		SMSC_TRACE("  Interface Name = \"%s\"",SMSC911x.name);
	}
	result=result;//make lint happy
	SMSC_TRACE("<-- init_module()");
	return device_present ? 0 : -ENODEV;
}

void Smsc911x_cleanup_module(void)
{
	SMSC_TRACE("--> cleanup_module()");
	if(SMSC911x.priv!=NULL) {
		kfree(SMSC911x.priv);
	}
	unregister_netdev(&SMSC911x);
	SMSC_TRACE("<-- cleanup_module()");
}

int Smsc911x_init(struct net_device *dev)
{
	DWORD dwLanBase=0UL;
	DWORD dwIdRev=0UL;
	DWORD dwFpgaRev=0UL;
	PPRIVATE_DATA privateData=NULL;
	PPLATFORM_DATA platformData=NULL;
	int result=-ENODEV;
	SMSC_TRACE("-->Smsc911x_init(dev=0x%08lX)",(DWORD)dev);

	if(dev==NULL) {
		SMSC_WARNING("Smsc911x_init(dev==NULL)");
		result=-EFAULT;
		goto DONE;
	}

	if(dev->priv!=NULL) {
		SMSC_WARNING("dev->priv!=NULL, going to overwrite pointer");
	}
	dev->priv=kmalloc(sizeof(PRIVATE_DATA),GFP_KERNEL);
	if(dev->priv==NULL) {
		SMSC_WARNING("Unable to allocate PRIVATE_DATA");
		result=-ENOMEM;
		goto DONE;
	}
	memset(dev->priv,0,sizeof(PRIVATE_DATA));
	privateData=(PPRIVATE_DATA)(dev->priv);
	platformData=&(privateData->PlatformData);

	dwLanBase=Platform_Initialize(
		platformData,
		lan_base,bus_width);

	if(dwLanBase==0UL) {
		SMSC_WARNING("dwLanBase==0x00000000");
		result=-ENODEV;
		goto DONE;
	}
	SMSC_TRACE("dwLanBase=0x%08lX",dwLanBase);

	if(check_mem_region(dwLanBase,LAN_REGISTER_EXTENT)!=0) {
		SMSC_WARNING("  Memory Region specified (0x%08lX to 0x%08lX) is not available.",
			dwLanBase,dwLanBase+LAN_REGISTER_EXTENT-1UL);
		result=-ENOMEM;
		goto DONE;
	}
	
	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
UNKNOWN_CHIP:
		SMSC_WARNING("  LAN911x NOT Identified, dwIdRev==0x%08lX",dwIdRev);
		result=-ENODEV;
		goto DONE;
	}
	switch(dwIdRev&0xFFFF0000UL) {
	case 0x01180000UL:
		SMSC_TRACE("  LAN9118 identified, dwIdRev==0x%08lX",dwIdRev);break;
	case 0x01170000UL:
		SMSC_TRACE("  LAN9117 identified, dwIdRev==0x%08lX",dwIdRev);break;
	case 0x01160000UL:
		SMSC_TRACE("  LAN9116 identified, dwIdRev==0x%08lX",dwIdRev);break;
	case 0x01150000UL:
		SMSC_TRACE("  LAN9115 identified, dwIdRev==0x%08lX",dwIdRev);break;
	default:
		goto UNKNOWN_CHIP;
	}
	dwFpgaRev=Lan_GetRegDW(FPGA_REV);
	SMSC_TRACE("  FPGA_REV == 0x%08lX",dwFpgaRev);

	ether_setup(dev);
	dev->open=				Smsc911x_open;
	dev->stop=				Smsc911x_stop;
	dev->hard_start_xmit=	Smsc911x_hard_start_xmit;
	dev->get_stats=			Smsc911x_get_stats;
	dev->do_ioctl=			Smsc911x_do_ioctl;
	dev->set_multicast_list=Smsc911x_set_multicast_list;
	dev->flags|=IFF_MULTICAST;

	SET_MODULE_OWNER(dev);

	privateData->dwIdRev=dwIdRev;
	privateData->dwFpgaRev=dwFpgaRev&(0x000000FFUL);
	privateData->dev=dev;

	sprintf(privateData->ifName,"%s",dev->name);
	result=0;
    
DONE:
	if(result!=0) {
		if(dev!=NULL) {
			if(dev->priv!=NULL) {
				kfree(dev->priv);
				dev->priv=NULL;
			}
		}
	}
	SMSC_TRACE("<--Smsc911x_init(), result=%d",result);
	return result;
}

int Smsc911x_open(struct net_device *dev)
{
	int result=-ENODEV;
	PPRIVATE_DATA privateData=NULL;
	PPLATFORM_DATA platformData=NULL;
	BOOLEAN acquired_mem_region=FALSE;
	BOOLEAN acquired_isr=FALSE;
	SMSC_TRACE("-->Smsc911x_open(dev=0x%08lX)",(DWORD)dev);
	if(dev==NULL) {
		SMSC_WARNING("Smsc911x_open(dev==NULL)");
		result=-EFAULT;
		goto DONE;
	}
	privateData=(PPRIVATE_DATA)(dev->priv);
	if(privateData==NULL) {
		SMSC_WARNING("Smsc911x_open(privateData==NULL)");
		result=-EFAULT;
		goto DONE;
	}
	platformData=&(privateData->PlatformData);

	//get memory region
	if(check_mem_region(privateData->dwLanBase,LAN_REGISTER_EXTENT)!=0)
	{
		SMSC_WARNING("Device memory is already in use.");
		result=-ENOMEM;
		goto DONE;
	}
	request_mem_region(privateData->dwLanBase,LAN_REGISTER_EXTENT,"SMSC_LAN911x");
	acquired_mem_region=TRUE;

	//initialize the LAN911x
	{
		DWORD dwIntCfg=0;
		if(irq_pol) {
			dwIntCfg|=INT_CFG_IRQ_POL_;
		}
		if(irq_type) {
			dwIntCfg|=INT_CFG_IRQ_TYPE_;
		}
		if(!Lan_Initialize(privateData,dwIntCfg,tx_fif_sz,afc_cfg))
		{
			SMSC_WARNING("Failed Lan_Initialize");
			result=-ENODEV;
			goto DONE;
		}
	}


	if(!Platform_RequestIRQ(platformData,irq,Smsc911x_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=1000;
		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 LAN911x 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));
	}

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

	{
		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) {

⌨️ 快捷键说明

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