📄 fdi_recl.c
字号:
* 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 */
SEM_MTX_POST(SEM_ReclaimInProg); /* Give the ReclaimInProg semaphore */
do
{
SEM_MTX_WAIT(SEM_ReclaimInProg); /* Take the ReclaimInProg semaphore*/
/* read the next unit header in the reclaim block */
errors = FlashDevRead((BYTE_PTR) & header,
Rip.reclaim_block_addr +
Rip.reclaim_header_offset,
sizeof(UNIT_HEADER));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30070000 */);
break;
}
if (!HDR_STATE(HDR_EMPTY, header.status))
{
/* IF the unit header status is valid */
if (!INVALID_HDR(header.status))
{
setBitMask(Rip.recl_header_mask,
(Rip.reclaim_header_offset / sizeof(UNIT_HEADER)));
/* save the reclaim block's unit offset */
reclaim_unit_offset = BOTTOM_OF_UNITS -
TO_BYTES(header.g_unit_offset_bottom);
/* reclaim unit size in bytes */
reclaim.unit_size = TO_BYTES(header.g_unit_size);
/* calculate location of unit in spare block */
spare_unit_offset -= (reclaim.unit_size);
/* copy spare_unit_offset into the unit header */
header.g_unit_offset_bottom = (WORD)((BOTTOM_OF_UNITS -
spare_unit_offset) / UNIT_GRANULARITY);
SEM_MTX_WAIT(SEM_WriteInProg); /* pend on writes in progress */
/* write the unit header fields to the spare block */
errors = FlashDevWrite((BYTE_PTR) & header,
Rip.spare_block_addr +
Rip.spare_header_offset,
sizeof(UNIT_HEADER));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30080000 */);
break;
}
/*
* copy the unit from the reclaim block to the spare block at
* the new unit_offset value
*/
errors = FlashDevCopy(Rip.spare_block_addr +
spare_unit_offset,
Rip.reclaim_block_addr +
reclaim_unit_offset,
reclaim.unit_size);
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30090000 */);
break;
}
#if (PACKET_DATA == TRUE)
if ((header.type_attribute & ATTRIBUTE_MASK) == ATTR_DATA_FRAG
&& header.identifier == FDI_Pckt.ID
&& (NIBBLE_HIGH(header.type_attribute)) == FDI_Pckt.type)
{
DWORD temp_new_address, temp_old_address;
/*
* compute out the physical addresses of the begining of the
* data fragments in reclaiming block and spare block
*/
temp_new_address = Rip.spare_block_addr + spare_unit_offset +
FLASH_START_ADDRESS;
temp_old_address = Rip.reclaim_block_addr +
reclaim_unit_offset +
FLASH_START_ADDRESS;
if (tag_index == WORDMAX) /* the first time need to scan */
tag_index = 0;
else
tag_index ++;
while (tag_index < FDI_Pckt.Count)
{
if (FDI_Pckt.TagRAMp[tag_index] ==
(WORD_PTR)temp_old_address)
break;
tag_index ++;
}
#ifdef TEST_MSGS
logMsg("\nTag-RAM UPDATED, tag-entry: %X, new-offset:%X",
tag_index, temp_new_address, 0, 0, 0, 0);
#endif /* TEST_MSGS */
if (tag_index < FDI_Pckt.Count) /* update the entry */
FDI_Pckt.TagRAMp[tag_index] = (WORD_PTR)temp_new_address;
else /* if no matched in Tag-RAM, report an error */
{
errors = HW_ERR_SYSTEM;
FDI_HandleError(errors);
break;
}
}
#endif /* PACKET_DATA */
SEM_MTX_POST(SEM_WriteInProg); /* finished blocking writes */
/* subt spare block's free space by unit header and unit_size */
Rip.spare_free -= (WORD) (sizeof(UNIT_HEADER) +
reclaim.unit_size);
/*
* increment spare block's unit header offset by sizeof unit
* header
*/
Rip.spare_header_offset += sizeof(UNIT_HEADER);
} /* ENDIF unit header status is valid */
/* inc reclaim block's unit header offset by sizeof unit header */
Rip.reclaim_header_offset += sizeof(UNIT_HEADER);
SEM_MTX_POST(SEM_ReclaimInProg);
} /* ENDIF header.status != HDR_EMPTY */
} while (!HDR_STATE(HDR_EMPTY, header.status));
/* ENDDO WHILE status != EMPTY */
if (errors != HW_ERR_NONE)
{
break;
}
/*
* We are done transferring valid unit headers and their associated data
* units Update the BLOCK_INFO fields of the spare block with
* information from the reclaim block
*/
/* read the reclaim block's block information */
errors = FlashDevRead((BYTE_PTR) & block_info,
Rip.reclaim_block_addr + BOTTOM_OF_UNITS,
sizeof(BLOCK_INFO));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x300b0000 */);
break;
}
/*
* write the physical block number of the reclaim block into the spare's
* block information physical_copy field
*/
errors = FlashDevWrite((BYTE_PTR) & RECL_ReclaimBlock,
Rip.spare_block_addr + BOTTOM_OF_UNITS +
offsetof(BLOCK_INFO, physical_copy),
mFDI_MemberSize(BLOCK_INFO, physical_copy));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -