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

📄 nftllite.c.bak

📁 VxWOrks中bspMCF5200下的Nand Flash TFFS的驱动程序。
💻 BAK
📖 第 1 页 / 共 5 页
字号:
/*----------------------------------------------------------------------*/
/*		         g e t F o l d M a r k				*/
/*									*/
/* Get the fold mark a unit.						*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Physical unit number				*/
/*                                                                      */
/* Returns:                                                             */
/*	Return the OR of the two words in the fold mark area (the words	*/
/*	should be identical)						*/
/*----------------------------------------------------------------------*/

static unsigned short getFoldMark(Anand vol, UnitNo unitNo)
{
	unsigned short foldMark[2];

	vol.flash.read(&vol.flash,
	unitBaseAddress(&vol,unitNo) + FOLD_MARK_OFFSET,
	&foldMark, sizeof foldMark,
	EXTRA);

	return foldMark[0] | foldMark[1];
}


/*----------------------------------------------------------------------*/
/*		         g e t U n i t T a i l e r			*/
/*									*/
/* Get the erase record of a unit.					*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Physical unit number				*/
/*	eraseMark	: Receives the erase mark of the unit		*/
/*	eraseCount	: Receives the erase count of the unit		*/
/*                                                                      */
/*----------------------------------------------------------------------*/

static void getUnitTailer(Anand vol,UnitNo unitNo,unsigned short *eraseMark,unsigned long *eraseCount)
{
	UnitTailer unitTailer;

	vol.flash.read(&vol.flash,
	unitBaseAddress(&vol,unitNo) + UNIT_TAILER_OFFSET,
	&unitTailer,
	sizeof(UnitTailer),
	EXTRA);

	/* Mask out any 1 -> 0 bit faults by or'ing with spare data */
	*eraseMark = LE2(unitTailer.eraseMark) | LE2(unitTailer.eraseMark1);
	*eraseCount = LE4(unitTailer.eraseCount);
}


/*----------------------------------------------------------------------*/
/*		         s e t U n i t T a i l e r			*/
/*									*/
/* Set the erase record of a unit.					*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Physical unit number				*/
/*	eraseMark	: Erase mark to set				*/
/*	eraseCount	: Erase count to set				*/
/*                                                                      */
/*----------------------------------------------------------------------*/

static FLStatus setUnitTailer(Anand vol,
UnitNo unitNo,
unsigned short eraseMark,
unsigned long eraseCount)
{
	UnitTailer unitTailer;

	toLE2(unitTailer.eraseMark,eraseMark);
	toLE2(unitTailer.eraseMark1,eraseMark);
	toLE4(unitTailer.eraseCount,eraseCount);

	return vol.flash.write(&vol.flash,
	unitBaseAddress(&vol,unitNo) + UNIT_TAILER_OFFSET,
	&unitTailer,
	sizeof(UnitTailer),
	EXTRA);
}


/*----------------------------------------------------------------------*/
/*      	             i n i t N F T L				*/
/*									*/
/* Initializes essential volume data as a preparation for mount or	*/
/* format.								*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus initNFTL(Anand vol)
{
	long int size = 1;

	if (!(vol.flash.flags & NFTL_ENABLED)) {
		#ifdef DEBUG_PRINT
		DEBUG_PRINT("Debug: media is not fit for NFTL format.\n");
		#endif
		return flUnknownMedia;
	}

	vol.physicalUnits = NULL;
	vol.virtualUnits = NULL;

	for (vol.erasableBlockSizeBits = 0; size < vol.flash.erasableBlockSize;
	vol.erasableBlockSizeBits++, size <<= 1);
	vol.unitSizeBits = vol.erasableBlockSizeBits;

	vol.noOfUnits = (unsigned short)((vol.flash.noOfChips * vol.flash.chipSize) >> vol.unitSizeBits);

	/* Adjust unit size so header unit fits in one unit */
	while (vol.noOfUnits * sizeof(PhysUnit) + SECTOR_SIZE > (1UL << vol.unitSizeBits)) {
		vol.unitSizeBits++;
		vol.noOfUnits >>= 1;
	}

	vol.badFormat = TRUE;	/* until mount completes*/
	vol.mappedSectorNo = UNASSIGNED_SECTOR;
	/*get pointer to buffer (we assume SINGLE_BUFFER is not defined) */
	vol.buffer = flBufferOf(flSocketNoOf(vol.flash.socket));
	vol.countsValid = 0;		/* No units have a valid count yet */

	return flOK;
}


/*----------------------------------------------------------------------*/
/*      	            i n i t T a b l e s				*/
/*									*/
/* Allocates and initializes the dynamic volume table, including the	*/
/* unit tables and secondary virtual map.				*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus initTables(Anand vol)
{
	/* Allocate the conversion tables */
	#ifdef MALLOC_TFFS
	vol.physicalUnits = (PhysUnit *) MALLOC_TFFS(vol.noOfUnits * sizeof(PhysUnit));
	vol.virtualUnits = (UnitNo *) MALLOC_TFFS(vol.noOfVirtualUnits * sizeof(UnitNo));
	if (vol.physicalUnits == NULL || vol.virtualUnits == NULL) {
		#ifdef DEBUG_PRINT
		DEBUG_PRINT("Debug: failed allocating conversion tables for NFTL.\n");
		#endif
		return flNotEnoughMemory;
	}
	#else
	char *heapPtr;

	heapPtr = vol.heap;
	vol.physicalUnits = (PhysUnit *) heapPtr;
	heapPtr += vol.noOfUnits * sizeof(PhysUnit);
	vol.virtualUnits = (UnitNo *) heapPtr;
	heapPtr += vol.noOfVirtualUnits * sizeof(UnitNo);
	if (heapPtr > vol.heap + sizeof vol.heap) {
		#ifdef DEBUG_PRINT
		DEBUG_PRINT("Debug: not enough memory for NFTL conversion tables.\n");
		#endif
		return flNotEnoughMemory;
	}
	#endif

	return flOK;
}

/*----------------------------------------------------------------------*/
/*      	            m a r k U n i t B a d			*/
/*									*/
/* Mark a unit as bad in the conversion table and the bad units table.	*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Physical number of bad unit			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus markUnitBad(Anand vol, UnitNo unitNo)
{
	unsigned short eraseMark;
	unsigned long eraseCount;

	vol.physicalUnits[unitNo] = UNIT_BAD_MARKED;

	getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount);

	return setUnitTailer(&vol,unitNo,0,eraseCount);
}


/*----------------------------------------------------------------------*/
/*		          f o r m a t U n i t				*/
/*									*/
/* Format one unit. Erase the unit, and mark the physical units table.  */
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Unit to format				*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus formatUnit(Anand vol, UnitNo unitNo)
{
	unsigned short eraseMark;
	unsigned long eraseCount;
	FLStatus status;

	if (!(vol.physicalUnits[unitNo] & UNIT_AVAILABLE))
	{
		return flWriteFault;
	}
	
	if (vol.physicalUnits[unitNo] == UNIT_FREE)
	{
		vol.freeUnits--;
	}
	vol.physicalUnits[unitNo] &= ~UNIT_AVAILABLE;

	getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount);

	status = vol.flash.erase(&vol.flash,
	unitNo << (vol.unitSizeBits - vol.erasableBlockSizeBits),
	1 << (vol.unitSizeBits - vol.erasableBlockSizeBits));
	if (status != flOK) {
		markUnitBad(&vol,unitNo);	/* make sure unit format is not valid */
		return status;
	}

	eraseCount++;
	if (eraseCount == 0)		/* was hex FF's */
	{
		eraseCount++;
	}
	
	checkStatus(setUnitTailer(&vol,unitNo,ERASE_MARK,eraseCount));

	vol.physicalUnits[unitNo] = UNIT_FREE;
	vol.freeUnits++;

	return flOK;
}


/*----------------------------------------------------------------------*/
/*      	        w r i t e A n d C h e c k 			*/
/*									*/
/* Write one sector. 							*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	address		: Physical address of the sector to write to	*/
/*	fromAddress	: Buffer of data to write			*/
/*	flags		: Write flags (ECC, overwrite etc.)		*/
/*									*/
/* Returns:                                                             */
/* 	Status 		: 0 on success, failed otherwise.		*/
/*----------------------------------------------------------------------*/

static FLStatus writeAndCheck(Anand vol,
CardAddress address,
void FAR1 *fromAddress,
unsigned flags)
{
	FLStatus status = vol.flash.write(&vol.flash,address,fromAddress,SECTOR_SIZE,flags);
	if (status == flWriteFault) {  /* write failed, ignore this sector */
		unsigned char sectorFlags[2];

		//2007-7-16 15:14
		unsigned int SectorNoInPage = ((address)>>SECTOR_SIZE_BITS) % 4;
		unsigned int PageBase = address&(~((SECTOR_SIZE<<3) - 1));
		//2007-7-16 15:14

		sectorFlags[0] = sectorFlags[1] = SECTOR_IGNORE;
		vol.flash.write(&vol.flash,
		PageBase + SECTOR_DATA_OFFSET + SectorNoInPage*16,//2007-7-16 15:25 + SectorNoInPage*16
		sectorFlags,sizeof sectorFlags,EXTRA);
	}

	return status;
}


/*----------------------------------------------------------------------*/
/*      	        c o p y S e c t o r	 			*/
/*									*/
/* Copy one sector to another.						*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	sourceSectorAddress	: Physical address of Sector to copy 	*/
/*				  from.					*/
/*	targetSectorAddress	: Physical address of sector to copy	*/
/*				  to.					*/
/*                                                                      */
/* Returns:                                                             */
/* 	FLStatus       		: 0 on success, failed otherwise.	*/
/*----------------------------------------------------------------------*/

static FLStatus copySector(Anand vol,
CardAddress sourceSectorAddress,
CardAddress targetSectorAddress)
{
	unsigned flags = EDC;

	vol.flash.socket->remapped = TRUE;
	if (vol.flash.read(&vol.flash,
	sourceSectorAddress,
	nftlBuffer,
	SECTOR_SIZE,
	EDC) == flDataError) {
		/* If there is an uncorrectable ECC error, copy the data as is */
		unsigned short sectorDataInfo[4];

		vol.flash.read(&vol.flash,
		sourceSectorAddress + SECTOR_ECC_OFFSET,//2007-7-30 9:38 +SECTOR_ECC_OFFSET
		sectorDataInfo,
		sizeof sectorDataInfo,
		EXTRA);
		checkStatus(vol.flash.write(&vol.flash,
		sourceSectorAddress + SECTOR_ECC_OFFSET,//2007-7-30 9:38 +SECTOR_ECC_OFFSET
		sectorDataInfo,
		sizeof sectorDataInfo,
		EXTRA));
		flags &= ~EDC;
	}

	return writeAndCheck(&vol,targetSectorAddress,nftlBuffer,flags);
}


/*----------------------------------------------------------------------*/
/*      	        l a s t I n C h a i n	 			*/
/*									*/
/* Find last unit in chain.						*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/* 	unitNo		: Start the search from this unit		*/
/*                                                                      */
/* Returns:                                                             */
/* 	Physical unit number of the last unit in chain.			*/
/*----------------------------------------------------------------------*/

static UnitNo lastInChain(Anand vol, UnitNo unitNo)
{
	UnitNo firstVirtualUnitNo, firstReplacementUnitNo;
	UnitNo lastUnit = unitNo, nextUnitNo;;

	getUnitData(&vol,unitNo,&firstVirtualUnitNo,&firstReplacementUnitNo);
	nextUnitNo = firstReplacementUnitNo;

	while (nextUnitNo < vol.noOfUnits) {  /* Validate replacement unit no. */
		UnitNo nextVirtualUnitNo, nextReplacementUnitNo;

		getUnitData(&vol,nextUnitNo,&nextVirtualUnitNo,&nextReplacementUnitNo);
		if (nextVirtualUnitNo != (firstVirtualUnitNo | REPLACING_UNIT))
		{
		   	break;/* Virtual unit no. not validated */
		}
		lastUnit = nextUnitNo;
		nextUnitNo = nextReplacementUnitNo;
	}

	return lastUnit;
}


/*----------------------------------------------------------------------*/
/*		           a s s i g n U n i t				*/
/*									*/
/* Assigns a virtual unit no. to a unit					*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Physical unit number				*/
/*	virtualUnitNo	: Virtual unit number to assign			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus assignUnit(Anand vol, UnitNo unitNo, UnitNo virtualUnitNo)
{
	UnitNo newVirtualUnitNo, newReplacementUnitNo;
	UnitNo oldVirtualUnitNo, oldReplacementUnitNo;
	FLStatus status;
	UnitNo firstUnitNo = vol.virtualUnits[virtualUnitNo];

	/* Assign the new unit */
	newVirtualUnitNo = virtualUnitNo;
	if (firstUnitNo != NO_UNIT)
	{

⌨️ 快捷键说明

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