Chinaunix首页 | 论坛 | 博客
  • 博客访问: 77261
  • 博文数量: 62
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 14
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-23 21:49
文章分类

全部博文(62)

文章存档

2014年(55)

2013年(7)

我的朋友

分类: LINUX

2014-05-01 15:56:09

/*************************************************************************************************************************************/
/* queue.h */

#ifndef MMC_QUEUE_H
#define MMC_QUEUE_H

struct request;
struct task_struct;

struct mmc_queue { /* mmc请求队列 -----对MMC卡的操作是通过该结构的传递来完成的*/
 struct mmc_card  *card;   /* 指向卡 */
 struct task_struct *thread;   /* 执行处理请求的线程 */
 struct semaphore thread_sem;  /* 线程使用的信号量 */
 unsigned int  flags;   /*  标志位*/
 struct request  *req;  /* 通用的请求 */
 int   (*issue_fn)(struct mmc_queue *, struct request *);  /* 发出请求让设备开始处理函数 */
 void   *data;  /* 指向私有数据 */
 struct request_queue *queue;  /* 指向块层请求队列 */
 struct scatterlist *sg;
 char   *bounce_buf;  /* 弹性缓冲区 */
 struct scatterlist *bounce_sg;  /* 碎片链表 */
 unsigned int  bounce_sg_len; /* 碎片长度 */
};

extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
extern void mmc_cleanup_queue(struct mmc_queue *);
extern void mmc_queue_suspend(struct mmc_queue *);
extern void mmc_queue_resume(struct mmc_queue *);

extern unsigned int mmc_queue_map_sg(struct mmc_queue *);
extern void mmc_queue_bounce_pre(struct mmc_queue *);
extern void mmc_queue_bounce_post(struct mmc_queue *);

#endif

/*************************************************************************************************************************************/
/* queue.c */

/*
 *  linux/drivers/mmc/card/queue.c
 *
 *  Copyright (C) 2003 Russell King, All Rights Reserved.
 *  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 version 2 as
 * published by the Free Software Foundation.
 *
 */
#include
#include
#include
#include
#include

#include
#include
#include "queue.h"

#define MMC_QUEUE_BOUNCESZ 65536

#define MMC_QUEUE_SUSPENDED (1 << 0)

/*
 * Prepare a MMC request. This just filters out odd stuff.
 */
 /* 命令预处理函数 */
static int mmc_prep_request(struct request_queue *q, struct request *req)
{
 /*
  * We only like normal block requests.
  */
 if (!blk_fs_request(req)) {  /*如果不是文件系统请求 */
  blk_dump_rq_flags(req, "MMC bad request");  /* 无效请求 */
  return BLKPREP_KILL;
 }

 req->cmd_flags |= REQ_DONTPREP;

 return BLKPREP_OK;
}

/* 请求队列处理线程 */
static int mmc_queue_thread(void *d)
{
 struct mmc_queue *mq = d;
 struct request_queue *q = mq->queue;

 current->flags |= PF_MEMALLOC;

 down(&mq->thread_sem);
 do {
  struct request *req = NULL;

  spin_lock_irq(q->queue_lock);
  set_current_state(TASK_INTERRUPTIBLE);  /* 设置当前进程状态为TASK_INTERRUPTIBLE */
  if (!blk_queue_plugged(q))  /* 如果队列是非阻塞状态,得到下一个请求 */
   req = elv_next_request(q);  /* 获取第一个未完成的请求 */
  mq->req = req;
  spin_unlock_irq(q->queue_lock);

  if (!req) {  /* 如果请求为空 */
   if (kthread_should_stop()) {  /* 线程是否应该返回 */
    set_current_state(TASK_RUNNING); /*  如果是则设置当前进程状态为TASK_RUNNING*/
    break;
   }
   up(&mq->thread_sem);
   schedule();  /* 调度出进程----进程进入睡眠 */
   down(&mq->thread_sem);
   continue;
  }
  set_current_state(TASK_RUNNING);  /* 设置当前进程为TASK_RUNNING */

  mq->issue_fn(mq, req);  /* 调用mmc请求队列的issue_fn函数发出请求让设备处理请求 */
 } while (1);
 up(&mq->thread_sem);

 return 0;
}

/*
 * Generic MMC request handler.  This is called for any queue on a
 * particular host.  When the host is not busy, we look for a request
 * on any queue on this host, and attempt to issue it.  This may
 * not be the queue we were asked to process.
 */
 /* mmc请求处理函数 ,它唤醒请求队列处理线程*/
