零、说明
前面介绍完sd card的协议中的初始化之后,接下来就是如何将sd card实现为一个块设备以及其读写流程的实现。
对应代码在drivers/mmc/card目录下block.c 、queue.c中。
先研究sd card作为一个块设备的读写流程。
在学习sdcard块读写的过程中主要围绕以下几个问题进行学习:
- 关于sd card 读写地址的问题?
- 向mmc core发起mmc读写请求的接口?
- 块设备的整个层次结构?
- 从上层(IO调度层)传下来的是什么数据?
- 从struct request到struct mmc_async_req的处理过程?
- mmc_blk_issue_rq对request的整体操作、下发流程?
一、关于sd card 读写地址的问题
1、sd card 读写地址
也就是CMD17\CMD18\CMD24\CMD25的参数问题。
根据SD 3.0协议:
If partial block access is enabled in Standard Capacity Card (i.e. the CSD parameter READ_BL_PARTIAL
equals 1), the block length can be any number between 1 and 512 Bytes. The start address can be any
byte address in the valid address range of the card. Every block, however, shall be contained in a single
physical card sector. If partial block access is disabled, only 512-Byte data length is supported.
// partial block access 分块访问
The High Capacity SD Memory Card only supports 512-byte block length. The start address shall be
aligned to the block boundary.
The unit of "data address" in argument is byte for Standard Capacity SD Memory Card and block (512 bytes) for
High Capacity SD Memory Card.
对于CMD17\CMD18\CMD24\CMD25的参数表示要读写的地址,对于SDSC card来说,数据地址的单位是字节。而对于SDHC和SDXC来说,数据地址的单位是512字节(以块为单位)。
(很好理解啊,SDSC 只支持到2GB,32bit的地址空间完全够了)。
2、代码上
根据CSD寄存器中CSD_STRUCTURE的版本来区分card的容量类型,也就是能判断其读写时的地址的单位了。
static int mmc_decode_csd(struct mmc_card *card)
{
switch (csd_struct) {
case 1: // 说明为SDHC 或者SDXC card
mmc_card_set_blockaddr(card); // 设置mmc的MMC_STATE_BLOCKADDR属性,也就是以块作为地址。
// CMD17 CMD18 CMD24 CMD25的参数也就是块地址。
static void mmc_blk_rw_rq_prep
在设置读写地址的时候
brq->cmd.arg = blk_rq_pos(req);
if (!mmc_card_blockaddr(card)) // 检测MMC_STATE_BLOCKADDR属性
brq->cmd.arg <<= 9; // 没有设置的话,则是以byte作为单位的,IO调度器传下来的是以扇区为单位,也就是以512byte为单位
二、向mmc core发起mmc读写请求的接口
使用的是mmc_start_req接口。
参考《[mmc subsystem] mmc core(第六章)——mmc core主模块》
不阻塞等待该命令的处理流程:
(注意:并不是说调用这个接口并不会阻塞ÿ