亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? mmc_block.c

?? linux下基于arm處理器s3c2410x開發板的MMC設備驅動程序。
?? C
字號:
/* * Block driver for media (i.e., flash cards) * */#include <linux/moduleparam.h>#include <linux/module.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/hdreg.h>#include <linux/kdev_t.h>#include <linux/blkdev.h>#include <linux/devfs_fs_kernel.h>#include <linux/mmc/card.h>#include <linux/mmc/protocol.h>#include <asm/system.h>#include <asm/uaccess.h>#include "mmc_queue.h"/* * max 8 partitions per card */#define MMC_SHIFT	3static int major;/* * There is one mmc_blk_data per slot. */struct mmc_blk_data {	spinlock_t	lock;	struct gendisk	*disk;	struct mmc_queue queue;	unsigned int	usage;	unsigned int	block_bits;};static DECLARE_MUTEX(open_lock);static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk){	struct mmc_blk_data *md;	down(&open_lock);	md = disk->private_data;	if (md && md->usage == 0)		md = NULL;	if (md)		md->usage++;	up(&open_lock);	return md;}static void mmc_blk_put(struct mmc_blk_data *md){	down(&open_lock);	md->usage--;	if (md->usage == 0) {		put_disk(md->disk);		mmc_cleanup_queue(&md->queue);		kfree(md);	}	up(&open_lock);}static int mmc_blk_open(struct inode *inode, struct file *filp){	struct mmc_blk_data *md;	int ret = -ENXIO;	md = mmc_blk_get(inode->i_bdev->bd_disk);	if (md) {		if (md->usage == 2)			check_disk_change(inode->i_bdev);		ret = 0;	}	return ret;}static int mmc_blk_release(struct inode *inode, struct file *filp){	struct mmc_blk_data *md = inode->i_bdev->bd_disk->private_data;	mmc_blk_put(md);	return 0;}static intmmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){	struct block_device *bdev = inode->i_bdev;	if (cmd == HDIO_GETGEO) {		struct hd_geometry geo;		memset(&geo, 0, sizeof(struct hd_geometry));		geo.cylinders	= get_capacity(bdev->bd_disk) / (4 * 16);		geo.heads	= 4;		geo.sectors	= 16;		geo.start	= get_start_sect(bdev);		return copy_to_user((void __user *)arg, &geo, sizeof(geo))			? -EFAULT : 0;	}	return -ENOTTY;}static struct block_device_operations mmc_bdops = {	.open			= mmc_blk_open,	.release		= mmc_blk_release,	.ioctl			= mmc_blk_ioctl,	.owner			= THIS_MODULE,};struct mmc_blk_request {	struct mmc_request	mrq;	struct mmc_command	cmd;	struct mmc_command	stop;	struct mmc_data		data;};static int mmc_blk_prep_rq(struct mmc_queue *mq, struct request *req){	struct mmc_blk_data *md = mq->data;	int stat = BLKPREP_OK;	/*	 * If we have no device, we haven't finished initialising.	 */	if (!md || !mq->card) {		printk(KERN_ERR "%s: killing request - no device/host\n",		       req->rq_disk->disk_name);		stat = BLKPREP_KILL;	}	return stat;}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;	int ret;	if (mmc_card_claim_host(card))		goto cmd_err;	do {		struct mmc_blk_request brq;		struct mmc_command cmd;		memset(&brq, 0, sizeof(struct mmc_blk_request));		brq.mrq.cmd = &brq.cmd;		brq.mrq.data = &brq.data;		brq.cmd.arg = req->sector << 9;		brq.cmd.flags = MMC_RSP_R1;		brq.data.req = req;		brq.data.timeout_ns = card->csd.tacc_ns * 10;		brq.data.timeout_clks = card->csd.tacc_clks * 10;		brq.data.blksz_bits = md->block_bits;		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);		brq.stop.opcode = MMC_STOP_TRANSMISSION;		brq.stop.arg = 0;		brq.stop.flags = MMC_RSP_R1B;		if (rq_data_dir(req) == READ) {			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;			brq.data.flags |= MMC_DATA_READ;		} else {			brq.cmd.opcode = MMC_WRITE_BLOCK;			brq.cmd.flags = MMC_RSP_R1B;			brq.data.flags |= MMC_DATA_WRITE;			brq.data.blocks = 1;		}		brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL;		brq.data.sg = mq->sg;		brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);		mmc_wait_for_req(card->host, &brq.mrq);		if (brq.cmd.error) {			printk(KERN_ERR "%s: error %d sending read/write command\n",			       req->rq_disk->disk_name, brq.cmd.error);			goto cmd_err;		}		if (brq.data.error) {			printk(KERN_ERR "%s: error %d transferring data\n",			       req->rq_disk->disk_name, brq.data.error);			goto cmd_err;		}		if (brq.stop.error) {			printk(KERN_ERR "%s: error %d sending stop command\n",			       req->rq_disk->disk_name, brq.stop.error);			goto cmd_err;		}		do {			int err;			cmd.opcode = MMC_SEND_STATUS;			cmd.arg = card->rca << 16;			cmd.flags = MMC_RSP_R1;			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;			}		} while (!(cmd.resp[0] & R1_READY_FOR_DATA));#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		/*		 * A block was successfully transferred.		 */		spin_lock_irq(&md->lock);		ret = end_that_request_chunk(req, 1, brq.data.bytes_xfered);		if (!ret) {			/*			 * The whole request completed successfully.			 */			add_disk_randomness(req->rq_disk);			blkdev_dequeue_request(req);			end_that_request_last(req);		}		spin_unlock_irq(&md->lock);	} while (ret);	mmc_card_release_host(card);	return 1; cmd_err:	mmc_card_release_host(card);	/*	 * This is a little draconian, but until we get proper	 * error handling sorted out here, its the best we can	 * do - especially as some hosts have no idea how much	 * data was transferred before the error occurred.	 */	spin_lock_irq(&md->lock);	do {		ret = end_that_request_chunk(req, 0,				req->current_nr_sectors << 9);	} while (ret);	add_disk_randomness(req->rq_disk);	blkdev_dequeue_request(req);	end_that_request_last(req);	spin_unlock_irq(&md->lock);	return 0;}#define MMC_NUM_MINORS	(256 >> MMC_SHIFT)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;	devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);	if (devidx >= MMC_NUM_MINORS)		return ERR_PTR(-ENOSPC);	__set_bit(devidx, dev_use);	md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);	if (md) {		memset(md, 0, sizeof(struct mmc_blk_data));		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;		md->disk->first_minor = devidx << MMC_SHIFT;		md->disk->fops = &mmc_bdops;		md->disk->private_data = md;		md->disk->queue = md->queue.queue;		md->disk->driverfs_dev = &card->dev;		sprintf(md->disk->disk_name, "mmcblk%d", devidx);		sprintf(md->disk->devfs_name, "mmc/blk%d", devidx);		md->block_bits = card->csd.read_blkbits;		blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);		set_capacity(md->disk, card->csd.capacity);	} out:	return md;}static intmmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card){	struct mmc_command cmd;	int err;	mmc_card_claim_host(card);	cmd.opcode = MMC_SET_BLOCKLEN;	cmd.arg = 1 << card->csd.read_blkbits;	cmd.flags = MMC_RSP_R1;	err = mmc_wait_for_cmd(card->host, &cmd, 5);	mmc_card_release_host(card);	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;}static int mmc_blk_probe(struct mmc_card *card){	struct mmc_blk_data *md;	int err;	if (card->csd.cmdclass & ~0x1ff)		return -ENODEV;	if (card->csd.read_blkbits < 9) {		printk(KERN_WARNING "%s: read blocksize too small (%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 "%s: %s %s %dKiB\n",		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);	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) {		int devidx;		del_gendisk(md->disk);		/*		 * I think this is needed.		 */		md->disk->queue = NULL;		devidx = md->disk->first_minor >> MMC_SHIFT;		__clear_bit(devidx, dev_use);		mmc_blk_put(md);	}	mmc_set_drvdata(card, NULL);}#ifdef CONFIG_PMstatic int mmc_blk_suspend(struct mmc_card *card, u32 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#endifstatic struct mmc_driver mmc_driver = {	.drv		= {		.name	= "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 = -ENOMEM;	res = register_blkdev(major, "mmc");	if (res < 0) {		printk(KERN_WARNING "Unable to get major %d for MMC media: %d\n",		       major, res);		goto out;	}	if (major == 0)		major = res;	devfs_mk_dir("mmc");	return mmc_register_driver(&mmc_driver); out:	return res;}static void __exit mmc_blk_exit(void){	mmc_unregister_driver(&mmc_driver);	devfs_remove("mmc");	unregister_blkdev(major, "mmc");}module_init(mmc_blk_init);module_exit(mmc_blk_exit);MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");module_param(major, int, 0444);MODULE_PARM_DESC(major, "specify the major device number for MMC block driver");

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
欧美日韩精品欧美日韩精品一 | 亚洲妇熟xx妇色黄| 国产麻豆一精品一av一免费| 日韩欧美国产小视频| 国产在线国偷精品免费看| 免费精品视频在线| 国产亚洲一本大道中文在线| 国产成人精品三级| 亚洲素人一区二区| 欧美一级国产精品| 91视频观看免费| 日韩和的一区二区| 国产精品麻豆欧美日韩ww| 在线观看不卡一区| 国产在线精品国自产拍免费| 国产精品综合网| 天堂蜜桃91精品| 免费成人在线影院| 国产精品99久久久久久久女警 | 久久精品欧美一区二区三区不卡 | 亚洲免费在线电影| 精品国产乱码久久久久久老虎 | 偷偷要91色婷婷| 国产欧美中文在线| 日韩一区二区免费高清| 精品成人一区二区三区四区| 国产亚洲欧美一级| 亚洲另类在线一区| 国产精品美女久久久久aⅴ| 亚洲视频资源在线| 日欧美一区二区| 国产盗摄精品一区二区三区在线| 成人短视频下载| 久久99精品国产91久久来源| 樱桃国产成人精品视频| 日韩av午夜在线观看| 一区二区三区91| 国产精品短视频| 国产精品久久久久aaaa| 五月激情六月综合| 成人丝袜高跟foot| 国产99久久久国产精品| 国产精品77777竹菊影视小说| 色综合网站在线| 99精品视频在线观看免费| 成人福利电影精品一区二区在线观看| 91久久久免费一区二区| 91福利在线导航| 久久综合久久综合久久| 精品国产伦一区二区三区观看体验| 欧美国产精品中文字幕| 国产精品乱码人人做人人爱| 爽爽淫人综合网网站| 成人app在线| 26uuu另类欧美| 日韩中文字幕一区二区三区| av电影在线观看完整版一区二区| 亚洲成人综合网站| 亚洲电影你懂得| a亚洲天堂av| 精品国产免费人成电影在线观看四季| 性做久久久久久久免费看| 99久久伊人网影院| 国产欧美日韩三区| 国产成人8x视频一区二区| 91精品在线麻豆| 日韩午夜精品视频| 午夜免费久久看| 欧美日韩国产电影| 亚洲精品国产成人久久av盗摄| 成人免费看视频| 国产丝袜在线精品| 国产在线一区二区综合免费视频| 国产成人亚洲综合a∨婷婷| 精品少妇一区二区三区免费观看| 国产情人综合久久777777| 久久精品国产99国产| 成人动漫av在线| 国产欧美日韩精品一区| 国产综合久久久久久鬼色| 日韩欧美国产综合一区| 麻豆视频观看网址久久| 岛国av在线一区| 国产视频亚洲色图| 国产成人综合自拍| 久久久久成人黄色影片| 亚洲综合色区另类av| 激情av综合网| 欧美激情一二三区| 99久久综合精品| 亚洲午夜电影网| 制服丝袜亚洲色图| 国产精品一区三区| 国产精品素人视频| 91黄视频在线| 蓝色福利精品导航| 欧美国产精品专区| 欧美视频一区二区| 国产精品国产三级国产有无不卡| 99国产精品视频免费观看| 一区二区三区高清不卡| 欧美男人的天堂一二区| 免费成人在线播放| 久久精品网站免费观看| 91丨porny丨国产| 视频一区二区三区在线| 精品国产乱码久久久久久图片 | 亚洲视频香蕉人妖| 欧美日韩视频在线第一区 | 色素色在线综合| 亚洲欧美一区二区在线观看| 国产一区二区在线看| 国产精品美女视频| 欧美男人的天堂一二区| 国产成人精品亚洲午夜麻豆| 一区二区欧美精品| 国产亚洲污的网站| 51午夜精品国产| 成人一区二区三区在线观看| 午夜一区二区三区在线观看| 2017欧美狠狠色| 欧美精品久久久久久久久老牛影院| 亚洲婷婷国产精品电影人久久| 欧美精品久久久久久久多人混战 | 亚洲成人在线免费| 国产区在线观看成人精品| 欧美高清视频在线高清观看mv色露露十八 | 欧美美女bb生活片| 成人激情开心网| 日韩福利视频导航| 一区二区三区日韩欧美| 国产欧美日韩另类视频免费观看| 91精品久久久久久久99蜜桃| 91女厕偷拍女厕偷拍高清| 国产精品小仙女| 男人的天堂久久精品| 日韩美女视频一区| 久久亚洲精华国产精华液| 69久久夜色精品国产69蝌蚪网| 91蜜桃免费观看视频| 国产v综合v亚洲欧| 国内外成人在线视频| 日本成人在线不卡视频| 亚洲成人久久影院| 国产乱码精品一区二区三区av| 亚洲一级二级三级| 亚洲日本成人在线观看| 中文字幕亚洲视频| 国产精品久久久久久久久快鸭| 国产欧美一区二区在线| 久久九九全国免费| 国产无遮挡一区二区三区毛片日本 | 国产一区不卡在线| 理论片日本一区| 九九**精品视频免费播放| 午夜不卡在线视频| 日韩 欧美一区二区三区| 日韩精品久久理论片| 日韩精品久久理论片| 欧美aⅴ一区二区三区视频| 蜜桃av一区二区| 激情都市一区二区| 国产福利精品一区| 国产成人免费9x9x人网站视频| 国产精品一区二区免费不卡 | 国产精品美女久久久久高潮| 国产精品区一区二区三| **性色生活片久久毛片| 一区二区在线看| 日韩国产成人精品| 另类中文字幕网| 狠狠色狠狠色综合日日91app| 国产成人精品午夜视频免费| 成人av免费在线观看| 日本二三区不卡| 欧美一区二区三区视频在线观看| 国产精品一区二区在线播放| 欧美中文字幕一区二区三区亚洲| 欧美色视频在线观看| 91精品国产色综合久久不卡蜜臀| 精品久久久久久最新网址| 国产欧美精品一区二区色综合朱莉 | 国产精品国产自产拍高清av| 亚洲午夜精品在线| 精品中文字幕一区二区| 成人h精品动漫一区二区三区| 欧美影视一区二区三区| 日韩一区二区三区观看| 国产精品嫩草久久久久| 天天操天天干天天综合网| 国产精选一区二区三区| 色综合久久99| 精品福利视频一区二区三区| 国产精品久久久久影院| 日日摸夜夜添夜夜添国产精品| 成人高清伦理免费影院在线观看| 欧美浪妇xxxx高跟鞋交| 欧美激情在线看| 欧美精品一区二区精品网| 久久久99精品免费观看|