Linux内核设备模型(5)

译者:郭少悲
2009/12/02

原文:linux/Documentation/driver-model/device.txt

基本的设备数据结构
~~~~~~~~~~~~~~~~~~

struct device {
        struct list_head g_list;
        struct list_head node;
        struct list_head bus_list;
        struct list_head driver_list;
        struct list_head intf_list;
        struct list_head children;
        struct device   * parent;

        char    name[DEVICE_NAME_SIZE];
        char    bus_id[BUS_ID_SIZE];

        spinlock_t      lock;
        atomic_t        refcount;

        struct bus_type * bus;
        struct driver_dir_entry dir;

    u32        class_num;

        struct device_driver *driver;
        void            *driver_data;
        void            *platform_data;

        u32             current_state;
        unsigned char *saved_state;

        void    (*release)(struct device * dev);
};


~~
g_list:    全局设备链表中的节点。

node: 设备的父亲的孩子链表中的节点(父子关系是树结构中的常用关系)。

bus_list: 设备所属的总线的设备链表中的节点。

driver_list: 设备所关联的驱动的设备链表中的节点。

intf_list: intf_data结构的链表。该结构分配给设备支持的每个接口。

children: 孩子设备链表。

parent:        *** FIXME ***

name: 设备的文本描述。
      例子: " 3Com Corporation 3c905 100BaseTX [Boomerang]"

bus_id:    设备所处的总线位置的文本描述。这个域对于每一个属于该总线的设备而言应当是
一个唯一的名字。
      例如:PCI bus_ids有下己部分构成:
      <bus number>:<slot number>.<function number>
      这个名字对于PCI上的设备来说是唯一标识的。

lock: 设备锁。

refcount: 设备的引用计数。

bus: 指向设备所属的总线类型的指针。

dir: 设备的sysfs目录。

class_num: 设备的class-enumerated值。

driver: 指向控制设备的struct device_driver指针。

driver_data: 驱动相关的数据。

platform_data: 针对设备的平台数据。
    示例:对于各种嵌入式和SOC上的设备,Linux常常使用platform_data来表示板级相关的数据
    结构,以此来描述设备及其连接。这包括了适用的端口号,芯片管脚值(GPIO管脚用途)等等。
    这种方式缩小了BSPs尺寸,减少了驱动中板级相关的#ifdefs语句。



current_state: 当前设备的电源状态。

saved_state: 指向设备的保存状态的指针。这个域被控制设备的驱动来使用。

release: 所有引用结束后的释放设备的回调函数。它应当由设备的分配器来设置(例如,
由探测设备的总线驱动来设置)。


编程接口
~~~~~
探测设备的总线驱动使用下面的函数接口来注册设备到核心:

int device_register(struct device * dev);

总线应当初始化下面的域:

    - parent
    - name
    - bus_id
    - bus

当一个设备的引用计数为0时,设备会从核心中被一删除。引用计数的增减应当
使用下面的函数接口:

struct device * get_device(struct device * dev);
void put_device(struct device * dev);

get_device()将会返回一个指向struct device的指针,如果引用计数不为0。

一个驱动访问设备结构中的锁,使用下面接口函数:

void lock_device(struct device * dev);
void unlock_device(struct device * dev);


属性
~~~~
struct device_attribute {
    struct attribute    attr;
    ssize_t (*show)(struct device *dev, struct device_attribute *attr,
            char *buf);
    ssize_t (*store)(struct device *dev, struct device_attribute *attr,
             const char *buf, size_t count);
};

驱动可以导出设备的属性,通过使用一个简单的procfs-like接口。

请阅读Documentation/filesystems/sysfs.tx来获取更多的sysfs的信息。

通过宏DEVICE_ATTR来声明属性:

#define DEVICE_ATTR(name,mode,show,store)

例如:

DEVICE_ATTR(power,0644,show_power,store_power);

它声明了一个结构为device_attribute的'dev_attr_power'变量。可以使用
下面接口函数来添加和删除这个属性变量。

int device_create_file(struct device *device, struct device_attribute * entry);
void device_remove_file(struct device * dev, struct device_attribute * attr);

例如:

device_create_file(dev,&dev_attr_power);
device_remove_file(dev,&dev_attr_power);

这个文件名为'power',文件访问属性为0644(-rw-r--r--)。

警告信息:尽管内核允许在一个设备的任何时间上调用device_create_file()和
device_remove_file()函数,用户空间对属性的创建还是有严格的预期。当一个新设备
被注册到内核时,一个uevent事件产生通知用户空间(udev)一个新设备可用。当设备新
属性在设备注册后添加,用户空间没有获得事件通知,就无法得知新的属性。

设备驱动在驱动探测时间内需要为一个设备添加额外的属性,这是很重要的一个需求。
如果设备驱动仅仅简单的调用device_create_file(),用户空间得不到任何关于
新属性的通知。因此,应当在module_init()函数里使用class_create()和
class->dev_attrs建立一个所需属性的链表,然后在.probe()钩子函数里使用device_create()
来创建一个新的设备,作为被探测设备的孩子。这个新设备将产生一个新的uevent,
将新的属性通知给用户空间。

例如,一个驱动想添加如下的属性:
struct device_attribute mydriver_attribs[] = {
    __ATTR(port_count, 0444, port_count_show),
    __ATTR(serial_number, 0444, serial_number_show),
    NULL
};

在module_init()函数里应当:
    mydriver_class = class_create(THIS_MODULE, "my_attrs");
    mydriver_class.dev_attr = mydriver_attribs;

假定'dev'是传递给probe钩子函数的struct device结构变量,驱动的probe函数应当作如下
的事情:
    create_device(&mydriver_class, dev, chrdev, &private_data, "my_name");

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值