linux open sd设备,(9)linux设备驱动之MMC SD卡——SD卡相关接口简单分析

/*************************************************************************************************************************************/

/* 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");

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值