Chinaunix首页 | 论坛 | 博客
  • 博客访问: 84699
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 18
  • 用 户 组: 普通用户
  • 注册时间: 2013-11-07 23:50
文章分类
文章存档

2014年(13)

2013年(16)

我的朋友

分类: LINUX

2014-01-23 17:56:21

原文地址:内核驱动框架 作者:leonwang202

内核(linux-2.6.24)有一个大的框架来管理总线,外设及其驱动。
看外设驱动代码时,明白了这个框架,可以很方便的找到需要看的函数。

1.数据结构

这个框架涉及到3个比较重要的数据结构:
   struct bus_type         用来描述总线
   struct device           用来描述设备
   struct device_driver   用来描述设备驱动

有如下拓扑图


 内核中可以有很多的总线bus_type
 总线bus_type上可以有很多的设备device
 每个设备device都有它所对应的驱动device_driver

  1. struct bus_type { //…..省略一些成员
  2.     const char * name;
  3.     struct kset drivers;
  4.     struct kset devices;

  5.     int (*match)(struct device * dev, struct device_driver * drv);
  6.     int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
  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 (*suspend_late)(struct device * dev, pm_message_t state);
  12.     int (*resume_early)(struct device * dev);
  13.     int (*resume)(struct device * dev);
  14.     unsigned int drivers_autoprobe:1;
  15. };

  16. struct device { //…..省略一些成员
  17.     struct klist klist_children;
  18.     struct klist_node knode_parent; /* node in sibling list */
  19.     struct klist_node knode_driver;
  20.     struct klist_node knode_bus;
  21.     struct device *parent;
  22.     char bus_id[BUS_ID_SIZE];       /* position on parent bus */

  23.     struct bus_type * bus;          /* type of bus device is on */
  24.     struct device_driver *driver;   /* which driver has allocated this device */
  25.     void *driver_data;              /* data private to the driver */
  26.     void *platform_data;            /* Platform specific data, device core doesn't touch it */
  27. };

  28. struct device_driver { //…..省略一些成员
  29.     const char * name;
  30.     struct bus_type * bus;
  31.     int (*probe) (struct device * dev);
  32.     int (*remove) (struct device * dev);
  33.     void(*shutdown) (struct device * dev);
  34.     int (*suspend) (struct device * dev, pm_message_t state);
  35.     int (*resume) (struct device * dev);
  36. };



按照面向对象的思想,
bus_type虚基类,子类包括 platform_bus_type,mdio_bus_type,i2c_bus_type,pci_bus_type等
device是虚基类,子类包括 platform_device,  phy_device,   i2c_client, pci_device等
device_driver虚基类,子类有platform_driver,  phy_driver,i2c_driver, pci_driver等

2.API


框架有几个关键API:
bus_register(stuct bus_type* bus)         用来注册一条总线bus
device_register(struct device *dev)       把dev加到bus的设备列表中去

driver_register(stuct device_driver *drv)   
    1. 遍历bus上所有的dev,调用 drv->match(dev,drv) 对drv与dev进行比对
    2. 比对成功后调用 dev->bus->probe(dev) 或 drv->probe(dev)
    3. 把驱动drv加入到bus的驱动列表中去
    4. 绑定drv和dev

为了便于使用,内核针对不同总线,对上述API进行了包装,衍生出了另外一批API:
platform_driver_register
platform_device_register

phy_driver_register
mdiobus_register



下面讲将这3个API

  1. bus_register(struct bus_type *bus)
  2.     //没啥说的,此函数最重要一点就是 bus->drivers_autoprobe=1


  1. driver_register(struct device_driver *drv)
  2.     --》bus_add_driver(drv)
  3.     //若bus->drivers_autoprobe = 1
  4.         --》driver_attach(drv)
  5.         //遍历bus下所有dev,调用
  6.             --》__driver_attach(dev,drv)
  7.                 --》driver_probe_device(drv,dev)
  8.             //调用 bus_type.match(dev, drv),如果比对成功就执行
  9.                 --》really_probe(dev,drv)
  10.                     //调用 bus->probe(dev) 或 drv->probe(dev)

3.总线的注册

所有总线的注册几乎内核启动过程时完成的。

start_kernel()
  --》rest_init()
    --》kernel_init()
      --》do_basic_setup()
        --》do_initcalls()
          --》platform_bus_init()--》bus_register(&platform_bus)
          --》mdio_bus_init()    --》bus_register(&mdio_bus_type)
          --》i2c_init()         --》bus_register(&i2c_bus_type)

粉红色的都是全局变量

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