前言
在linux设备驱动模型中,总线可以看作是linux设备模型的核心,系统中的其他设备以及驱动都是以总线为核心围绕。不过驱动程序员在系统中创建一条总线的机会并不多。驱动模型中的总线可以是真是存在的物理总线(USB总线,I2C总线,PCI总线),也可以是为了驱动模型架构设计出的虚拟总线(Platform总线)。为此linux设备驱动模型都将围绕"总线--设备--驱动"来展开,因为符合linux设备驱动模型的设备与驱动都是必须挂载在一个总线上的,无论是实际存在的或者虚拟的。
数据结构
在详细说明bus开始的时候,先需要说明其数据结构,因为一个好的数据结构,就可以很大程度上了解其功能,内核中使用bus_type代表一个总线。
struct bus_type {
const char *name;
const char *dev_name;
struct device *dev_root;
struct device_attribute *dev_attrs; /* use dev_groups instead */
const struct attribute_group **bus_groups;
const struct attribute_group **dev_groups;
const struct attribute_group **drv_groups;
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*online)(struct device *dev);
int (*offline)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
const struct dev_pm_ops *pm;
const struct iommu_ops *iommu_ops;
struct subsys_private *p;
struct lock_class_key lock_key;
};
.name: 总线的名称,比如i2c, spi
.dev_name: 通常用户枚举设备的名称,比如常见的i2c-0, i2c-1....
.dev_root: 该bus默认的父设备。
.dev_attrs: 此bus设备上默认的属性。
.bus_groups, dev_groups, drv_groups: 分别是总线, 设备,驱动的属性。
.match: 当一个设备或者驱动添加到此总线上的时候,bus就会调用match对设备和驱动一一匹配的。
.uevent: 当该bus下的任何设备,驱动发生增加,删除的操作时,就会调用到uevnet函数。
.probe,remove: 当一个driver添加到系统的时候,是先会调用bus的probe的,如果bus的probe都没有初始化,则bus下的任何驱动或者设备都无法使用。但是不是所有的bus都会实现probe函数的,虚拟的bus是不存在初始化的。
.supend,resume: bus电源管理回调函数。
.pm: 一组电源管理的回调函数。
p: 一个用来管理总线上设备与驱动的数据结构。
struc