📄 nftllite.c
字号:
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, ANANDUnitNo unitNo)
{
unsigned short eraseMark;
unsigned long eraseCount;
FLStatus status;
if (!isAvailable(unitNo))
return flWriteFault;
if (vol.physicalUnits[unitNo] == ANAND_UNIT_FREE)
vol.freeUnits--;
setUnavail(unitNo);
getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount);
#ifdef NFTL_CACHE
/* purge ANANDUnitHeader cache to force re-filling from flash */
if (vol.ucache != NULL) {
vol.ucache[unitNo].virtualUnitNo = 0xDEAD;
vol.ucache[unitNo].replacementUnitNo = 0xDEAD;
}
/*
* Purge the Sector Flags cache (set entries for all the unit's
* sectors to SECTOR_FREE).
*/
if (vol.scache != NULL) {
tffsset(&(vol.scache[unitNo << (vol.unitSizeBits - SECTOR_SIZE_BITS-2)]),
S_CACHE_4_SECTORS_FREE, 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS - 2));
}
#endif /* NFTL_CACHE */
status = vol.flash->erase(vol.flash,
(word)(unitNo << (vol.unitSizeBits - vol.erasableBlockSizeBits)),
(word)(1 << (vol.unitSizeBits - vol.erasableBlockSizeBits)));
if (status != flOK) {
markUnitBad(&vol,unitNo); /* make sure unit format is not valid */
return status;
}
vol.eraseSum++;
eraseCount++;
if (eraseCount == 0) /* was hex FF's */
eraseCount++;
checkStatus(setUnitTailer(&vol,unitNo,ERASE_MARK,eraseCount));
vol.physicalUnits[unitNo] = ANAND_UNIT_FREE;
vol.freeUnits++;
return flOK;
}
#ifndef FL_READ_ONLY
/*----------------------------------------------------------------------*/
/* 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;
#ifdef VERIFY_ERASED_SECTOR
register int noOfDword;
int i;
#endif /* VERIFY_ERASED_SECTOR */
/* Toggle verify write flag */
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
switch (flVerifyWrite[vol.socketNo][vol.flash->socket->curPartition])
{
case FL_OFF:
if (vol.verifiedSectorNo>vol.curSectorWrite)
break;
case FL_ON:
#ifdef VERIFY_WRITE
vol.flash->socket->verifyWrite = FL_ON;
#endif /* VERIFY_WRITE */
#ifdef VERIFY_ERASED_SECTOR
/* Make sure all of the sectors are really free */
checkStatus(vol.flash->read(vol.flash,address,vol.verifyBuffer,SECTOR_SIZE,0));
noOfDword = SECTOR_SIZE/sizeof(dword);
for(i = 0;i<noOfDword;i++) /* Loop over sector data */
{
if(vol.verifyBuffer[i]!=0xffffffffL)
{
markAsIgnored(&vol,address);
DEBUG_PRINT(("writeAndCheck : The sector was not erased and is ignored\r\n"));
return flWriteFault;
}
}
#endif /* VERIFY_ERASED_SECTOR */
default:
break;
}
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
/* Write sector */
status = vol.flash->write(vol.flash,address,fromAddress,SECTOR_SIZE,(word)flags);
if (status == flWriteFault) { /* write failed, ignore this sector */
markAsIgnored(&vol,address);
}
#ifdef NFTL_CACHE
else {
setSectorFlagsCache(&vol, address, SECTOR_USED);
}
#endif
#ifdef VERIFY_WRITE
/* Restore verify write mode */
if(flVerifyWrite[flSocketNoOf(vol.flash->socket)][vol.flash->socket->curPartition] != FL_ON)
vol.flash->socket->verifyWrite = FL_OFF;
#endif /* VERIFY_WRITE */
return status;
}
#endif /* FL_READ_ONLY */
/*----------------------------------------------------------------------*/
/* 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 ANANDUnitNo lastInChain(Anand vol, ANANDUnitNo unitNo)
{
ANANDUnitNo firstVirtualUnitNo, firstReplacementUnitNo;
ANANDUnitNo lastUnit = unitNo, nextUnitNo;
ANANDUnitNo chainBound = 0;
if(unitNo == ANAND_NO_UNIT)
return ANAND_NO_UNIT;
getUnitData(&vol,unitNo,&firstVirtualUnitNo,&firstReplacementUnitNo);
nextUnitNo = firstReplacementUnitNo;
while( (nextUnitNo < vol.noOfUnits) && /* Validate replacement unit no. */
(chainBound < DOUBLE_MAX_UNIT_CHAIN) ) {
ANANDUnitNo nextVirtualUnitNo, nextReplacementUnitNo;
if( !isAvailable(nextUnitNo) )
break;
getUnitData(&vol,nextUnitNo,&nextVirtualUnitNo,&nextReplacementUnitNo);
if( nextVirtualUnitNo != (firstVirtualUnitNo | ANAND_REPLACING_UNIT) )
break; /* Virtual unit no. not validated */
lastUnit = nextUnitNo;
nextUnitNo = nextReplacementUnitNo;
chainBound++;
}
return lastUnit;
}
#ifndef FL_READ_ONLY
/*----------------------------------------------------------------------*/
/* 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, ANANDUnitNo unitNo, ANANDUnitNo virtualUnitNo)
{
ANANDUnitNo newVirtualUnitNo, newReplacementUnitNo;
ANANDUnitNo oldVirtualUnitNo, oldReplacementUnitNo;
FLStatus status;
ANANDUnitNo newestUnitNo = vol.virtualUnits[virtualUnitNo];
ANANDUnitNo oldUnitNo;
/* Assign the new unit */
newVirtualUnitNo = virtualUnitNo;
if (newestUnitNo != ANAND_NO_UNIT)
newVirtualUnitNo |= ANAND_REPLACING_UNIT;
newReplacementUnitNo = ANAND_NO_UNIT;
vol.physicalUnits[unitNo] = 0;
vol.freeUnits--;
status = setUnitData(&vol,unitNo,newVirtualUnitNo,newReplacementUnitNo);
if (status != flOK)
{
markUnitBad(&vol,unitNo);
return status;
}
/* Add unit to chain */
if (newestUnitNo != ANAND_NO_UNIT)
{
/* If unit is frozen, don't attempt to chain (folding not-in-place) */
if (!isAvailable(newestUnitNo))
return flOK;
oldUnitNo = lastInChain(&vol,newestUnitNo);
getUnitData(&vol,oldUnitNo,&oldVirtualUnitNo,&oldReplacementUnitNo);
if (oldReplacementUnitNo != ANAND_NO_UNIT)
status = flWriteFault; /* can't write here, so assume failure */
else {
vol.physicalUnits[oldUnitNo] |= UNIT_REPLACED;
status = setUnitData(&vol,oldUnitNo,oldVirtualUnitNo,unitNo);
}
if (status != flOK) {
formatUnit(&vol,unitNo); /* Get rid of the allocated unit quickly */
setUnavail(newestUnitNo); /* freeze the chain */
return status;
}
if (vol.countsValid > virtualUnitNo && newestUnitNo != oldUnitNo){
if (countOf(newestUnitNo) + countOf(oldUnitNo) <= UNIT_MAX_COUNT)
vol.physicalUnits[newestUnitNo] += countOf(oldUnitNo);
else
return flGeneralFailure;
}
}
else
vol.virtualUnits[virtualUnitNo] = unitNo;
return flOK;
}
#endif /* FL_READ_ONLY */
/*----------------------------------------------------------------------*/
/* 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, ANANDUnitNo unitNo)
{
/* Erase the chain from end to start */
ANANDUnitNo chainBound;
setUnitCount(unitNo,0); /* Reenable erase of this unit */
for (chainBound=0;( chainBound < DOUBLE_MAX_UNIT_CHAIN ); chainBound++) {
/* Find last unit in chain */
ANANDUnitNo unitToErase = lastInChain(&vol,unitNo);
if( formatUnit(&vol,unitToErase) != flOK )
break;
if (unitToErase == unitNo)
break; /* Erased everything */
}
return flOK;
}
#ifndef FL_READ_ONLY
/*----------------------------------------------------------------------*/
/* S w a p U n i t s */
/* */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -