Linux驱动之设备模型(6)-驱动

1.  设备驱动,在Linux设备模型中,设备驱动用device_driver结构来表示

  1. struct device_driver {  
  2.          const char                  *name;       /*名字*/  
  3.          struct bus_type                 *bus;      /* 附属的总线 */  
  4.          struct module           *owner;  
  5.          const struct of_device_id         *of_match_table;  
  6.    
  7.          int (*probe) (struct device *dev);  /* 设备与驱动匹配时调用 */  
  8.          int (*remove) (struct device *dev); /* 设备移除时调用 */  
  9.    
  10.          void (*shutdown) (struct device *dev);  
  11.          int (*suspend) (struct device *dev,pm_message_t state);  
  12.          int (*resume) (struct device *dev);  
  13.          const struct attribute_group **groups;  /* 属性组 */  
  14.    
  15.          /*电源管理操作*/  
  16.          const struct dev_pm_ops *pm;  
  17.    
  18.          struct driver_private *p;  /* 私有数据:内嵌的kobject,设备链表,总线链表节点*/  
  19. };  

2. 声明和初始化驱动结构体

     驱动结构体一般被静态的声明,至少需要初始化name和bus成员,一般情况下,不会直接 使用device_driver结构体,而是使用一个封装了它的结构体。以下是eepro100的驱动结构体声明例子:

  1. /* 封装的新驱动结构体 */  
  2. struct pci_driver {  
  3.        const struct pci_device_id *id_table;  
  4.        struct device_driver       driver;  
  5. };  
  6. /* 声明驱动结构体 */  
  7. static struct pci_driver eepro100_driver = {  
  8.        .id_table       = eepro100_pci_tbl,  
  9.        .driver         = {  
  10.                 .name           = "eepro100",  
  11.                 .bus            = &pci_bus_type,  
  12.                 .probe          = eepro100_probe,  
  13.                 .remove         = eepro100_remove,  
  14.                 .suspend        = eepro100_suspend,  
  15.                 .resume         = eepro100_resume,  
  16.        },  
  17. };  


3. 注册和注销驱动

     注册驱动

     int driver_register(struct device_driver *drv);

     注销驱动

     void driver_unregister(struct device_driver *drv);

     注册驱动函数分析:

  1. int driver_register(struct device_driver *drv)  
  2. {  
  3.     int ret;  
  4.     struct device_driver *other;  
  5.   
  6.        /* 如果私有数据p指针为NULL,会产生oops */  
  7.     BUG_ON(!drv->bus->p);  
  8.   
  9.    /* 检查是否实现了probe,remove,shutdown  callback */  
  10.     if ((drv->bus->probe && drv->probe) ||  
  11.         (drv->bus->remove && drv->remove) ||  
  12.         (drv->bus->shutdown && drv->shutdown))  
  13.         printk(KERN_WARNING "Driver '%s' needs updating - please use "  
  14.             "bus_type methods\n", drv->name);  
  15.   
  16.    /* 查找总线上是否已经注册此驱动 */  
  17.     other = driver_find(drv->name, drv->bus);  
  18.     if (other) {  
  19.         put_driver(other);  
  20.         printk(KERN_ERR "Error: Driver '%s' is already registered, "  
  21.             "aborting...\n", drv->name);  
  22.         return -EBUSY;  
  23.     }  
  24.   
  25.     /* 向总线注册驱动 */  
  26.     ret = bus_add_driver(drv);  
  27.     if (ret)  
  28.         return ret;  
  29.     /* 创建属性文件 */  
  30.     ret = driver_add_groups(drv, drv->groups);  
  31.     if (ret)  
  32.         bus_remove_driver(drv);  
  33.     return ret;  
  34. }  
  35.   
  36. int bus_add_driver(struct device_driver *drv)  
  37. {  
  38.     struct bus_type *bus;  
  39.     struct driver_private *priv;  
  40.     int error = 0;  
  41.   
  42.   /* bus的引用计数加1 */  
  43.     bus = bus_get(drv->bus);  
  44.     if (!bus)  
  45.         return -EINVAL;  
  46.   
  47.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);  
  48.     if (!priv) {  
  49.         error = -ENOMEM;  
  50.         goto out_put_bus;  
  51.     }  
  52.     klist_init(&priv->klist_devices, NULL, NULL);  
  53.     priv->driver = drv;  
  54.     drv->p = priv;  
  55.     priv->kobj.kset = bus->p->drivers_kset;  
  56.     /* 初始化和添加kobject */  
  57.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,  
  58.                      "%s", drv->name);  
  59.     if (error)  
  60.         goto out_unregister;  
  61.   
  62.     /* 如果设置了自动probe,会调用driver_attach */  
  63.     if (drv->bus->p->drivers_autoprobe) {  
  64.         error = driver_attach(drv);  
  65.         if (error)  
  66.             goto out_unregister;  
  67.     }  
  68.     /* 将驱动添加到总线上的驱动链表 */  
  69.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);  
  70.     module_add_driver(drv->owner, drv);  
  71.   
  72.     /* 创建驱动属性文件 */  
  73.     error = driver_create_file(drv, &driver_attr_uevent);  
  74.     if (error) {  
  75.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",  
  76.             __func__, drv->name);  
  77.     }  
  78.     error = driver_add_attrs(bus, drv);  
  79.     if (error) {  
  80.         /* How the hell do we get out of this pickle? Give up */  
  81.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",  
  82.             __func__, drv->name);  
  83.     }  
  84.   
  85.   
  86.     if (!drv->suppress_bind_attrs) {  
  87.         error = add_bind_files(drv);  
  88.         if (error) {  
  89.             /* Ditto */  
  90.             printk(KERN_ERR "%s: add_bind_files(%s) failed\n",  
  91.                 __func__, drv->name);  
  92.         }  
  93.     }  
  94.   
  95.     /* 向用户空间发送KOBJ_ADD uevent */  
  96.     kobject_uevent(&priv->kobj, KOBJ_ADD);  
  97.     return 0;  
  98. }  

