📄 nftllite.c
字号:
chainsUnit[chainBound] = unitNo; /* Save location of current unit */
for(i = 0 ; i < chainBound ; i++) /* Check if already been to this unit */
{
if(chainsUnit[chainBound] == unitNo) /* Bad next unit number pointer */
break;
}
}
return chainsUnit[chainBound-1];
}
/*----------------------------------------------------------------------*/
/* v i r t u a l 2 P h y s i c a l */
/* */
/* Translate virtual sector number to physical address. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* sectorNo : Virtual sector number */
/* endAddress : End address for sector search. NULL for no end */
/* */
/* Returns: */
/* endAddress : Next free sector address */
/* physical address of sectorNo */
/*----------------------------------------------------------------------*/
static CardAddress virtual2Physical(Anand vol, SectorNo sectorNo , CardAddress* endAddress)
{
unsigned unitOffset = (unsigned)((sectorNo % vol.sectorsPerUnit) << SECTOR_SIZE_BITS);
CardAddress prevSectorAddress = ANAND_UNASSIGNED_ADDRESS;
CardAddress sectorAddress;
CardAddress *freeSectorAddressPtr;
ANANDUnitNo unitNo, virUnitNo;
ANANDUnitNo chainBound = 0;
ANANDUnitNo endUnit;
byte sectorFlags;
/* Set end unit and nextFreeSectorAddress */
if(endAddress == NULL)
{
endUnit = ANAND_NO_UNIT;
}
else
{
endUnit = (ANANDUnitNo)(*endAddress>>vol.unitSizeBits);
*endAddress = ANAND_UNASSIGNED_ADDRESS;
}
/* follow the chain */
virUnitNo = (ANANDUnitNo)(sectorNo / vol.sectorsPerUnit);
for (unitNo = vol.virtualUnits[virUnitNo];
( (unitNo != endUnit) && (chainBound < DOUBLE_MAX_UNIT_CHAIN) );
unitNo = getNextUnit(&vol,unitNo,virUnitNo))
{
sectorAddress = unitBaseAddress(&vol,unitNo) + unitOffset;
sectorFlags = getSectorFlags(&vol,sectorAddress);
if (sectorFlags == SECTOR_FREE)
{
if(endAddress != NULL)
*endAddress = sectorAddress;
break;
}
if (sectorFlags != SECTOR_IGNORE)
prevSectorAddress = sectorFlags != SECTOR_DELETED ? sectorAddress :
ANAND_UNASSIGNED_ADDRESS;
chainBound++;
}
if(chainBound < DOUBLE_MAX_UNIT_CHAIN)
return prevSectorAddress;
/* Infint loop caused by power failure */
if(endAddress == NULL)
{
freeSectorAddressPtr = §orAddress;
}
else
{
freeSectorAddressPtr = endAddress;
}
*freeSectorAddressPtr = unitOffset +
unitBaseAddress(&vol,
findEndOfEndlessChain(&vol,virUnitNo));
return virtual2Physical(&vol, sectorNo , freeSectorAddressPtr);
}
/*----------------------------------------------------------------------*/
/* 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, ANANDUnitNo 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,
ANANDUnitNo 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,
ANANDUnitNo 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 */
/* flash : Flash media mounted on this socket */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/*----------------------------------------------------------------------*/
static FLStatus initNFTL(Anand vol, FLFlash *flash)
{
dword size = 1;
if (flash == NULL || !(flash->flags & NFTL_ENABLED)) {
DEBUG_PRINT(("Debug: media is not fit for NFTL format.\r\n"));
return flUnknownMedia;
}
vol.flash = flash;
vol.socketNo = (byte)flSocketNoOf(vol.flash->socket);
vol.physicalUnits = NULL;
vol.virtualUnits = NULL;
#ifdef NFTL_CACHE
vol.ucache = NULL;
vol.scache = NULL;
#endif
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(ANANDPhysUnit) + SECTOR_SIZE > (1UL << vol.unitSizeBits)) {
vol.unitSizeBits++;
vol.noOfUnits >>= 1;
}
/* Bound number of units to find room in 64 Kbytes Segment */
if( (vol.noOfUnits >= MAX_UNIT_NUM) && (vol.unitSizeBits < MAX_UNIT_SIZE_BITS) ) {
vol.unitSizeBits++;
vol.noOfUnits >>= 1;
}
vol.badFormat = TRUE; /* until mount completes*/
vol.mappedSectorNo = UNASSIGNED_SECTOR;
vol.countsValid = 0; /* No units have a valid count yet */
/*get pointer to buffer (we assume SINGLE_BUFFER is not defined) */
vol.buffer = flBufferOf(flSocketNoOf(vol.flash->socket));
#ifdef VERIFY_ERASED_SECTOR
vol.verifyBuffer = (dword *)flReadBackBufferOf(flSocketNoOf(flash->socket));
#endif /* VERIFY_ERASED_SECTOR */
#if (defined(VERIFY_WRITE) || defined(VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
vol.verifiedSectorNo = 0; /* Largest sector verified so far */
#endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
vol.invalidReplacement = ANAND_NO_UNIT; /* a unit with bad RUN */
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 FL_MALLOC
vol.physicalUnits = (ANANDPhysUnit FAR1*) FL_FAR_MALLOC (vol.noOfUnits * sizeof(ANANDPhysUnit));
vol.virtualUnits = (ANANDUnitNo FAR1*) FL_FAR_MALLOC (vol.noOfVirtualUnits * sizeof(ANANDUnitNo));
if (vol.physicalUnits == NULL ||
vol.virtualUnits == NULL) {
DEBUG_PRINT(("Debug: failed allocating conversion tables for NFTL.\r\n"));
return flNotEnoughMemory;
}
#else
char *heapPtr;
heapPtr = vol.heap;
vol.physicalUnits = (ANANDPhysUnit *) heapPtr;
heapPtr += vol.noOfUnits * sizeof(ANANDPhysUnit);
vol.virtualUnits = (ANANDUnitNo *) heapPtr;
heapPtr += vol.noOfVirtualUnits * sizeof(ANANDUnitNo);
if (heapPtr > vol.heap + sizeof vol.heap) {
DEBUG_PRINT(("Debug: not enough memory for NFTL conversion tables.\r\n"));
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, ANANDUnitNo unitNo)
{
unsigned short eraseMark;
unsigned long eraseCount;
vol.physicalUnits[unitNo] = UNIT_BAD_MOUNT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -