- 论坛徽章:
- 0
|
![]()
一 驱动程序注册
驱动程序注册,其实就是驱动程序的初始化,其中最重要的是建立各个数据结构的连接关系。如图所示:
首先,系统在初始时枚举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 |
|