static void mmc_request(struct request_queue *q)
{
 struct mmc_queue *mq = q->queuedata;   /* 在 mmc_init_queue函数中将struct mmc_queue 结构体地址保存到了mq->queue->queuedata*/
 struct request *req;
 int ret;

 if (!mq) {  /* 如果mq为空则 没有创建mmc请求队列*/
  printk(KERN_ERR "MMC: killing requests for dead queue\n");
  while ((req = elv_next_request(q)) != NULL) {  /* 获取请求队列中下一个要传输的请求 */
   do {
    ret = __blk_end_request(req, -EIO,
       blk_rq_cur_bytes(req));
   } while (ret);
  }
  return;
 }

 if (!mq->req) 
  wake_up_process(mq->thread);  /* 如果有请求则唤醒请求队列处理线程 */
}

/**
 * mmc_init_queue - initialise a queue structure.
 * @mq: mmc queue
 * @card: mmc card to attach this queue
 * @lock: queue lock
 *
 * Initialise a MMC card request queue.
 */
 /* 初始化mmc 请求队列*/
int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock)
{
 struct mmc_host *host = card->host;
 u64 limit = BLK_BOUNCE_HIGH;
 int ret;

 if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
  limit = *mmc_dev(host)->dma_mask;

 mq->card = card;
 mq->queue = blk_init_queue(mmc_request, lock);  /* 初始化请求队列,mmc_request为请求处理函数 */
 if (!mq->queue)
  return -ENOMEM;

 mq->queue->queuedata = mq;  /* 将mq保存起来方便以后使用*/
 mq->req = NULL;

 blk_queue_prep_rq(mq->queue, mmc_prep_request);  /* 绑定命令预处理函数----把这个处理请求的命令发送给硬件设备 */
 blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL);
 queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);

#ifdef CONFIG_MMC_BLOCK_BOUNCE
 if (host->max_hw_segs == 1) {
  unsigned int bouncesz;

  bouncesz = MMC_QUEUE_BOUNCESZ;

  if (bouncesz > host->max_req_size)
   bouncesz = host->max_req_size;
  if (bouncesz > host->max_seg_size)
   bouncesz = host->max_seg_size;
  if (bouncesz > (host->max_blk_count * 512))
   bouncesz = host->max_blk_count * 512;

  if (bouncesz > 512) {
   mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
   if (!mq->bounce_buf) {
    printk(KERN_WARNING "%s: unable to "
     "allocate bounce buffer\n",
     mmc_card_name(card));
   }
  }

  if (mq->bounce_buf) {
   blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
   blk_queue_max_sectors(mq->queue, bouncesz / 512);
   blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
   blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
   blk_queue_max_segment_size(mq->queue, bouncesz);

   mq->sg = kmalloc(sizeof(struct scatterlist),
    GFP_KERNEL);
   if (!mq->sg) {
    ret = -ENOMEM;
    goto cleanup_queue;
   }
   sg_init_table(mq->sg, 1);

   mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *
    bouncesz / 512, GFP_KERNEL);
   if (!mq->bounce_sg) {
    ret = -ENOMEM;
    goto cleanup_queue;
   }
   sg_init_table(mq->bounce_sg, bouncesz / 512);
  }
 }  
#endif
          /* 初始化请求队列的扇区及片段限制 */
 if (!mq->bounce_buf) {
  blk_queue_bounce_limit(mq->queue, limit);
  blk_queue_max_sectors(mq->queue,
   min(host->max_blk_count, host->max_req_size / 512));
  blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
  blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
  blk_queue_max_segment_size(mq->queue, host->max_seg_size);

  mq->sg = kmalloc(sizeof(struct scatterlist) *
   host->max_phys_segs, GFP_KERNEL);
  if (!mq->sg) {
   ret = -ENOMEM;
   goto cleanup_queue;
  }
  sg_init_table(mq->sg, host->max_phys_segs);
 }

 init_MUTEX(&mq->thread_sem);

 mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");  /*  创建一个内核线程来处理请求 队列*/
 if (IS_ERR(mq->thread)) {
  ret = PTR_ERR(mq->thread);
  goto free_bounce_sg;
 }

 return 0;
 free_bounce_sg:
  if (mq->bounce_sg)
   kfree(mq->bounce_sg);
  mq->bounce_sg = NULL;
 cleanup_queue:
  if (mq->sg)
  kfree(mq->sg);
 mq->sg = NULL;
 if (mq->bounce_buf)
  kfree(mq->bounce_buf);
 mq->bounce_buf = NULL;
 blk_cleanup_queue(mq->queue);
 return ret;
}

/*释放请求队列 */
void mmc_cleanup_queue(struct mmc_queue *mq)
{
 struct request_queue *q = mq->queue;
 unsigned long flags;

 /* Mark that we should start throwing out stragglers */
 spin_lock_irqsave(q->queue_lock, flags);
 q->queuedata = NULL;
 spin_unlock_irqrestore(q->queue_lock, flags);

 /* Make sure the queue isn't suspended, as that will deadlock */
 mmc_queue_resume(mq);  /*恢复请求队列 */

 /* Then terminate our worker thread */
 kthread_stop(mq->thread);  /* 停止请求处理线程 */

  if (mq->bounce_sg)
   kfree(mq->bounce_sg);  /*  */
  mq->bounce_sg = NULL;

 kfree(mq->sg);
 mq->sg = NULL;

 if (mq->bounce_buf)
  kfree(mq->bounce_buf);
 mq->bounce_buf = NULL;

 blk_cleanup_queue(mq->queue); /* 释放请求队列 */

 mq->card = NULL;
}
EXPORT_SYMBOL(mmc_cleanup_queue);

/**
 * mmc_queue_suspend - suspend a MMC request queue
 * @mq: MMC queue to suspend
 *
 * Stop the block request queue, and wait for our thread to
 * complete any outstanding requests.  This ensures that we
 * won't suspend while a request is being processed.
 */
 /* 挂起mmc请求队列 */
void mmc_queue_suspend(struct mmc_queue *mq)
{
 struct request_queue *q = mq->queue;
 unsigned long flags;

 if (!(mq->flags & MMC_QUEUE_SUSPENDED)) {
  mq->flags |= MMC_QUEUE_SUSPENDED;

  spin_lock_irqsave(q->queue_lock, flags);
  blk_stop_queue(q);  /*  停止请求队列 */
  spin_unlock_irqrestore(q->queue_lock, flags);

  down(&mq->thread_sem);
 }
}

/**
 * mmc_queue_resume - resume a previously suspended MMC request queue
 * @mq: MMC queue to resume
 */
 /*恢复请求队列 */
void mmc_queue_resume(struct mmc_queue *mq)
{
 struct request_queue *q = mq->queue;
 unsigned long flags;

 if (mq->flags & MMC_QUEUE_SUSPENDED) {
  mq->flags &= ~MMC_QUEUE_SUSPENDED;

  up(&mq->thread_sem);

  spin_lock_irqsave(q->queue_lock, flags);
  blk_start_queue(q);  /* 启动请求队列 */
  spin_unlock_irqrestore(q->queue_lock, flags);
 }
}

/*
 * Prepare the sg list(s) to be handed of to the host driver
 */
 /*为主机驱动 准备一个 struct scatterlist*/
unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
{
 unsigned int sg_len;
 size_t buflen;
 struct scatterlist *sg;
 int i;

 if (!mq->bounce_buf)
  return blk_rq_map_sg(mq->queue, mq->req, mq->sg);

 BUG_ON(!mq->bounce_sg);

 sg_len = blk_rq_map_sg(mq->queue, mq->req, mq->bounce_sg);

 mq->bounce_sg_len = sg_len;

 buflen = 0;
 for_each_sg(mq->bounce_sg, sg, sg_len, i)
  buflen += sg->length;

 sg_init_one(mq->sg, mq->bounce_buf, buflen);

 return 1;
}

/*
 * If writing, bounce the data to the buffer before the request
 * is sent to the host driver
 */
 /* 如果是写,则在请求被发送到主机驱动前弹出数据到buffer */
void mmc_queue_bounce_pre(struct mmc_queue *mq)
{
 unsigned long flags;

 if (!mq->bounce_buf)
  return;

 if (rq_data_dir(mq->req) != WRITE)
  return;

 local_irq_save(flags);
 sg_copy_to_buffer(mq->bounce_sg, mq->bounce_sg_len,
  mq->bounce_buf, mq->sg[0].length);
 local_irq_restore(flags);
}

/*
 * If reading, bounce the data from the buffer after the request
 * has been handled by the host driver
 */
  /* 如果是读,则在请求被主机驱动处理后弹出数据到buffer */
void mmc_queue_bounce_post(struct mmc_queue *mq)
{
 unsigned long flags;

 if (!mq->bounce_buf)
  return;

 if (rq_data_dir(mq->req) != READ)
  return;

 local_irq_save(flags);
 sg_copy_from_buffer(mq->bounce_sg, mq->bounce_sg_len,
  mq->bounce_buf, mq->sg[0].length);
 local_irq_restore(flags);
}

 /*************************************************************************************************************************************/
/* block.c */

/*
 * Block driver for media (i.e., flash cards)
 *
 * Copyright 2002 Hewlett-Packard Company
 * Copyright 2005-2008 Pierre Ossman
 *
 * Use consistent with the GNU GPL is permitted,
 * provided that this copyright notice is
 * preserved in its entirety in all copies and derived works.
 *
 * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
 * FITNESS FOR ANY PARTICULAR PURPOSE.
 *
 * Many thanks to Alessandro Rubini and Jonathan Corbet!
 *
 * Author:  Andrew Christian
 *          28 May 2002
 */
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include
#include
#include

#include
#include

#include "queue.h"

MODULE_ALIAS("mmc:block");

/*
 * max 8 partitions per card
 */
 /* 最大支持8个mmc主机控制器,每个控制器可控制4个卡,每个卡最大可有8个分区 */

#define MMC_SHIFT 3      /* 表示最大支持8个分区(1<< MMC_SHIFT) */
#define MMC_NUM_MINORS (256 >> MMC_SHIFT)    /*次设备号数   MMC_NUM_MINORS=32 */

static DECLARE_BITMAP(dev_use, MMC_NUM_MINORS);   /* 一个控制器用32位表示使用情况 */
/* 定义位图

   #define BITS_PER_BYTE  8
   #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
   #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))    将一个bit转换为long
   #define DECLARE_BITMAP(name,bits) unsigned long name[BITS_TO_LONGS(bits)]---->定义位映射

   static DECLARE_BITMAP(dev_use, MMC_NUM_MINORS)= unsigned long dev_use[BITS_TO_LONGS(32)]=unsigned long dev_use[DIV_ROUND_UP(32, 8 * 4) ]===>
   =unsigned long dev_use[ (((32) + (32) - 1) / (32))]=unsigned long dev_use[ (((32) + (32) - 1) / (32))]=unsigned long dev_use[1]

   即tatic DECLARE_BITMAP(dev_use, MMC_NUM_MINORS)=unsigned long dev_use[1]
    */
/*
 * There is one mmc_blk_data per slot.
 */
struct mmc_blk_data { /* mmc卡插槽对应的一个块的数据结构*/
 spinlock_t lock;
 struct gendisk *disk; /* 通用磁盘指针 */
 struct mmc_queue queue; /* mmc请求队列 */

 unsigned int usage;  /* 使用计数 */
 unsigned int read_only;  /* 只读标志 */
};

static DEFINE_MUTEX(open_lock);
/*  通过gendisk结构体获取 struct mmc_blk_data指针*/
static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
{
 struct mmc_blk_data *md;

 mutex_lock(&open_lock);
 md = disk->private_data;
 if (md && md->usage == 0)
  md = NULL;
 if (md)
  md->usage++;  /*  增加使用计数*/
 mutex_unlock(&open_lock);

 return md;
}

/* 释放struct mmc_blk_data结构 */
static void mmc_blk_put(struct mmc_blk_data *md)
{
 mutex_lock(&open_lock);
 md->usage--;
 if (md->usage == 0) {
  int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT;
  __clear_bit(devidx, dev_use);  /* dev_use[devidx]=0 */

  put_disk(md->disk);
  kfree(md);
 }
 mutex_unlock(&open_lock);
}

/* 打开设备 */
static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
{
 struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
 int ret = -ENXIO;

 if (md) {
  if (md->usage == 2)
   check_disk_change(bdev);  /* 检查磁盘介质释放改变 */
  ret = 0;

  if ((mode & FMODE_WRITE) && md->read_only) {
   mmc_blk_put(md);
   ret = -EROFS;
  }
 }

 return ret;
}

/* 关闭设备 */
static int mmc_blk_release(struct gendisk *disk, fmode_t mode)
{
 struct mmc_blk_data *md = disk->private_data;

 mmc_blk_put(md);
 return 0;
}

/* 获取驱动器信息 */
static int
mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
 geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);  /* 柱面数 */
 geo->heads = 4;  /* 磁头数 */
 geo->sectors = 16; /* 扇区数 */
 return 0;
}

static struct block_device_operations mmc_bdops = {  /* 块设备操作函数  */
 .open   = mmc_blk_open,
 .release  = mmc_blk_release,
 .getgeo   = mmc_blk_getgeo,
 .owner   = THIS_MODULE,
};

struct mmc_blk_request {  /* mmc块设备请求描述结构体 */
 struct mmc_request mrq;  /* mmc卡的请求 */
 struct mmc_command cmd;  /* mmc命令 */
 struct mmc_command stop;  /* mmc停止命令 */
 struct mmc_data  data;  /* mmc卡读写的数据相关信息 */
};

/* mmc SD卡读写多个块 */
static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
{
 int err;
 __be32 blocks;

 struct mmc_request mrq;
 struct mmc_command cmd;
 struct mmc_data data;
 unsigned int timeout_us;

 struct scatterlist sg;

 memset(&cmd, 0, sizeof(struct mmc_command)); 
       /* 设置命令 */
 cmd.opcode = MMC_APP_CMD;
 cmd.arg = card->rca << 16;
 cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;

 err = mmc_wait_for_cmd(card->host, &cmd, 0); /*  发送命令并等待它完成 */
 if (err)
  return (u32)-1;
 if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
  return (u32)-1;

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

 cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
 cmd.arg = 0;
 cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;

 memset(&data, 0, sizeof(struct mmc_data));

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

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

 if (timeout_us > 100000) {
  data.timeout_ns = 100000000;
  data.timeout_clks = 0;
 }

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

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

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

 sg_init_one(&sg, &blocks, 4);

 mmc_wait_for_req(card->host, &mrq);

 if (cmd.error || data.error)
  return (u32)-1;

 return ntohl(blocks);
}

/* 获取卡的状态 */
static u32 get_card_status(struct mmc_card *card, struct request *req)
{
 struct mmc_command cmd;
 int err;

 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, 0);   /* 发送一个命令并等待它完成 */
 if (err)
  printk(KERN_ERR "%s: error %d sending status comand",
         req->rq_disk->disk_name, err);
 return cmd.resp[0];
}

 /* 发出读写请求的函数----初始化块请求结构后,向卡发送请求命令,并等待请求完成 */
static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
{
 struct mmc_blk_data *md = mq->data;
 struct mmc_card *card = md->queue.card;
 struct mmc_blk_request brq;  /* 定义一个struct mmc_blk_request结构体类型变量 */
 int ret = 1, disable_multi = 0;

 mmc_claim_host(card->host);  /* 声明一个主机来进行一系列的操作 ----认领控制器,发送命令到卡设置卡的选中状态*/

 do {
  struct mmc_command cmd;
  u32 readcmd, writecmd, status = 0;
             /* 设置 struct mmc_blk_request的成员*/
  memset(&brq, 0, sizeof(struct mmc_blk_request));
  brq.mrq.cmd = &brq.cmd;
  brq.mrq.data = &brq.data;

  brq.cmd.arg = req->sector;
  if (!mmc_card_blockaddr(card)) /* struct mmc_card *card->state & MMC_STATE_BLOCKADDR */
   brq.cmd.arg <<= 9;
  brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
  brq.data.blksz = 512;
  brq.stop.opcode = MMC_STOP_TRANSMISSION;
  brq.stop.arg = 0;
  brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
  brq.data.blocks = req->nr_sectors;

  /*
   * The block layer doesn't support all sector count
   * restrictions, so we need to be prepared for too big
   * requests.
   */
   /* 检查请求中 数据*/
  if (brq.data.blocks > card->host->max_blk_count)
   brq.data.blocks = card->host->max_blk_count;

  /*
   * After a read error, we redo the request one sector at a time
   * in order to accurately determine which sectors can be read
   * successfully.
   */
  if (disable_multi && brq.data.blocks > 1)
   brq.data.blocks = 1;

  if (brq.data.blocks > 1) {  /* 多块读写 */
   /* SPI multiblock writes terminate using a special
    * token, not a STOP_TRANSMISSION request.
    */
   if (!mmc_host_is_spi(card->host)
     || rq_data_dir(req) == READ)  /* 如果mmc主机控制器不是SPI模式或者是读取数据 */
    brq.mrq.stop = &brq.stop;
   readcmd = MMC_READ_MULTIPLE_BLOCK;
   writecmd = MMC_WRITE_MULTIPLE_BLOCK;
  } else { /* 单块读写 */
   brq.mrq.stop = NULL;
   readcmd = MMC_READ_SINGLE_BLOCK;
   writecmd = MMC_WRITE_BLOCK;
  }

  if (rq_data_dir(req) == READ) {  /* 读 */
   brq.cmd.opcode = readcmd;
   brq.data.flags |= MMC_DATA_READ;
  } else { /* 写 */
   brq.cmd.opcode = writecmd;
   brq.data.flags |= MMC_DATA_WRITE;
  }

  mmc_set_data_timeout(&brq.data, card); /* 设置一个数据命令的超时时间 */

  brq.data.sg = mq->sg;
  brq.data.sg_len = mmc_queue_map_sg(mq);  /* 为主机驱动准备一个struct scatterlist */

  /*
   * Adjust the sg list so it is the same size as the
   * request.
   */
  if (brq.data.blocks != req->nr_sectors) {
   int i, data_size = brq.data.blocks << 9;
   struct scatterlist *sg;

   for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) {
    data_size -= sg->length;
    if (data_size <= 0) {
     sg->length += data_size;
     i++;
     break;
    }
   }
   brq.data.sg_len = i;
  }

  mmc_queue_bounce_pre(mq);   /* 如果是写,则在请求被发送到主机驱动前弹出数据到buffer */

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

  mmc_queue_bounce_post(mq);    /* 如果是读,则在请求被主机驱动处理后弹出数据到buffer */

  /*
   * Check for errors here, but don't jump to cmd_err
   * until later as we need to wait for the card to leave
   * programming mode even when things go wrong.
   */
  if (brq.cmd.error || brq.data.error || brq.stop.error) {
   if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {
    /* Redo read one sector at a time */
    printk(KERN_WARNING "%s: retrying using single "
           "block read\n", req->rq_disk->disk_name);
    disable_multi = 1;
    continue;
   }
   status = get_card_status(card, req);  /* 获取卡的状态 */
  }

  if (brq.cmd.error) {
   printk(KERN_ERR "%s: error %d sending read/write "
          "command, response %#x, card status %#x\n",
          req->rq_disk->disk_name, brq.cmd.error,
          brq.cmd.resp[0], status);
  }

  if (brq.data.error) {
   if (brq.data.error == -ETIMEDOUT && brq.mrq.stop)
    /* 'Stop' response contains card status */
    status = brq.mrq.stop->resp[0];
   printk(KERN_ERR "%s: error %d transferring data,"
          " sector %u, nr %u, card status %#x\n",
          req->rq_disk->disk_name, brq.data.error,
          (unsigned)req->sector,
          (unsigned)req->nr_sectors, status);
  }

  if (brq.stop.error) {
   printk(KERN_ERR "%s: error %d sending stop command, "
          "response %#x, card status %#x\n",
          req->rq_disk->disk_name, brq.stop.error,
          brq.stop.resp[0], status);
  }

  if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
   do {
    int err;

    cmd.opcode = MMC_SEND_STATUS;
    cmd.arg = card->rca << 16;
    cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
    err = mmc_wait_for_cmd(card->host, &cmd, 5);
    if (err) {
     printk(KERN_ERR "%s: error %d requesting status\n",
            req->rq_disk->disk_name, err);
     goto cmd_err;
    }
    /*
     * Some cards mishandle the status bits,
     * so make sure to check both the busy
     * indication and the card state.
     */
   } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
    (R1_CURRENT_STATE(cmd.resp[0]) == 7));

#if 0
   if (cmd.resp[0] & ~0x00000900)
    printk(KERN_ERR "%s: status = %08x\n",
           req->rq_disk->disk_name, cmd.resp[0]);
   if (mmc_decode_status(cmd.resp))
    goto cmd_err;
#endif
  }

  if (brq.cmd.error || brq.stop.error || brq.data.error) {
   if (rq_data_dir(req) == READ) {
    /*
     * After an error, we redo I/O one sector at a
     * time, so we only reach here after trying to
     * read a single sector.
     */
    spin_lock_irq(&md->lock);
    ret = __blk_end_request(req, -EIO, brq.data.blksz);
    spin_unlock_irq(&md->lock);
    continue;
   }
   goto cmd_err;
  }

  /*
   * A block was successfully transferred.
   */
  spin_lock_irq(&md->lock);
  ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
  spin_unlock_irq(&md->lock);
 } while (ret);

 mmc_release_host(card->host);  /* 释放主机 */

 return 1;

 cmd_err:
  /*
   * If this is an SD card and we're writing, we can first
   * mark the known good sectors as ok.
   *
  * If the card is not SD, we can still ok written sectors
  * as reported by the controller (which might be less than
  * the real number of written sectors, but never more).
  */
 if (mmc_card_sd(card)) {
  u32 blocks;

  blocks = mmc_sd_num_wr_blocks(card);
  if (blocks != (u32)-1) {
   spin_lock_irq(&md->lock);
   ret = __blk_end_request(req, 0, blocks << 9);
   spin_unlock_irq(&md->lock);
  }
 } else {
  spin_lock_irq(&md->lock);
  ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
  spin_unlock_irq(&md->lock);
 }

 mmc_release_host(card->host);

 spin_lock_irq(&md->lock);
 while (ret)
  ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
 spin_unlock_irq(&md->lock);

 return 0;
}


static inline int mmc_blk_readonly(struct mmc_card *card)
{
 return mmc_card_readonly(card) ||
        !(card->csd.cmdclass & CCC_BLOCK_WRITE);
}

/* 分配一个MMC块设备----分配并初始化一个struct mmc_blk_data结构体,初始化通用磁盘及请求队列 */
static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
{
 struct mmc_blk_data *md;
 int devidx, ret;

 devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);  /* 在 dev_use数组中找到第一个0位*/
 if (devidx >= MMC_NUM_MINORS)
  return ERR_PTR(-ENOSPC);
 __set_bit(devidx, dev_use);  /* 设置数组 dev_use的第devidx位的值为1--->表示使用*/

 md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);  /* 分配一个struct mmc_blk_data结构体 */
 if (!md) {
  ret = -ENOMEM;
  goto out;
 }


 /*
  * Set the read-only status based on the supported commands
  * and the write protect switch.
  */
 md->read_only = mmc_blk_readonly(card);

 md->disk = alloc_disk(1 << MMC_SHIFT);  /* 分配一个struct gendisk结构体 ,次设备号(分区数)为8*/
 if (md->disk == NULL) {
  ret = -ENOMEM;
  goto err_kfree;
 }

 spin_lock_init(&md->lock);
 md->usage = 1;

 ret = mmc_init_queue(&md->queue, card, &md->lock);  /* 初始化mmc 请求队列*/
 if (ret)
  goto err_putdisk;

 md->queue.issue_fn = mmc_blk_issue_rq;  /* 绑定发出读写请求的函数 */
 md->queue.data = md;  /*struct mmc_blk_data结构体的地址保存起来方便以后使用  */
 
      /* 初始化分配的gendisk的成员 */
 md->disk->major = MMC_BLOCK_MAJOR;
 md->disk->first_minor = devidx << MMC_SHIFT;
 md->disk->fops = &mmc_bdops;  /* 设置操作函数 */
 md->disk->private_data = md;  /*struct mmc_blk_data结构体的地址保存起来方便以后使用  */
 md->disk->queue = md->queue.queue;
 md->disk->driverfs_dev = &card->dev;

 /*
  * As discussed on lkml, GENHD_FL_REMOVABLE should:
  *
  * - be set for removable media with permanent block devices
  * - be unset for removable block devices with permanent media
  *
  * Since MMC block devices clearly fall under the second
  * case, we do not set GENHD_FL_REMOVABLE.  Userspace
  * should use the block device creation/destruction hotplug
  * messages to tell when the card is present.
  */

 sprintf(md->disk->disk_name, "mmcblk%d", devidx);

 blk_queue_hardsect_size(md->queue.queue, 512);  /* 设置硬件能处理的最小的扇区大小为512字节 */

 if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {  /* 如果卡不是SD卡并且 卡使用块地址  */
  /*
   * The EXT_CSD sector count is in number or 512 byte
   * sectors.
   */
  set_capacity(md->disk, card->ext_csd.sectors);  /* 设置容量(单位为扇区) 即md->disk->part0.nr_sects = card->ext_csd.sectors*/
 } else {       /* SD卡 */ 
  /*
   * The CSD capacity field is in units of read_blkbits.
   * set_capacity takes units of 512 bytes.
   */
  set_capacity(md->disk,
   card->csd.capacity << (card->csd.read_blkbits - 9)); /* 设置容量(单位为扇区) 即md->disk->part0.nr_sects =card->csd.capacity << (card->csd.read_blkbits - 9)*/
 }
 return md;

 err_putdisk:
 put_disk(md->disk);
 err_kfree:
 kfree(md);
 out:
 return ERR_PTR(ret);
}

 /* 设置卡大小,发送命令设置卡为选中状态 */
static int
mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
{
 struct mmc_command cmd;
 int err;

 /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
 if (mmc_card_blockaddr(card))  /* 如果卡使用块地址则返回*/
  return 0;

 mmc_claim_host(card->host);  /* 声明一个主机 */
 cmd.opcode = MMC_SET_BLOCKLEN;
 cmd.arg = 512;
 cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
 err = mmc_wait_for_cmd(card->host, &cmd, 5);  /* 发送命令并等待它完成 */
 mmc_release_host(card->host); /* 释放主机 */

 if (err) {
  printk(KERN_ERR "%s: unable to set block size to %d: %d\n",
   md->disk->disk_name, cmd.arg, err);
  return -EINVAL;
 }

 return 0;
}

 /* 探测函数----它探测MMC控制器释否存在,并初始化控制器的结构以及探测MMC卡的状态并初始化 */
static int mmc_blk_probe(struct mmc_card *card)
{
 struct mmc_blk_data *md;
 int err;

 char cap_str[10];

 /*
  * Check that the card supports the command class(es) we need.
  */
 if (!(card->csd.cmdclass & CCC_BLOCK_READ))  /* 如果 卡不支持块读命令则返回错误*/
  return -ENODEV;

 md = mmc_blk_alloc(card);  /* 分配一个MMC块设备----分配并初始化一个struct mmc_blk_data结构体 */
 if (IS_ERR(md))
  return PTR_ERR(md);

 err = mmc_blk_set_blksize(md, card); /* 设置卡大小,发送命令设置卡为选中状态 */
 if (err)
  goto out;

 string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
   cap_str, sizeof(cap_str));
 printk(KERN_INFO "%s: %s %s %s %s\n",
  md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
  cap_str, md->read_only ? "(ro)" : "");

 mmc_set_drvdata(card, md);  /* 将md保存起来即card->dev->driver_data=md */
 add_disk(md->disk);  /* 添加 一个磁盘*/
 return 0;

 out:
 mmc_blk_put(md);

 return err;
}

/* 移除函数 */
static void mmc_blk_remove(struct mmc_card *card)
{
 struct mmc_blk_data *md = mmc_get_drvdata(card);

 if (md) {
  /* Stop new requests from getting into the queue */
  del_gendisk(md->disk);  /* 注销磁盘 */

  /* Then flush out any already in there */
  mmc_cleanup_queue(&md->queue);  /* 释放请求队列 */

  mmc_blk_put(md);  /* 释放struct mmc_blk_data结构体 */
 }
 mmc_set_drvdata(card, NULL);  /*card->dev->driver_data=NULL  */
}

#ifdef CONFIG_PM
 /* 挂起设备函数 */
static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
{
 struct mmc_blk_data *md = mmc_get_drvdata(card);

 if (md) {
  mmc_queue_suspend(&md->queue);  /* 挂起请求队列 */
 }
 return 0;
}

/* 恢复设备函数 */
static int mmc_blk_resume(struct mmc_card *card)
{
 struct mmc_blk_data *md = mmc_get_drvdata(card);

 if (md) {
  mmc_blk_set_blksize(md, card); /* 设置卡的大小,发送命令设置卡为选中状态 */
  mmc_queue_resume(&md->queue);  /* 恢复请求队列 */
 }
 return 0;
}
#else
#define mmc_blk_suspend NULL
#define mmc_blk_resume NULL
#endif

static struct mmc_driver mmc_driver = {
 .drv  = {
  .name = "mmcblk",  /* 驱动名字为mmcblk */
 },
 .probe  = mmc_blk_probe,    /* 探测函数 */
 .remove  = mmc_blk_remove, /* 移除函数 */
 .suspend = mmc_blk_suspend,       /* 挂起设备函数 */
 .resume  = mmc_blk_resume, /* 恢复设备函数 */
};

static int __init mmc_blk_init(void)
{
 int res;

 res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");  /* 注册块设备,设备名为mmc */
 if (res)
  goto out;

 res = mmc_register_driver(&mmc_driver);  /* 注册MMC设备驱动 */
 if (res)
  goto out2;

 return 0;
 out2:
 unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
 out:
 return res;
}

static void __exit mmc_blk_exit(void)
{
 mmc_unregister_driver(&mmc_driver);
 unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
}

module_init(mmc_blk_init);
module_exit(mmc_blk_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");

 

阅读(1954) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~