📄 map.c
字号:
// erase_start cache always begins cleared to k_block_free
_media_data(erase_start)[(g_addr_zone?1:0)]=k_block_free;
// clear the logical2physical table
for( lb=0 ; lb < _media_data(logical_blocks_per_zone) ; lb++ )
_l2p_map[lb] = k_block_free ;
// clear out the physical block assignment table
for ( pb=0; pb < ( _media_data(physical_blocks_per_zone)/8); pb++ )
{
_a_map[pb]=0x00;
_e_map[pb]=0x00;
}
max_lb = g_addr_zone?_media_data(logical_blocks_per_zone):_media_data(logical_blocks_per_boot_zone);
trace1(0, map, 0, "max log_block this zone:%d", max_lb) ;
// populate the assignment map
for (g_addr_rd_phy_blk=0;g_addr_rd_phy_blk<_media_data(physical_blocks_per_zone);g_addr_rd_phy_blk++)
{
if( _media_is_phyblock_reserved() )
{
trace1(0, map, 0, "phy_blk %d: reserved", g_addr_rd_phy_blk) ;
// first zone, before CIS struct... in sm terms, nothing comes there
_map_phy_blk_used( _a_map, g_addr_rd_phy_blk ) ;
continue;
}
if(k_error == _media_read_extra_data() )
{
trace1(0, map, 0, "phy_blk %d: corrupt or bad extra data", g_addr_rd_phy_blk) ;
_map_phy_blk_used( _a_map, g_addr_rd_phy_blk ) ;
continue;
}
// skip bad block
if( !_media_is_phyblock_ok() )
{
trace1(0, map, 0, "phy_blk %d: user block not usable", g_addr_rd_phy_blk) ;
// treat block as if it is reserved... (i.e. mark it used, but do not add it to l2p table)
_map_phy_blk_used( _a_map, g_addr_rd_phy_blk ) ;
continue;
}
if( _media_is_phyblock_blank() )
{
trace1(0, map, 0, "phy_blk %d: blank", g_addr_rd_phy_blk) ;
continue;
}
// set the block used
_map_phy_blk_used( _a_map, g_addr_rd_phy_blk ) ;
// check for bad data status
bad_data=_media_block_has_bad_data();
if(bad_data)
{
trace1(0, map, 0, "phy_blk %d: contains pages with invalid data", g_addr_rd_phy_blk);
}
// call media to retrieve lb of current pb, or return a reason why it can't be done
if(k_error == _media_phy2log())
{
trace1(0, map, 0, "phy_blk %d: invalid log binding", g_addr_rd_phy_blk) ;
continue;
}
// block can be loaded. is block beyond max logical blocks?
if ( g_addr_log_blk >= max_lb )
{
trace1(0, map, 0, "phy_blk %d: log binding out of range", g_addr_log_blk) ;
continue;
}
// does log_block have a previously detected phy_block?
if (_l2p_map[g_addr_log_blk]==k_block_free)
{
trace2(0, map, 0, "phy_blk %d: log_blk %d", g_addr_rd_phy_blk, g_addr_log_blk);
_l2p_map[g_addr_log_blk] = g_addr_rd_phy_blk|(bad_data?kbm_map_blk_has_bad_data:0);
continue;
}
trace3(0, map, 0, "phy_blk %d: log_blk binding conflict. log_blk %d already mapped to phy_blk %d", g_addr_rd_phy_blk, g_addr_log_blk, (_l2p_map[g_addr_log_blk])) ;
// $$$ cds to do -> potential bug which could drop bad_data info here
// store the rd_phy_blk, and set up the resolver
pb = g_addr_rd_phy_blk ;
g_addr_wr_phy_blk = _l2p_map[g_addr_log_blk] ;
// g_addr_rd_phy_blk contains one of the bindings,
// g_addr_wr_phy_blk contains the original mapping
// call media specific resolver
_media_resolve_conflict();
// g_addr_rd_phy_blk should contain the correct mapping
// g_addr_wr_phy_blk should contain the block to be erased (or not used)
_l2p_map[g_addr_log_blk]=g_addr_rd_phy_blk ;
trace2(0, map, 0, "log_blk %d now mapped to phy_blk:%d", g_addr_log_blk, (_l2p_map[g_addr_log_blk])) ;
trace1(0, map, 0, "*** conflict resolution: Erase Block %d", g_addr_wr_phy_blk) ;
if( k_success == _media_erase_block() )
{
_clrbit( _a_map, g_addr_wr_phy_blk ) ;
}
// restore rd_phy_blk & sector
g_addr_rd_phy_blk = pb ;
g_addr_page=0;
g_addr_wr_phy_blk=k_block_free;
}
_media_data(assign_start)[g_addr_zone?1:0]=0;
TRACE0(303, media, 0, "sector map built") ;
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// map_alloc_wr_blk()
//
// Declaration:
// t_result map_alloc_wr_blk(void) reentrant ;
//
// Purpose:
// Physical Block Assign/Release Subroutine, ported from SMIL
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result map_alloc_wr_blk(void) reentrant
{
uint8 zone_idx ;
t_bool retry ;
trace0(0, map, 0, "map_alloc_wr_blk()") ;
// _stack_dump() ;
zone_idx = g_addr_zone?1:0 ;
_a_map = _assign_map(g_addr_zone) ;
retry=k_true;
while(retry)
{
trace1(0, map, 0, " starting search at phyblock %d", _media_data(assign_start)[zone_idx]) ;
for (g_addr_wr_phy_blk = _media_data(assign_start)[zone_idx] ;
g_addr_wr_phy_blk < _media_data(physical_blocks_per_zone) ;
g_addr_wr_phy_blk++ )
{
if ( _map_is_phy_blk_free(_a_map, g_addr_wr_phy_blk) )
{
_map_phy_blk_used(_a_map, g_addr_wr_phy_blk) ;
_media_data(assign_start)[zone_idx] = g_addr_wr_phy_blk + 1;
trace2(0, map, 0, "zone %d phy_blk %d allocated for writing", g_addr_zone, g_addr_wr_phy_blk) ;
return k_success ;
}
}
for (g_addr_wr_phy_blk = 0 ;
g_addr_wr_phy_blk < _media_data(assign_start)[zone_idx] ;
g_addr_wr_phy_blk++ )
{
if( _map_is_phy_blk_free(_a_map, g_addr_wr_phy_blk) )
{
_map_phy_blk_used(_a_map, g_addr_wr_phy_blk) ;
_media_data(assign_start)[zone_idx]=g_addr_wr_phy_blk+1;
trace2(0, map, 0, "zone %d phy_blk %d allocated for writing", g_addr_zone, g_addr_wr_phy_blk) ;
return k_success ;
}
}
trace0(0, map, 0, "error: no more available phyblocks in this zone! try to reclaim some 'bad' blocks") ;
#ifdef k_opt_erase_cache
if( _media_data(options)&kbm_media_data_opt_erase_cache)
{
if(!map_erase_cache_flush_one())
{
trace0(0, map, 0, "erase cache is empty... no blocks available in this zone!") ;
retry=k_false;
}
}
else
#endif
{
trace0(0, map, 0, "no blocks available in this zone!");
retry=k_false;
}
}
g_addr_wr_phy_blk = k_block_free ;
trace1(0, map, 0, "error: k_media_err_write_fault - no more phyblocks available in zone %d", g_addr_zone) ;
return k_error ;
}
//+-----------------------------------------------------------------------------
// Name:
// map_bind_wr_blk()
//
// Declaration:
// t_result map_release_read_block(void) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result map_bind_wr_blk(void) reentrant
{
trace0(0, map, 0, "map_bind_wr_blk()") ;
_l2p_map = _log_map(g_addr_zone) ;
_l2p_map[g_addr_log_blk] = g_addr_wr_phy_blk ;
trace3(0, map, 0, "zone:%d log_blk:%d bound to phy_blk:%d", g_addr_zone, g_addr_log_blk, g_addr_wr_phy_blk ) ;
// release the wr_phy_blk... it is no longer the write-block after the binding.
g_addr_wr_phy_blk = k_block_free ;
return k_success ;
}
//+-----------------------------------------------------------------------------
// Name:
// map_erase_rd_block()
//
// Declaration:
// t_result map_erase_block(void) reentrant ;
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result map_erase_rd_blk(void) reentrant
{
uint16 old_wr_blk ;
trace0(0, map, 0, "map_erase_rd_blk()") ;
// get log2phy mapping for the zone
_l2p_map = _log_map(g_addr_zone) ;
if(g_addr_rd_phy_blk==k_block_free)
{
trace0(0, map, 0, "rd_blk blank. not erasing") ;
// ensure that the log2phy map table is correctly marked 'free'
_l2p_map[g_addr_log_blk] = k_block_free ;
trace1(0, map, 0, "log block %d unbound", g_addr_log_blk) ;
}
else
{
trace1(0, map, 0, "unbinding rd phy block %d.", g_addr_rd_phy_blk);
// save wr_phy_block
old_wr_blk = g_addr_wr_phy_blk ;
// aim the wr_phy_block to the rd target
g_addr_wr_phy_blk = g_addr_rd_phy_blk&kbm_map_l2p_bits;
// check for soft binding.
if( !(_l2p_map[g_addr_log_blk]&kbm_map_soft_l2p_binding))
{
trace0(0, map, 0, "full binding: phy block needs erasing");
// to cache or not to cache
#ifdef k_opt_erase_cache
if(_media_data(options)&kbm_media_data_opt_erase_cache)
map_erase_block_cache();
else
#endif
map_erase_block();
}
else
{
trace1(0, map, 0, "rd phy blk %d has soft binding. not erasing", g_addr_rd_phy_blk) ;
_a_map=_assign_map(g_addr_zone);
_map_phy_blk_free(_a_map,g_addr_rd_phy_blk);
}
// block is erased, or will be. unbind it
_l2p_map[g_addr_log_blk] = k_block_free ;
g_addr_rd_phy_blk = k_block_free ;
// restore wr_phy_blk
g_addr_wr_phy_blk = old_wr_blk ;
}
return k_success ;
}
#if 0 // $$$ cds -> 242 code reduction
//+-----------------------------------------------------------------------------
// Name:
// map_erase_block()
//
// Declaration:
// t_result map_erase_block(void) reentrant ;
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result map_erase_wr_blk(void) reentrant
{
trace0(0, map, 0, "map_erase_wr_blk()") ;
if(g_addr_wr_phy_blk == k_block_free)
return k_success ;
_a_map = _assign_map(g_addr_zone) ;
_media_erase_block() ;
trace1(0, map, 0, "phy block %d erased", g_addr_wr_phy_blk) ;
_map_phy_blk_free( _a_map, g_addr_wr_phy_blk) ;
trace1(0, map, 0, "phy block %d set to 'free' in assign table", g_addr_wr_phy_blk) ;
g_addr_wr_phy_blk = k_block_free ;
return k_success ;
}
#endif // $$$ cds -> 242 code reduction
#if 0 // $$$ cds -> 242 code reduction
//+-----------------------------------------------------------------------------
// Name:
// map_reassign_block_head()
//
// Declaration:
// t_result map_reassign_block_head(void) reentrant ;
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result map_reassign_block_head(void) reentrant
{
#if 1
trace0(0, map, 0, "+map_reassign_block_head() - not implemented yet") ;
return k_error ;
#else
uint16 block;
uint8 page;
block=g_addr_rd_phy_blk ;
page=g_addr_page;
if (k_success != map_alloc_wr_blk())
return k_error ;
for (g_addr_page=0; g_addr_page<page; g_addr_page++)
{
if (k_success != media_copy_sector())
{
g_addr_page=page;
trace0(0, map, 0, "+map_reassign_block_head() failed") ;
return k_error ;
}
}
if (k_success != map_release_read_block())
return k_error ;
g_addr_rd_phy_blk=block;
g_addr_page=page;
return k_success;
#endif
}
#endif // $$$ cds -> 242 code reduction
//+-----------------------------------------------------------------------------
// Name:
// map_lba2addr_rd()
//
// Declaration:
// t_result sm_map_lba2phy(unsigned long addr) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
// fmc-1.0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -