总线类型 【ChatGPT】

发布时间 2023-12-10 13:00:35作者: 摩斯电码

总线类型

定义

请参阅结构体bus_type的内核文档。

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”的顶级目录。

每个总线在总线目录中都有一个目录,以及两个默认目录:

/sys/bus/pci/
|-- devices
`-- drivers

在总线注册的驱动程序在总线的驱动程序目录中获得一个目录:

/sys/bus/pci/
|-- devices
`-- drivers
    |-- Intel ICH
    |-- Intel ICH Joystick
    |-- agpgart
    `-- e100

在该类型总线上发现的每个设备都会在总线的设备目录中得到一个符号链接,指向物理层次结构中设备的目录:

/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 *);