device与driver的关系

/**

 *    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.

 *

 *    The one interesting aspect is that we setup @drv->unloaded

 *    as a completion that gets complete when the driver reference

 *    count reaches 0.

 */

int driver_register(struct device_driver * drv)

{

       klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put);

       init_completion(&drv->unloaded);

       return bus_add_driver(drv);

}

int bus_add_driver(struct device_driver * drv)

{

       struct bus_type * bus = get_bus(drv->bus);

       int error = 0;

 

       if (bus) {

              pr_debug("bus %s: add driver %s/n", bus->name, drv->name);

              error = kobject_set_name(&drv->kobj, "%s", drv->name);

              if (error) {

                     put_bus(bus);

                     return error;

              }

              drv->kobj.kset = &bus->drivers;

              if ((error = kobject_register(&drv->kobj))) {

                     put_bus(bus);

                     return error;

              }

 

              driver_attach(drv);//这个函数用来匹配device device_driver机构

              klist_add_tail(&drv->knode_bus, &bus->klist_drivers);

              module_add_driver(drv->owner, drv);

 

              driver_add_attrs(bus, drv);

              driver_create_file(drv, &driver_attr_unbind);

              driver_create_file(drv, &driver_attr_bind);

       }

       return error;

}

/**

 *    driver_attach - try to bind driver to devices.

 *    @drv:     driver.

 *

 *    Walk the list of devices that the bus has on it and try to

 *    match the driver with each one.  If driver_probe_device()

 *    returns 0 and the @dev->driver is set, we've found a

 *    compatible pair.

 */

void driver_attach(struct device_driver * drv)

{

       bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

}

 

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.

        */

 

       down(&dev->sem);

       if (!dev->driver)

              driver_probe_device(drv, dev);

       up(&dev->sem);

 

 

       return 0;

}

/**

 *    driver_probe_device - attempt to bind device & driver.

 *    @drv:     driver.

 *    @dev:     device.

 *

 *    First, we call the bus's match function, if one present, which

 *    should compare the device IDs the driver supports with the

 *    device IDs of the device. Note we don't do this ourselves

 *    because we don't know the format of the ID structures, nor what

 *    is to be considered a match and what is not.

 *

 *

 *    This function returns 1 if a match is found, an error if one

 *    occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.

 *

 *    This function must be called with @dev->sem held.

 */

int driver_probe_device(struct device_driver * drv, struct device * dev)

{

       int ret = 0;

 

       if (drv->bus->match && !drv->bus->match(dev, drv))//由此可见匹配是有总线模型中定义的match函数决定的

              goto Done;

 

       pr_debug("%s: Matched Device %s with Driver %s/n",

               drv->bus->name, dev->bus_id, drv->name);

       dev->driver = drv;

       if (drv->probe) {

              ret = drv->probe(dev);//在此处 device_driver中的probe函数被调用所以一些初始化的东西可以放在这个函数中实现。

              if (ret) {

                     dev->driver = NULL;

                     goto ProbeFailed;

              }

       }

       device_bind_driver(dev);//将两个结构联系在一起

       ret = 1;

       pr_debug("%s: Bound Device %s to Driver %s/n",

               drv->bus->name, dev->bus_id, drv->name);

       goto Done;

 

 ProbeFailed:

       if (ret == -ENODEV || ret == -ENXIO) {

              /* Driver matched, but didn't support device

               * or device not found.

               * Not an error; keep going.

               */

              ret = 0;

       } else {

              /* driver matched but the probe failed */

              printk(KERN_WARNING

                     "%s: probe of %s failed with error %d/n",

                     drv->name, dev->bus_id, ret);

       }

 Done:

       return ret;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值