赞
踩
Linux MMC/SD存储卡是一种典型的块设备,他的实现位于driver/mmc。driver/mmc下又分为card,core,host这3个目录。
card实际上跟Linux的块设备子系统
对接,实现块设备驱动以及完成请求。但是具体的协议经过core层
的接口,最终通过host
完成传输。
另外card目录除了实现标准的MMC/SD存储卡以外,该目录还包含了一些SDIO外设卡的驱动,如driver/mmc/card/sdio_uart.c。core目录除了给card提供接口外,实际上也定义好了host驱动的框架。
driver/mmc/card/queue.c
的mmc_init_queue()
函数通过blk_init_queue
(mmc_request_fn,lock)绑定了请求函数mmc_request_fn()
;
int mmc_init_queue(struct mmc_queue *mq,struct mmc_card *card,spinlock_t *lock,const char *subname)
{
......
mq->queue = blk_init_queue(mmc_request_fn,lock);
......
}
而mmc_request_fn()
函数会唤醒与MMC对应的内核线程来处理请求,与该线程对应的处理函数mmc_queue_thread()
执行与MMC对应的mq->issue_fn(mq,req);
static int mmc_queue_thread(void *d)
{
......
do{
......
req = blk_fetch_request(q);
mq->mqrq_cur->req = req;
......
if(req ||mq->mqrq_prev->req)
{
set_current_state(TASK_RUNNING);
cmd_flags = req?req->cmd_flags:0;
mq->issue_fn(mq,req);
}
}
......
return 0;
}
对于存储设备而言,mq->issue_fn()
函数指向driver/mmc/card/block.c
中的mmc_blk_issue_rq()
;
static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,struct device *parent,sector_t size,bool default_ro,const char *subname,int area_type)
{
......
md->queue.issue_fn = mmc_blk_issue_rq;
md->queue.data = md;
......
}
其中的mmc_blk_issue_rw_rq()等函数最终会调用driver/mmc/core/core.c中的mmc_start_req()这样的函数
static int mmc_blk_issue_rw_rq(struct mmc_queue *mq,struct rquest *rqc)
{
...
areq = mmc_start_req(card->host,areq,(int*)&status);
...
}
mmc_start_req()反过来又调用host驱动的host->ops->pre_req(),hoost->ops->enable(),host->ops->disable(),host->ops->request()等成员函数,这些函数实现于driver/mmc/host目录中。
host->ops实际上是一个MMC host操作的集合,对应的结构体为mmc_host_ops,MMC主机驱动的主题工作就是实现该结构体的成员函数。
由于目前大多数的SOC内嵌的MMC/SD/SDIO控制器是SDHCI,所以更多的是直接重用driver/mmc/host/sdhci.c驱动,很多芯片甚至还可以进一步使用基于driver/mmc/host/sdhci.c定义的driver/mmc/host/sdhci-pltfm.c框架
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。