Linux设备驱动子系统第二弹- SD卡 - 图文(8)

2019-08-31 13:59

协议层为我们解析了寄存器里的域,并赋给card->cid,比如厂商名称,就可以通过card->cid.manfid直接读取到。

static int mmc_decode_cid(struct mmc_card *card) {

u32 *resp = card->raw_cid;

card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); card->cid.serial = UNSTUFF_BITS(resp, 16, 32); card->cid.month = UNSTUFF_BITS(resp, 12, 4); card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; return 0; }

3.1.4 注册SD卡设备驱动

int mmc_attach_sd(struct mmc_host *host, u32 ocr) {

/* mmc_alloc_card(host, &sd_type); 在mmc_sd_init_card()已完成 */

mmc_add_card(host->card); ... ... }

上文已经提到,设备驱动程序都会通过alloc_xxx()和add_xxx()两步来注册驱动,其实质是调用/drivers/base/core.c里的device_initialize()和device_add(),device_add()完成建立kobject,sys文件,发送uevent,等工作。 3.2 拔出SD卡

void mmc_rescan(struct work_struct *work) {

struct mmc_host *host = container_of(work, struct mmc_host, detect.work); mmc_bus_get(host);

/* if there is a card registered, check whether it is still present */

if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) host->bus_ops->detect(host); mmc_bus_put(host); ... ... }

这里的mmc_bus_get/put(),为SD总线加上一个自旋锁,规定同时只能有一个线程在SD总线上操作。

3.2.1 bus_ops->detect() mmc_rescan()扫描SD总线,如果发现host->ops上赋了值,即之前已有SD卡注册过,就执行bus_ops->detect()操作去探测SD总线上是否还存在SD卡,如果不存在了,就执行bus_ops->remove()拔出SD卡。之前已经提到,这个bus_ops->detect()已在mmc_attach_sd()注册完成了。

static void mmc_sd_detect(struct mmc_host *host) {

mmc_claim_host(host); /*

* Just check if our card has been removed. */

err = mmc_send_status(host->card, NULL); mmc_release_host(host); if (err) {

mmc_sd_remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); } }

这里的mmc_claim_host(host)通过set_current_state(TASK_RUNNING);将当前进程设置为正在运行进程。

mmc_send_status()发送得到SD卡状态的请求,如果未能得到状态数据,则执行mmc_sd_remove(host)拔出SD卡。

int mmc_send_status(struct mmc_card *card, u32 *status) {

struct mmc_command cmd;

cmd.opcode = MMC_SEND_STATUS; /* #define MMC_SEND_STATUS 13 */ cmd.arg = card->rca << 16;

cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); if (err)

return err; // 接收来自SD卡的response失败,即没有发现SD卡

if (status)

*status = cmd.resp[0]; return 0; }

主控制器发送命令CMD13,要求得到SD卡的状态寄存器CSR和SSR。

SD协议规定,状态寄存器CSR是必须的,这个32位寄存器作为R1的一个域返回给主控制器,

状态寄存器SSR作为扩充功能,具体参考SD2.0协议。

3.2.2 bus_ops->remove() 拔出SD卡,其实就是注册SD卡驱动的反操作,实质就是执行device_del()和device_put()。 static void mmc_sd_remove(struct mmc_host *host) {

mmc_remove_card(host->card);

host->card = NULL; }

void mmc_remove_card(struct mmc_card *card) {

if (mmc_card_present(card)) device_del(&card->dev); put_device(&card->dev); }

4. 块设备

首先,必须知道为什么要用到块设备。在linux下,SD卡通过block块的方式(以512字节为最小单位)进行数据传输,它必须遵从块设备架构。在linux块设备层,I/O调度者通过请求队列机制负责对块数据的处理。

SD卡子系统分为三层,主设备层,协议层和块设备层。块设备驱动位于/drivers/mmc/card/block.c,主要完成两个任务,

? ?

建立设备节点

通过请求队列机制进行数据传输


Linux设备驱动子系统第二弹- SD卡 - 图文(8).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:太阳能热水器控制仪使用说明书资料

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: