dev_init()网络设备的初始化函数如下:


/*
 * Initialize the DEV module. At boot time this walks the device list and
 * unhooks any devices that fail to initialise (normally hardware not
 * present) and leaves us with a valid list of present and active devices.
 *
 * The PCMCIA code may need to change this a little, and add a pair
 * of register_inet_device() unregister_inet_device() calls. This will be
 * needed for ethernet as modules support.
 */
 
void dev_init(void)
{
 struct device *dev, *dev2;

 /*
  * Add the devices.
  * If the call to dev->init fails, the dev is removed
  * from the chain disconnecting the device until the
  * next reboot.
  */
 
 dev2 = NULL;
 for (dev = dev_base; dev != NULL; dev=dev->next) //循环移除设备由璞傅?ev_base指向的网络设备链表
 {
  if (dev->init && dev->init(dev)) //如果设备有初始化函数并且初始化失败,则从链表摘除设备(init()函数成功返回0)
  {
   /*
    * It failed to come up. Unhook it.这个函数还挺有技巧性的,从默认配置的设备中扫描不存在的设备,将其移除
    */
   
   if (dev2 == NULL)
    dev_base = dev->next;
   else
    dev2->next = dev->next;
  }
  else
  {
   dev2 = dev;
  }
 }
}
 


  这里我们看一下dev_base这个队列是如何定义的,这里我们仅仅看eth网卡的定义方式即可


/* "eth0" defaults to autoprobe (== 0), other use a base of 0xffe0 (== -0x20),
   which means "don't probe".  These entries exist to only to provide empty
   slots which may be enabled at boot-time. */

static struct device eth3_dev = {
    "eth3", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe };
static struct device eth2_dev = {
    "eth2", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, eth3_dev, ethif_probe };
static struct device eth1_dev = {
    "eth1", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, eth2_dev, ethif_probe };

static struct device eth0_dev = {
    "eth0", 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, eth1_dev, ethif_probe };

#   undef NEXT_DEV
#   define NEXT_DEV (eth0_dev)
 


  可以看出eth系列网卡设备的init函数定义为ethif_probe(),该函数会调用具体网卡的探测函数,我们还是以 NS8390 ethernet网卡为例来分析,该网卡的驱动实现文件为drivers/net/ne.c

  ethif_probe()函数会调用函数ne_probe()探测函数,而该函数对设备地址进行检查后调用ne_probe1()函数,具体工作有ne_probe1()函数完成。