Chinaunix首页 | 论坛 | 博客
  • 博客访问: 313615
  • 博文数量: 159
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 182
  • 用 户 组: 普通用户
  • 注册时间: 2013-11-02 10:42
文章分类

全部博文(159)

文章存档

2015年(18)

2014年(132)

2013年(9)

分类: LINUX

2014-05-28 18:16:03

原文地址:关于device 与device_driver 作者:bensonliao


/**

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

}

/*************************************************/

/**

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

}

 

总线类型注册其实也差不多啦?2410为例内核的代码如下:

struct bus_type platform_bus_type = {

       .name             = "platform",

       .match           = platform_match,//这个函数将决定你的device device_driver的匹配方式2410 只是strcmp一下 name

       .suspend  = platform_suspend,

       .resume          = platform_resume,

};

 

struct device platform_bus = {

       .bus_id           = "platform",

};

 

int __init platform_bus_init(void)

{

       device_register(&platform_bus);

       return bus_register(&platform_bus_type);

}

 

上面是设备模型的注册要完成用户空间的系统还要调用各种设备的自己的注册过程。

比如 字符设备。

内核在调用 字符设备驱动时(如 open 通过设备节点的主设备号来查找到对应的驱动程序所以你还是要调用 cdev_add 把你的字符设备注册到系统中。这个可以参考http://blog.chinaunix.net/u2/71164/showart_1887233.html

阅读(340) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~