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