⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 map.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
    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 + -