【翻译】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 *);

posted @ 2010-07-24 21:43  leonardo1019  阅读(315)  评论(0)    收藏  举报