Chinaunix首页 | 论坛 | 博客

XX

  • 博客访问: 506824
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 562
  • 用 户 组: 普通用户
  • 注册时间: 2013-02-17 21:40
个人简介

XXX

文章分类

全部博文(281)

文章存档

2017年(1)

2015年(3)

2014年(117)

2013年(160)

我的朋友

分类: LINUX

2014-03-31 11:17:51

声明:这里是在linux-2.6.24基础上分析的。
刚开始接触linux设备驱动程序的时候,我充满着各种疑惑,比如:
(1)在linux-2.6.24/drivers/rtc目录下已经存在了RTC芯片DS1307的驱动程序(rtc-ds1307.c)了,又由于在项目里面要用到DS1307,于是乎,我的问题就来了:内核里面已经有了,那我还要自己写吗?但是初步看了一下DS1307的驱动,貌似不是自己想要要的,于是各种困惑与纠结,到底要不要自己另外写?
(2)platform平台设备驱动又是什么东西?LDD3上貌似没有说过啊?他是字符型设备还是其他什么的?
等等。反正,那个纠结啊!
至今,仍然存在各种困惑。希望有朋友帮我解除这个困惑。
好了,废话少说,来分析一下platform驱动吧!
首先,看hinand.c的源代码,这里只挑重点给予解释:


点击(此处)折叠或打开

  1. /*
  2.  * Main initialization routine
  3.  */
  4. static int hinand_module_init(void)
  5. {
  6.     int retval;

  7. //    printk("hinand_module_init\n");
  8.     retval = driver_register (&hinand_driver);
  9.     if (retval < 0)
  10.     {
  11.             return retval;
  12.     }

  13.     retval = platform_device_register (&hinand_pdev);
  14.     if (retval < 0)
  15.     {
  16.             driver_unregister(&hinand_driver);
  17.             return retval;
  18.     }

  19.     return retval;
  20. }

  21. static void __exit hinand_module_exit (void)
  22. {
  23.     driver_unregister (&hinand_driver);
  24.     platform_device_unregister (&hinand_pdev);
  25. }

  26. module_init(hinand_module_init);
  27. module_exit(hinand_module_exit);

这个驱动里面的入口函数是hinand_module_init,这个大家都可以看出来,看上去还蛮简单的,就调用了2个主要的函数:
retval = driver_register (&hinand_driver);
retval = platform_device_register (&hinand_pdev);
第一个函数里面主要牵扯了hinand_driver这个结构体,这个结构体定义如下:

点击(此处)折叠或打开

  1. static struct device_driver hinand_driver =
  2. {
  3.     .name = "hinand",
  4.     .bus = &platform_bus_type,
  5.     .probe = hinand_probe,
  6.     .remove = hinand_remove,
  7. };
来看看struct device_driver的定义(linux-2.6.24/include/linux/device.h):

点击(此处)折叠或打开

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

  4.     struct kobject        kobj;
  5.     struct klist        klist_devices;
  6.     struct klist_node    knode_bus;

  7.     struct module        * owner;
  8.     const char         * mod_name;    /* used for built-in modules */
  9.     struct module_kobject    * mkobj;

  10.     int    (*probe)    (struct device * dev);
  11.     int    (*remove)    (struct device * dev);
  12.     void    (*shutdown)    (struct device * dev);
  13.     int    (*suspend)    (struct device * dev, pm_message_t state);
  14.     int    (*resume)    (struct device * dev);
  15. };
结合上面两段代码,可以看出来hinand_driver只对其中的四个元素赋值了,即:
name -----> 驱动的名字,很重要。
bus  -----> 驱动所挂载的总线的名字,注意这里的挂载只是表示一个依附的意思,并不是实际中的连到这个总线上了,实际中也不存在一条总线叫什么platform。
probe ----> 驱动函数的真正的入口
remove ---> 驱动函数的出口
其余的元素有的是要在后面的程序里面进行初始化,不过这里不影响我们的讨论。
那driver_register (&hinand_driver);(linux-2.6.24/drivers/base/driver.c)这个函数到底做了哪些事情呢?下面就要看他的定义了:

点击(此处)折叠或打开

  1. /**
  2.  *    driver_register - register driver with bus
  3.  *    @drv:    driver to register
  4.  *
  5.  *    We pass off most of the work to the bus_add_driver() call,
  6.  *    since most of the things we have to do deal with the bus
  7.  *    structures.
  8.  */
  9. int driver_register(struct device_driver * drv)
  10. {
  11.     if ((drv->bus->probe && drv->probe) ||
  12.      (drv->bus->remove && drv->remove) ||
  13.      (drv->bus->shutdown && drv->shutdown)) {
  14.         printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
  15.     }
  16.     klist_init(&drv->klist_devices, NULL, NULL);
  17.     return bus_add_driver(drv);
  18. }
这个函数就是把驱动注册到对应的总线上面去,当然,这个总线必须是已经存在了的,那platform这条总线已经存在了吗?答案显然是存在了的。于是乎,又来疑问了,这条总线是什么时候开始就存在了?或者说是什么时候注册到了系统中了呢?话说那还是盘古开天辟地的时候,呵呵!开个玩笑。至于platform总线是什么时候注册到系统里就要看linux启动的过程代码了。
                         start_kernel(void);(linux-2.6.24/init/main.c)
                               |
                               |
                          rest_init();(linux-2.6.24/init/main.c)
                               |
                               |
                          kernel_init();(linux-2.6.24/init/main.c)
                               |
                               |
                          do_basic_setup();(linux-2.6.24/init/main.c)
                               |
                               |
                           driver_init();(linux-2.6.24/drivers/base/init.c)
                               |
                               |
                       platform_bus_init()(linux-2.6.24/drivers/base/platform.c);
这个过程就是注册platform总线的过程。
再看driver_register()这个函数里面,主要就是调用了bus_add_driver()(linux-2.6.24/drivers/base/bus.c),看他的定义:

点击(此处)折叠或打开

  1. int bus_add_driver(struct device_driver *drv)
  2. {
  3.     struct bus_type * bus = bus_get(drv->bus);
  4.     int error = 0;

  5.     if (!bus)
  6.         return -EINVAL;

  7.     pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
  8.     error = kobject_set_name(&drv->kobj, "%s", drv->name);
  9.     if (error)
  10.         goto out_put_bus;
  11.     drv->kobj.kset = &bus->drivers;
  12.     error = kobject_register(&drv->kobj);
  13.     if (error)
  14.         goto out_put_bus;

  15.     if (drv->bus->drivers_autoprobe) {
  16.         error = driver_attach(drv);
  17.         if (error)
  18.             goto out_unregister;
  19.     }
  20.     klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
  21.     module_add_driver(drv->owner, drv);

  22.     error = driver_create_file(drv, &driver_attr_uevent);
  23.     if (error) {
  24.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",
  25.             __FUNCTION__, drv->name);
  26.     }
  27.     error = driver_add_attrs(bus, drv);
  28.     if (error) {
  29.         /* How the hell do we get out of this pickle? Give up */
  30.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
  31.             __FUNCTION__, drv->name);
  32.     }
  33.     error = add_bind_files(drv);
  34.     if (error) {
  35.         /* Ditto */
  36.         printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
  37.             __FUNCTION__, drv->name);
  38.     }

  39.     return error;
  40. out_unregister:
  41.     kobject_unregister(&drv->kobj);
  42. out_put_bus:
  43.     bus_put(bus);
  44.     return error;
  45. }
挑重点看,这个函数主要就是这句话:
if (drv->bus->drivers_autoprobe) {
  error = driver_attach(drv);
  if (error)
   goto out_unregister;
 }
drv->bus->drivers_autoprobe如果为真就调用driver_attach()这个函数,这里我也不知道是不是为真,当然为真了,因为注册platform_bus_type总线的时候是这样的:

点击(此处)折叠或打开

  1. int __init platform_bus_init(void)
  2. {
  3.     int error;

  4.     error = device_register(&platform_bus);
  5.     if (error)
  6.         return error;
  7.     error = bus_register(&platform_bus_type);
  8.     if (error)
  9.         device_unregister(&platform_bus);
  10.     return error;
  11. }
上面代码中bus_register(&platform_bus_type);注册过程,但是再看platform_bus_type的定义:

点击(此处)折叠或打开

  1. struct bus_type platform_bus_type = {
  2.     .name        = "platform",
  3.     .dev_attrs    = platform_dev_attrs,
  4.     .match        = platform_match,
  5.     .uevent        = platform_uevent,
  6.     .suspend    = platform_suspend,
  7.     .suspend_late    = platform_suspend_late,
  8.     .resume_early    = platform_resume_early,
  9.     .resume        = platform_resume,
  10. };
再看struct bus_tpye的定义:

点击(此处)折叠或打开

  1. struct bus_type {
  2.     const char        * name;
  3.     struct module        * owner;

  4.     struct kset        subsys;
  5.     struct kset        drivers;
  6.     struct kset        devices;
  7.     struct klist        klist_devices;
  8.     struct klist        klist_drivers;

  9.     struct blocking_notifier_head bus_notifier;

  10.     struct bus_attribute    * bus_attrs;
  11.     struct device_attribute    * dev_attrs;
  12.     struct driver_attribute    * drv_attrs;

  13.     int        (*match)(struct device * dev, struct device_driver * drv);
  14.     int        (*uevent)(struct device *dev, struct kobj_uevent_env *env);
  15.     int        (*probe)(struct device * dev);
  16.     int        (*remove)(struct device * dev);
  17.     void        (*shutdown)(struct device * dev);

  18.     int (*suspend)(struct device * dev, pm_message_t state);
  19.     int (*suspend_late)(struct device * dev, pm_message_t state);
  20.     int (*resume_early)(struct device * dev);
  21.     int (*resume)(struct device * dev);

  22.     unsigned int drivers_autoprobe:1;
  23. };
最后一行unsigned int drivers_autoprobe:1;
再看bus_register()这个函数:

点击(此处)折叠或打开

  1. int bus_register(struct bus_type * bus)
  2. {
  3.     int retval;

  4.     BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);

  5.     retval = kobject_set_name(&bus->subsys.kobj, "%s", bus->name);
  6.     if (retval)
  7.         goto out;

  8.     bus->subsys.kobj.kset = &bus_subsys;

  9.     retval = subsystem_register(&bus->subsys);
  10.     if (retval)
  11.         goto out;

  12.     retval = bus_create_file(bus, &bus_attr_uevent);
  13.     if (retval)
  14.         goto bus_uevent_fail;

  15.     kobject_set_name(&bus->devices.kobj, "devices");
  16.     bus->devices.kobj.parent = &bus->subsys.kobj;
  17.     retval = kset_register(&bus->devices);
  18.     if (retval)
  19.         goto bus_devices_fail;

  20.     kobject_set_name(&bus->drivers.kobj, "drivers");
  21.     bus->drivers.kobj.parent = &bus->subsys.kobj;
  22.     bus->drivers.ktype = &driver_ktype;
  23.     retval = kset_register(&bus->drivers);
  24.     if (retval)
  25.         goto bus_drivers_fail;

  26.     klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
  27.     klist_init(&bus->klist_drivers, NULL, NULL);

  28.     bus->drivers_autoprobe = 1;
  29.     retval = add_probe_files(bus);
  30.     if (retval)
  31.         goto bus_probe_files_fail;

  32.     retval = bus_add_attrs(bus);
  33.     if (retval)
  34.         goto bus_attrs_fail;

  35.     pr_debug("bus type '%s' registered\n", bus->name);
  36.     return 0;

  37. bus_attrs_fail:
  38.     remove_probe_files(bus);
  39. bus_probe_files_fail:
  40.     kset_unregister(&bus->drivers);
  41. bus_drivers_fail:
  42.     kset_unregister(&bus->devices);
  43. bus_devices_fail:
  44.     bus_remove_file(bus, &bus_attr_uevent);
  45. bus_uevent_fail:
  46.     subsystem_unregister(&bus->subsys);
  47. out:
  48.     return retval;
  49. }
这么一句话 bus->drivers_autoprobe = 1;
对drivers_autoprobe初始化为1了,所以还是会调用driver_attach()这个函数的。
再看这个函数的定义:

点击(此处)折叠或打开

  1. /**
  2.  *    driver_attach - try to bind driver to devices.
  3.  *    @drv:    driver.
  4.  *
  5.  *    Walk the list of devices that the bus has on it and try to
  6.  *    match the driver with each one. If driver_probe_device()
  7.  *    returns 0 and the @dev->driver is set, we've found a
  8.  *    compatible pair.
  9.  */
  10. int driver_attach(struct device_driver * drv)
  11. {
  12.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
  13. }
看英文解释貌似是说将这条总线上的所有设备和这个驱动配对,当然有一定的配对条件,不能不管三七二十一胡乱配对,这是不行的。这里主要调用了bus_for_each_dev这个函数还有__driver_attach这个函数,先看bus_for_each_dev:

点击(此处)折叠或打开

  1. /**
  2.  *    bus_for_each_dev - device iterator.
  3.  *    @bus:    bus type.
  4.  *    @start:    device to start iterating from.
  5.  *    @data:    data for the callback.
  6.  *    @fn:    function to be called for each device.
  7.  *
  8.  *    Iterate over @bus's list of devices, and call @fn for each,
  9.  *    passing it @data. If @start is not NULL, we use that device to
  10.  *    begin iterating from.
  11.  *
  12.  *    We check the return of @fn each time. If it returns anything
  13.  *    other than 0, we break out and return that value.
  14.  *
  15.  *    NOTE: The device that returns a non-zero value is not retained
  16.  *    in any way, nor is its refcount incremented. If the caller needs
  17.  *    to retain this data, it should do, and increment the reference
  18.  *    count in the supplied callback.
  19.  */

  20. int bus_for_each_dev(struct bus_type * bus, struct device * start,
  21.          void * data, int (*fn)(struct device *, void *))
  22. {
  23.     struct klist_iter i;
  24.     struct device * dev;
  25.     int error = 0;

  26.     if (!bus)
  27.         return -EINVAL;

  28.     klist_iter_init_node(&bus->klist_devices, &i,
  29.              (start ? &start->knode_bus : NULL));
  30.     while ((dev = next_device(&i)) && !error)
  31.         error = fn(dev, data);
  32.     klist_iter_exit(&i);
  33.     return error;
  34. }
最主要的还是其中的fn(dev,data);其实从上面可以看出来这个就是__driver_attach函数,再看这个函数的定义:

点击(此处)折叠或打开

  1. static int __driver_attach(struct device * dev, void * data)
  2. {
  3.     struct device_driver * drv = data;

  4.     /*
  5.      * Lock device and try to bind to it. We drop the error
  6.      * here and always return 0, because we need to keep trying
  7.      * to bind to devices and some drivers will return an error
  8.      * simply if it didn't support the device.
  9.      *
  10.      * driver_probe_device() will spit a warning if there
  11.      * is an error.
  12.      */

  13.     if (dev->parent)    /* Needed for USB */
  14.         down(&dev->parent->sem);
  15.     down(&dev->sem);
  16.     if (!dev->driver)
  17.         driver_probe_device(drv, dev);
  18.     up(&dev->sem);
  19.     if (dev->parent)
  20.         up(&dev->parent->sem);

  21.     return 0;
  22. }
主要就是调用driver_probe_device(drv, dev);那么再看这个函数的定义,怎么写着写着觉得自己好烦啊!

点击(此处)折叠或打开

  1. /**
  2.  * driver_probe_device - attempt to bind device & driver together
  3.  * @drv: driver to bind a device to
  4.  * @dev: device to try to bind to the driver
  5.  *
  6.  * First, we call the bus's match function, if one present, which should
  7.  * compare the device IDs the driver supports with the device IDs of the
  8.  * device. Note we don't do this ourselves because we don't know the
  9.  * format of the ID structures, nor what is to be considered a match and
  10.  * what is not.
  11.  *
  12.  * This function returns 1 if a match is found, -ENODEV if the device is
  13.  * not registered, and 0 otherwise.
  14.  *
  15.  * This function must be called with @dev->sem held. When called for a
  16.  * USB interface, @dev->parent->sem must be held as well.
  17.  */
  18. int driver_probe_device(struct device_driver * drv, struct device * dev)
  19. {
  20.     int ret = 0;

  21.     if (!device_is_registered(dev))
  22.         return -ENODEV;
  23.     if (drv->bus->match && !drv->bus->match(dev, drv))
  24.         goto done;

  25.     pr_debug("%s: Matched Device %s with Driver %s\n",
  26.          drv->bus->name, dev->bus_id, drv->name);

  27.     ret = really_probe(dev, drv);

  28. done:
  29.     return ret;
  30. }
