SDIO总线:
static struct bus_type sdio_bus_type = { .name = "sdio", .dev_attrs = sdio_dev_attrs, .match = sdio_bus_match, .uevent = sdio_bus_uevent, .probe = sdio_bus_probe, .remove = sdio_bus_remove, .pm = SDIO_PM_OPS_PTR, };一条总线上有一个设备链表klist_devices,记录挂在此bus上的device;一个驱动链表(待查)klist_drivers,记录挂在此bus上的driver。
当注册新设备或者新驱动的时候,遍历驱动/设备链表,总线上的match回调函数得到调用进行驱动/设备的匹配。纯粹的叙述总显得空洞,那就简单看下设备/驱动的注册流程。
注册device:
int device_add(struct device *dev) -->void bus_probe_device(struct device *dev) ---->int device_attach(struct device *dev) ------>int __device_attach(struct device_driver *drv, void *data) { if (!driver_match_device(drv, dev)) return 0; return driver_probe_device(drv, dev); } -------->int driver_probe_device(struct device_driver *drv, struct device *dev) ---------->int really_probe(struct device *dev, struct device_driver *drv) { if (dev->bus->probe) { ret = dev->bus->probe(dev); } 注册driver:
int driver_register(struct device_driver *drv) -->int bus_add_driver(struct device_driver *drv) ---->int driver_attach(struct device_driver *drv) ------>int __driver_attach(struct device *dev, void *data) { if (!driver_match_device(drv, dev)) return 0; driver_probe_device(drv, dev); } -------->int driver_probe_device(struct device_driver *drv, struct device *dev) ----------> int really_probe(struct device *dev, struct device_driver *drv) { if (dev->bus->probe) { ret = dev->bus->probe(dev); }看至此有没有想起一个词叫做”殊途同归“?如果device没有绑定驱动,那么先match一下;match成功后才进行probe,否则直接返回0。
driver_match_device是一个inline函数,实现:
static inline int driver_match_device(struct device_driver *drv, struct device *dev) { return drv->bus->match ? drv->bus->match(dev, drv) : 1; }
对于sdio总线,match实现如下:
static int sdio_bus_match(struct device *dev, struct device_driver *drv) { struct sdio_func *func = dev_to_sdio_func(dev); struct sdio_driver *sdrv = to_sdio_driver(drv); if (sdio_match_device(func, sdrv)) return 1; return 0; }dev_to_sdio_func/to_sdio_driver,根据结构体中某个成员获取整个结构体(的地址),最终都是封装的宏container_of(ptr, type, member):
/** * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * */ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})它就像是一个魅影,出现在 kernel的任何子系统中,在2.6.38的源码下搜索结果:
Referenced in 2338 files container_of宏的原理还是很简单的:在C/C++中,一个结构体中的成员偏移在编译时地址就固定下来了,所以成员的地址减去它的offset就是结构体的地址。
Let's go on:
static const struct sdio_device_id *sdio_match_device(struct sdio_func *func, struct sdio_driver *sdrv) { const struct sdio_device_id *ids; ids = sdrv->id_table; if (ids) { while (ids->class || ids->vendor || ids->device) { if (sdio_match_one(func, ids)) return ids; ids++; } } return NULL; } id_table成员由driver的提供方赋值,第5行就是去除该值,用于接下来的匹配。sdio总线match时用的是sdio_device_id类型数据:/* SDIO */ #define SDIO_ANY_ID (~0) struct sdio_device_id { __u8 class; /* Standard interface or SDIO_ANY_ID */ __u16 vendor; /* Vendor or SDIO_ANY_ID */ __u16 device; /* Device ID or SDIO_ANY_ID */ kernel_ulong_t driver_data /* Data private to the driver */ __attribute__((aligned(sizeof(kernel_ulong_t)))); };之前都是准备工作,所谓磨刀不误砍柴工而已,该砍柴了:
static const struct sdio_device_id *sdio_match_one(struct sdio_func *func, const struct sdio_device_id *id) { if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class) return NULL; if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor) return NULL; if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device) return NULL; return id; }如果class/vendor/device某一项不为SDIO_ANY_ID就和sdio_func中的对应项进行比对。sdio_match_device某次返回结果不为NULL,结束匹配操作返回OK。 之前说过,match成功后进行probe。
