⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inftlmount.c

📁 基于linux-2.6.28的mtd驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
		mtd->erase(inftl->mbd.mtd, instr);		if (instr->state == MTD_ERASE_FAILED) {			printk(KERN_WARNING "INFTL: error while formatting block %d\n",				block);			goto fail;		}		/*		 * Check the "freeness" of Erase Unit before updating metadata.		 * FixMe: is this check really necessary? Since we have check		 * the return code after the erase operation.		 */		if (check_free_sectors(inftl, instr->addr, instr->len, 1) != 0)			goto fail;	}	uci.EraseMark = cpu_to_le16(ERASE_MARK);	uci.EraseMark1 = cpu_to_le16(ERASE_MARK);	uci.Reserved[0] = 0;	uci.Reserved[1] = 0;	uci.Reserved[2] = 0;	uci.Reserved[3] = 0;	instr->addr = block * inftl->EraseSize + SECTORSIZE * 2;	if (inftl_write_oob(mtd, instr->addr + 8, 8, &retlen, (char *)&uci) < 0)		goto fail;	return 0;fail:	/* could not format, update the bad block table (caller is responsible	   for setting the PUtable to BLOCK_RESERVED on failure) */	inftl->mbd.mtd->block_markbad(inftl->mbd.mtd, instr->addr);	return -1;}/* * format_chain: Format an invalid Virtual Unit chain. It frees all the Erase *	Units in a Virtual Unit Chain, i.e. all the units are disconnected. * *	Since the chain is invalid then we will have to erase it from its *	head (normally for INFTL we go from the oldest). But if it has a *	loop then there is no oldest... */static void format_chain(struct INFTLrecord *inftl, unsigned int first_block){	unsigned int block = first_block, block1;	printk(KERN_WARNING "INFTL: formatting chain at block %d\n",		first_block);	for (;;) {		block1 = inftl->PUtable[block];		printk(KERN_WARNING "INFTL: formatting block %d\n", block);		if (INFTL_formatblock(inftl, block) < 0) {			/*			 * Cannot format !!!! Mark it as Bad Unit,			 */			inftl->PUtable[block] = BLOCK_RESERVED;		} else {			inftl->PUtable[block] = BLOCK_FREE;		}		/* Goto next block on the chain */		block = block1;		if (block == BLOCK_NIL || block >= inftl->lastEUN)			break;	}}void INFTL_dumptables(struct INFTLrecord *s){	int i;	printk("-------------------------------------------"		"----------------------------------\n");	printk("VUtable[%d] ->", s->nb_blocks);	for (i = 0; i < s->nb_blocks; i++) {		if ((i % 8) == 0)			printk("\n%04x: ", i);		printk("%04x ", s->VUtable[i]);	}	printk("\n-------------------------------------------"		"----------------------------------\n");	printk("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);	for (i = 0; i <= s->lastEUN; i++) {		if ((i % 8) == 0)			printk("\n%04x: ", i);		printk("%04x ", s->PUtable[i]);	}	printk("\n-------------------------------------------"		"----------------------------------\n");	printk("INFTL ->\n"		"  EraseSize       = %d\n"		"  h/s/c           = %d/%d/%d\n"		"  numvunits       = %d\n"		"  firstEUN        = %d\n"		"  lastEUN         = %d\n"		"  numfreeEUNs     = %d\n"		"  LastFreeEUN     = %d\n"		"  nb_blocks       = %d\n"		"  nb_boot_blocks  = %d",		s->EraseSize, s->heads, s->sectors, s->cylinders,		s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs,		s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks);	printk("\n-------------------------------------------"		"----------------------------------\n");}void INFTL_dumpVUchains(struct INFTLrecord *s){	int logical, block, i;	printk("-------------------------------------------"		"----------------------------------\n");	printk("INFTL Virtual Unit Chains:\n");	for (logical = 0; logical < s->nb_blocks; logical++) {		block = s->VUtable[logical];		if (block > s->nb_blocks)			continue;		printk("  LOGICAL %d --> %d ", logical, block);		for (i = 0; i < s->nb_blocks; i++) {			if (s->PUtable[block] == BLOCK_NIL)				break;			block = s->PUtable[block];			printk("%d ", block);		}		printk("\n");	}	printk("-------------------------------------------"		"----------------------------------\n");}int INFTL_mount(struct INFTLrecord *s){	struct mtd_info *mtd = s->mbd.mtd;	unsigned int block, first_block, prev_block, last_block;	unsigned int first_logical_block, logical_block, erase_mark;	int chain_length, do_format_chain;	struct inftl_unithead1 h0;	struct inftl_unittail h1;	size_t retlen;	int i;	u8 *ANACtable, ANAC;	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=%p)\n", s);	/* Search for INFTL MediaHeader and Spare INFTL Media Header */	if (find_boot_record(s) < 0) {		printk(KERN_WARNING "INFTL: could not find valid boot record?\n");		return -ENXIO;	}	/* Init the logical to physical table */	for (i = 0; i < s->nb_blocks; i++)		s->VUtable[i] = BLOCK_NIL;	logical_block = block = BLOCK_NIL;	/* Temporary buffer to store ANAC numbers. */	ANACtable = kcalloc(s->nb_blocks, sizeof(u8), GFP_KERNEL);	if (!ANACtable) {		printk(KERN_WARNING "INFTL: allocation of ANACtable "				"failed (%zd bytes)\n",				s->nb_blocks * sizeof(u8));		return -ENOMEM;	}	/*	 * First pass is to explore each physical unit, and construct the	 * virtual chains that exist (newest physical unit goes into VUtable).	 * Any block that is in any way invalid will be left in the	 * NOTEXPLORED state. Then at the end we will try to format it and	 * mark it as free.	 */	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 1, explore each unit\n");	for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) {		if (s->PUtable[first_block] != BLOCK_NOTEXPLORED)			continue;		do_format_chain = 0;		first_logical_block = BLOCK_NIL;		last_block = BLOCK_NIL;		block = first_block;		for (chain_length = 0; ; chain_length++) {			if ((chain_length == 0) &&			    (s->PUtable[block] != BLOCK_NOTEXPLORED)) {				/* Nothing to do here, onto next block */				break;			}			if (inftl_read_oob(mtd, block * s->EraseSize + 8,					   8, &retlen, (char *)&h0) < 0 ||			    inftl_read_oob(mtd, block * s->EraseSize +					   2 * SECTORSIZE + 8, 8, &retlen,					   (char *)&h1) < 0) {				/* Should never happen? */				do_format_chain++;				break;			}			logical_block = le16_to_cpu(h0.virtualUnitNo);			prev_block = le16_to_cpu(h0.prevUnitNo);			erase_mark = le16_to_cpu((h1.EraseMark | h1.EraseMark1));			ANACtable[block] = h0.ANAC;			/* Previous block is relative to start of Partition */			if (prev_block < s->nb_blocks)				prev_block += s->firstEUN;			/* Already explored partial chain? */			if (s->PUtable[block] != BLOCK_NOTEXPLORED) {				/* Check if chain for this logical */				if (logical_block == first_logical_block) {					if (last_block != BLOCK_NIL)						s->PUtable[last_block] = block;				}				break;			}			/* Check for invalid block */			if (erase_mark != ERASE_MARK) {				printk(KERN_WARNING "INFTL: corrupt block %d "					"in chain %d, chain length %d, erase "					"mark 0x%x?\n", block, first_block,					chain_length, erase_mark);				/*				 * Assume end of chain, probably incomplete				 * fold/erase...				 */				if (chain_length == 0)					do_format_chain++;				break;			}			/* Check for it being free already then... */			if ((logical_block == BLOCK_FREE) ||			    (logical_block == BLOCK_NIL)) {				s->PUtable[block] = BLOCK_FREE;				break;			}			/* Sanity checks on block numbers */			if ((logical_block >= s->nb_blocks) ||			    ((prev_block >= s->nb_blocks) &&			     (prev_block != BLOCK_NIL))) {				if (chain_length > 0) {					printk(KERN_WARNING "INFTL: corrupt "						"block %d in chain %d?\n",						block, first_block);					do_format_chain++;				}				break;			}			if (first_logical_block == BLOCK_NIL) {				first_logical_block = logical_block;			} else {				if (first_logical_block != logical_block) {					/* Normal for folded chain... */					break;				}			}			/*			 * Current block is valid, so if we followed a virtual			 * chain to get here then we can set the previous			 * block pointer in our PUtable now. Then move onto			 * the previous block in the chain.			 */			s->PUtable[block] = BLOCK_NIL;			if (last_block != BLOCK_NIL)				s->PUtable[last_block] = block;			last_block = block;			block = prev_block;			/* Check for end of chain */			if (block == BLOCK_NIL)				break;			/* Validate next block before following it... */			if (block > s->lastEUN) {				printk(KERN_WARNING "INFTL: invalid previous "					"block %d in chain %d?\n", block,					first_block);				do_format_chain++;				break;			}		}		if (do_format_chain) {			format_chain(s, first_block);			continue;		}		/*		 * Looks like a valid chain then. It may not really be the		 * newest block in the chain, but it is the newest we have		 * found so far. We might update it in later iterations of		 * this loop if we find something newer.		 */		s->VUtable[first_logical_block] = first_block;		logical_block = BLOCK_NIL;	}#ifdef CONFIG_MTD_DEBUG_VERBOSE	if (CONFIG_MTD_DEBUG_VERBOSE >= 2)		INFTL_dumptables(s);#endif	/*	 * Second pass, check for infinite loops in chains. These are	 * possible because we don't update the previous pointers when	 * we fold chains. No big deal, just fix them up in PUtable.	 */	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 2, validate virtual chains\n");	for (logical_block = 0; logical_block < s->numvunits; logical_block++) {		block = s->VUtable[logical_block];		last_block = BLOCK_NIL;		/* Check for free/reserved/nil */		if (block >= BLOCK_RESERVED)			continue;		ANAC = ANACtable[block];		for (i = 0; i < s->numvunits; i++) {			if (s->PUtable[block] == BLOCK_NIL)				break;			if (s->PUtable[block] > s->lastEUN) {				printk(KERN_WARNING "INFTL: invalid prev %d, "					"in virtual chain %d\n",					s->PUtable[block], logical_block);				s->PUtable[block] = BLOCK_NIL;			}			if (ANACtable[block] != ANAC) {				/*				 * Chain must point back to itself. This is ok,				 * but we will need adjust the tables with this				 * newest block and oldest block.				 */				s->VUtable[logical_block] = block;				s->PUtable[last_block] = BLOCK_NIL;				break;			}			ANAC--;			last_block = block;			block = s->PUtable[block];		}		if (i >= s->nb_blocks) {			/*			 * Uhoo, infinite chain with valid ANACS!			 * Format whole chain...			 */			format_chain(s, first_block);		}	}#ifdef CONFIG_MTD_DEBUG_VERBOSE	if (CONFIG_MTD_DEBUG_VERBOSE >= 2)		INFTL_dumptables(s);	if (CONFIG_MTD_DEBUG_VERBOSE >= 2)		INFTL_dumpVUchains(s);#endif	/*	 * Third pass, format unreferenced blocks and init free block count.	 */	s->numfreeEUNs = 0;	s->LastFreeEUN = BLOCK_NIL;	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 3, format unused blocks\n");	for (block = s->firstEUN; block <= s->lastEUN; block++) {		if (s->PUtable[block] == BLOCK_NOTEXPLORED) {			printk("INFTL: unreferenced block %d, formatting it\n",				block);			if (INFTL_formatblock(s, block) < 0)				s->PUtable[block] = BLOCK_RESERVED;			else				s->PUtable[block] = BLOCK_FREE;		}		if (s->PUtable[block] == BLOCK_FREE) {			s->numfreeEUNs++;			if (s->LastFreeEUN == BLOCK_NIL)				s->LastFreeEUN = block;		}	}	kfree(ANACtable);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -