ImageVerifierCode 换一换
格式:PDF , 页数:20 ,大小:152.73KB ,
资源ID:5935243      下载积分:10 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.docduoduo.com/d-5935243.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(MMC卡驱动分析.pdf)为本站会员(HR专家)主动上传,道客多多仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知道客多多(发送邮件至docduoduo@163.com或直接QQ联系客服),我们立即给予删除!

MMC卡驱动分析.pdf

1、MMC 卡驱动分析最近花时间研究了一下 MMC 卡驱动程序,开始在网上找了很多关于 MMC 卡驱动的分析文章,但大都是在描述各个层,这对于初学者来讲帮助并不大,所以我就打算把自己的理解写下来,希望对大家有用。个人觉得理解LINUX 内核当中 MMC/SD 卡驱动程序构架是学习 MMC 卡驱动程序的重点,只有理解了它的基本框架或流程才能真正理解一个块设备驱动程序的写法,同时才能真正理解 LINUX 设备驱动模型是如何发挥作用的。一需要的基础知识:1. LINUX 设备驱动的基本结构。2. 块设备驱动程序的基本构架(相信研究过 LDD3 当中的 sbull 的人应该都不成问题,如果只是走马观花的话

2、,那 得 了 3. LINUX 设备驱动模型。驱动程序分析,来 一下我 需要分析的文 。下 的文 来自 linux-2.6.24 ,我 重点是分析驱动程序的基本构架,所以不同内核 本的 并不是很大。 MMC/SD 卡驱动程序 于 drivers/mmc 下,我 只 我 分析过程 的 个文 :Card/block.cqueue.c/queue.hcore/bus.c/bus.hcore.c/core.hhost.c/host.hmmc.cmmc_ops.c/mmc_ops.h MMC 卡来分析, SD 卡驱动程序流程 。host/s3cmci.c/s3cmci.h 以 S3C24XX 的 MMC

3、/SD 卡 ,它 型的 。LINUX 当中对 的分是很有讲究的,这文 分currency1在 3 个 下,正 对应 MMC/SD 驱动程序的 3 个层(关于层的分这“一下,有个fifl ,当我 分析 了 来, 觉得很 :(1 块层”要是 LINUX 块设备驱动程序的框架 一个卡的块设备驱动,这 block.c 当中我 以 写一个块设备驱动程序时需要的 block_device_operations 结构 的,中有 open/release/request 的 ,queue.c 是对内核 的 的,我 时不用 理解它,只需要知 一个块设备需要一个 就 以了。(2 核 层核 层了 MMC/SD 卡的

4、 ,如 卡的识 ,设 , 写。如不 卡都应该有一识 ,设 , 写的 ,这流程都是 要有的,只是对于不同的卡有一各自 有的作。 Core.c 文 是 sd.c mmc.c 个文 的, core.c 把 MMC 卡 SD 卡的 来,它 的 sd.c sd_ops.c mmc.c mmc_ops.c 来 成。(3 ” 层” 是 于不同的 的,如 s3c2410 的卡 atmel 的卡 是不一的,所以要 对不同的 来 。以 s3cmci.c ,它 要 一设 ,如中 ,能。它 core 层 一个” ( host ,用结构 mmc_host_ops 描述,这核 层就以 这个 host 来作s3c24xx

5、的卡 了,是 s3c24xx 的卡 是 atmel 的卡 ,core 层是不用知 的。驱动程序层 了,对这 个 有一个大 识以,我 来 个重要的据结构:struct mmc_host 用来描述卡 struct mmc_card 用来描述卡struct mmc_driver 用来描述 mmc 卡驱动struct mmc_host_ops 用来描述卡 作集,用于从” 层 core 层 作,从将core 层与的” 隔离。也就是说 core 要作” ,就用这个 ops 当中给的指 作,不能直接调用” 的。第一阶段:从 s3cmci_init 开始往下static int _init s3cmci_in

6、it(void)platform_driver_register(有 platform_driver_register ,根据设备模型的知识,我 知 那一有对应的 platform_device_register的, 是在哪“呢?没有 ,那是不是这个 s3cmci_driver_2410 当中给的 probe 就不执 了?当不是, mci 接口一般都是硬 做 的(我 是这 ,所以在系统启动时一有调用 platform_device_register 对板上的资 ,如果没有这个硬 资 ,那我 这个驱动也就没有用了。 ,我 就假是有mci 接口的,且也有与 s3cmci_driver_2410 对

7、应的硬 资 了,那自己就去跑 probe 。来一下s3cmci_driver_2410:static struct platform_driver s3cmci_driver_2410 = .driver.name = “s3c2410-sdi“,.probe = s3cmci_probe_2410,.remove = s3cmci_remove,.suspend = s3cmci_suspend,.resume = s3cmci_resume,;我 s3cmci_probe_2410 中, 是干脆直接 s3cmci_probe 算了:static int s3cmci_probe(struc

8、t platform_device *pdev, int is2440) / 来自 /host/s3cmci.cstruct mmc_host *mmc;struct s3cmci_host *host;int ret;mmc = mmc_alloc_host (sizeof(struct s3cmci_host), if (!mmc) ret = -ENOMEM;goto probe_out;mmc-ops = ret = mmc_add_host (mmc);if (ret) dev_err(goto free_dmabuf;platform_set_drvdata(pdev, mmc);

9、return 0;这个很长,做的事 也很多,但我 关 的整个驱动的构架 / 流程,所以过滤掉一细节的东西,只 2 个最重要的: mmc_alloc_host mmc_add_host 。 名已经很了,前者是申一个 mmc_host ,者是添加一个 mmc_host 。中间 有一个作,就是给 mmc 的 ops 成员赋上了 s3cmci_ops 这个值。申mmc_host 当很简单,就是申一个结构(我 且这 ,因他“ 做的它事情, ,添加又是添加 哪“去呢? mmc_add_host :int mmc_add_host(struct mmc_host *host) / 来自 core/host.

10、cint err;err = device_add(if (err)return err;mmc_start_host(host);return 0;很简单,就是增加了一个 device ,就调用 mmc_start_host 了,那就 跳过 device_add 这个动作,来mmc_start_host:void mmc_start_host(struct mmc_host *host) / 来自 /host/core.cmmc_power_off(host); / 掉电一下mmc_detect_change(host, 0); / ?上去只有 代 ,不过浓缩才是精华, mmc_power_

11、off(host) 光名子都知 是在干 , 跳过,来mmc_detect_change ,那 它 底干了 呢?一下就知 了:void mmc_detect_change(struct mmc_host *host, unsigned long delay) / core/core.cmmc_schedule_delayed_work(static int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)return queue_delayed_work(workqueue, work, delay

12、);mmc_detect_change 又跳了一下,最调用了 queue_delayed_work ,不知 这个功能的去查一下LDD3 理解 LINUX 内核,这 个代 告诉我 在 workqueue 这个工作 当中添加一个延迟的工作任务,这个工作任务就是 host-detect 来描述的,在随的 delay 个 jiffies 有一个记 在host-detect “ 的执 ,那 这“ s3cmci_probe 这个算是结束了,但事情没有 ,workqueue 这个工作 在忙,不一儿它就调用 host-detect “ 那个,这个 底是哪个, 底是用来干 的呢? 像没有 , detect 包含

13、在 host “ ,那估计是在刚才那个申的地方设 的那个,过来一下 mmc_alloc_host:struct mmc_host *mmc_alloc_host(int extra, struct device *dev) / 来自 core/host.cstruct mmc_host *host;host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);if (!host)return NULL;INIT_DELAYED_WORK(return host;如果 了 queue_delayed_work 这个功能介绍,相信对 INI

14、T_DELAYED_WORK 也不陌生了吧。不废话了,来 mmc_rescan :/ 来自 core/host.cvoid mmc_rescan(struct work_struct *work) / / 来自 core/host.cstruct mmc_host *host = container_of(work, struct mmc_host, detect.work);u32 ocr;int err;/* detect a newly inserted card */* First we search for SDIO.*/err = mmc_send_io_op_cond(host,

15、 0, if (!err) if (mmc_attach_sdio(host, ocr)mmc_power_off(host);goto out;/* .then normal SD.*/err = mmc_send_app_op_cond(host, 0, if (!err) if (mmc_attach_sd(host, ocr)mmc_power_off(host);goto out;/* .and finally MMC.*/err = mmc_send_op_cond(host, 0, if (!err) if (mmc_attach_mmc(host, ocr)mmc_power_

16、off(host);goto out;mmc_release_host(host);mmc_power_off(host);out:if (host-caps 一个这个,名, 释,知 了吗?它是在检测是不是有卡插 了卡 ,如果有卡挺 就要采取相应的 动了。这“要 白一点,我 时用的 SD/MMC 卡就是一个卡,如果要作它得用SD/MMC 卡 才 ,所以 以 有 struct mmc_card,struct mmc_host 的分。这“了,来忆一下 s3cmci_probe 这个做的事情,大就是准备一个 mmc_host 结构,添加一个” 设备 内核,最又调用了一下 mmc_rescan 来检测

17、是不是有卡插 了。如果有卡插 了 , 以去作卡了,那如果没有卡插 呢? mmc_rescan 不是白调用了一吗?是啊,的 是白调用了一。 是卡插 时 PC 是能检测 呢?来卡检测的动作不光是在 probe 的最一步做了一,它地方也有做。卡插 一般都是人地随时去插 的,像这种情况一般都是用中 去 系统有外来侵 , 去采取 动。 SD/MMC 卡也的 是这做的,找来找去,发 在 s3cmci_probe “ 了一个中 s3cmci_irq_cd( 名的意思应该是 irq card detect) ,就是这个了,这个 :static irqreturn_t s3cmci_irq_cd(int irq

18、, void *dev_id) / host/s3cmci.cstruct s3cmci_host *host = (struct s3cmci_host *)dev_id;mmc_detect_change(host-mmc, msecs_to_jiffies(500);return IRQ_HANDLED; 这个想都不用想,直接跳 mmc_rescan “ 去就 了。前 已经知 了 mmc_rescan “ 就是在检测卡是不是插 了,既卡随时插 我 都能检测 了,那就来卡插 都做了 动作吧。第 阶段:mmc_rescan “ 既要检测 sd 卡,又要检测 mmc 卡的,我 就 一个往下走,

19、假有个人插 了 MMC卡,那就应该走下 这 :err = mmc_send_op_cond(host, 0, if (!err) if (mmc_attach_mmc(host, ocr)mmc_power_off(host);goto out;mmc_send_op_cond 这个据说是 了一下卡的 值,这个值是 意我也不清 ,这就像检测 FLASH时 FLASH 的 ID 一,网卡也是这的,不用 这个值的意了,只要知 它能 识是一个 MMC 卡插 就 了。如果取这个值没有 的话就得 mmc_attach_mmc 了:/* Starting point for MMC card init.*

20、/int mmc_attach_mmc(struct mmc_host *host, u32 ocr) / core/mmc.cint err;mmc_attach_bus_ops(host); / 这个与 的电 理有关,时跳过/* Detect and init the card.*/err = mmc_init_card(host, host-ocr, NULL);if (err)goto err;mmc_release_host(host);err = mmc_add_card(host-card);if (err)goto remove_card;return 0;remove_car

21、d:err:return err;是找 个关 来 mmc_init_card 从名来就是初始 一个 card ,这个 card 就用 struct mmc_card结构来描述,又调用 mmc_add_card 将卡设备添加 了内核, 来 mmc_init_card 都做了 事情:static int mmc_init_card(struct mmc_host *host, u32 ocr,struct mmc_card *oldcard)struct mmc_card *card;int err;u32 cid4;unsigned int max_dtr;/* Allocate card st

22、ructure.*/card = mmc_alloc_card(host, if (IS_ERR(card) err = PTR_ERR(card);goto err;card-type = MMC_TYPE_MMC;card-rca = 1;memcpy(card-raw_cid, cid, sizeof(card-raw_cid);host-card = card;return 0;free_card:err:return err;将与硬 作相关的 掉,最对我 有用的也就这 了 mmc_alloc_card 申了一个 struct mmc_card结构,给 card-type 赋上 MMC

23、_TYPE_MMC ,最将 card 又赋给了 host-card ,这硬 是挺像的,因一个” 一般就插一个卡,有卡时 host-card 有值,没有卡时 host-card 自己就是 NULL 了。mmc_alloc_card “ 来:/* Allocate and initialise a new MMC card structure.*/struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)struct mmc_card *card;card = kzalloc(sizeof(str

24、uct mmc_card), GFP_KERNEL);if (!card)return ERR_PTR(-ENOMEM);card-host = host;device_initialize(card-dev.parent = mmc_classdev(host);card-dev.bus = card-dev.release = mmc_release_card;card-dev.type = type;return card;Struct mmc_card 结构“ 包含了一个 struct device 结构, mmc_alloc_card 不但申了内 ,且 了struct device

25、中的 个成员, card-dev.bus = 这一 要重点对 。申一个 mmc_card 结构,并简单初始 , mmc_init_card 的 就 成了, 调用mmc_add_card 将这个 card 设备添加 内核。 mmc_add_card 很简单,就是调用 device_add 将 card-dev 添加 内核当中去。知 模型这个东西的人都 白,理 device_add “ 就应该有动作了,是哪个 呢?那就得 调用 device_add 时 的那个 dev “ 指的是哪个 了,我 的 card-dev ,那 card-dev.bus指 呢?很 是那个 mmc_bus_type :sta

26、tic struct bus_type mmc_bus_type = .name = “mmc“,.dev_attrs = mmc_dev_attrs,.match = mmc_bus_match,.uevent = mmc_bus_uevent,.probe = mmc_bus_probe,.remove = mmc_bus_remove,.suspend = mmc_bus_suspend,.resume = mmc_bus_resume,;在 device_add “ ,设备对应的 这个设备 在这个 上的所有驱动程序去 ( match , 时调用 match ,如果 了就调用 的 pro

27、be 或驱动的 probe ,那我 一下这“的mmc_bus_match 是如何 的:static int mmc_bus_match(struct device *dev, struct device_driver *drv)return 1;来 match 都能成功,那就去执 probe 吧:static int mmc_bus_probe(struct device *dev)struct mmc_driver *drv = to_mmc_driver(dev-driver);struct mmc_card *card = dev_to_mmc_card(dev);return drv-

28、probe(card);这“就有点 了,在这个“ 又调用了一下 drv-probe() ,那这个 drv 是 呢?上 有: struct mmc_driver *drv = to_mmc_driver(dev-driver);match 是 1 ,那来只要是 在这 上的 driver 都有 能跑 这“来了,事的 也是这的,不过 在 在这 上的 driver 只有一个,它是这的:static struct mmc_driver mmc_driver = .drv = .name = “mmcblk“,.probe = mmc_blk_probe,.remove = mmc_blk_remove,

29、.suspend = mmc_blk_suspend,.resume = mmc_blk_resume,; 这“时, card/core/host 个已经 来了, mmc_driver 中的 个,他 个如何系 来也就 白了。那我 吧。第阶段:前 已经 了,在 的 probe “ 调用了 drv-probe, 这个就对应的是 mmc_blk_probe ,这个mmc_driver 是 mmc_bus 上的,自己去 mmc_blk_init() ,就 代 ,应该不。static int mmc_blk_probe(struct mmc_card *card) / 来自 card/block.cst

30、ruct mmc_blk_data *md;int err;md = mmc_blk_alloc(card);if (IS_ERR(md)return PTR_ERR(md);add_disk(md-disk);return 0;out:mmc_blk_put(md);return err;是重要的,一 这个最调用了 add_disk , 应该 以想 吧?如果 不知 我在说 ,那我估计 没有过 LDD3 ,或者了也是走马观花了。我来告诉 :如果 add_disk ,那说 前 一有 alloc_disk 初始 的动作,在 mmc_blk_probe 时 没有 来,那就mmc_blk_alloc(

31、card) 那一 :static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)struct mmc_blk_data *md;int devidx, ret;devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);if (devidx = MMC_NUM_MINORS)return ERR_PTR(-ENOSPC);_set_bit(devidx, dev_use);md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);

32、if (!md) ret = -ENOMEM;goto out;/* Set the read-only status based on the supported commands* and the write protect switch.*/md-read_only = mmc_blk_readonly(card);md-disk = alloc_disk(1 disk = NULL) ret = -ENOMEM;goto err_kfree;spin_lock_init(md-usage = 1;ret = mmc_init_queue(if (ret)goto err_putdisk

33、;md-queue.issue_fn = mmc_blk_issue_rq;md-queue.data = md;md-disk-major = MMC_BLOCK_MAJOR;md-disk-first_minor = devidx disk-fops = md-disk-private_data = md;md-disk-queue = md-queue.queue;md-disk-driverfs_dev = /* As discussed on lkml, GENHD_FL_REMOVABLE should:* - be set for removable media with per

34、manent block devices* - be unset for removable block devices with permanent media* Since MMC block devices clearly fall under the second* case, we do not set GENHD_FL_REMOVABLE. Userspace* should use the block device creation/destruction hotplug* messages to tell when the card is present.*/sprintf(m

35、d-disk-disk_name, “mmcblk%d“, devidx);blk_queue_logical_block_size(md-queue.queue, 512);if (!mmc_card_sd(card) else /* The CSD capacity field is in units of read_blkbits.* set_capacity takes units of 512 bytes.*/set_capacity(md-disk,card-csd.capacity csd.read_blkbits - 9);return md;err_putdisk:put_d

36、isk(md-disk);err_kfree:kfree(md);out:return ERR_PTR(ret); 这个的代 ,我 自就忆 了块设备驱动的整个currency1了:1. 分 初始 ,并 。2. 分 ,初始 gendisk ,给 gendisk 的 major , fops , queue 成员赋值,最添加 gendisk 。3. 块设备驱动。我 MMC 卡驱动程序有没有这个currency1走,1 mmc_init_queue 初始了 ,并将 mmc_blk_issue_rq; 成“2 alloc_disk 分 了 gendisk 结构,并初始 了 major , fops ,

37、 queue “3 最调用 add_disk 将块设备加 KERNEL 中去。这“ mmc_blk_probe 已经结束了,但我 下来。记得 LDD3 上在讲 sbull 时说过, add_disk 的调用 一个块设备驱动将fifl,所以在这 前 把它所有准备工作 做 ,作者这说是有理 的,因在 add_disk “ kernel 去调用 中的, 的是去的块设备上 分。且是在 add_disk 内 就要做的,不是 add_disk 做, 这,去 add_disk 的代 就知 了。既要调用去 ,那我 就来: mmc_blk_issue_rqstatic int mmc_blk_issue_rq(

38、struct mmc_queue *mq, struct request *req)struct mmc_blk_data *md = mq-data;struct mmc_card *card = md-queue.card;struct mmc_blk_request brq;int ret = 1, disable_multi = 0;do mmc_wait_for_req(card-host, /* A block was successfully transferred.*/spin_lock_irq(ret = _blk_end_request(req, 0, brq.data.b

39、ytes_xfered);spin_unlock_irq( while (ret);return 1;这个在长了, 在我 不用 ,大 分 据的准备代 理的代 已经我 掉了,只要知 据都是在这“ 成的就了。不 这个的, 上 LDD3 找个人的地方,将 sbull “ ” “ ”研究了也就 白这个了。不过这个“ 的东西 挺不, ,都在这“ 了,有时间 去研究吧。在块设备驱动当中 只需要” 就 以了,那 block_device_operations “ 赋值的 不像设备驱动“ 那 关 了。分析 这“, MMC/SD 卡的驱动整个构架基本也就很 析了,说简单了就是做了 事:1. 卡的检测“2. 卡据

40、的 取。最 将这 个过程大一下:1. 卡的检测:S3cmci_probe(host/s3cmci.c)Mmc_alloc_host(core/core.c)Mmc_rescan(core/core.c)Mmc_attach_mmc(core/mmc.c)Mmc_init_card(core/mmc.c)mmc_add_card(core/bus.c)device_addmmc_bus_match(core/bus.c)mmc_bus_probe(core/bus.c)mmc_blk_probe(card/block.c)alloc_disk/add_disk2. 写据:mmc_blk_issue_rq ( card/block.c mmc_wait_for_req(core/core.c)mmc_start_request(core/core.c)host-ops-request(host, mrq) / s3cmci 中 s3cmci_requestMMC/SD 卡的驱动分析 了,是不是有 ,不过这设计的 的是了分层, 的驱动写加事。

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报