📄 fsmrecl.c
字号:
/*****************************************************************************
FILE NAME: FsmRecl.c
DESCRIPTION:
Dfs Reclamation functions.
Copyright (c) 2002, VIA Technologies, Inc.
*****************************************************************************/
#include "fsmdefs.h"
#include "FsmDev.h"
#include "FsmFlash.h"
#include "FsmDfs.h"
#include "Ostype.h"
static uint32
DfsReclaimThisBlock(
FsmDevObjHdrT * DevObjP,
uint16 ReclaimedPbn
);
static uint32
DfsCopySectorValidData(
FsmDevObjHdrT * DevObjP,
uint32 DestAddr,
uint32 SrcAddr
);
/************************************************************************************
*
* Function Name: DfsReclaimProcess(FsmDevObjHdrT * DevObjP)
* Description:
* Find out the block which need to be reclaimed, and reclaim it.
* Input:
* FsmDevObjHdrT * DevObjP: the Falsh device structure,which need to be reclaimed.
* Output:
* N/A
* Return:
* 0 or ErrorCode
* Comment:
* There is no need to lock externally.Because of the call of DfsReclaimThisBlock,
* there are two internal lock, DevLsntoPsnMapLock and DevInfoLock.
*
*************************************************************************************/
uint32 DfsReclaimProcess(FsmDevObjHdrT * DevObjP)
{
uint32 status;
uint16 i;
uint32 MaxBlocks;
uint32 EraseCount;
uint32 DirtySectors;
uint16 ReclaimedPbn;
uint32 DirtiestSpace;
uint32 MaxEraseCount;
uint32 MinEraseCount;
FsmFlashMediaT * MediaP;
#ifdef DEBUG_FSM
uint32 Start_Time,End_Time,Execute_Time;
Start_Time = FsmGetCurrentTime();
MonPrintf("\nReclaim Process Start!");
#endif
if(DevObjP == NULL)
{
return ERR_PARAM;
}
if(DevObjP->DevType != DEV_TYPE_FLASH)
{
#ifdef DEBUG_FSM
MonPrintf("\nIn FsmReclaimProcess(), DevType is not Flash Media.");
#endif
return ERR_PARAM;
}
MediaP = (FsmFlashMediaT *)DevObjP->MediaObjP;
MaxBlocks = ((FsmFlashDevT *)DevObjP)->Blocks;
#ifdef DEBUG_FSM
MonPrintf("\nSpare Block Pbn is %d.",MediaP->SpareBlk);
#endif
MaxEraseCount = 0;
MinEraseCount = (uint32)(-1);
ReclaimedPbn = (uint16)(-1);
/* scan all blocks' erase count */
for(i = 0; i < MaxBlocks; i++)
{
if(MediaP->SpareBlk == i)
{
/* Skip Spare Block */
continue;
}
EraseCount = MediaP->BlockInfoP[i].EraseCount;
#ifdef DEBUG_FSM
MonPrintf("\nThe Erase Count of Block %d is %d.", i, EraseCount);
#endif
if(EraseCount < MinEraseCount)
{
MinEraseCount = EraseCount;
ReclaimedPbn = i;
}
if(EraseCount > MaxEraseCount)
{
MaxEraseCount = EraseCount;
}
}
#ifdef DEBUG_FSM
MonPrintf("\nMaximum Erase Conut is %d; \nMinimum Erase Count is %d.", MaxEraseCount, MinEraseCount);
#endif
/* check if it is up to wearing-level threshold */
if((MaxEraseCount - MinEraseCount) > WEARING_LEVEL_THRESHOLD)
{
#ifdef DEBUG_FSM
MonPrintf("\nUpto Wearing Level Threshold");
#endif
if((status = FsmGetMtxSem(MediaP->InfoLock)) != ERR_NONE)
{
#ifdef DEBUG_FSM
MonPrintf("\nIn FsmReclaimProcess(),Sem (DevInfoLock) Obtained Failed.");
#endif
return status;
}
MediaP->BlockInfoP[ReclaimedPbn].EraseCount += WEARING_LEVEL_INCREMENT;
FsmReleaseMtxSem(MediaP->InfoLock);
status = DfsReclaimThisBlock(DevObjP, ReclaimedPbn);
}
else /* not up to wearing-level threshold */
{
MinEraseCount = (uint32)(-1);
ReclaimedPbn = (uint16)(-1);
DirtiestSpace = 0;
/* Scan all Blocks dirty space */
for(i = 0; i < MaxBlocks; i++)
{
DirtySectors = MediaP->BlockInfoP[i].DirtySectors;
#ifdef DEBUG_FSM
MonPrintf("\nThe Dirty Sector of Block %d is %d.", i, DirtySectors);
#endif
if(DirtySectors == 0) /* no dirty sector*/
{
continue;
}
if(DirtySectors > DirtiestSpace)
{
DirtiestSpace = DirtySectors;
ReclaimedPbn = i;
}
/* Reclaim The Block which dirty space is up to pre-defined threshold */
if(DirtySectors >= MediaP->SectorsPerBlock)
{
#ifdef DEBUG_FSM
MonPrintf("\nUp to Dirty Threshold");
#endif
EraseCount = MediaP->BlockInfoP[i].EraseCount;
if(EraseCount < MinEraseCount)
{
/* select the block with minimum erase count. */
MinEraseCount = EraseCount;
ReclaimedPbn = i;
}
}
}
if(ReclaimedPbn == (uint16)(-1))
return ERR_FULL;
/* Reclaim the dirtiest block or its dirty space is up to pre-defined threshold*/
if((status = FsmGetMtxSem(MediaP->InfoLock)) != ERR_NONE)
{
#ifdef DEBUG_FSM
MonPrintf("\n In FsmReclaimProcess(),Sem (DevInfoLock) Obtained Failed.");
#endif
return status;
}
MediaP->BlockInfoP[ReclaimedPbn].EraseCount += 1;
FsmReleaseMtxSem(MediaP->InfoLock);
status = DfsReclaimThisBlock(DevObjP,ReclaimedPbn);
}
#ifdef DEBUG_FSM
End_Time = FsmGetCurrentTime();
Execute_Time = (End_Time - Start_Time);
MonPrintf("\n Reclaim Process Execute Time is %d",Execute_Time);
#endif
return status;
}
/************************************************************************************
*
* Function Name: DfsReclaimThisBlock(FsmMediaObjHdrT *pDevHdr,uint16 ReclaimedPbn)
* Description:
* Reclaim the specified block(ReclaimedPbn).
* When DEBUG_FSM, print total running time of Reclaiming one block.
* Input:
* ReclaimedPbn: The Physical Block Number which needs to be reclaimed.
* FsmMediaObjHdrT *pDevHdr: the Falsh device structure,which need to be reclaimed.
* Output:
* N/A
* Return:
* 0 or ErrorCode
* Comment:
* This Function does not need external lock.
* But, There are two internal locks, DevLSNtoPSNMapLOCK and DevInfoLock
* that is provided by struct DevObjHdrT.
* Note: Need Record LSN of Valid Sector And New PSN(need calculate)
*
***************************************************************************************/
static uint32 DfsReclaimThisBlock(FsmDevObjHdrT * DevObjP,uint16 ReclaimedPbn)
{
uint32 status;
uint16 i;
uint16 SectorIndex;
uint32 BlockSize;
uint32 WholeSectorSize;
uint16 SectorsPerBlk;
uint16 SpareBlockPbn;
uint32 FsmTag;
uint32 ReclaimedAddr;
uint16 SectorStatus;
uint16 BlockStatus;
uint32 SectorLsn;
uint32 SectorPsn;
uint32 EraseCount;
uint32 SpareBlockAddr;
uint32 ReclaimedBlockAddr;
uint32 BlockInfoAddr;
FsmFlashMediaT * MediaP;
FsmDevDrvT * pDrv;
#ifdef DEBUG_FSM
uint32 Start_Time,End_Time,Execute_Time;
Start_Time = FsmGetCurrentTime();
MonPrintf("\n Reclaim the Block %d Start!",ReclaimedPbn);
#endif
pDrv = DevObjP->DevDrvP;
MediaP = (FsmFlashMediaT *)DevObjP->MediaObjP;
if(MediaP == NULL)
{
return ERR_PARAM;
}
if(ReclaimedPbn >= ((FsmFlashDevT *)DevObjP)->Blocks)
{
#ifdef DEBUG_FSM
MonPrintf("\n The parameter--ReclaimedPbn--of DfsReclaimThisBlock() is OverFlow.");
#endif
return ERR_PARAM;
}
SpareBlockPbn = MediaP->SpareBlk;
WholeSectorSize = MediaP->SectorSize + sizeof(FsmFlashSectorHdrT);
SectorsPerBlk = MediaP->SectorsPerBlock;
BlockSize = ((FsmFlashDevT *)DevObjP)->BlockSize;
SpareBlockAddr = SpareBlockPbn * BlockSize;
ReclaimedBlockAddr = ReclaimedPbn * BlockSize;
/* Get Spare Block Info Start Address */
BlockInfoAddr = SpareBlockAddr + BlockSize - sizeof(FsmBlockInfoT);
/* Recording */
BlockStatus = BLOCK_WRITING;
/* Set SpareBlock Status to BLK_WRITING */
status = pDrv->FsmDevWrite (DevObjP,
(uint8 *)&BlockStatus,
BlockInfoAddr + FIELD_OFFSET(FsmBlockInfoT, Status),
FIELD_SIZE(FsmBlockInfoT, Status)
);
if(status != ERR_NONE)
{
#ifdef DEBUG_FSM
MonPrintf("\n In DfsReclaimThisBlock(),FsmDevWrite SB Status Failed.");
#endif
return status;
}
/* Backup ReclaimedPbn in SpareBlock. */
status = pDrv->FsmDevWrite (DevObjP,
(uint8 *)&ReclaimedPbn,
BlockInfoAddr + FIELD_OFFSET(FsmBlockInfoT,Pbn),
FIELD_SIZE(FsmBlockInfoT,Pbn)
);
if(status != ERR_NONE)
{
#ifdef DEBUG_FSM
MonPrintf("\n In DfsReclaimThisBlock(),FsmDevWrite Failed.");
#endif
return status;
}
EraseCount = MediaP->BlockInfoP[ReclaimedPbn].EraseCount;
/* Backup EraseCount of Reclaimed Block to SpareBlock. */
status = pDrv->FsmDevWrite (DevObjP,
(uint8 *)&EraseCount,
BlockInfoAddr + FIELD_OFFSET(FsmBlockInfoT, BackupEraseCount),
FIELD_SIZE(FsmBlockInfoT, BackupEraseCount)
);
if(status != ERR_NONE)
{
#ifdef DEBUG_FSM
MonPrintf("\n In DfsReclaimThisBlock(),FsmDevWrite Failed.");
#endif
return status;
}
SectorIndex = 0;
/* Copying */
for(i = 0; i < SectorsPerBlk; i++)
{
ReclaimedAddr = ReclaimedBlockAddr + i * WholeSectorSize;
/* Get Sector Status */
status = pDrv->FsmDevRead(DevObjP,
(uint8 *)&SectorStatus,
ReclaimedAddr + FIELD_OFFSET(FsmFlashSectorHdrT,Status),
FIELD_SIZE(FsmFlashSectorHdrT,Status)
);
if(status != ERR_NONE)
{
#ifdef DEBUG_FSM
MonPrintf("\n In DfsReclaimThisBlock(),FsmDevRead Failed.");
#endif
return status;
}
if(SectorStatus == SECTOR_INVALID)
{
continue;
}
else if(SectorStatus == SECTOR_EMPTY)
{
break;
}
else /* if(SectorStatus == SECTOR_VALID) */
{
/* Get Reclaimed Sector's LSN. */
status = pDrv->FsmDevRead(DevObjP,
(uint8 *)&SectorLsn,
ReclaimedAddr + FIELD_OFFSET(FsmFlashSectorHdrT,Lsn),
FIELD_SIZE(FsmFlashSectorHdrT,Lsn)
);
if(status != ERR_NONE)
{
#ifdef DEBUG_FSM
MonPrintf("\n In DfsReclaimThisBlock(),FsmDevRead Failed.");
#endif
return status;
}
if(SectorLsn >= MediaP->MaxPsn)
return ERR_SYSTEM;
/* Get This Sector New Psn */
SectorPsn = SpareBlockPbn * ((uint32)SectorsPerBlk) + SectorIndex;
/* Copy the valid data of Sector */
status = DfsCopySectorValidData(DevObjP,
SpareBlockAddr + SectorIndex * WholeSectorSize,
ReclaimedAddr
);
SectorIndex++;
if(status != ERR_NONE)
{
#ifdef DEBUG_FSM
MonPrintf("\n In DfsReclaimThisBlock(), DfsCopySectorValidData Failed.");
#endif
return status;
}
/* Update the Map Table of Lsn2Psn */
if((status = FsmGetMtxSem(MediaP->MapTblLock)) != ERR_NONE)
{
#ifdef DEBUG_FSM
MonPrintf("\n In DfsReclaimThisBlock(),Sem (DevMapTblLock) Obtained Failed.");
#endif
return status;
}
MediaP->Lsn2PsnP[SectorLsn] = SectorPsn;
FsmReleaseMtxSem(MediaP->MapTblLock);
}
}
#ifdef DEBUG_FSM
MonPrintf("\n Copy Data Finished.Copy %d Sectors Data,Free %d Sectors Space",SectorIndex, i - SectorIndex);
#endif
/* Erasing */
/* Set SpareBlock Status to BLK_ERASING */
BlockStatus = BLOCK_ERASING;
status = pDrv->FsmDevWrite( DevObjP,
(uint8 *)&BlockStatus,
BlockInfoAddr + FIELD_OFFSET(FsmBlockInfoT, Status),
FIELD_SIZE(FsmBlockInfoT, Status)
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -