译者:郭少悲
2009/12/01
原文:linux-2.6/Documentation/driver-model/bus.txt
总线类型
定义
~~~~
struct bus_type {
char * name;
struct subsystem subsys;
struct kset drivers;
struct kset devices;
struct bus_attribute * bus_attrs;
struct device_attribute * dev_attrs;
struct driver_attribute * drv_attrs;
int (*match)(struct device * dev, struct device_driver * drv);
int (*hotplug) (struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
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 device
和struct device_driver结构的链表。总线驱动可以自由的使用这些链表,但可能需要
转换为总线相关的数据类型。
Linux设备模型核心提供了迭代每个链表的帮助函数。
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
~~~~~~~~
在sysfs的顶层目录里,有个目录被命名为'bus'。
每个总线在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)(struct bus_type *, char * buf);
ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
};
总线驱动会通过BUS_ATTR宏导出属性,BUS_ATTR与DEVICE_ATTR类似。例如,如下定义:
static BUS_ATTR(debug,0644,show_debug,store_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 *);