【翻译】bus
原文:linux-2.6.34.1\Documentation\driver-model\bus.txt
translated by:leonardo1019
2010年7月23日
总线类型
定义
~~~~
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数组,用以说明它支持的设备。设备ID数组的结构体存在于特定的总线驱动中。
match回调函数的作用是让总线能够通过比较驱动支持的设备ID和设备自带的ID信息来决定该驱动是否支持该设备。这样就不用牺牲设备功能或类型安全。
当驱动程序注册到总线后,总线的设备链表就查询一遍,如果有匹配设备没有驱动的灰,相应的回调函数会被调用。
设备和驱动链表
~~~~~~~~~~~~~~
设备和驱动的链表用来替代许多总线保有的本地链表。他们是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 *));
这些函数分别遍历列表,然后为列表中的设备或驱动程序调用回调函数。对列表的所有访问,都要通缩获取总线lock来同步访问。当回调函数被调用时,列表中的对象的引用计数要增加;并在下一个对象被获得时引用计数减少。当调用回调函数时不占有lock。
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 -> http://www.cnblogs.com/../root/pci0/00:00.0
| |-- 00:01.0 -> http://www.cnblogs.com/../root/pci0/00:01.0
| `-- 00:02.0 -> http://www.cnblogs.com/../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);
};
类似于设备的DEVICE_ATTR宏,总线驱动可以使用BUS_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 *);