📄 smsc911x.c
字号:
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 + -