嵌入式Linux设备驱动程序开发指南(原书第2版)
上QQ阅读APP看书,第一时间看更新

2.1 总线核心驱动

每个内核支持的总线都有一个对应的通用总线核心驱动。总线是处理器与设备之间的通道。为了统一设备模型,所有的设备都通过总线连接,哪怕它是一个内部的、抽象的“平台”总线。

总线核心驱动会分配一个bus_type数据结构,并将这个数据结构注册到内核的总线类型链表中。bus_type数据结构定义在include/linux/device.h中,用来表示一类总线(USB、PCI、I2C等)。把总线注册到系统中是通过调用bus_register()函数来完成的。bus_type数据结构定义如下:

061-01

下面的代码展示了一个初始化bus_type数据结构并注册总线的例子,该例子截取自平台核心驱动(drivers/base/platform.c):

061-02

bus_type数据结构有一个成员变量是一个指向subsys_private数据结构的指针,subsys_private数据结构定义在drivers/base/base.h中:

062-01

subsys_private数据结构中的klist_devices成员以列表的方式维护系统中的所有设备,这些设备关联到这一类型的总线上。总线控制器驱动扫描总线上的设备时(在系统初始化或者设备热插入的时候触发)会调用device_register()函数来更新该列表。

subsys_private数据结构中的klist_drivers成员则以列表的方式维护所有能够处理该总线上设备的驱动。当驱动初始化自己的时候通过调用driver_register()函数来更新该列表。

当新设备插入系统时,总线控制器驱动会侦测到该设备并调用device_register()函数。当总线控制器驱动注册一个设备时,device数据结构的parent成员变量被设置为总线控制器设备并以此来构造物理设备列表。总线上关联的驱动会被依次遍历,以查找是否有合适的驱动来支持该设备。bus_type数据结构提供的match函数被用于检查一个特定的驱动是否能够支持一个给定的设备。当一个能够支持该设备的驱动被找到时,device数据结构的driver成员变量就会被设置为相应的驱动。

当一个内核模块被插入内核并且相应的驱动调用了driver_register()时,与总线关联的设备的列表会被依次遍历,通过调用match函数来确定是否有设备能够被该驱动所支持。如果查找到这样一个匹配设备,该设备就会与该驱动关联,驱动的probe()函数也会被调用,这就是我们俗称的绑定

驱动什么时候会尝试绑定一个设备呢?

1. 驱动被注册的时候(如果设备已经存在)。

2. 设备被创建的时候(如果驱动已经被注册)。

总的来说,总线驱动负责在系统中注册一个总线,并且:

1. 允许总线控制器驱动的注册,该驱动的主要职责包括发现设备和配置资源。

2. 允许设备驱动的注册。

3. 负责设备与设备驱动的匹配。