📄 nftllite.c
字号:
/* Applies wear leveling. */
/* A rover unit dictates the current unit to level. If a unit chain */
/* fold, if single unit chain , append a unit and then fold. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/*----------------------------------------------------------------------*/
FLStatus swapUnits(Anand vol)
{
ANANDUnitNo i,unitNo,virtualUnitNo,replacementUnitNo;
FLStatus status;
if(vol.wearLevel.currUnit>=vol.noOfVirtualUnits)
return flOK;
for(i=0,unitNo=vol.virtualUnits[vol.wearLevel.currUnit];
(unitNo==ANAND_NO_UNIT) && (i<vol.noOfVirtualUnits);i++) {
vol.wearLevel.currUnit++;
if(vol.wearLevel.currUnit>=vol.noOfVirtualUnits)
vol.wearLevel.currUnit = 0;
unitNo=vol.virtualUnits[vol.wearLevel.currUnit];
}
if(unitNo==ANAND_NO_UNIT) /*The media is empty*/
return flOK;
virtualUnitNo = vol.wearLevel.currUnit;
vol.wearLevel.currUnit++;
if(vol.wearLevel.currUnit>=vol.noOfVirtualUnits)
vol.wearLevel.currUnit = 0;
if((vol.physicalUnits[unitNo] & UNIT_REPLACED) ||
(!isAvailable(unitNo) ) )
{
status = foldUnit(&vol,virtualUnitNo,FALSE);
}
else
{
checkStatus(allocateUnit(&vol,&replacementUnitNo));
return assignUnit(&vol,replacementUnitNo,virtualUnitNo);
}
/* If folding failed make sure there are enough units and call again */
if(status == flCanNotFold)
return checkFolding(&vol,virtualUnitNo);
return status;
}
/*----------------------------------------------------------------------*/
/* f i n d F r e e U n i t */
/* */
/* Find a free unit from the physical unit pool. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* unitNo : Receives the physical unit no. */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/*----------------------------------------------------------------------*/
static FLStatus findFreeUnit(Anand vol, ANANDUnitNo *unitNo)
{
ANANDUnitNo originalUnit = vol.roverUnit;
unsigned short eraseMark;
unsigned long eraseCount;
do
{
if (++vol.roverUnit >= vol.noOfUnits)
vol.roverUnit = vol.bootUnits;
if (vol.physicalUnits[vol.roverUnit] == ANAND_UNIT_FREE)
{
/* found a free unit, if not erased, */
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 flNotEnoughMemory; /* Report no space at all */
}
/*----------------------------------------------------------------------*/
/* 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. */
/* forceFolding : Boolean flag stating wether to force folding even */
/* at the cost of loosing sector data. */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/*----------------------------------------------------------------------*/
static FLStatus foldUnit(Anand vol, ANANDUnitNo virtualUnitNo, FLBoolean forceFolding)
{
ANANDUnitNo unitNo = vol.virtualUnits[virtualUnitNo];
ANANDUnitNo targetUnitNo, chainBound;
unsigned long foldMark;
SectorNo virtualSectorNo = (SectorNo)virtualUnitNo * vol.sectorsPerUnit;
CardAddress endSectorAddress;
CardAddress targetSectorAddress;
CardAddress sourceSectorAddress;
unsigned newSectorCount, i;
FLBoolean partialFoldingFlag = FALSE;
FLStatus status;
/* Force remapping of internal catched sector */
vol.flash->socket->remapped = TRUE;
vol.unitsFolded++;
/* When using FL_OFF option the media is scanned in the folding operation */
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
if(flVerifyWrite[flSocketNoOf(vol.flash->socket)][vol.flash->socket->curPartition]==FL_OFF)
{
checkStatus(verifySectors(&vol,SECTORS_VERIFIED_PER_FOLDING));
vol.curSectorWrite = virtualSectorNo;
}
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
/* Find target unit */
if (!isAvailable(unitNo)) /* If this unit is frozen, */
{
if(vol.freeUnits > 0)
{
/* allocate a new unit to fold into */
checkStatus(findFreeUnit(&vol,&targetUnitNo));
checkStatus(assignUnit(&vol,targetUnitNo,virtualUnitNo));
}
else
{
if(forceFolding==FALSE)
return flCanNotFold;
partialFoldingFlag = TRUE;
}
}
if((isAvailable(unitNo)) || (partialFoldingFlag == TRUE))
{ /* Default. Fold into end of chain */
targetUnitNo = unitNo;
for (chainBound=0;( chainBound < DOUBLE_MAX_UNIT_CHAIN );chainBound++)
{
ANANDUnitNo nextUnitNo = getNextUnit(&vol,targetUnitNo,virtualUnitNo);
if (nextUnitNo == ANAND_NO_UNIT)
break;
targetUnitNo = nextUnitNo;
}
if(chainBound == DOUBLE_MAX_UNIT_CHAIN)
{
targetUnitNo = findEndOfEndlessChain(&vol, virtualUnitNo);
}
}
/***********************************/
/* Copy all sectors to target unit */
/***********************************/
/* Mark unit as currently folded */
foldMark = FOLDING_IN_PROGRESS * 0x10001l;
if( getFoldMark(&vol,unitNo) != FOLDING_IN_PROGRESS )
vol.flash->write(vol.flash,
unitBaseAddress(&vol,unitNo) + FOLD_MARK_OFFSET,
&foldMark,
sizeof foldMark,
EXTRA);
setUnavail(unitNo); /* Freeze this unit chain */
/* Copy all sectors to target unit */
targetSectorAddress = unitBaseAddress(&vol,targetUnitNo);
newSectorCount = 0;
for (i = 0; i < vol.sectorsPerUnit; i++, virtualSectorNo++,
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
vol.curSectorWrite++,
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
targetSectorAddress += SECTOR_SIZE)
{
endSectorAddress = ANAND_UNASSIGNED_ADDRESS;
for(chainBound=0;chainBound<DOUBLE_MAX_UNIT_CHAIN;chainBound++)
{
sourceSectorAddress = virtual2Physical(&vol,virtualSectorNo,&endSectorAddress);
if(sourceSectorAddress == targetSectorAddress)
{
/* Sector resides on the last unit of the virtual chain and */
/* does not need to be copied */
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
switch(flVerifyWrite[flSocketNoOf(vol.flash->socket)][vol.flash->socket->curPartition])
{
case FL_UPS:
newSectorCount++;
goto nextSectorLable;
case FL_OFF:
if(vol.verifiedSectorNo > virtualSectorNo)
{
newSectorCount++;
goto nextSectorLable;
}
default: /* FL_ON */
break;
}
/* Validate the sector has valid EDC/ECC */
status = vol.flash->read(vol.flash,sourceSectorAddress,nftlBuffer,SECTOR_SIZE,EDC);
if(status!=flOK)
{ /* Last sector of chain has EDC errors - can not fold there */
if(forceFolding!=TRUE)
{
return flCanNotFold;
}
else
{
goto nextSectorLable;
}
}
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
newSectorCount++;
goto nextSectorLable;
}
else if(sourceSectorAddress != ANAND_UNASSIGNED_ADDRESS)
{
/* Check that area is free (ignore flag) */
if(getSectorFlags(&vol,targetSectorAddress) != SECTOR_FREE)
{
if(forceFolding!=TRUE)
{
return flCanNotFold;
}
else
{
break;
}
}
/* Copy sector to target sector */
status = vol.flash->read(vol.flash,sourceSectorAddress,nftlBuffer,SECTOR_SIZE,EDC);
if (status != flOK) /* Try reading previous sector */
{
endSectorAddress = sourceSectorAddress;
continue;
}
status = writeAndCheck(&vol,targetSectorAddress,nftlBuffer,EDC);
switch (status)
{
case flOK: /* Success */
vol.parasiteWrites++;
newSectorCount++;
goto nextSectorLable;
case flWriteFault: /* Faild in verify write */
if (forceFolding == FALSE)
return flCanNotFold;
goto nextSectorLable;
default : /* Protection error or any other */
return status;
}
}
else /* ANAND_UNASSIGNED_ADDRESS - Sector not used */
{
goto nextSectorLable;
}
}
return flGeneralFailure;
nextSectorLable:;
} /* End of copy sector loop */
/*****************************/
/* Add unit to virtual chain */
/*****************************/
if (newSectorCount > 0) { /* Some sectors remaining*/
/* Mark target unit as original */
if( (setUnitData(&vol,targetUnitNo,virtualUnitNo,ANAND_NO_UNIT) != flOK ) ||
(partialFoldingFlag == TRUE))
{
setUnavail(targetUnitNo); /* freeze this unit */
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -