www.pudn.com > SMSC USB2.0.zip > nand_util.c


/*============================================================================ 
  ____________________________________________________________________________ 
                                ______________________________________________ 
   SSSS  M   M          CCCC          Standard Microsystems Corporation 
  S      MM MM   SSSS  C                    Austin Design Center 
   SSS   M M M  S      C                 11000 N. Mopac Expressway 
      S  M   M   SSS   C                Stonelake Bldg. 6, Suite 500 
  SSSS   M   M      S   CCCC                Austin, Texas 78759 
                SSSS            ______________________________________________ 
  ____________________________________________________________________________ 
  Copyright(C) 1999, Standard Microsystems Corporation 
  All Rights Reserved. 
  This program code listing is proprietary to SMSC and may not be copied, 
  distributed, or used without a license to do so.  Such license may have 
  Limited or Restricted Rights. Please refer to the license for further 
  clarification. 
  ____________________________________________________________________________ 
  Notice: The program contained in this listing is a proprietary trade 
  secret of SMSC, Hauppauge, New York, and is copyrighted 
  under the United States Copyright Act of 1976 as an unpublished work, 
  pursuant to Section 104 and Section 408 of Title XVII of the United 
  States code. Unauthorized copying, adaption, distribution, use, or 
  display is prohibited by this law. 
  ____________________________________________________________________________ 
  Use, duplication, or disclosure by the Government is subject to 
  restrictions as set forth in subparagraph(c)(1)(ii) of the Rights 
  in Technical Data and Computer Software clause at DFARS 52.227-7013. 
  Contractor/Manufacturer is Standard Microsystems Corporation, 
  80 Arkay Drive, Hauppauge, New York, 1178-8847. 
  ____________________________________________________________________________ 
  ____________________________________________________________________________ 
  nand.c - nand flash fixed media mass storage class implementation 
  ____________________________________________________________________________ 
  comments tbd 
  ____________________________________________________________________________ 
  Revision History 
  Date      Who  Comment 
  ________  ___  _____________________________________________________________ 
  08/28/02  cds  initial version to debug smart media corruption 
  10/17/02  cds  - project-wide lun data & vtbl paging to reduce code space.            
                 - removed g_active_media from _lun_data, _lun_() virtual functions     
                 - added _lun_data_rd() and _lun_data_wr() macros to bypass lun paging  
                 - added lun_set_active(log_lun) function to switch luns                
 ============================================================================*/ 
 
#include "project.h" 
#include "dev.h" 
 
//----------------------------------------------------------------------------- 
// bit control macros 
//----------------------------------------------------------------------------- 
static code char k_tbl_bitdata[] = { 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80} ; 
#define _setbit(__buffer,__bitaddr) (__buffer[(uint8)((__bitaddr)/8)] |=  k_tbl_bitdata[(__bitaddr)%8]) 
#define _clrbit(__buffer,__bitaddr) (__buffer[(uint8)((__bitaddr)/8)] &= ~k_tbl_bitdata[(__bitaddr)%8]) 
#define _chkbit(__buffer,__bitaddr) (__buffer[(uint8)((__bitaddr)/8)] &   k_tbl_bitdata[(__bitaddr)%8]) 
#define _flpbit(__buffer,__bitaddr) (__buffer[(uint8)((__bitaddr)/8)] ^=  k_tbl_bitdata[(__bitaddr)%8]) 
 
 
extern t_result sm_media_erase_card() reentrant ; 
extern uint16 map_log2phy(uint16 log) reentrant ; 
extern xdata uint8 g_sector_buffer[]; 
 
t_log2phy_map_ref _log_map(uint8 __zone) reentrant; 
t_assign_map_ref _assign_map( uint8 __zone ) reentrant; 
 
static xdata t_log2phy_map_ref  _l2p_map; 
static xdata t_assign_map_ref   _a_map; 
 
 
#if 0 
 
static code uint8 k_tbl_sm_media_cis_512[512] = 
{ 
  0x01,0x03,0xd9,0x01,0xff,0x18,0x02,0xdf,0x01,0x20,0x04,0x00,0x00,0x00,0x00,0x21, 
  0x02,0x04,0x01,0x22,0x02,0x01,0x01,0x22,0x03,0x02,0x04,0x07,0x1a,0x05,0x01,0x03, 
  0x00,0x02,0x0f,0x1b,0x08,0xc0,0xc0,0xa1,0x01,0x55,0x08,0x00,0x20,0x1b,0x0a,0xc1, 
  0x41,0x99,0x01,0x55,0x64,0xf0,0xff,0xff,0x20,0x1b,0x0c,0x82,0x41,0x18,0xea,0x61, 
  0xf0,0x01,0x07,0xf6,0x03,0x01,0xee,0x1b,0x0c,0x83,0x41,0x18,0xea,0x61,0x70,0x01, 
  0x07,0x76,0x03,0x01,0xee,0x15,0x14,0x05,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  0x00,0x20,0x20,0x20,0x20,0x00,0x30,0x2e,0x30,0x00,0xff,0x14,0x00,0xff,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x01,0x03,0xd9,0x01,0xff,0x18,0x02,0xdf,0x01,0x20,0x04,0x00,0x00,0x00,0x00,0x21, 
  0x02,0x04,0x01,0x22,0x02,0x01,0x01,0x22,0x03,0x02,0x04,0x07,0x1a,0x05,0x01,0x03, 
  0x00,0x02,0x0f,0x1b,0x08,0xc0,0xc0,0xa1,0x01,0x55,0x08,0x00,0x20,0x1b,0x0a,0xc1, 
  0x41,0x99,0x01,0x55,0x64,0xf0,0xff,0xff,0x20,0x1b,0x0c,0x82,0x41,0x18,0xea,0x61, 
  0xf0,0x01,0x07,0xf6,0x03,0x01,0xee,0x1b,0x0c,0x83,0x41,0x18,0xea,0x61,0x70,0x01, 
  0x07,0x76,0x03,0x01,0xee,0x15,0x14,0x05,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  0x00,0x20,0x20,0x20,0x20,0x00,0x30,0x2e,0x30,0x00,0xff,0x14,0x00,0xff,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 
} ; 
 
