📄 fdi_recl.c
字号:
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));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x300c0000 */);
break;
}
/*
* write the logical block number of the reclaim block into the spare's
* block information logical_block_number field
*/
errors = FlashDevWrite((BYTE_PTR)&block_info.logical_block_number,
Rip.spare_block_addr + BOTTOM_OF_UNITS +
offsetof(BLOCK_INFO, logical_block_number),
mFDI_MemberSize(BLOCK_INFO, logical_block_number));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x300d0000 */);
break;
}
/* if we are reclaiming a block because of wear leveling, we want to */
/* increment more than one because otherwise we could get into a */
/* situation where we are wear leveling often. Need to give space */
/* for natural wear leveling to begin again. */
if ((most_erased_count - block_info.erase_count) > WEARLEVELING_LIMIT)
block_info.erase_count += RECL_WEARLEVEL_DIFFERENTIAL;
else
block_info.erase_count++; /* increment the erase count before */
/*
* write the reclaim block's erase count into the spare's block
* information physical_erase_count field
*/
errors = FlashDevWrite((BYTE_PTR) & block_info.erase_count,
Rip.spare_block_addr + BOTTOM_OF_UNITS +
offsetof(BLOCK_INFO, physical_erase_count),
mFDI_MemberSize(BLOCK_INFO, physical_erase_count));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x300e0000 */);
break;
}
/*
* Prepare to erase the reclaim block by marking the spare block
* BLK_ERASING.
*/
/* write the spare block's block information status field to 'erasing' */
block.status = BLK_ERASING; /* set the status to 'erasing' */
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/* | 0x300f0000 */);
break;
}
/*
* NOTE!!!!: We will update the LogicalBlockTable here so that other
* processes can use the data in the spare block while the reclaim block
* is being erased....
*/
#if (CONSISTENT_ACCESS_TIME == TRUE)
/* wait for DLT access */
SEM_MTX_WAIT(SEM_LookupTable);
#endif
SEM_MTX_WAIT(SEM_BlockTable); /* wait for block table access */
#if (CONSISTENT_ACCESS_TIME == TRUE)
/* update DLT */
errors = FlashDevUpdateDLT(Rip.spare_block_addr);
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30150000 */);
break;
}
#endif
/*
* update the physical_block_number field of the FDI_LogicalBlockTable
* with the spare's physical block number
*/
FDI_LogicalBlockTable[this_blk.logical_block].physical_block_number =
FDI_SpareBlock;
/*
* update the free_space field of the FDI_LogicalBlockTable with spare's
* free space
*/
FDI_LogicalBlockTable[this_blk.logical_block].free_space = (Rip.spare_free /
sizeof(DWORD));
/* initialize the dirty_space field of the FDI_LogicalBlockTable */
FDI_LogicalBlockTable[this_blk.logical_block].dirty_space =
(Rip.spare_dirty / sizeof(DWORD));
/* Set the last_header_offset field of LBT */
SET_LAST_HEADER_OFFSET(this_blk.logical_block, Rip.spare_header_offset);
/*
* assign FDI_SpareBlock global variable to the reclaim block's physical
* block number
*/
FDI_SpareBlock = RECL_ReclaimBlock;
SEM_MTX_POST(SEM_BlockTable); /* finished with block table access */
#if (CONSISTENT_ACCESS_TIME == TRUE)
SEM_MTX_POST(SEM_LookupTable);
#endif
SEM_MTX_WAIT(SEM_WriteInProg); /* pend on writes in progress */
SEM_MTX_WAIT(SEM_OpenStream); /* Take the open stream semaphore */
for(index =0; index < OPEN_ARRAY_SIZE; index++)
{
if(FDI_OpenParam[index].identifier == WORDMAX)
continue;
RIP_OpenStreamUpdate(&FDI_OpenParam[index]);
}
SEM_MTX_POST(SEM_OpenStream); /* Give the open stream semaphore */
SEM_MTX_POST(SEM_WriteInProg); /* finished blocking writes */
RECL_SetState(RECL_ERASING); /* reclaim state flag */
/*
* reset these globals to keep the background from using them even when
* reclaim has finished.
*/
Rip.recl_in_prog_flag = FALSE; /* done with the copy phase */
reclaim_block_addr = Rip.reclaim_block_addr; /* save local copy */
Rip.reclaim_block_addr = DWORDMAX;
spare_block_addr = Rip.spare_block_addr; /* save local copy */
Rip.spare_block_addr = DWORDMAX;
Rip.reclaim_header_offset = FIRST_HEADER_OFFSET;
/*invalidate the reclaim block's integrity */
block_info.current_state = BLK_INTEGRITY_INVALID;
errors = FlashDevWrite((BYTE_PTR) & block_info.current_state,
reclaim_block_addr + BOTTOM_OF_UNITS +
offsetof(BLOCK_INFO, current_state),
sizeof(block_info.current_state));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30100000 */);
break;
}
SEM_MTX_POST(SEM_ReclaimInProg); /* finished blocking writes */
/* ERASE the reclaim block now.... ############################### */
errors = FlashDevEraseBlock(reclaim_block_addr);
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30110000 */);
break;
}
/* write spare block's block information status field to 'updating' */
block.status = BLK_UPDATING; /* set the status to 'updating' */
errors = FlashDevWrite(&block.status,
spare_block_addr + BOTTOM_OF_UNITS +
offsetof(BLOCK_INFO, status),
mFDI_MemberSize(BLOCK_INFO, status));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30120000 */);
break;
}
/*
* update the spare block erase count in the parameter where it is
* maintained
*/
errors = WriteData((BYTE_PTR) & block_info.erase_count, 0,
ERASE_COUNT_ID, sizeof(DWORD), ERASE_COUNT_TYPE,
WRITE_REPLACE);
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30130000 */);
break;
}
/* write the spare block's block information status field to 'write' */
block.status = BLK_WRITE; /* set the status to 'write' */
errors = FlashDevWrite(&block.status,
spare_block_addr + BOTTOM_OF_UNITS +
offsetof(BLOCK_INFO, status),
mFDI_MemberSize(BLOCK_INFO, status));
if (errors != HW_ERR_NONE)
{
FDI_HandleError(errors/* | 0x30140000 */);
break;
}
/* read the reclaim block's block information */
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -