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

📄 map.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:

  // 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 + -