Linux驱动模型 - 总线

 

Bus Types

 

Definition~~~~~~~~~~

See the kernel doc for the struct bus_type.(include/linux/device.h)

struct bus_type {

         const char                  *name;

         structbus_attribute        *bus_attrs;

         struct device_attribute   *dev_attrs;

         structdriver_attribute    *drv_attrs;

 

         int(*match)(struct device *dev, struct device_driver *drv);

         int(*uevent)(struct device *dev, struct kobj_uevent_env *env);

         int(*probe)(struct device *dev);

         int(*remove)(struct device *dev);

         void(*shutdown)(struct device *dev);

 

         int(*suspend)(struct device *dev, pm_message_t state);

         int(*suspend_late)(struct device *dev, pm_message_t state);

         int(*resume_early)(struct device *dev);

         int(*resume)(struct device *dev);

 

         struct pm_ext_ops*pm;

 

         structbus_type_private *p;

};

 

int bus_register(struct bus_type * bus);

 

 

Declaration~~~~~~~~~~~

内核中的每种总线(PCI, USB, 等等) 都应该要声明一个该类型的静态对象,并初始化其name域。对match()回调函数的初始化则是可选的.

struct bus_type pci_bus_type = {

       .name         = "pci",

       .match        = pci_bus_match,

};

 

这个数据结构应被包含在头文件中以使驱动程序可以访问:

extern struct bus_type pci_bus_type;

 

Registration~~~~~~~~~~~~

总线驱动在初始化时调用bus_register(),以初始化其它的域并将该结构对象插入到一个全局的总线类型列表中. 一旦这个总线对象注册完成,总线驱动就可以访问该结构中的所有域.

 

 

Callbacks~~~~~~~~~

match():  绑定设备和驱动

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

结构device ID的格式以及比较设备和驱动的方法依总线类型而不同. 驱动总是将其所支持的设备声明为一组device ID,这个组被嵌入到该总线的驱动的数据结构中.

 

Match()互调函数的目的是使总线有机会去对比特定设备的device ID和某个驱动所支持的device ID组,以确定该驱动是否支持这个特定设备, 而不必牺牲总线的功能性或类型安全性.

 

当驱动注册到总线上,该总线的设备列表会被遍历一次,针对每一个尚未绑定驱动的设备都会调用一次match().

 

 

Device and Driver Lists

~~~~~~~~~~~~~~~~~~~~~~~

设备/驱动列表用于取代之前由很多总线在本地维护的列表. 它们的类型分别为

struct devices 和structdevice_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, structdevice_driver * start,

                        void * data, int (*fn)(structdevice_driver *, void *));

 

这两个辅助函数分别遍历设备/驱动列表,并未列表中的每一个设备/驱动调用回调函数. 所有对列表的访问都由总线锁(表示正在读)进行同步. 列表中每一个对象的reference count 在调用回调函数前都会+1;而在操作下一个对象时会-1. 调用回调函数是不会保持总线锁.

 

 

sysfs

~~~~~~~~

/sysfs下的顶级子目录是'bus'.

 

每种总线在/sysfs/bus/下都有自己的子目录, 其中又有两个默认的目录:

 

         /sys/bus/pci/

         |-- devices

         `-- drivers

 

注册到总线的驱动在bus/drivers下都有自己的子目录:

         /sys/bus/pci/

         |-- devices

         `-- drivers

             |-- Intel ICH

             |-- Intel ICH Joystick

             |-- agpgart

             `-- e100

 

总线上探测到的每个设备则在bus/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

 

 

Exporting Attributes

~~~~~~~~~~~~~~~~~~~~

struct bus_attribute {

         structattribute        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 *, structbus_attribute *);

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值