现在的位置: 首页 > 综合 > 正文

设备驱动模型

2017年08月24日 ⁄ 综合 ⁄ 共 5985字 ⁄ 字号 评论关闭

设备模型元素----

总线

驱动

设备

总线是处理器和设备之间的通道,在设备模型中,所有的设备都通过总线相连,甚至是内部的虚拟总线。(platform)在linux设备模型中,总线由bus_type结构表示,定义在linux/device.h

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 (*suspend_late)(struct device *dev, pm_message_t state);
    int (*resume_early)(struct device *dev);
    int (*resume)(struct device *dev);

    struct dev_pm_ops *pm;

    struct bus_type_private *p;
};

总线注册------

bus_register(struct bus_type *bus)

若成功,新的总线将被添加进系统,并可在sysfs的/sys/bus下看到。

总线的删除使用

void bus_unregister(struct bus_type *bus)

总线方法----

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

当一个新设备或者驱动添加到这个总线时,该方法调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零值。

int (*uevent)(struct device *dev,char **envp,int num_envp,char *buffer,int buffer_size)

在为用户空间产生热插拔事件之前,这个方法允许总线添加环境变量

总线属性------

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 conunt);

}


int bus_create_file(struct bus_type *bus,struct bus_attribute *attr)

创建属性


void bus_remove_file(struct bus_type *bus,struct
bus_attribute
*attr
)

删除属性

#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>

MODULE_AUTHOR("David Xie");
MODULE_LICENSE("Dual BSD/GPL");

static char *Version = "$Revision: 1.0 $";

static int my_match(struct device *dev, struct device_driver *driver)
{
    return !strncmp(dev->bus_id, driver->name, strlen(driver->name));
}

struct bus_type my_bus_type = {
    .name = "my_bus",目录名
    .match = my_match,
};

static ssize_t show_bus_version(struct bus_type *bus, char *buf)
{
    return snprintf(buf, PAGE_SIZE, "%s\n", Version);
}

static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);

static int __init my_bus_init(void)
{
    int ret;
        
        /*注册总线*/
    ret = bus_register(&my_bus_type);
    if (ret)
        return ret;
        
    /*创建属性文件*/    
    if (bus_create_file(&my_bus_type, &bus_attr_version))
        printk(KERN_NOTICE "Fail to create version attribute!\n");
        
    return ret;
}

static void my_bus_exit(void)
{
    bus_unregister(&my_bus_type);
}

module_init(my_bus_init);
module_exit(my_bus_exit);

#define BUS_ATTR(_name, _mode, _show, _store)    \
struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)

#define __ATTR(_name,_mode,_show,_store) { \
    .attr = {.name = __stringify(_name), .mode = _mode },    \
    .show    = _show,                    \
    .store    = _store,                    \
}

#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)


设备描述

struct
device
{
    struct klist        klist_children;
    struct klist_node    knode_parent;    /* node in sibling list */
    struct klist_node    knode_driver;
    struct klist_node    knode_bus;
    struct device        *parent;

    struct kobject kobj;
    char    bus_id[BUS_ID_SIZE];    /* position on parent bus */

在总线上唯一标识该设备的字符串

    unsigned        uevent_suppress:1;
    const char        *init_name; /* initial name of the device */
    struct device_type    *type;

    struct semaphore    sem;    /* semaphore 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        *driver_data;    /* data private to the driver */

该设备驱动使用的私有数据成员

    void        *platform_data;    /* Platform specific data, device
                       core doesn't touch it */
    struct dev_pm_info    power;

#ifdef CONFIG_NUMA
    int        numa_node;    /* NUMA node this device is close to */
#endif
    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;
    struct attribute_group    **groups;    /* optional groups */

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

通常的注册和注销函数在

int device_register(struct device *dev);
void device_unregister(struct device *dev);

一条总线也是个设备,也必须按设备注册

sysfs 中的设备入口可有属性. 相关的结构是:

struct device_attribute {
 struct attribute attr;
 ssize_t (*show)(struct device *dev, char *buf);
 ssize_t (*store)(struct device *dev, const char *buf,
 size_t count);
};
创建 删除属性
int device_create_file(struct device *device, struct device_attribute *entry);
void device_remove_file(struct device *dev, struct device_attribute *attr);

 


驱动描述

struct device_driver {
    const char        *name;驱动程序的名字---体现在sysfs中。
    struct bus_type        *bus;驱动程序所在的总线

    struct module        *owner;
    const char         *mod_name;    /* used for built-in modules */

    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);
    struct attribute_group **groups;

    struct dev_pm_ops *pm;

    struct driver_private *p;
};

 调用时机---------int (*probe) (struct device *dev);

当驱动找到与它匹配的设备的时候就会调用。

int driver_register(struct device_driver *drv)

注册驱动

int driver_unregister(struct device_driver *drv)

注销驱动

驱动属性---

struct driver_attribute {
    struct attribute attr;
    ssize_t (*show)(struct device_driver *driver, char *buf);
    ssize_t (*store)(struct device_driver *driver, const char *buf,
             size_t count);
};

int driver_create_file(struct device_driver *drv,struct driver_attribute *attr)

创建属性

void driver_remove_file(struct device_driver *drv, struct driver_attribute *attr)

删除属性

总结-----

当一个新设备或者驱动添加到这个总线时,该方法调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零值。通过设备的bud_id和驱动的名字来匹配。

当驱动找到与它匹配的设备的时候就会调用。



抱歉!评论已关闭.