📄 fdi_recl.c
字号:
DWORD spare_unit_offset; /* offset to spare block unit */
DWORD reclaim_unit_offset; /* offset to reclaim block unit */
union this_block
{
WORD physical_block; /* physical reclaim block number */
WORD logical_block; /* logical reclaim block number */
} this_blk;
union bytes
{
WORD logical; /* logical block loop counter */
BYTE status; /* power off recovery status field */
WORD physical; /* physical block loop counter */
DWORD actual; /* the actual size data read */
WORD state; /* */
} block;
#if (DATA_STREAM == TRUE)
BYTE streaming_in_prog = FALSE;
#endif
HW_ERROR errors = HW_ERR_NONE;
#if (PACKET_DATA == TRUE)
WORD tag_index;
#endif /* PACKET_DATA */
this_blk.physical_block = 0;
Rip.recl_in_prog_flag = FALSE;
MemorySet(Rip.recl_header_mask, 0, HDR_MASK_SIZE);
Rip.reclaim_block_addr = DWORDMAX;
Rip.spare_block_addr = DWORDMAX;
Rip.reclaim_header_offset = FIRST_HEADER_OFFSET;
Rip.spare_header_offset = FIRST_HEADER_OFFSET;
Rip.spare_free = 0;
Rip.spare_dirty = 0;
RECL_SetState(RECL_DONE); /* initialize state flag */
for(;;) /* DO FOREVER */
{
/* Wait for ReclaimEnable semaphore to become unlocked */
SEM_WAIT(RECL_Enable);
#ifdef TIMING
/* Get timestamp for start of update */
COMM_getTimestamp(&RECL_Start);
#endif
/*
* Lock the ReclaimDone semaphore for the background task to know that
* the reclamation is in progress.
*/
SEM_TRY_WAIT(RECL_Done);
RECL_SetState(RECL_ENABLED); /* state flag */
/* Determine the reclaim block candidate and determine the spare block */
least_erased_count = DWORDMAX; /* initialize the least erased count */
most_erased_count = 0; /* initialize the most erased count */
reclaim.this_count = 0;
/* assign reclaim_addr to the first data block's first address */
reclaim_block_addr = FDV_RELATIVE_ADDRESS;
/* DO FOR each physical block */
for (block.physical = 0;
block.physical < FDV_BLOCKCOUNT;
block.physical++)
{
/* IF this block is the spare THEN continue to the next block */
if (block.physical == FDI_SpareBlock)
{
/* increment to the next block */
reclaim_block_addr += FDV_BLOCK_SIZE;
continue;
}
/* read the erase_count field of BLOCK_INFO for this block */
errors = FlashDevRead((BYTE_PTR) & block_info,
reclaim_block_addr + BOTTOM_OF_UNITS,
sizeof(BLOCK_INFO));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors);
break;
}
/*
* IF this block's current status is okay THEN save the block's erase
* count
*/
if (block_info.current_state == BLOCK_INTEGRITY)
{
/* save the block's erase count */
reclaim.this_count = block_info.erase_count;
}
/* there is a format problem with this block; return error. */
else
{
errors = HW_ERR_READ;
FDI_HandleError(errors);
break;
} /* ENDELSE block's totally erased */
/* IF the block's erase count < least erased block count */
if (reclaim.this_count < least_erased_count)
{
/* assign least erased block count to the block's erase count */
least_erased_count = reclaim.this_count;
/* save the physical block number of the least_erased_count */
this_blk.physical_block = block.physical;
} /* ENDIF < least_erased_count */
/* IF the block's erase count > most erased block count */
if (reclaim.this_count > most_erased_count)
{
/* assign the most erased block count to the block's erase count */
most_erased_count = reclaim.this_count;
} /* ENDIF > most_erased_count */
/* increment to the next block */
reclaim_block_addr += FDV_BLOCK_SIZE;
} /* ENDDO FOR each block */
if (errors != HW_ERR_NONE)
break;
#if (DATA_STREAM == TRUE) /* wearleveling while data stream is set */
/* can not take the SEM_OpenStream semaphore without effecting
* data streaming throughput */
/* if FDI_OpenParam is in use set the flag true, else false */
/*If "this_blk.open_flag" is set then that invalidates the "this_blk.physical_block */
/*this_blk.open_flag = ((FDI_OpenParam.identifier != WORDMAX) &&
(FDI_OpenParam.data_streaming == FALSE)) ?
TRUE : FALSE;
*/
/*
* IF FDI_OpenParam is not in use and the difference between the least
* erased count and the most erased count is < the wear leveling limit
*/
if((most_erased_count - least_erased_count ) > WEARLEVELING_LIMIT)
{
streaming_in_prog = FALSE;
for(index =0; index < OPEN_ARRAY_SIZE; index++)
{
if ((FDI_OpenParam[index].identifier != WORDMAX) &&
(FDI_OpenParam[index].data_streaming == FALSE))
{
streaming_in_prog = TRUE;
break;
}
}
}
if(((most_erased_count - least_erased_count ) > WEARLEVELING_LIMIT) &&
(streaming_in_prog == FALSE))
#else /* !DATA_STREAM */
/*
* IF the difference between the least erased count and the most erased
* count is < the wear leveling limit
*/
if ((most_erased_count - least_erased_count) > WEARLEVELING_LIMIT)
#endif /* DATA_STREAM */
{
/* assign the reclaim block number to be the least erased block */
RECL_ReclaimBlock = this_blk.physical_block;
SEM_MTX_WAIT(SEM_BlockTable); /* wait for block table access */
for (block.logical = 0; block.logical < MAX_DATA_BLOCKS;
block.logical++)
{
if (FDI_LogicalBlockTable[block.logical].physical_block_number ==
RECL_ReclaimBlock)
{
this_blk.logical_block = block.logical;
break;
}
}
SEM_MTX_POST(SEM_BlockTable);
#ifdef TEST_MSGS
logMsg("WEARLEVELING LIMIT REACHED, least %d, most %d, reclaim %d\n",
(WORD) least_erased_count, (WORD) most_erased_count,
RECL_ReclaimBlock, 0, 0, 0);
#endif /* TEST_MSGS */
}
/* ELSE did not meet the WEARLEVELING_LIMIT value */
else
{
/* initialize the dirtiest block count to ZERO */
reclaim.this_count = 0;
this_blk.logical_block = 0;
SEM_MTX_WAIT(SEM_BlockTable); /* wait for block table access */
RECL_ReclaimBlock = FDI_LogicalBlockTable[0].physical_block_number;
/* DO FOR each block in logical block table */
for (block.logical = 0; block.logical < MAX_DATA_BLOCKS;
block.logical++)
{
/*
* read the dirty space field in the logical block table IF the
* dirty space > the dirtiest block count THEN assign the dirtiest
* count to the block's dirty_space and assign the
* RECL_ReclaimBlock to the physical block number
*/
#if (DATA_STREAM == TRUE)
if ((FDI_LogicalBlockTable[block.logical].dirty_space != 0) &&
(reclaim.this_count <
FDI_LogicalBlockTable[block.logical].dirty_space))
{
reclaim.this_count =
FDI_LogicalBlockTable[block.logical].dirty_space;
RECL_ReclaimBlock =
FDI_LogicalBlockTable[block.logical].physical_block_number;
/* save the reclaim block's logical block number */
this_blk.logical_block = block.logical;
} /* ENDIF count > dirty_space */
#else
if ((FDI_LogicalBlockTable[block.logical].dirty_space != 0) &&
(reclaim.this_count <
(FDI_LogicalBlockTable[block.logical].dirty_space +
FDI_LogicalBlockTable[block.logical].free_space)))
{
reclaim.this_count =
FDI_LogicalBlockTable[block.logical].free_space +
FDI_LogicalBlockTable[block.logical].dirty_space;
RECL_ReclaimBlock =
FDI_LogicalBlockTable[block.logical].physical_block_number;
/* save the reclaim block's logical block number */
this_blk.logical_block = block.logical;
} /* ENDIF count > dirty_space */
#endif
} /* ENDDO FOR each logical block */
SEM_MTX_POST(SEM_BlockTable); /* finished with block table access */
} /* #ENDIF WEARLEVELING not enabled */
/*
* We now have the first addresses of the reclaim block and the spare
* block
*/
/* Check to make sure a reclaim really needs to occur. If not, state */
/* reclaim done and return */
if (((most_erased_count - least_erased_count) < WEARLEVELING_LIMIT) &&
(reclaim.this_count == 0))
{
#ifdef TEST_MSGS
logMsg("reclaim done, Nothing to reclaim\n", 0, 0, 0, 0, 0, 0);
#endif
RECL_ReclaimBlock = WORDMAX;
RECL_SetState(RECL_DONE);
SEM_POST(RECL_Done);
continue;
}
SEM_MTX_WAIT(SEM_ReclaimInProg); /* Take the ReclaimInProg semaphore */
/* assign reclaim_addr the first address of the RECL_ReclaimBlock */
Rip.reclaim_block_addr = BLOCK_ADDRESS(RECL_ReclaimBlock);
/* assign spare_addr the first address of the FDI_SpareBlock */
Rip.spare_block_addr = BLOCK_ADDRESS(FDI_SpareBlock);
RECL_SetState(RECL_BLK_FOUND); /* state flag */
/* write the spare block's block information status field to 'recover' */
block.status = BLK_RECOVER; /* set the status to 'recover' */
errors = FlashDevWrite(&block.status,
Rip.spare_block_addr + BOTTOM_OF_UNITS +
offsetof(BLOCK_INFO, status),
mFDI_MemberSize(BLOCK_INFO, status));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30030000 */);
break;
}
RECL_SetState(RECL_RECOVERING); /* state flag */
/* Write BLOCK_INTEGRITY word to the last address in the spare block */
/* write the spare block's block information current_state field */
block.state = BLOCK_INTEGRITY; /* set the current_state */
errors = FlashDevWrite((BYTE_PTR) & block.state,
Rip.spare_block_addr + BOTTOM_OF_UNITS +
offsetof(BLOCK_INFO, current_state),
mFDI_MemberSize(BLOCK_INFO, current_state));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30040000 */);
break;
}
/*
* Read the erase count from the parameter system and write this to the
* spare block's erase count field in BLOCK_INFO
*/
/*
* read the erase_count of the spare block as data identifier
* NUM_IDENTIFIERS, increment the erase_count and then write into the
* block information structure.
*/
errors = ReadModify((BYTE_PTR) & reclaim.this_count,
(DWORD_PTR)&block.actual, 0, sizeof(DWORD), ERASE_COUNT_ID,
ERASE_COUNT_TYPE, 1, READ_DATA);
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30050000 */);
break;
}
errors = FlashDevWrite((BYTE_PTR) & reclaim.this_count,
Rip.spare_block_addr + BOTTOM_OF_UNITS +
offsetof(BLOCK_INFO, erase_count),
mFDI_MemberSize(BLOCK_INFO, erase_count));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30060000 */);
break;
}
/*
* initialize spare_free to sizeof the block minus the size of the block
* information structure
*/
Rip.spare_free = ((BOTTOM_OF_UNITS - sizeof(UNIT_HEADER)) -
FIRST_HEADER_OFFSET);
Rip.spare_dirty = 0;
/* reset the recl_header_mask to zeros */
MemorySet(Rip.recl_header_mask, 0, HDR_MASK_SIZE);
/* initialize spare_header_offset and reclaim_header_offset to zero */
Rip.reclaim_header_offset = FIRST_HEADER_OFFSET;
Rip.spare_header_offset = FIRST_HEADER_OFFSET;
reclaim_unit_offset = 0;
/*
* initialize spare_unit_offset to block size - sizeof the block
* information structure
*/
spare_unit_offset = BOTTOM_OF_UNITS;
/*
* Scan through each unit header in the reclaim block and transfer only
* the valid headers and units to the spare block
*/
Rip.recl_in_prog_flag = TRUE;
/*
* DO WHILE there are unit headers to read, copy only valid headers from
* the reclaim block to the spare
*/
#if (PACKET_DATA == TRUE)
tag_index = WORDMAX; /* initialization */
#endif /* PACKET_DATA */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -