内核(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)
括号里的都是全局变量