//+----------------------------------------------------------------------------- 
// Name: 
//   k_tbl_sm_media_cis_512() 
// 
// Purpose: 
//   default table data for restoring 512 + 16 byte media 
//------------------------------------------------------------------------------ 
static code uint8 k_tbl_sm_media_cis_flash_edata[16] = 
{ 
  0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x0c,0xcc,0xc3,0x00,0x00,0x0c,0xcc,0xc3 
} ; 
 
 
 
t_result util_blank_smart_media_card(void) reentrant 
{ 
  uint8* buf ; 
  trace0(0, util, 0, "repairing card...") ; 
 
  g_addr_wr_phy_blk = 0 ; 
  g_addr_zone = 0 ; 
  g_addr_page = 0 ; 
 
  for ( g_addr_wr_phy_blk=0; 
        g_addr_wr_phy_blk<(_media_data(physical_blocks_per_zone)-_media_data(logical_blocks_per_zone)-1); 
        g_addr_wr_phy_blk++) 
  { 
    mcu_begin_critical_section() ; 
    trace1(0, util, 0, "erasing phy_block %d", g_addr_wr_phy_blk) ; 
    mcu_end_critical_section() ; 
 
    // do erase here, because "erase_block" will prevent you from erasing the boot block 
    if (k_success != sm_media_erase_block()) 
    { 
      trace0(0, sm_media, 0, "repair card... failed to erase block") ; 
      continue; 
    } 
 
   
/* 
    _sm_wr_cmd_begin(k_sm_erase1); 
    _media_set_erase_addr(); 
    _sm_set_wr_cmd(k_sm_erase2); 
    if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_erase_timeout)) 
    { 
      trace0(0, sm_media, 0, "failed to erase block") ; 
    } 
    _sm_hw_set_wr_standby(); 
    _sm_hw_set_rd_standby(); 
*/ 
 
    for ( g_addr_page=0; g_addr_page < k_sm_max_cis_sect; g_addr_page++) 
    { 
      trace2(0, sm, 0, "attempting to write cis data to phy_blk %d sector %d", g_addr_wr_phy_blk, g_addr_page) ; 
      // write the default data 
      memcpy(g_sector_buffer, k_tbl_sm_media_cis_512, 512) ; 
      memcpy(x_sm_redt_data,  k_tbl_sm_media_cis_flash_edata, 16) ; 
      _media_data(sector_buffer) = g_sector_buffer ; 
//      fmc_dbg_dump_sector(_media_data(sector_buffer)) ; 
      sm_media_write_sector() ; 
      _media_data(sector_buffer) = g_sector_buffer ; 
 
      g_addr_rd_phy_blk = g_addr_wr_phy_blk ; 
      // read it back 
      sm_media_read_sector() ; 
      if(0==memcmp(g_sector_buffer, k_tbl_sm_media_cis_512, 512)) 
      { 
        trace0(0, sm_media, 0, "success!") ; 
        _media_data(boot_block) = g_addr_wr_phy_blk ; 
        _media_data(boot_page) = g_addr_page ; 
        sm_media_erase_card() ; 
        _media_data(sector_buffer) = buf ; 
        return k_success ; 
      } 
/* 
      else 
      { 
        fmc_dbg_dump_sector(g_sector_buffer) ; 
      } 
*/       
    } 
    g_addr_page = 0 ; 
    sm_media_set_phyblock_failed() ; 
  } 
  return k_error ; 
} 
#endif 
 
 
//------------------------------------------------------------------------------ 
//------------------------------------------------------------------------------ 
void util_trace_buffer(uint8* sector, uint16 size) reentrant 
{ 
  uint16 i; 
 
  _mcu_begin_critical_section(); 
  for (i=0;i lb: %d", g_addr_rd_phy_blk, g_addr_log_blk) ; 
} 
 
//------------------------------------------------------------------------------ 
//------------------------------------------------------------------------------ 
void util_trace_map_zone() reentrant 
{ 
  trace1(0, util, 0, "--- Zone %d Map -----------", g_addr_zone) ; 
  for(g_addr_rd_phy_blk=0; g_addr_rd_phy_blk<_media_data(physical_blocks_per_zone);g_addr_rd_phy_blk++) 
  { 
    util_trace_map_block() ; 
  } 
  trace1(0, util, 0, "--- Zone %d Map End -------", g_addr_zone) ; 
} 
 
//------------------------------------------------------------------------------ 
//------------------------------------------------------------------------------ 
void util_trace_map_media() reentrant 
{ 
  for(g_addr_zone=0;g_addr_zone<_media_data(num_zones);g_addr_zone++) 
  { 
    if(g_active_media != k_ix_media_sm) 
    { 
      nand_select_card() ; 
    } 
    util_trace_map_zone() ; 
  } 
} 
#endif 
 
xdata uint16 _erase_blocks ; 
xdata uint16 _erase_blocks_rsvd ;  
xdata uint16 _erase_blocks_bad ; 
xdata uint16 _erase_blocks_restored ; 
 
xdata uint16 _total_blocks ; 
xdata uint16 _total_blocks_rsvd ; 
xdata uint16 _total_blocks_bad ; 
xdata uint16 _total_blocks_restored ; 
 
//------------------------------------------------------------------------------ 
//------------------------------------------------------------------------------ 
t_result util_wr_verify_page_aa() reentrant 
{ 
  return k_false ; 
} 
 
//------------------------------------------------------------------------------ 
//------------------------------------------------------------------------------ 
t_result util_wr_verify_page_55() reentrant 
{ 
  return k_true ; 
} 
 
//------------------------------------------------------------------------------ 
//------------------------------------------------------------------------------ 
t_result util_recover_bad_block() reentrant 
{ 
  uint16 i ; 
  t_result result ; 
 
  if(g_active_media == k_ix_media_ms) 
  { 
    return _media_erase_block() ; 
  } 
   
#if (k_lun_sm < k_max_log_lun) 
  result = k_error ; 
  // smart media/nand recovery only 
  // test for factor-marked bad... redt data of all 0's is the best test 
  for(i=0; i<16;i++) 
  { 
    if(x_sm_redt_data[i] != 0x00) 
      result = k_success ; 
  } 
#endif 
 
  // an error indicates a factory-marked-bad candidate 
  if(k_success != result) 
  { 
    // check to see if the block is all 00's too... if so, don't touch it 
    nand_rd_va2pa() ; 
    _media_data(sector_buffer) = g_sector_buffer ; 
 
    result = _media_read_sector() ; 
    if(k_success != result) 
      return result ; 
 
    result = k_error ; 
    for(i=0;i<512;i++) 
    { 
      if(g_sector_buffer[i] != 0x00) 
      { 
        result = k_success ; 
      } 
    } 
 
    if(k_success != result) 
    { 
      // factory-marked-bad block... bail 
      return result ; 
    } 
  } 
 
 
  // do the block erase here 
  result = _media_erase_block() ; 
#if 0  
  if(k_success != result) 
    return result ; 
 
  // write first pattern 
  for(g_addr_page;g_addr_page < _media_data(pages_per_block);g_addr_page++) 
  { 
    result=util_wr_verify_page_55() ; 
    if(result != k_success) 
      return result ; 
  } 
 
  g_addr_page=0 ; 
  result = _media_erase_block() ; 
  for(g_addr_page;g_addr_page < _media_data(pages_per_block);g_addr_page++) 
  { 
    result=util_wr_verify_page_aa() ; 
    if(result != k_success) 
      return result ; 
  } 
 
  g_addr_page=0; 
  result = _media_erase_block() ; 
#endif 
  // technically, should write the pattern here for save erase 
  return result ; 
} 
//------------------------------------------------------------------------------ 
//------------------------------------------------------------------------------ 
void util_safe_erase_block() reentrant 
{ 
  if ((!g_addr_zone) && (g_addr_rd_phy_blk <= _media_data(boot_block))) 
  { 
    trace2(0, util, 0, "zone %d block %d - reserved.  not erased", g_addr_zone, g_addr_rd_phy_blk) ; 
    _erase_blocks_rsvd++ ; 
    return; 
  } 
  g_addr_page=0 ; 
 
  _media_read_extra_data() ; 
  if( _media_is_phyblock_ok() ) 
  { 
    if (_media_is_phyblock_blank() ) 
    { 
      // not bad... not written... don't erase 
      return; 
    } 
    if (k_success == _media_erase_block()) 
    { 
      _erase_blocks++ ; 
      return; 
    } 
  } 
  _erase_blocks_bad++ ; 
   
  // attempt to recover blocks not marked bad by the factory 
  if( k_success == util_recover_bad_block() ) 
  { 
    trace2(0, util, 0, "zone %d block %d - restored", g_addr_zone, g_addr_wr_phy_blk) ; 
    _erase_blocks_bad-- ; 
    _erase_blocks_restored++ ; 
    return; 
  } 
   
  trace2(0, util, 0, "zone %d block %d - block is bad",g_addr_zone, g_addr_wr_phy_blk) ; 
} 
 
//------------------------------------------------------------------------------ 
//------------------------------------------------------------------------------ 
void util_safe_erase_zone() reentrant 
{ 
  trace1(0, util, 0, "Erasing Zone %d ------", g_addr_zone) ; 
 
  for(g_addr_rd_phy_blk=0; g_addr_rd_phy_blk<_media_data(physical_blocks_per_zone);g_addr_rd_phy_blk++) 
  { 
    g_addr_wr_phy_blk=g_addr_rd_phy_blk ; 
    util_safe_erase_block() ; 
  } 
   
   
/* 
  trace1(0, util, 0, "Zone %d Erase Stats:", g_addr_zone) ; 
  trace1(0, util, 0, " blocks erased:  %d", _erase_blocks) ; 
  trace1(0, util, 0, " blocks_rsvd:    %d", _erase_blocks_rsvd) ; 
  trace1(0, util, 0, " blocks_bad:     %d", _erase_blocks_bad) ; 
  trace1(0, util, 0, " blocks_restored:%d", _erase_blocks_restored) ; 
*/ 
 
} 
 
//------------------------------------------------------------------------------ 
//------------------------------------------------------------------------------ 
void util_safe_erase_media() reentrant 
{ 
  trace0(0, util, 0, "util_safe_erase_media() - erase all blocks not explicitly marked 'bad' by the factory") ; 
 
  _total_blocks=0; 
  _total_blocks_rsvd=0; 
  _total_blocks_bad=0; 
  _total_blocks_restored=0; 
  for(g_addr_zone=0;g_addr_zone<_media_data(num_zones);g_addr_zone++) 
  { 
    if( !((g_active_media==k_ix_media_sm)||(g_active_media==k_ix_media_ms))) 
    { 
      nand_select_card() ; 
    } 
     
    _erase_blocks=0; 
    _erase_blocks_rsvd=0;  
    _erase_blocks_bad=0; 
    _erase_blocks_restored=0; 
    util_safe_erase_zone() ; 
    _total_blocks += _erase_blocks ; 
    _total_blocks_rsvd += _erase_blocks_rsvd ; 
    _total_blocks_bad += _erase_blocks_bad ; 
    _total_blocks_restored += _erase_blocks_restored ; 
  } 
/* 
  trace0(0, util, 0, "Safe Erase Results:") ; 
  trace1(0, util, 0, " total blocks erased:  %d", _total_blocks) ; 
  trace1(0, util, 0, " total blocks_rsvd:    %d", _total_blocks_rsvd) ; 
  trace1(0, util, 0, " total blocks_bad:     %d", _total_blocks_bad) ; 
  trace1(0, util, 0, " total blocks_restored:%d", _total_blocks_restored) ; 
*/ 
} 
 
#if 0 
//------------------------------------------------------------------------------ 
//------------------------------------------------------------------------------ 
void fmc_dbg_dump_sector(uint8* sector) reentrant; 
void sm_dbg_dump_redt_data() reentrant; 
void n2k_test_read_sequential() reentrant 
{ 
  uint16 i ; 
 
  // useful routine for dumping the contents of a block 
  g_addr_zone=0; 
  map_build_sector_map() ; 
  map_lba2addr_rd(0) ; 
  nand_select_card() ; 
  nand_rd_va2pa() ; 
 
  // read page into page buffer 
  nand_page_read_for_datay() ; 
   
  // read next page into cache 
  n2k_read_cache_next() ; 
  for(g_addr_page=0;g_addr_page<_media_data(pages_per_block);g_addr_page++) 
  { 
    trace1(0, nand, 0, "Read Page %d", g_addr_page) ; 
    for(i=0;i<512;i++) 
    { 
      g_sector_buffer[i] = _sm_data_rd() ; 
    } 
    fmc_dbg_dump_sector(g_sector_buffer) ; 
    for(i=0;i<16;i++) 
    { 
      x_sm_redt_data[i] = _sm_data_rd() ; 
    } 
    sm_dbg_dump_redt_data() ; 
 
    if( (g_addr_page&0x03)==3) 
    { 
      trace0(0, nand, 0, "read cache decision...") ; 
      if(g_addr_page==255) 
      { 
        trace0(0, nand, 0, "last page... don't issue any command") ; 
        continue ; 
      } 
      else if(g_addr_page==251) 
      { 
        trace0(0, nand, 0, "2nd to last page.  issue read-final-cache command") ; 
        n2k_read_cache_final() ; 
      } 
      else 
      { 
        trace0(0, nand, 0, "read in next cached page") ; 
        n2k_read_cache_next() ; 
      } 
    } 
  } 
} 
 
#endif 
 
 
#if 0  
void util_clear_boot_block() reentrant 
{ 
   
  uint16 i; 
 
  for(i=0;i<256;i++) 
  { 
    nand_boot_write(i, 0xff) ; 
  } 
  nand_boot_write_flush() ; 
} 
#endif 
 
 
 
 
 
 
 
 
//+----------------------------------------------------------------------------- 
// Name: 
//   util_verify_sector_map() 
// 
// Declaration: 
//   t_result util_verify_sector_map(void) reentrant 
// 
// Purpose: 
// 
// Arguments: 
// 
// Return: 
// 
// Notes: 
// 
// Since: 
//   fmc-1.0 
//------------------------------------------------------------------------------ 
#if 0 
 
void util_verify_sector_map(void) reentrant 
{ 
  uint8   zone ; 
  uint16  max_lb ; 
  uint16  lb; 
  uint8   check_for_l2p_entry ; 
 
  trace0(0, map, 0, "map_verify_sector_map()") ; 
 
  zone = g_addr_zone?1:0; 
  g_addr_page=0; 
 
 
  trace2(0, map, 0, "verifying sector map of media zone %d to map index %d", g_addr_zone, zone) ; 
 
  _l2p_map = _l2p_map(zone) ; 
  _a_map =   _assign_map(zone) ; 
 
  max_lb = zone?_media_data(logical_blocks_per_zone):_media_data(logical_blocks_per_boot_zone); 
 
  // 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++ ) 
  { 
 
    g_addr_page = 0 ; 
    if ((!g_addr_zone) && (g_addr_rd_phy_blk <= _media_data(boot_block))) 
    { 
      // 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() ) 
    { 
      trace0(0, map, 0, "phy_block %d: cannot read extra data.  mark block used, but not mapped.") ; 
      if( !_map_is_phy_blk_used( _a_map, g_addr_rd_phy_blk ) ) 
      { 
        trace0(0, map, 0, "***  error!  phy_block %d mapping corrupted!") ; 
      } 
      continue; 
    } 
 
    if( _media_is_phyblock_blank() ) 
    { 
      if( _map_is_phy_blk_used( _a_map, g_addr_rd_phy_blk) ) 
      { 
        trace1(0, map, 0, "***  error!  phy_block %d is marked blank on media, but is in use in ram map", g_addr_rd_phy_blk) ; 
      } 
 
      for(lb=0; lb < max_lb ; lb++ ) 
      { 
        if( _l2p_map[lb] == g_addr_rd_phy_blk ) 
        { 
          trace2(0, map, 0, "***  error!  phy_block %d is blank on media, but has logical mapping to log_blk:%d", g_addr_rd_phy_blk, lb) ; 
        } 
      } 
      continue; 
    } 
 
    // the block SHOULD be marked used in the assignment map 
    if ( !_map_is_phy_blk_used( _a_map, g_addr_rd_phy_blk )) 
    { 
      trace1(0, map, 0, "*** error!  phy_block %d in use, but assign_map shows phy_block is available", g_addr_rd_phy_blk) ; 
    } 
 
    check_for_l2p_entry = k_false ; 
 
    // tests to determine whether the block is in-use, but not mapped. 
    if( !_media_is_phyblock_ok() ) 
      check_for_l2p_entry = k_true ; 
    if(k_error == _media_phy2log()) 
      check_for_l2p_entry = k_true ; 
    if ( g_addr_log_blk >= max_lb ) 
      check_for_l2p_entry = k_true ; 
 
    // if block should be in use, but not mapped, make sure there is no mapping 
    if(check_for_l2p_entry) 
    { 
      for(lb=0; lb < max_lb ; lb++ ) 
      { 
        if( _l2p_map[lb] == g_addr_rd_phy_blk ) 
        { 
          trace2(0, map, 0, "***  error!  log_blk %d bound to phy_block %d.  However, phy_block should not have a mapping due to extra-data errors", lb, g_addr_rd_phy_blk) ; 
        } 
      } 
      continue; 
    } 
 
    // if the block is in use, and there SHOULD be a mapping, make sure the mapping 
    // in the ram tables matches what is on the media 
    for(lb=0; lb < max_lb ; lb++) 
    { 
      if( lb == g_addr_log_blk ) 
      { 
        if(_l2p_map[lb] != g_addr_rd_phy_blk) 
        { 
          trace3(0, map, 0, "*** error!  log_blk: %d maps to rd_phy_blk %d, should map to rd_phy_blk %d", lb, _l2p_map[lb], g_addr_rd_phy_blk) ; 
        } 
      } 
      else if(_l2p_map[lb] == g_addr_rd_phy_blk) 
      { 
        trace3(0, map, 0, "*** error!  log_blk: %d incorrectly maps to rd_phy_blk %d!  Should ONLY be mapped log blk %d", lb, g_addr_rd_phy_blk, g_addr_log_blk) ; 
      } 
    } 
  } 
} 
#endif 
 
 
//+----------------------------------------------------------------------------- 
// Name: 
//   map_reclaim_bad_sectors() 
// 
// Declaration: 
//   t_result map_reclaim_bad_sectors(void) reentrant 
// 
// Purpose: 
//  TBD 
// 
// Arguments: 
//  TBD 
// 
// Return: 
//  TBD 
// 
// Notes: 
//  TBD 
// 
// Since: 
//   fmc-1.0 
//------------------------------------------------------------------------------ 
#if 0 
t_result map_reclaim_bad_sectors() reentrant 
{ 
  uint8 zone_idx ; 
  uint8 page ; 
  uint8 rd_blk ; 
 
  trace0(0, map, 0, "map_alloc_wr_blk()") ; 
  zone_idx    = g_addr_zone?1:0 ; 
  page = g_addr_page ; 
  rd_blk = g_addr_rd_phy_blk ; 
  _a_map = _assign_map(g_addr_zone) ; 
 
  for( g_addr_rd_phy_blk = 0 ; 
       g_addr_rd_phy_blk < _media_data(physica_blocks_per_zone) ; 
       g_addr_rd_phy_blk++) 
  { 
    if ((!g_addr_zone) && (g_addr_rd_phy_blk <= _media_data(boot_block))) 
    { 
      trace1(0, map, 0, "phy_block %d: not reclaimable", g_addr_rd_phy_blk) ; 
      continue; 
    } 
 
    if(k_error == _media_read_extra_data() ) 
    { 
      trace0(0, map, 0, "cannot read extra data.  not attempting to reclaim.") ; 
      continue; 
    } 
 
    // skip bad block 
    if( !_media_is_phyblock_ok() ) 
    { 
      trace0(0, map, 0, "phy_block marked bad.  not included in log2phy map") ; 
      continue; 
    } 
 
    g_addr_wr_phy_blk = g_addr_rd_phy_blk ; 
 
    trace(0, map, 0, "trying to reclaim block %d") ; 
    _media_erase_block() ; 
 
    if(k_error == _media_read_extra_data() ) 
    { 
      trace0(0, map, 0, "still cannot read extra data.  not attempting to reclaim.") ; 
      continue; 
    } 
 
    if( !_media_is_phyblock_ok() ) 
    { 
      trace0(0, map, 0, "phy_block still bad.  not included in log2phy map") ; 
      continue; 
    } 
 
    if( !_media_is_phyblock_blank() ) 
    { 
      trace0(0, map, 0, "phyblock not blank.  moving on") ; 
      continue; 
    } 
 
 
 
  } 
    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") ; 
  //  map_reclaim_sectors() ; 
 
  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 ; 
  page = g_addr_page ; 
  rd_blk = g_addr_rd_phy_blk ; 
 
  g_addr_page = 0 ; 
  trace0(0, map, 0, "seeking bad blocks") ; 
  // 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++ ) 
  { 
 
 
 
    // set the block used 
    _map_phy_blk_used( _a_map, g_addr_rd_phy_blk ) ; 
 
  } 
} 
 
#endif 
 
 
// -------------------------------------------------------------------- 
// -------------------------------------------------------------------- 
 
#if 0 
/* log block 0, phy block 2, page 0 */ 
static code uint8 k_tbl_sm_log_0_pg_0[528] = 
{ 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 
  0x10, 0x00, 0x06, 0x0f, 0x60, 0xf3, 0x2f, 0x00, 
  0x00, 0x00, 0xd1, 0xe7, 0x03, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x01, 
  0xc0, 0xff, 0x3f, 0x10, 0x01, 0xff, 0xff, 0xff 
}; 
 
 
/* log block 1, phy block 3, page 15 */ 
static code uint8 k_tbl_sm_log_1_pg_15[528] = 
{ 
  0xe9, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 
  0x20, 0x20, 0x20, 0x00, 0x02, 0x20, 0x01, 0x00, 
  0x02, 0x00, 0x01, 0x00, 0x00, 0xf8, 0x20, 0x00, 
  0x20, 0x00, 0x10, 0x00, 0x2f, 0x00, 0x00, 0x00, 
  0xd1, 0xe7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x41, 
  0x54, 0x31, 0x36, 0x20, 0x20, 0x20, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 
   
  /* extra data */ 
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x02, 
  0xff, 0xff, 0xff, 0x10, 0x02, 0x99, 0xa9, 0x5b 
}; 
 
/* log block 1, phy block 3, page 16 */ 
static code uint8 k_tbl_sm_log_1_pg_16[528] = 
{ 
  0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
   
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x02, 
  0xff, 0xff, 0xff, 0x10, 0x02, 0xaa, 0xaa, 0x97 
}; 
 
 
 
void util_create_bad_128mb_media(void) reentrant 
{ 
  trace0(0, util, 0, "Creating bad 128 mb media...") ; 
  // safe-erase media 
  util_safe_erase_media() ; 
 
  // allocate a write block 
  g_addr_rd_phy_blk = k_block_free ; 
  g_addr_zone = 0 ; 
  g_addr_log_blk = 0; 
  g_addr_page=0 ; 
  _media_data(sector_buffer) = g_sector_buffer ; 
   
  map_alloc_wr_blk() ; 
 
  // write log 0 pg 0 
  memcpy(g_sector_buffer, k_tbl_sm_log_0_pg_0, 512) ; 
  memcpy(x_sm_redt_data, k_tbl_sm_log_0_pg_0+512, 16) ; 
  trace4(0, util, 0, "writing zone %d logical block %d, page %d, to phy block %d", g_addr_zone, g_addr_log_blk, g_addr_page, g_addr_wr_phy_blk) ; 
  _media_write_sector() ; 
  util_trace_buffer(g_sector_buffer, 512) ; 
  util_trace_buffer(x_sm_redt_data, 16) ; 
 
  // clear extra data and write log 0 pg 1-end of block 
  memset(g_sector_buffer, 0xff, 512) ; 
  _media_clear_extra_data() ; 
  _media_bind_log2phy() ; 
  for(g_addr_page=1;g_addr_page<_media_data(pages_per_block);g_addr_page++) 
  { 
    trace4(0, util, 0, "writing zone %d logical block %d, page %d, to phy block %d", g_addr_zone, g_addr_log_blk, g_addr_page, g_addr_wr_phy_blk) ; 
    _media_write_sector() ; 
    util_trace_buffer(g_sector_buffer, 512) ; 
    util_trace_buffer(x_sm_redt_data, 16) ; 
  } 
 
  // write log 1 pg 0-14 
  g_addr_log_blk=1 ; 
   
  map_alloc_wr_blk() ; 
  _media_clear_extra_data() ; 
  _media_bind_log2phy() ; 
  for(g_addr_page=0; g_addr_page<15; g_addr_page++) 
  { 
    trace4(0, util, 0, "writing zone %d logical block %d, page %d, to phy block %d", g_addr_zone, g_addr_log_blk, g_addr_page, g_addr_wr_phy_blk) ; 
    _media_write_sector() ; 
    util_trace_buffer(g_sector_buffer, 512) ; 
    util_trace_buffer(x_sm_redt_data, 16) ; 
  } 
 
  // write log 1 pg 15 
  memcpy(g_sector_buffer, k_tbl_sm_log_1_pg_15, 512) ; 
  memcpy(x_sm_redt_data, k_tbl_sm_log_1_pg_15+512, 16) ; 
  g_addr_page=15 ; 
  trace4(0, util, 0, "writing zone %d logical block %d, page %d, to phy block %d", g_addr_zone, g_addr_log_blk, g_addr_page, g_addr_wr_phy_blk) ; 
  _media_write_sector() ; 
  util_trace_buffer(g_sector_buffer, 512) ; 
  util_trace_buffer(x_sm_redt_data, 16) ; 
 
  // write log 1 pg 16 
  memcpy(g_sector_buffer, k_tbl_sm_log_1_pg_16, 512) ; 
  memcpy(x_sm_redt_data, k_tbl_sm_log_1_pg_16+512, 16) ; 
  g_addr_page=16 ; 
  trace4(0, util, 0, "writing zone %d logical block %d, page %d, to phy block %d", g_addr_zone, g_addr_log_blk, g_addr_page, g_addr_wr_phy_blk) ; 
  _media_write_sector() ; 
  util_trace_buffer(g_sector_buffer, 512) ; 
  util_trace_buffer(x_sm_redt_data, 16) ; 
 
  memset(g_sector_buffer, 0x00, 512) ; 
  _media_clear_extra_data() ; 
  _media_bind_log2phy() ; 
  for(g_addr_page=17; g_addr_page<_media_data(pages_per_block);g_addr_page++) 
  { 
    trace4(0, util, 0, "writing zone %d logical block %d, page %d, to phy block %d", g_addr_zone, g_addr_log_blk, g_addr_page, g_addr_wr_phy_blk) ; 
    _media_write_sector() ; 
    util_trace_buffer(g_sector_buffer, 512) ; 
    util_trace_buffer(x_sm_redt_data, 16) ; 
  } 
 
  // write log 2,3 pgs 0-31 
  for(g_addr_log_blk=2;g_addr_log_blk<=3;g_addr_log_blk++) 
  { 
    map_alloc_wr_blk() ; 
    _media_bind_log2phy() ; 
    for(g_addr_page=0 ;g_addr_page < _media_data(pages_per_block);g_addr_page++) 
    { 
      trace4(0, util, 0, "writing zone %d logical block %d, page %d, to phy block %d", g_addr_zone, g_addr_log_blk, g_addr_page, g_addr_wr_phy_blk) ; 
      _media_write_sector() ; 
      util_trace_buffer(g_sector_buffer, 512) ; 
      util_trace_buffer(x_sm_redt_data, 16) ; 
    } 
  } 
 
  // done 
  trace0(0, util, 0, "create bad media:  done") ; 
  trace0(0, util, 0, "dumping phy blocks 0-5") ; 
  for(g_addr_rd_phy_blk=0; g_addr_rd_phy_blk<5; g_addr_rd_phy_blk++) 
  { 
    util_trace_phy_block() ; 
  } 
 
  trace0(0, util, 0, "done") ; 
} 
#endif // ghosting an optimized format onto blank media 
// -------------------------------------------------------------------- 
// -------------------------------------------------------------------- 
 
#define kbm_map_soft_l2p_binding (0x8000) 
#define kbm_map_l2p_bits         (0x03FF) 
#if 0  
 
void map_debug(uint8 zone) reentrant 
{ 
  _l2p_map = _log_map(zone); 
  _a_map = _assign_map(zone); 
#ifdef k_opt_erase_cache 
  if( _media_data(options)&kbm_media_data_opt_erase_cache) 
  { 
    _e_map = _erase_cache(zone); 
  } 
  else 
#endif 
  { 
    // this simplifies the clearing of the data below 
    _e_map = _a_map; 
  } 
 
  trace1(0, map, 0, "&_l2p_map    :%04x", ((uint16)_l2p_map));  
  trace1(0, map, 0, "&_a_map      :%04x", ((uint16)_a_map)); 
  trace1(0, map, 0, "&_e_map      :%04x", ((uint16)_e_map)); 
 
  for(g_addr_wr_phy_blk=0;g_addr_wr_phy_blk<1024;g_addr_wr_phy_blk++) 
  { 
    g_addr_rd_phy_blk=k_block_free; 
    for(g_addr_log_blk=0;g_addr_log_blk<1000;g_addr_log_blk++) 
    { 
      if( (_l2p_map[g_addr_log_blk]&kbm_map_l2p_bits) ==g_addr_wr_phy_blk) 
      { 
        g_addr_rd_phy_blk=g_addr_log_blk;  
        break; 
      } 
    } 
    trace4(0, map, 0, "phy_blk:%d - in_use:%c in_cache:%c log_binding:%d", g_addr_wr_phy_blk, (_map_is_phy_blk_used(_a_map,g_addr_wr_phy_blk)?'Y':'N'), (_map_is_phy_blk_used(_e_map,g_addr_wr_phy_blk)?'Y':'N'), g_addr_log_blk); 
    for(g_addr_log_blk++;g_addr_log_blk<1000;g_addr_log_blk++) 
    { 
      if((_l2p_map[g_addr_log_blk]&kbm_map_l2p_bits)==g_addr_wr_phy_blk) 
      { 
        trace1(0, map, 0, "           - *** also bound to log:%d", g_addr_log_blk); 
      } 
    } 
  } 
} 
#endif 
 
 
 
 
void util_read_lba(uint32 lba) reentrant 
{ 
  map_lba2addr_rd(lba) ; 
  _media_data(sector_buffer)=g_sector_buffer; 
  _media_read_sector(); 
} 
 
xdata _tmp_buf[16]; 
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
void util_write_lba(uint32 lba) reentrant 
{ 
  memcpy(_tmp_buf, x_sm_redt_data, 16); 
  map_write_begin(lba); 
  _media_data(sector_buffer)=g_sector_buffer; 
  memcpy(x_sm_redt_data, _tmp_buf, 16); 
  _media_write_sector(); 
  map_write_flush(); 
} 
 
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
void util_test_hardware_ecc(uint32 lba, uint16 ix_bit) reentrant 
{ 
  trace2(0, util, 0, "util_test_hardware_ecc() - creating 1-bit error in lba %d bit %d", lba, ix_bit) ; 
  util_read_lba(lba); 
  // there's a bug in _flipbit that won't go higher than 256 bytes.  should be a non-issue for mapper 
  if(ix_bit<2048) 
  { 
    _flpbit((g_sector_buffer), ix_bit); 
  } 
  else 
  { 
    _flpbit(((g_sector_buffer)+100), ix_bit); 
  } 
  util_write_lba(lba); 
} 
 
void util_create_2bit_error(uint32 lba) reentrant 
{ 
  util_read_lba(lba); 
  _flpbit(g_sector_buffer,0); 
  _flpbit(g_sector_buffer,1); 
  util_write_lba(lba); 
} 
 
void util_create_1bit_error(uint32 lba) reentrant 
{ 
  util_read_lba(lba); 
  _flpbit(g_sector_buffer,0); 
  util_write_lba(lba); 
} 
 
 
#if 0  
xdata uint8 buffer1[528]; 
xdata uint8 buffer2[528]; 
void util_compare_blocks(uint16 blk1, uint16 blk2) reentrant 
{ 
  uint16 offset; 
 
  trace0(0, util, 0, "Compare Block Data") ; 
  trace1(0, util, 0, "block 1: %d",blk1) ; 
  trace1(0, util, 0, "block 2: %d",blk2) ; 
  for(g_addr_page=0;g_addr_page<_media_data(pages_per_block);g_addr_page++) 
  { 
    trace1(0, util, 0, "--- page %d ---", g_addr_page); 
    g_addr_rd_phy_blk=blk1; 
    _media_data(sector_buffer)=buffer1; 
    _media_read_sector(); 
    memcpy(buffer1+512, x_sm_redt_data, 16); 
 
    g_addr_rd_phy_blk=blk2; 
    _media_data(sector_buffer)=buffer2; 
    _media_read_sector(); 
    memcpy(buffer2+512, x_sm_redt_data, 16); 
 
    if(memcmp(buffer1, buffer2, 512)) 
    { 
      for(offset=0; offset<512;offset++) 
      { 
        if(buffer1[offset]!=buffer2[offset]) 
        { 
          trace5(0, util, 0, "page data difference at offset %d -- block %d:%02X block %d:%02X", offset, blk1, buffer1[offset], blk2, buffer2[offset]); 
        } 
      } 
    } 
    else 
    { 
      trace0(0, util, 0, "page data identical") ; 
    } 
    if(memcmp(buffer1+512, buffer2+512, 16)) 
    { 
      trace0(0, util, 0, "extra data differs"); 
      for(offset=0;offset<16;offset++) 
      { 
        if(buffer1[offset+512]!=buffer2[offset+512]) 
        { 
          trace5(0, util, 0, "extra data difference at offset %d -- block %d:%02X block %d:%02X", offset, blk1, buffer1[offset+512], blk2, buffer2[offset+512]); 
        } 
      } 
    } 
    else 
    { 
      trace0(0, util, 0, "extra data identical") ; 
    } 
  } 
 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
void util_test_copy_double_bit_ecc(uint32 lba) reentrant 
{ 
  uint16 first_rd_blk; 
  uint16 org_rd_blk; 
  uint16 err_rd_blk; 
  trace0(0, util, 0, "------------ 2-bit during copy head (copy before starting user data)") ; 
   
   
  map_lba2addr_rd(lba) ; 
  trace5(0, util, 0, "------------ creating 2-bit error on block %d:%d[r%d|w%d]:%d", g_addr_zone, g_addr_log_blk, g_addr_rd_phy_blk, g_addr_wr_phy_blk, g_addr_page); 
  trace0(0, util, 0, "------------ original data/redundant") ; 
  first_rd_blk=org_rd_blk = g_addr_rd_phy_blk; 
  util_trace_page(); 
   
  util_create_2bit_error(lba); 
 
  trace0(0, util, 0, "------------ compare org blk to err blk to verify only difference is 2-bit error"); 
  map_lba2addr_rd(lba); 
  err_rd_blk=g_addr_rd_phy_blk; 
  util_compare_blocks(org_rd_blk, err_rd_blk); 
 
  // read n write a block back to simulate "user" data 
  trace0(0, util, 0, "------------ writing 'user data'") ; 
  util_read_lba(lba+1); 
  util_write_lba(lba+1); 
   
  trace0(0, util, 0, "------------ compare err blk w/ new blk(verify blk status 'bad' in err blk, verify data status 'bad' in error page, verify ecc data updated in error page, verify page data identical for ALL pages)");  
  map_lba2addr_rd(lba); 
  util_compare_blocks(err_rd_blk, g_addr_rd_phy_blk); 
 
  trace0(0, util, 0, "------------ compare org blk w/ new blk (verify only differnce is in page that has error)") ; 
  map_lba2addr_rd(lba); 
  util_compare_blocks(org_rd_blk, g_addr_rd_phy_blk); 
   
 
  map_lba2addr_rd(lba+2) ; 
  trace5(0, util, 0, "------------ creating 2-bit error on block %d:%d[r%d|w%d]:%d", g_addr_zone, g_addr_log_blk, g_addr_rd_phy_blk, g_addr_wr_phy_blk, g_addr_page); 
  org_rd_blk = g_addr_rd_phy_blk; 
 
  util_create_2bit_error(lba+2); 
 
  trace0(0, util, 0, "------------ compare org blk to err blk to verify only difference is 2-bit error"); 
  map_lba2addr_rd(lba); 
  err_rd_blk = g_addr_rd_phy_blk; 
  util_compare_blocks(org_rd_blk, err_rd_blk); 
 
 
  trace0(0, util, 0, "------------ causing copy-tail 2-bit ecc error") ; 
  // do a read/write before the 2-bit error to cause problem in copy-tail 
  util_read_lba(lba+1); 
  util_write_lba(lba+1); 
   
  trace0(0, util, 0, "------------ compare err blk w/ new blk(verify blk status 'bad' in err blk, verify data status 'bad' in error page, verify ecc data updated in error page, verify page data identical for ALL pages)");  
  map_lba2addr_rd(lba+2); 
  util_compare_blocks(err_rd_blk, g_addr_rd_phy_blk); 
 
  trace0(0, util, 0, "------------ compare org blk w/ new blk (verify only differnce is in page that has error)") ; 
  map_lba2addr_rd(lba+2); 
  util_compare_blocks(org_rd_blk, g_addr_rd_phy_blk); 
 
  trace0(0, util, 0, "------------ dump of Final Logical Block") ; 
  util_trace_phy_block(); 
   
  trace0(0, util, 0, "------------ dump of First Logical Block") ; 
  g_addr_rd_phy_blk=first_rd_blk; 
  util_trace_phy_block(); 
 
 
  if( _media_data(options)&kbm_media_data_opt_erase_cache) 
  { 
    trace0(0, nand, 0, "flushing erase cache()") ; 
    map_erase_cache_flush_all(); 
  } 
   
  mcu_halt(); 
} 
 
#endif