</pre><span style="font-size:14px;">设备模型是2.6内核引入的特征</span><p></p><p><span style="font-size:24px;">一、总线</span></p><p><span style="font-size:14px;">总线是处理器与设备之间的通道,包括某些嵌入式处理器的外设,内核也可以用虚拟的platform连接他们</span></p><p></p><pre name="code" class="html"><span style="font-size:14px;">/linux/device.h</span>
<span style="font-size:14px;">struct bus_type {
const char *name;
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 (*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 (*resume)(struct device *dev);
const struct dev_pm_ops *pm;
struct subsys_private *p;
};</span>
内核中用bus_type来描述总线
初始化时主要需要定义其中的name、match、remove、还可以定义属性
总线的注册和删除
<span style="font-size:14px;">int bus_register(struct bus_type *bus)</span>
<span style="font-size:14px;">void bus_unregister(struct bus_type *bus);</span>
设置总线属性的两个步骤
1、下面的宏创建一个名为bus_attr__name的bus_attibute结构,并设置成员名为name、mode、读取属性文件的show函数和写入属性文件的store函数
<pre name="code" class="html"><span style="font-size:14px;">BUS_ATTR(_name, _mode, _show, _store)</span>
2、将属性文件添加到相应的bus上
<span style="font-size:14px;">int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)</span>
删除属性
<span style="font-size:14px;">void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr)
</span>
其实device和driver定义和属性文件的添加也是类似的方法,将上述函数中的bus改为device或者driver即可
二、设备
内核用一个device结构来描述设备
<span style="font-size:14px;">struct device {
struct device *parent;
struct device_private *p;
struct kobject kobj;
const char *init_name; /* initial name of the device */
struct device_type *type;
struct mutex mutex; /* mutex to synchronize calls to
* its driver.
*/
struct bus_type *bus; /* type of bus device is on */
struct device_driver *driver; /* which driver has allocated this
device */
void *platform_data; /* Platform specific data, device
core doesn't touch it */
struct dev_pm_info power;
u64 *dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask;/* Like dma_mask, but for
alloc_coherent mappings as
not all hardware supports
64 bit addresses for consistent
allocations such descriptors. */
struct device_dma_parameters *dma_parms;
struct list_head dma_pools; /* dma pools (if dma'ble) */
struct dma_coherent_mem *dma_mem; /* internal for coherent mem
override */
/* arch specific additions */
struct dev_archdata archdata;
dev_t devt; /* dev_t, creates the sysfs "dev" */
spinlock_t devres_lock;
struct list_head devres_head;
struct klist_node knode_class;
struct class *class;
const struct attribute_group **groups; /* optional groups */
void (*release)(struct device *dev);
};
</span>
其中至少要定义init_name(这里没有看到资料上说的bus_id)、bus、和release函数
设备的注册和注销和bus_(un)register类似
<span style="font-size:14px;">int device_register(struct device *dev)
函数失败返回非零,需要判断返回值来检查注册是否成功。</span>
<span style="font-size:14px;">void device_unregister(struct device *dev)</span>
属性的添加和总线类似
三、驱动程序
驱动的结构体
<span style="font-size:14px;">struct device_driver {
const char *name;
struct bus_type *bus;
struct module *owner;
const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void end) (struct device *dev, pm_message_t state);
int (*r(*shutdown) (struct device *dev);
int (*suspesume) (struct device *dev);
const struct attribute_group **groups;
const struct dev_pm_ops *pm;
struct driver_private *p;
};
</span>
一遍需要初始化的有 name、bus、probe 函数
驱动的注册和注销采用下列函数
<span style="font-size:14px;">int driver_register(struct device_driver *drv)
函数失败返回非零,需要判断返回值来检查注册是否成功。
设备注销函数:
void driver_unregister(struct device_driver *drv)</span>
<span style="font-size:14px;">
</span>
<span style="font-size:14px;">属性的添加和总线类似</span>
<span style="font-size:14px;">
</span>
借用从别的博客上看来的一段话:
归纳起来就是四个函数一个属性结构体。
属性结构体:xx_attribute。
注册函数:xx_register。
注销函数:xx_unregister。
创建属性文件函数:xx_create_file。
删除属性文件函数:xx_remove_file。
其中xx可以是总线(bus)、设备(device)或者驱动函数(deriver)。
一但注册成功,就会在/sys目录下相应的地方创建一个自己命名的目录。其中,设备和驱动函数还可以添加到指定的bus目录下。
总线的成功注册后会在/sys/bus目录下创建相应的目录。
设备的成功注册后会在/sys/device目录下创建相应的目录,如果指定总线,会在指定总线目录/sys/bus/xx/device下创建一个指向/sys/device目录的软连接。
驱动函数的公共注册会在/sys/bus/xx/driver目录下创建相应的目录。
属性文件提供了shoe和store两个函数调用,当读写文件时会触发相应的函数调用,实现内核sysfs与用户空间的数据交互。
四、其他
struct bus_type bus 中的match函数用来比对挂接在该总线上的驱动和设备,当两者或者别的匹配时,返回 1 。代表两者配对成功、
struct device_driver中的probe 探针函数、当match函数配对成功后、内核就会调用该函数来查询设备是否可以别该驱动操作,如果可以,就会调用该函数,
所以说。真正的驱动函数的入口在probe中
引用:http://blog.chinaunix.net/uid-25014876-id-110295.html