📄 inftl.c
字号:
/*************************************************/
/* T r u e F F S 5.0 S o u r c e F i l e s */
/* --------------------------------------------- */
/*************************************************/
/*****************************************************************************
* File Header *
* ----------- *
* Name : inftl.c *
* *
* Description : Implementation of INFTL flash translation layer. *
* *
*****************************************************************************/
/* Internal compilation flags */
/* #define CHAINS_DEBUG */ /* Prints unit chains after mount routine */
/* #define CHECK_MOUNT */ /* Print serious tl debug warnings to */
/* tl_out global file handle */
/* #define MAKE_SURE_IGNORE_HAS_BAD_EDC */ /* Make sure the ignore mark was */
/* written. If not fill sector */
/* with 0's. */
/* List of included files */
#include "inftl.h"
/* Private variables */
static Bnand vols[VOLUMES];
#ifndef FL_MALLOC
#ifdef NFTL_CACHE
static ucacheEntry socketUcache[SOCKETS][U_CACHE_SIZE];
static byte socketScache[SOCKETS][S_CACHE_SIZE];
#endif /* NFTL_CACHE */
static Sbyte socketHeap[SOCKETS][ANAND_HEAP_SIZE];
static byte multiSectorBuf[SOCKETS][SECTOR_SIZE<<1];
#else
static byte *multiSectorBuf[SOCKETS];
static Sbyte multiSectorBufCounter[SOCKETS];
#endif /* FL_MALLOC */
#ifdef NFTL_CACHE
/* translation table for Sector Flags cache */
static byte scacheTable[4] = { SECTOR_DELETED, /* 0 */
SECTOR_IGNORE, /* 1 */
SECTOR_USED, /* 2 */
SECTOR_FREE }; /* 3 */
#endif /* NFTL_CACHE */
/* Macros */
#define roundToUnits(var) ((var > 0) ? ((ANANDUnitNo)((var - 1) >> vol.unitSizeBits) + 1) : 0)
#define NextGoodUnit(addr,bbt) for(;bbt[(addr >> vol.unitSizeBits) - vol.firstQuickMountUnit]!=ANAND_UNIT_FREE;addr+=1L<<vol.unitSizeBits)
#define countOf(unitNo) (vol.physicalUnits[unitNo] & UNIT_COUNT)
#define isAvailable(unitNo) ((vol.physicalUnits[unitNo] == ANAND_UNIT_FREE) || (countOf(unitNo) <= UNIT_MAX_COUNT))
#define setUnavail(unitNo) (vol.physicalUnits[unitNo] = UNIT_UNAVAIL)
#define setUnitCount(unitNo,unitCount) { vol.physicalUnits[unitNo] &= ~UNIT_COUNT; vol.physicalUnits[unitNo] |= (ANANDPhysUnit)unitCount; }
#define isLegalUnit(unitNo) ((unitNo < vol.noOfUnits) || (unitNo == ANAND_NO_UNIT))
#define isValidSectorFlag(sectorFlag) ((sectorFlag==SECTOR_FREE)||(sectorFlag==SECTOR_USED)||(sectorFlag==SECTOR_DELETED))
#define badParityResult(parityResult) (parityResult != ALL_PARITY_BITS_OK)
#define consecutiveNumbers(first,second) ((byte)(second+1)==first)
#define unitBaseAddress(vol,unitNo) ((CardAddress)((ANANDUnitNo)unitNo+(ANANDUnitNo)vol.firstUnit) << vol.unitSizeBits)
#define distanceOf(read, expected) (onesCount((byte)(read ^ expected)))
#define MarkSectorAsChecked(addr) (scannedBlocks[((addr)>>SECTOR_SIZE_BITS) & vol.sectorsPerUnitMask] = TRUE)
#define WasSectorChecked(addr) scannedBlocks[((addr)>>SECTOR_SIZE_BITS) & vol.sectorsPerUnitMask]
/* M-Systems INFTL debug routines */
#ifndef CHECK_MOUNT
#define TL_DEBUG_PRINT(x,y,z)
#define SET_EXIT(x)
#define DID_MOUNT_FAIL 1
#endif /* CHECK_MOUNT */
#if (defined(CHECK_MOUNT) || defined (CHAINS_DEBUG))
#include "inftldbg.c"
#endif /* CHECK_MOUNT || CHAINS_DEBUG */
/*------------------------------------------------------*/
/* o n e s C o u n t */
/* */
/* counts number of bits that valued 1 in a given byte */
/*------------------------------------------------------*/
static byte onesCount(byte flag)
{
byte counter;
for (counter = 0; flag; flag >>= 1)
if (flag & 1)
counter++;
return counter;
}
/*----------------------------------------------------------------------*/
/* 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 */
/* offset : offset in unit */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/* */
/*----------------------------------------------------------------------*/
static FLStatus getUnitTailer(Bnand vol,
ANANDUnitNo unitNo,
word *eraseMark,
dword *eraseCount,
dword offset)
{
UnitTailer unitTailer;
FLStatus status;
status = vol.flash->read(vol.flash,
unitBaseAddress(vol,unitNo) + offset,
&unitTailer,
sizeof(UnitTailer),
EXTRA);
/* Mask out any 1 -> 0 bit faults by or'ing with spare data */
*eraseMark = (word)(LE2(unitTailer.eraseMark) | LE2(unitTailer.eraseMark1));
*eraseCount = LE4(unitTailer.eraseCount);
return status;
}
#ifndef FL_READ_ONLY
/*----------------------------------------------------------------------*/
/* 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 */
/* offset : offset in unit */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/* */
/*----------------------------------------------------------------------*/
static FLStatus setUnitTailer(Bnand vol,
ANANDUnitNo unitNo,
word eraseMark,
dword eraseCount,
dword offset)
{
UnitTailer unitTailer;
toLE2(unitTailer.eraseMark,eraseMark);
toLE2(unitTailer.eraseMark1,eraseMark);
toLE4(unitTailer.eraseCount,eraseCount);
return vol.flash->write(vol.flash,
unitBaseAddress(vol,unitNo) + offset,
&unitTailer,
sizeof(UnitTailer),
EXTRA);
}
/*----------------------------------------------------------------------*/
/* 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(Bnand vol, ANANDUnitNo unitNo)
{
word eraseMark;
dword eraseCount;
FLStatus status;
vol.physicalUnits[unitNo] = UNIT_BAD;
if(vol.freeUnits)
vol.freeUnits--;
status = getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET);
if (status == flOK)
status = setUnitTailer(&vol,unitNo,FL_BAD_ERASE_MARK,eraseCount,UNIT_TAILER_OFFSET);
#ifdef NFTL_CACHE
if (vol.ucache != NULL) /* Mark unit cache as unavaialbel */
{
vol.ucache[unitNo].virtualUnitNo = 0xDEAD;
vol.ucache[unitNo].prevUnitNo = 0xDEAD;
}
#endif /* NFTL_CACHE */
return status;
}
/*----------------------------------------------------------------------*/
/* 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 : Physical unit to format */
/* eraseMarkOffset : Offset to place erase mark */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/*----------------------------------------------------------------------*/
static FLStatus formatUnit(Bnand vol, ANANDUnitNo unitNo,
dword eraseMarkOffset)
{
word eraseMark;
dword eraseCount;
FLStatus status;
#ifndef RAM_MTD
static const
#endif /* RAM_MTD */
byte discard = (byte)CLEAR_DISCARD;
status = getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET);
if(status != flOK)
return status;
#ifdef NFTL_CACHE
/* Update ANANDUnitHeader cache to prevent re-filling from flash */
if (vol.ucache != NULL) {
vol.ucache[unitNo].virtualUnitNo = ANAND_NO_UNIT;
vol.ucache[unitNo].prevUnitNo = ANAND_NO_UNIT;
vol.ucache[unitNo].ANAC = ANAND_UNIT_FREE;
vol.ucache[unitNo].NAC = ANAND_UNIT_FREE;
}
/*
* 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 */
/* Mark unit as unusable before erase */
vol.flash->write(vol.flash,(((dword)(vol.firstUnit + unitNo))<<vol.unitSizeBits)+DISCARD_UNIT_OFFSET,&discard,1,EXTRA);
/* Physicaly erase unit */
status = vol.flash->erase(vol.flash,(word)((word)(vol.firstUnit + unitNo)
<< vol.blockMultiplierBits),(word)(1 << vol.blockMultiplierBits));
vol.eraseSum++;
eraseCount++;
if (eraseCount == 0) /* was hex FF's */
eraseCount++;
if (status == flOK)
status = setUnitTailer(&vol,unitNo,ERASE_MARK,eraseCount,eraseMarkOffset);
if (status != flOK) {
markUnitBad(&vol,unitNo); /* make sure unit format is not valid */
return status;
}
if (vol.physicalUnits[unitNo] != ANAND_UNIT_FREE)
{
vol.physicalUnits[unitNo] = ANAND_UNIT_FREE;
vol.freeUnits++;
}
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -