sd卡驱动分析之core
core层处理(linux/driver/mmc/core)
1. core层初始化
一切变化逃不出Kconfig/Makefile的魔爪,这话一点也不假。同样core层的故事也将从这里拉开帷幕。二话不说先还是进到core目录下瞧瞧…
与以往所见到的Kconfig相比这里的显然少了几分生机和活力,貌似整个文件看完也难以发现令我们眼前发亮的字眼。也罢,少一个config也许就意味这我们少看几千行代码。再看看Makefile:
5 ifeq ($(CONFIG_MMC_DEBUG),y)
9 obj-$(CONFIG_MMC) += mmc_core.o
10 mmc_core-y := core.o bus.o host.o \
11 mmc.o mmc_ops.o sd.o sd_ops.o \
12 sdio.o sdio_ops.o sdio_bus.o \
13 sdio_cis.o sdio_io.o sdio_irq.o
15 mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
看到这里我们再也兴奋不起来了,好像处理debugfs.c这个文件我们可以不怎么关注外,其他的文件都是我们研究的重点了。命运本该如此,不能改变就学着去接受吧.....
1315 static int __init mmc_init(void)
1319 workqueue = create_singlethread_workqueue("kmmcd");
1323 ret = mmc_register_bus();
1327 ret = mmc_register_host_class();
1331 ret = sdio_register_bus();
1333 goto unregister_host_class;
1338 mmc_unregister_host_class();
1342 destroy_workqueue(workqueue);
150 int mmc_register_bus(void)
152 return bus_register(&mmc_bus_type);
看这代码清晰简单,比起小葱拌豆腐还一清二白。如果你硬是说不认识bus_register那我就没辙了,回去翻翻设备模型估计第一页就有讲述他老人家的风骚故事。
1327行这句话看不看能,如果你硬是对sys目录下的那点东西怎么来的感兴趣的话,就去瞅两眼吧。一眼就够了,太多了伤身体。
GSM/GPRS modem card、Bluetooth card、Radio/TV card。SDIO的应用将是未来嵌入式系统最重要的接口技术之一,并且也会取代目前 GPIO式的 SPI 接口。
2. mmc_claim_host
mmc_claim_host定义在/mmc/core/core.h中实际的代码是由__ mmc_claim_host来完成的,具体的实现如下:
150 static inline void mmc_claim_host(struct mmc_host *host)
152 __mmc_claim_host(host, NULL);
函数以非终止的方式调用,传递的abort实参为NULL。关于__ mmc_claim_host的内容将做详细分析,具体代码如下:
451 int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
453 DECLARE_WAITQUEUE(wait, current);
459 add_wait_queue(&host->wq, &wait);
460 spin_lock_irqsave(&host->lock, flags);
462 set_current_state(TASK_UNINTERRUPTIBLE);
463 stop = abort ? atomic_read(abort) : 0;
464 if (stop || !host->claimed || host->claimer == current)
466 spin_unlock_irqrestore(&host->lock, flags);
468 spin_lock_irqsave(&host->lock, flags);
470 set_current_state(TASK_RUNNING);
477 spin_unlock_irqrestore(&host->lock, flags);
478 remove_wait_queue(&host->wq, &wait);
457行might_sleep宏其实就是检查是否需要重新调度,如果是,则进行调度。一般都用在可能引发睡眠的上下文中,完成任务的抢占。
459行将新的等待节点加入到主机的host->wq等待对列中,主要这里只是说加入进来
另外,刚才说到了mmc_host_enable这个函数,定义在/mmc/core/core.c中,还是来简单的看一下:
347 * mmc_host_enable - enable a host.
348 * @host: mmc host to enable
350 * Hosts that support power saving can use the 'enable' and 'disable'
351 * methods to exit and enter power saving states. For more information
352 * see comments for struct mmc_host_ops.
354 int mmc_host_enable(struct mmc_host *host)
356 if (!(host->caps & MMC_CAP_DISABLE))
365 cancel_delayed_work_sync(&host->disable);
374 err = host->ops->enable(host);
378 pr_debug("%s: enable error %d\n",
365行这实际上是内核维护的一个全局的工作队列,使用时不需要定义工作队列结构体,全局工作队列创建的时候可以使用如下方法:
370-382行就是调用host所提供的mmc_host_ops方法来设置了,其实整个过程是和低功耗相关的,这里就不再深入研究了。
看完mmc_claim_host,我们乘热打铁把他的孪生兄弟mmc_release_host也给解决了。
3. mmc_release_host
mmc_release_host与mmc_claim_host一起出生入死,始终是成对出现,执行的过程肯能在顺序上有点颠倒,上点源码如下:
575 void mmc_release_host(struct mmc_host *host)
579 mmc_host_lazy_disable(host);
581 mmc_do_release_host(host);
545 int mmc_host_lazy_disable(struct mmc_host *host)
547 if (!(host->caps & MMC_CAP_DISABLE))
559 if (host->disable_delay) {
560 mmc_schedule_delayed_work(&host->disable,
561 msecs_to_jiffies(host->disable_delay));
564 return mmc_host_do_disable(host, 1);
整个过程与上面说说的mmc_host_enable正好相反。
564行如果主机没有这个癖好直接可以disable那再好不过了,mmc_host_do_disable(host, 1);为您解决一切后顾之忧。
388 static int mmc_host_do_disable(struct mmc_host *host, int lazy)
394 err = host->ops->disable(host, lazy);
398 pr_debug("%s: disable error %d\n",
403 unsigned long delay = msecs_to_jiffies(err);
405 mmc_schedule_delayed_work(&host->disable, delay);
回到mmc_release_host还剩下最后一行,mmc_do_release_host(host)。
509 static void mmc_do_release_host(struct mmc_host *host)
513 spin_lock_irqsave(&host->lock, flags);
515 /* Release for nested claim */
516 spin_unlock_irqrestore(&host->lock, flags);
520 spin_unlock_irqrestore(&host->lock, flags);
这段代码逻辑异常清晰,格式异常工整,一切犹如行云流水一般。环环相扣,句句入理。这么多的优点面前我只说一句,省的大煞风景。
521行再见了wake_up,前面说过一个变态的,这里出现的这个可是他家的正统血脉哦,一个主机控制器的release,wake_up了一批抢占他的线程,这里就是个强有力的证明。
好了,废话加白话总之没有一句真话的把mmc_release_host讲完了,接下来该步入整个SD卡故事得正题了,别笑的太早,到时候有你好受。
4. mmc_wait_for_req
总算是轮到他了,不是不想说他,是说起他来估计说到天黑还没个底。但是无论怎样,天塌下来内核源代码都还是要看的。废话少说,先上源码:
185 * mmc_wait_for_req - start a request and wait for completion
186 * @host: MMC host to start command
187 * @mrq: MMC request to start
189 * Start a new MMC custom command request for a host, and wait
190 * for the command to complete. Does not attempt to parse the
193 void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
195 DECLARE_COMPLETION_ONSTACK(complete);
197 mrq->done_data = &complete;
198 mrq->done = mmc_wait_done;
200 mmc_start_request(host, mrq);
202 wait_for_completion(&complete);
我汗,这啥意思,咋整个代码比潘长江还短。罢了不管他,研究下代码。
200行mmc_start_request搞了半天才开始请求,你说这急人不急人,好了看你怎个start法。
122 mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
129 pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
130 mmc_hostname(host), mrq->cmd->opcode,
131 mrq->cmd->arg, mrq->cmd->flags);
134 pr_debug("%s: blksz %d blocks %d flags %08x "
136 mmc_hostname(host), mrq->data->blksz,
137 mrq->data->blocks, mrq->data->flags,
138 mrq->data->timeout_ns / 1000000,
143 pr_debug("%s: CMD%u arg %08x flags %08x\n",
144 mmc_hostname(host), mrq->stop->opcode,
145 mrq->stop->arg, mrq->stop->flags);
150 led_trigger_event(host->led, LED_FULL);
155 BUG_ON(mrq->data->blksz > host->max_blk_size);
156 BUG_ON(mrq->data->blocks > host->max_blk_count);
157 BUG_ON(mrq->data->blocks * mrq->data->blksz >
162 for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i)
164 BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
167 mrq->cmd->data = mrq->data;
171 mrq->data->stop = mrq->stop;
176 host->ops->request(host, mrq);
这不看不大紧,一看乐死人。149行以前全是debug要用的,本来就不长的代码这一缩水可真没啥分量了。
167-173行这几行什么意思我始终没能明白,也许真的到了春暖花开的季节才能明白他的良苦用心吧。没办法,现在还不能说,那就等待等待在等待吧....
176行不用我多说肯定都知道这是个什么意思,不错调用的真是host边的接口,好了不能再说了,再说就有人告我侵犯领土完整了。
前面说了这个函数很复杂的,怎么?放心好戏在后头。好了回到mmc_wait_for_req...
197-198行mmc_wait_done等待完成,进去看看
179 static void mmc_wait_done(struct mmc_request *mrq)
5. mmc_wait_for_cmd
是时候进入mmc_wait_for_cmd了,不过遗憾的是这个函数也确实没有太多吸引人眼球的地方,还是贴出他的源码来吧。
217 int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
223 memset(&mrq, 0, sizeof(struct mmc_request));
225 memset(cmd->resp, 0, sizeof(cmd->resp));
231 mmc_wait_for_req(host, &mrq);
struct mmc_reques现在确实不方便也没办法说清楚,说到真正作用在硬件上的传输过程之时,也将是揭开他神秘面纱之日。
http://m.blog.csdn.net/blog/rain0993/8476755
sd卡驱动分析之core相关推荐
- Linux SD卡驱动开发(五) —— SD 卡驱动分析Core补充篇
Core层中有两个重要函数 mmc_alloc_host 用于构造host,前面已经学习过,这里不再阐述:另一个就是 mmc_add_host,用于注册host 前面探测函数s3cmci_probe, ...
- SD卡驱动分析(二)
三.下面分析一下高通的android2.3的代码中SD卡驱动的流程. 在kernel中,SD卡是作为平台设备加入到内核中去的,在/kernel/arch/arm/mach-msm/devices-ms ...
- SD卡驱动分析(一)
Android下的SD卡驱动与标准LINUX下的SD卡驱动好像没有太大的区别,这里就以高通的ANDROID 2.3以代表,来简要分析一下LINUX下SD卡驱动的写法.由于小弟的技术有限,分析的有错的地 ...
- linux SD卡驱动分析
1. 硬件基础: SD/MMC/SDIO 概念区分概要 SD (Secure Digital )与 MMC (Multimedia Card ) SD 是一种 flash memory card 的标 ...
- S3C2440上MMC/SD卡驱动分析(二)
下面的文章主要是转载的,先记录下自己的经验. MMC/SD驱动有两种模式:FIFO和DMA.在代码中两种方式都予以了实现,在make menuconfig时候,可以选择是使用fifo方式还是DMA方式 ...
- Linux SD卡驱动开发(二) —— SD 卡驱动分析HOST篇
回顾一下前面的知识,MMC 子系统范围三个部分: HOST 部分是针对不同主机的驱动程序,这一部是驱动程序工程师需要根据自己的特点平台来完成的. CORE 部分: 这是整个MMC 的核心存,这部分完成 ...
- sd 卡驱动--基于高通平台
点击打开链接 内容来自以下博客: http://blog.csdn.net/qianjin0703/article/details/5918041 Linux设备驱动子系统第二弹 - SD卡 (有介绍 ...
- Linux SD卡驱动开发(六) —— SD卡启动过程总体分析
一.工作流程 mmc驱动主要文件包括 drivers/mmc/card/block.c drivers/mmc/card/queue.c drivers/mmc/core/core.c drivers ...
- rt-thread SDIO驱动框架分析(SD卡驱动\SD Nand驱动)
rt-thread SDIO驱动框架分析之SD卡驱动 文章目录 rt-thread SDIO驱动框架分析之SD卡驱动 1. 前言 2. SDIO通用驱动框架介绍 3. 文件架构分析 4. SDIO设备 ...
- 嵌入式linux sd卡读写,嵌入式Linux之我行——S3C2440上MMC/SD卡驱动实例开发讲解(二)...
嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤.一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便.如有错误之处,谢请指正. 一.开发环境 主 机:VMWa ...
最新文章
- 2019 ICPC Asia Nanjing Regional K.Triangle(求一个能将三角形分成两个面积相同的线段、计算几何)
- 【Java】PMD规则学习(1) --字符串比较
- uni-calendar更改打点颜色实现签到和缺勤不同打点颜色效果
- eNSP仿真模拟与实际环境的几个不符点
- C#中用ToString方法格式化时间
- 自动控制原理复习——第二章 控制系统的数学模型,系统框图简化,信号流图,梅森公式,控制系统的传递函数(详细介绍)
- dstwo linux 模拟器,dstwo使用gba模拟器V1.30版本下载和使用作弊功能的作弊教程
- Pycharm_EmmyLua断点调试Lua
- 用ProcessOn在线作图
- Java 输出三角形
- TOM企业邮箱,为你打造企业专属邮箱
- java 用户态_内核启动用户态的程序 - 但行好事 莫问前程 - JavaEye技术网站
- vim插入(insert)模式下的快捷键
- Java - 加号(+)的作用
- 微信聊天记录丢失后的记录(二)
- 最新的VMware Workstation Pro 17安装教程+安装包下载
- NLP自然语言处理中oov的词的解释
- jq实现导航吸顶效果
- 同一个excel文件在不同电脑上打印高度不同的原因
- 使用dlsym动态加载库函数、封装原有库函数