📄 map.c
字号:
trace1(0, cache, 0, "erase cache zone %d: empty->not_empty", g_addr_zone) ;
_media_data(erase_start)[zone_idx]=g_addr_wr_phy_blk;
}
_map_phy_blk_used(_e_map, g_addr_wr_phy_blk) ;
g_addr_wr_phy_blk=k_block_free;
return k_true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// should only be called by internal functions...
void erase_cache_flush_one() reentrant
{
uint8 zone_idx ;
trace1(0, cache, 0, "erase_cache_flush_one(). zone:%d", g_addr_zone) ;
// _stack_dump();
zone_idx= g_addr_zone?1:0 ;
if(_media_data(erase_start)[zone_idx]==k_block_free)
{
trace0(0, cache, 0, "erase cache is empty... scroll through again, just in case, though") ;
_media_data(erase_start)[zone_idx]=0;
}
_e_map=_erase_cache(g_addr_zone) ;
trace1(0, map, 0, " searching cache... starting at %d", _media_data(erase_start)[zone_idx]) ;
for (g_addr_wr_phy_blk=_media_data(erase_start)[zone_idx];g_addr_wr_phy_blk<_media_data(physical_blocks_per_zone);g_addr_wr_phy_blk++)
{
if ( _map_is_phy_blk_used(_e_map, g_addr_wr_phy_blk) )
{
trace2(0, cache, 0, "erase cache: erasing phy %d:%d", g_addr_zone, g_addr_wr_phy_blk) ;
map_erase_block();
_map_phy_blk_free(_e_map, g_addr_wr_phy_blk) ;
_media_data(erase_start)[zone_idx]=g_addr_wr_phy_blk+1;
return ;
}
}
for (g_addr_wr_phy_blk=0;g_addr_wr_phy_blk<_media_data(erase_start)[zone_idx];g_addr_wr_phy_blk++ )
{
if( _map_is_phy_blk_used(_e_map, g_addr_wr_phy_blk) )
{
trace2(0, cache, 0, "erase cache: erasing phy %d:%d", g_addr_zone, g_addr_wr_phy_blk) ;
map_erase_block();
_map_phy_blk_free(_e_map, g_addr_wr_phy_blk) ;
_media_data(erase_start)[zone_idx]=g_addr_wr_phy_blk+1;
return ;
}
}
trace1(0, map, 0, "erase cache zone %d: not_empty->empty detected", g_addr_zone) ;
_media_data(erase_start)[zone_idx]=k_block_free;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// can be called from anywhere
xdata uint8 _ec_prev_zone;
xdata uint16 _ec_prev_blk;
t_result map_erase_cache_flush_one() reentrant
{
uint8 i=k_erase_cnt;
_ec_prev_blk=g_addr_wr_phy_blk;
// _stack_dump();
// zone_idx=g_addr_zone?1:0;
if( _media_data(erase_start)[(g_addr_zone?1:0)]==k_block_free)
{
trace0(0, cache, 0, "erase cache: zone %d erase cache is empty.") ;
return k_false;
}
while(i--)
{
erase_cache_flush_one();
}
g_addr_wr_phy_blk=_ec_prev_blk;
return k_true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result map_erase_cache_flush_zone(uint8 zone) reentrant
{
_ec_prev_zone = g_addr_zone;
_ec_prev_blk = g_addr_wr_phy_blk;
g_addr_zone=zone?_media_data(assign_zone):0;
trace1(0, cache, 0, "map_erase_cache_flush_zone(zone:%d)", g_addr_zone)
while(!_is_erase_cache_empty(g_addr_zone))
erase_cache_flush_one();
g_addr_zone=_ec_prev_zone;
g_addr_wr_phy_blk=_ec_prev_blk;
return k_success;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// assumes g_addr_zone has been set now
t_result map_erase_cache_flush_all() reentrant
{
trace0(0, cache, 0, "map_erase_cache_flush_all()");
//_stack_dump();
// flush boot zone
map_erase_cache_flush_zone(0) ;
// flush paged zone
if(_media_data(assign_zone))
map_erase_cache_flush_zone(_media_data(assign_zone));
return k_success;
}
#endif
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result map_rebind_log_blk() reentrant
{
uint8 bad_data;
uint16 blk;
trace4(0, map, 0, "map_rebind_log_blk(). updating log binding %d:%d. old phy_blk:%d new phy_blk:%d", g_addr_zone, g_addr_log_blk, g_addr_rd_phy_blk, g_addr_wr_phy_blk);
bad_data=map_log_blk_has_bad_data();
if (k_success != map_erase_rd_blk() )
{
trace0(0, map, 0, "mapper error erasing rd block") ;
return k_error;
}
blk=g_addr_wr_phy_blk;
if(k_success != map_bind_wr_blk())
{
trace0(0, map, 0, "mapper error binding wr block") ;
return k_error;
}
if(bad_data)
{
trace0(0, map, 0, "old binding had a bad data page. check the new binding to see if it carried over");
_l2p_map=_log_map(g_addr_zone);
g_addr_rd_phy_blk=_l2p_map[g_addr_log_blk]&kbm_map_l2p_bits;
trace2(0, map, 0, "checking read phyblk %d (old wr_phy_blk:%d)", g_addr_rd_phy_blk, g_addr_wr_phy_blk);
// there was a bad block on the old phy blk. check to see if there is one there now
if(_media_block_has_bad_data())
{
trace2(0, map, 0, "log blk %d (phy blk %d) has bad data page", g_addr_log_blk, g_addr_rd_phy_blk);
_l2p_map[g_addr_log_blk]|=kbm_map_blk_has_bad_data;
}
g_addr_rd_phy_blk=k_block_free;
}
return k_success;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result map_copy_block_tail() reentrant
{
t_result result;
trace0(0, map, 0, "map_copy_block_tail()");
result=media_copy_block_tail();
if (k_success != result)
{
if(k_media_copy_error_src==result)
{
uint16 old_wr_phy_blk;
trace2(0, map, 0, "failure reading from source block %d:%d. setting phyblock failed", g_addr_zone, g_addr_rd_phy_blk) ;
old_wr_phy_blk=g_addr_wr_phy_blk;
g_addr_wr_phy_blk=g_addr_rd_phy_blk;
_media_set_phyblock_failed();
g_addr_wr_phy_blk=old_wr_phy_blk;
// switch the logical binding on the read block to "soft-binding" so that it's not erased
_l2p_map = _log_map(g_addr_zone);
_l2p_map[g_addr_log_blk]|=kbm_map_soft_l2p_binding|kbm_map_blk_has_bad_data;
trace2(0, map, 0, "block %d:%d now soft bound, and marked having bad binding", g_addr_zone, g_addr_rd_phy_blk);
// no need to report a write failure, since the error occured on non-user data.
}
else
{
trace0(0, map, 0, "unrecoverable copy error. erasing write block reporting error") ;
map_erase_block() ;
return k_error;
}
}
// else status was good
result=map_rebind_log_blk();
if (k_success!=result)
{
trace0(0, map, 0, "mapper error when rebinding log blk from rd_blk to wr_blk") ;
return k_error;
}
return result;
}
#ifdef k_enable_write_caching
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void map_write_cache_get_tail() reentrant
{
g_addr_log_blk =g_wr_cache_tail_log;
g_addr_rd_phy_blk=g_wr_cache_tail_src;
g_addr_wr_phy_blk=g_wr_cache_tail_dst;
g_addr_page =g_wr_cache_tail_page;
g_addr_zone =g_wr_cache_tail_zone;
trace5(0, map, 0, "write cache: get tail from cache: zone:%d log:%d src:%d dst:%d page:%d", g_wr_cache_tail_zone, g_wr_cache_tail_log, g_wr_cache_tail_src, g_wr_cache_tail_dst, g_wr_cache_tail_page) ;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void map_write_cache_set_tail() reentrant
{
g_wr_cache_tail_log=g_addr_log_blk;
g_wr_cache_tail_src=g_addr_rd_phy_blk;
g_wr_cache_tail_dst=g_addr_wr_phy_blk;
g_wr_cache_tail_page=g_addr_page;
g_wr_cache_tail_page=g_addr_zone;
trace5(0, cache, 0, "write cache: deferring copy tail. zone:%d log:%d src:%d dst:%d page:%d", g_wr_cache_tail_zone, g_wr_cache_tail_log, g_wr_cache_tail_src, g_wr_cache_tail_dst, g_wr_cache_tail_page) ;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void map_write_cache_init() reentrant
{
trace0(0, cache, 0, "map_write_cache_init()") ;
// g_wr_cache_head_log=k_block_free;
g_wr_cache_tail_log=k_block_free;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void map_write_cache_free() reentrant
{
trace0(0, cache, 0, "map_write_cache_free(). write is now empty") ;
// g_wr_cache_head_log=k_block_free;
g_wr_cache_tail_log=k_block_free;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result map_copy_block_head_cache(void) reentrant
{
uint8 page ;
page=g_addr_page;
trace0(0, map, 0, "map_copy_block_head_cache()") ;
// check to see if there is a cached head or tail already present... if so,
// decide whether we can add this request to the tail, or if we need to flush
// the cached copy....
if(!_write_cache_is_empty())
{
if( (g_wr_cache_tail_log==g_addr_log_blk) && (g_wr_cache_tail_page == g_addr_page))
{
trace0(0, map, 0, "copy cache: copy head begins at cached copy_tail. no need to do a new copy head") ;
g_addr_wr_phy_blk=g_wr_cache_tail_dst;
// clear the tail cache... the rest of the parameters should be the same, but will be re-set at the
// end of the write
g_wr_cache_tail_log=k_block_free;
trace5(0, map, 0, "copy cache: resuming cached write transfer at log %d:%d src:%d dst:%d pg:%d", g_addr_zone, g_addr_log_blk, g_addr_rd_phy_blk, g_addr_wr_phy_blk, g_addr_page) ;
return k_success;
}
else
{
trace0(0, map, 0, "copy cache: cannot resume write transfer. flush cache and start new xfer") ;
map_write_cache_flush_one() ;
// fall through to empty cache processing
}
}
trace0(0, map, 0, "copy cache: begin new cached write transfer.") ;
if (k_success != map_alloc_wr_blk())
return k_error ;
media_copy_block_head() ;
#if 0
/*
map_write_cache_set_head();
return k_success;
*/
#endif
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result map_copy_block_tail_cache(void) reentrant
{
// only work on one cache entry at a time, so it should already be available
trace4(0, cache, 0, "map_copy_block_tail_cache(): log:%d, dst:%d, src:%d, page:%d", g_addr_log_blk, g_addr_wr_phy_blk, g_addr_rd_phy_blk, g_addr_page) ;
map_write_cache_set_tail() ;
return k_success;
}
xdata uint16 prev_log;
xdata uint16 prev_src;
xdata uint16 prev_dst;
xdata uint16 prev_page;
xdata uint16 prev_zone;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result map_write_cache_flush_one() reentrant
{
t_result result ;
trace0(0, cache, 0, "map_write_cache_flush_one()") ;
prev_log=g_addr_log_blk;
prev_src=g_addr_rd_phy_blk;
prev_dst=g_addr_wr_phy_blk;
prev_page=g_addr_page;
prev_zone=g_addr_zone;
result=k_success;
#if 0
/*
// bind the phy block(s) to the log2phy table
// note: this assertion must be tested, and when working, can be taken out of the code
if(g_wr_cache_head_log == g_wr_cache_tail_log)
{
if( g_wr_cache_head_log != k_block_free)
{
if(g_wr_cache_head_src != g_wr_cache_tail_src)
{
trace0(0, cache, 0, "write cache error: copy-head/copy-tail entry has same logical binding, but different src blocks!") ;
return k_error ;
}
if(g_wr_cache_head_dst != g_wr_cache_tail_dst)
{
trace0(0, cache, 0, "write cache error: copy-head/copy-tail entry has same logical binding, but different dst blocks!") ;
return k_error;
}
if(g_wr_cache_head_page >= g_wr_cache_tail_page)
{
trace0(0, cache, 0, "write cache error: copy-head/copy-tail entry has same logical binding, but head page > tail page.") ;
return k_error;
}
}
}
// cached copy head operation
map_write_cache_get_head();
if( g_addr_log_blk != k_block_free )
{
if (k_success!=media_copy_block_head())
{
trace0(0, cache, 0, "error copying block head... abort") ;
return k_error;
}
trace0(0, cache, 0, "write cache copy_head() complete.") ;
}
// update map bindings for the head, only if the block isn't teh same as the tail
if(g_addr_log_blk != g_wr_cache_tail_log)
{
trace0(0, cache, 0, "binding block head in table") ;
map_rebind_log_blk() ;
}
*/
#endif
// cached copy tail operation
map_write_cache_get_tail();
if( g_addr_log_blk!=k_block_free )
{
if( k_success != map_copy_block_tail())
{
trace0(0, cache, 0, "error coyping block head... no logical block specified in cached copy_tail!") ;
result=k_error;
}
}
map_write_cache_free();
trace0(0, cache, 0, "write cache: copy complete") ;
g_addr_log_blk=prev_log;
g_addr_rd_phy_blk=prev_src;
g_addr_wr_phy_blk=prev_dst;
g_addr_page=prev_page;
g_addr_zone=prev_zone;
return result;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result map_write_cache_flush_all() reentrant
{
// TRACE0(200, cache, 0, "map_write_cache_flush_all() - flushing write cache") ;
while(!_write_cache_is_empty())
map_write_cache_flush_one() ;
trace0(0, cache, 0, "write cache empty") ;
return k_success;
}
#endif // k_enable_write_cache
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_bool map_log_blk_has_bad_data() reentrant
{
_l2p_map = _log_map(g_addr_zone);
trace2(0, map, 0, "map_log_blk_has_bad_data(%d) - %c", g_addr_log_blk, ((_l2p_map[g_addr_log_blk]&kbm_map_blk_has_bad_data)?'Y':'N'));
return (_l2p_map[g_addr_log_blk]&kbm_map_blk_has_bad_data)?k_true:k_false;
}
//---eof------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -