pci_register_driver

转自:https://blog.csdn.net/Buyi_Shizi/article/details/51262587

    在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也已经初始化完毕。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值