driver_attach()->bus_for_each_dev()遍历bus上的所有设备,并对每个device调用__driver_attach()来完成驱动和设备的绑定

  1. static int __driver_attach(struct device *dev, void *data)  
  2. {  
  3.     struct device_driver *drv = data;  
  4.   
  5.     /* 驱动和设备匹配 */  
  6.     if (!driver_match_device(drv, dev))  
  7.         return 0;  
  8.   
  9.     if (dev->parent) /* Needed for USB */  
  10.         device_lock(dev->parent);  
  11.     device_lock(dev);  
  12.     if (!dev->driver)  
  13.         /* 调用probe */  
  14.         driver_probe_device(drv, dev);  
  15.     device_unlock(dev);  
  16.     if (dev->parent)  
  17.         device_unlock(dev->parent);  
  18.   
  19.     return 0;  
  20. }  

当有驱动支持的设备时,调用__driver_attach函数完成相应的工作__driver_attach()->driver_probe_device()->driver_probe_device()->bus->probe()->drv->probe () 优先调用总线中定义的probe函数,如果bus中未定义probe,则再调用驱动中定义的probe。


4. 驱动属性,驱动属性由driver_attribute来描述

  1. struct driver_attribute {  
  2.          struct attribute attr;  
  3.          ssize_t (*show)(struct device_driver*driver, char *buf);  
  4.          ssize_t (*store)(struct device_driver*driver, const char *buf,  
  5.                              size_t count);  
  6. };  
  7. DRIVER_ATTR(_name,_mode, _show, _store)  

创建属性

intdriver_create_file(struct device_driver *driver,

                            const structdriver_attribute *attr);

删除属性

voiddriver_remove_file(struct device_driver *driver,

                                const struct driver_attribute *attr);

 

7.4  实例分析

  1. /* 
  2. * for learn driver 
  3. */  
  4. #include <linux/kernel.h>  
  5. #include <linux/module.h>  
  6. #include <linux/init.h>  
  7. #include <linux/device.h>  
  8. #include <linux/string.h>  
  9.    
  10. extern struct bus_type scbus_type;  
  11.    
  12. static char *Version = "revision 1.0,scdriver";  
  13.    
  14. static int sc_probe(struct device *dev)  
  15. {  
  16.          printk("driverfound device\n");  
  17.          return0;  
  18. }  
  19.    
  20. static int sc_remove(struct device *dev)  
  21. {  
  22.          printk("deviceremove\n");  
  23.          return0;  
  24. }  
  25.    
  26. struct device_driver scdriver = {  
  27.          .name       = "scdevice0",     /* 驱动名字,用来匹配支持的设备 */  
  28.          .bus = &scbus_type,     /* 依附的总线类型 */  
  29.          .probe      = sc_probe,      /* 设备和驱动匹配时调用 */  
  30.          .remove   = sc_remove,     /* 设备移除时调用 */  
  31. };  
  32.    
  33. /* 
  34. * export driver attribute 
  35. */  
  36. static ssize_t driver_show_version(structdevice_driver *driver, char *buf)  
  37. {  
  38.          returnsprintf(buf, "%s\n", Version);  
  39. }  
  40. static DRIVER_ATTR(version, S_IRUGO,driver_show_version, NULL);  
  41.    
  42. static int __init scdriver_init(void)  
  43. {  
  44.          intret;  
  45.   /* 注册驱动 */  
  46.          ret= driver_register(&scdriver);  
  47.          if(ret)  
  48.                    returnret;  
  49.          /*创建属性 */  
  50.          ret= driver_create_file(&scdriver, &driver_attr_version);  
  51.          if(ret)  
  52.                    gotoerr_create;  
  53.    
  54.          printk("drvierregistered\n");  
  55.          return0;  
  56.    
  57. err_create:  
  58.          driver_unregister(&scdriver);  
  59.          returnret;  
  60. }  
  61.    
  62. static void __exit scdriver_exit(void)  
  63. {  
  64.          driver_remove_file(&scdriver,&driver_attr_version);  
  65.          driver_unregister(&scdriver);  
  66. }  
  67.    
  68. module_init(scdriver_init);  
  69. module_exit(scdriver_exit);  
  70.    
  71. MODULE_LICENSE("Dual BSD/GPL");  
  72. MODULE_AUTHOR("CJOK<cjok.liao@gmail.com>");  

试验结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值