www.ourkernel.com 我们的内核
sysfs
当一个设备注册之后,文件目录就可以在它的总线目录上建立。在这个
目录里,设备能为用户空间提供一个接口,这是为了在全局的基础上控制设备 在设备上切换调试输出
未来这个目录的特征将是具有设备特征的目录.它将包含支持指向设备目录的连接。
回收
int (*probe) (struct device * dev);
在任务内容里probe()函数将被调用.伴随着总线的rwsem被锁和设备驱动找到设备.
设备驱动程序在probe()和其它的程序中一般用container_of() 函数去把dev转换为一个特定的总线类型.这种类型经常设备来存储数据,像 pci_dev.resource[] or platform_device.resources经常被添加进dev->platform_data去初始化设备.
这回收特定设备的方法去绑定一个设备到已经给出的设备上。并且包含了验证设备是存在的,它的版本能被识别,它的数据结构能被创建和初始化,任何的硬件都能被初始化。设备驱动经常提供一个指针,指向dev_set_drvdata()状态。当设备已经成功的绑定到那个设备上时,probe()函数返回0,设备模块代码将完成它的部分设备向那块设备.
一个设备的probe()也可能返回一个消极的错误代码。它能显示设备不能绑定到那块设备上。在这种情况下它应该已经释放已经分配的所有资源。
int (*remove)
(struct device * dev);
remove函数在解除一个设备的驱动时被调用。当设备物理的从系统中移走时,当设备模块被撤消时,或者一些其它的情况,在重启的过程中它将被调用.
它取决于设备驱动去确定设备存在与否.它应该释放任何为设备分配的资源。也就是任何在设备driver_data中的区域
如果设备依然存在,系统应该quiesce那个设备,并把它置为一个支持的低电压的状态.
int (*suspend)
(struct device * dev, pm_message_t state);
26
www.ourkernel.com 我们的内核
suspend把设备置为低电压的状态。 int (*resume) (struct device * dev);
resume会把设备从低电压状态中恢复
属性
struct driver_attribute {
struct attribute attr;
ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off); ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off); };
设备驱动能通过它们的文件目录输出属性。
驱动能一个DRIVER_ATTR宏声明属性。这个宏和DEVICE_ATTR宏的作用一样.
例子:
DRIVER_ATTR(debug,0644,show_debug,store_debug);
这是一个声明的等价特.
struct driver_attribute driver_attr_debug;
这能被用来从设备目录里增加和移除属性
int driver_create_file(struct device_driver *, struct driver_attribute *); void driver_remove_file(struct device_driver *, struct driver_attribute *);
Interface
原文作者:
翻 译者:陈勇彪 524396959@qq.com 校 订者:
版本状态:还未完成
27
www.ourkernel.com 我们的内核
======================================
设备接口 介绍
设备接口是指直接与用户空间相连的设备类逻辑接口,比如说设备节点。 每一个设备类可能拥有多个的接口,通过这些接口,你可以使用同样的设备。输入设备可能支持鼠标接口、evdev界面和触摸屏界面。SCSI磁盘将支持磁盘接口,一般的SCSI接口,或者可能是原始设备接口。 设备接口被注册到他们所属的类。随着设备被添加到类,它们便被添加到每个接口注册的类别。该接口负责决定是否该设备支持这个接口或者没有。 编程接口
~~~~~~~~~~~
struct device_interface {
char * name; rwlock_t lock; u32 devnum; struct device_class * devclass;
struct list_head node; struct driver_dir_entry dir;
int (*add_device)(struct device *); int (*add_device)(struct intf_data *); };
int interface_register(struct device_interface *); void interface_unregister(struct device_interface *);
一种接口必须指定他所属的设备类。它被添加到该类别接口的注册清单上。
接口可能随时加入到一种类别中。一旦它被加入,这一类别中的每一设备通过界面的 add_device 回调。当一种接口注销后,每一种设备从接口上移开。
设备
~~~~~~~
一旦一个设备加入一个设备类中(class),它将同时被注册个这个类的每个接口。每个设备都需要在device::class_data中填写和设备相关的信息。每个接口都能够使用这些信息来判断该设备是否支持该接口。
数据 ~~~~~ struct intf_data {
struct list_head node; struct device_interface * intf; struct device * dev;
28
www.ourkernel.com 我们的内核
u32 intf_num;
};
int interface_add_data(struct interface_data *);
该接口是负责分配并初始化一种结构intf_data,并调用interface_add_data()将其添加到他所属于的设备接口清单中。当设备从类中注销时该清单会被更新(而不是一个类中所有可能的接口(发生改变))。这种结构或许应该根植于无论何种的单一设备数据结构,无论接口是如何分配的。
枚举设备的接口。其发生在interface_add_data()和枚举值中,存放在设备的结构intf_data。
sysfs
~~~~~
在其所属的设备类的目录中,每一种接口都给定一索引: 在class目录中,接口同时得到一个索引: class/ `-- input
|-- devices |-- drivers |-- mouse
`-- evdev
当一个设备加入到接口中,便形成了一个指向物理层中设备目录的符号链接。 class/
`-- input
|-- devices
| `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/ |-- drivers
| `-- usb:usb_mouse -> ../../../bus/drivers/usb_mouse/ |-- mouse
| `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/ `-- evdev
`-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/
未来计划
~~~~~~
一种设备接口直接与一个用户空间的接口相连,(一种特殊的设备节点。)比如说,一个SCSI磁盘提供了至少两个用户空间的接口:标准的SCSI磁盘接口和一般的SCSI接口。他可能也会使用一个更加原始设备接口。
许多接口都具有一个主设备号,该接口下的每个设备都有一个次设备号。 在特殊情况下,几个接口共用一个主设备号,分别使用不同区间的从设备号(比如说是输入设备)。
我们可以将主设备号和次设备号保存在interface结构体中。在接口向class注册时,将分配主设备号和次设备号。我们也可以使用一个内核函数来完成主次设备号的分配。
29
www.ourkernel.com 我们的内核
Platform
原文作者:
翻 译者: Solarapex solarapex.hxf@gmail.com 校 订者:
版本状态:还未完成
======================================
平台设备和驱动
~~~~~~~~~~~~
在
这样的总线包括许多片上系统上的那些用来整合外设的总线, 也包括一些\古董\上的连接器; 但不包
括像PCI或USB这样的有庞大正规说明的总线.
平台设备
~~~~~~
平台设备通常指的是系统中的自治体, 包括老式的基于端口的设备和连接外设总线的北桥(host bridges),
以及集成在片上系统中的绝大多数控制器. 它们通常拥有的一个共同特征是直接编址于CPU总线上. 即使在某
些罕见的情况下, 平台设备会通过某段其他类型的总线连入系统, 它们的寄存器也会被直接编址.
平台设备会分到一个名称(用在驱动绑定中)以及一系列诸如地址和中断请求号(IRQ)之类的资源.
struct platform_device { const char *name;
u32 id;
struct device dev;
u32 num_resources; struct resource *resource; };
平台驱动
~~~~~~
平台驱动遵循标准驱动模型的规范, 也就是说发现/列举(discovery/enumeration)在驱动之外处理, 而
由驱动提供probe()和remove方法. 平台驱动按标准规范对电源管理和关机通告提供支持.
struct platform_driver {
30