📄 fdi_int.c
字号:
#if (INCLUDE_FRAGMENTED_DATA == TRUE)
/*
*############################################################################
*### ScanEntryTables
*###
*### DESCRIPTION:
*### Scans the group table to do necessary power loss recovery for the
*### sequence table unit headers refered to by it. The steps involved in
*### power loss recovery are the following.
*### 1.invalidate the old sequence table unit headers refered by the
*### physical index field of the group table entry
*### 2.invalidate all the old fragment unit headers refered by the
*### physical index and old_block_number fields of the sequence table entry,
*### and validate all the new fragment headers refered by the new sequence
*### table entries by calling the ScanSequenceTable function
*### 3.validate the new sequence table unit headers refered by the
*### the new group table entries
*###
*### PARAMETERS:
*### INPUT:
*### UNIT_HDR_PTR new_grp_hdr_ptr - pointer to the new group table's
*### UNIT_HEADER type
*### DWORD new_grp_hdr_addr - address of the new group table's unit header
*### WORD current_index
*### WORD index
*### BYTE seq_table_number
*###
*### OUTPUT:
*###
*### RETURNS:
*### ERR_NONE ERR_NOTEXISTS
*###
*/
/* E.5.0.652 Begin */
#if (PACKET_DATA == TRUE)
ERR_CODE
#else /* PACKET_DATA */
static ERR_CODE
#endif /* PACKET_DATA */
ScanEntryTables(UNIT_HEADER * new_tbl_hdr_ptr,
DWORD new_tbl_hdr_addr,
WORD current_index,
WORD index,
WORD seq_tbl_number)
/* E.5.0.652 End */
{
UNIT_HEADER unit_header_buffer;
DWORD block_address = 0;
DWORD new_tbl_addr = 0;
/*
* save the address of the first new sequence table entry with status
* SEQ_VALID_ENTRY. If its corresponding fragment unit header status
* is HDR_VALID_HDR, this entry will be marked SEQ_INVALID after all the
* other new sequence table entries are marked SEQ_INVALID, because if
* dual power loss happens, we need to know which sequence table entry
* is the first new one to do plr again.
*/
DWORD first_seq_tbl_entry_addr = DWORDMAX;
WORD unit_index = 0;
WORD tbl_index;
WORD ENTRY_TABLE_size;
ENTRY_TABLE new_tbl_buff;
WORD block_index = 0;
WORD data_instance = 0;
ERR_CODE status = ERR_NONE;
HW_ERROR hw_status = HW_ERR_NONE;
/*
* this flag will be set to TRUE when the status of the first new sequence
* table entry's corresponding fragment is HDR_VALID_HDR. When it is TRUE,
* it indicates that all the data hasn't been written, if we find any
* fragment with status HDR_ALLOCATED for this data, it will be
* invalidated then.
*/
BYTE invalidate_flag = FALSE;
/* valid group entry number */
WORD grp_entry_number = 0;
/* bump_seq_addr will be set to FALSE only if there are any
intermediate states found. */
BYTE bump_seq_addr;
BYTE entry_state_mask;
WORD header_state_mask;
/* Calculate the actual address of the new group table unit. */
new_tbl_addr = ((new_tbl_hdr_addr / FDV_BLOCK_SIZE) * FDV_BLOCK_SIZE) +
((FDV_BLOCK_SIZE - sizeof(BLOCK_INFO)) -
TO_BYTES(new_tbl_hdr_ptr->g_unit_offset_bottom));
/*
* At this point the seq table unit header will be marked either valid or
* allocated. If not returns an error.
*/
ENTRY_TABLE_size = TO_BYTES(new_tbl_hdr_ptr->g_unit_size);
tbl_index = 0;
/* if header status is HDR_ALLOCATED, check all entries */
if (new_tbl_hdr_ptr->status != HDR_VALID)
{
/* Until done scanning the entry table, */
do
{
/* Read one new entry table information. */
hw_status = FlashDevRead((BYTE_PTR) & new_tbl_buff, (new_tbl_addr +
(tbl_index * sizeof(ENTRY_TABLE))),
sizeof(ENTRY_TABLE));
if (hw_status != HW_ERR_NONE)
{
return ERR_READ;
}
/* Exit if the end of the entry table has been reached. */
if (new_tbl_buff.entry_status == SEQ_EMPTY)
{
break;
}
/*
* If the new table entry has a valid physical index value
*/
if (new_tbl_buff.physical_index != WORDMAX)
{
/* Validate the block_number and old_entry_block fields to check
that they are within the valid range for logical block numbers
in this configuration
*/
if (!VALID_BLOCK_RANGE(new_tbl_buff.old_entry_block) ||
!VALID_BLOCK_RANGE(new_tbl_buff.block_number))
return ERR_FORMAT;
/*
* invalidate the table unit header refered by the physical index
* field of the table entry.
*/
block_index = FDI_LogicalBlockTable[new_tbl_buff.old_entry_block].
physical_block_number;
block_address = BLOCK_ADDRESS(block_index);
/*
* Read the unit header information of the header refered to by
* the physical_index and old_block_number fields.
*/
hw_status = FlashDevRead((BYTE_PTR) & unit_header_buffer,
(block_address + FIRST_HEADER_OFFSET +
(new_tbl_buff.physical_index *
sizeof(UNIT_HEADER))),
sizeof(UNIT_HEADER));
if (hw_status != HW_ERR_NONE)
{
return ERR_READ;
}
if(CheckAddr((block_address + FIRST_HEADER_OFFSET +
(new_tbl_buff.physical_index * sizeof(UNIT_HEADER))),
current_index, index) == BYTEMAX)
unit_header_buffer.g_unit_size = WORDMAX;
/* Invalidate the table unit header. */
status =
WriteUnitHeaderStatus((block_address + FIRST_HEADER_OFFSET +
(new_tbl_buff.physical_index *
sizeof(UNIT_HEADER))), HDR_INVALID,
unit_header_buffer.status,
unit_header_buffer.g_unit_size, 1);
mDEBUG_CHECK_ERRCODE(status)
if (status != ERR_NONE)
return ERR_WRITE;
} /* ENDIF physical_index != WORDMAX */
/* skip to next table entry. */
tbl_index++;
ENTRY_TABLE_size -= sizeof(ENTRY_TABLE);
} while (ENTRY_TABLE_size >= sizeof(ENTRY_TABLE));
} /* ENDIF new_tbl_hdr_ptr->status != HDR_VALID */
/*
* At this point the seq table unit header will be marked either valid or
* allocated. If not returns an error.
*/
ENTRY_TABLE_size = TO_BYTES(new_tbl_hdr_ptr->g_unit_size);
tbl_index = 0;
/* Until done scanning the table, */
do
{
bump_seq_addr = TRUE;
/* Read one new table entry information. */
hw_status = FlashDevRead((BYTE_PTR) & new_tbl_buff, (new_tbl_addr +
(tbl_index * sizeof(ENTRY_TABLE))),
sizeof(ENTRY_TABLE));
if (hw_status != HW_ERR_NONE)
{
return ERR_READ;
}
/* Exit if the end of the table has been reached. */
if (new_tbl_buff.entry_status == SEQ_EMPTY)
break;
/*
* IF the entry status is marked GRP_VALID_ENTRY or GRP_VALID, find the
* table unit header associated with the table entry.
*/
else if ((new_tbl_buff.entry_status == GRP_VALID) ||
(new_tbl_buff.entry_status == GRP_VALID_ENTRY))
{
if((first_seq_tbl_entry_addr == DWORDMAX) &&
(new_tbl_buff.entry_status == GRP_VALID_ENTRY))
{
/*
* save the address of the first new table entry
* with status GRP_VALID_ENTRY
*/
first_seq_tbl_entry_addr = new_tbl_addr +
(tbl_index * sizeof(ENTRY_TABLE));
}
unit_index = 0; /* initialize loop counter variables. */
/* Validate the block_number field to check that
it is within the valid range for logical block numbers in this
configuration
*/
if(!VALID_BLOCK_RANGE(new_tbl_buff.block_number))
return ERR_FORMAT;
block_index = FDI_LogicalBlockTable[new_tbl_buff.block_number].
physical_block_number;
block_address = BLOCK_ADDRESS(block_index);
data_instance = new_tbl_buff.entry_instance;
/*
* Until proper instance of the table entry is found, or until no more
* unit header exists, read each unit header at the beginning of the
* block address.
*/
do
{
/*
* Read the unit header information of the refered unit.
*/
hw_status = FlashDevRead((BYTE_PTR) & unit_header_buffer,
block_address + FIRST_HEADER_OFFSET +
(unit_index * sizeof(UNIT_HEADER)),
sizeof(UNIT_HEADER));
if (hw_status != HW_ERR_NONE)
{
return ERR_READ;
}
/* check to see if we are in any intermediate states. If we
are, then correct for them */
if ((header_state_mask =
HDR_INTERMEDIATE(unit_header_buffer.status)) != 0)
{
#ifdef TEST_MSGS
logMsg("Intermediate header status found in ScanEntryTables(), \
0x%X\n", unit_header_buffer.status,0,0,0,0,0);
#endif
/* Determine mask needed to push out of intermediate state */
unit_header_buffer.status = HDR_FIX_INTERMEDIATE
(header_state_mask, unit_header_buffer.status);
hw_status = FlashDevWrite((BYTE_PTR) &unit_header_buffer.status,
block_address + FIRST_HEADER_OFFSET +
(unit_index * sizeof(UNIT_HEADER)) +
offsetof(UNIT_HEADER, status),
sizeof(unit_header_buffer.status));
if (hw_status != HW_ERR_NONE)
{
mDEBUG_CHECK_ERRCODE(hw_status)
return ERR_WRITE;
}
}
/*
* Look for matching identifier and type and the
* attribute seq table if group table is being scanned and
* attribute fragment if seq table is being scanned,
* to determine when we have reached the appropriate instance.
*/
if ((unit_header_buffer.identifier ==
new_tbl_hdr_ptr->identifier) &&
(NIBBLE_HIGH(unit_header_buffer.type_attribute) ==
NIBBLE_HIGH(new_tbl_hdr_ptr->type_attribute)) &&
(((unit_header_buffer.table_number == seq_tbl_number) &&
(((unit_header_buffer.type_attribute & ATTRIBUTE_MASK) ==
ATTR_DATA_FRAG) ||
((unit_header_buffer.type_attribute & ATTRIBUTE_MASK) ==
ATTR_SINGL_INST)) &&
((new_tbl_hdr_ptr->type_attribute & ATTRIBUTE_MASK) ==
ATTR_SEQ_TABLE)) ||
(((unit_header_buffer.type_attribute & ATTRIBUTE_MASK) ==
ATTR_SEQ_TABLE) &&
((new_tbl_hdr_ptr->type_attribute & ATTRIBUTE_MASK) ==
ATTR_GRP_TABLE))
) && (!INVALID_HDR(unit_header_buffer.status)))
{
/* E.5.3.877 Start */
/*
* if the table status is valid, finding the appropriate instance will
* count the 'invalidating' units since they belong to this valid table,
* but for 'allocated' table, should not count the 'invalidating' units,
* because all sub-units of allocated table should not be 'invalidating'
* status
*/
if ((new_tbl_hdr_ptr->status == HDR_VALID) ||
((new_tbl_hdr_ptr->status == HDR_ALLOCATED) &&
(!HDR_STATE(HDR_INVALIDATING, unit_header_buffer.status))))
{
data_instance--; /* decrment the instance counter */
}
/* E.5.3.877 End */
/* If matching instance found, */
if (data_instance == 0)
{
switch (unit_header_buffer.status)
{
case HDR_VALID:
if ((new_tbl_hdr_ptr->type_attribute &
ATTRIBUTE_MASK) == ATTR_GRP_TABLE)
{
/* mark group table entry GRP_VALID */
if ((status = ScanEntryTables(&unit_header_buffer,
block_address + FIRST_HEADER_OFFSET +
(unit_index * sizeof(UNIT_HEADER)),
current_index,
index, grp_entry_number)) != ERR_NONE)
{
break;
}
grp_entry_number++;
}
else if ((unit_header_buffer.type_attribute &
ATTRIBUTE_MASK) != ATTR_DATA_FRAG)
{
/*
* Convert to ATTR_DATA_FRAG
*/
unit_header_buffer.type_attribute =
BYTEMASK(NIBBLE_HIGH(
unit_header_buffer.type_attribute),
ATTR_DATA_FRAG);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -