zoukankan      html  css  js  c++  java
  • 【转】linux设备驱动之MMC SD卡——核心层简单分析

    原文网址:http://blog.chinaunix.net/uid-28685940-id-3889878.html

    /*************************************************************************************************************************************/
    /* bus.c */

    /*
     *  linux/drivers/mmc/core/bus.c
     *
     *  Copyright (C) 2003 Russell King, All Rights Reserved.
     *  Copyright (C) 2007 Pierre Ossman
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     *
     *  MMC card bus driver model
     */

    #include <linux/device.h>
    #include <linux/err.h>

    #include <linux/mmc/card.h>
    #include <linux/mmc/host.h>

    #include "core.h"
    #include "sdio_cis.h"
    #include "bus.h"

    #define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev)
    #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)

    /*显示mmc类型 */
    static ssize_t mmc_type_show(struct device *dev,
     struct device_attribute *attr, char *buf)
    {
     struct mmc_card *card = dev_to_mmc_card(dev);

     switch (card->type) {
     case MMC_TYPE_MMC:
      return sprintf(buf, "MMC ");
     case MMC_TYPE_SD:
      return sprintf(buf, "SD ");
     case MMC_TYPE_SDIO:
      return sprintf(buf, "SDIO ");
     default:
      return -EFAULT;
     }
    }

    static struct device_attribute mmc_dev_attrs[] = {  /* 设备属性文件 */
     __ATTR(type, S_IRUGO, mmc_type_show, NULL),
     __ATTR_NULL,
    };

    /*
     * This currently matches any MMC driver to any MMC card - drivers
     * themselves make the decision whether to drive this card in their
     * probe method.
     */
     /* 匹配函数 */
    static int mmc_bus_match(struct device *dev, struct device_driver *drv)
    {
     return 1;
    }

    /* 热插拔事件处理函数 */
    static int
    mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
    {
     struct mmc_card *card = dev_to_mmc_card(dev);
     const char *type;
     int retval = 0;

     switch (card->type) {
     case MMC_TYPE_MMC:
      type = "MMC";
      break;
     case MMC_TYPE_SD:
      type = "SD";
      break;
     case MMC_TYPE_SDIO:
      type = "SDIO";
      break;
     default:
      type = NULL;
     }

     if (type) {
      retval = add_uevent_var(env, "MMC_TYPE=%s", type);  /* 添加ueven环境变量 */
      if (retval)
       return retval;
     }

     retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card));
     if (retval)
      return retval;

     /*
      * Request the mmc_block device.  Note: that this is a direct request
      * for the module it carries no information as to what is inserted.
      */
     retval = add_uevent_var(env, "MODALIAS=mmc:block");

     return retval;
    }

    /* 探测函数 */
    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->probe(card); /* 调用struct mmc_driver 的probe函数来挂起设备----由此可见probe函数必须提供 */
    }

    /* 移除函数 */
    static int mmc_bus_remove(struct device *dev)
    {
     struct mmc_driver *drv = to_mmc_driver(dev->driver);
     struct mmc_card *card = dev_to_mmc_card(dev);

     drv->remove(card); /* 调用struct mmc_driver 的remove函数来挂起设备----由此可见remove函数必须提供 */

     return 0;
    }

     /* 挂起函数 */
    static int mmc_bus_suspend(struct device *dev, pm_message_t state)
    {
     struct mmc_driver *drv = to_mmc_driver(dev->driver);
     struct mmc_card *card = dev_to_mmc_card(dev);
     int ret = 0;

     if (dev->driver && drv->suspend)
      ret = drv->suspend(card, state);  /* 调用struct mmc_driver 的suspend函数来挂起设备 */
     return ret;
    }

    /* 恢复函数 */
    static int mmc_bus_resume(struct device *dev)
    {
     struct mmc_driver *drv = to_mmc_driver(dev->driver);
     struct mmc_card *card = dev_to_mmc_card(dev);
     int ret = 0;

     if (dev->driver && drv->resume)
      ret = drv->resume(card);  /* 调用struct mmc_driver 的resume函数来恢复设备 */
     return ret;
    }

    static struct bus_type mmc_bus_type = {  /* 总线类型 */
     .name  = "mmc",     /* 总线类型为mmc,会在/sys/bus目录下创建一个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, /* 恢复函数 */
    };

    int mmc_register_bus(void)
    {
     return bus_register(&mmc_bus_type);  /* 向设备模型核心注册一条总线 */
    }

    void mmc_unregister_bus(void)
    {
     bus_unregister(&mmc_bus_type);  /* 注销总线 */
    }

    /**
     * mmc_register_driver - register a media driver
     * @drv: MMC media driver
     */
     /* 注册mmc驱动 */
    int mmc_register_driver(struct mmc_driver *drv)
    {
     drv->drv.bus = &mmc_bus_type; 
     return driver_register(&drv->drv); /* 向驱动模型核心注册驱动 */
    }

    EXPORT_SYMBOL(mmc_register_driver);

    /**
     * mmc_unregister_driver - unregister a media driver
     * @drv: MMC media driver
     */
     /* 注销mmc驱动 */
    void mmc_unregister_driver(struct mmc_driver *drv)
    {
     drv->drv.bus = &mmc_bus_type;
     driver_unregister(&drv->drv);
    }

    EXPORT_SYMBOL(mmc_unregister_driver);

    /* 释放SD卡描述结构体----struct mmc_card */
    static void mmc_release_card(struct device *dev)
    {
     struct mmc_card *card = dev_to_mmc_card(dev);

     sdio_free_common_cis(card);

     if (card->info)
      kfree(card->info);

     kfree(card);
    }

    /*
     * Allocate and initialise a new MMC card structure.
     */
     /* 分配并初始化一个SD卡描述结构体--struct mmc_card- */
    struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
    {
     struct mmc_card *card;

     card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);  /* 分配一个struct mmc_card结构体 */
     if (!card)
      return ERR_PTR(-ENOMEM);
           /* 初始化其成员 */
     card->host = host;

     device_initialize(&card->dev);  /* 初始化设备 */

     card->dev.parent = mmc_classdev(host);
     card->dev.bus = &mmc_bus_type;
     card->dev.release = mmc_release_card;
     card->dev.type = type;

     return card;
    }

    /*
     * Register a new MMC card with the driver model.
     */
     /* 注册一个MMC卡到驱动模型 */
    int mmc_add_card(struct mmc_card *card)
    {
     int ret;
     const char *type;

     dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);  /* 设置设备的名字 */

     switch (card->type) {
     case MMC_TYPE_MMC:
      type = "MMC";
      break;
     case MMC_TYPE_SD:
      type = "SD";
      if (mmc_card_blockaddr(card))
       type = "SDHC";
      break;
     case MMC_TYPE_SDIO:
      type = "SDIO";
      break;
     default:
      type = "?";
      break;
     }

     if (mmc_host_is_spi(card->host)) {  /* 如果mmc主机控制器使用的是SPI总线 */
      printk(KERN_INFO "%s: new %s%s card on SPI ",
       mmc_hostname(card->host),
       mmc_card_highspeed(card) ? "high speed " : "",
       type);
     } else {
      printk(KERN_INFO "%s: new %s%s card at address %04x ",
       mmc_hostname(card->host),
       mmc_card_highspeed(card) ? "high speed " : "",
       type, card->rca);
     }

     ret = device_add(&card->dev);  /* 向设备驱动模型核心添加一个设备 */
     if (ret)
      return ret;

    #ifdef CONFIG_DEBUG_FS
     mmc_add_card_debugfs(card);
    #endif

     mmc_card_set_present(card);

     return 0;
    }

    /*
     * Unregister a new MMC card with the driver model, and
     * (eventually) free it.
     */
     /*注销一个MMC卡从驱动模型 */
    void mmc_remove_card(struct mmc_card *card)
    {
    #ifdef CONFIG_DEBUG_FS
     mmc_remove_card_debugfs(card);
    #endif

     if (mmc_card_present(card)) {
      if (mmc_host_is_spi(card->host)) {
       printk(KERN_INFO "%s: SPI card removed ",
        mmc_hostname(card->host));
      } else {
       printk(KERN_INFO "%s: card %04x removed ",
        mmc_hostname(card->host), card->rca);
      }
      device_del(&card->dev);  /* 从设备驱动模型核心删除 */
     }

     put_device(&card->dev); /* 减小设备的引用计数 */
    }

     /*************************************************************************************************************************************/
    /* core.h */

    /*
     *  linux/drivers/mmc/core/core.h
     *
     *  Copyright (C) 2003 Russell King, All Rights Reserved.
     *  Copyright 2007 Pierre Ossman
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */

    /*
          SD卡内部结构:
             ______________________________________________________________________________
           /              --         --           --          --          --          --          --         --                                   |
         /   --         ||          ||           ||          ||         ||          ||          ||          ||                                   |
       /     ||         ||          ||           ||          ||         ||          ||          ||          ||                                   |
     /       ||         --          --           --          --         --          --          --          --                                    |
    |        --          |            |            |            |           |            |           |            |                                |
    |        ↓       ↓        ↓         ↓        ↓       ↓        ↓        ↓        ↓                                 |
    |   DATA2   CD/DATA3 CMD       GND       VDD       CLK      GND       DATA0     DATA1                        |
    |                                                                                                                                                 |
    |             ----------                         -------------------------------------                                                    |
    |            |OCR[31:0]|<---->|                                                    |                                                    |
    |             ----------              |                                                     |                                                   |
    |             ----------              |                                                     |                                                   |
    |            |CID[127:0]|<--> |                                                     |                                                    |
    |             ----------              |                                                     |                                                    |
    |            -----------             |                        Card                       |                                                    |
    |            |RCA[15:0]|<--->|                      interface                    |                                                    |
    |            -----------             |                      controller                  |                                                    |
    |            -----------             |                                                     |                                                    |
    |            |DSR[15:0]|<--->|                                                     |            ------                                  |
    |            -----------             |                                                     |           |  P    |                                |
    |            -----------             |                                                     |           |  o    |                                |
    |            |CSD[127:0]|<-->|                                                    |<-----    |  w    |                               |
    |            -----------             |                                                     |           |  e    |                                |
    |            -----------             |                                                     |           |  r     |                                |
    |            |SCR[63:0] |<--> |                                                     |           |        |                                |
    |                                            --------------------------------------                |  o     |                                |
    |                                                                                                         |  n    |                                |
    |                                                                                                          |        |                               |
    |     ---------------------------------------------------------------       |  d    |                                                    |
    |    |                                  Memory core interface                      reset|<--|  e    |                                |
    |     ---------------------------------------------------------------       |   t    |                                                    |
    |                                                         ↑                                                 |   e    |                             |
    |                                                          |                                                |   c    |                              |
    |                                                          |                                                 |   t     |                             |
    |                                                          |                                                 |   i     |                              |
    |                                                          |                                                 |   o    |                              |
    |                                                         ↓                                                  |   n    |                              |
    |  -----------------------------------------------------------------       ------                        |
    | |                                                                                                               |                                    |
    | |                                                                                                               |                                    |
    | |                                                                                                               |                                    |
    | |                                                                                                               |                                    |
    | |                                            Memory   core                                              |                                     |
    | |                                                                                                               |                                    
    | |                                                                                                               |                                    |
    | |                                                                                                               |                                    |
    | |                                                                                                               |                                    |
    |  ----------------------------------------------------------------                                                                          |
    _______________________________________________________________________________________


    OCR寄存器:操作条件寄存器
    SCR寄存器:SD配置寄存器----保存卡的特殊功能信息
    CSD寄存器:卡的特殊数据寄存器----卡的操作条件信息
    DSR寄存器:驱动配置寄存器----用来配置卡的输出驱动
    RCA寄存器:卡的相对地址----本地系统中卡的地址,动态变化,在主机初始化的时候确定
    CID寄存器:卡的识别序列号
    */
    #ifndef _MMC_CORE_CORE_H
    #define _MMC_CORE_CORE_H

    #include <linux/delay.h>

    #define MMC_CMD_RETRIES        3

    struct mmc_bus_ops {  /* mmc总线操作函数集 */
     void (*remove)(struct mmc_host *);  /* 移除 */
     void (*detect)(struct mmc_host *);   /* 探测 */
     void (*suspend)(struct mmc_host *); /* 挂起 */
     void (*resume)(struct mmc_host *);  /* 恢复 */
    };

    void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
    void mmc_detach_bus(struct mmc_host *host);

    void mmc_set_chip_select(struct mmc_host *host, int mode);
    void mmc_set_clock(struct mmc_host *host, unsigned int hz);
    void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
    void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
    u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
    void mmc_set_timing(struct mmc_host *host, unsigned int timing);

    /* 延时ms毫秒 */
    static inline void mmc_delay(unsigned int ms)
    {
     if (ms < 1000 / HZ) {
      cond_resched();
      mdelay(ms);
     } else {
      msleep(ms);
     }
    }

    void mmc_rescan(struct work_struct *work);
    void mmc_start_host(struct mmc_host *host);
    void mmc_stop_host(struct mmc_host *host);

    int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
    int mmc_attach_sd(struct mmc_host *host, u32 ocr);
    int mmc_attach_sdio(struct mmc_host *host, u32 ocr);

    extern int use_spi_crc;

    /* Debugfs information for hosts and cards */
    void mmc_add_host_debugfs(struct mmc_host *host);
    void mmc_remove_host_debugfs(struct mmc_host *host);

    void mmc_add_card_debugfs(struct mmc_card *card);
    void mmc_remove_card_debugfs(struct mmc_card *card);

    #endif
    /*************************************************************************************************************************************/
    /* core.c */

    /*
     *  linux/drivers/mmc/core/core.c
     *
     *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
     *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
     *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
     *  MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved.
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/interrupt.h>
    #include <linux/completion.h>
    #include <linux/device.h>
    #include <linux/delay.h>
    #include <linux/pagemap.h>
    #include <linux/err.h>
    #include <linux/leds.h>
    #include <linux/scatterlist.h>
    #include <linux/log2.h>
    #include <linux/regulator/consumer.h>

    #include <linux/mmc/card.h>
    #include <linux/mmc/host.h>
    #include <linux/mmc/mmc.h>
    #include <linux/mmc/sd.h>

    #include "core.h"
    #include "bus.h"
    #include "host.h"
    #include "sdio_bus.h"

    #include "mmc_ops.h"
    #include "sd_ops.h"
    #include "sdio_ops.h"

    static struct workqueue_struct *workqueue;

    /*
     * Enabling software CRCs on the data blocks can be a significant (30%)
     * performance cost, and for other reasons may not always be desired.
     * So we allow it it to be disabled.
     */
    int use_spi_crc = 1;
    module_param(use_spi_crc, bool, 0);

    /*
     * Internal function. Schedule delayed work in the MMC work queue.
     */
     /* 调度mmc工作队列上延时工作 */
    static int mmc_schedule_delayed_work(struct delayed_work *work,
             unsigned long delay)
    {
     return queue_delayed_work(workqueue, work, delay);
    }

    /*
     * Internal function. Flush all scheduled work from the MMC work queue.
     */
    static void mmc_flush_scheduled_work(void)
    {
     flush_workqueue(workqueue);
    }

    /**
     * mmc_request_done - finish processing an MMC request
     * @host: MMC host which completed request
     * @mrq: MMC request which request
     *
     * MMC drivers should call this function when they have completed
     * their processing of a request.
     */
     /* 完成处理一个mmc请求 */
    void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
    {
     struct mmc_command *cmd = mrq->cmd;
     int err = cmd->error;

     if (err && cmd->retries && mmc_host_is_spi(host)) {
      if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND)
       cmd->retries = 0;
     }

     if (err && cmd->retries) {
      pr_debug("%s: req failed (CMD%u): %d, retrying... ",
       mmc_hostname(host), cmd->opcode, err);

      cmd->retries--;
      cmd->error = 0;
      host->ops->request(host, mrq);  /* 如果出现错误并且重复次数不为0则再次调用请求处理函数来处理请求 */
     } else {
      led_trigger_event(host->led, LED_OFF);

      pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x ",
       mmc_hostname(host), cmd->opcode, err,
       cmd->resp[0], cmd->resp[1],
       cmd->resp[2], cmd->resp[3]);

      if (mrq->data) {
       pr_debug("%s:     %d bytes transferred: %d ",
        mmc_hostname(host),
        mrq->data->bytes_xfered, mrq->data->error);
      }

      if (mrq->stop) {
       pr_debug("%s:     (CMD%u): %d: %08x %08x %08x %08x ",
        mmc_hostname(host), mrq->stop->opcode,
        mrq->stop->error,
        mrq->stop->resp[0], mrq->stop->resp[1],
        mrq->stop->resp[2], mrq->stop->resp[3]);
      }

      if (mrq->done)
       mrq->done(mrq);  /* 如果 struct mmc_request mrq->done有定义则调用该完成回调函数*/
     }
    }

    EXPORT_SYMBOL(mmc_request_done);

     /* 开始一个请求 */
    static void
    mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
    {
    #ifdef CONFIG_MMC_DEBUG
     unsigned int i, sz;
     struct scatterlist *sg;
    #endif

     pr_debug("%s: starting CMD%u arg %08x flags %08x ",
       mmc_hostname(host), mrq->cmd->opcode,
       mrq->cmd->arg, mrq->cmd->flags);

     if (mrq->data) {
      pr_debug("%s:     blksz %d blocks %d flags %08x "
       "tsac %d ms nsac %d ",
       mmc_hostname(host), mrq->data->blksz,
       mrq->data->blocks, mrq->data->flags,
       mrq->data->timeout_ns / 1000000,
       mrq->data->timeout_clks);
     }

     if (mrq->stop) {
      pr_debug("%s:     CMD%u arg %08x flags %08x ",
        mmc_hostname(host), mrq->stop->opcode,
        mrq->stop->arg, mrq->stop->flags);
     }

     WARN_ON(!host->claimed);

     led_trigger_event(host->led, LED_FULL);

     mrq->cmd->error = 0;
     mrq->cmd->mrq = mrq;
     if (mrq->data) {
      BUG_ON(mrq->data->blksz > host->max_blk_size);
      BUG_ON(mrq->data->blocks > host->max_blk_count);
      BUG_ON(mrq->data->blocks * mrq->data->blksz >
       host->max_req_size);

    #ifdef CONFIG_MMC_DEBUG
      sz = 0;
      for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i)
       sz += sg->length;
      BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
    #endif

      mrq->cmd->data = mrq->data;
      mrq->data->error = 0;
      mrq->data->mrq = mrq;
      if (mrq->stop) {
       mrq->data->stop = mrq->stop;
       mrq->stop->error = 0;
       mrq->stop->mrq = mrq;
      }
     }
     host->ops->request(host, mrq);  /* 调用host->ops->request请求处理函数来完成mmc协议的命令处理 */
    }

    /* 请求完成回调函数 */
    static void mmc_wait_done(struct mmc_request *mrq)
    {
     complete(mrq->done_data);  /* 唤醒等待队列中睡眠进程 */
    }

    /**
     * mmc_wait_for_req - start a request and wait for completion
     * @host: MMC host to start command
     * @mrq: MMC request to start
     *
     * Start a new MMC custom command request for a host, and wait
     * for the command to complete. Does not attempt to parse the
     * response.
     */
     /* 开始一个 请求并等待它完成 */
    void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
    {
     DECLARE_COMPLETION_ONSTACK(complete);

     mrq->done_data = &complete;
     mrq->done = mmc_wait_done;  /* 设置请求完成回调函数 */

     mmc_start_request(host, mrq);  /* 开始一个请求 */

     wait_for_completion(&complete); /* 等待请求完成 */
    }

    EXPORT_SYMBOL(mmc_wait_for_req);

    /**
     * mmc_wait_for_cmd - start a command and wait for completion
     * @host: MMC host to start command
     * @cmd: MMC command to start
     * @retries: maximum number of retries
     *
     * Start a new MMC command for a host, and wait for the command
     * to complete.  Return any error that occurred while the command
     * was executing.  Do not attempt to parse the response.
     */
     /* 发送一个命令并等待它完成 */
    int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
    {
     struct mmc_request mrq;

     WARN_ON(!host->claimed);

     memset(&mrq, 0, sizeof(struct mmc_request));

     memset(cmd->resp, 0, sizeof(cmd->resp));
     cmd->retries = retries;

     mrq.cmd = cmd;  /* 指向命令 */
     cmd->data = NULL;  /* 没有数据 */

     mmc_wait_for_req(host, &mrq);  /* 开始一个请求并等待它完成 */

     return cmd->error;
    }

    EXPORT_SYMBOL(mmc_wait_for_cmd);

    /**
     * mmc_set_data_timeout - set the timeout for a data command
     * @data: data phase for command
     * @card: the MMC card associated with the data transfer
     *
     * Computes the data timeout parameters according to the
     * correct algorithm given the card type.
     */
     /* 设置一个数据命令的超时时间 */
    void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
    {
     unsigned int mult;

     /*
      * SDIO cards only define an upper 1 s limit on access.
      */
     if (mmc_card_sdio(card)) {  /* 如果是SDIO卡 */
      data->timeout_ns = 1000000000;
      data->timeout_clks = 0;
      return;
     }

     /*
      * SD cards use a 100 multiplier rather than 10
      */
     mult = mmc_card_sd(card) ? 100 : 10;

     /*
      * Scale up the multiplier (and therefore the timeout) by
      * the r2w factor for writes.
      */
     if (data->flags & MMC_DATA_WRITE)
      mult <<= card->csd.r2w_factor;

     data->timeout_ns = card->csd.tacc_ns * mult;
     data->timeout_clks = card->csd.tacc_clks * mult;

     /*
      * SD cards also have an upper limit on the timeout.
      */
     if (mmc_card_sd(card)) {
      unsigned int timeout_us, limit_us;

      timeout_us = data->timeout_ns / 1000;
      timeout_us += data->timeout_clks * 1000 /
       (card->host->ios.clock / 1000);

      if (data->flags & MMC_DATA_WRITE)
       /*
        * The limit is really 250 ms, but that is
        * insufficient for some crappy cards.
        */
       limit_us = 300000;
      else
       limit_us = 100000;

      /*
       * SDHC cards always use these fixed values.
       */
      if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
       data->timeout_ns = limit_us * 1000;
       data->timeout_clks = 0;
      }
     }
     /*
      * Some cards need very high timeouts if driven in SPI mode.
      * The worst observed timeout was 900ms after writing a
      * continuous stream of data until the internal logic
      * overflowed.
      */
     if (mmc_host_is_spi(card->host)) {
      if (data->flags & MMC_DATA_WRITE) {
       if (data->timeout_ns < 1000000000)
        data->timeout_ns = 1000000000; /* 1s */
      } else {
       if (data->timeout_ns < 100000000)
        data->timeout_ns =  100000000; /* 100ms */
      }
     }
    }
    EXPORT_SYMBOL(mmc_set_data_timeout);

    /**
     * mmc_align_data_size - pads a transfer size to a more optimal value
     * @card: the MMC card associated with the data transfer
     * @sz: original transfer size
     *
     * Pads the original data size with a number of extra bytes in
     * order to avoid controller bugs and/or performance hits
     * (e.g. some controllers revert to PIO for certain sizes).
     *
     * Returns the improved size, which might be unmodified.
     *
     * Note that this function is only relevant when issuing a
     * single scatter gather entry.
     */
    unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz)
    {
     /*
      * FIXME: We don't have a system for the controller to tell
      * the core about its problems yet, so for now we just 32-bit
      * align the size.
      */
     sz = ((sz + 3) / 4) * 4;

     return sz;
    }
    EXPORT_SYMBOL(mmc_align_data_size);

    /**
     * __mmc_claim_host - exclusively claim a host
     * @host: mmc host to claim
     * @abort: whether or not the operation should be aborted
     *
     * Claim a host for a set of operations.  If @abort is non null and
     * dereference a non-zero value then this will return prematurely with
     * that non-zero value without acquiring the lock.  Returns zero
     * with the lock held otherwise.
     */
     /* 声明主机控制器 */
    int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
    {
     DECLARE_WAITQUEUE(wait, current);  /* 定义并初始化一个等待队列 wait*/
     unsigned long flags;
     int stop;

     might_sleep();

     add_wait_queue(&host->wq, &wait);  /* 将 host->wq添加到等待队列wait*/
     spin_lock_irqsave(&host->lock, flags);
     while (1) {
      set_current_state(TASK_UNINTERRUPTIBLE);  /* 设置当前进程的状态为TASK_UNINTERRUPTIBLE */
      stop = abort ? atomic_read(abort) : 0;  /* stop= abort? abort->counter:0?*/
      if (stop || !host->claimed)  /* 当stop=1或者 host->claimed=0时则继续循环*/
       break;
      spin_unlock_irqrestore(&host->lock, flags);
      schedule();  /* 将进程调度处CPU----进程进入休眠 */
      spin_lock_irqsave(&host->lock, flags);
     }
     set_current_state(TASK_RUNNING);  /* 设置当前进程状态为TASK_RUNNING----CPU会调度该进程运行 */
     if (!stop)  /* 如果stop=0则设置 host->claimed = 1,否则*/
      host->claimed = 1;
     else
      wake_up(&host->wq);  /* 唤醒等待队列 host->wq上的进程*/
     spin_unlock_irqrestore(&host->lock, flags);
     remove_wait_queue(&host->wq, &wait);  /* 将host->wq从wait中移除 */
     return stop;
    }

    EXPORT_SYMBOL(__mmc_claim_host);

    /**
     * mmc_release_host - release a host
     * @host: mmc host to release
     *
     * Release a MMC host, allowing others to claim the host
     * for their operations.
     */
     /* 释放主机 */
    void mmc_release_host(struct mmc_host *host)
    {
     unsigned long flags;

     WARN_ON(!host->claimed);

     spin_lock_irqsave(&host->lock, flags);
     host->claimed = 0;
     spin_unlock_irqrestore(&host->lock, flags);

     wake_up(&host->wq);  /*  唤醒host->wq上的进程*/
    }

    EXPORT_SYMBOL(mmc_release_host);

    /*
     * Internal function that does the actual ios call to the host driver,
     * optionally printing some debug output.
     */
     /* 设置卡的I/O状态 */
    static inline void mmc_set_ios(struct mmc_host *host)
    {
     struct mmc_ios *ios = &host->ios;

     pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
      "width %u timing %u ",
       mmc_hostname(host), ios->clock, ios->bus_mode,
       ios->power_mode, ios->chip_select, ios->vdd,
       ios->bus_width, ios->timing);

     host->ops->set_ios(host, ios);  /* 调用 struct mmc_host *host->ops->set_ios函数来对卡的I/O状态的进行设置*/
    }

    /*
     * Control chip select pin on a host.
     */
     /* 设置芯片片选 */
    void mmc_set_chip_select(struct mmc_host *host, int mode)
    {
     host->ios.chip_select = mode;
     mmc_set_ios(host);
    }

    /*
     * Sets the host clock to the highest possible frequency that
     * is below "hz".
     */
     /* 设置主机控制器时钟 */
    void mmc_set_clock(struct mmc_host *host, unsigned int hz)
    {
     WARN_ON(hz < host->f_min);

     if (hz > host->f_max)
      hz = host->f_max;

     host->ios.clock = hz;
     mmc_set_ios(host);
    }

    /*
     * Change the bus mode (open drain/push-pull) of a host.
     */
     /* 设置总线模式 */
    void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
    {
     host->ios.bus_mode = mode;
     mmc_set_ios(host);
    }

    /*
     * Change data bus width of a host.
     */
     /* 设置总线宽度 */
    void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
    {
     host->ios.bus_width = width;
     mmc_set_ios(host);
    }

    /**
     * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number
     * @vdd: voltage (mV)
     * @low_bits: prefer low bits in boundary cases
     *
     * This function returns the OCR bit number according to the provided @vdd
     * value. If conversion is not possible a negative errno value returned.
     *
     * Depending on the @low_bits flag the function prefers low or high OCR bits
     * on boundary voltages. For example,
     * with @low_bits = true, 3300 mV translates to ilog2(MMC_VDD_32_33);
     * with @low_bits = false, 3300 mV translates to ilog2(MMC_VDD_33_34);
     *
     * Any value in the [1951:1999] range translates to the ilog2(MMC_VDD_20_21).
     */
     /* 将一个电压值转换为OCR寄存器的比特编号 */
    static int mmc_vdd_to_ocrbitnum(int vdd, bool low_bits)
    {
     const int max_bit = ilog2(MMC_VDD_35_36);
     int bit;

     if (vdd < 1650 || vdd > 3600)
      return -EINVAL;

     if (vdd >= 1650 && vdd <= 1950)
      return ilog2(MMC_VDD_165_195);

     if (low_bits)
      vdd -= 1;

     /* Base 2000 mV, step 100 mV, bit's base 8. */
     bit = (vdd - 2000) / 100 + 8;
     if (bit > max_bit)
      return max_bit;
     return bit;
    }

    /**
     * mmc_vddrange_to_ocrmask - Convert a voltage range to the OCR mask
     * @vdd_min: minimum voltage value (mV)
     * @vdd_max: maximum voltage value (mV)
     *
     * This function returns the OCR mask bits according to the provided @vdd_min
     * and @vdd_max values. If conversion is not possible the function returns 0.
     *
     * Notes wrt boundary cases:
     * This function sets the OCR bits for all boundary voltages, for example
     * [3300:3400] range is translated to MMC_VDD_32_33 | MMC_VDD_33_34 |
     * MMC_VDD_34_35 mask.
     */
     /* 将一个电压等级转换为寄存器OCR的掩码 */
    u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
    {
     u32 mask = 0;

     if (vdd_max < vdd_min)
      return 0;

     /* Prefer high bits for the boundary vdd_max values. */
     vdd_max = mmc_vdd_to_ocrbitnum(vdd_max, false);
     if (vdd_max < 0)
      return 0;

     /* Prefer low bits for the boundary vdd_min values. */
     vdd_min = mmc_vdd_to_ocrbitnum(vdd_min, true);
     if (vdd_min < 0)
      return 0;

     /* Fill the mask, from max bit to min bit. */
     while (vdd_max >= vdd_min)
      mask |= 1 << vdd_max--;

     return mask;
    }
    EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);

    #ifdef CONFIG_REGULATOR

    /**
     * mmc_regulator_get_ocrmask - return mask of supported voltages
     * @supply: regulator to use
     *
     * This returns either a negative errno, or a mask of voltages that
     * can be provided to MMC/SD/SDIO devices using the specified voltage
     * regulator.  This would normally be called before registering the
     * MMC host adapter.
     */
     /*返回支持的电压的掩码 */
    int mmc_regulator_get_ocrmask(struct regulator *supply)
    {
     int   result = 0;
     int   count;
     int   i;

     count = regulator_count_voltages(supply);
     if (count < 0)
      return count;

     for (i = 0; i < count; i++) {
      int  vdd_uV;
      int  vdd_mV;

      vdd_uV = regulator_list_voltage(supply, i);
      if (vdd_uV <= 0)
       continue;

      vdd_mV = vdd_uV / 1000;
      result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
     }

     return result;
    }
    EXPORT_SYMBOL(mmc_regulator_get_ocrmask);

    /**
     * mmc_regulator_set_ocr - set regulator to match host->ios voltage
     * @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
     * @supply: regulator to use
     *
     * Returns zero on success, else negative errno.
     *
     * MMC host drivers may use this to enable or disable a regulator using
     * a particular supply voltage.  This would normally be called from the
     * set_ios() method.
     */
     /* 设置调节器使得其能够匹配 host->ios voltage*/
    int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit)
    {
     int   result = 0;
     int   min_uV, max_uV;
     int   enabled;

     enabled = regulator_is_enabled(supply);
     if (enabled < 0)
      return enabled;

     if (vdd_bit) {
      int  tmp;
      int  voltage;

      /* REVISIT mmc_vddrange_to_ocrmask() may have set some
       * bits this regulator doesn't quite support ... don't
       * be too picky, most cards and regulators are OK with
       * a 0.1V range goof (it's a small error percentage).
       */
      tmp = vdd_bit - ilog2(MMC_VDD_165_195);
      if (tmp == 0) {
       min_uV = 1650 * 1000;
       max_uV = 1950 * 1000;
      } else {
       min_uV = 1900 * 1000 + tmp * 100 * 1000;
       max_uV = min_uV + 100 * 1000;
      }

      /* avoid needless changes to this voltage; the regulator
       * might not allow this operation
       */
      voltage = regulator_get_voltage(supply);
      if (voltage < 0)
       result = voltage;
      else if (voltage < min_uV || voltage > max_uV)
       result = regulator_set_voltage(supply, min_uV, max_uV);
      else
       result = 0;

      if (result == 0 && !enabled)
       result = regulator_enable(supply);
     } else if (enabled) {
      result = regulator_disable(supply);
     }

     return result;
    }
    EXPORT_SYMBOL(mmc_regulator_set_ocr);

    #endif

    /*
     * Mask off any voltages we don't support and select
     * the lowest voltage
     */
     /* 选择电压 
        屏蔽不支持的电压并且选择最低的工作电压 */
    u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
    {
     int bit;

     ocr &= host->ocr_avail;

     bit = ffs(ocr);
     if (bit) {
      bit -= 1;

      ocr &= 3 << bit;

      host->ios.vdd = bit;
      mmc_set_ios(host);
     } else {
      pr_warning("%s: host doesn't support card's voltages ",
        mmc_hostname(host));
      ocr = 0;
     }

     return ocr;
    }

    /*
     * Select timing parameters for host.
     */
     /* 为主机控制器选择时序参数 */
    void mmc_set_timing(struct mmc_host *host, unsigned int timing)
    {
     host->ios.timing = timing;
     mmc_set_ios(host);
    }

    /*
     * Apply power to the MMC stack.  This is a two-stage process.
     * First, we enable power to the card without the clock running.
     * We then wait a bit for the power to stabilise.  Finally,
     * enable the bus drivers and clock to the card.
     *
     * We must _NOT_ enable the clock prior to power stablising.
     *
     * If a host does all the power sequencing itself, ignore the
     * initial MMC_POWER_UP stage.
     */
     /* 上电 */
    static void mmc_power_up(struct mmc_host *host)
    {
     int bit = fls(host->ocr_avail) - 1;

     host->ios.vdd = bit;
     if (mmc_host_is_spi(host)) {
      host->ios.chip_select = MMC_CS_HIGH;
      host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
     } else {
      host->ios.chip_select = MMC_CS_DONTCARE;
      host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
     }
     host->ios.power_mode = MMC_POWER_UP;
     host->ios.bus_width = MMC_BUS_WIDTH_1;
     host->ios.timing = MMC_TIMING_LEGACY;
     mmc_set_ios(host);

     /*
      * This delay should be sufficient to allow the power supply
      * to reach the minimum voltage.
      */
     mmc_delay(10);

     host->ios.clock = host->f_min;
     host->ios.power_mode = MMC_POWER_ON;
     mmc_set_ios(host);

     /*
      * This delay must be at least 74 clock sizes, or 1 ms, or the
      * time required to reach a stable voltage.
      */
     mmc_delay(10);
    }

    /* 关闭电源 */
    static void mmc_power_off(struct mmc_host *host)
    {
     host->ios.clock = 0;
     host->ios.vdd = 0;
     if (!mmc_host_is_spi(host)) {
      host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
      host->ios.chip_select = MMC_CS_DONTCARE;
     }
     host->ios.power_mode = MMC_POWER_OFF;
     host->ios.bus_width = MMC_BUS_WIDTH_1;
     host->ios.timing = MMC_TIMING_LEGACY;
     mmc_set_ios(host);
    }

    /*
     * Cleanup when the last reference to the bus operator is dropped.
     */
     /* 释放总线操作函数 */
    static void __mmc_release_bus(struct mmc_host *host)
    {
     BUG_ON(!host);
     BUG_ON(host->bus_refs);
     BUG_ON(!host->bus_dead);

     host->bus_ops = NULL;
    }

    /*
     * Increase reference count of bus operator
     */
     /* 增加 总线引用计数*/
    static inline void mmc_bus_get(struct mmc_host *host)
    {
     unsigned long flags;

     spin_lock_irqsave(&host->lock, flags);
     host->bus_refs++;
     spin_unlock_irqrestore(&host->lock, flags);
    }

    /*
     * Decrease reference count of bus operator and free it if
     * it is the last reference.
     */
     /* 减小总线引用计数 */
    static inline void mmc_bus_put(struct mmc_host *host)
    {
     unsigned long flags;

     spin_lock_irqsave(&host->lock, flags);
     host->bus_refs--;
     if ((host->bus_refs == 0) && host->bus_ops)
      __mmc_release_bus(host);  /* 如果总线计数器为0并且总线操作函数集有定义则释放它 */
     spin_unlock_irqrestore(&host->lock, flags);
    }

    /*
     * Assign a mmc bus handler to a host. Only one bus handler may control a
     * host at any given time.
     */
     /* 将主机控制器和总线操作函数绑定 */
    void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
    {
     unsigned long flags;

     BUG_ON(!host);
     BUG_ON(!ops);

     WARN_ON(!host->claimed);

     spin_lock_irqsave(&host->lock, flags);

     BUG_ON(host->bus_ops);
     BUG_ON(host->bus_refs);

     host->bus_ops = ops;
     host->bus_refs = 1;
     host->bus_dead = 0;

     spin_unlock_irqrestore(&host->lock, flags);
    }

    /*
     * Remove the current bus handler from a host. Assumes that there are
     * no interesting cards left, so the bus is powered down.
     */
     /* 将总线和主机控制器分离 */
    void mmc_detach_bus(struct mmc_host *host)
    {
     unsigned long flags;

     BUG_ON(!host);

     WARN_ON(!host->claimed);
     WARN_ON(!host->bus_ops);

     spin_lock_irqsave(&host->lock, flags);

     host->bus_dead = 1;  /* 标记总线已经释放 */

     spin_unlock_irqrestore(&host->lock, flags);

     mmc_power_off(host);  /* 关闭电源 */

     mmc_bus_put(host);
    }

    /**
     * mmc_detect_change - process change of state on a MMC socket
     * @host: host which changed state.
     * @delay: optional delay to wait before detection (jiffies)
     *
     * MMC drivers should call this when they detect a card has been
     * inserted or removed. The MMC layer will confirm that any
     * present card is still functional, and initialize any newly
     * inserted.
     */
     /* 处理mmc插槽变化的状态 */
    void mmc_detect_change(struct mmc_host *host, unsigned long delay)
    {
    #ifdef CONFIG_MMC_DEBUG
     unsigned long flags;
     spin_lock_irqsave(&host->lock, flags);
     WARN_ON(host->removed);
     spin_unlock_irqrestore(&host->lock, flags);
    #endif

     mmc_schedule_delayed_work(&host->detect, delay);
    }

    EXPORT_SYMBOL(mmc_detect_change);

    /* 重新扫描 */
    void mmc_rescan(struct work_struct *work)
    {
     struct mmc_host *host =
      container_of(work, struct mmc_host, detect.work);
     u32 ocr;
     int err;

     mmc_bus_get(host);  /* 增加总线引用计数 */

     if (host->bus_ops == NULL) {  /* 如果总线操作函数集没有定义 */
      /*
       * Only we can add a new handler, so it's safe to
       * release the lock here.
       */
      mmc_bus_put(host); /* 减小总线引用计数 */

      if (host->ops->get_cd && host->ops->get_cd(host) == 0)  /* 如果 host->ops->get_cd函数有定义则调用它,如果该函数返回0则表示没有卡插入则退出*/
       goto out;

      mmc_claim_host(host);  /* 声明一个主机控制器 */

      mmc_power_up(host);  /* 上电 */
      mmc_go_idle(host);  /* 进入idle邋状态 */

      mmc_send_if_cond(host, host->ocr_avail);

      /*
       * First we search for SDIO...
       */
      err = mmc_send_io_op_cond(host, 0, &ocr);
      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, &ocr);
      if (!err) {
       if (mmc_attach_sd(host, ocr))
        mmc_power_off(host);
       goto out;
      }

      /*
       * ...and finally MMC.
       */
      err = mmc_send_op_cond(host, 0, &ocr);
      if (!err) {
       if (mmc_attach_mmc(host, ocr))
        mmc_power_off(host);
       goto out;
      }

      mmc_release_host(host);
      mmc_power_off(host);
     } else {
      if (host->bus_ops->detect && !host->bus_dead)
       host->bus_ops->detect(host);  /* 探测卡 */

      mmc_bus_put(host);
     }
    out:
     if (host->caps & MMC_CAP_NEEDS_POLL)
      mmc_schedule_delayed_work(&host->detect, HZ);
    }

    /* 启动主机控制器 */
    void mmc_start_host(struct mmc_host *host)
    {
     mmc_power_off(host);  /* 打开电源 */
     mmc_detect_change(host, 0);  /* 探测 插槽是否发生变化*/
    }

    /* 停止主机控制器 */
    void mmc_stop_host(struct mmc_host *host)
    {
    #ifdef CONFIG_MMC_DEBUG
     unsigned long flags;
     spin_lock_irqsave(&host->lock, flags);
     host->removed = 1;  /* 标记主机被移除 */
     spin_unlock_irqrestore(&host->lock, flags);
    #endif

     cancel_delayed_work(&host->detect);
     mmc_flush_scheduled_work();

     mmc_bus_get(host);
     if (host->bus_ops && !host->bus_dead) {
      if (host->bus_ops->remove)
       host->bus_ops->remove(host);  /* 调用总线操作函数的移除函数 */

      mmc_claim_host(host); /* 声明一个主机控制器 */
      mmc_detach_bus(host); /* 将总线和主机控制器分离 */
      mmc_release_host(host); /* 释放主机控制器 */
     }
     mmc_bus_put(host);  /* 减小总线引用计数 */

     BUG_ON(host->card);

     mmc_power_off(host);  /* 关闭电源 */
    }

    #ifdef CONFIG_PM

    /**
     * mmc_suspend_host - suspend a host
     * @host: mmc host
     * @state: suspend mode (PM_SUSPEND_xxx)
     */
     /* 挂起主机控制器 */
    int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
    {
     cancel_delayed_work(&host->detect);
     mmc_flush_scheduled_work();

     mmc_bus_get(host);  /* 增加总线引用计数 */
     if (host->bus_ops && !host->bus_dead) {
      if (host->bus_ops->suspend)
       host->bus_ops->suspend(host);    /* 如果总线操作函数集的挂起函数有定义则调用它 */
      if (!host->bus_ops->resume) {
       if (host->bus_ops->remove)
        host->bus_ops->remove(host); /* 如果总线操作函数集的移除函数有定义则调用它 */

       mmc_claim_host(host); /* 声明一个主机控制器 */
       mmc_detach_bus(host);  /* 将总线和主机控制器分离 */
       mmc_release_host(host); /* 释放主机控制器 */
      }
     }
     mmc_bus_put(host);  /* 减小总线计数 */

     mmc_power_off(host);  /* 关闭电源 */

     return 0;
    }

    EXPORT_SYMBOL(mmc_suspend_host);

    /**
     * mmc_resume_host - resume a previously suspended host
     * @host: mmc host
     */
     /* 恢复主机控制器 */
    int mmc_resume_host(struct mmc_host *host)
    {
     mmc_bus_get(host);  /* 增加引用计数 */
     if (host->bus_ops && !host->bus_dead) {
      mmc_power_up(host);  /* 上电 */
      mmc_select_voltage(host, host->ocr);  /* 选择工作电压 */
      BUG_ON(!host->bus_ops->resume);
      host->bus_ops->resume(host);  /* 调用 */
     }
     mmc_bus_put(host);

     /*
      * We add a slight delay here so that resume can progress
      * in parallel.
      */
     mmc_detect_change(host, 1);

     return 0;
    }

    EXPORT_SYMBOL(mmc_resume_host);

    #endif

    static int __init mmc_init(void)
    {
     int ret;

     workqueue = create_singlethread_workqueue("kmmcd");  /* 创建工作队列 */
     if (!workqueue)
      return -ENOMEM;

     ret = mmc_register_bus();  /* 注册mmc总线 */
     if (ret)
      goto destroy_workqueue;

     ret = mmc_register_host_class();  /* 注册主机类 */
     if (ret)
      goto unregister_bus;

     ret = sdio_register_bus();  /* 注册SDIO总线 */
     if (ret)
      goto unregister_host_class;

     return 0;

    unregister_host_class:
     mmc_unregister_host_class();
    unregister_bus:
     mmc_unregister_bus();
    destroy_workqueue:
     destroy_workqueue(workqueue);

     return ret;
    }

    static void __exit mmc_exit(void)
    {
     sdio_unregister_bus();
     mmc_unregister_host_class();
     mmc_unregister_bus();
     destroy_workqueue(workqueue);
    }

    subsys_initcall(mmc_init);
    module_exit(mmc_exit);

    MODULE_LICENSE("GPL");

    /*************************************************************************************************************************************/
    /*  host.c*/

    /*
     *  linux/drivers/mmc/core/host.c
     *
     *  Copyright (C) 2003 Russell King, All Rights Reserved.
     *  Copyright (C) 2007-2008 Pierre Ossman
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     *
     *  MMC host class device management
     */

    #include <linux/device.h>
    #include <linux/err.h>
    #include <linux/idr.h>
    #include <linux/pagemap.h>
    #include <linux/leds.h>

    #include <linux/mmc/host.h>

    #include "core.h"
    #include "host.h"

    #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)

    /* 释放主机 */
    static void mmc_host_classdev_release(struct device *dev)
    {
     struct mmc_host *host = cls_dev_to_mmc_host(dev);
     kfree(host);
    }

    static struct class mmc_host_class = {  /* 主机类 */
     .name  = "mmc_host",   /* 类的名字为mmc_host */
     .dev_release = mmc_host_classdev_release,
    };

    /* 注册一个主机类 */
    int mmc_register_host_class(void)
    {
     return class_register(&mmc_host_class); /* 注册mmc_host_class类 */
    }
    /* 注销主机类 */
    void mmc_unregister_host_class(void)
    {
     class_unregister(&mmc_host_class);
    }

    static DEFINE_IDR(mmc_host_idr);
    static DEFINE_SPINLOCK(mmc_host_lock);

    /**
     * mmc_alloc_host - initialise the per-host structure.
     * @extra: sizeof private data structure
     * @dev: pointer to host device model structure
     *
     * Initialise the per-host structure.
     */
     /* 分配一个struct mmc_host结构
         参数extra为要分配的额外的内存*/
    struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
    {
     int err;
     struct mmc_host *host;

     if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
      return NULL;

     host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); /* 分配内存 */
     if (!host)
      return NULL;

     spin_lock(&mmc_host_lock);
     err = idr_get_new(&mmc_host_idr, host, &host->index);
     spin_unlock(&mmc_host_lock);
     if (err)
      goto free;
           /* 初始化struct mmc_host名字 */
     dev_set_name(&host->class_dev, "mmc%d", host->index);

     host->parent = dev;
     host->class_dev.parent = dev;
     host->class_dev.class = &mmc_host_class;
     device_initialize(&host->class_dev);  /* 初始化设备 */

     spin_lock_init(&host->lock);
     init_waitqueue_head(&host->wq); /*  初始化等待队列 */
     INIT_DELAYED_WORK(&host->detect, mmc_rescan); /* 初始化延时工作结构 */

     /*
      * By default, hosts do not support SGIO or large requests.
      * They have to set these according to their abilities.
      */
     /* 设置它的成员 */
     host->max_hw_segs = 1;
     host->max_phys_segs = 1;
     host->max_seg_size = PAGE_CACHE_SIZE;

     host->max_req_size = PAGE_CACHE_SIZE;
     host->max_blk_size = 512;
     host->max_blk_count = PAGE_CACHE_SIZE / 512;

     return host;

    free:
     kfree(host);
     return NULL;
    }

    EXPORT_SYMBOL(mmc_alloc_host);

    /**
     * mmc_add_host - initialise host hardware
     * @host: mmc host
     *
     * Register the host with the driver model. The host must be
     * prepared to start servicing requests before this function
     * completes.
     */
     /* 添加一个mmc主机 */
    int mmc_add_host(struct mmc_host *host)
    {
     int err;

     WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
      !host->ops->enable_sdio_irq);

     led_trigger_register_simple(dev_name(&host->class_dev), &host->led);

     err = device_add(&host->class_dev);  /* 向驱动模型核心添加一个设备 */
     if (err)
      return err;

    #ifdef CONFIG_DEBUG_FS
     mmc_add_host_debugfs(host);
    #endif

     mmc_start_host(host);  /* 启动主机控制器 */

     return 0;
    }

    EXPORT_SYMBOL(mmc_add_host);

    /**
     * mmc_remove_host - remove host hardware
     * @host: mmc host
     *
     * Unregister and remove all cards associated with this host,
     * and power down the MMC bus. No new requests will be issued
     * after this function has returned.
     */
     /* 移除一个mmc主机控制器 */
    void mmc_remove_host(struct mmc_host *host)
    {
     mmc_stop_host(host);

    #ifdef CONFIG_DEBUG_FS
     mmc_remove_host_debugfs(host);
    #endif

     device_del(&host->class_dev); /* 从设备驱动模型核心删除一个设备 */

     led_trigger_unregister_simple(host->led);
    }

    EXPORT_SYMBOL(mmc_remove_host);

    /**
     * mmc_free_host - free the host structure
     * @host: mmc host
     *
     * Free the host once all references to it have been dropped.
     */
     /* 释放主机控制器结构 */
    void mmc_free_host(struct mmc_host *host)
    {
     spin_lock(&mmc_host_lock);
     idr_remove(&mmc_host_idr, host->index);
     spin_unlock(&mmc_host_lock);

     put_device(&host->class_dev);
    }

    EXPORT_SYMBOL(mmc_free_host);

     /*************************************************************************************************************************************/
    /* mmc.c */

    /*
     *  linux/drivers/mmc/core/mmc.c
     *
     *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
     *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
     *  MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved.
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */

    #include <linux/err.h>

    #include <linux/mmc/host.h>
    #include <linux/mmc/card.h>
    #include <linux/mmc/mmc.h>

    #include "core.h"
    #include "bus.h"
    #include "mmc_ops.h"

    static const unsigned int tran_exp[] = {
     10000,  100000,  1000000, 10000000,
     0,  0,  0,  0
    };

    static const unsigned char tran_mant[] = {
     0, 10, 12, 13, 15, 20, 25, 30,
     35, 40, 45, 50, 55, 60, 70, 80,
    };

    static const unsigned int tacc_exp[] = {
     1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
    };

    static const unsigned int tacc_mant[] = {
     0, 10, 12, 13, 15, 20, 25, 30,
     35, 40, 45, 50, 55, 60, 70, 80,
    };

    #define UNSTUFF_BITS(resp,start,size)     
     ({        
      const int __size = size;    
      const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; 
      const int __off = 3 - ((start) / 32);   
      const int __shft = (start) & 31;   
      u32 __res;      
             
      __res = resp[__off] >> __shft;    
      if (__size + __shft > 32)    
       __res |= resp[__off-1] << ((32 - __shft) % 32); 
      __res & __mask;      
     })

    /*
     * Given the decoded CSD structure, decode the raw CID to our CID structure.
     */
     /* 解码CID寄存器 */
    static int mmc_decode_cid(struct mmc_card *card)
    {
     u32 *resp = card->raw_cid;

     /*
      * The selection of the format here is based upon published
      * specs from sandisk and from what people have reported.
      */
     switch (card->csd.mmca_vsn) {
     case 0: /* MMC v1.0 - v1.2 */
     case 1: /* MMC v1.4 */
      card->cid.manfid = UNSTUFF_BITS(resp, 104, 24);
      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.prod_name[6] = UNSTUFF_BITS(resp, 48, 8);
      card->cid.hwrev  = UNSTUFF_BITS(resp, 44, 4);
      card->cid.fwrev  = UNSTUFF_BITS(resp, 40, 4);
      card->cid.serial = UNSTUFF_BITS(resp, 16, 24);
      card->cid.month  = UNSTUFF_BITS(resp, 12, 4);
      card->cid.year  = UNSTUFF_BITS(resp, 8, 4) + 1997;
      break;

     case 2: /* MMC v2.0 - v2.2 */
     case 3: /* MMC v3.1 - v3.3 */
     case 4: /* MMC v4 */
      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;
      break;

     default:
      printk(KERN_ERR "%s: card has unknown MMCA version %d ",
       mmc_hostname(card->host), card->csd.mmca_vsn);
      return -EINVAL;
     }

     return 0;
    }

    /*
     * Given a 128-bit response, decode to our card CSD structure.
     */
     /* 解码CSD寄存器 */
    static int mmc_decode_csd(struct mmc_card *card)
    {
     struct mmc_csd *csd = &card->csd;
     unsigned int e, m, csd_struct;
     u32 *resp = card->raw_csd;

     /*
      * We only understand CSD structure v1.1 and v1.2.
      * v1.2 has extra information in bits 15, 11 and 10.
      */
     csd_struct = UNSTUFF_BITS(resp, 126, 2);
     if (csd_struct != 1 && csd_struct != 2) {
      printk(KERN_ERR "%s: unrecognised CSD structure version %d ",
       mmc_hostname(card->host), csd_struct);
      return -EINVAL;
     }

     csd->mmca_vsn  = UNSTUFF_BITS(resp, 122, 4);
     m = UNSTUFF_BITS(resp, 115, 4);
     e = UNSTUFF_BITS(resp, 112, 3);
     csd->tacc_ns  = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
     csd->tacc_clks  = UNSTUFF_BITS(resp, 104, 8) * 100;

     m = UNSTUFF_BITS(resp, 99, 4);
     e = UNSTUFF_BITS(resp, 96, 3);
     csd->max_dtr   = tran_exp[e] * tran_mant[m];
     csd->cmdclass   = UNSTUFF_BITS(resp, 84, 12);

     e = UNSTUFF_BITS(resp, 47, 3);
     m = UNSTUFF_BITS(resp, 62, 12);
     csd->capacity   = (1 + m) << (e + 2);

     csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
     csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
     csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
     csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
     csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
     csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
     csd->write_partial = UNSTUFF_BITS(resp, 21, 1);

     return 0;
    }

    /*
     * Read and decode extended CSD.
     */
     /* 读取并且解码扩展的CSD寄存器 */
    static int mmc_read_ext_csd(struct mmc_card *card)
    {
     int err;
     u8 *ext_csd;
     unsigned int ext_csd_struct;

     BUG_ON(!card);

     if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
      return 0;

     /*
      * As the ext_csd is so large and mostly unused, we don't store the
      * raw block in mmc_card.
      */
     ext_csd = kmalloc(512, GFP_KERNEL);
     if (!ext_csd) {
      printk(KERN_ERR "%s: could not allocate a buffer to "
       "receive the ext_csd. ", mmc_hostname(card->host));
      return -ENOMEM;
     }

     err = mmc_send_ext_csd(card, ext_csd);
     if (err) {
      /*
       * We all hosts that cannot perform the command
       * to fail more gracefully
       */
      if (err != -EINVAL)
       goto out;

      /*
       * High capacity cards should have this "magic" size
       * stored in their CSD.
       */
      if (card->csd.capacity == (4096 * 512)) {
       printk(KERN_ERR "%s: unable to read EXT_CSD "
        "on a possible high capacity card. "
        "Card will be ignored. ",
        mmc_hostname(card->host));
      } else {
       printk(KERN_WARNING "%s: unable to read "
        "EXT_CSD, performance might "
        "suffer. ",
        mmc_hostname(card->host));
       err = 0;
      }

      goto out;
     }

     ext_csd_struct = ext_csd[EXT_CSD_REV];
     if (ext_csd_struct > 3) {
      printk(KERN_ERR "%s: unrecognised EXT_CSD structure "
       "version %d ", mmc_hostname(card->host),
       ext_csd_struct);
      err = -EINVAL;
      goto out;
     }

     if (ext_csd_struct >= 2) {
      card->ext_csd.sectors =
       ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
       ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
       ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
       ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
      if (card->ext_csd.sectors)
       mmc_card_set_blockaddr(card);
     }

     switch (ext_csd[EXT_CSD_CARD_TYPE]) {
     case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
      card->ext_csd.hs_max_dtr = 52000000;
      break;
     case EXT_CSD_CARD_TYPE_26:
      card->ext_csd.hs_max_dtr = 26000000;
      break;
     default:
      /* MMC v4 spec says this cannot happen */
      printk(KERN_WARNING "%s: card is mmc v4 but doesn't "
       "support any high-speed modes. ",
       mmc_hostname(card->host));
      goto out;
     }

    out:
     kfree(ext_csd);

     return err;
    }

    MMC_DEV_ATTR(cid, "%08x%08x%08x%08x ", card->raw_cid[0], card->raw_cid[1],
     card->raw_cid[2], card->raw_cid[3]);
    MMC_DEV_ATTR(csd, "%08x%08x%08x%08x ", card->raw_csd[0], card->raw_csd[1],
     card->raw_csd[2], card->raw_csd[3]);
    MMC_DEV_ATTR(date, "%02d/%04d ", card->cid.month, card->cid.year);
    MMC_DEV_ATTR(fwrev, "0x%x ", card->cid.fwrev);
    MMC_DEV_ATTR(hwrev, "0x%x ", card->cid.hwrev);
    MMC_DEV_ATTR(manfid, "0x%06x ", card->cid.manfid);
    MMC_DEV_ATTR(name, "%s ", card->cid.prod_name);
    MMC_DEV_ATTR(oemid, "0x%04x ", card->cid.oemid);
    MMC_DEV_ATTR(serial, "0x%08x ", card->cid.serial);

    static struct attribute *mmc_std_attrs[] = {
     &dev_attr_cid.attr,
     &dev_attr_csd.attr,
     &dev_attr_date.attr,
     &dev_attr_fwrev.attr,
     &dev_attr_hwrev.attr,
     &dev_attr_manfid.attr,
     &dev_attr_name.attr,
     &dev_attr_oemid.attr,
     &dev_attr_serial.attr,
     NULL,
    };

    static struct attribute_group mmc_std_attr_group = {
     .attrs = mmc_std_attrs,
    };

    static struct attribute_group *mmc_attr_groups[] = {
     &mmc_std_attr_group,
     NULL,
    };

    static struct device_type mmc_type = {
     .groups = mmc_attr_groups,
    };

    /*
     * Handle the detection and initialisation of a card.
     *
     * In the case of a resume, "oldcard" will contain the card
     * we're trying to reinitialise.
     */
     /* 初始化卡 */
    static int mmc_init_card(struct mmc_host *host, u32 ocr,
     struct mmc_card *oldcard)
    {
     struct mmc_card *card;
     int err;
     u32 cid[4];
     unsigned int max_dtr;

     BUG_ON(!host);
     WARN_ON(!host->claimed);

     /*
      * Since we're changing the OCR value, we seem to
      * need to tell some cards to go back to the idle
      * state.  We wait 1ms to give cards time to
      * respond.
      */
     mmc_go_idle(host);  /* 进入空闲模式 */

     /* The extra bit indicates that we support high capacity */
     err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
     if (err)
      goto err;

     /*
      * For SPI, enable CRC as appropriate.
      */
     if (mmc_host_is_spi(host)) {
      err = mmc_spi_set_crc(host, use_spi_crc);
      if (err)
       goto err;
     }

     /*
      * Fetch CID from card.
      */
     if (mmc_host_is_spi(host))
      err = mmc_send_cid(host, cid);
     else
      err = mmc_all_send_cid(host, cid);
     if (err)
      goto err;

     if (oldcard) {
      if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
       err = -ENOENT;
       goto err;
      }

      card = oldcard;
     } else {
      /*
       * Allocate card structure.
       */
      card = mmc_alloc_card(host, &mmc_type);  /*  */
      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));
     }

     /*
      * For native busses:  set card RCA and quit open drain mode.
      */
     if (!mmc_host_is_spi(host)) {
      err = mmc_set_relative_addr(card);
      if (err)
       goto free_card;

      mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
     }

     if (!oldcard) {
      /*
       * Fetch CSD from card.
       */
      err = mmc_send_csd(card, card->raw_csd);
      if (err)
       goto free_card;

      err = mmc_decode_csd(card);
      if (err)
       goto free_card;
      err = mmc_decode_cid(card);
      if (err)
       goto free_card;
     }

     /*
      * Select card, as all following commands rely on that.
      */
     if (!mmc_host_is_spi(host)) {
      err = mmc_select_card(card);
      if (err)
       goto free_card;
     }

     if (!oldcard) {
      /*
       * Fetch and process extended CSD.
       */
      err = mmc_read_ext_csd(card);
      if (err)
       goto free_card;
     }

     /*
      * Activate high speed (if supported)
      */
     if ((card->ext_csd.hs_max_dtr != 0) &&
      (host->caps & MMC_CAP_MMC_HIGHSPEED)) {
      err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
       EXT_CSD_HS_TIMING, 1);
      if (err)
       goto free_card;

      mmc_card_set_highspeed(card);

      mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
     }

     /*
      * Compute bus speed.
      */
     max_dtr = (unsigned int)-1;

     if (mmc_card_highspeed(card)) {
      if (max_dtr > card->ext_csd.hs_max_dtr)
       max_dtr = card->ext_csd.hs_max_dtr;
     } else if (max_dtr > card->csd.max_dtr) {
      max_dtr = card->csd.max_dtr;
     }

     mmc_set_clock(host, max_dtr);

     /*
      * Activate wide bus (if supported).
      */
     if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
         (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
      unsigned ext_csd_bit, bus_width;

      if (host->caps & MMC_CAP_8_BIT_DATA) {
       ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
       bus_width = MMC_BUS_WIDTH_8;
      } else {
       ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
       bus_width = MMC_BUS_WIDTH_4;
      }

      err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
         EXT_CSD_BUS_WIDTH, ext_csd_bit);

      if (err)
       goto free_card;

      mmc_set_bus_width(card->host, bus_width);
     }

     if (!oldcard)
      host->card = card;

     return 0;

    free_card:
     if (!oldcard)
      mmc_remove_card(card);
    err:

     return err;
    }

    /*
     * Host is being removed. Free up the current card.
     */
     /* 移除函数 */
    static void mmc_remove(struct mmc_host *host)
    {
     BUG_ON(!host);
     BUG_ON(!host->card);

     mmc_remove_card(host->card);  /* 移除卡 */
     host->card = NULL;
    }

    /*
     * Card detection callback from host.
     */
     /* 探测函数 */
    static void mmc_detect(struct mmc_host *host)
    {
     int err;

     BUG_ON(!host);
     BUG_ON(!host->card);

     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_remove(host);

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

    #ifdef CONFIG_MMC_UNSAFE_RESUME

    /*
     * Suspend callback from host.
     */
     /* 挂起函数 */
    static void mmc_suspend(struct mmc_host *host)
    {
     BUG_ON(!host);
     BUG_ON(!host->card);

     mmc_claim_host(host);  /* 声明主机控制器 */
     if (!mmc_host_is_spi(host))
      mmc_deselect_cards(host);
     host->card->state &= ~MMC_STATE_HIGHSPEED;
     mmc_release_host(host);
    }

    /*
     * Resume callback from host.
     *
     * This function tries to determine if the same card is still present
     * and, if so, restore all state to it.
     */
     /* 恢复函数 */
    static void mmc_resume(struct mmc_host *host)
    {
     int err;

     BUG_ON(!host);
     BUG_ON(!host->card);

     mmc_claim_host(host);  /* 声明一个主机控制器 */
     err = mmc_init_card(host, host->ocr, host->card);  /* 初始化卡 */
     mmc_release_host(host);  /* 释放主机 */

     if (err) {
      mmc_remove(host);

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

    }

    #else

    #define mmc_suspend NULL
    #define mmc_resume NULL

    #endif

    static const struct mmc_bus_ops mmc_ops = {  /* 总线操作函数 */
     .remove = mmc_remove,
     .detect = mmc_detect,
     .suspend = mmc_suspend,
     .resume = mmc_resume,
    };

    /*
     * Starting point for MMC card init.
     */
     /*  */
    int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
    {
     int err;

     BUG_ON(!host);
     WARN_ON(!host->claimed);

     mmc_attach_bus(host, &mmc_ops);  /* 将主机和总线操作函数绑定 */

     /*
      * We need to get OCR a different way for SPI.
      */
     if (mmc_host_is_spi(host)) {
      err = mmc_spi_read_ocr(host, 1, &ocr);
      if (err)
       goto err;
     }

     /*
      * Sanity check the voltages that the card claims to
      * support.
      */
     if (ocr & 0x7F) {
      printk(KERN_WARNING "%s: card claims to support voltages "
             "below the defined range. These will be ignored. ",
             mmc_hostname(host));
      ocr &= ~0x7F;
     }

     host->ocr = mmc_select_voltage(host, ocr); /* 选择电压  */

     /*
      * Can we support the voltage of the card?
      */
     if (!host->ocr) {
      err = -EINVAL;
      goto err;
     }

     /*
      * 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_card:
     mmc_remove_card(host->card);
     host->card = NULL;
     mmc_claim_host(host);
    err:
     mmc_detach_bus(host);
     mmc_release_host(host);

     printk(KERN_ERR "%s: error %d whilst initialising MMC card ",
      mmc_hostname(host), err);

     return err;
    }
    /*************************************************************************************************************************************/
    /* mmc_ops.c */

    /*
     *  linux/drivers/mmc/core/mmc_ops.h
     *
     *  Copyright 2006-2007 Pierre Ossman
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or (at
     * your option) any later version.
     */

    #include <linux/types.h>
    #include <linux/scatterlist.h>

    #include <linux/mmc/host.h>
    #include <linux/mmc/card.h>
    #include <linux/mmc/mmc.h>

    #include "core.h"
    #include "mmc_ops.h"
    /* mmc操作函数集 */

     /* 选中卡 */
    static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
    {
     int err;
     struct mmc_command cmd;

     BUG_ON(!host);

     memset(&cmd, 0, sizeof(struct mmc_command));

     cmd.opcode = MMC_SELECT_CARD;

     if (card) {
      cmd.arg = card->rca << 16;
      cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
     } else {
      cmd.arg = 0;
      cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
     }

     err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
     if (err)
      return err;

     return 0;
    }

    /*选中卡 */
    int mmc_select_card(struct mmc_card *card)
    {
     BUG_ON(!card);

     return _mmc_select_card(card->host, card);
    }

    /* 取消选中 */
    int mmc_deselect_cards(struct mmc_host *host)
    {
     return _mmc_select_card(host, NULL);
    }

    /* 进入空闲模式 */
    int mmc_go_idle(struct mmc_host *host)
    {
     int err;
     struct mmc_command cmd;

     /*
      * Non-SPI hosts need to prevent chipselect going active during
      * GO_IDLE; that would put chips into SPI mode.  Remind them of
      * that in case of hardware that won't pull up DAT3/nCS otherwise.
      *
      * SPI hosts ignore ios.chip_select; it's managed according to
      * rules that must accomodate non-MMC slaves which this layer
      * won't even know about.
      */
     if (!mmc_host_is_spi(host)) {
      mmc_set_chip_select(host, MMC_CS_HIGH);
      mmc_delay(1);
     }

     memset(&cmd, 0, sizeof(struct mmc_command));

     cmd.opcode = MMC_GO_IDLE_STATE;
     cmd.arg = 0;
     cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC;

     err = mmc_wait_for_cmd(host, &cmd, 0);

     mmc_delay(1);

     if (!mmc_host_is_spi(host)) {
      mmc_set_chip_select(host, MMC_CS_DONTCARE);
      mmc_delay(1);
     }

     host->use_spi_crc = 0;

     return err;
    }

    int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
    {
     struct mmc_command cmd;
     int i, err = 0;

     BUG_ON(!host);

     memset(&cmd, 0, sizeof(struct mmc_command));

     cmd.opcode = MMC_SEND_OP_COND;
     cmd.arg = mmc_host_is_spi(host) ? 0 : ocr;
     cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;

     for (i = 100; i; i--) {
      err = mmc_wait_for_cmd(host, &cmd, 0);
      if (err)
       break;

      /* if we're just probing, do a single pass */
      if (ocr == 0)
       break;

      /* otherwise wait until reset completes */
      if (mmc_host_is_spi(host)) {
       if (!(cmd.resp[0] & R1_SPI_IDLE))
        break;
      } else {
       if (cmd.resp[0] & MMC_CARD_BUSY)
        break;
      }

      err = -ETIMEDOUT;

      mmc_delay(10);
     }

     if (rocr && !mmc_host_is_spi(host))
      *rocr = cmd.resp[0];

     return err;
    }

    int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
    {
     int err;
     struct mmc_command cmd;

     BUG_ON(!host);
     BUG_ON(!cid);

     memset(&cmd, 0, sizeof(struct mmc_command));

     cmd.opcode = MMC_ALL_SEND_CID;
     cmd.arg = 0;
     cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;

     err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);  /* 等待命令发送完成 */
     if (err)
      return err;

     memcpy(cid, cmd.resp, sizeof(u32) * 4);

     return 0;
    }

    /* 设置相对地址 */
    int mmc_set_relative_addr(struct mmc_card *card)
    {
     int err;
     struct mmc_command cmd;

     BUG_ON(!card);
     BUG_ON(!card->host);

     memset(&cmd, 0, sizeof(struct mmc_command));

     cmd.opcode = MMC_SET_RELATIVE_ADDR;
     cmd.arg = card->rca << 16;
     cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;

     err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
     if (err)
      return err;

     return 0;
    }

    static int
    mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode)
    {
     int err;
     struct mmc_command cmd;

     BUG_ON(!host);
     BUG_ON(!cxd);

     memset(&cmd, 0, sizeof(struct mmc_command));

     cmd.opcode = opcode;
     cmd.arg = arg;
     cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;

     err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
     if (err)
      return err;

     memcpy(cxd, cmd.resp, sizeof(u32) * 4);

     return 0;
    }

    static int
    mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
      u32 opcode, void *buf, unsigned len)
    {
     struct mmc_request mrq;
     struct mmc_command cmd;
     struct mmc_data data;
     struct scatterlist sg;
     void *data_buf;

     /* dma onto stack is unsafe/nonportable, but callers to this
      * routine normally provide temporary on-stack buffers ...
      */
     data_buf = kmalloc(len, GFP_KERNEL);
     if (data_buf == NULL)
      return -ENOMEM;

     memset(&mrq, 0, sizeof(struct mmc_request));
     memset(&cmd, 0, sizeof(struct mmc_command));
     memset(&data, 0, sizeof(struct mmc_data));

     mrq.cmd = &cmd;
     mrq.data = &data;

     cmd.opcode = opcode;
     cmd.arg = 0;

     /* NOTE HACK:  the MMC_RSP_SPI_R1 is always correct here, but we
      * rely on callers to never use this with "native" calls for reading
      * CSD or CID.  Native versions of those commands use the R2 type,
      * not R1 plus a data block.
      */
     cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;

     data.blksz = len;
     data.blocks = 1;
     data.flags = MMC_DATA_READ;
     data.sg = &sg;
     data.sg_len = 1;

     sg_init_one(&sg, data_buf, len);

     if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) {
      /*
       * The spec states that CSR and CID accesses have a timeout
       * of 64 clock cycles.
       */
      data.timeout_ns = 0;
      data.timeout_clks = 64;
     } else
      mmc_set_data_timeout(&data, card);

     mmc_wait_for_req(host, &mrq);

     memcpy(buf, data_buf, len);
     kfree(data_buf);

     if (cmd.error)
      return cmd.error;
     if (data.error)
      return data.error;

     return 0;
    }

    int mmc_send_csd(struct mmc_card *card, u32 *csd)
    {
     int ret, i;

     if (!mmc_host_is_spi(card->host))
      return mmc_send_cxd_native(card->host, card->rca << 16,
        csd, MMC_SEND_CSD);

     ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16);
     if (ret)
      return ret;

     for (i = 0;i < 4;i++)
      csd[i] = be32_to_cpu(csd[i]);

     return 0;
    }

    int mmc_send_cid(struct mmc_host *host, u32 *cid)
    {
     int ret, i;

     if (!mmc_host_is_spi(host)) {
      if (!host->card)
       return -EINVAL;
      return mmc_send_cxd_native(host, host->card->rca << 16,
        cid, MMC_SEND_CID);
     }

     ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16);
     if (ret)
      return ret;

     for (i = 0;i < 4;i++)
      cid[i] = be32_to_cpu(cid[i]);

     return 0;
    }

    int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
    {
     return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD,
       ext_csd, 512);
    }

    int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp)
    {
     struct mmc_command cmd;
     int err;

     memset(&cmd, 0, sizeof(struct mmc_command));

     cmd.opcode = MMC_SPI_READ_OCR;
     cmd.arg = highcap ? (1 << 30) : 0;
     cmd.flags = MMC_RSP_SPI_R3;

     err = mmc_wait_for_cmd(host, &cmd, 0);

     *ocrp = cmd.resp[1];
     return err;
    }

    int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
    {
     struct mmc_command cmd;
     int err;

     memset(&cmd, 0, sizeof(struct mmc_command));

     cmd.opcode = MMC_SPI_CRC_ON_OFF;
     cmd.flags = MMC_RSP_SPI_R1;
     cmd.arg = use_crc;

     err = mmc_wait_for_cmd(host, &cmd, 0);
     if (!err)
      host->use_spi_crc = use_crc;
     return err;
    }

    int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
    {
     int err;
     struct mmc_command cmd;

     BUG_ON(!card);
     BUG_ON(!card->host);

     memset(&cmd, 0, sizeof(struct mmc_command));

     cmd.opcode = MMC_SWITCH;
     cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
        (index << 16) |
        (value << 8) |
        set;
     cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;

     err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
     if (err)
      return err;

     return 0;
    }

    /* 发送卡的状态 */
    int mmc_send_status(struct mmc_card *card, u32 *status)
    {
     int err;
     struct mmc_command cmd;

     BUG_ON(!card);
     BUG_ON(!card->host);

     memset(&cmd, 0, sizeof(struct mmc_command));

     cmd.opcode = MMC_SEND_STATUS;
     if (!mmc_host_is_spi(card->host))
      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;

     /* NOTE: callers are required to understand the difference
      * between "native" and SPI format status words!
      */
     if (status)
      *status = cmd.resp[0];

     return 0;
    }

     /*************************************************************************************************************************************/
    /* sd.c */

    /*
     *  linux/drivers/mmc/core/sd.c
     *
     *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
     *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
     *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */

    #include <linux/err.h>

    #include <linux/mmc/host.h>
    #include <linux/mmc/card.h>
    #include <linux/mmc/mmc.h>
    #include <linux/mmc/sd.h>

    #include "core.h"
    #include "bus.h"
    #include "mmc_ops.h"
    #include "sd_ops.h"

    static const unsigned int tran_exp[] = {
     10000,  100000,  1000000, 10000000,
     0,  0,  0,  0
    };

    static const unsigned char tran_mant[] = {
     0, 10, 12, 13, 15, 20, 25, 30,
     35, 40, 45, 50, 55, 60, 70, 80,
    };

    static const unsigned int tacc_exp[] = {
     1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
    };

    static const unsigned int tacc_mant[] = {
     0, 10, 12, 13, 15, 20, 25, 30,
     35, 40, 45, 50, 55, 60, 70, 80,
    };

    #define UNSTUFF_BITS(resp,start,size)     
     ({        
      const int __size = size;    
      const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; 
      const int __off = 3 - ((start) / 32);   
      const int __shft = (start) & 31;   
      u32 __res;      
             
      __res = resp[__off] >> __shft;    
      if (__size + __shft > 32)    
       __res |= resp[__off-1] << ((32 - __shft) % 32); 
      __res & __mask;      
     })

    /*
     * Given the decoded CSD structure, decode the raw CID to our CID structure.
     */
     /* 解码CID寄存器 */
    static void mmc_decode_cid(struct mmc_card *card)
    {
     u32 *resp = card->raw_cid;

     memset(&card->cid, 0, sizeof(struct mmc_cid));

     /*
      * SD doesn't currently have a version field so we will
      * have to assume we can parse this.
      */
     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.hwrev   = UNSTUFF_BITS(resp, 60, 4);
     card->cid.fwrev   = UNSTUFF_BITS(resp, 56, 4);
     card->cid.serial  = UNSTUFF_BITS(resp, 24, 32);
     card->cid.year   = UNSTUFF_BITS(resp, 12, 8);
     card->cid.month   = UNSTUFF_BITS(resp, 8, 4);

     card->cid.year += 2000; /* SD cards year offset */
    }

    /*
     * Given a 128-bit response, decode to our card CSD structure.
     */
     /* 解码SCD寄存器 */
    static int mmc_decode_csd(struct mmc_card *card)
    {
     struct mmc_csd *csd = &card->csd;
     unsigned int e, m, csd_struct;
     u32 *resp = card->raw_csd;

     csd_struct = UNSTUFF_BITS(resp, 126, 2);

     switch (csd_struct) {
     case 0:
      m = UNSTUFF_BITS(resp, 115, 4);
      e = UNSTUFF_BITS(resp, 112, 3);
      csd->tacc_ns  = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
      csd->tacc_clks  = UNSTUFF_BITS(resp, 104, 8) * 100;

      m = UNSTUFF_BITS(resp, 99, 4);
      e = UNSTUFF_BITS(resp, 96, 3);
      csd->max_dtr   = tran_exp[e] * tran_mant[m];
      csd->cmdclass   = UNSTUFF_BITS(resp, 84, 12);

      e = UNSTUFF_BITS(resp, 47, 3);
      m = UNSTUFF_BITS(resp, 62, 12);
      csd->capacity   = (1 + m) << (e + 2);

      csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
      csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
      csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
      csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
      csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
      csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
      csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
      break;
     case 1:
      /*
       * This is a block-addressed SDHC card. Most
       * interesting fields are unused and have fixed
       * values. To avoid getting tripped by buggy cards,
       * we assume those fixed values ourselves.
       */
      mmc_card_set_blockaddr(card);

      csd->tacc_ns  = 0; /* Unused */
      csd->tacc_clks  = 0; /* Unused */

      m = UNSTUFF_BITS(resp, 99, 4);
      e = UNSTUFF_BITS(resp, 96, 3);
      csd->max_dtr   = tran_exp[e] * tran_mant[m];
      csd->cmdclass   = UNSTUFF_BITS(resp, 84, 12);

      m = UNSTUFF_BITS(resp, 48, 22);
      csd->capacity     = (1 + m) << 10;

      csd->read_blkbits = 9;
      csd->read_partial = 0;
      csd->write_misalign = 0;
      csd->read_misalign = 0;
      csd->r2w_factor = 4; /* Unused */
      csd->write_blkbits = 9;
      csd->write_partial = 0;
      break;
     default:
      printk(KERN_ERR "%s: unrecognised CSD structure version %d ",
       mmc_hostname(card->host), csd_struct);
      return -EINVAL;
     }

     return 0;
    }

    /*
     * Given a 64-bit response, decode to our card SCR structure.
     */
     /* 解码SCR寄存器 */
    static int mmc_decode_scr(struct mmc_card *card)
    {
     struct sd_scr *scr = &card->scr;
     unsigned int scr_struct;
     u32 resp[4];

     resp[3] = card->raw_scr[1];
     resp[2] = card->raw_scr[0];

     scr_struct = UNSTUFF_BITS(resp, 60, 4);
     if (scr_struct != 0) {
      printk(KERN_ERR "%s: unrecognised SCR structure version %d ",
       mmc_hostname(card->host), scr_struct);
      return -EINVAL;
     }

     scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
     scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);

     return 0;
    }

    /*
     * Fetches and decodes switch information
     */
     /* 获取总线宽度 */
    static int mmc_read_switch(struct mmc_card *card)
    {
     int err;
     u8 *status;

     if (card->scr.sda_vsn < SCR_SPEC_VER_1)
      return 0;

     if (!(card->csd.cmdclass & CCC_SWITCH)) {
      printk(KERN_WARNING "%s: card lacks mandatory switch "
       "function, performance might suffer. ",
       mmc_hostname(card->host));
      return 0;
     }

     err = -EIO;

     status = kmalloc(64, GFP_KERNEL);
     if (!status) {
      printk(KERN_ERR "%s: could not allocate a buffer for "
       "switch capabilities. ", mmc_hostname(card->host));
      return -ENOMEM;
     }

     err = mmc_sd_switch(card, 0, 0, 1, status);
     if (err) {
      /*
       * We all hosts that cannot perform the command
       * to fail more gracefully
       */
      if (err != -EINVAL)
       goto out;

      printk(KERN_WARNING "%s: problem reading switch "
       "capabilities, performance might suffer. ",
       mmc_hostname(card->host));
      err = 0;

      goto out;
     }

     if (status[13] & 0x02)
      card->sw_caps.hs_max_dtr = 50000000;

    out:
     kfree(status);

     return err;
    }

    /*
     * Test if the card supports high-speed mode and, if so, switch to it.
     */
     /* 测试卡是否支持高度模式,如果支持则切换到高速模式 */
    static int mmc_switch_hs(struct mmc_card *card)
    {
     int err;
     u8 *status;

     if (card->scr.sda_vsn < SCR_SPEC_VER_1)
      return 0;

     if (!(card->csd.cmdclass & CCC_SWITCH))
      return 0;

     if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
      return 0;

     if (card->sw_caps.hs_max_dtr == 0)
      return 0;

     err = -EIO;

     status = kmalloc(64, GFP_KERNEL);
     if (!status) {
      printk(KERN_ERR "%s: could not allocate a buffer for "
       "switch capabilities. ", mmc_hostname(card->host));
      return -ENOMEM;
     }

     err = mmc_sd_switch(card, 1, 0, 1, status);
     if (err)
      goto out;

     if ((status[16] & 0xF) != 1) {
      printk(KERN_WARNING "%s: Problem switching card "
       "into high-speed mode! ",
       mmc_hostname(card->host));
     } else {
      mmc_card_set_highspeed(card);
      mmc_set_timing(card->host, MMC_TIMING_SD_HS);
     }

    out:
     kfree(status);

     return err;
    }

    MMC_DEV_ATTR(cid, "%08x%08x%08x%08x ", card->raw_cid[0], card->raw_cid[1],
     card->raw_cid[2], card->raw_cid[3]);
    MMC_DEV_ATTR(csd, "%08x%08x%08x%08x ", card->raw_csd[0], card->raw_csd[1],
     card->raw_csd[2], card->raw_csd[3]);
    MMC_DEV_ATTR(scr, "%08x%08x ", card->raw_scr[0], card->raw_scr[1]);
    MMC_DEV_ATTR(date, "%02d/%04d ", card->cid.month, card->cid.year);
    MMC_DEV_ATTR(fwrev, "0x%x ", card->cid.fwrev);
    MMC_DEV_ATTR(hwrev, "0x%x ", card->cid.hwrev);
    MMC_DEV_ATTR(manfid, "0x%06x ", card->cid.manfid);
    MMC_DEV_ATTR(name, "%s ", card->cid.prod_name);
    MMC_DEV_ATTR(oemid, "0x%04x ", card->cid.oemid);
    MMC_DEV_ATTR(serial, "0x%08x ", card->cid.serial);


    static struct attribute *sd_std_attrs[] = {
     &dev_attr_cid.attr,
     &dev_attr_csd.attr,
     &dev_attr_scr.attr,
     &dev_attr_date.attr,
     &dev_attr_fwrev.attr,
     &dev_attr_hwrev.attr,
     &dev_attr_manfid.attr,
     &dev_attr_name.attr,
     &dev_attr_oemid.attr,
     &dev_attr_serial.attr,
     NULL,
    };

    static struct attribute_group sd_std_attr_group = {
     .attrs = sd_std_attrs,
    };

    static struct attribute_group *sd_attr_groups[] = {
     &sd_std_attr_group,
     NULL,
    };

    static struct device_type sd_type = {
     .groups = sd_attr_groups,
    };

    /*
     * Handle the detection and initialisation of a card.
     *
     * In the case of a resume, "oldcard" will contain the card
     * we're trying to reinitialise.
     */
     /* 探测并初始化SD卡 */
    static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
     struct mmc_card *oldcard)
    {
     struct mmc_card *card;
     int err;
     u32 cid[4];
     unsigned int max_dtr;

     BUG_ON(!host);
     WARN_ON(!host->claimed);

     /*
      * Since we're changing the OCR value, we seem to
      * need to tell some cards to go back to the idle
      * state.  We wait 1ms to give cards time to
      * respond.
      */
     mmc_go_idle(host);  /* 进入空闲模式 */

     /*
      * If SD_SEND_IF_COND indicates an SD 2.0
      * compliant card and we should set bit 30
      * of the ocr to indicate that we can handle
      * block-addressed SDHC cards.
      */
     err = mmc_send_if_cond(host, ocr);
     if (!err)
      ocr |= 1 << 30;

     err = mmc_send_app_op_cond(host, ocr, NULL);
     if (err)
      goto err;

     /*
      * Fetch CID from card.
      */
     if (mmc_host_is_spi(host))
      err = mmc_send_cid(host, cid);
     else
      err = mmc_all_send_cid(host, cid);  /* 读取存储卡的CID寄存器 */
     if (err)
      goto err;

     if (oldcard) {
      if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
       err = -ENOENT;
       goto err;
      }

      card = oldcard;
     } else {
      /*
       * Allocate card structure.
       */
      card = mmc_alloc_card(host, &sd_type);
      if (IS_ERR(card)) {
       err = PTR_ERR(card);
       goto err;
      }

      card->type = MMC_TYPE_SD;
      memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
     }

     /*
      * For native busses:  get card RCA and quit open drain mode.
      */
     if (!mmc_host_is_spi(host)) {
      err = mmc_send_relative_addr(host, &card->rca);
      if (err)
       goto free_card;

      mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
     }

     if (!oldcard) {
      /*
       * Fetch CSD from card.
       */
      err = mmc_send_csd(card, card->raw_csd);
      if (err)
       goto free_card;

      err = mmc_decode_csd(card);
      if (err)
       goto free_card;

      mmc_decode_cid(card);
     }

     /*
      * Select card, as all following commands rely on that.
      */
     if (!mmc_host_is_spi(host)) {
      err = mmc_select_card(card);
      if (err)
       goto free_card;
     }

     if (!oldcard) {
      /*
       * Fetch SCR from card.
       */
      err = mmc_app_send_scr(card, card->raw_scr);
      if (err)
       goto free_card;

      err = mmc_decode_scr(card);
      if (err < 0)
       goto free_card;

      /*
       * Fetch switch information from card.
       */
      err = mmc_read_switch(card);
      if (err)
       goto free_card;
     }

     /*
      * For SPI, enable CRC as appropriate.
      * This CRC enable is located AFTER the reading of the
      * card registers because some SDHC cards are not able
      * to provide valid CRCs for non-512-byte blocks.
      */
     if (mmc_host_is_spi(host)) {
      err = mmc_spi_set_crc(host, use_spi_crc);
      if (err)
       goto free_card;
     }

     /*
      * Attempt to change to high-speed (if supported)
      */
     err = mmc_switch_hs(card);
     if (err)
      goto free_card;

     /*
      * Compute bus speed.
      */
     max_dtr = (unsigned int)-1;

     if (mmc_card_highspeed(card)) {
      if (max_dtr > card->sw_caps.hs_max_dtr)
       max_dtr = card->sw_caps.hs_max_dtr;
     } else if (max_dtr > card->csd.max_dtr) {
      max_dtr = card->csd.max_dtr;
     }

     mmc_set_clock(host, max_dtr);

     /*
      * Switch to wider bus (if supported).
      */
     if ((host->caps & MMC_CAP_4_BIT_DATA) &&
      (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
      err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
      if (err)
       goto free_card;

      mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
     }

     /*
      * Check if read-only switch is active.
      */
     if (!oldcard) {
      if (!host->ops->get_ro || host->ops->get_ro(host) < 0) {
       printk(KERN_WARNING "%s: host does not "
        "support reading read-only "
        "switch. assuming write-enable. ",
        mmc_hostname(host));
      } else {
       if (host->ops->get_ro(host) > 0)
        mmc_card_set_readonly(card);
      }
     }

     if (!oldcard)
      host->card = card;

     return 0;

    free_card:
     if (!oldcard)
      mmc_remove_card(card);
    err:

     return err;
    }

    /*
     * Host is being removed. Free up the current card.
     */
     /* 移除函数 */
    static void mmc_sd_remove(struct mmc_host *host)
    {
     BUG_ON(!host);
     BUG_ON(!host->card);

     mmc_remove_card(host->card);  /* 移除卡 */
     host->card = NULL;
    }

    /*
     * Card detection callback from host.
     */
     /* 探测函数 */
    static void mmc_sd_detect(struct mmc_host *host)
    {
     int err;

     BUG_ON(!host);
     BUG_ON(!host->card);

     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);
     }
    }

    #ifdef CONFIG_MMC_UNSAFE_RESUME

    /*
     * Suspend callback from host.
     */
     /* 挂起函数 */
    static void mmc_sd_suspend(struct mmc_host *host)
    {
     BUG_ON(!host);
     BUG_ON(!host->card);

     mmc_claim_host(host);
     if (!mmc_host_is_spi(host))
      mmc_deselect_cards(host);
     host->card->state &= ~MMC_STATE_HIGHSPEED;
     mmc_release_host(host);
    }

    /*
     * Resume callback from host.
     *
     * This function tries to determine if the same card is still present
     * and, if so, restore all state to it.
     */
     /* 恢复函数 */
    static void mmc_sd_resume(struct mmc_host *host)
    {
     int err;

     BUG_ON(!host);
     BUG_ON(!host->card);

     mmc_claim_host(host); /* 声明一个主机控制器 */
     err = mmc_sd_init_card(host, host->ocr, host->card);/* 探测并初始化SD卡 */
     mmc_release_host(host); /* 释放主机 */

     if (err) {
      mmc_sd_remove(host);

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

    }

    #else

    #define mmc_sd_suspend NULL
    #define mmc_sd_resume NULL

    #endif

    static const struct mmc_bus_ops mmc_sd_ops = {  /* SD总线操作函数 */
     .remove = mmc_sd_remove,
     .detect = mmc_sd_detect,
     .suspend = mmc_sd_suspend,
     .resume = mmc_sd_resume,
    };

    /*
     * Starting point for SD card init.
     */
     /* 依附一个SD卡 */
    int mmc_attach_sd(struct mmc_host *host, u32 ocr)
    {
     int err;

     BUG_ON(!host);
     WARN_ON(!host->claimed);

     mmc_attach_bus(host, &mmc_sd_ops);  /* 将主机和总线绑定 */

     /*
      * We need to get OCR a different way for SPI.
      */
     if (mmc_host_is_spi(host)) {
      mmc_go_idle(host);

      err = mmc_spi_read_ocr(host, 0, &ocr);
      if (err)
       goto err;
     }

     /*
      * Sanity check the voltages that the card claims to
      * support.
      */
     if (ocr & 0x7F) {
      printk(KERN_WARNING "%s: card claims to support voltages "
             "below the defined range. These will be ignored. ",
             mmc_hostname(host));
      ocr &= ~0x7F;
     }

     if (ocr & MMC_VDD_165_195) {
      printk(KERN_WARNING "%s: SD card claims to support the "
             "incompletely defined 'low voltage range'. This "
             "will be ignored. ", mmc_hostname(host));
      ocr &= ~MMC_VDD_165_195;
     }

     host->ocr = mmc_select_voltage(host, ocr); /* 选择工作电压 */

     /*
      * Can we support the voltage(s) of the card(s)?
      */
     if (!host->ocr) {
      err = -EINVAL;
      goto err;
     }

     /*
      * Detect and init the card.
      */
     err = mmc_sd_init_card(host, host->ocr, NULL);  /* 探测并初始化SD卡 */
     if (err)
      goto err;

     mmc_release_host(host);  /* 释放主机控制器 */

     err = mmc_add_card(host->card);  /* 添加一个SD卡 */
     if (err)
      goto remove_card;

     return 0;

    remove_card:
     mmc_remove_card(host->card);
     host->card = NULL;
     mmc_claim_host(host);
    err:
     mmc_detach_bus(host);
     mmc_release_host(host);

     printk(KERN_ERR "%s: error %d whilst initialising SD card ",
      mmc_hostname(host), err);

     return err;
    }

     /*************************************************************************************************************************************/
    /* sdio_bus.c */

    /*
     *  linux/drivers/mmc/core/sdio_bus.c
     *
     *  Copyright 2007 Pierre Ossman
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or (at
     * your option) any later version.
     *
     * SDIO function driver model
     */

    #include <linux/device.h>
    #include <linux/err.h>

    #include <linux/mmc/card.h>
    #include <linux/mmc/sdio_func.h>

    #include "sdio_cis.h"
    #include "sdio_bus.h"

    #define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)
    #define to_sdio_driver(d)      container_of(d, struct sdio_driver, drv)

    /* show configuration fields */
    #define sdio_config_attr(field, format_string)    
    static ssize_t        
    field##_show(struct device *dev, struct device_attribute *attr, char *buf)    
    {         
     struct sdio_func *func;      
             
     func = dev_to_sdio_func (dev);     
     return sprintf (buf, format_string, func->field);  
    }

    sdio_config_attr(class, "0x%02x ");
    sdio_config_attr(vendor, "0x%04x ");
    sdio_config_attr(device, "0x%04x ");

    static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
    {
     struct sdio_func *func = dev_to_sdio_func (dev);

     return sprintf(buf, "sdio:c%02Xv%04Xd%04X ",
       func->class, func->vendor, func->device);
    }

    static struct device_attribute sdio_dev_attrs[] = {
     __ATTR_RO(class),
     __ATTR_RO(vendor),
     __ATTR_RO(device),
     __ATTR_RO(modalias),
     __ATTR_NULL,
    };

    static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,
     const struct sdio_device_id *id)
    {
     if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class)
      return NULL;
     if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor)
      return NULL;
     if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device)
      return NULL;
     return id;
    }

    static const struct sdio_device_id *sdio_match_device(struct sdio_func *func,
     struct sdio_driver *sdrv)
    {
     const struct sdio_device_id *ids;

     ids = sdrv->id_table;

     if (ids) {
      while (ids->class || ids->vendor || ids->device) {
       if (sdio_match_one(func, ids))
        return ids;
       ids++;
      }
     }

     return NULL;
    }

    static int sdio_bus_match(struct device *dev, struct device_driver *drv)
    {
     struct sdio_func *func = dev_to_sdio_func(dev);
     struct sdio_driver *sdrv = to_sdio_driver(drv);

     if (sdio_match_device(func, sdrv))
      return 1;

     return 0;
    }

    static int
    sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
    {
     struct sdio_func *func = dev_to_sdio_func(dev);

     if (add_uevent_var(env,
       "SDIO_CLASS=%02X", func->class))
      return -ENOMEM;

     if (add_uevent_var(env, 
       "SDIO_ID=%04X:%04X", func->vendor, func->device))
      return -ENOMEM;

     if (add_uevent_var(env,
       "MODALIAS=sdio:c%02Xv%04Xd%04X",
       func->class, func->vendor, func->device))
      return -ENOMEM;

     return 0;
    }

    static int sdio_bus_probe(struct device *dev)
    {
     struct sdio_driver *drv = to_sdio_driver(dev->driver);
     struct sdio_func *func = dev_to_sdio_func(dev);
     const struct sdio_device_id *id;
     int ret;

     id = sdio_match_device(func, drv);
     if (!id)
      return -ENODEV;

     /* Set the default block size so the driver is sure it's something
      * sensible. */
     sdio_claim_host(func);
     ret = sdio_set_block_size(func, 0);
     sdio_release_host(func);
     if (ret)
      return ret;

     return drv->probe(func, id);
    }

    static int sdio_bus_remove(struct device *dev)
    {
     struct sdio_driver *drv = to_sdio_driver(dev->driver);
     struct sdio_func *func = dev_to_sdio_func(dev);

     drv->remove(func);

     if (func->irq_handler) {
      printk(KERN_WARNING "WARNING: driver %s did not remove "
       "its interrupt handler! ", drv->name);
      sdio_claim_host(func);
      sdio_release_irq(func);
      sdio_release_host(func);
     }

     return 0;
    }

    static struct bus_type sdio_bus_type = { /*定义总线类型 */
     .name  = "sdio",
     .dev_attrs = sdio_dev_attrs,
     .match  = sdio_bus_match,
     .uevent  = sdio_bus_uevent,
     .probe  = sdio_bus_probe,
     .remove  = sdio_bus_remove,
    };

    /* 注册SDIO总线 */
    int sdio_register_bus(void)
    {
     return bus_register(&sdio_bus_type);  /* 注册总线 */
    }

    /* 注销SDIO总线 */
    void sdio_unregister_bus(void)
    {
     bus_unregister(&sdio_bus_type);
    }

    /**
     * sdio_register_driver - register a function driver
     * @drv: SDIO function driver
     */
    int sdio_register_driver(struct sdio_driver *drv)  /* 注册SDIO总线驱动 */
    {
     drv->drv.name = drv->name;
     drv->drv.bus = &sdio_bus_type;
     return driver_register(&drv->drv);
    }
    EXPORT_SYMBOL_GPL(sdio_register_driver);

    /**
     * sdio_unregister_driver - unregister a function driver
     * @drv: SDIO function driver
     */
    void sdio_unregister_driver(struct sdio_driver *drv) /* 注销SDIO总线驱动 */
    {
     drv->drv.bus = &sdio_bus_type;
     driver_unregister(&drv->drv);
    }
    EXPORT_SYMBOL_GPL(sdio_unregister_driver);

    static void sdio_release_func(struct device *dev)
    {
     struct sdio_func *func = dev_to_sdio_func(dev);

     sdio_free_func_cis(func);

     if (func->info)
      kfree(func->info);

     kfree(func);
    }

    /*
     * Allocate and initialise a new SDIO function structure.
     */
    struct sdio_func *sdio_alloc_func(struct mmc_card *card)
    {
     struct sdio_func *func;

     func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL);
     if (!func)
      return ERR_PTR(-ENOMEM);

     func->card = card;

     device_initialize(&func->dev);

     func->dev.parent = &card->dev;
     func->dev.bus = &sdio_bus_type;
     func->dev.release = sdio_release_func;

     return func;
    }

    /*
     * Register a new SDIO function with the driver model.
     */
    int sdio_add_func(struct sdio_func *func)
    {
     int ret;

     dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);

     ret = device_add(&func->dev);
     if (ret == 0)
      sdio_func_set_present(func);

     return ret;
    }

    /*
     * Unregister a SDIO function with the driver model, and
     * (eventually) free it.
     */
    void sdio_remove_func(struct sdio_func *func)
    {
     if (sdio_func_present(func))
      device_del(&func->dev);

     put_device(&func->dev);
    }

     /*************************************************************************************************************************************/
    /* sdio_irq.c */

    /*
     * linux/drivers/mmc/core/sdio_irq.c
     *
     * Author:      Nicolas Pitre
     * Created:     June 18, 2007
     * Copyright:   MontaVista Software Inc.
     *
     * Copyright 2008 Pierre Ossman
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or (at
     * your option) any later version.
     */

    #include <linux/kernel.h>
    #include <linux/sched.h>
    #include <linux/kthread.h>
    #include <linux/wait.h>
    #include <linux/delay.h>

    #include <linux/mmc/core.h>
    #include <linux/mmc/host.h>
    #include <linux/mmc/card.h>
    #include <linux/mmc/sdio.h>
    #include <linux/mmc/sdio_func.h>

    #include "sdio_ops.h"

    /* 处理SDIO挂起中断 */
    static int process_sdio_pending_irqs(struct mmc_card *card)
    {
     int i, ret, count;
     unsigned char pending;

     ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending);
     if (ret) {
      printk(KERN_DEBUG "%s: error %d reading SDIO_CCCR_INTx ",
             mmc_card_id(card), ret);
      return ret;
     }

     count = 0;
     for (i = 1; i <= 7; i++) {
      if (pending & (1 << i)) {
       struct sdio_func *func = card->sdio_func[i - 1];
       if (!func) {
        printk(KERN_WARNING "%s: pending IRQ for "
         "non-existant function ",
         mmc_card_id(card));
        ret = -EINVAL;
       } else if (func->irq_handler) {
        func->irq_handler(func);
        count++;
       } else {
        printk(KERN_WARNING "%s: pending IRQ with no handler ",
               sdio_func_id(func));
        ret = -EINVAL;
       }
      }
     }

     if (count)
      return count;

     return ret;
    }

    /* SDIO中断处理线程 */
    static int sdio_irq_thread(void *_host)
    {
     struct mmc_host *host = _host;
     struct sched_param param = { .sched_priority = 1 };
     unsigned long period, idle_period;
     int ret;

     sched_setscheduler(current, SCHED_FIFO, &param);

     /*
      * We want to allow for SDIO cards to work even on non SDIO
      * aware hosts.  One thing that non SDIO host cannot do is
      * asynchronous notification of pending SDIO card interrupts
      * hence we poll for them in that case.
      */
     idle_period = msecs_to_jiffies(10);
     period = (host->caps & MMC_CAP_SDIO_IRQ) ?
      MAX_SCHEDULE_TIMEOUT : idle_period;

     pr_debug("%s: IRQ thread started (poll period = %lu jiffies) ",
       mmc_hostname(host), period);

     do {
      /*
       * We claim the host here on drivers behalf for a couple
       * reasons:
       *
       * 1) it is already needed to retrieve the CCCR_INTx;
       * 2) we want the driver(s) to clear the IRQ condition ASAP;
       * 3) we need to control the abort condition locally.
       *
       * Just like traditional hard IRQ handlers, we expect SDIO
       * IRQ handlers to be quick and to the point, so that the
       * holding of the host lock does not cover too much work
       * that doesn't require that lock to be held.
       */
      ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort);
      if (ret)
       break;
      ret = process_sdio_pending_irqs(host->card);
      mmc_release_host(host);

      /*
       * Give other threads a chance to run in the presence of
       * errors.
       */
      if (ret < 0) {
       set_current_state(TASK_INTERRUPTIBLE);
       if (!kthread_should_stop())
        schedule_timeout(HZ);
       set_current_state(TASK_RUNNING);
      }

      /*
       * Adaptive polling frequency based on the assumption
       * that an interrupt will be closely followed by more.
       * This has a substantial benefit for network devices.
       */
      if (!(host->caps & MMC_CAP_SDIO_IRQ)) {
       if (ret > 0)
        period /= 2;
       else {
        period++;
        if (period > idle_period)
         period = idle_period;
       }
      }

      set_current_state(TASK_INTERRUPTIBLE);
      if (host->caps & MMC_CAP_SDIO_IRQ)
       host->ops->enable_sdio_irq(host, 1);
      if (!kthread_should_stop())
       schedule_timeout(period);
      set_current_state(TASK_RUNNING);
     } while (!kthread_should_stop());

     if (host->caps & MMC_CAP_SDIO_IRQ)
      host->ops->enable_sdio_irq(host, 0);

     pr_debug("%s: IRQ thread exiting with code %d ",
       mmc_hostname(host), ret);

     return ret;
    }


    static int sdio_card_irq_get(struct mmc_card *card)
    {
     struct mmc_host *host = card->host;

     WARN_ON(!host->claimed);

     if (!host->sdio_irqs++) {
      atomic_set(&host->sdio_irq_thread_abort, 0);
      host->sdio_irq_thread =
       kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
        mmc_hostname(host));
      if (IS_ERR(host->sdio_irq_thread)) {
       int err = PTR_ERR(host->sdio_irq_thread);
       host->sdio_irqs--;
       return err;
      }
     }

     return 0;
    }

    static int sdio_card_irq_put(struct mmc_card *card)
    {
     struct mmc_host *host = card->host;

     WARN_ON(!host->claimed);
     BUG_ON(host->sdio_irqs < 1);

     if (!--host->sdio_irqs) {
      atomic_set(&host->sdio_irq_thread_abort, 1);
      kthread_stop(host->sdio_irq_thread);
     }

     return 0;
    }

    /**
     * sdio_claim_irq - claim the IRQ for a SDIO function
     * @func: SDIO function
     * @handler: IRQ handler callback
     *
     * Claim and activate the IRQ for the given SDIO function. The provided
     * handler will be called when that IRQ is asserted.  The host is always
     * claimed already when the handler is called so the handler must not
     * call sdio_claim_host() nor sdio_release_host().
     */
     /* 声明中断 */
    int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler)
    {
     int ret;
     unsigned char reg;

     BUG_ON(!func);
     BUG_ON(!func->card);

     pr_debug("SDIO: Enabling IRQ for %s... ", sdio_func_id(func));

     if (func->irq_handler) {
      pr_debug("SDIO: IRQ for %s already in use. ", sdio_func_id(func));
      return -EBUSY;
     }

     ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);
     if (ret)
      return ret;

     reg |= 1 << func->num;

     reg |= 1; /* Master interrupt enable */

     ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);
     if (ret)
      return ret;

     func->irq_handler = handler;
     ret = sdio_card_irq_get(func->card);
     if (ret)
      func->irq_handler = NULL;

     return ret;
    }
    EXPORT_SYMBOL_GPL(sdio_claim_irq);

    /**
     * sdio_release_irq - release the IRQ for a SDIO function
     * @func: SDIO function
     *
     * Disable and release the IRQ for the given SDIO function.
     */
     /* 释放中断 */
    int sdio_release_irq(struct sdio_func *func)
    {
     int ret;
     unsigned char reg;

     BUG_ON(!func);
     BUG_ON(!func->card);

     pr_debug("SDIO: Disabling IRQ for %s... ", sdio_func_id(func));

     if (func->irq_handler) {
      func->irq_handler = NULL;
      sdio_card_irq_put(func->card);
     }

     ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);
     if (ret)
      return ret;

     reg &= ~(1 << func->num);

     /* Disable master interrupt with the last function interrupt */
     if (!(reg & 0xFE))
      reg = 0;

     ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);
     if (ret)
      return ret;

     return 0;
    }
    EXPORT_SYMBOL_GPL(sdio_release_irq);

  • 相关阅读:
    标定相关-一些资源
    论文基础-5几何知识
    论文基础-3微积分
    h5页面 判断网页是否由微信或qq内置浏览器打开
    Html5 页面后退并刷新
    h5 页面下拉刷新
    绑定点击事件 传参
    公众号做分享功能
    清微信缓存
    手机端适配
  • 原文地址:https://www.cnblogs.com/wi100sh/p/4336247.html
Copyright © 2011-2022 走看看