pci_register_driver

来源:互联网 发布:电玩战魂赫卡里姆淘宝 编辑:程序博客网 时间:2024/06/03 13:21

    在bus总线对应的数据结构bus_type中,有两份重要的结构体,struct kset drivers和struct kset devices。在写驱动程序的时候,要想驱动程序能工作,首先就要把驱动程序对应的driver程序放进struct kset driver结构体中,然后把设备的信息放入struct kset device中。

    而pci_register_driver()就是把某个设备下的driver程序放入struct kset drivers结构体中,而这个过程又分成如下子过程:

    1,首先会调用int _pci_register_driver()函数,在这个函数里面,首先会把pci_driver存储的信息复制到device_driver中,因为内核最终要注册的是一个device的driver信息,而不单单指pci设备的driver信息。在复制完成之后,内核会调用driver_register()函数注册device_driver的信息,代码如下:

    linux/drivers/pci/pci_driver.c

/** * __pci_register_driver - register a new pci driver * @drv: the driver structure to register * @owner: owner module of drv * @mod_name: module name string *  * Adds the driver structure to the list of registered drivers. * Returns a negative value on error, otherwise 0.  * If no error occurred, the driver remains registered even if  * no device was claimed during registration. */int __pci_register_driver(struct pci_driver *drv, struct module *owner,  const char *mod_name){int error;/* initialize common driver fields */drv->driver.name = drv->name; /* struct driver is in /include/linux/device.h */drv->driver.bus = &pci_bus_type;drv->driver.owner = owner;drv->driver.mod_name = mod_name;spin_lock_init(&drv->dynids.lock);INIT_LIST_HEAD(&drv->dynids.list);/* register with core */error = driver_register(&drv->driver); /* driver/base/driver.c */
    2,driver_register()函数,driver_register首先会检查struct kset drivers链表中有没有对应名称的dirver: driver_find(drv->name, drv->bus); 如果已经有了,则重新把对应的driver加载到struct kset drivers中,如果没有,则会执行bus_add_drivers函数,把当前的驱动加载到struct kset drivers中,对应程序如下:

    /linux/drivers/base/drivers.c

/** * driver_register - register driver with bus * @drv: driver to register * * We pass off most of the work to the bus_add_driver() call, * since most of the things we have to do deal with the bus * structures. */int driver_register(struct device_driver *drv){int ret;struct device_driver *other;BUG_ON(!drv->bus->p);if ((drv->bus->probe && drv->probe) ||    (drv->bus->remove && drv->remove) ||    (drv->bus->shutdown && drv->shutdown))printk(KERN_WARNING "Driver '%s' needs updating - please use ""bus_type methods\n", drv->name);other = driver_find(drv->name, drv->bus);if (other) {put_driver(other);printk(KERN_ERR "Error: Driver '%s' is already registered, ""aborting...\n", drv->name);return -EBUSY;}ret = bus_add_driver(drv); /* driver/base/bus.c */
    4,driver_add_driver函数,这个函数中重要的一个操作就是driver_attach操作,在driver_attach函数中会调用dirver_match_deivce函数来判断总线上是否有设备与当前driver相匹配,实现的方式应该就是比较vendor_id和device_id。如果当前bus中有设备和当前driver相匹配,那么就会执行driver_pobe_device函数,对当前deivce进行初始化,这个probe函数就是最终指向的驱动程序中编写的probe函数,程序如下:
static int __driver_attach(struct device *dev, void *data){struct device_driver *drv = data;/* * Lock device and try to bind to it. We drop the error * here and always return 0, because we need to keep trying * to bind to devices and some drivers will return an error * simply if it didn't support the device. * * driver_probe_device() will spit a warning if there * is an error. */if (!driver_match_device(drv, dev))return 0;if (dev->parent)/* Needed for USB */down(&dev->parent->sem);down(&dev->sem);if (!dev->driver)driver_probe_device(drv, dev);up(&dev->sem);if (dev->parent)up(&dev->parent->sem);return 0;}
    至此,driver和deivce就绑定完毕,而且device也已经初始化完毕。

0 0
原创粉丝点击