struct sdio_cis cis; /* common tuple info */ ... ... };
mmc_card结构体内的数据结构主要存放SD卡的信息,其中RCA, CID, CSD, SCR为SD卡内部的32位寄存器。
2.1.2 struct mmc_request 结构体mmc_request定义于/include/linux/mmc/core.h,它主要存放两大数据结构的指针,分别是cmd和data,顾名思意,一个为指令,一个为数据,也就是说,mmc_request结构体存放了进行主控制器与sd卡间通信所需要的指令和数据,struct mmc_request, struct mmc_command *cmd, struct mmc_data *data三者之间的关系如下所示,
struct mmc_request { struct mmc_command *cmd; struct mmc_data *data; struct mmc_command *stop;
void *done_data; /* completion data */
void (*done)(struct mmc_request *);/* completion function */ };
说到结构体mmc_command和mmc_data,就必须说说SD卡的协议了。 1) 物理结构
SD卡有9个pin脚(micro-SD为8个,少一个接地pin脚),如图所示,
SD的数据传输方式有两种,普通SD模式和SPI模式,以SD模式为例,9个pin脚分别是VDD,VSS,CLK,以及我们需要关注的一根指令线CMD,4根数据线DAT0~DAT3。 2) 传输模式
首先由主机向SD卡发送命令command,等待SD卡的回复response,如果成功收到回复,则进行数据传输。其中,指令线和数据线上传输的指令和数据都要遵循相应的协议格式。
3) 指令格式
一条指令command共48位,其中command index指代这条具体的指令名称,argument为该指令的参数。
一条回复response根据不同的指令有几种不同类型。 struct mmc_command {
u32 opcode; // 对应command index u32 arg; // 对应argument u32 resp[4]; // 对应response
unsigned int flags; /* expected response type */ ... ...
unsigned int retries; /* max number of retries */ unsigned int error; /* command error */
struct mmc_data *data; /* data segment associated with cmd */ struct mmc_request *mrq; /* associated request */ };
4) 数据格式
数据传输按数据线可分为一线传输和四线传输,按数据大小可分为字节传输和块传输(512字节)。
struct mmc_data {
unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */ unsigned int timeout_clks; /* data timeout (in clocks) */ unsigned int blksz; /* data block size */ unsigned int blocks; /* number of blocks */
unsigned int error; /* data error */ unsigned int flags;
#define MMC_DATA_WRITE (1 << 8) #define MMC_DATA_READ (1 << 9) #define MMC_DATA_STREAM (1 << 10) unsigned int bytes_xfered;
struct mmc_command *stop; /* stop command */ struct mmc_request *mrq; /* associated request */ unsigned int sg_len; /* size of scatter list */ struct scatterlist *sg; /* I/O scatter list */ };
2.2 驱动程序
系统初始化时扫描platform总线上是否有名为该SD主控制器名字\的设备,如果有, 驱动程序将主控制器挂载到platform总线上,并注册该驱动程序。 static int __init pxamci_init(void) {
return platform_driver_register(&pxamci_driver); }
static struct platform_driver pxamci_driver = { .probe = pxamci_probe, .remove = pxamci_remove, .suspend = pxamci_suspend, .resume = pxamci_resume, .driver = {
.name = “pxa2xx-mci”, .owner = THIS_MODULE, }, };