Linux SD Driver (四)
2、mmc_start_host & mmc_stop_host
mmc_start_host 用来启动一个host,mmc_stop_host用来停止一个host。
当底层host controller调用mmc_add_host来注册host时,在mmc_add_host中就会调用mmc_start_host来
启动一个host了。具体参考《mmc core——host模块说明》。
相对应的,会在mmc_remove_host中调用mmc_stop_host停止host。
voidmmc_start_host(structmmc_host *host)
{
mmc_claim_host(host);// 因为上电操作涉及到对host的使用和设置,需要先占用
host host->f_init =max(freqs[0], host->f_min); // 通过最小频率要设置初始化频率
host->rescan_disable = 0; // 设置rescan_disable标志为0,说明已经可以进行card检测了
if(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)
// 如果mmc属性设置了MMC_CAP2_NO_PRESCAN_POWERUP,也就是在rescan前不需要进行
power up操作时,则进行关电
mmc_power_off(host);
elsemmc_power_up(host); // 否则,调用mmc_power_up对host进行上电操作。
这里也是mmc core中启动host的核心函数。
3.
static struct mmc_host_ops mt_msdc_ops= {.post_req = msdc_post_req,
.pre_req = msdc_pre_req,
.request = msdc_ops_request,
.tuning =msdc_tune_async_request,
.set_ios =msdc_ops_set_ios,
.get_ro =msdc_ops_get_ro,
.get_cd =msdc_ops_get_cd,
.enable_sdio_irq = msdc_ops_enable_sdio_irq,
.start_signal_voltage_switch = msdc_ops_switch_volt,
.send_stop = msdc_ops_stop,
.dma_error_reset = msdc_dma_error_reset,
.check_written_data = msdc_check_written_data,
};
static void
mmc_start_request(struct mmc_host*host, struct mmc_request *mrq)
{
#ifdef CONFIG_MMC_DEBUG
unsignedint i, sz;
structscatterlist *sg;
#endif
staticint __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
{
init_completion(&mrq->completion);
mrq->done = mmc_wait_done;
if (mmc_card_removed(host->card)) {
mrq->cmd->error =-ENOMEDIUM;
complete(&mrq->completion);
return -ENOMEDIUM;
}
mmc_start_request(host, mrq); ------- host->ops->request(host, mrq);
return 0;
}
4. 函数完成块设备驱动的模块加载模板
static structmmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
struct device *parent,
sector_t size,
booldefault_ro,
constchar *subname,
intarea_type)
{
md->queue.issue_fn = mmc_blk_issue_rq;
md->queue.data = md;
md->disk->major =MMC_BLOCK_MAJOR;
md->disk->first_minor = devidx * perdev_minors;
md->disk->fops =&mmc_bdops;