📄 nftllite.c.bak
字号:
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 + -