内核(linux-2.6.24)有一个大的框架来管理总线,外设及其驱动。
看外设驱动代码时,明白了这个框架,可以很方便的找到需要看的函数。
1.数据结构这个框架涉及到3个比较重要的数据结构:
struct bus_type 用来描述总线
struct device 用来描述设备
struct device_driver 用来描述设备驱动
有如下拓扑图
内核中可以有很多的总线
bus_type 总线
bus_type上可以有很多的设备
device 每个设备
device都有它所对应的驱动
device_driver- struct bus_type { //…..省略一些成员
-
const char * name;
-
struct kset drivers;
-
struct kset devices;
-
-
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);
-
unsigned int drivers_autoprobe:1;
-
};
-
-
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;
-
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
-
-
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 device_driver { //…..省略一些成员
-
const char * name;
-
struct bus_type * bus;
-
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);
-
};
按照面向对象的思想,
bus_type虚基类,子类包括 platform_bus_type,mdio_bus_type,i2c_bus_type,pci_bus_type等
device是虚基类,子类包括 platform_device, phy_device, i2c_client, pci_device等
device_driver虚基类,子类有platform_driver, phy_driver,i2c_driver, pci_driver等
2.API框架有几个关键API:
bus_register(stuct bus_type* bus) 用来注册一条总线bus
device_register(struct device *dev) 把dev加到bus的设备列表中去
driver_register(stuct device_driver *drv)
1. 遍历bus上所有的dev,调用 drv->match(dev,drv) 对drv与dev进行比对
2. 比对成功后调用 dev->bus->probe(dev) 或 drv->probe(dev)
3. 把驱动drv加入到bus的驱动列表中去
4. 绑定drv和dev
为了便于使用,内核针对不同总线,对上述API进行了包装,衍生出了另外一批API:
platform_driver_register
platform_device_register
phy_driver_register
mdiobus_register
下面讲将这3个API
- bus_register(struct bus_type *bus)
-
//没啥说的,此函数最重要一点就是 bus->drivers_autoprobe=1
- driver_register(struct device_driver *drv)
-
--》bus_add_driver(drv)
-
//若bus->drivers_autoprobe = 1
-
--》driver_attach(drv)
-
//遍历bus下所有dev,调用
-
--》__driver_attach(dev,drv)
-
--》driver_probe_device(drv,dev)
-
//调用 bus_type.match(dev, drv),如果比对成功就执行
-
--》really_probe(dev,drv)
-
//调用 bus->probe(dev) 或 drv->probe(dev)
3.总线的注册所有总线的注册几乎内核启动过程时完成的。
start_kernel()
--》rest_init()
--》kernel_init()
--》do_basic_setup()
--》do_initcalls()
--》platform_bus_init()--》bus_register(&
platform_bus)
--》mdio_bus_init() --》bus_register(&
mdio_bus_type)
--》i2c_init() --》bus_register(&
i2c_bus_type)
粉红色的都是全局变量
阅读(1052) | 评论(0) | 转发(0) |