device

1.device的结构:

struct device

{

 struct klist        klist_children;       //设备列表中的子列表

 struct klist_node     knode_parent;     //兄弟节点

 struct klist_node     knode_driver;         //驱动程序节点

 struct klist_node     knode_bus;            //总线节点

 struct device*        parent;        //父设备节点,即,当前设备所附着到的设备

 struct kobject        kobj;                 //代表当前设备,并连接它到层次中的kobject

 char                     bus_id[BUS_ID_SIZE]; //唯一确定这个总线上的设备的字符串,即,总线上设备的位置

 struct device_attribute   uevent_attr;

 struct device_attribute*  devt_attr;

 struct semaphore     sem;      //信号量

 struct bus_type*      bus;      //总线类型,即,哪种总线

 struct device_driver*   driver;     //这个设备所使用的驱动程序

 void*           driver_data;  //一个可能被设备驱动程序所使用的私有数据

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

 void*           firmware_data;  /* Firmware specific data (e.g. ACPI, BIOS data),reserved for device core*/

 struct dev_pm_info    power;

 u64*           dma_mask;      /* dma mask (if dma'able device) */

 u64            coherent_dma_mask;

 struct list_head     dma_pools;     /* dma pools (if dma'ble) */

 struct dma_coherent_mem* dma_mem;       /* internal for coherent mem override */

 struct list_head     node;        /* class_device migration path */

 struct class*       class;       /* optional */

 dev_t           devt;        /* dev_t, creates the sysfs "dev" */

 void (*release)(struct device* dev);          //释放设备的函数

};

//重点看一下私有属性结构  

struct device_private {  

    struct klist klist_children;             //子集结构  

    struct klist_node knode_parent;          //父级挂接点  

    struct klist_node knode_driver;          //driver挂接点  

    struct klist_node knode_bus;             //bus挂接点  

    void *driver_data;  

    struct device *device;                   //回指  

};  

2.device的注册

int device_register(struct device *dev)  

{  

    device_initialize(dev);                //初始化dev  

    return device_add(dev);                //添加dev  

}  

先看一下device_initialize(dev) 

void device_initialize(struct device *dev)  

{  

    dev->kobj.kset = devices_kset; //可见device和bus都有其起始的kset,而driver没有  

    kobject_init(&dev->kobj, &device_ktype); //初始化kobj并建立层次关系以及属性文件

    INIT_LIST_HEAD(&dev->dma_pools); //是放到了总的device文件目录下面  

    mutex_init(&dev->mutex);  

    lockdep_set_novalidate_class(&dev->mutex);  

    spin_lock_init(&dev->devres_lock);  

    INIT_LIST_HEAD(&dev->devres_head);  

    device_pm_init(dev);  

    set_dev_node(dev, -1);  

}  

再来看一下device_add(dev) 

int device_add(struct device *dev)  

{  

    struct device *parent = NULL;  

    struct class_interface *class_intf;  

    dev = get_device(dev);  

    if (!dev->p) {  

        error = device_private_init(dev);  //初始化dev的私有成员,及其链表操作函数  

    }  

    if (dev->init_name) {  

        dev_set_name(dev, "%s", dev->init_name);            //设置名字,给kobj  

        dev->init_name = NULL;  

    }  

    if (!dev_name(dev)) {                                //名字为空出错退出  

        error = -EINVAL;  

        goto name_error;  

    }  

    parent = get_device(dev->parent);    //返回父节点,如果有返回,没有返回NULL  

    setup_parent(dev, parent); 

    if (parent)  

        set_dev_node(dev, dev_to_node(parent));  

    error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); //初始化kobj与其父节点的连接  

    if (platform_notify)  

        platform_notify(dev);  

    error = device_create_file(dev, &uevent_attr);             //产生属性文件  

    if (MAJOR(dev->devt)) {  

        error = device_create_file(dev, &devt_attr); //在sys下产生dev属性文件  

        error = device_create_sys_dev_entry(dev);  

        devtmpfs_create_node(dev);                                 

    }  

    error = device_add_class_symlinks(dev);  

    error = device_add_attrs(dev);                             //增加属性文件  

    error = bus_add_device(dev);   //把device的bus节点挂到bus的设备节点上  

    error = dpm_sysfs_add(dev);  

    device_pm_add(dev);  

    if (dev->bus)  

        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  

                         BUS_NOTIFY_ADD_DEVICE, dev);  

    kobject_uevent(&dev->kobj, KOBJ_ADD);  

    bus_probe_device(dev);    //匹配driver  

    if (parent)  

        klist_add_tail(&dev->p->knode_parent, //把该设备的节点挂到其父节点的链表  

                   &parent->p->klist_children);  

    if (dev->class) {  

        mutex_lock(&dev->class->p->class_mutex);  

        /* tie the class to the device */  

        klist_add_tail(&dev->knode_class,  

                   &dev->class->p->class_devices);  

        /* notify any interfaces that the device is here */  

        list_for_each_entry(class_intf,  

                    &dev->class->p->class_interfaces, node)  

            if (class_intf->add_dev)  

                class_intf->add_dev(dev, class_intf);  

        mutex_unlock(&dev->class->p->class_mutex);  

    }   

}  

重点看一下bus_probe_device匹配driver以及初始化过程 

void bus_probe_device(struct device *dev)  

{  

    struct bus_type *bus = dev->bus;  

    int ret;  

    if (bus && bus->p->drivers_autoprobe) {         //设置了自动匹配初始化那么就开始匹配  

        ret = device_attach(dev);  

        WARN_ON(ret < 0);  

    }  

}  

继续device_attach  

int device_attach(struct device *dev)  

{  

    int ret = 0;  

    device_lock(dev);  

    if (dev->driver) {                            //默认指定了driver就直接绑定  

        ret = device_bind_driver(dev);  

        if (ret == 0)  

            ret = 1;  

        else {  

            dev->driver = NULL;  

            ret = 0;  

        }  

    } else {                                      //没有指定就进行遍历匹配  

        pm_runtime_get_noresume(dev);  

        ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);  

        pm_runtime_put_sync(dev);  

    }  

    device_unlock(dev);  

    return ret;  

}  

再来看device_bind_driver分支 

int device_bind_driver(struct device *dev)  

{  

    int ret;  

    ret = driver_sysfs_add(dev);  

    if (!ret)  

        driver_bound(dev);              //主要是完成了将私有成员的driver节点挂到  

    return ret;                         //了driver的设备链表  

}  

先看bus_for_each_drv分支 

int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,  

             void *data, int (*fn)(struct device_driver *, void *))  

{  

    struct klist_iter i;  

    struct device_driver *drv;  

    int error = 0;  

    if (!bus)  

        return -EINVAL;  

    klist_iter_init_node(&bus->p->klist_drivers, &i,           //和driver遍历device类似,从头开始遍历bus的driver链表  

                 start ? &start->p->knode_bus : NULL);         //发现一个driver就调用fn即__device_attach进行匹配  

    while ((drv = next_driver(&i)) && !error)  

        error = fn(drv, data);  

    klist_iter_exit(&i);  

    return error;  

}  

最后来看一下__device_attach这个函数 

static int __device_attach(struct device_driver *drv, void *data)  

{  

    struct device *dev = data;  

    if (!driver_match_device(drv, dev))      

        return 0;  

    return driver_probe_device(drv, dev);  

}  

3.设备属性:

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

};

int device_create_file(struct device* dev, struct device_attribute* attr):为指定设备添加属性;

void device_remove_file(struct device* dev, struct device_attribute* attr):删除指定设备上的指定属性;

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值