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

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

?? nftlcore.c

?? 飛思卡爾芯片imx27下的MTD模塊的驅動源碼
?? C
?? 第 1 頁 / 共 2 頁
字號:
/* Linux driver for NAND Flash Translation Layer      *//* (c) 1999 Machine Vision Holdings, Inc.             *//* Author: David Woodhouse <dwmw2@infradead.org>      *//* $Id: nftlcore.c,v 1.1.1.1 2007/09/01 10:29:10 hansorblue Exp $ *//*  The contents of this file are distributed under the GNU General  Public License version 2. The author places no additional  restrictions of any kind on it. */#define PRERELEASE#include <linux/kernel.h>#include <linux/module.h>#include <asm/errno.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/miscdevice.h>#include <linux/pci.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/hdreg.h>#include <linux/kmod.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/mtd/nftl.h>#include <linux/mtd/blktrans.h>/* maximum number of loops while examining next block, to have a   chance to detect consistency problems (they should never happen   because of the checks done in the mounting */#define MAX_LOOPS 10000static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd){	struct NFTLrecord *nftl;	unsigned long temp;	if (mtd->type != MTD_NANDFLASH)		return;	/* OK, this is moderately ugly.  But probably safe.  Alternatives? */	if (memcmp(mtd->name, "DiskOnChip", 10))		return;	if (!mtd->block_isbad) {		printk(KERN_ERR"NFTL no longer supports the old DiskOnChip drivers loaded via docprobe.\n""Please use the new diskonchip driver under the NAND subsystem.\n");		return;	}	DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name);	nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);	if (!nftl) {		printk(KERN_WARNING "NFTL: out of memory for data structures\n");		return;	}	memset(nftl, 0, sizeof(*nftl));	nftl->mbd.mtd = mtd;	nftl->mbd.devnum = -1;	nftl->mbd.blksize = 512;	nftl->mbd.tr = tr;        if (NFTL_mount(nftl) < 0) {		printk(KERN_WARNING "NFTL: could not mount device\n");		kfree(nftl);		return;        }	/* OK, it's a new one. Set up all the data structures. */	/* Calculate geometry */	nftl->cylinders = 1024;	nftl->heads = 16;	temp = nftl->cylinders * nftl->heads;	nftl->sectors = nftl->mbd.size / temp;	if (nftl->mbd.size % temp) {		nftl->sectors++;		temp = nftl->cylinders * nftl->sectors;		nftl->heads = nftl->mbd.size / temp;		if (nftl->mbd.size % temp) {			nftl->heads++;			temp = nftl->heads * nftl->sectors;			nftl->cylinders = nftl->mbd.size / temp;		}	}	if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) {		/*		  Oh no we don't have		   mbd.size == heads * cylinders * sectors		*/		printk(KERN_WARNING "NFTL: cannot calculate a geometry to "		       "match size of 0x%lx.\n", nftl->mbd.size);		printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d "			"(== 0x%lx sects)\n",			nftl->cylinders, nftl->heads , nftl->sectors,			(long)nftl->cylinders * (long)nftl->heads *			(long)nftl->sectors );	}	if (add_mtd_blktrans_dev(&nftl->mbd)) {		kfree(nftl->ReplUnitTable);		kfree(nftl->EUNtable);		kfree(nftl);		return;	}#ifdef PSYCHO_DEBUG	printk(KERN_INFO "NFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a');#endif}static void nftl_remove_dev(struct mtd_blktrans_dev *dev){	struct NFTLrecord *nftl = (void *)dev;	DEBUG(MTD_DEBUG_LEVEL1, "NFTL: remove_dev (i=%d)\n", dev->devnum);	del_mtd_blktrans_dev(dev);	kfree(nftl->ReplUnitTable);	kfree(nftl->EUNtable);	kfree(nftl);}/* * Read oob data from flash */int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,		  size_t *retlen, uint8_t *buf){	struct mtd_oob_ops ops;	int res;	ops.mode = MTD_OOB_PLACE;	ops.ooboffs = offs & (mtd->writesize - 1);	ops.ooblen = len;	ops.oobbuf = buf;	ops.datbuf = NULL;	ops.len = len;	res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);	*retlen = ops.retlen;	return res;}/* * Write oob data to flash */int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,		   size_t *retlen, uint8_t *buf){	struct mtd_oob_ops ops;	int res;	ops.mode = MTD_OOB_PLACE;	ops.ooboffs = offs & (mtd->writesize - 1);	ops.ooblen = len;	ops.oobbuf = buf;	ops.datbuf = NULL;	ops.len = len;	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);	*retlen = ops.retlen;	return res;}#ifdef CONFIG_NFTL_RW/* * Write data and oob to flash */static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,		      size_t *retlen, uint8_t *buf, uint8_t *oob){	struct mtd_oob_ops ops;	int res;	ops.mode = MTD_OOB_PLACE;	ops.ooboffs = offs;	ops.ooblen = mtd->oobsize;	ops.oobbuf = oob;	ops.datbuf = buf;	ops.len = len;	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);	*retlen = ops.retlen;	return res;}/* Actual NFTL access routines *//* NFTL_findfreeblock: Find a free Erase Unit on the NFTL partition. This function is used *	when the give Virtual Unit Chain */static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ){	/* For a given Virtual Unit Chain: find or create a free block and	   add it to the chain */	/* We're passed the number of the last EUN in the chain, to save us from	   having to look it up again */	u16 pot = nftl->LastFreeEUN;	int silly = nftl->nb_blocks;	/* Normally, we force a fold to happen before we run out of free blocks completely */	if (!desperate && nftl->numfreeEUNs < 2) {		DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n");		return 0xffff;	}	/* Scan for a free block */	do {		if (nftl->ReplUnitTable[pot] == BLOCK_FREE) {			nftl->LastFreeEUN = pot;			nftl->numfreeEUNs--;			return pot;		}		/* This will probably point to the MediaHdr unit itself,		   right at the beginning of the partition. But that unit		   (and the backup unit too) should have the UCI set		   up so that it's not selected for overwriting */		if (++pot > nftl->lastEUN)			pot = le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN);		if (!silly--) {			printk("Argh! No free blocks found! LastFreeEUN = %d, "			       "FirstEUN = %d\n", nftl->LastFreeEUN,			       le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN));			return 0xffff;		}	} while (pot != nftl->LastFreeEUN);	return 0xffff;}static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ){	struct mtd_info *mtd = nftl->mbd.mtd;	u16 BlockMap[MAX_SECTORS_PER_UNIT];	unsigned char BlockLastState[MAX_SECTORS_PER_UNIT];	unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT];	unsigned int thisEUN;	int block;	int silly;	unsigned int targetEUN;	struct nftl_oob oob;	int inplace = 1;	size_t retlen;	memset(BlockMap, 0xff, sizeof(BlockMap));	memset(BlockFreeFound, 0, sizeof(BlockFreeFound));	thisEUN = nftl->EUNtable[thisVUC];	if (thisEUN == BLOCK_NIL) {		printk(KERN_WARNING "Trying to fold non-existent "		       "Virtual Unit Chain %d!\n", thisVUC);		return BLOCK_NIL;	}	/* Scan to find the Erase Unit which holds the actual data for each	   512-byte block within the Chain.	*/	silly = MAX_LOOPS;	targetEUN = BLOCK_NIL;	while (thisEUN <= nftl->lastEUN ) {		unsigned int status, foldmark;		targetEUN = thisEUN;		for (block = 0; block < nftl->EraseSize / 512; block ++) {			nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +				      (block * 512), 16 , &retlen,				      (char *)&oob);			if (block == 2) {				foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;				if (foldmark == FOLD_MARK_IN_PROGRESS) {					DEBUG(MTD_DEBUG_LEVEL1,					      "Write Inhibited on EUN %d\n", thisEUN);					inplace = 0;				} else {					/* There's no other reason not to do inplace,					   except ones that come later. So we don't need					   to preserve inplace */					inplace = 1;				}			}			status = oob.b.Status | oob.b.Status1;			BlockLastState[block] = status;			switch(status) {			case SECTOR_FREE:				BlockFreeFound[block] = 1;				break;			case SECTOR_USED:				if (!BlockFreeFound[block])					BlockMap[block] = thisEUN;				else					printk(KERN_WARNING					       "SECTOR_USED found after SECTOR_FREE "					       "in Virtual Unit Chain %d for block %d\n",					       thisVUC, block);				break;			case SECTOR_DELETED:				if (!BlockFreeFound[block])					BlockMap[block] = BLOCK_NIL;				else					printk(KERN_WARNING					       "SECTOR_DELETED found after SECTOR_FREE "					       "in Virtual Unit Chain %d for block %d\n",					       thisVUC, block);				break;			case SECTOR_IGNORE:				break;			default:				printk("Unknown status for block %d in EUN %d: %x\n",				       block, thisEUN, status);			}		}		if (!silly--) {			printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",			       thisVUC);			return BLOCK_NIL;		}		thisEUN = nftl->ReplUnitTable[thisEUN];	}	if (inplace) {		/* We're being asked to be a fold-in-place. Check		   that all blocks which actually have data associated		   with them (i.e. BlockMap[block] != BLOCK_NIL) are		   either already present or SECTOR_FREE in the target		   block. If not, we're going to have to fold out-of-place		   anyway.		*/		for (block = 0; block < nftl->EraseSize / 512 ; block++) {			if (BlockLastState[block] != SECTOR_FREE &&			    BlockMap[block] != BLOCK_NIL &&			    BlockMap[block] != targetEUN) {				DEBUG(MTD_DEBUG_LEVEL1, "Setting inplace to 0. VUC %d, "				      "block %d was %x lastEUN, "				      "and is in EUN %d (%s) %d\n",				      thisVUC, block, BlockLastState[block],				      BlockMap[block],				      BlockMap[block]== targetEUN ? "==" : "!=",				      targetEUN);				inplace = 0;				break;			}		}		if (pendingblock >= (thisVUC * (nftl->EraseSize / 512)) &&		    pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) &&		    BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] !=		    SECTOR_FREE) {			DEBUG(MTD_DEBUG_LEVEL1, "Pending write not free in EUN %d. "			      "Folding out of place.\n", targetEUN);			inplace = 0;		}	}	if (!inplace) {		DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. "		      "Trying out-of-place\n", thisVUC);		/* We need to find a targetEUN to fold into. */		targetEUN = NFTL_findfreeblock(nftl, 1);		if (targetEUN == BLOCK_NIL) {			/* Ouch. Now we're screwed. We need to do a			   fold-in-place of another chain to make room			   for this one. We need a better way of selecting			   which chain to fold, because makefreeblock will			   only ask us to fold the same one again.			*/			printk(KERN_WARNING			       "NFTL_findfreeblock(desperate) returns 0xffff.\n");			return BLOCK_NIL;		}	} else {		/* We put a fold mark in the chain we are folding only if we               fold in place to help the mount check code. If we do not fold in               place, it is possible to find the valid chain by selecting the               longer one */		oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);		oob.u.c.unused = 0xffffffff;		nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,			       8, &retlen, (char *)&oob.u);	}	/* OK. We now know the location of every block in the Virtual Unit Chain,	   and the Erase Unit into which we are supposed to be copying.	   Go for it.	*/	DEBUG(MTD_DEBUG_LEVEL1,"Folding chain %d into unit %d\n", thisVUC, targetEUN);	for (block = 0; block < nftl->EraseSize / 512 ; block++) {		unsigned char movebuf[512];		int ret;		/* If it's in the target EUN already, or if it's pending write, do nothing */		if (BlockMap[block] == targetEUN ||		    (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) {			continue;		}

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
日av在线不卡| 欧美日韩国产精品自在自线| 亚洲欧美日本韩国| 91免费看视频| 日本视频一区二区三区| 久久久99久久| 欧美视频在线一区| 精品一区二区三区欧美| 亚洲精品国久久99热| 日韩欧美一区二区视频| 在线观看国产91| 丁香啪啪综合成人亚洲小说| 免费在线成人网| 一区二区三区免费在线观看| 久久久一区二区三区| 欧美日韩国产小视频| 亚洲综合网站在线观看| 日本一区二区三区视频视频| 国产乱一区二区| 亚洲自拍与偷拍| 91福利在线播放| 91美女在线视频| 色又黄又爽网站www久久| 成人美女在线观看| 成人一区二区三区| 成人免费毛片片v| 福利电影一区二区三区| 国产福利不卡视频| 粉嫩高潮美女一区二区三区| 国内精品国产成人国产三级粉色 | 欧美日韩成人在线一区| 日本黄色一区二区| 日本丶国产丶欧美色综合| 91成人网在线| 欧美福利一区二区| 欧美三级电影网| 91丝袜美腿高跟国产极品老师 | 欧美sm美女调教| 国产午夜精品久久| 一区二区三区久久| 韩国欧美国产1区| 91在线观看地址| 日韩一区国产二区欧美三区| 久久蜜桃一区二区| 午夜免费久久看| 国产成人一区在线| 欧美一区日本一区韩国一区| 久久精品亚洲乱码伦伦中文 | 综合亚洲深深色噜噜狠狠网站| 亚洲欧美激情视频在线观看一区二区三区| 亚洲最大成人网4388xx| 国产精品自在欧美一区| 欧美日韩高清一区二区三区| 国产三级精品视频| 久久激情五月激情| 在线免费观看日韩欧美| 国产午夜精品一区二区三区四区| 亚洲国产综合视频在线观看| 高清不卡一二三区| 久久综合资源网| 精品一二线国产| 日韩午夜激情免费电影| 亚洲一区电影777| 欧美亚洲图片小说| 亚洲综合999| 欧美日韩免费不卡视频一区二区三区| 亚洲欧洲日韩在线| av在线一区二区三区| 欧美成人猛片aaaaaaa| 五月开心婷婷久久| 日韩欧美一区二区在线视频| 亚洲综合区在线| 欧美日韩一级二级三级| 亚洲第一福利视频在线| 欧美日韩视频在线观看一区二区三区| 亚洲久草在线视频| 欧美人与z0zoxxxx视频| 亚洲国产中文字幕| 欧美电影免费观看高清完整版在线 | 一区二区三区高清| 色婷婷亚洲综合| 亚洲国产日韩一级| 日韩一区和二区| 大胆欧美人体老妇| 亚洲色图欧美在线| 日韩一区二区麻豆国产| 成人精品鲁一区一区二区| 亚洲美女视频在线观看| 日韩一区二区精品在线观看| 成人动漫中文字幕| 日韩影院在线观看| 国产精品久久久久婷婷二区次| 欧美亚洲动漫精品| 国产91精品免费| 麻豆视频一区二区| 亚洲色图在线播放| 国产午夜精品福利| 91精品欧美久久久久久动漫 | bt欧美亚洲午夜电影天堂| 蜜臀91精品一区二区三区| 亚洲色图都市小说| 久久综合久久综合九色| 欧美日本在线看| 91麻豆免费观看| 国产剧情av麻豆香蕉精品| 亚洲激情一二三区| 亚洲一区二区3| 亚洲国产精品久久不卡毛片 | 91精品福利在线一区二区三区 | 日本中文一区二区三区| 亚洲一区二区三区中文字幕 | 亚洲成av人影院| 亚洲永久免费视频| 亚洲一区二区三区在线看| 亚洲一区二区精品久久av| 亚洲三级在线播放| 亚洲综合在线免费观看| 亚洲午夜日本在线观看| 亚洲成人tv网| 蜜桃av一区二区三区电影| 精品夜夜嗨av一区二区三区| 国产一区二区三区精品欧美日韩一区二区三区 | 亚洲日本va午夜在线影院| 一色屋精品亚洲香蕉网站| 亚洲黄色片在线观看| 亚洲成人av电影| 国产69精品久久久久777| 一本久道中文字幕精品亚洲嫩| 日本韩国欧美三级| 日韩视频不卡中文| 亚洲欧美日韩中文播放| 亚洲狠狠爱一区二区三区| 久久国产精品区| 一本到一区二区三区| 久久蜜桃一区二区| 日韩电影免费在线看| 成人app下载| 国产亚洲美州欧州综合国| 亚洲国产精品久久久久婷婷884 | 日韩一区日韩二区| 国产在线不卡一区| 欧美性极品少妇| 国产精品污网站| 黄色精品一二区| 日韩欧美中文字幕一区| 一区二区三区在线影院| 欧美一区二区在线观看| 综合久久国产九一剧情麻豆| 久久国产婷婷国产香蕉| 91精品国产手机| 午夜影院久久久| 欧美日韩精品欧美日韩精品一| 亚洲日本在线看| 99久久精品国产一区二区三区| 中文字幕欧美日本乱码一线二线| 极品少妇一区二区三区精品视频| 91麻豆精品国产91久久久久久久久 | 蜜臀av性久久久久av蜜臀妖精| 欧美午夜精品一区二区蜜桃| 亚洲欧美国产毛片在线| 91色视频在线| 日本亚洲最大的色成网站www| 欧美天堂一区二区三区| 午夜国产精品一区| 制服丝袜亚洲网站| 国产久卡久卡久卡久卡视频精品| 国产农村妇女精品| 91丨porny丨首页| 蜜臀精品一区二区三区在线观看 | 欧美精品一二三区| 国产在线视视频有精品| 成人免费在线观看入口| 欧美日高清视频| caoporen国产精品视频| 日韩精品成人一区二区在线| 国产喷白浆一区二区三区| 91国内精品野花午夜精品| 黄色小说综合网站| 亚洲丶国产丶欧美一区二区三区| 欧美精品一区视频| 欧美专区在线观看一区| 成人黄色在线看| 韩国成人在线视频| 日韩av中文在线观看| 亚洲综合在线五月| 日韩毛片一二三区| 久久久久国产精品麻豆ai换脸| 欧美日韩国产首页| 在线观看欧美黄色| 在线免费观看成人短视频| 国产a久久麻豆| 国产成人av一区二区| 国产精品资源在线看| 国产麻豆精品在线| 国产精品一区二区三区四区| 免费观看日韩av| 国产精品一区久久久久| 国产精品一级在线| 风流少妇一区二区| 91蝌蚪porny|