主要就是really_probe()这个函数,注意上面
if (drv->bus->match && !drv->bus->match(dev, drv))
  goto done;
这句话,就是调用platform_bus_type里面的match,也就是platform_match,看这个match到底干嘛了:

点击(此处)折叠或打开

  1. /**
  2.  *    platform_match - bind platform device to platform driver.
  3.  *    @dev:    device.
  4.  *    @drv:    driver.
  5.  *
  6.  *    Platform device IDs are assumed to be encoded like this:
  7.  *    "", where <name> is a short description of the
  8.  *    type of device, like "pci" or "floppy", and <instance> is the
  9.  *    enumerated instance of the device, like '0' or '42'.
  10.  *    Driver IDs are simply "".
  11.  *    So, extract the <name> from the platform_device structure,
  12.  *    and compare it against the name of the driver. Return whether
  13.  *    they match or not.
  14.  */

  15. static int platform_match(struct device * dev, struct device_driver * drv)
  16. {
  17.     struct platform_device *pdev = container_of(dev, struct platform_device, dev);

  18.     return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
  19. }
也就是匹配总线上的驱动和设备的名字是否相同,如果相同匹配成功。这就验证了上面提到的,不能乱匹配,是有原则的,这里的原则就是看名字是否相同。
再看really_probe()这个函数的定义,我靠,突然发现自己用了n多个“再看”了。妈的,语文太差,不知道还有什么词可以替换一下。

点击(此处)折叠或打开

  1. static int really_probe(struct device *dev, struct device_driver *drv)
  2. {
  3.     int ret = 0;

  4.     atomic_inc(&probe_count);
  5.     pr_debug("%s: Probing driver %s with device %s\n",
  6.          drv->bus->name, drv->name, dev->bus_id);
  7.     WARN_ON(!list_empty(&dev->devres_head));

  8.     dev->driver = drv;
  9.     if (driver_sysfs_add(dev)) {
  10.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
  11.             __FUNCTION__, dev->bus_id);
  12.         goto probe_failed;
  13.     }

  14.     if (dev->bus->probe) {
  15.         ret = dev->bus->probe(dev);
  16.         if (ret)
  17.             goto probe_failed;
  18.     } else if (drv->probe) {
  19.         ret = drv->probe(dev);
  20.         if (ret)
  21.             goto probe_failed;
  22.     }

  23.     driver_bound(dev);
  24.     ret = 1;
  25.     pr_debug("%s: Bound Device %s to Driver %s\n",
  26.          drv->bus->name, dev->bus_id, drv->name);
  27.     goto done;

  28. probe_failed:
  29.     devres_release_all(dev);
  30.     driver_sysfs_remove(dev);
  31.     dev->driver = NULL;

  32.     if (ret != -ENODEV && ret != -ENXIO) {
  33.         /* driver matched but the probe failed */
  34.         printk(KERN_WARNING
  35.          "%s: probe of %s failed with error %d\n",
  36.          drv->name, dev->bus_id, ret);
  37.     }
  38.     /*
  39.      * Ignore errors returned by ->probe so that the next driver can try
  40.      * its luck.
  41.      */
  42.     ret = 0;
  43. done:
  44.     atomic_dec(&probe_count);
  45.     wake_up(&probe_waitqueue);
  46.     return ret;
  47. }
主要还是看这几句话:
if (dev->bus->probe) {
  ret = dev->bus->probe(dev);
  if (ret)
   goto probe_failed;
 } else if (drv->probe) {
  ret = drv->probe(dev);
  if (ret)
   goto probe_failed;
 }
根据上面的分析,platform_bus_type总线里面的probe函数是空的,所以dev->bus->probe为假,所以执行
drv->probe(dev);
这个probe函数你知道是什么吗?正是hinand_probe,就是hinand_driver里面的probe啊!我操,现在才看出来,也明白了那句“驱动的真正入口是probe函数”这句不知道是哪个家伙说的话,于是乎。。。接下来就没什么好分析的了,说是分析其实也是照搬源代码而已。
至于platform_device_register (&hinand_pdev);这句话的分析过程和上面差不多,感兴趣的可以自己分析一下,这里就不说了。。。最后附上一张图:

结束了。。。。。。


                  

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