📄 nftllite.c
字号:
vol.ucache[unitNo].virtualUnitNo =
LE2(unitData.virtualUnitNo) | LE2(unitData.spareVirtualUnitNo);
vol.ucache[unitNo].replacementUnitNo =
LE2(unitData.replacementUnitNo) | LE2(unitData.spareReplacementUnitNo);
}
*virtualUnitNo = vol.ucache[unitNo].virtualUnitNo;
*replacementUnitNo = vol.ucache[unitNo].replacementUnitNo;
}
else
#endif /* NFTL_CACHE */
{ /* no ANANDUnitHeader cache */
vol.flash->read(vol.flash,
unitBaseAddress(&vol,unitNo) + UNIT_DATA_OFFSET,
&unitData,
sizeof(ANANDUnitHeader),
EXTRA);
/* Mask out any 1 -> 0 bit faults by or'ing with spare data */
*virtualUnitNo = LE2(unitData.virtualUnitNo) |
LE2(unitData.spareVirtualUnitNo);
*replacementUnitNo = LE2(unitData.replacementUnitNo) |
LE2(unitData.spareReplacementUnitNo);
}
if( !isLegalUnit(*replacementUnitNo) ) {
vol.invalidReplacement = unitNo;
if(vol.badFormat == FALSE) /* Not called by mount operation */
{
ANANDUnitNo firstUnits = vol.virtualUnits[*virtualUnitNo];
if(firstUnits != ANAND_NO_UNIT)
setUnavail(firstUnits & (~ANAND_REPLACING_UNIT)); /* freeze unit chain */
}
*replacementUnitNo = ANAND_NO_UNIT;
}
}
#ifndef FL_READ_ONLY
/*----------------------------------------------------------------------*/
/* s e t U n i t D a t a */
/* */
/* Set virtual unit No. and replacement unit no. of a unit. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* unitNo : Physical unit number */
/* virtualUnitNo : Virtual unit no. */
/* replacementUnitNo : Replacement unit no. */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/* */
/*----------------------------------------------------------------------*/
static FLStatus setUnitData(Anand vol,
ANANDUnitNo unitNo,
ANANDUnitNo virtualUnitNo,
ANANDUnitNo replacementUnitNo)
{
ANANDUnitHeader unitData;
ANANDUnitNo newVirtualUnitNo, newReplacementUnitNo;
if( replacementUnitNo == unitNo ) /* prevent chain loop */
return flGeneralFailure;
toLE2(unitData.virtualUnitNo,virtualUnitNo);
toLE2(unitData.spareVirtualUnitNo,virtualUnitNo);
toLE2(unitData.replacementUnitNo,replacementUnitNo);
toLE2(unitData.spareReplacementUnitNo,replacementUnitNo);
checkStatus(vol.flash->write(vol.flash,
unitBaseAddress(&vol,unitNo) + UNIT_DATA_OFFSET,
&unitData,
sizeof(ANANDUnitHeader),
EXTRA));
#ifdef VERIFY_WRITE
if (vol.flash->socket->verifyWrite==FL_ON)
{
#ifdef NFTL_CACHE
/* Set new entries for ANANDUnitHeader cache */
if (vol.ucache != NULL) {
vol.ucache[unitNo].virtualUnitNo = virtualUnitNo;
vol.ucache[unitNo].replacementUnitNo = replacementUnitNo;
}
#endif /* NFTL_CACHE */
return flOK;
}
#endif /* VERIFY_WRITE */
#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;
}
#endif /* NFTL_CACHE */
/* Verify the new unit data */
getUnitData(&vol,unitNo,&newVirtualUnitNo, &newReplacementUnitNo);
if (virtualUnitNo != newVirtualUnitNo ||
replacementUnitNo != newReplacementUnitNo)
return flWriteFault;
else
return flOK;
}
#endif /* FL_READ_ONLY */
/*----------------------------------------------------------------------*/
/* g e t N e x t U n i t */
/* */
/* Get next unit in chain. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* unitNo : Physical unit number */
/* virUnitNo : Virtual unit number of the chain. */
/* */
/* Returns: */
/* Physical unit number of the unit following unitNo in the chain. */
/* If such unit do not exist, return ANAND_NO_UNIT. */
/*----------------------------------------------------------------------*/
static ANANDUnitNo getNextUnit(Anand vol, ANANDUnitNo unitNo, ANANDUnitNo virUnitNo)
{
ANANDUnitNo virtualUnitNo, replacementUnitNo;
if (!(vol.physicalUnits[unitNo] & UNIT_REPLACED))
return ANAND_NO_UNIT;
getUnitData(&vol,unitNo,&virtualUnitNo,&replacementUnitNo);
if( virUnitNo != (virtualUnitNo & ~ANAND_REPLACING_UNIT) ) {
unitNo = vol.virtualUnits[virUnitNo];
setUnavail(unitNo); /* freeze unit chain */
return ANAND_NO_UNIT;
}
return replacementUnitNo;
}
#ifdef NFTL_CACHE
/*----------------------------------------------------------------------*/
/* g e t S e c t o r F l a g s F r o m C a c h e */
/* */
/* Get sector flags from Sector Cache. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : starting address of the sector */
/* */
/* Returns: */
/* sector flags (SECTOR_USED, SECTOR_DELETED etc.) */
/*----------------------------------------------------------------------*/
static unsigned char getSectorFlagsFromCache(Anand vol, CardAddress address)
{
return scacheTable[(vol.scache[address >> (SECTOR_SIZE_BITS+2)] >>
(((unsigned int)address >> 8) & 0x7)) & 0x3];
}
/*----------------------------------------------------------------------*/
/* s e t S e c t o r F l a g s C a c h e */
/* */
/* Get sector flags from Sector Cache. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : starting address of the sector */
/* sectorFlags : one of SECTOR_USED, SECTOR_DELETED etc. */
/* */
/*----------------------------------------------------------------------*/
static void setSectorFlagsCache(Anand vol, CardAddress address,
unsigned char sectorFlags)
{
register unsigned char tmp, val;
if (vol.scache == NULL)
return;
tmp = vol.scache[address >> (SECTOR_SIZE_BITS+2)];
switch(sectorFlags) {
case SECTOR_USED: val = S_CACHE_SECTOR_USED; break;
case SECTOR_FREE: val = S_CACHE_SECTOR_FREE; break;
case SECTOR_DELETED: val = S_CACHE_SECTOR_DELETED; break;
default:/* SECTOR_IGNORE */val = S_CACHE_SECTOR_IGNORE; break;
}
switch (((unsigned int)address >> 8) & 0x7) {
case 0: tmp = (tmp & 0xfc) | (val ); break; /* update bits 0..1 */
case 2: tmp = (tmp & 0xf3) | (val << 2); break; /* bits 2..3 */
case 4: tmp = (tmp & 0xcf) | (val << 4); break; /* bits 4..5 */
case 6: tmp = (tmp & 0x3f) | (val << 6); break; /* bits 6..7 */
}
vol.scache[address >> (SECTOR_SIZE_BITS+2)] = tmp;
}
#endif /* NFTL_CACHE */
/*----------------------------------------------------------------------*/
/* g e t S e c t o r F l a g s */
/* */
/* Get sector status. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* sectorAddress : Physical address of the sector */
/* */
/* Returns: */
/* Return the OR of the two bytes in the sector status area (the */
/* bytes should contain the same data). */
/*----------------------------------------------------------------------*/
static unsigned char getSectorFlags(Anand vol, CardAddress sectorAddress)
{
byte flags[2];
byte blockFlag = SECTOR_IGNORE;
byte index,tmpSector;
FLStatus status;
#ifdef NFTL_CACHE
if (vol.scache != NULL) { /* check for Sector Flags cache hit */
blockFlag = getSectorFlagsFromCache(&vol, sectorAddress);
if (blockFlag != SECTOR_IGNORE)
return blockFlag;
}
#endif /* NFTL_CACHE */
vol.flash->read(vol.flash, sectorAddress + SECTOR_DATA_OFFSET,
flags, sizeof flags, EXTRA);
if((flags[0] == flags[1]) && (isValidSectorFlag(flags[0])))
{
blockFlag = flags[0];
}
else /* Sector flags that were read are not legal */
{
/* Force remapping of internal catched sector */
vol.flash->socket->remapped = TRUE;
/* Check for ignored sector using the EDC */
status = vol.flash->read(vol.flash, sectorAddress,
nftlBuffer, SECTOR_SIZE, EDC);
if(status == flOK)
{
/* Check if distance is less then 2 bits failure since */
/* 2 bits failure can be either delete or used */
for (index=0 , tmpSector = (byte)SECTOR_USED ; index < 2 ;
index++ , tmpSector = (byte)SECTOR_DELETED)
{
if (distanceOf(flags[0], tmpSector) +
distanceOf(flags[1], tmpSector) <= 2)
{
blockFlag = tmpSector;
break;
}
}
if(index>=2)
return SECTOR_IGNORE;
}
else
{
return SECTOR_IGNORE;
}
}
#ifdef NFTL_CACHE
/* update Sector Flags cache */
setSectorFlagsCache(&vol, sectorAddress, blockFlag);
#endif /* NFTL_CACHE */
return blockFlag;
}
/*----------------------------------------------------------------------*/
/* f i n d E n d O f E n d l e s s C h a i n */
/* */
/* Find end of endless chain - last unit of unit chain that points to */
/* itself. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* virUnitNo : Virtual unit number */
/* */
/* Returns: */
/* Physical unit number of oldest unit of the chain */
/*----------------------------------------------------------------------*/
static ANANDUnitNo findEndOfEndlessChain(Anand vol, ANANDUnitNo virUnitNo)
{
ANANDUnitNo chainsUnit[DOUBLE_MAX_UNIT_CHAIN/2+2];
ANANDUnitNo unitNo;
int i;
int chainBound;
for (unitNo = vol.virtualUnits[virUnitNo] , chainBound = 0 ;
chainBound < MAX_UNIT_CHAIN ;
unitNo = getNextUnit(&vol,unitNo,virUnitNo) , chainBound++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -