📄 fsmplr.c
字号:
}
}
/* 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 *)§or_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 *)§or_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 *)§or_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 *)§or_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 *)§or_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 *)§or_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 *)§or_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 + -