zoukankan      html  css  js  c++  java
  • Linux总线设备驱动模型

    1. Linux2.6内核引入总线、设备、驱动模型来描述各种总线(PCI、USB、I2C、SPI)与外围设备及其驱动之间的关系。

    2. 在Linux内核中,总线用bus_type结构来描述,定义于文件:include/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;
    };

    ① name:总线名字,如PCI

    bus_attrs:总线属性

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

    ④ uevent:

    ⑤ probe:

    ⑥ remove:

    (1) 总线的注册:int us_register(struct bus_type *bus)(若注册成功,新的总线将被添加进系统,可在/sys/bus 下看到相应的目录)

    (2) 总线的注销:void bus_unregister(struct bus_type *bus)

    3. 在Linux内核中, 驱动由device_driver结构描述

    struct device_driver {
        const char        *name;
        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;
    };

    ① probe:

    ② remove:

    (1)驱动的注册:int driver_register(struct device_driver *drv)

    (2)驱动的注销:void driver_unregister(struct device_driver *drv)

    4. 在Linux内核中, 设备由struct device结构描述

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

    (1)设备的注册:int device_register(struct device *dev)

    (2)设备的注销:void device_unregister(struct device *dev)

    5. 简单示例

    (1)Bus.c

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/device.h>
    
    MODULE_LICENSE("GPL");
    
    int my_match(struct device *dev, struct device_driver *drv)
    {
        printk("Bus: my_match
    ");
        return !strncmp(dev->kobj.name, drv->name, strlen(drv->name));
    }
    
    int my_remove(struct device *dev)
    {
        printk("Bus: Device %s removed from bus
    ", dev->init_name);
    }
    
    struct bus_type my_bus_type = {
        .name = "my_bus",
        .match = my_match,
        .remove = my_remove,
    };
        
    EXPORT_SYMBOL(my_bus_type);
    
    int my_bus_init(void)
    {
        int ret;
        
        ret = bus_register(&my_bus_type);
        
        return ret;
    }
    
    void my_bus_exit(void)
    {
        bus_unregister(&my_bus_type);
    }
    
    module_init(my_bus_init);
    module_exit(my_bus_exit);

    (2)Device.c

    #include <linux/device.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    
    MODULE_LICENSE("GPL");
    
    extern struct bus_type my_bus_type;
    
    void my_release(struct device *dev)
    {
        printk("Device: Device %s's release function
    ", dev->init_name);
    }
    
    struct device my_dev = {
        .init_name = "my_dev",
        .bus = &my_bus_type,
        .release = my_release,
    };
    
    int my_device_init(void)
    {
        int ret;
        ret = device_register(&my_dev);
        return ret;
    }
    
    void my_device_exit(void)
    {
        device_unregister(&my_dev);
    }
    
    module_init(my_device_init);
    module_exit(my_device_exit);

    (3)Driver.c

    #include <linux/device.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    
    MODULE_LICENSE("GPL");
    
    extern struct bus_type my_bus_type;
    
    int my_probe(struct device *dev)
    {
        printk("Driver: driver found the device it can handle!
    ");
        return 0;
    }
    
    struct device_driver my_driver = {
        .name = "my_dev",
        .bus = &my_bus_type,    
        .probe = my_probe,
    };
    
    int my_driver_init(void)
    {
        int ret;
        
        ret = driver_register(&my_driver);
        
        return ret;
    }
    
    void my_driver_exit(void)
    {
        driver_unregister(&my_driver);    
    }
    
    module_init(my_driver_init);
    module_exit(my_driver_exit);
  • 相关阅读:
    C#深入浅出 修饰符(二)
    HDU 5785 Interesting
    HDU 5783 Divide the Sequence
    HDU 5781 ATM Mechine
    UVA 714 Copying Books
    uva 1471 Defense Lines
    UVA 11134 Fabled Rooks
    UVA 11572 Unique Snowflakes
    UVA 11093 Just Finish it up
    UVA 10954 Add All
  • 原文地址:https://www.cnblogs.com/wulei0630/p/9542343.html
Copyright © 2011-2022 走看看