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

📄 nftllite.c.bak

📁 VxWOrks中bspMCF5200下的Nand Flash TFFS的驱动程序。
💻 BAK
📖 第 1 页 / 共 5 页
字号:
		newVirtualUnitNo |= REPLACING_UNIT;
	}
	newReplacementUnitNo = NO_UNIT;
	vol.physicalUnits[unitNo] = UNIT_AVAILABLE;
	vol.freeUnits--;
	status = setUnitData(&vol,unitNo,newVirtualUnitNo,newReplacementUnitNo);
	if (status != flOK) {
		markUnitBad(&vol,unitNo);
		return status;
	}

	/* Add unit to chain */
	if (firstUnitNo != NO_UNIT) {
		UnitNo oldUnitNo;

		/* If unit is frozen, don't attempt to chain (folding not-in-place) */
		if (!(vol.physicalUnits[firstUnitNo] & UNIT_AVAILABLE))
		{
			return flOK;
		}
		oldUnitNo = lastInChain(&vol,firstUnitNo);
		getUnitData(&vol,oldUnitNo,&oldVirtualUnitNo,&oldReplacementUnitNo);
		if (oldReplacementUnitNo != NO_UNIT)
		{
		   status = flWriteFault;	/* can't write here, so assume failure */
		}
		else {
			oldReplacementUnitNo = unitNo;
			vol.physicalUnits[oldUnitNo] |= UNIT_REPLACED;
			status = setUnitData(&vol,oldUnitNo,oldVirtualUnitNo,oldReplacementUnitNo);
		}
		if (status != flOK) {
			formatUnit(&vol,unitNo); /* Get rid of the allocated unit quickly */
			vol.physicalUnits[firstUnitNo] &= ~UNIT_AVAILABLE; /* freeze the chain */

			return status;
		}
		if (vol.countsValid > virtualUnitNo && firstUnitNo != oldUnitNo)
		{
			if ((vol.physicalUnits[firstUnitNo] & UNIT_COUNT) +
			(vol.physicalUnits[oldUnitNo] & UNIT_COUNT) <= UNIT_COUNT)
			{
				vol.physicalUnits[firstUnitNo] += (vol.physicalUnits[oldUnitNo] & UNIT_COUNT);
			}
			else
			{
				return flGeneralFailure;
			}
		}
	}
	else
	{
	  vol.virtualUnits[virtualUnitNo] = unitNo;
	}
	return flOK;
}


/*----------------------------------------------------------------------*/
/*		           f o r m a t C h a i n			*/
/*									*/
/* Format all the units in a chain. Start from the last one and go	*/
/* backwards until unitNo is reached.					*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Format the chain from this unit onwards	*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus formatChain(Anand vol, UnitNo unitNo)
{
	/* Erase the chain from end to start */
	vol.physicalUnits[unitNo] |= UNIT_AVAILABLE;  /* Reenable erase of this unit */
	for (;;) {
		/* Find last unit in chain */
		UnitNo unitToErase = lastInChain(&vol,unitNo);

		formatUnit(&vol,unitToErase);

		if (unitToErase == unitNo)
		{
			break;    /* Erased everything*/ 
		}
	}

	return flOK;
}


static FLStatus allocateUnit(Anand vol, UnitNo *);


/*----------------------------------------------------------------------*/
/*      	             f o l d U n i t				*/
/*									*/
/* Copy all the sectors that hold valid data in the chain to the last   */
/* unit of the chain and erase the chain. 				*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	virtualUnitNo	: Virtual unit number of the first unit in 	*/
/*			  chain.					*/
/*									*/
/* Returns:								*/
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus foldUnit(Anand vol, UnitNo virtualUnitNo)
{
	UnitNo unitNo = vol.virtualUnits[virtualUnitNo];
	UnitNo targetUnitNo;
	unsigned long foldMark;
	SectorNo virtualSectorNo;
	CardAddress targetSectorAddress;
	unsigned newSectorCount, i;

	vol.unitsFolded++;

	/* Find target unit */
	if (!(vol.physicalUnits[unitNo] & UNIT_AVAILABLE)) {
		/* If this unit is frozen, */
		/* allocate a new unit to fold into */
		checkStatus(allocateUnit(&vol,&targetUnitNo));
		checkStatus(assignUnit(&vol,targetUnitNo,virtualUnitNo));
	}
	else {		/* Default. Fold into end of chain */
		targetUnitNo = unitNo;

		for (;;) {
			UnitNo nextUnitNo = getNextUnit(&vol,targetUnitNo);
			if (nextUnitNo == NO_UNIT)
			{
			  break;
			}
			targetUnitNo = nextUnitNo;
		}
	}

	/* Mark unit as currently folded */
	foldMark = FOLDING_IN_PROGRESS * 0x10001l;

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

	vol.physicalUnits[unitNo] &= ~UNIT_AVAILABLE;	/* Freeze this unit chain */

	/* Copy all sectors to target unit */
	virtualSectorNo = (SectorNo)virtualUnitNo * vol.sectorsPerUnit;
	targetSectorAddress = unitBaseAddress(&vol,targetUnitNo);
	newSectorCount = 0;
	for (i = 0; i < vol.sectorsPerUnit; i++, virtualSectorNo++,
	targetSectorAddress += SECTOR_SIZE) {
		CardAddress sourceSectorAddress = virtual2Physical(&vol,virtualSectorNo);
		if (sourceSectorAddress != UNASSIGNED_ADDRESS) {
			newSectorCount++;
			if (sourceSectorAddress != targetSectorAddress) {
				checkStatus(copySector(&vol,sourceSectorAddress,targetSectorAddress));
				vol.parasiteWrites++;
			}
		}
	}

	if (newSectorCount > 0) {	/* Some sectors remaining*/
		/* Mark target unit as original */
		checkStatus(setUnitData(&vol,targetUnitNo,virtualUnitNo,NO_UNIT));
		/* Set target unit in virtual unit table */
		vol.virtualUnits[virtualUnitNo] = targetUnitNo;
		vol.physicalUnits[targetUnitNo] &= ~UNIT_COUNT;
		vol.physicalUnits[targetUnitNo] |= newSectorCount;
	}
	else {
		if (unitNo != targetUnitNo) {
			/*    If there is a chain to delete ... */
			/*    mark unit as completed folding, pending erase */
			unsigned long foldMark = FOLDING_COMPLETE * 0x10001l;

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

		vol.virtualUnits[virtualUnitNo] = NO_UNIT;
	}

	/* Erase source units */
	return formatChain(&vol,unitNo);
}


/*----------------------------------------------------------------------*/
/*		           s e t U n i t C o u n t			*/
/*									*/
/* Count the number of sectors in a unit that hold valid data.		*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Physical unit number				*/
/*                                                                      */
/*----------------------------------------------------------------------*/

static void setUnitCount(Anand vol, UnitNo unitNo)
{
	unsigned int i;
	SectorNo sectorNo;
	UnitNo physicalUnitNo = vol.virtualUnits[unitNo];
	if (physicalUnitNo == NO_UNIT)
	{
		return;
	}
	/* Get a count of the valid sector in this unit */
	vol.physicalUnits[physicalUnitNo] &= ~UNIT_COUNT;

	sectorNo = (SectorNo)unitNo * vol.sectorsPerUnit;
	for (i = 0; i < vol.sectorsPerUnit; i++, sectorNo++) {
		CardAddress sectorAddress = virtual2Physical(&vol,sectorNo);
		if (sectorAddress != UNASSIGNED_ADDRESS) {
			UnitNo currUnitNo = (UnitNo)(sectorAddress >> (vol.unitSizeBits+1));//2007-7-30 10:52 +1
			if (vol.physicalUnits[currUnitNo] & UNIT_REPLACED)
			{
				currUnitNo = physicalUnitNo;
			}
			vol.physicalUnits[currUnitNo]++;
		}
	}
}


/*----------------------------------------------------------------------*/
/*      	             f o l d B e s t C h a i n			*/
/*									*/
/* Find the best chain to fold and fold it.A good chain to fold is a	*/
/* long chain with a small number of sectors that hold valid data.	*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Receives the physical unit no. of the first 	*/
/*			  unit in the chain that was folded.		*/
/*									*/
/* Returns:								*/
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus foldBestChain(Anand vol, UnitNo *unitNo)
{
	unsigned leastCount = vol.sectorsPerUnit + 1;
	unsigned longestChain = 0;
	UnitNo virtualUnitNo = (UnitNo)0, u;

	for (u = 0; u < vol.noOfVirtualUnits; u++) {
		if (vol.countsValid <= u) {
			setUnitCount(&vol,u);
			vol.countsValid = u + 1;
		}

		if (vol.virtualUnits[u] != NO_UNIT) {
			unsigned char pU = vol.physicalUnits[vol.virtualUnits[u]];
			unsigned unitCount = pU & UNIT_COUNT;

			if (leastCount >= unitCount &&
			(pU & UNIT_AVAILABLE) &&
			((pU & UNIT_REPLACED) || unitCount == 0)) {
				if (unitCount > 0) {
					int chainLength = 0;

					/* Compare chain length */
					UnitNo nextUnitNo = getNextUnit(&vol,vol.virtualUnits[u]);
					while (nextUnitNo != NO_UNIT) {
						chainLength++;
						nextUnitNo = getNextUnit(&vol,nextUnitNo);
					}
					if (leastCount == unitCount && longestChain >= (unsigned)chainLength)
					{
						continue;
					}
					longestChain = chainLength;
				}
				leastCount = unitCount;
				virtualUnitNo = u;
				if (leastCount == 0)
				break;
			}
		}
	}

	if (leastCount > vol.sectorsPerUnit)
	return flNotEnoughMemory;	/* No space at all */
	else {
		*unitNo = vol.virtualUnits[virtualUnitNo];
		return foldUnit(&vol,virtualUnitNo);
	}
}


/*----------------------------------------------------------------------*/
/*      	             a l l o c a t e U n i t			*/
/*									*/
/* Find a free unit to allocate, erase it if necessary.			*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/* 	unitNo		: Receives the physical number of the allocated */
/*			  unit 						*/
/* Returns:								*/
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus allocateUnit(Anand vol, UnitNo *unitNo)
{
	UnitNo originalUnit = vol.roverUnit;

	if (vol.freeUnits) {
		do {
			unsigned char unitFlags;

			if (++vol.roverUnit >= vol.noOfUnits)
			vol.roverUnit = vol.bootUnits;

			unitFlags = vol.physicalUnits[vol.roverUnit];

			if (unitFlags == UNIT_FREE) { /* found a free unit, if not erased, */
				unsigned short eraseMark;
				unsigned long eraseCount;

				getUnitTailer(&vol,vol.roverUnit,&eraseMark,&eraseCount);
				if (eraseMark != ERASE_MARK) {
					if (formatUnit(&vol,vol.roverUnit) != flOK)
					continue;	/* this unit is bad, find another */
				}

				*unitNo = vol.roverUnit;
				return flOK;
			}
		} while (vol.roverUnit != originalUnit);
	}

	return foldBestChain(&vol,unitNo);  /* make free units by folding the best chain */
}

/*----------------------------------------------------------------------*/
/*      	             m a p S e c t o r				*/
/*									*/
/* Maps and returns location of a given sector no.			*/
/* NOTE: This function is used in place of a read-sector operation.	*/
/*									*/
/* A one-sector cache is maintained to save on map operations.		*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	sectorNo	: Sector no. to read				*/
/*	physAddress	: Optional pointer to receive sector address	*/
/*                                                                      */
/* Returns:                                                             */
/*	Pointer to physical sector location. NULL returned if sector	*/
/*	does not exist.							*/
/*----------------------------------------------------------------------*/

static const void FAR0 *mapSector(Anand vol, SectorNo sectorNo, CardAddress *physAddress)
{
	if (sectorNo != vol.mappedSectorNo || vol.flash.socket->remapped) {
		if (sectorNo >= vol.virtualSectors)
		{
			vol.mappedSector = NULL;
		}
		else {
			vol.mappedSectorAddress = virtual2Physical(&vol,sectorNo);

			if (vol.mappedSectorAddress == UNASSIGNED_SECTOR)
			{
				vol.mappedSector = NULL;	/* no such sector */
			}
			else
			{
				vol.mappedSector = vol.flash.map(&vol.flash,vol.mappedSectorAddress,SECTOR_SIZE);
			}
		}
		vol.mappedSectorNo = sectorNo;
		vol.flash.socket->remapped = FALSE;
	}

	if (physAddress)
	{
		*physAddress = vol.mappedSectorAddress;
	}
	return vol.mappedSector;
}


/* Mounting and formatting */

#define UNIT_ORPHAN	0x10

/*----------------------------------------------------------------------*/
/*		           m o u n t U n i t				*/
/*									*/
/* Mount one unit. Read the relevant data from the unit header and 	*/
/* update the conversion tables. 					*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Unit to mount					*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/

⌨️ 快捷键说明

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