mmc流程
2014-02-25 15:36
267 查看
看mmc之前先看看mmc在Linux中的位置
图片来自:http://free-electrons.com/doc/block_drivers.pdf
从上图可以看出,MMC与SCSI,IDE一样都属于block driver
上面这张图清晰的描述了mmc subsystem的结构,接下来我们分开来看
drivers/mmc/host/ 下面存放mmc host driver, 这些driver完成芯片的初始化之后会调用mmc_add_host向mmc core层注册这个host.
mmc_add_host (core/host.c)
mmc_start_host (core/core.c)
mmc_detect_change (core/core.c)
mmc_rescan (core/core.c)
mmc_rescan_try_freq (core/core.c)
mmc_attach_sd (core/sd.c): starting point for SD card init
mmc_sd_init_card (core/sd.c)
mmc_alloc_card (core/bus.c)
mmc_add_card (core/bus.c)
device_add
这个调用关系中,主要是mmc_alloc_card和mmc_add_card
可以看到,第336行指定bus mmc_bus_type
这样当mmc_add_card调用device_add的时候,根据linux device driver模型,会自动去找bus上对应的driver。
那首先会调用match去判断是否匹配
这里直接return 1,那接下来会调用mmc_bus_probe
从mmc_bus_probe的实现可以看出,会调用对应driver的probe函数
这个driver在mmc/card/block.c中注册,到这里,上图中host和core基本介绍完了
我们先来看 mmc_register_driver
可以看到bus是mmc_bus_type,和刚刚的mmc_add_card中添加的device是同一个bus,这样的话device添加的时候就调用到了这个driver的probe
mmc_blk_probe
图片来自:http://free-electrons.com/doc/block_drivers.pdf
从上图可以看出,MMC与SCSI,IDE一样都属于block driver
上面这张图清晰的描述了mmc subsystem的结构,接下来我们分开来看
drivers/mmc/host/ 下面存放mmc host driver, 这些driver完成芯片的初始化之后会调用mmc_add_host向mmc core层注册这个host.
mmc_add_host (core/host.c)
mmc_start_host (core/core.c)
mmc_detect_change (core/core.c)
mmc_rescan (core/core.c)
mmc_rescan_try_freq (core/core.c)
mmc_attach_sd (core/sd.c): starting point for SD card init
mmc_sd_init_card (core/sd.c)
mmc_alloc_card (core/bus.c)
mmc_add_card (core/bus.c)
device_add
这个调用关系中,主要是mmc_alloc_card和mmc_add_card
320 /* 321 * Allocate and initialise a new MMC card structure. 322 */ 323 struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) 324 { 325 struct mmc_card *card; 326 327 card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); 328 if (!card) 329 return ERR_PTR(-ENOMEM); 330 331 card->host = host; 332 333 device_initialize(&card->dev); 334 335 card->dev.parent = mmc_classdev(host); 336 card->dev.bus = &mmc_bus_type; 337 card->dev.release = mmc_release_card; 338 card->dev.type = type; 339 340 spin_lock_init(&card->bkops_info.bkops_stats.lock); 341 spin_lock_init(&card->wr_pack_stats.lock); 342 343 return card; 344 }
可以看到,第336行指定bus mmc_bus_type
263 static struct bus_type mmc_bus_type = { 264 .name = "mmc", 265 .dev_attrs = mmc_dev_attrs, 266 .match = mmc_bus_match, 267 .uevent = mmc_bus_uevent, 268 .probe = mmc_bus_probe, 269 .remove = mmc_bus_remove, 270 .shutdown = mmc_bus_shutdown, 271 .pm = &mmc_bus_pm_ops, 272 };
这样当mmc_add_card调用device_add的时候,根据linux device driver模型,会自动去找bus上对应的driver。
那首先会调用match去判断是否匹配
60 static int mmc_bus_match(struct device *dev, struct device_driver *drv) 61 { 62 return 1; 63 }
这里直接return 1,那接下来会调用mmc_bus_probe
108 static int mmc_bus_probe(struct device *dev) 109 { 110 struct mmc_driver *drv = to_mmc_driver(dev->driver); 111 struct mmc_card *card = mmc_dev_to_card(dev); 112 113 return drv->probe(card); 114 }
从mmc_bus_probe的实现可以看出,会调用对应driver的probe函数
这个driver在mmc/card/block.c中注册,到这里,上图中host和core基本介绍完了
3597 static struct mmc_driver mmc_driver = { 3598 .drv = { 3599 .name = "mmcblk", 3600 }, 3601 .probe = mmc_blk_probe, 3602 .remove = mmc_blk_remove, 3603 .suspend = mmc_blk_suspend, 3604 .resume = mmc_blk_resume, 3605 .shutdown = mmc_blk_shutdown, 3606 }; 3607 3608 static int __init mmc_blk_init(void) 3609 { 3610 int res; 3611 3612 if (perdev_minors != CONFIG_MMC_BLOCK_MINORS) 3613 pr_info("mmcblk: using %d minors per device\n", perdev_minors); 3614 3615 max_devices = 256 / perdev_minors; 3616 3617 res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); 3618 if (res) 3619 goto out; 3620 3621 res = mmc_register_driver(&mmc_driver); 3622 if (res) 3623 goto out2; 3624 3625 return 0; 3626 out2: 3627 unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); 3628 out: 3629 return res; 3630 }
我们先来看 mmc_register_driver
288 int mmc_register_driver(struct mmc_driver *drv) 289 { 290 drv->drv.bus = &mmc_bus_type; 291 return driver_register(&drv->drv); 292 }
可以看到bus是mmc_bus_type,和刚刚的mmc_add_card中添加的device是同一个bus,这样的话device添加的时候就调用到了这个driver的probe
mmc_blk_probe
相关文章推荐
- OpenGL: Ubuntu创建窗体
- MySQL CMake参数说明手册
- Dell定制Intel 主动管理技术 (Intel AMT)设置指南
- 俄语专业个人简历范文
- Html中td自动换行问题
- css回到顶部
- zend framework框架的action大小写和请求url大小写问题
- ubuntu 12.10 安装ffmpeg
- WPF-控件-编辑圆角TextBox
- C# 7个读写Excel文件的类库
- openssl 移植到 arm
- Longest Substring Without Repeating Characters - LeetCode
- qt中qDebug()无法输出解决办法
- 通信十年,通信真是个死胡同吗?
- SIFT算法详解
- Ruby自学笔记(二)— Ruby的一些基础知识
- (原)android修改文件所属的用户组
- 用户全选管理设计篇
- ubuntu设置系统时间与网络时间同步
- 验证控件jquery.validate.js使用说明+中文API