📄 simp911x.c
字号:
// through register_netdev, to Simp911x_init
struct net_device SIMP911X[MAX_INSTANCES];
#define DRIVER_VERSION (0x00000111UL)
//entry point for loading the module
int Simp911x_init_module(void)
{
int result=0;
int device_present=0;
DWORD index=0;
SMSC_TRACE("--> init_module()");
#ifdef USE_PHY_WORK_AROUND
SMSC_TRACE("Simple Driver Version = %lX.%02lX, with phy work around",
(DRIVER_VERSION>>8),(DRIVER_VERSION&0xFFUL));
#else
SMSC_TRACE("Simple Driver Version = %lX.%02lX",
(DRIVER_VERSION>>8),(DRIVER_VERSION&0xFFUL));
#endif
SMSC_TRACE("Compiled: %s, %s",__DATE__,__TIME__);
if(lan_base[0]!=0) {
for(index=0;index<MAX_INSTANCES;index++) {
SIMP911X[index].priv=NULL;
SIMP911X[index].init=Simp911x_init;
if(lan_base[index]!=0) {
strcpy(SIMP911X[index].name,"eth%d");
gRegistrationIndex=index;
result=register_netdev(&(SIMP911X[index]));
if(result) {
SMSC_WARNING("error %i registering device",result);
registered[index]=0;
} else {
device_present=1;
registered[index]=1;
SMSC_TRACE(" Interface Name = \"%s\"",SIMP911X[index].name);
}
} else {
registered[index]=0;
}
}
} else {
SMSC_WARNING("Must supply lan_base and irq.");
}
SMSC_TRACE("<-- init_module()");
return device_present ? 0 : -ENODEV;
}
//entry point for unloading the module
void Simp911x_cleanup_module(void)
{
DWORD index=0;
SMSC_TRACE("--> cleanup_module()");
for(index=0;index<MAX_INSTANCES;index++) {
if(SIMP911X[index].priv!=NULL) {
kfree(SIMP911X[index].priv);
}
if(registered[index]) {
unregister_netdev(&(SIMP911X[index]));
}
}
SMSC_TRACE("<-- cleanup_module()");
}
//entry point for initializing the driver
int Simp911x_init(struct net_device *dev)
{
DWORD dwIdRev=0UL;
PPRIVATE_DATA privateData=NULL;
int result=-ENODEV;
SMSC_TRACE("-->Simp911x_init(dev=0x%08lX)",(DWORD)dev);
if(dev==NULL) {
SMSC_WARNING("Simp911x_init(dev==NULL)");
result=-EFAULT;
goto DONE;
}
SMSC_TRACE("Device Instance Index = %ld",gRegistrationIndex);
SMSC_TRACE("Driver Parameters");
SMSC_TRACE(" lan_base = 0x%08lX",lan_base[gRegistrationIndex]);
SMSC_TRACE( " irq = %ld",irq[gRegistrationIndex]);
if(mac_addr_hi16[gRegistrationIndex]==0xFFFFFFFFUL) {
SMSC_TRACE(" mac_addr_hi16 = 0x%08lX, will attempt to read from LAN911x",
mac_addr_hi16[gRegistrationIndex]);
SMSC_TRACE(" mac_addr_lo32 = 0x%08lX, will attempt to read from LAN911x",
mac_addr_lo32[gRegistrationIndex]);
} else {
if(mac_addr_hi16[gRegistrationIndex]&0xFFFF0000UL) {
//The high word is reserved
SMSC_WARNING(" mac_addr_hi16 = 0x%08lX, reserved bits are high.",
mac_addr_hi16[gRegistrationIndex]);
mac_addr_hi16[gRegistrationIndex]&=0x0000FFFFUL;
SMSC_WARNING(" reseting to mac_addr_hi16 = 0x%08lX",
mac_addr_hi16[gRegistrationIndex]);
}
if(mac_addr_lo32[gRegistrationIndex]&0x00000001UL) {
//bit 0 is the I/G bit
SMSC_WARNING(" mac_addr_lo32 = 0x%08lX, I/G bit is set.",
mac_addr_lo32[gRegistrationIndex]);
mac_addr_lo32[gRegistrationIndex]&=0xFFFFFFFEUL;
SMSC_WARNING(" reseting to mac_addr_lo32 = 0x%08lX",
mac_addr_lo32[gRegistrationIndex]);
}
SMSC_TRACE(" mac_addr_hi16 = 0x%08lX",
mac_addr_hi16[gRegistrationIndex]);
SMSC_TRACE(" mac_addr_lo32 = 0x%08lX",
mac_addr_lo32[gRegistrationIndex]);
}
SMSC_TRACE( " debug_mode = 0x%08lX",debug_mode);
if(phy_addr[gRegistrationIndex]==0xFFFFFFFFUL) {
SMSC_TRACE(" phy_addr = 0xFFFFFFFF, Use internal phy");
} else if(phy_addr[gRegistrationIndex]<=31) {
SMSC_TRACE(" phy_addr = 0x%08lX, use this address for external phy",
phy_addr[gRegistrationIndex]);
} else {
SMSC_TRACE(" phy_addr = 0x%08lX, auto detect external phy",
phy_addr[gRegistrationIndex]);
}
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);
if(lan_base[gRegistrationIndex]==0UL) {
SMSC_WARNING("lan_base==0x00000000");
result=-ENODEV;
goto DONE;
}
if(check_mem_region(lan_base[gRegistrationIndex],LAN_REGISTER_EXTENT)!=0) {
SMSC_WARNING(" Memory Region specified (0x%08lX to 0x%08lX) is not available.",
lan_base[gRegistrationIndex],lan_base[gRegistrationIndex]+LAN_REGISTER_EXTENT-1);
result=-ENOMEM;
goto DONE;
}
privateData->dwLanBase=lan_base[gRegistrationIndex];
privateData->dwInstanceIndex=gRegistrationIndex;
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;
case 0x01120000UL:
SMSC_TRACE("LAN9112 identified, dwIdRev==0x%08lX",dwIdRev);break;
default:
goto UNKNOWN_CHIP;
}
privateData->dwIdRev=dwIdRev;
if((dwIdRev&0x0000FFFFUL)==0UL) {
SMSC_WARNING("This driver is not intended for this chip revision");
}
ether_setup(dev);
dev->open= Simp911x_open;
dev->stop= Simp911x_stop;
dev->hard_start_xmit= Simp911x_hard_start_xmit;
dev->get_stats= Simp911x_get_stats;
dev->set_multicast_list=Simp911x_set_multicast_list;
dev->flags|=IFF_MULTICAST;
SET_MODULE_OWNER(dev);
privateData->dev=dev;
result=0;
DONE:
if(result!=0) {
//something went wrong, perform clean up
if(dev!=NULL) {
if(dev->priv!=NULL) {
kfree(dev->priv);
dev->priv=NULL;
}
}
}
SMSC_TRACE("<--Simp911x_init(), result=%d",result);
return result;
}
//entry point for starting/opening the interface
int Simp911x_open(struct net_device *dev)
{
int result=-ENODEV;
PPRIVATE_DATA privateData=NULL;
BOOLEAN acquired_mem_region=FALSE;
BOOLEAN acquired_isr=FALSE;
char temp_name[25];
SMSC_TRACE("-->Simp911x_open(dev=0x%08lX)",(DWORD)dev);
if(dev==NULL) {
SMSC_WARNING("Simp911x_open(dev==NULL)");
result=-EFAULT;
goto DONE;
}
privateData=(PPRIVATE_DATA)(dev->priv);
if(privateData==NULL) {
SMSC_WARNING("Simp911x_open(privateData==NULL)");
result=-EFAULT;
goto DONE;
}
//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;
}
sprintf(temp_name,"SIMP_LAN911X_%ld",privateData->dwInstanceIndex);
request_mem_region(privateData->dwLanBase,LAN_REGISTER_EXTENT,temp_name);
acquired_mem_region=TRUE;
//initialize the LAN911x
{
const DWORD dwIntCfg=(((DWORD)22UL)<<24);//set interrupt deassertion to 220uS
//dwIntCfg|=INT_CFG_IRQ_POL_; //use this line to set IRQ_POL bit
//dwIntCfg|=INT_CFG_IRQ_TYPE_; //use this line to set IRQ_TYPE bit
if(!Lan_Initialize(privateData,dwIntCfg)) {
goto DONE;
}
}
sprintf(temp_name,"SIMP_LAN911X_ISR_%ld",privateData->dwInstanceIndex);
if(request_irq(
irq[privateData->dwInstanceIndex],
Simp911x_ISR,
SA_INTERRUPT,
temp_name,
privateData)!=0)
{
result=-ENODEV;
goto DONE;
}
acquired_isr=TRUE;
//must now test the IRQ connection to the ISR
SMSC_TRACE("Testing ISR using IRQ %ld",irq[privateData->dwInstanceIndex]);
{
DWORD dwTimeOut=1000;
privateData->RequestIrqDisable=FALSE;
privateData->SoftwareInterruptSignal=FALSE;
Lan_SetBitsDW(INT_EN,INT_EN_SW_INT_EN_);
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",irq[privateData->dwInstanceIndex]);
Mac_Initialize(privateData);
{//get mac address
DWORD dwHigh16=0;
DWORD dwLow32=0;
//Because this is part of the single threaded initialization
// path there is no need to acquire the MacPhyAccessLock
if(mac_addr_hi16[privateData->dwInstanceIndex]==0xFFFFFFFF) {
dwHigh16=Mac_GetRegDW(privateData,ADDRH);
dwLow32=Mac_GetRegDW(privateData,ADDRL);
if((dwHigh16==0x0000FFFFUL)&&(dwLow32==0xFFFFFFFF))
{
dwHigh16=0x00000070UL;
dwLow32=0x110F8000UL;
Mac_SetRegDW(privateData,ADDRH,dwHigh16);
Mac_SetRegDW(privateData,ADDRL,dwLow32);
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 {
dwHigh16=mac_addr_hi16[privateData->dwInstanceIndex];
dwLow32=mac_addr_lo32[privateData->dwInstanceIndex];
Mac_SetRegDW(privateData,ADDRH,dwHigh16);
Mac_SetRegDW(privateData,ADDRL,dwLow32);
SMSC_TRACE("Mac Address is set by parameter to 0x%04lX%08lX",
dwHigh16,dwLow32);
}
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[privateData->dwInstanceIndex]))
{
SMSC_WARNING("Failed to initialize Phy");
result=-ENODEV;
goto DONE;
}
Tx_Initialize(privateData);
Rx_Initialize(privateData);
#ifndef LINUX_2_6_OR_NEWER
MOD_INC_USE_COUNT;
#endif
netif_start_queue(dev);
result=0;
DONE:
if(result!=0) {
#ifndef LINUX_2_6_OR_NEWER
MOD_DEC_USE_COUNT;
#endif
if((acquired_isr)&&(privateData!=NULL)) {
free_irq(irq[privateData->dwInstanceIndex],privateData);
}
if((acquired_mem_region)&&(privateData!=NULL)) {
release_mem_region(
privateData->dwLanBase,
LAN_REGISTER_EXTENT);
}
}
SMSC_TRACE("<--Simp911x_open, result=%d",result);
return result;
}
//entry point for stopping the interface
int Simp911x_stop(struct net_device *dev)
{
int result=0;
PPRIVATE_DATA privateData=NULL;
SMSC_TRACE("-->Simp911x_stop(dev=0x%08lX)",(DWORD)dev);
if(dev==NULL) {
SMSC_WARNING("Simp911x_stop(dev==NULL)");
result=-EFAULT;
goto DONE;
}
privateData=(PPRIVATE_DATA)(dev->priv);
if(privateData==NULL) {
SMSC_WARNING("Simp911x_stop(privateData==NULL)");
result=-EFAULT;
goto DONE;
}
privateData->StopLinkPolling=TRUE;
del_timer_sync(&(privateData->LinkPollingTimer));
{//Disable IRQ safely, by using the software interrupt
// to do it in the ISR itself.
DWORD dwTimeOut=1000;
privateData->RequestIrqDisable=TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -