Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3125102
  • 博文数量: 685
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5303
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-19 14:17
个人简介

文章分类

全部博文(685)

文章存档

2015年(116)

2014年(569)

分类: LINUX

2014-09-05 10:33:19

原文地址:http://blog.chinaunix.net/uid-24631445-id-3428100.html

1:device_driver结构体

  1. struct device_driver {
  2.     const char        *name;
  3.     struct bus_type        *bus;

  4.     struct module        *owner;
  5.     const char        *mod_name;    /* used for built-in modules */

  6.     bool suppress_bind_attrs;    /* disables bind/unbind via sysfs */

  7.     int (*probe) (struct device *dev);
  8.     int (*remove) (struct device *dev);
  9.     void (*shutdown) (struct device *dev);
  10.     int (*suspend) (struct device *dev, pm_message_t state);
  11.     int (*resume) (struct device *dev);
  12.     const struct attribute_group **groups;

  13.     const struct dev_pm_ops *pm;

  14.     struct driver_private *p;
  15. };

  16. struct driver_private {
  17.     struct kobject kobj;
  18.     struct klist klist_devices;
  19.     struct klist_node knode_bus;
  20.     struct module_kobject *mkobj;
  21.     struct device_driver *driver;
  22. };
  23.  
  24. struct driver_attribute {
  25. struct attribute attr;
  26. ssize_t (*show)(struct device_driver *driver, char *buf);
  27. ssize_t (*store)(struct device_driver *driver, const char *buf,
  28.  size_t count);
  29. };

  30. /* 一个attribute_group中包含一组attribute。用sysfs_create_group,可以为这一组属性创建文件,文件都处于表示该group的name目录中。*/
  31. struct attribute_group {
  32. const char *name;
  33. mode_t (*is_visible)(struct kobject *,
  34.       struct attribute *, int);
  35. struct attribute **attrs;
  36. };
从device_driver结构体可知,一个驱动中会有一组attribute_group,因此驱动的属性文件可能在多个子目录中。


2:创建属性文件的函数

  1. int driver_create_file(struct device_driver *drv,
  2.          struct driver_attribute *attr)
  3. {
  4.     int error;
  5.     if (drv)
  6.         error = sysfs_create_file(&drv->p->kobj, &attr->attr);
  7.     else
  8.         error = -EINVAL;
  9.     return error;
  10. }

  11. void driver_remove_file(struct device_driver *drv,
  12.             struct driver_attribute *attr)
  13. {
  14.     if (drv)
  15.         sysfs_remove_file(&drv->p->kobj, &attr->attr);
  16. }


3:驱动注册
正如总线有bus_register, 设备有device_register, 驱动有driver_register。都是重要函数呀。

  1. int driver_register(struct device_driver *drv)
  2. {
  3.     int ret;
  4.     struct device_driver *other;

  5.     BUG_ON(!drv->bus->p);

  6.     if ((drv->bus->probe && drv->probe) ||
  7.      (drv->bus->remove && drv->remove) ||
  8.      (drv->bus->shutdown && drv->shutdown))
  9.         printk(KERN_WARNING "Driver '%s' needs updating - please use "
  10.             "bus_type methods\n", drv->name);
  11.     /* 在drv->bus的driver_kset中查找名字为drv->name的驱动是否已经存在,
  12.        不存在就返回NULL */
  13.     other = driver_find(drv->name, drv->bus);
  14.     if (other) {
  15.         /* 若已存在则用put_driver增加驱动的kobj的引用计数 */
  16.         put_driver(other);
  17.         printk(KERN_ERR "Error: Driver '%s' is already registered, "
  18.             "aborting...\n", drv->name);
  19.         return -EBUSY;
  20.     }
  21.     /* 若没找到,则对该bus添加该驱动。(见下面) */
  22.     ret = bus_add_driver(drv);
  23.     if (ret)
  24.         return ret;
  25.     /* 为driver的所有属性group在sysfs中创建文件夹和文件 */
  26.     ret = driver_add_groups(drv, drv->groups);
  27.     if (ret)
  28.         bus_remove_driver(drv);
  29.     return ret;
  30. }
  31.  
  32.  
  33. int bus_add_driver(struct device_driver *drv)
  34. {
  35. struct bus_type *bus;
  36. struct driver_private *priv;
  37. int error = 0;
  38.         /* 获得驱动的总线,可见注册驱动前必须先设定好驱动的总线 */
  39. bus = bus_get(drv->bus);
  40. if (!bus)
  41. return -EINVAL;

  42. pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
  43.         /* 为驱动的私有数据分配空间,bus_type和device都存在私有数据 */
  44. priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  45. if (!priv) {
  46. error = -ENOMEM;
  47. goto out_put_bus;
  48. }
  49. klist_init(&priv->klist_devices, NULL, NULL);
  50. priv->driver = drv;
  51. drv->p = priv;
  52. priv->kobj.kset = bus->p->drivers_kset;  // 在调用bus_register创建的drivers目录
  53. /* kobject的初始化和注册,这样便在drivers目录下为该驱动创建了一个目录 */
  54.         error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
  55.      "%s", drv->name);
  56. if (error)
  57. goto out_unregister;

  58. if (drv->bus->p->drivers_autoprobe) {
  59.         /* 这里大致的意思是,将driver与device匹配起来,这个函数涉及到了bus, device, driver,
  60.            需要结合例子来讲,下次遇到个真实的driver后,再来说这个,目前还不太懂。
  61.            既然涉及了bus,device,driver, 也许从这里来理解这三者的关系会比较好 */
  62. error = driver_attach(drv);
  63. if (error)
  64. goto out_unregister;
  65. }
  66.         /* 看来关于klist和klist_node得另外写文章来说了,还有module结构体,一直不知道作用是什么 */
  67. klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
  68. module_add_driver(drv->owner, drv);

  69.         /* 为属性创建文件 */
  70. error = driver_create_file(drv, &driver_attr_uevent);
  71. if (error) {
  72. printk(KERN_ERR "%s: uevent attr (%s) failed\n",
  73. __func__, drv->name);
  74. }
  75.         /* 在bus结构中有一个drv_attrs指针,如果总线类型设定了该值,则为其执行的一组属性创建文件。
  76.            并不是一定会有,比如pci_bus_type中没有设定drv_attrs的值 */
  77. error = driver_add_attrs(bus, drv);
  78. if (error) {
  79. /* How the hell do we get out of this pickle? Give up */
  80. printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
  81. __func__, drv->name);
  82. }

  83. if (!drv->suppress_bind_attrs) {
  84.                 /* 为driver_attr_unbind属性和driver_attr_bind属性创建文件 */
  85. error = add_bind_files(drv);
  86. if (error) {
  87. /* Ditto */
  88. printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
  89. __func__, drv->name);
  90. }
  91. }

  92. kobject_uevent(&priv->kobj, KOBJ_ADD);
  93. return 0;

  94. out_unregister:
  95. kfree(drv->p);
  96. drv->p = NULL;
  97. kobject_put(&priv->kobj);
  98. out_put_bus:
  99. bus_put(bus);
  100. return error;
  101. }
在驱动注册的过程中,会在/sys/bus下相应的总线目录中的driver目录中为驱动创建目录。 同时查找该驱动匹配的设备。(这一点暂不太明白)

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