Chinaunix首页 | 论坛 | 博客
  • 博客访问: 60208
  • 博文数量: 35
  • 博客积分: 2000
  • 博客等级: 大尉
  • 技术积分: 390
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-23 13:36
文章分类

全部博文(35)

文章存档

2011年(1)

2010年(1)

2009年(33)

我的朋友
最近访客

分类: LINUX

2009-04-28 19:10:38

 

 还没有弄明白,先翻译一部分 

Driver Binding  驱动绑定

Driver binding is the process of associating a device with a device driver that can control it. Bus

驱动绑定就是把设备和能控制该设备的设备驱动相关联。 总线驱动已经自行处理了这个部分,因为总线有专门的结构来代替设备和驱动。

drivers have typically handled this because there have been bus-specific structures to represent the devices and the drivers.

With generic device and device driver structures, most of the binding can take place using common code.

利用通用的设备和设别驱动数据结构,大部分的绑定可以通过通用代码实现。

Bus ~~~总线

The bus type structure contains a list of all devices that are on that bus type in the system.

总线类型数据结构包含了一系列的设备,这些设备在系统中是挂载该总线上的

 When device_register is called for a device, it is inserted into the end of this list.

当设备注册函数被调用的时候,需要挂载的设别会插入到总线类型数据内设备列表的末尾

The bus object also contains a list of all drivers of that bus type. When driver_register is called for

总线对象同时包含了一个符合这种总线类型的驱动列表。当驱动注册函数被调用时,需要注

a driver, it is inserted at the end of this list. These are the two events which trigger driver binding.

注册的驱动会插入到这个列表的末尾。当绑定总线驱动的时候这两样会发生

device_register ~~~~~~~~~~~~~~~设备注册

 

When a new device is added, the bus's list of drivers is iterated over to find one that supports it. In

当一个新的设备需要加入,总线会查阅它所维护的驱动列表以发现支持该设备的驱动。

order to determine that, the device ID of the device must match one of the device IDs that the

为了实现匹配,设备的ID必须与驱动所支持的设备ID相符

 driver supports. The format and semantics for comparing IDs is bus-specific. Instead of trying to

比较ids的格式和语法是针对具体的bus

 derive a complex state machine and matching algorithm, it is up to the bus driver to provide a callback to compare a device against the IDs of a driver.

这种方法的好处就是通过提供给bus driver 一个设备号让它去比较设备驱动支持的设备号来代替那些复杂的状态操作和数据计算

The bus returns 1 if a match was found; 0 otherwise.

如果发现驱动就会返回1,否则返回0

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

If a match is found, the device's driver field is set to the driver and the driver's probe callback is

如果必配的发现了,设备的驱动域就会被设置成找到的驱动,并且调用driver’s probe callback

called. This gives the driver a chance to verify that it really does support the hardware, and that it's

这个步骤的作用是让驱动程序有机会确认真的支持这个硬件设备,并且置状态为工作

in a working state.

Device Class ~~~~~~~~~~~~设备类型

Upon the successful completion of probe, the device is registered with the class to which it

基于已经成功的进行了探查,这个设备被注册到正确的类中。

belongs. Device drivers belong to one and only one class, and that is set in the driver's devclass

设备驱动属于一个且仅一个类,并且在驱动的devclass中设置。

field. devclass_add_device is called to enumerate the device within the class and actually register

it with the class, which happens with the class's register_dev callback.

register_dev函数被调用以后,devclass_add_device函数将被调用来添加设备到类中并用这个类注册设备,

 

NOTE: The device class structures and core routines to manipulate them are not in the mainline kernel, so the discussion is still a bit speculative. 不在内核主线中操作The device class structures and core routines ,还需进一部的探讨  

Driver ~~~~~~

When a driver is attached to a device, the device is inserted into the driver's list of devices.

当驱动被关联到设备,设备就会被插入到驱动的设备列表

sysfs ~~~~~系统文件系统

A symlink is created in the driver's 'devices' directory that points to the device's directory in the physical hierarchy.

一个指向物理结构中设备目录的符号连接会在驱动的设备域创建目录

A directory for the device is created in the class's directory. A symlink is created in that directory that points to the device's physical location in the sysfs tree.

一个设备目录在类目录创建。一个指向设备物理位置的符号连接在该目录创建

A symlink can be created (though this isn't done yet) in the device's physical directory to either its class directory, or the class's top-level directory. One can also be created to point to its driver's directory also. 这个就不用翻译了

driver_register ~~~~~~~~~~~~~~~驱动注册

The process is almost identical for when a new driver is added. The bus's list of devices is iterated

当一个新的驱动被加入的时候步骤基本是确定的。总线的设备列表会被查阅以发现相匹配的

over to find a match. Devices that already have a driver are skipped. All the devices are iterated

那些已经有有驱动的设备将会被跳过。同时应该绑定所有匹配的设备到驱动

 over, to bind as many devices as possible to the driver.

Removal ~~~~~~~删除

When a device is removed, the reference count for it will eventually go to 0. When it does, the

但一个设备被移除,设备的应用次数会被设为0.当一处设备的时候,驱动的remove callback会被调用

 remove callback of the driver is called. It is removed from the driver's list of devices and the

这个会将设备从驱动的设备列表移除,并且对驱动的引用会剪掉一。

reference count of the driver is decremented. All symlinks between the two are removed.

所有的建立在两者之间的符号链接都会被移除

When a driver is removed, the list of devices that it supports is iterated over, and the driver's

当一个驱动被移除,驱动所支持的设备将会被遍历,并且driver’s renove callback会被调用一次针对每一个设备

remove callback is called for each one. The device is removed from that list and the symlinks removed. 设备将会从表中移除,符号链接也会被移除。

 

 

 

 

 

 

 

 

 

 

 

Bus Types  总线类型

Definition ~~~~~~~~~~

struct bus_type {

char               * name;

       struct subsystem    subsys;

       struct kset             drivers;

       struct kset             devices;

       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           (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);

int           (*suspend)(struct device * dev, pm_message_t state);

       int           (*resume)(struct device * dev);

 };

 

 

int      bus_register(struct bus_type * bus);

 

Declaration ~~~~~~~~~~~说明

Each bus type in the kernel (PCI, USB, etc) should declare one static object of this type. They

每一种总线类型都应该声明一个静态的对象。

must initialize the name field, and may optionally initialize the match callback.

他们必须初始化名称域,并且可以有选择的初始化匹配调用函数。

struct bus_type pci_bus_type = { .name      = "pci",                      这是一个例子

                           .match      = pci_bus_match, };

The structure should be exported to drivers in a header file:

总线类型结构体应该被引用到驱动的头文件里

extern struct bus_type pci_bus_type;         引用方法

Registration ~~~~~~~~~~~~注册总线

When a bus driver is initialized, it calls bus_register. This initializes the rest of the fields in the bus

当一个总线驱动被初始化的时候,就会调用总线注册函数。它会初始化总线对象的其他域

 object and inserts it into a global list of bus types. Once the bus object is registered, the fields in

并且插入这个对象到一个全局型的总线数据列表。一旦总线对象被注册,它的内部数据就可以被驱动使用。

 it are usable by the bus driver.

Callbacks ~~~~~~~~~

match(): Attaching Drivers to Devices ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~这个函数用来匹配驱动和设备

The format of device ID structures and the semantics for comparing them are inherently

匹配所依靠的设备id结构和语法是bus-specific

bus-specific. Drivers typically declare an array of device IDs of devices they support that reside in

驱动典型的声明一串它所支持的设备id并放在一个bus-specific驱动结构里

 a bus-specific driver structure.

The purpose of the match callback is provide the bus an opportunity to determine if a particular

Match calback的主要目的是提供给总线有机会去确定特定的驱动支持特定的设备,主要是通过对比设备di与驱动所支持的id.

 driver supports a particular device by comparing the device IDs the driver supports with the device ID of a particular device, without sacrificing bus-specific functionality or type-safety.

不用通过(没看懂)

When a driver is registered with the bus, the bus's list of devices is iterated over, and the match

当一个针对一个总线的驱动被注册的时候,总线的设备就会被遍历,通过调用match callback

callback is called for each device that does not have a driver associated with it.

发现还没有被驱动的设备

Device and Driver Lists ~~~~~~~~~~~~~~~~~~~~~~~设备和驱动列表

The lists of devices and drivers are intended to replace the local lists that many buses keep.

设备和驱动列表的主要是用来代替总线所保存的列表

They are lists of struct devices and struct device_drivers, respectively. Bus drivers are free to use

这个列表设备类型列表和设备驱动列表。总线驱动可以自由的使用这个列表当他们请求的时候

the lists as they please, but conversion to the bus-specific type may be necessary.

但是需要将这个列表转化成bus-specific的形式

The LDM core provides helper functions for iterating over each list.

Ldm提供比遍历每一个列表的帮助功能

int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, int (*fn)(struct device *, void *));  设备表遍历函数

int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, void * data, int (*fn)(struct device_driver *, void *));      驱动表遍历函数

These helpers iterate over the respective list, and call the callback for each device or driver in the list.

这些函数遍历各个列表,并对每个设备和驱动调用callback 函数

All list accesses are synchronized by taking the bus's lock (read currently).

所有列表的进入需要通过使用总线锁来现实同步

The reference count on each object in the list is incremented before the callback is called;

callback被调用以前在列表中对每个对象的引用的次数会减少

it is decremented after the next object has been obtained. The lock is not held when calling the callback.

引用次数会在下一个对象获得列表的时候增加。锁不能被获得在调用callback的时候。

sysfs ~~~~~~~~ There is a top-level directory named 'bus'. 文件系统中有个顶端目录叫bus

Each bus gets a directory in the bus directory, along with two default directories: 默认有设备目录和驱动目录

       /sys/bus/pci/

       |-- devices

       `-- drivers

Drivers registered with the bus get a directory in the bus's drivers directory:驱动被注册以后会在驱动目录里显示

       /sys/bus/pci/

       |-- devices

       `-- drivers |-- Intel ICH

           |-- Intel ICH Joystick

           |-- agpgart

           `-- e100

Each device that is discovered on a bus of that type gets a symlink in the bus's devices directory to the device's directory in the physical hierarchy:在设备目录里的是一些对设备实际位置的符号链接

       /sys/bus/pci/

       |-- devices

       |   |-- 00:00.0 -> ../../../root/pci0/00:00.0

       |   |-- 00:01.0 -> ../../../root/pci0/00:01.0

       |   `-- 00:02.0 -> ../../../root/pci0/00:02.0

       `-- drivers

Exporting Attributes ~~~~~~~~~~~~~~~~~~~~ 引进属性

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

 };

Bus drivers can export attributes using the BUS_ATTR macro that works similarly to the DEVICE_ATTR macro for devices.

总线驱动可以通过使用宏BUS_ATTRDEVICE_ATTR来引进属性

For example, a definition like this:

static BUS_ATTR(debug,0644,show_debug,store_debug);这个可以生成bus_attr_debug

is equivalent to declaring:

static bus_attribute bus_attr_debug;

This can then be used to add and remove the attribute from the bus's sysfs directory using:

可以通过使用如下函数增加和移除总线文件目录的属性

int bus_create_file(struct bus_type *, struct bus_attribute *); void bus_remove_file(struct bus_type *, struct bus_attribute *);

 

 

 

 

 

 

 

 

 

 

Device Classes 设备类

Introduction ~~~~~~~~~~~~ A device class describes a type of device, like an audio or network device. The following device classes have been identified:

一个设备类用来描述一个类型的设备,想声音和网络设备。下面的设备类已经被系统确定。

Each device class defines a set of semantics and a programming interface that devices of that class adhere to.

每一类设备都定义了该类设备所遵循的一套语法和编程接口

 Device drivers are the implemention of that programming interface for a particular device on a particular bus.

设备驱动就是用来完善特定总线的特定设备的这个编程接口

Device classes are agnostic with respect to what bus a device resides on.

设备类并不知道自己该放在哪个总线上

Programming Interface ~~~~~~~~~~~~~~~~~~~~~ The device class structure looks like:

typedef int (*devclass_add)(struct device *);

typedef void (*devclass_remove)(struct device *);

struct device_class {

char               * name;

       rwlock_t        lock;

       u32                devnum;

       struct list_head       node;

       struct list_head       drivers;

       struct list_head       intf_list;

       struct driver_dir_entry   dir;

       struct driver_dir_entry   device_dir;

       struct driver_dir_entry   driver_dir;

       devclass_add         add_device;

       devclass_remove           remove_device;

 };

A typical device class definition would look like: 典型的定义方式

struct device_class input_devclass = { .name             = "input",

                               .add_device      = input_add_device,

 .remove_device = input_remove_device, };

Each device class structure should be exported in a header file so it can be used by drivers, extensions and interfaces. 设备类应该放在文件中,以方便驱动,扩展,接口使用

Device classes are registered and unregistered with the core using:

设备类的注册和移除

int devclass_register(struct device_class * cls);

void devclass_unregister(struct device_class * cls);

Devices ~~~~~~~ As devices are bound to drivers, they are added to the device class that the

由于设备要和驱动绑定,所以设备会加到某类驱动属于的设备类

 driver belongs to. Before the driver model core, this would typically happen during the driver's

一旦设备完成初始化,设备就会在调用驱动的探测函数完成这项工作,。。

 probe() callback, once the device has been initialized. It now happens after the probe() callback finishes from the core.

The device is enumerated in the class. Each time a device is added to the class, the class's devnum

设备在类中就会被列出来。每次一个设备被加到类中,类的设备数量域就会增加并把这个量分给设备。

 field is incremented and assigned to the device. The field is never decremented, so if the device is

这个变量是不会减少的,因此在移除设备然后重新挂载的时候设备会收到一个不同的值。

 removed from the class and re-added, it will receive a different enumerated value.

The class is allowed to create a class-specific structure for the device and store it in the device's class_data pointer.

设备类允许创建class-specific这个结构体,并把这个变量的指针存到设备的class_data

There is no list of devices in the device class. Each driver has a list of devices that it supports.

在设备类中没有设备列表。每一个驱动有一个它所支持的设备列表

The device class has a list of drivers of that particular class.

设备类维持的一个是支持该类设备的驱动的列表。

To access all of the devices in the class, iterate over the device lists of each driver in the class.

进入类的设备的方法是:遍历类的驱动列表中每个驱动所维持的设备列表

Device Drivers ~~~~~~~~~~~~~~ Device drivers are added to device classes when they are registered with the core.

当注册设备驱动的时候内核会把它加到设备类中

A driver specifies the class it belongs to by setting the struct device_driver::devclass field.

个驱动通过设定结构体device_driverdevclas域来确定他所属于的设备类。

sysfs directory structure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There is a top-level sysfs directory named 'class'. 目录结构

Each class gets a directory in the class directory, along with two default subdirectories:每个类目录下会有两个默认的分支目录

        class/

        `-- input |-- devices

            `-- drivers

Drivers registered with the class get a symlink in the drivers/ directory that points to the driver's directory (under its bus directory):一旦注册驱动在类的驱动目录会建立一个设备的驱动的符号连接指向驱动实际所在的目录

   class/

   `-- input |-- devices

       `-- drivers `-- usb:usb_mouse -> ../../../bus/drivers/usb_mouse/

Each device gets a symlink in the devices/ directory that points to the device's directory in the physical hierarchy:每一个设备目录下会有一个符号链接指向设备所在的真正目录

   class/

   `-- input |-- devices

       |   `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/

       `-- drivers

Exporting Attributes ~~~~~~~~~~~~~~~~~~~~

 struct devclass_attribute {

struct attribute        attr;

          ssize_t (*show)(struct device_class *, char * buf, size_t count, loff_t off);

ssize_t (*store)(struct device_class *, const char * buf, size_t count, loff_t off);

};

Class drivers can export attributes using the DEVCLASS_ATTR macro that works similarly to the DEVICE_ATTR macro for devices. For example, a definition like this:

static DEVCLASS_ATTR(debug,0644,show_debug,store_debug);

is equivalent to declaring:

static devclass_attribute devclass_attr_debug;

The bus driver can add and remove the attribute from the class's sysfs directory using:

总线驱动可以增加和移除类的目录属性通过使用如下的函数

int devclass_create_file(struct device_class *, struct devclass_attribute *);

void devclass_remove_file(struct device_class *, struct devclass_attribute *);

In the example above, the file will be named 'debug' in placed in the class's directory in sysfs.

上面的例子会增加一个名叫 debug 的目录在系统文件系统的class

Interfaces ~~~~~~~~~~ There may exist multiple mechanisms for accessing the same device of a particular class type. 可能存在很多种机制来进入一个特定类的同一个设备

Device interfaces describe these mechanisms. 设备的接口描述了这种机制

When a device is added to a device class, the core attempts to add it to every interface that is registered with the device class.

当一个设备被加到设备类,系统内核会试着把它加到设备类所注册的所有接口上

 

 

 

 

 

 

 

 

The Basic Device Structure ~~~~~~~~~~~~~~~~~~~~~~~~~~

struct device {

 struct list_head g_list;

        struct list_head node;

        struct list_head bus_list;

        struct list_head driver_list;

        struct list_head intf_list;

        struct list_head children;

        struct device   * parent;

        char    name[DEVICE_NAME_SIZE];

        char    bus_id[BUS_ID_SIZE];

        spinlock_t      lock;

        atomic_t        refcount;

        struct bus_type * bus;

        struct driver_dir_entry dir;

     u32         class_num;

        struct device_driver *driver;

        void            *driver_data;

        void            *platform_data;

        u32             current_state;

        unsigned char *saved_state;

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

Fields ~~~~~~ g_list:     Node in the global device list.

node:       Node in device's parent's children list.

bus_list: Node in device's bus's devices list.

driver_list:   Node in device's driver's devices list.

intf_list:     List of intf_data. There is one structure allocated for each interface that the device supports.

children:      List of child devices.

parent:        *** FIXME ***

name:             ASCII description of device. Example: " 3Com Corporation 3c905 100BaseTX [Boomerang]"

bus_id:           ASCII representation of device's bus position. This field should be a name unique across all devices on the

              bus type the device belongs to.

              Example: PCI bus_ids are in the form of

              :.

              This name is unique across all PCI devices in the system.

lock:              Spinlock for the device.

refcount:      Reference count on the device. 设备的引用次数

bus:        Pointer to struct bus_type that device belongs to.设备所属于的总线

dir:          Device's sysfs directory.                      设备的目录

class_num:     Class-enumerated value of the device.设备在注册时获得的累枚举量

driver:            Pointer to struct device_driver that controls the device. 驱动

driver_data:   Driver-specific data.                     驱动的数据区

platform_data: Platform data specific to the device.  端口映射,引脚功能等

              Example:  for devices on custom boards, as typical of embedded and SOC based hardware, Linux often uses platform_data to point

              to board-specific structures describing devices and how they

              are wired.  That can include what ports are available, chip variants, which GPIO pins act in what additional roles, and so

              on.  This shrinks the "Board Support Packages" (BSPs) and minimizes board-specific #ifdefs in drivers.

current_state: Current power state of the device.设备上电没有

saved_state:   Pointer to saved state of the device. This is usable by the device driver controlling the device.设备驱动控制设备的时候要用到的设备状态

release:       Callback to free the device after all references have gone away. This should be set by the allocator of the 释放设备

              device (i.e. the bus driver that discovered the device).

Programming Interface ~~~~~~~~~~~~~~~~~~~~~编程接口

 The bus driver that discovers the device uses this to register the device with the core:

发现设备的总线驱动使用这个结构向内核注册设备

int device_register(struct device * dev);

The bus should initialize the following fields:总线应该初始化下列域

    - parent 设备的父节点

    - name  设备的名字

    - bus_id 设备的 位置

    - bus    总线

A device is removed from the core when its reference count goes to0.

如果一个设备的引用数降到零内核就从内核中移除

 The reference count can be adjusted using:

struct device * get_device(struct device * dev);

void put_device(struct device * dev);

get_device() will return a pointer to the struct device passed to it if the reference is not already 0 (if it's in the process of being removed already).

A driver can access the lock in the device structure using:

void lock_device(struct device * dev); 上锁

void unlock_device(struct device * dev);开锁

Attributes ~~~~~~~~~~

struct device_attribute {

 struct attribute        attr;

        ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);

ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off); };

Attributes of devices can be exported via drivers using a simple procfs-like interface.

Please see Documentation/filesystems/sysfs.txt for more information on how sysfs works.

Attributes are declared using a macro called DEVICE_ATTR:

#define DEVICE_ATTR(name,mode,show,store)

Example:

DEVICE_ATTR(power,0644,show_power,store_power);

This declares a structure of type struct device_attribute named 'dev_attr_power'. This can then be added and removed to the device's directory using:

int device_create_file(struct device *device, struct device_attribute * entry); void device_remove_file(struct device * dev, struct device_attribute * attr);

Example:

device_create_file(dev,&dev_attr_power); device_remove_file(dev,&dev_attr_power);

The file name will be 'power' with a mode of 0644 (-rw-r--r--).

 

 

 

 

 

 

 

 

 

 

 

 

阅读(397) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~