Linux内核MTD驱动程序与SD卡驱动程序(10)

2019-08-29 20:26

/*

* These are the response types, and correspond to valid bit * patterns of the above flags. One additional valid pattern * is all zeros, which means we don't expect a response. */

#define MMC_RSP_R1 (MMC_RSP_SHORT|MMC_RSP_CRC)

#define MMC_RSP_R1B (MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_BUSY) #define MMC_RSP_R2 (MMC_RSP_LONG|MMC_RSP_CRC) #define MMC_RSP_R3 (MMC_RSP_SHORT) unsigned int retries; /* max number of retries */ unsigned int error; /* command error */

#define MMC_ERR_NONE 0 #define MMC_ERR_TIMEOUT 1 #define MMC_ERR_BADCRC 2 #define MMC_ERR_FIFO 3 #define MMC_ERR_FAILED 4 #define MMC_ERR_INVALID 5 struct mmc_data *data; //与命令相关的数据片断 struct mmc_request *mrq; //与命令相关的请求 };

MMC抽象设备层MMC块设备驱动程序

(1)MMC块设备驱动程序初始化

函数mmc_blk_init注册一个MMC块设备驱动程序,它先将MMC块设备名注册到名称数组major_names中,然后,还把驱动程序注册到sysfs文件系统中的总线和设备目录中。一方面,sysfs文件系统中可显示MMC块设备相关信息,另一方面,sysfs文件系统以树形结构管理着MMC块设备驱动程序。 函数mmc_blk_init分析如下(在drivers/mmc/mmc_block.c中):

static int __init mmc_blk_init(void)

{ int res = -ENOMEM;

//将卡名字mmc和major注册到块设备的名称数组major_names中 res = register_blkdev(major, \ if (res < 0) { printk(KERN_WARNING \media: %d\\n\ major, res); goto out; } if (major == 0) major = res;

//在devfs文件系统中创建mmc目录 devfs_mk_dir(\ return mmc_register_driver(&mmc_driver);

out: return res; }

mmc_driver驱动程序实例声明如下:

static struct mmc_driver mmc_driver = { .drv = { .name = \ }, .probe = mmc_blk_probe, // MMC块设备驱动程序探测函数 .remove = mmc_blk_remove, .suspend = mmc_blk_suspend, .resume = mmc_blk_resume, };

函数mmc_register_driver 注册一个媒介层驱动程序。其中参数drv是MMC媒介层驱动程序结构。

函数mmc_register_driver分析如下(在drivers/mmc/mmc_sysfs.c中):

int mmc_register_driver(struct mmc_driver *drv) { drv->drv.bus = &mmc_bus_type; drv->drv.probe = mmc_drv_probe; drv->drv.remove = mmc_drv_remove;

//把块设备注册到sysfs文件系统中对应的总线及设备目录下 return driver_register(&drv->drv); }

(2)MMC块设备驱动程序探测函数

图 函数mmc_blk_probe调用层次图

函数mmc_blk_probe是MMC控制器探测函数,它探测MMC控制器是否存在,并初始化控制器的结构,同时,还探测MMC卡的状态并初始化。函数mmc_blk_probe调用层次图如上图。

函数mmc_blk_probe列出如下:

static int mmc_blk_probe(struct mmc_card *card) { struct mmc_blk_data *md; //每个插槽一个结构mmc_blk_data int err; if (card->csd.cmdclass & ~0x1ff) return -ENODEV;

if (card->csd.read_blkbits < 9) {//所读的块小于1扇区 printk(KERN_WARNING \(%u)\\n\ mmc_card_id(card), 1 << card->csd.read_blkbits); return -ENODEV; }

//分配每个插槽的卡的块数据结构,初始化了通用硬盘及请求队列 md = mmc_blk_alloc(card); if (IS_ERR(md)) return PTR_ERR(md);

//设置块大小,发命令设置卡为选中状态 err = mmc_blk_set_blksize(md, card); if (err) goto out; printk(KERN_INFO \ md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), (card->csd.capacity << card->csd.read_blkbits) / 1024); mmc_set_drvdata(card, md);//即card ->driver_data = md add_disk(md->disk); //向系统注册通用硬盘结构,它包括每分区信息 return 0;

out: mmc_blk_put(md); return err; }

函数*mmc_blk_alloc给每一插槽分配一个结构mmc_blk_data,并分配设置通用硬盘结构和初始了请求队列结构。

函数*mmc_blk_alloc分析如下(在drivers/mmc/mmc_block.c中):

//最大支持8个控制器,每个控制器可控制4个卡,每个卡最大8个分区。 #define MMC_SHIFT 3 //表示每个卡最大支持8个分区 #define MMC_NUM_MINORS (256 >> MMC_SHIFT) //为256/8=32

//即定义dev_use[32/(8*4)] = devuse[1],一个控制器用32位表示使用情况 static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))]; static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) { struct mmc_blk_data *md; int devidx, ret;

//查找dev_use中第一个bit为0的位序号(在MMC_NUM_MINORS位以内) //找到第个空闲的分区 devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS); if (devidx >= MMC_NUM_MINORS) return ERR_PTR(-ENOSPC); __set_bit(devidx, dev_use);//将分区对应的位设置为1,表示使用。 md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);//分配对象空间 if (md) { memset(md, 0, sizeof(struct mmc_blk_data)); //分配gendisk结构及通用硬盘的分区hd_struct结构,并初始化内核对象 md->disk = alloc_disk(1 << MMC_SHIFT); if (md->disk == NULL) { kfree(md); md = ERR_PTR(-ENOMEM); goto out; } spin_lock_init(&md->lock); md->usage = 1; //初始化请求队列 ret = mmc_init_queue(&md->queue, card, &md->lock); if (ret) { put_disk(md->disk); kfree(md); md = ERR_PTR(ret); goto out; }

//赋上各种请求队列处理函数 md->queue.prep_fn = mmc_blk_prep_rq;//准备请求 md->queue.issue_fn = mmc_blk_issue_rq;//发出请求让设备开始处理 md->queue.data = md; //初始化通用硬盘 md->disk->major = major;


Linux内核MTD驱动程序与SD卡驱动程序(10).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:8个穴位治8种常见病 记住一生受益

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: