免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1256 | 回复: 0
打印 上一主题 下一主题

linux网络学习笔记--网卡驱动(1) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-06-09 23:47 |只看该作者 |倒序浏览


一 驱动程序注册
       驱动程序注册,其实就是驱动程序的初始化,其中最重要的是建立各个数据结构的连接关系。如图所示:

       首先,系统在初始时枚举PCI设备时,已经根据PCI设备建立起了对应得pci_dev结构,并挂在相应的链表中。其中pci_dev结构中的dev指向一个device结构。注册的时候主要是为pci_dev结构找相应的driver结构。
       定义pci_driver结构
       static struct pci_driver pcnet32_driver = {
       .name = DRV_NAME,
       .probe = pcnet32_probe_pci,
       .remove = __devexit_p(pcnet32_remove_one),
       .id_table = pcnet32_pci_tbl,
}
在初始化函数种注册pci_driver。
pcnet32_init_module->pci_register_driver
根据pci_driver的数据初始化其中的device_driver结构:
drv->driver.name = drv->name;
       drv->driver.bus = &pci_bus_type;
       drv->driver.owner = owner;
       drv->driver.mod_name = mod_name;
       drv->driver.kobj.ktype = &pci_driver_kobj_type;
其中pci_bus_type结构是全局结构,所以pci设备都使用这个结构:
struct bus_type pci_bus_type = {
       .name             = "pci",
       .match           = pci_bus_match,
       .uevent           = pci_uevent,
       .probe            = pci_device_probe,
       .remove          = pci_device_remove,
       .suspend  = pci_device_suspend,
       .suspend_late  = pci_device_suspend_late,
       .resume_early = pci_device_resume_early,
       .resume          = pci_device_resume,
       .shutdown      = pci_device_shutdown,
       .dev_attrs       = pci_dev_attrs,
};
该结构组织起了所有pci设备,以后扫描pci设备都是根据这个结构。具体结构通过其kobject来组织。
pcnet32_init_module->pci_register_driver-> driver_register-> bus_add_driver-> driver_attach
扫描pci_driver.device_driver->bus上的每一个设备,对每个设备调用__driver_attach方法。其中在bus_for_each_dev方法中,根据pci_driver.device_driver->bus得到bus上所有的device结构。并把该结构传给__driver_attach,同时也传入需要匹配的pci_driver。
__driver_attach->driver_probe_device
对给定的一个设备device,用查找其对应得device_driver。
if (drv->bus->match && !drv->bus->match(dev, drv))
              goto done;
drv->bus->match实际上是pci_bus_type的pci_bus_match (struct device *dev, struct device_driver *drv)方法。方法中通过containof函数分别从device和device_driver得到pci_device和pci_driver。其中调用pci_match_id(drv->id_table, dev)来匹配pci_device和pci_driver中的pci_id。如果找到math方法返回1。如果match返回1,则执行really_probe.
__driver_attach->driver_probe_device->really_probe
传入由device_driver和device组成的结构,进行真正的probe。在扫描之前dev->driver = drv;(注,对于一个驱动支持多个设备,即一个驱动match多个设备,则dev->driver会指向最后一个参加match操作的。device结构和driver结构应该是n对1关系。)
使device中的device_driver指针指向device_driver结构。因为之前的match操作已经确定了这两个结构的对应关系。这下面是调用bus_type,或者device_driver中的probe来真正扫描设备。
if (dev->bus->probe) {
              ret = dev->bus->probe(dev);
              if (ret)
                     goto probe_failed;
       } else if (drv->probe) {
              ret = drv->probe(dev);
              if (ret)
                     goto probe_failed;
       }
注意,这儿执行的是pic_driver.device_driver->bus->probe方法(device_driver.probe没有赋值)。也就是pci_bus_type.probe即pci_device_probe(struct device * dev)方法。在该方法中,实际是通过传入的device结构,找到对应的pci_driver和pci_device结构。再调用pci_driver中的probe方法。也就是我们自己的probe方法。在该方法中进行一些初始化的设置,包括net_device的初始化。参考pcnet32_probe_pci。到此为止,网卡初始化完毕。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/15278/showart_318443.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP