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

📄 fsmplr.c

📁 norflash的文件系统。 用于中低端手机开发的参考
💻 C
📖 第 1 页 / 共 5 页
字号:
		}
	}

	/* If 'invalid_tag != 0', 
	 * then there may be still some 
	 *      blocks with invalid TAG.
	 */
	if(invalid_tag != 0)
	{
		/* calculate erase count for blocks with incorrect tag. */
		if((MaxEraseCount == 0) && (MinEraseCount == (uint32)(-1)))
		{
			avg_erasecount = 1;
		}
		else
		{
			avg_erasecount = (MaxEraseCount + MinEraseCount)/2;
		}

		for(Pbn = 0; Pbn < Blocks; Pbn++)
		{
			block_address = Pbn * BlockSize;

			info_address = block_address + info_offset;

			hw_status = DevRead(pDev, 
								(uint8 *)&block_tag,
								info_address + FIELD_OFFSET(FsmBlockInfoT, Tag),
								FIELD_SIZE(FsmBlockInfoT, Tag)
								);

			if(hw_status != HW_ERR_NONE)
				return ERR_READ;

			if(block_tag != FSM_TAG)
			{
				#ifdef DEBUG_FSM
				MonPrintf("No.%d block is found with invalid tag!\n", Pbn);
				#endif

				hw_status = DevErase(pDev, block_address);

				if(hw_status != HW_ERR_NONE)
				{
					return ERR_ERASE;
				}

				BlockInfo.BackupEraseCount = (uint32)(-1);
				BlockInfo.EraseCount = avg_erasecount;
				BlockInfo.Pbn = (uint16)(-1);
				BlockInfo.Tag = FSM_TAG;

				if(spare_block == (uint16)(-1))
				{
					spare_block = Pbn;
					BlockInfo.Status = BLOCK_ERASED;	
				}
				else 
				{
					/* All blocks !!MUST!! be in BLOCK_VALID state 
					 * except the spare block, which !!MUST!! be in 
					 * BLOCK_ERASED state. 
					 */
					BlockInfo.Status = BLOCK_VALID;
				}

				hw_status = DevWrite(pDev,
									 (uint8 *)&BlockInfo,
									 info_address,
									 sizeof(FsmBlockInfoT)
									 );

				if(hw_status != HW_ERR_NONE)
					return ERR_WRITE;

				BlockStatP[Pbn].EraseCount = BlockInfo.EraseCount;
			}
		}
	}

	if(spare_block == (uint16)(-1))
	{
		return ERR_FORMAT;
	}
	else
	{
		((FsmFlashMediaT *)(pDev->MediaObjP))->SpareBlk = spare_block;

		#ifdef DEBUG_FSM
		MonPrintf("Exit Interface DfsPlrScanBlock successfully!\n");
		#endif

		return ERR_NONE;
	}
}

/*#############################################################################
  ### DfsPlrScanSector
  ###
  ### DESCRIPTION:
  ###   Scan sectors one by one.Recover the sector in middle status.
  ###   Scan directory entries one by one.Recover the directory entry in middle 
  ###   status and its related sectors.
  ###   Designate sector for storing file root directory entries.
  ###	Designate sector for storing item root directory entries.
  ###	Establish Lsn2Psn map.
  ###   Statistic info about free, dirty, used sector number of every block.
  ###
  ### PARAMETERS:
  ###    IN:  pDev - poiter to designated FsmDevObjHdrT of data file system.
  ###	      block_size - flash block size.
  ###	      block_num - flash block number.
  ###    OUT: Lsn2Psn - lsn of valid sector has corresponding psn.
  ###	      UsedSectors, FreeSectors, DirtySectors - Statistic of BlockInfoT
  ###
  ### RETURNS:
  ###   If read operation is not successful, the function returns ERR_READ.
  ###	If write operation is not successful, the function returns ERR_WRITE.
  ###	If sector is found in irrelavant status, the function returns ERR_EXIST.
  ###	If designated sector is not found, the function returns ERR_NOTEXIST.
  ###	Otherwise, the function returns ERR_NONE.
  ###
 */

static uint32 DfsPlrScanSector(
	FsmDevObjHdrT *		pDev, 
	uint32			block_size, 
	uint32			block_num, 
	DfsPlrQueueT **	head, 
	uint32 *		Psn2LsnP
	)
{
	FsmBlockStatisticT *	BlockStatP;

	uint32 *	Lsn2PsnP;
	uint32		block_sectors;
	uint32		max_psn;
	uint32		sector_size;
	uint32		spare_blk;

	uint32		file_entries;
	uint32		item_entries;

	uint32		i;
	uint16		Pbn;
	uint32		Psn;
	uint32		Lsn;

	uint8		scan_end;

	uint16		sector_status;
	uint16		sector_status_msk;
	uint16		sector_type;

	uint16		entry_status;
	uint16		entry_status_msk;
	uint32		entry_firstlsn;

	DfsPlrQueueT * CurP;

	uint32		sector_address;
	uint32		entry_address;

	uint32		err_status;
	uint32		hw_status;

	DEV_WRITE_FUNCPTR	DevWrite = pDev->DevDrvP->FsmDevWrite;
	DEV_READ_FUNCPTR	DevRead  = pDev->DevDrvP->FsmDevRead;


	#ifdef DEBUG_FSM
	MonPrintf("Enter Interface DfsPlrScanSector!\n");
	#endif

	block_sectors = ((FsmFlashMediaT *)(pDev->MediaObjP))->SectorsPerBlock;
	sector_size   = ((FsmFlashMediaT *)(pDev->MediaObjP))->SectorSize;
	BlockStatP    = ((FsmFlashMediaT *)(pDev->MediaObjP))->BlockInfoP;
	Lsn2PsnP      = ((FsmFlashMediaT *)(pDev->MediaObjP))->Lsn2PsnP;
	max_psn       = ((FsmFlashMediaT *)(pDev->MediaObjP))->MaxPsn;
	spare_blk     = ((FsmFlashMediaT *)(pDev->MediaObjP))->SpareBlk;

	/* The maximum number of file entries in one sector. */	
	file_entries = sector_size / sizeof(FsmFileDirEntryT);

	/* The maximum number of item entries in one sector*/
	item_entries = sector_size / sizeof(FsmItemDirEntryT);

	/* scan sectors one by one.
	 * sectors in middle status will 
	 * be put into queue for future recovery.
	 */

	for(Pbn = 0; Pbn < block_num; Pbn++)
	{
		scan_end = 0;

		for(i = 0; i < block_sectors; i++)
		{
			Psn = Pbn * block_sectors + i;

			sector_address = DfsGetAddr2(Pbn, i, block_size, sector_size);

			hw_status = DevRead(pDev, 
							    (uint8 *)&sector_status, 
							    sector_address + FIELD_OFFSET(FsmFlashSectorHdrT, Status), 
							    FIELD_SIZE(FsmFlashSectorHdrT, Status)
							    );

			if(hw_status != HW_ERR_NONE)
				return ERR_READ;

			if((sector_status_msk = VALID_SECTOR_STATE(sector_status)) != 0)
			{
				sector_status = FIX_SECTOR_STATE(sector_status_msk, sector_status);

				hw_status = DevWrite(pDev, 
								     (uint8 *)&sector_status, 
									 sector_address + FIELD_OFFSET(FsmFlashSectorHdrT, Status), 
									 FIELD_SIZE(FsmFlashSectorHdrT, Status)
									 );

				if(hw_status != HW_ERR_NONE)
					return ERR_WRITE;

			}

			switch(sector_status)
			{
			case SECTOR_EMPTY:
				scan_end = 1;
				break;

			case SECTOR_UPDATING:
			case SECTOR_APPENDING:
			case SECTOR_ALLOCATED:
			case SECTOR_DELETING:
				#ifdef DEBUG_FSM
				MonPrintf("No.%d sector in No.%d block (psn = %d) is found in %x status!\n",
					i, Pbn, Psn, sector_status);
				#endif

				/* add a queue member. */
				err_status = AddQueue(Psn, sector_status, head);

				if(err_status != ERR_NONE)
				{
					#ifdef DEBUG_FSM
					MonPrintf("Memory allocation false when add a queue member!\n");
					#endif

					return ERR_SYSTEM;
				}

				/* write corresponding lsn to Psn2Lsn map. */
				hw_status = DevRead(pDev, 
									(uint8 *)&Lsn, 
									sector_address + FIELD_OFFSET(FsmFlashSectorHdrT, Lsn), 
									FIELD_SIZE(FsmFlashSectorHdrT, Lsn)
									);

				if(hw_status != HW_ERR_NONE)
					return ERR_READ;

				Psn2LsnP[Psn] = Lsn;

				break;

			case SECTOR_VALID:
				/* write corresponding lsn to Psn2Lsn map. */
				hw_status = DevRead(pDev, 
									(uint8 *)&Lsn, 
									sector_address + FIELD_OFFSET(FsmFlashSectorHdrT, Lsn), 
									FIELD_SIZE(FsmFlashSectorHdrT, Lsn)
									);

				if(hw_status != HW_ERR_NONE)
					return ERR_READ;

				Psn2LsnP[Psn] = Lsn;

				/* read sector type. */
				hw_status = DevRead(pDev, 
									(uint8 *)&sector_type, 
									sector_address + FIELD_OFFSET(FsmFlashSectorHdrT, Type), 
									FIELD_SIZE(FsmFlashSectorHdrT, Type)
									);

				if(hw_status != HW_ERR_NONE)
					return ERR_READ;

				if(sector_type == SECTOR_TYPE_MID)
				{
					/* recovers item in this sector. */
					err_status = DfsPlrSecMultiInstances(Psn, pDev, block_size, block_num);

					if(err_status != ERR_NONE)
						return err_status;
				}
				break;

			case SECTOR_INVALID:
				Psn2LsnP[Psn] = DIRTYLSN;
				break;

			case SECTOR_WRITING:
				/* Pass through. */

			default:
				#ifdef DEBUG_FSM
				MonPrintf("No.%d sector in No.%d block (psn = %d) is found in %x status!\n",
					i, Pbn, Psn, sector_status);
				#endif

				sector_status = SECTOR_INVALID;

				hw_status = DevWrite(pDev, 
									 (uint8 *)&sector_status, 
									 sector_address + FIELD_OFFSET(FsmFlashSectorHdrT, Status), 
									 FIELD_SIZE(FsmFlashSectorHdrT, Status)
									 );

				if(hw_status != HW_ERR_NONE)
					return ERR_WRITE;

				Psn2LsnP[Psn] = DIRTYLSN;

				break;
			}

			if(scan_end == 1)
				break;
		}
	}

	CurP = *head;

	while(CurP != NULL)
	{
		if(CurP->Status == SECTOR_UPDATING)
		{
			err_status = DfsPlrSecUpdating(CurP->Psn, Psn2LsnP, pDev, block_size, block_num);

			if(err_status != ERR_NONE)
				return err_status;
		}
		else if(CurP->Status == SECTOR_APPENDING)
		{
			sector_address = DfsGetAddr(CurP->Psn, (uint16)block_sectors, block_size, sector_size);

			hw_status = DevRead(pDev, 
								(uint8 *)&sector_type, 
								sector_address + FIELD_OFFSET(FsmFlashSectorHdrT, Type), 
								FIELD_SIZE(FsmFlashSectorHdrT, Type)
								);

			if(hw_status != HW_ERR_NONE)
				return ERR_READ;

			/* recover sectors containing directory entry and in SECTOR_APPENDING status. */
			if((sector_type == SECTOR_TYPE_FDE) || (sector_type == SECTOR_TYPE_IDE))
			{
				err_status = /*DfsPlrEntrySecAppending*/ DfsPlrSecAppending(CurP->Psn, Psn2LsnP, pDev, block_size, block_num);

				if(err_status != ERR_NONE)
					return err_status;
			}	
		}

		CurP = CurP->NextP;			
	}

	for(Psn = 0; Psn < max_psn; Psn++)
	{
		Lsn = Psn2LsnP[Psn];

		/* scan directory entries one by one in SECTOR_VALID sector. */
		if((Lsn == EMPTYLSN) || (Lsn == DIRTYLSN))
			continue;

		sector_address = DfsGetAddr(Psn, (uint16)block_sectors, block_size, sector_size);

		hw_status = DevRead(pDev,
							(uint8 *)&sector_type,
							sector_address + FIELD_OFFSET(FsmFlashSectorHdrT, Type),
							FIELD_SIZE(FsmFlashSectorHdrT, Type)
							);

		if(hw_status != HW_ERR_NONE)
			return ERR_READ;

		if(sector_type == SECTOR_TYPE_FDE)
		{
			hw_status = DevRead(pDev, 
								(uint8 *)&sector_status, 
								sector_address + FIELD_OFFSET(FsmFlashSectorHdrT, Status), 
								FIELD_SIZE(FsmFlashSectorHdrT, Status)
								);

			if(hw_status != HW_ERR_NONE)
				return ERR_READ;

			if(sector_status != SECTOR_VALID)
				continue;

			/* scan file entries one by one in this sector. */
			scan_end = 0;

			for(i = 0; i < file_entries; i++)
			{
				/* read entry status. */
				entry_address = sector_address + sizeof(FsmFlashSectorHdrT)
								+ i * sizeof(FsmFileDirEntryT);

				hw_status = DevRead(pDev,
									(uint8 *)&entry_status,
									entry_address + FIELD_OFFSET(FsmFileDirEntryT, Status),
									FIELD_SIZE(FsmFileDirEntryT, Status)
									);

				if(hw_status != HW_ERR_NONE)
					return ERR_READ;

				/* fix entry status to predefined value. */
				if((entry_status_msk = VALID_ENTRY_STATE(entry_status)) != 0)
				{
					entry_status = FIX_ENTRY_STATE(entry_status_msk, entry_status);

					hw_status = DevWrite(pDev, 
										 (uint8 *)&entry_status, 
										 entry_address + FIELD_OFFSET(FsmFileDirEntryT, Status), 
										 FIELD_SIZE(FsmFileDirEntryT, Status)
										 );

					if(hw_status != HW_ERR_NONE)
						return ERR_WRITE;
				}

				switch(entry_status)
				{
				case ENTRY_EMPTY:
					scan_end = 1;
					break;

				case ENTRY_ALLOCATED:
					hw_status = DevRead(pDev, 
										(uint8 *)&entry_firstlsn, 
										entry_address + FIELD_OFFSET(FsmFileDirEntryT, FirstLsn), 
										FIELD_SIZE(FsmFileDirEntryT, FirstLsn)
										);

					if(hw_status != HW_ERR_NONE)
						return ERR_READ;

					#ifdef DEBUG_FSM
					MonPrintf("File entry whose first lsn is %d is in "
						"ENTRY_ALLOCATED status in the No.%d entry of No.%d sector!\n",
						entry_firstlsn, i, Psn);
					#endif

					err_status = DfsPlrEntryAllocated(entry_firstlsn, 
													  Psn2LsnP, 
													  pDev, 
													  block_size, 
													  block_num
													  );

					if(err_status != ERR_NONE)
						return err_status;

					entry_status = ENTRY_VALID;

					hw_status = DevWrite(pDev, 
										 (uint8 *)&entry_status, 
										 entry_address + FIELD_OFFSET(FsmFileDirEntryT, Status), 
									  	 FIELD_SIZE(FsmFileDirEntryT, Status)
									  	 );

					if(hw_status != HW_ERR_NONE)
						return ERR_WRITE;

					break;

				case ENTRY_DELETING:
					hw_status = DevRead(pDev, 
										(uint8 *)&entry_firstlsn, 
										entry_address + FIELD_OFFSET(FsmFileDirEntryT, FirstLsn), 
										FIELD_SIZE(FsmFileDirEntryT, FirstLsn)
										);

					if(hw_status != HW_ERR_NONE)
						return ERR_READ;

					#ifdef DEBUG_FSM
					MonPrintf("File entry whose first lsn is %d is in"
						"ENTRY_DELETING status in the No.%d entry of No.%d sector!\n",
						entry_firstlsn, i, Psn);
					#endif

					err_status = DfsPlrEntryDeleting(entry_firstlsn, 
													 Psn, 
													 (uint16)i,
													 Psn2LsnP,
													 pDev, 
													 block_size, 
													 block_num
													 );

					if(err_status != ERR_NONE)
						return err_status;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -