⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsmrecl.c

📁 norflash的文件系统。 用于中低端手机开发的参考
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 
  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 + -