首页
登录 | 注册

* LINUX设备驱动程序(第3版)第十四章Linux设备模型中的总线、设备和驱动程序的理解

ldd_bus.h 定义如下:
//LDD driver type
struct ldd_driver
{
    char    *version;
    struct module *module;
    struct device_driver driver;
    struct driver_attribute    version_attr;
};

//A device type for things "plugged" into the LDD bus.
struct     ldd_device
{
    char     *name;
    struct ldd_driver    *driver;
    struct device        dev;
};

sculld.h 中定义如下:
struct sculld_dev
{
    void    **data;
    struct sculld_dev     *next;    //next listitem
    int        vmas;                //active mappings
    int        order;                //the current allocation order
    int        qset;                //the current array size
    size_t    size;                //32-bit will suffice
    struct semaphore    sem;    //Mutual exclusion
    struct cdev         cdev;
    char    devname[SCULLD_DEVNAME_SIZE];
    struct    ldd_device    ldev;
};


struct device :
  1. /**
  2.  * struct device - The basic device structure
  3.  * @parent:    The device's "parent" device, the device to which it is attached.
  4.  *         In most cases, a parent device is some sort of bus or host
  5.  *         controller. If parent is NULL, the device, is a top-level device,
  6.  *         which is not usually what you want.
  7.  * @p:        Holds the private data of the driver core portions of the device.
  8.  *         See the comment of the struct device_private for detail.
  9.  * @kobj:    A top-level, abstract class from which other classes are derived.
  10.  * @init_name:    Initial name of the device.
  11.  * @type:    The type of device.
  12.  *         This identifies the device type and carries type-specific
  13.  *         information.
  14.  * @mutex:    Mutex to synchronize calls to its driver.
  15.  * @bus:    Type of bus device is on.
  16.  * @driver:    Which driver has allocated this
  17.  * @platform_data: Platform data specific to the device.
  18.  *         Example: For devices on custom boards, as typical of embedded
  19.  *         and SOC based hardware, Linux often uses platform_data to point
  20.  *         to board-specific structures describing devices and how they
  21.  *         are wired. That can include what ports are available, chip
  22.  *         variants, which GPIO pins act in what additional roles, and so
  23.  *         on. This shrinks the "Board Support Packages" (BSPs) and
  24.  *         minimizes board-specific #ifdefs in drivers.
  25.  * @power:    For device power management.
  26.  *         See Documentation/power/devices.txt for details.
  27.  * @pm_domain:    Provide callbacks that are executed during system suspend,
  28.  *         hibernation, system resume and during runtime PM transitions
  29.  *         along with subsystem-level and driver-level callbacks.
  30.  * @numa_node:    NUMA node this device is close to.
  31.  * @dma_mask:    Dma mask (if dma'ble device).
  32.  * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
  33.  *         hardware supports 64-bit addresses for consistent allocations
  34.  *         such descriptors.
  35.  * @dma_parms:    A low level driver may set these to teach IOMMU code about
  36.  *         segment limitations.
  37.  * @dma_pools:    Dma pools (if dma'ble device).
  38.  * @dma_mem:    Internal for coherent mem override.
  39.  * @archdata:    For arch-specific additions.
  40.  * @of_node:    Associated device tree node.
  41.  * @devt:    For creating the sysfs "dev".
  42.  * @devres_lock: Spinlock to protect the resource of the device.
  43.  * @devres_head: The resources list of the device.
  44.  * @knode_class: The node used to add the device to the class list.
  45.  * @class:    The class of the device.
  46.  * @groups:    Optional attribute groups.
  47.  * @release:    Callback to free the device after all references have
  48.  *         gone away. This should be set by the allocator of the
  49.  *         device (i.e. the bus driver that discovered the device).
  50.  *
  51.  * At the lowest level, every device in a Linux system is represented by an
  52.  * instance of struct device. The device structure contains the information
  53.  * that the device model core needs to model the system. Most subsystems,
  54.  * however, track additional information about the devices they host. As a
  55.  * result, it is rare for devices to be represented by bare device structures;
  56.  * instead, that structure, like kobject structures, is usually embedded within
  57.  * a higher-level representation of the device.
  58.  */
  59. struct device {
  60.     struct device        *parent;

  61.     struct device_private    *p;

  62.     struct kobject kobj;
  63.     const char        *init_name; /* initial name of the device */
  64.     const struct device_type *type;

  65.     struct mutex        mutex;    /* mutex to synchronize calls to
  66.                      * its driver.
  67.                      */

  68.     struct bus_type    *bus;        /* type of bus device is on */
  69.     struct device_driver *driver;    /* which driver has allocated this
  70.                      device */
  71.     void        *platform_data;    /* Platform specific data, device
  72.                      core doesn't touch it */
  73.     struct dev_pm_info    power;
  74.     struct dev_pm_domain    *pm_domain;

  75. #ifdef CONFIG_NUMA
  76.     int        numa_node;    /* NUMA node this device is close to */
  77. #endif
  78.     u64        *dma_mask;    /* dma mask (if dma'able device) */
  79.     u64        coherent_dma_mask;/* Like dma_mask, but for
  80.                      alloc_coherent mappings as
  81.                      not all hardware supports
  82.                      64 bit addresses for consistent
  83.                      allocations such descriptors. */

  84.     struct device_dma_parameters *dma_parms;

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

  86.     struct dma_coherent_mem    *dma_mem; /* internal for coherent mem
  87.                      override */
  88.     /* arch specific additions */
  89.     struct dev_archdata    archdata;

  90.     struct device_node    *of_node; /* associated device tree node */

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

  92.     spinlock_t        devres_lock;
  93.     struct list_head    devres_head;

  94.     struct klist_node    knode_class;
  95.     struct class        *class;
  96.     const struct attribute_group **groups;    /* optional groups */

  97.     void    (*release)(struct device *dev);
  98. };
struct device_private :
  1. /**
  2.  * struct device_private - structure to hold the private to the driver core portions of the device structure.
  3.  *
  4.  * @klist_children - klist containing all children of this device
  5.  * @knode_parent - node in sibling list
  6.  * @knode_driver - node in driver list
  7.  * @knode_bus - node in bus list
  8.  * @driver_data - private pointer for driver specific info. Will turn into a
  9.  * list soon.
  10.  * @device - pointer back to the struct class that this structure is
  11.  * associated with.
  12.  *
  13.  * Nothing outside of the driver core should ever touch these fields.
  14.  */
  15. struct device_private {
  16.     struct klist klist_children;
  17.     struct klist_node knode_parent;
  18.     struct klist_node knode_driver;
  19.     struct klist_node knode_bus;
  20.     void *driver_data;
  21.     struct device *device;
  22. };





struct bus_type :
  1. /**
  2.  * struct bus_type - The bus type of the device
  3.  *
  4.  * @name:    The name of the bus.
  5.  * @bus_attrs:    Default attributes of the bus.
  6.  * @dev_attrs:    Default attributes of the devices on the bus.
  7.  * @drv_attrs:    Default attributes of the device drivers on the bus.
  8.  * @match:    Called, perhaps multiple times, whenever a new device or driver
  9.  *        is added for this bus. It should return a nonzero value if the
  10.  *        given device can be handled by the given driver.
  11.  * @uevent:    Called when a device is added, removed, or a few other things
  12.  *        that generate uevents to add the environment variables.
  13.  * @probe:    Called when a new device or driver add to this bus, and callback
  14.  *        the specific driver's probe to initial the matched device.
  15.  * @remove:    Called when a device removed from this bus.
  16.  * @shutdown:    Called at shut-down time to quiesce the device.
  17.  * @suspend:    Called when a device on this bus wants to go to sleep mode.
  18.  * @resume:    Called to bring a device on this bus out of sleep mode.
  19.  * @pm:        Power management operations of this bus, callback the specific
  20.  *        device driver's pm-ops.
  21.  * @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU
  22.  * driver implementations to a bus and allow the driver to do
  23.  * bus-specific setup
  24.  * @p:        The private data of the driver core, only the driver core can
  25.  *        touch this.
  26.  *
  27.  * A bus is a channel between the processor and one or more devices. For the
  28.  * purposes of the device model, all devices are connected via a bus, even if
  29.  * it is an internal, virtual, "platform" bus. Buses can plug into each other.
  30.  * A USB controller is usually a PCI device, for example. The device model
  31.  * represents the actual connections between buses and the devices they control.
  32.  * A bus is represented by the bus_type structure. It contains the name, the
  33.  * default attributes, the bus' methods, PM operations, and the driver core's
  34.  * private data.
  35.  */
  36. struct bus_type {
  37.     const char        *name;
  38.     struct bus_attribute    *bus_attrs;
  39.     struct device_attribute    *dev_attrs;
  40.     struct driver_attribute    *drv_attrs;

  41.     int (*match)(struct device *dev, struct device_driver *drv);
  42.     int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
  43.     int (*probe)(struct device *dev);
  44.     int (*remove)(struct device *dev);
  45.     void (*shutdown)(struct device *dev);

  46.     int (*suspend)(struct device *dev, pm_message_t state);
  47.     int (*resume)(struct device *dev);

  48.     const struct dev_pm_ops *pm;

  49.     struct iommu_ops *iommu_ops;

  50.     struct subsys_private *p;
  51. };


struct module :
  1. struct module
  2. {
  3.     enum module_state state;

  4.     /* Member of list of modules */
  5.     struct list_head list;

  6.     /* Unique handle for this module */
  7.     char name[MODULE_NAME_LEN];

  8.     /* Sysfs stuff. */
  9.     struct module_kobject mkobj;
  10.     struct module_attribute *modinfo_attrs;
  11.     const char *version;
  12.     const char *srcversion;
  13.     struct kobject *holders_dir;

  14.     /* Exported symbols */
  15.     const struct kernel_symbol *syms;
  16.     const unsigned long *crcs;
  17.     unsigned int num_syms;

  18.     /* Kernel parameters. */
  19.     struct kernel_param *kp;
  20.     unsigned int num_kp;

  21.     /* GPL-only exported symbols. */
  22.     unsigned int num_gpl_syms;
  23.     const struct kernel_symbol *gpl_syms;
  24.     const unsigned long *gpl_crcs;

  25. #ifdef CONFIG_UNUSED_SYMBOLS
  26.     /* unused exported symbols. */
  27.     const struct kernel_symbol *unused_syms;
  28.     const unsigned long *unused_crcs;
  29.     unsigned int num_unused_syms;

  30.     /* GPL-only, unused exported symbols. */
  31.     unsigned int num_unused_gpl_syms;
  32.     const struct kernel_symbol *unused_gpl_syms;
  33.     const unsigned long *unused_gpl_crcs;
  34. #endif

  35.     /* symbols that will be GPL-only in the near future. */
  36.     const struct kernel_symbol *gpl_future_syms;
  37.     const unsigned long *gpl_future_crcs;
  38.     unsigned int num_gpl_future_syms;

  39.     /* Exception table */
  40.     unsigned int num_exentries;
  41.     struct exception_table_entry *extable;

  42.     /* Startup function. */
  43.     int (*init)(void);

  44.     /* If this is non-NULL, vfree after init() returns */
  45.     void *module_init;

  46.     /* Here is the actual code + data, vfree'd on unload. */
  47.     void *module_core;

  48.     /* Here are the sizes of the init and core sections */
  49.     unsigned int init_size, core_size;

  50.     /* The size of the executable code in each section. */
  51.     unsigned int init_text_size, core_text_size;

  52.     /* Size of RO sections of the module (text+rodata) */
  53.     unsigned int init_ro_size, core_ro_size;

  54.     /* Arch-specific module values */
  55.     struct mod_arch_specific arch;

  56.     unsigned int taints;    /* same bits as kernel:tainted */

  57. #ifdef CONFIG_GENERIC_BUG
  58.     /* Support for BUG */
  59.     unsigned num_bugs;
  60.     struct list_head bug_list;
  61.     struct bug_entry *bug_table;
  62. #endif

  63. #ifdef CONFIG_KALLSYMS
  64.     /*
  65.      * We keep the symbol and string tables for kallsyms.
  66.      * The core_* fields below are temporary, loader-only (they
  67.      * could really be discarded after module init).
  68.      */
  69.     Elf_Sym *symtab, *core_symtab;
  70.     unsigned int num_symtab, core_num_syms;
  71.     char *strtab, *core_strtab;

  72.     /* Section attributes */
  73.     struct module_sect_attrs *sect_attrs;

  74.     /* Notes attributes */
  75.     struct module_notes_attrs *notes_attrs;
  76. #endif

  77.     /* The command line arguments (may be mangled). People like
  78.      keeping pointers to this stuff */
  79.     char *args;

  80. #ifdef CONFIG_SMP
  81.     /* Per-cpu data. */
  82.     void __percpu *percpu;
  83.     unsigned int percpu_size;
  84. #endif

  85. #ifdef CONFIG_TRACEPOINTS
  86.     unsigned int num_tracepoints;
  87.     struct tracepoint * const *tracepoints_ptrs;
  88. #endif
  89. #ifdef HAVE_JUMP_LABEL
  90.     struct jump_entry *jump_entries;
  91.     unsigned int num_jump_entries;
  92. #endif
  93. #ifdef CONFIG_TRACING
  94.     unsigned int num_trace_bprintk_fmt;
  95.     const char **trace_bprintk_fmt_start;
  96. #endif
  97. #ifdef CONFIG_EVENT_TRACING
  98.     struct ftrace_event_call **trace_events;
  99.     unsigned int num_trace_events;
  100. #endif
  101. #ifdef CONFIG_FTRACE_MCOUNT_RECORD
  102.     unsigned int num_ftrace_callsites;
  103.     unsigned long *ftrace_callsites;
  104. #endif

  105. #ifdef CONFIG_MODULE_UNLOAD
  106.     /* What modules depend on me? */
  107.     struct list_head source_list;
  108.     /* What modules do I depend on? */
  109.     struct list_head target_list;

  110.     /* Who is waiting for us to be unloaded */
  111.     struct task_struct *waiter;

  112.     /* Destruction function. */
  113.     void (*exit)(void);

  114.     struct module_ref {
  115.         unsigned int incs;
  116.         unsigned int decs;
  117.     } __percpu *refptr;
  118. #endif

  119. #ifdef CONFIG_CONSTRUCTORS
  120.     /* Constructor functions. */
  121.     ctor_fn_t *ctors;
  122.     unsigned int num_ctors;
  123. #endif
  124. };


struct device_driver :
  1. /**
  2.  * struct device_driver - The basic device driver structure
  3.  * @name:    Name of the device driver.
  4.  * @bus:    The bus which the device of this driver belongs to.
  5.  * @owner:    The module owner.
  6.  * @mod_name:    Used for built-in modules.
  7.  * @suppress_bind_attrs: Disables bind/unbind via sysfs.
  8.  * @of_match_table: The open firmware table.
  9.  * @probe:    Called to query the existence of a specific device,
  10.  *        whether this driver can work with it, and bind the driver
  11.  *        to a specific device.
  12.  * @remove:    Called when the device is removed from the system to
  13.  *        unbind a device from this driver.
  14.  * @shutdown:    Called at shut-down time to quiesce the device.
  15.  * @suspend:    Called to put the device to sleep mode. Usually to a
  16.  *        low power state.
  17.  * @resume:    Called to bring a device from sleep mode.
  18.  * @groups:    Default attributes that get created by the driver core
  19.  *        automatically.
  20.  * @pm:        Power management operations of the device which matched
  21.  *        this driver.
  22.  * @p:        Driver core's private data, no one other than the driver
  23.  *        core can touch this.
  24.  *
  25.  * The device driver-model tracks all of the drivers known to the system.
  26.  * The main reason for this tracking is to enable the driver core to match
  27.  * up drivers with new devices. Once drivers are known objects within the
  28.  * system, however, a number of other things become possible. Device drivers
  29.  * can export information and configuration variables that are independent
  30.  * of any specific device.
  31.  */
  32. struct device_driver {
  33.     const char        *name;
  34.     struct bus_type        *bus;

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

  37.     bool suppress_bind_attrs;    /* disables bind/unbind via sysfs */

  38.     const struct of_device_id    *of_match_table;

  39.     int (*probe) (struct device *dev);
  40.     int (*remove) (struct device *dev);
  41.     void (*shutdown) (struct device *dev);
  42.     int (*suspend) (struct device *dev, pm_message_t state);
  43.     int (*resume) (struct device *dev);
  44.     const struct attribute_group **groups;

  45.     const struct dev_pm_ops *pm;

  46.     struct driver_private *p;
  47. };


struct attribute :
  1. struct attribute {
  2.     const char        *name;
  3.     mode_t            mode;
  4. #ifdef CONFIG_DEBUG_LOCK_ALLOC
  5.     struct lock_class_key    *key;
  6.     struct lock_class_key    skey;
  7. #endif
  8. };


struct driver_attribute :
  1. struct driver_attribute {
  2. struct attribute attr;
  3. ssize_t (*show)(struct device_driver *driver, char *buf);
  4. ssize_t (*store)(struct device_driver *driver, const char *buf,
  5. size_t count);
  6. };


ldd_bus.c
  1. static BUS_ATTR(Version,S_IRUGO,show_bus_version,NULL);
会在 /sys/bus/ldd 目录中生成一个 Version 的目录
  1. 在将lddbus子系统装载到内核和从内核卸载的源码如下:
  2. static int __init ldd_bus_init(void)
  3. {
  4.     int ret;
  5.     ret = bus_register(&ldd_bus_type); /*注册总线,在调用这个函数之后ldd_bus_type 结构体将向内核注册,在/sys/bus中出现ldd文件夹,其中包含两个目录:devices 和 drivers */
  6.     if (ret)
  7.         return ret;
  8.     if (bus_create_file(&ldd_bus_type, &bus_attr_version)) /*添加总线属性,将在/sys/bus/ldd目录中出现version属性文件*/
  9.         printk(KERN_NOTICE "Unable to create version attribute ! \n");
  10.     ret = device_register(&ldd_bus);/*将总线作为设备注册。因为总线也可以是一个设备,比如在S3C2440中SPI总线控制器相对于ARMv7核心来说,其实就是一个外设。调用此函数后,就会在/sys/devices中出现ldd0目录*/
  11.     if (ret)
  12.         printk(KERN_NOTICE "Unable to register ldd0 ! \n");
  13.    
  14.     printk(KERN_NOTICE "Mount lddbus ok !\nBus device is ldd0 !\nYou can see me in sys/module/ , sys/devices/ and sys/bus/ ! \n");
  15.    
  16.     return ret;
  17. }
#tree -AC /sys/module/lddbus/ /sys/devices/ldd0/ /sys/bus/ldd/
/sys/module/lddbus/
├── holders
├── initstate
├── refcnt
└── sections
    ├── __ksymtab
    └── __ksymtab_strings
/sys/devices/ldd0/
├── power
│ └── wakeup
└── uevent
/sys/bus/ldd/
├── devices
├── drivers
├── drivers_autoprobe
├── drivers_probe
└── Version




问题1:驱动是如何加载到总线上的?

答:
1,实现一个 struct ldd_driver 变量:
  1. static    struct ldd_driver    sculld_driver    =
  2. {
  3.     .version    = "$reversion: 2.0 $",
  4.     .module        = THIS_MODULE,
  5.     .driver        =
  6.                  {
  7.                     .name    = "sculld_driver",
  8.                  },
  9. };

2,把实现的这个变量添加到总线上:
  1. /*
  2.      * Register with the driver core.
  3.      */
  4.     register_ldd_driver(&sculld_driver);

3,在  register_ldd_driver(&sculld_driver); 实现如下:
   a)定义驱动的总线类型:
  1. driver->driver.bus    = &ldd_bus_type;
  1. //the bus type
  2. struct bus_type ldd_bus_type =
  3. {
  4.     .name        = "ldd",
  5.     .match        = ldd_match,
  6.     .uevent        = ldd_hotplug,
  7. };
        
      b)注册驱动
  1. ret    = driver_register(&driver->driver);
  1. /**
  2.  * driver_register - register driver with bus
  3.  * @drv: driver to register
  4.  *
  5.  * We pass off most of the work to the bus_add_driver() call,
  6.  * since most of the things we have to do deal with the bus
  7.  * structures.
  8.  */
  9. int driver_register(struct device_driver *drv)
  10. {
  11.     int ret;
  12.     struct device_driver *other;

  13.     BUG_ON(!drv->bus->p);

  14.         //@1@
  15.     if ((drv->bus->probe && drv->probe) ||
  16.      (drv->bus->remove && drv->remove) ||
  17.      (drv->bus->shutdown && drv->shutdown))
  18.         printk(KERN_WARNING "Driver '%s' needs updating - please use "
  19.             "bus_type methods\n", drv->name);

  20.         //@2@
  21.     other = driver_find(drv->name, drv->bus);
  22.     if (other) {
  23.         put_driver(other);
  24.         printk(KERN_ERR "Error: Driver '%s' is already registered, "
  25.             "aborting...\n", drv->name);
  26.         return -EBUSY;
  27.     }

  28.         //@3@
  29.     ret = bus_add_driver(drv);
  30.     if (ret)
  31.         return ret;

  32.        
  33.     ret = driver_add_groups(drv, drv->groups);
  34.     if (ret)
  35.         bus_remove_driver(drv);
  36.     return ret;
  37. }
  38. EXPORT_SYMBOL_GPL(driver_register);
        @1@ : 函数首先是检查device_driver类型的drv对象和其bus域的回调函数是否已经被赋值,
              如果为空,则打印警告。

        @2@ : 检测驱动是否已注册
        @3@ :驱动加载到总线上的核心操作
  1. /**
  2.  * bus_add_driver - Add a driver to the bus.
  3.  * @drv: driver.
  4.  */
  5. int bus_add_driver(struct device_driver *drv)
  6. {
  7.     struct bus_type *bus;
  8.     struct driver_private *priv;
  9.     int error = 0;

  10.     bus = bus_get(drv->bus);
  11.     if (!bus)
  12.         return -EINVAL;

  13.     pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

  14.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  15.     if (!priv) {
  16.         error = -ENOMEM;
  17.         goto out_put_bus;
  18.     }
  19.     klist_init(&priv->klist_devices, NULL, NULL);
  20.     priv->driver = drv;
  21.     drv->p = priv;
  22.     priv->kobj.kset = bus->p->drivers_kset;
  23.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
  24.                  "%s", drv->name);
  25.     if (error)
  26.         goto out_unregister;

  27.     if (drv->bus->p->drivers_autoprobe) {
  28.         error = driver_attach(drv);
  29.         if (error)
  30.             goto out_unregister;
  31.     }
  32.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
  33.     module_add_driver(drv->owner, drv);

  34.     error = driver_create_file(drv, &driver_attr_uevent);
  35.     if (error) {
  36.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",
  37.             __func__, drv->name);
  38.     }
  39.     error = driver_add_attrs(bus, drv);
  40.     if (error) {
  41.         /* How the hell do we get out of this pickle? Give up */
  42.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
  43.             __func__, drv->name);
  44.     }

  45.     if (!drv->suppress_bind_attrs) {
  46.         error = add_bind_files(drv);
  47.         if (error) {
  48.             /* Ditto */
  49.             printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
  50.                 __func__, drv->name);
  51.         }
  52.     }

  53.     kobject_uevent(&priv->kobj, KOBJ_ADD);
  54.     return 0;

  55. out_unregister:
  56.     kobject_put(&priv->kobj);
  57.     kfree(drv->p);
  58.     drv->p = NULL;
  59. out_put_bus:
  60.     bus_put(bus);
  61.     return error;
  62. }
在bus_add_driver()函数中,首先是检查drv->bus,如果为空可立即返回EINVAL(无效的变量),注册失败,
可见bus域必须提前初始化好才行。接下来是对kobj域进行初始化,检查bus域等。
/sys/bus/ldd/drivers/ 目录中创建
sculld_driver 目录
并在
/sys/bus/ldd/drivers/sculld_driver 创建属性文件 uevent,
最后调用add_bind_files()函数

  1. /*
  2.  * Thanks to drivers making their tables __devinit, we can't allow manual
  3.  * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
  4.  */
  5. static int __must_check add_bind_files(struct device_driver *drv)
  6. {
  7.     int ret;

  8.     ret = driver_create_file(drv, &driver_attr_unbind);
  9.     if (ret == 0) {
  10.         ret = driver_create_file(drv, &driver_attr_bind);
  11.         if (ret)
  12.             driver_remove_file(drv, &driver_attr_unbind);
  13.     }
  14.     return ret;
  15. }
/sys/bus/ldd/drivers/sculld_driver 创建属性文件 :bind 和 unbind

     
     c)设置驱动的属性
  1. driver->version_attr.attr.name        = "verSion";
  2. //    driver->version_attr.attr.owner        = driver->module;
  3.     driver->version_attr.attr.mode        = S_IRUGO;
  4.     driver->version_attr.show            = show_version;

  5.     return driver_create_file(&driver->driver,&driver->version_attr);
/sys/bus/ldd/drivers/sculld_driver 创建属性文件 :verSion
#tree -AC /sys/bus/ldd/
/sys/bus/ldd/
├── devices
├── drivers

│ ├── sculld_driver
│ └── sculld
│ ├── bind
│ ├── unbind
│ └── verSion
├── drivers_autoprobe
├── drivers_probe
└── Version




问题2:设备是如何加载到总线上的?

答:
sculld.c 中修改如下:
  1. static    ssize_t    sculld_show_dev(struct device *ddev,struct device_attribute *attr,char *buf)
  2. {
  3.     struct sculld_dev    *dev = dev_get_drvdata(ddev);
  4.     return print_dev_t(buf,dev->cdev.dev);
  5. //    return 0;
  6. }

  7. static    DEVICE_ATTR(dev,S_IRUGO,sculld_show_dev,NULL);

  8. static    void    sculld_register_dev(struct sculld_dev *dev,int index)
  9. {
  10.     sprintf(dev->devname,"sculld%d",index);
  11.     dev->ldev.name    = dev->devname;
  12.     dev->ldev.driver= &sculld_driver;
  13.     dev_set_drvdata(&dev->ldev.dev,dev);

  14. printk(KERN_NOTICE"\nsculld%i device\n",index);
  15.     register_ldd_device(&dev->ldev);

  16. printk(KERN_NOTICE"\nsculld%i create\n",index);
  17.     device_create_file(&dev->ldev.dev,&dev_attr_dev);
  18. }





问题3:驱动和设备是如何匹配上的?

答:


待续。。。





相关文章

  • 第十四章--Linux设备模型
            本章将对设备模型从下向上进行讲述. 一.Kobject.kset和子系统         kobject是组成设备模型的基本结构.现在kobject结构所能处理的任务以及它所支持的代码包括:         1.对象的引用计 ...
  • 随着互联网技术的迅猛发展,现在逐步渐入大数据.云计算.虚拟技术和人工智能时代,技术为王的现象越来越明显了.现下网站规模越来越大.架构越来越复杂,企业对于运维工程师.架构师的要求也越来越急迫,特别是对有经验的优秀运维人才需求量大,而运维工程师 ...
  • 随着互联网技术的迅猛发展,现在逐步渐入大数据.云计算.虚拟技术和人工智能时代,技术为王的现象越来越明显了.现下网站规模越来越大.架构越来越复杂,企业对于运维工程师.架构师的要求也越来越急迫,特别是对有经验的优秀运维人才需求量大,而运维工程师 ...
  • 随着互联网技术的迅猛发展,现在逐步渐入大数据.云计算.虚拟技术和人工智能时代,技术为王的现象越来越明显了.现下网站规模越来越大.架构越来越复杂,企业对于运维工程师.架构师的要求也越来越急迫,特别是对有经验的优秀运维人才需求量大,而运维工程师 ...
  • 一.板级设备扫描         针对上一篇博客最后的i2c_scan_static_board_info(adap)函数处,首先先看下在系统启动的时候板级设备的注册.         针对我现在使用的开发板,对于I2C设备注册程序如下: ...
  • 《循序渐进Linux》第二版即将出版发行(附封面)
    从<循序渐进Linux>第一版发布,到现在已经近6年了,6年的时间,技术发生了很大的变化,Linux系统的内核版本从2.6.9(RHEL4.x)已经更新到了现在的3.10(Centos7.x),第一版中的部分内容已经陈旧,Lin ...

2020 unjeep.com webmaster#unjeep.com
12 q. 0.016 s.
京ICP备10005923号