Chinaunix首页 | 论坛 | 博客
  • 博客访问: 145905
  • 博文数量: 55
  • 博客积分: 2510
  • 博客等级: 少校
  • 技术积分: 605
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-09 18:51
文章存档

2008年(55)

我的朋友

分类: LINUX

2008-05-03 23:15:30

网络设备的初始化
linux/include/linux/init.h
linux/net/net_init.c //好像现在变为了net/core/dev.c
linux/include/linux/etherdevice.h

网络设备被初始化,当linux内核发现了一定类型的设备通过调用probe函数去搜索一个适合的硬件和一个相关的驱动。
只要一个匹配的被发现了,那么驱动指明的初始化函数被调用。这个函数是通常被表示为__devinit或者__init,这两个东西被定义在linux/include/linux/init.h,当一个网络设备的驱动初始化函数或者probe函数被调用,第一件要做的就是申请驱动的私有化数据结构,这里的私有化数据结构包含了通用的net_device结构体;然后,必须设置一些关键的部位,第一个就是名字,它将作为后面用于注册网络接口设备,name通常被设置为一个字符串,用于标识设备的类型,比如,以太网设备通常用eth。最后的一位必须是%d。然后,当设备注册的时候,这个格式化的字符串被一个数字0-99替换;这俩步初始化至少可以用三种方式完成。非以太网设备可以在驱动的probe函数调用的时候去调用kmalloc去申请数据结构,通过dev_alloc_name去设置name字符串,然后直接初始化其他的设备特别的域(net_device 数据结构中的)。

linux提供了一些通用的设备申请和初始化函数,使得网络设备驱动的开发者可以比较方便进行开发,大部分这些可以在linux/net/net_init.c(我并没有再找到这个文件了)中,除了一些诶函数是为了特殊的以太网设备的,比如,我们将会看到以太网设备的初始化过程,这个过程使用了一个申请函数提供给了以太网设备驱动,这个函数alloc_etherdev(变成了一个宏了),这个函数定义在drivers/net/net_init.c和在文件linux/include/linux/etherdevice.h。数据结构的申请和初始化都被做了。在alloc_etherdev调用alloc_netdev,1* 传递一个指向setup函数的指针当作第二个参数,这个函数通常是ether_setup在早一些的内核版本中。函数netdev_boot_setup,实际是保存了所有boot time的设置杂一个netdev_boot_setup数据结构中,然后,这些设置被装入net_device数据结构中通过调用netdev_boot_setup_check.
当初始化到这一步时,net_device结构题被初始化:name,irq,base address,和io映射的范围。对于大多数的设备来说,更多的设备需要更多的数据被初始化在注册以前。硬件中断必须被设置,和任何的设备特殊的信息从设备中读出来,同时pci 配置空间,在这些结束后,初始化函数建立了自旋锁和其他的硬件特殊的信息,如果这些步骤不产生错误,那么priv被设置为指回到私有的数据结构,这些缓存被申请用来传输和接受从dma中。然后,指向这个驱动的服务函数被设置在net_device结构题中。最重要的服务例程是open,hard_start,stop,get_stats,set_multicast_list,和do_ioctl。然后一些特性将被填充去暗示设备的能力,比如计算ip校验和的功能。

1*
struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count)
{
       return alloc_netdev_mq(sizeof_priv, "eth%d", ether_setup, queue_count);
}
EXPORT_SYMBOL(alloc_etherdev_mq);

下面是一个实例:
/**
 147 * el1_probe:           -       probe for a 3c501
 148 * @dev: The device structure passed in to probe.
 149 *
 150 * This can be called from two places. The network layer will probe using
 151 * a device structure passed in with the probe information completed. For a
 152 * modular driver we use #init_module to fill in our own structure and probe
 153 * for it.
 154 *
 155 * Returns 0 on success. ENXIO if asked not to probe and ENODEV if asked to
 156 * probe and failing to find anything.
 157 */
 158
 159struct net_device * __init el1_probe(int unit)
 160{
 161        struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
 162        static unsigned ports[] = { 0x280, 0x300, 0};
 163        unsigned *port;
 164        int err = 0;
 165
 166        if (!dev)
 167                return ERR_PTR(-ENOMEM);
 168
 169        if (unit >= 0) {
 170                sprintf(dev->name, "eth%d", unit);
 171                netdev_boot_setup_check(dev);
 172                io = dev->base_addr;
 173                irq = dev->irq;
 174                mem_start = dev->mem_start & 7;
 175        }
 176
 177        SET_MODULE_OWNER(dev);
 178
 179        if (io > 0x1ff) {       /* Check a single specified location. */
 180                err = el1_probe1(dev, io);
 181        } else if (io != 0) {
 182                err = -ENXIO;           /* Don't probe at all. */
 183        } else {
 184                for (port = ports; *port && el1_probe1(dev, *port); port++)
 185                        ;
 186                if (!*port)
 187                        err = -ENODEV;
 188        }
 189        if (err)
 190                goto out;
 191        err = register_netdev(dev);
 192        if (err)
 193                goto out1;
 194        return dev;
 195out1:
 196        release_region(dev->base_addr, EL1_IO_EXTENT);
 197out:
 198        free_netdev(dev);
 199        return ERR_PTR(err);
 200}

阅读(1588) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~