总线类型¶
定义¶
请参阅 struct bus_type
的 kerneldoc。
int bus_register(struct bus_type
* bus);
声明¶
内核中的每种总线类型(PCI、USB 等)都应声明此类型的静态对象。它们必须初始化 name 字段,并且可以选择初始化 match 回调。
struct bus_type pci_bus_type = {
.name = "pci",
.match = pci_bus_match,
};
该结构应在头文件中导出到驱动程序
extern struct bus_type
pci_bus_type;
注册¶
当总线驱动程序初始化时,它会调用 bus_register。这将初始化总线对象中的其余字段,并将其插入到全局总线类型列表中。一旦注册了总线对象,总线驱动程序就可以使用其中的字段。
回调¶
match(): 将驱动程序附加到设备¶
设备 ID 结构的格式和比较它们的语义本质上是总线特定的。驱动程序通常声明其支持的设备的设备 ID 数组,这些设备位于特定于总线的驱动程序结构中。
match 回调的目的是让总线有机会通过比较驱动程序支持的设备 ID 与特定设备的设备 ID 来确定特定驱动程序是否支持特定设备,而不会牺牲特定于总线的功能或类型安全。
当驱动程序在总线上注册时,会迭代总线的设备列表,并为每个未关联驱动程序的设备调用 match 回调。
设备和驱动程序列表¶
设备和驱动程序的列表旨在取代许多总线保留的本地列表。它们分别是 struct devices 和 struct device_drivers 的列表。总线驱动程序可以随意使用这些列表,但可能需要转换为特定于总线的类型。
LDM 核心提供了用于迭代每个列表的帮助函数
int bus_for_each_dev(struct bus_type * bus, struct device * start,
void * data,
int (*fn)(struct device *, void *));
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *));
这些助手会迭代相应的列表,并为列表中的每个设备或驱动程序调用回调。所有列表访问都通过获取总线的锁(当前为读取)来同步。在调用回调之前,列表中每个对象的引用计数都会递增;在获取下一个对象后,引用计数会递减。调用回调时不会持有锁。
sysfs¶
有一个名为 'bus' 的顶层目录。
每个总线在 bus 目录中都有一个目录,以及两个默认目录
/sys/bus/pci/
|-- devices
`-- drivers
在总线上注册的驱动程序在总线的 drivers 目录中获得一个目录
/sys/bus/pci/
|-- devices
`-- drivers
|-- Intel ICH
|-- Intel ICH Joystick
|-- agpgart
`-- e100
在总线上发现的每种类型的设备,都会在总线的 devices 目录中获得一个指向设备在物理层次结构中目录的符号链接
/sys/bus/pci/
|-- devices
| |-- 00:00.0 -> ../../../root/pci0/00:00.0
| |-- 00:01.0 -> ../../../root/pci0/00:01.0
| `-- 00:02.0 -> ../../../root/pci0/00:02.0
`-- drivers
导出属性¶
struct bus_attribute {
struct attribute attr;
ssize_t (*show)(const struct bus_type *, char * buf);
ssize_t (*store)(const struct bus_type *, const char * buf, size_t count);
};
总线驱动程序可以使用 BUS_ATTR_RW 宏导出属性,该宏的工作方式类似于设备的 DEVICE_ATTR_RW 宏。例如,像这样的定义
static BUS_ATTR_RW(debug);
等效于声明
static bus_attribute bus_attr_debug;
然后可以使用以下方法从总线的 sysfs 目录添加和删除属性
int bus_create_file(struct bus_type *, struct bus_attribute *);
void bus_remove_file(struct bus_type *, struct bus_attribute *);