总线类型¶
定义¶
请参阅 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 数组,这些设备 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”的顶级目录。
每个总线在总线目录中都有一个目录,以及两个默认目录
/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 *);