📄 inftl.c
字号:
tmp = vol.scache[(address - vol.firstUnitAddress) >> (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 (((word)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 - vol.firstUnitAddress) >> (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 byte getSectorFlags(Bnand 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 or not valid */
{
TL_DEBUG_PRINT(tl_out,"getSectorFlags : Sector flags are not valid - physical addr %ld ",sectorAddress);
TL_DEBUG_PRINT(tl_out,"first flag was %x ",flags[0]);
TL_DEBUG_PRINT(tl_out,"while scond is %x\n",flags[1]);
SET_EXIT(INFTL_FAILED_MOUNT);
/* 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,
inftlBuffer, SECTOR_SIZE, EDC);
#if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
/* Now restore the ff's for the verifySectors routine */
tffsset(inftlBuffer,0xff,SECTOR_SIZE);
#endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
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;
}
#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. */
/* prevUnitNo : Previous unit no. */
/* ANAC : Accumulating Number Along Chain */
/* NAC : Number Along Chain. */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/* */
/*----------------------------------------------------------------------*/
static FLStatus setUnitData(Bnand vol,
ANANDUnitNo unitNo,
ANANDUnitNo virtualUnitNo,
ANANDUnitNo prevUnitNo,byte ANAC,byte NAC)
{
ANANDUnitHeader unitData;
SecondANANDUnitHeader secondUnitData;
FLStatus status;
ANANDUnitNo newVirtualUnitNo, newPrevUnitNo;
byte newANAC,newNAC;
byte temp;
byte parityPerField = 0;
if( prevUnitNo == unitNo ) /* prevent chain loop */
return flGeneralFailure;
/* Calculate parity per field */
temp=(byte)(((byte *)&virtualUnitNo)[0]^((byte *)&virtualUnitNo)[1]);
if((onesCount(temp) & 1)==1)
parityPerField|=VU_PARITY_BIT;
temp=(byte)(((byte *)&prevUnitNo)[0]^((byte *)&prevUnitNo)[1]);
if((onesCount(temp) & 1)==1)
parityPerField|=PU_PARITY_BIT;
if((onesCount(ANAC) & 1)==1)
parityPerField|=ANAC_PARITY_BIT;
if((onesCount(NAC) & 1)==1)
parityPerField|=NAC_PARITY_BIT;
/* Store fields in proper unit header record */
toLE2(unitData.virtualUnitNo,virtualUnitNo);
toLE2(secondUnitData.virtualUnitNo,virtualUnitNo);
toLE2(unitData.prevUnitNo,prevUnitNo);
toLE2(secondUnitData.prevUnitNo,prevUnitNo);
unitData.ANAC=secondUnitData.ANAC=ANAC;
unitData.NAC=secondUnitData.NAC=NAC;
unitData.parityPerField=secondUnitData.parityPerField=parityPerField;
unitData.discarded=DISCARD;
/* Write first unit header */
status = vol.flash->write(vol.flash,
unitBaseAddress(vol,unitNo) + UNIT_DATA_OFFSET,
&unitData,
sizeof(ANANDUnitHeader),
EXTRA);
if(status == flOK) /* Write second unit header */
status = vol.flash->write(vol.flash, unitBaseAddress(vol,unitNo) +
SECOND_HEADER_OFFSET+UNIT_DATA_OFFSET,
&secondUnitData,
sizeof(SecondANANDUnitHeader),
EXTRA);
if(status == flOK)
{
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
if (vol.flash->socket->verifyWrite == FL_ON)
goto fillCache;
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
#ifdef NFTL_CACHE
if (vol.ucache != NULL) /* Mark unit cache as none valid before read */
{
vol.ucache[unitNo].virtualUnitNo = 0xDEAD;
vol.ucache[unitNo].prevUnitNo = 0xDEAD;
}
#endif /* NFTL_CACHE */
status = getUnitData(&vol,unitNo,&newVirtualUnitNo, &newPrevUnitNo,&newANAC,&newNAC,&parityPerField);
if (status == flOK)
{
if ((virtualUnitNo == newVirtualUnitNo) &&
(prevUnitNo == newPrevUnitNo ) &&
(!badParityResult(parityPerField) ) )
goto fillCache;
}
}
/* If we reached here we failed in writing unit header */
/* Erase unit and report write fault */
DEBUG_PRINT(("setUnitData : Failed setting unit data\r\n"));
status = formatUnit(&vol,unitNo,UNIT_TAILER_OFFSET);
if (status != flOK)
{
markUnitBad(&vol,unitNo);
return status;
}
else
{
return flWriteFault;
}
fillCache: /* Unit headers were placed OK, now update cache */
#ifdef NFTL_CACHE
/* Update ANANDUnitHeader cache to prevent re-filling from flash */
if (vol.ucache != NULL) {
vol.ucache[unitNo].virtualUnitNo = virtualUnitNo;
vol.ucache[unitNo].prevUnitNo = prevUnitNo;
vol.ucache[unitNo].ANAC = ANAC;
vol.ucache[unitNo].NAC = NAC;
}
#endif /* NFTL_CACHE */
return flOK;
}
/*----------------------------------------------------------------------*/
/* d i s c a r d Q u i c k M o u n t I n f o */
/* */
/* Mark quick mount information is none valid. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/*----------------------------------------------------------------------*/
static FLStatus discardQuickMountInfo(Bnand vol)
{
#ifndef RAM_MTD
static const
#endif /* RAM_MTD */
dword tmp = 0;
/* Dis - validate quick mount data */
if(vol.firstMediaWrite == FALSE)
{
vol.firstMediaWrite = TRUE;
return vol.flash->write(vol.flash, QUICK_MOUNT_VALID_SIGN_OFFSET +
((dword)(vol.firstQuickMountUnit + vol.quickMountBB)<<
vol.unitSizeBits),
&tmp,
sizeof(tmp),
0);
}
return flOK;
}
/*----------------------------------------------------------------------*/
/* m a r k A s I g n o r e d */
/* */
/* Mark sector at given address as ignored. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* addr : Physical address of the sector */
/* */
/*----------------------------------------------------------------------*/
static void markAsIgnored(Bnand vol,CardAddress addr)
{
#ifndef RAM_MTD
static const
#endif /* RAM_MTD */
byte sectorFlags[2] = {SECTOR_IGNORE,SECTOR_IGNORE};
DEBUG_PRINT(("markAsIgnored : A sector is being marked as ignored\r\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -