分类:
2008-09-08 11:13:02
static struct bus_type mmc_bus_type = {
.name = "mmc",
.dev_attrs = mmc_dev_attrs,
.match = mmc_bus_match,
.uevent = mmc_bus_uevent,
.probe = mmc_bus_probe,
.remove = mmc_bus_remove,
.suspend = mmc_bus_suspend,
.resume = mmc_bus_resume,
};
这里,我们主要关注mmc_bus_match与mmc_bus_probe,此两函数将要在device_register和driver_register向总线注册设备的时候被调用。
static int mmc_bus_match(struct device *dev, struct device_driver *drv)
{
struct mmc_card *card = dev_to_mmc_card(dev);
return !mmc_card_bad(card);
}
#define mmc_card_bad(c) ((c)->state&(MMC_STATE_BAD)
可见,对于mmc总线,mmc_bus_match是通过返回struct mmc_card中的状态标示state位来实现的。
static int mmc_bus_probe(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = dev_to_mmc_card(dev);
return drv->probe(card);
}
在使用bus_register之后,我们可以在sysfs的/sys/bus目录里看到它
static struct class mmc_host_class = {
.name = "mmc_host",
.dev_release = mmc_host_classdev_release,
};
class_register之后,在/sys/class目录下将出现mmc_host目录
接下来,我们看mmc_block.c,还是从初始化函数mmc_blk_init开始分析
static int __init mmc_blk_init(void)
{
int res = -ENOMEM;
res = register_blkdev(major, "mmc");
if (res < 0) {
printk(KERN_WARNING "Unable to get major %d for MMC media: %d\n",
major, res);
goto out;
}
if (major == 0)
major = res;
return mmc_register_driver(&mmc_driver);
out:
return res;
}
在mmc_blk_init中, register_blkdev(major, "mmc")的作用是注册一个块设备。如果传递的major为0,这内核将分派一个新的主设备号给设备。
register_blkdev的功能比较少,一是动态分配设备号,二是在/proc/devices中创建一个入口项 。故通过它之后,系统还是不能使用块设备的。
接着我们看
return mmc_register_driver(&mmc_driver);
mmc_register_driver在mmc_sysfs.c中定义:
static struct mmc_driver mmc_driver = {
.drv = {
.name = "mmcblk",
},
.probe = mmc_blk_probe,
.remove = mmc_blk_remove,
.suspend = mmc_blk_suspend,
.resume = mmc_blk_resume,
};
int mmc_register_driver(struct mmc_driver *drv)
{
drv->drv.bus = &mmc_bus_type;
return driver_register(&drv->drv);
}
这两句代码比较好理解吧。在注册一个struct driver之前,都要先设置它的bus,类似的,在platform_driver_register中我们也可所以看到:
drv->driver.bus=&platform_bus_type
driver_register将到相应总线mmc_bus_type上去搜索相应设备。找到设备后就设置dev->driver=drv,并调用mmc_bus_type总线的probe函数被调用,即mmmc_bus_probe函数.
我们跟踪driver_register(&drv->drv),它会调应bus_add_driver。
int bus_add_driver(struct device_driver *drv)
{
...
...
error = kobject_set_name(&drv->kobj, "%s", drv->name);
if (error)
goto out_put_bus;
drv->kobj.kset = &bus->drivers;
if ((error = kobject_register(&drv->kobj)))
goto out_put_bus;
error = driver_attach(drv);
...
...
}
在调用kobject_register之后,我们可以在/sys/bus/mmc/driver目录下看到mmcblk文件driver_attach函数会遍历相应总线(mmc_bus_type)上的dev,对这些dev执行总线的match函数(mmc_bus_match)。如果match成功,它会调用mmc_bus_type总线的probe函数mmc_bus_probe(如果总线的probe存在的话).我们在以上走过的流程中可以看到,我们并没有向总线添加任何设备,故mmc_bus_probe是不会调用的。但相应的driver已经注册到系统了。
那么,现在mmc_block.c中的分析就先暂时到此为止。。。不过,等会儿我们还会继续回到这个文件的。。
----------------------------------未完待续-----------------------------------