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

📄 nand_bbt.c

📁 老版本的mtd-snap
💻 C
📖 第 1 页 / 共 3 页
字号:
		td->version[i] = 1;		if (md)			md->version[i] = 1;	writecheck:			/* read back first ? */		if (rd)			read_abs_bbt (mtd, buf, rd, chipsel);		/* If they weren't versioned, read both. */		if (rd2)			read_abs_bbt (mtd, buf, rd2, chipsel);		/* Write the bad block table to the device ? */		if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {			res = write_bbt (mtd, buf, td, md, chipsel);			if (res < 0)				return res;		}				/* Write the mirror bad block table to the device ? */		if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {			res = write_bbt (mtd, buf, md, td, chipsel);			if (res < 0)				return res;		}	}	return 0;	}/** * mark_bbt_regions - [GENERIC] mark the bad block table regions  * @mtd:	MTD device structure * @td:		bad block table descriptor * * The bad block table regions are marked as "bad" to prevent * accidental erasures / writes. The regions are identified by * the mark 0x02.*/static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td){	struct nand_chip *this = mtd->priv;	int i, j, chips, block, nrblocks, update;	uint8_t oldval, newval;	/* Do we have a bbt per chip ? */	if (td->options & NAND_BBT_PERCHIP) {		chips = this->numchips;		nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);	} else {		chips = 1;		nrblocks = (int)(mtd->size >> this->bbt_erase_shift);	}			for (i = 0; i < chips; i++) {		if ((td->options & NAND_BBT_ABSPAGE) ||		    !(td->options & NAND_BBT_WRITE)) {		    	if (td->pages[i] == -1) continue;			block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);			block <<= 1;					oldval = this->bbt[(block >> 3)];			newval = oldval | (0x2 << (block & 0x06));			this->bbt[(block >> 3)] = newval;			if ((oldval != newval) && td->reserved_block_code)				nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1));			continue;		}		update = 0;		if (td->options & NAND_BBT_LASTBLOCK)			block = ((i + 1) * nrblocks) - td->maxblocks;		else				block = i * nrblocks;		block <<= 1;			for (j = 0; j < td->maxblocks; j++) {			oldval = this->bbt[(block >> 3)];			newval = oldval | (0x2 << (block & 0x06));			this->bbt[(block >> 3)] = newval;			if (oldval != newval) update = 1;			block += 2;		}			/* If we want reserved blocks to be recorded to flash, and some		   new ones have been marked, then we need to update the stored		   bbts.  This should only happen once. */		if (update && td->reserved_block_code)			nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1));	}}/** * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) * @mtd:	MTD device structure * @bd:		descriptor for the good/bad block search pattern * * The function checks, if a bad block table(s) is/are already  * available. If not it scans the device for manufacturer * marked good / bad blocks and writes the bad block table(s) to * the selected place. * * The bad block table memory is allocated here. It must be freed * by calling the nand_free_bbt function. **/int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd){	struct nand_chip *this = mtd->priv;	int len, res = 0;	uint8_t *buf;	struct nand_bbt_descr *td = this->bbt_td;	struct nand_bbt_descr *md = this->bbt_md;	len = mtd->size >> (this->bbt_erase_shift + 2);	/* Allocate memory (2bit per block) */	this->bbt = kmalloc (len, GFP_KERNEL);	if (!this->bbt) {		printk (KERN_ERR "nand_scan_bbt: Out of memory\n");		return -ENOMEM;	}	/* Clear the memory bad block table */	memset (this->bbt, 0x00, len);	/* If no primary table decriptor is given, scan the device	 * to build a memory based bad block table	 */	if (!td) {		if ((res = nand_memory_bbt(mtd, bd))) {			printk (KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");			kfree (this->bbt);			this->bbt = NULL;		}		return res;	}	/* Allocate a temporary buffer for one eraseblock incl. oob */	len = (1 << this->bbt_erase_shift);	len += (len >> this->page_shift) * mtd->oobsize;	buf = kmalloc (len, GFP_KERNEL);	if (!buf) {		printk (KERN_ERR "nand_bbt: Out of memory\n");		kfree (this->bbt);		this->bbt = NULL;		return -ENOMEM;	}		/* Is the bbt at a given page ? */	if (td->options & NAND_BBT_ABSPAGE) {		res = read_abs_bbts (mtd, buf, td, md);	} else {			/* Search the bad block table using a pattern in oob */		res = search_read_bbts (mtd, buf, td, md);	}		if (res) 		res = check_create (mtd, buf, bd);		/* Prevent the bbt regions from erasing / writing */	mark_bbt_region (mtd, td);	if (md)		mark_bbt_region (mtd, md);		kfree (buf);	return res;}/** * nand_update_bbt - [NAND Interface] update bad block table(s)  * @mtd:	MTD device structure * @offs:	the offset of the newly marked block * * The function updates the bad block table(s)*/int nand_update_bbt (struct mtd_info *mtd, loff_t offs){	struct nand_chip *this = mtd->priv;	int len, res = 0, writeops = 0;	int chip, chipsel;	uint8_t *buf;	struct nand_bbt_descr *td = this->bbt_td;	struct nand_bbt_descr *md = this->bbt_md;	if (!this->bbt || !td)		return -EINVAL;	len = mtd->size >> (this->bbt_erase_shift + 2);	/* Allocate a temporary buffer for one eraseblock incl. oob */	len = (1 << this->bbt_erase_shift);	len += (len >> this->page_shift) * mtd->oobsize;	buf = kmalloc (len, GFP_KERNEL);	if (!buf) {		printk (KERN_ERR "nand_update_bbt: Out of memory\n");		return -ENOMEM;	}		writeops = md != NULL ? 0x03 : 0x01;	/* Do we have a bbt per chip ? */	if (td->options & NAND_BBT_PERCHIP) {		chip = (int) (offs >> this->chip_shift);		chipsel = chip;	} else {		chip = 0;		chipsel = -1;	}	td->version[chip]++;	if (md)		md->version[chip]++;		/* Write the bad block table to the device ? */	if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {		res = write_bbt (mtd, buf, td, md, chipsel);		if (res < 0)			goto out;	}	/* Write the mirror bad block table to the device ? */	if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {		res = write_bbt (mtd, buf, md, td, chipsel);	}out:		kfree (buf);	return res;}/* Define some generic bad / good block scan pattern which are used  * while scanning a device for factory marked good / bad blocks. */static uint8_t scan_ff_pattern[] = { 0xff, 0xff };static struct nand_bbt_descr smallpage_memorybased = {	.options = NAND_BBT_SCAN2NDPAGE,	.offs = 5,	.len = 1,	.pattern = scan_ff_pattern};static struct nand_bbt_descr largepage_memorybased = {	.options = 0,	.offs = 0,	.len = 2,	.pattern = scan_ff_pattern};static struct nand_bbt_descr smallpage_flashbased = {	.options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,	.offs = 5,	.len = 1,	.pattern = scan_ff_pattern};static struct nand_bbt_descr largepage_flashbased = {	.options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,	.offs = 0,	.len = 2,	.pattern = scan_ff_pattern};static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };static struct nand_bbt_descr agand_flashbased = {	.options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,	.offs = 0x20,	.len = 6,	.pattern = scan_agand_pattern};/* Generic flash bbt decriptors*/static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };static struct nand_bbt_descr bbt_main_descr = {	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,	.offs =	8,	.len = 4,	.veroffs = 12,	.maxblocks = 4,	.pattern = bbt_pattern};static struct nand_bbt_descr bbt_mirror_descr = {	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,	.offs =	8,	.len = 4,	.veroffs = 12,	.maxblocks = 4,	.pattern = mirror_pattern};/** * nand_default_bbt - [NAND Interface] Select a default bad block table for the device  * @mtd:	MTD device structure * * This function selects the default bad block table * support for the device and calls the nand_scan_bbt function **/int nand_default_bbt (struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;		/* Default for AG-AND. We must use a flash based 	 * bad block table as the devices have factory marked	 * _good_ blocks. Erasing those blocks leads to loss	 * of the good / bad information, so we _must_ store	 * this information in a good / bad table during 	 * startup	*/	if (this->options & NAND_IS_AND) {		/* Use the default pattern descriptors */		if (!this->bbt_td) {				this->bbt_td = &bbt_main_descr;			this->bbt_md = &bbt_mirror_descr;		}			this->options |= NAND_USE_FLASH_BBT;		return nand_scan_bbt (mtd, &agand_flashbased);	}			/* Is a flash based bad block table requested ? */	if (this->options & NAND_USE_FLASH_BBT) {		/* Use the default pattern descriptors */			if (!this->bbt_td) {				this->bbt_td = &bbt_main_descr;			this->bbt_md = &bbt_mirror_descr;		}		if (!this->badblock_pattern) {			this->badblock_pattern = (mtd->oobblock > 512) ?				&largepage_flashbased : &smallpage_flashbased;		}	} else {		this->bbt_td = NULL;		this->bbt_md = NULL;		if (!this->badblock_pattern) {			this->badblock_pattern = (mtd->oobblock > 512) ?				&largepage_memorybased : &smallpage_memorybased;		}	}	return nand_scan_bbt (mtd, this->badblock_pattern);}/** * nand_isbad_bbt - [NAND Interface] Check if a block is bad  * @mtd:	MTD device structure * @offs:	offset in the device * @allowbbt:	allow access to bad block table region **/int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt){	struct nand_chip *this = mtd->priv;	int block;	uint8_t	res;		/* Get block number * 2 */	block = (int) (offs >> (this->bbt_erase_shift - 1));	res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;	DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", 		(unsigned int)offs, block >> 1, res);	switch ((int)res) {	case 0x00:	return 0;	case 0x01:	return 1;	case 0x02:	return allowbbt ? 0 : 1;	}	return 1;}EXPORT_SYMBOL (nand_scan_bbt);EXPORT_SYMBOL (nand_default_bbt);

⌨️ 快捷键说明

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