Linux的设备驱动程序架构分析之MMC / SD(二)
时间:2023-01-19 15:00:00
转自:http://blog.csdn.net/liuhaoyutz
内核版本:3.10.1
一,s3cmci_ops分析
在上一篇文章中,我们分析了它Mini2440 MMC / SD驱动探针函数s3cmci_probe。结构在函数中初始化mmc_host指针变量mmc,其中,设置mmc-> ops为s3cmci_ops,s3cmci_ops定义在drivers / mmc / host / s3cmci.c文件中:
- 1427staticstructmmc_host_ops s3cmci_ops = {
- 1428 .request = s3cmci_request,
- 1429.set_ios = s3cmci_set_ios,
- 1430 .get_ro = s3cmci_get_ro,
- 1431 .get_cd = s3cmci_card_present,
- 1432.enable_sdio_irq = s3cmci_enable_sdio_irq,
- 1433};
struct mmc_host是mmc core层与主机层的接口,mmc_host.ops是控制主机完成用户请求的接口函数集,其类型是struct mmc_host_ops,该结构体定义在include / linux / mmc / host.h文件中:
- 83structmmc_host_ops {
- 84 / *
- 85 *“启用”在主机被声明时被调用,并且“禁用”被调用
- 86 *当主机被释放时。“启用”和“禁用”已被弃用。
- 87 * /
- 88 int (* enable)(struct mmc_host * host);
- 89 int (* disable)(struct mmc_host * host);
- 90 / *
- 91 *主机可以实现pre_req和post_req
- 92 *命令来支持请求的双缓冲(准备一个
- 93 *请求,而另一个请求是活动的)。
- 94 * pre_req()必须后跟post_req()。
- 95 *撤消对pre_req()的调用,调用post_req()
- 96 *非零错误条件。
- 97 * /
- 98 void (* post_req)(structmmc_host * host, struct mmc_request * req,
- 99 int err);
- 100 void (* pre_req)(struct mmc_host * host, struct mmc_request * req,
- 101 bool is_first_req);
- 102 void (* request)(struct mmc_host * host, struct mmc_request * req);
- 103 / *
- 104 *避免频繁地调用这三个函数,或者在“fastpath”中,
- 105 *因为底层控制器可能会以昂贵的方式实施它们
- 106 *和/或缓慢的方式。
- 107 *
- 108 *另请注意,这些功能可能会休眠,所以不要打电话给他们
- 109 *在原子语境中!
- 110 *
- 111 * get_ro回调函数的返回值应为:
- 112 * 0用于读/写卡
- 113 * 1用于只读卡
- 114 * -ENOSYS不支持时(等于NULL回调)
- 115 *或错误发生错误的负errno值
- 116 *
- 117 * get_cd回调的返回值应为:
- 118 * 0为缺席卡
- 119 * 1为现在的卡
- 不支持120 * -ENOSYS(等于NULL回调)
- 121 *或错误发生错误的负errno值
- 122 * /
- 123 void (* set_ios)(struct mmc_host * host, struct mmc_ios * ios);
- 124 int (* get_ro)(struct mmc_host * host);
- 125 int (* get_cd)(struct mmc_host * host);
- 126
- 127 void (* enable_sdio_irq)(structmmc_host * host, int enable);
- 128
- 129 / *可选回调HC怪癖* /
- 130 void (* init_card)(struct mmc_host * host, struct mmc_card * card);
- 131
- 132 int (* start_signal_voltage_switch)(struct mmc_host * host, struct mmc_ios * ios);
- 133
- 134 / *检查卡是否正在拉dat [0:3]低*
- 135 int (* card_busy)(struct mmc_host * host);
- 136
- 137 / * SD和eMMC卡的调谐命令操作码值不同* /
- 138 int (* execute_tuning)(struct mmc_host * host,u32 opcode);
- 139 int (* select_drive_strength)(unsigned int max_dtr, int host_drv,intcard_drv);
- 140 void (* hw_reset)(struct mmc_host * host);
- 141 void (* card_event)(structmmc_host * host);
- 142};
请求函数用于处理用户的请求。
set_ios函数用于设置SDI的控制参数,如时钟,总线宽度等等。
get_ro函数用于探测SD卡是否有写保护。
get_cd函数用于探测卡是否已插入插槽。
enable_sdio_irq函数用于启动或禁用SDI中断。
需要注意的是,为什么没有对MMC / SD进行读写的读取和写入函数呢?这是因为Linux的块设备的读写操作是通过请求函数完成的。
那么对于mini2440的,它的s3cmci_ops中的成员函数在什么时候会被调用呢举例如下?
在驱动器/ MMC /核心/ core.c文件中:
- 194staticvoid
- 195mmc_start_request(struct mmc_host * host,struct mmc_request * mrq)
- 196 {
- 197#ifdef CONFIG_MMC_DEBUG
- 198 unsigned int i,sz;
- 199 struct scatterlist * sg;
- 200#ENDIF
- 201
- 202 if (mrq-> sbc){
- 203 pr_debug(“<%s:starting CMD%u arg%08x flags%08x> \ n” ,
- 204 mm