📄 sm_media.c
字号:
trace0(0, sm_media, 0, "cis data failed ecc check. media unusable") ;
sm_soft_reset();
return k_error ;
}
_media_data(boot_block) = g_addr_rd_phy_blk ;
_media_data(boot_page) = g_addr_page;
trace2(0, sm_media, 0, "card info struct data found. rd_phy_blk:%04X sector:%02x", g_addr_rd_phy_blk, g_addr_page) ;
return k_success ;
}
g_addr_page++;
}
sm_soft_reset();
return k_error ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_redt_is_data_valid()
//
// Declaration:
// t_result sm_redt_is_data_valid(void) reentrant
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// TBD
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_redt_is_data_valid(void) reentrant
{
uint8 data_status = x_sm_redt_data[k_ix_redt_data_status] ;
if (data_status==0xFF)
return k_true;
if (data_status==0x00)
{
trace0(0, sm_media, 0, "data status:0x00 -> factory-marked bad-block") ;
return k_false;
}
if (bit_count8(data_status)<5)
{
trace0(0, sm_media, 0, "data status:0x02X -> 4 bits +/- 1 bit error: data either marked bad, or set bad by factory") ;
return k_false;
}
return k_true;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_read_extra_data()
//
// Declaration:
// TBD
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// TBD
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_read_extra_data(void) reentrant
{
uint8 i ;
trace3(0, sm_media, 0, "sm_media_read_extra_data() - zone:%d RD_PHY:%d page:%d", g_addr_zone, g_addr_rd_phy_blk, g_addr_page) ;
nand_rd_va2pa() ;
_sm_rd_cmd_begin(k_sm_read_redt) ;
_sm_set_rd_cmd(k_sm_read_redt);
_media_set_read_addr() ;
if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
{
trace0(0, sm_media, 0, "**** sm_media_read_extra_data() - timed out trying to read extra data") ;
nand_cmd_reset_device() ;
return(k_error);
}
if( !(x_media_sts&kbm_media_sts_sm_256_page) )
{
trace0(0, sm, 0, "reading 512+16 media extra data") ;
// read redundant data (512+16 media) ----------------------
for (i=0x00;i<k_sm_redt_buffer_sz;i++)
x_sm_redt_data[i] =_sm_data_rd();
// wait-with-timeout (k_sm_read_timeout)
if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
{
trace0(0, sm_media, 0, "error - timed out waiting for ready bit") ;
nand_cmd_reset_device() ;
return k_error ;
}
}
else
{
// read redundant data (256+8 media) -----------------------
trace0(0, sm, 0, "reading 256+8 media extra data") ;
// first page
for (i=0x00;i<0x08;i++)
x_sm_redt_data[i] =_sm_data_rd();
// wait-with-timeout (k_sm_read_timeout)
if (sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
{
nand_cmd_reset_device() ;
trace0(0, sm_media, 0, "error reading redt data even page") ;
return k_error;
}
// second page
x_smc_stat = kbm_smc_stat_rdy ;
_sm_set_rd_cmd(k_sm_read_redt);
nand_incr_addr() ;
_media_set_read_addr() ;
if (sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
{
nand_cmd_reset_device() ;
trace0(0, sm_media, 0, "error trying to read redt data odd page") ;
return k_error ;
}
for (i=0x08;i<0x10;i++)
x_sm_redt_data[i] =_sm_data_rd();
if (sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
{
nand_cmd_reset_device() ;
trace0(0, sm_media, 0, "error after reading redt data odd page") ;
return k_error ;
}
}
_sm_hw_set_rd_standby();
sm_synch_hw_buff_to_redt_buf() ;
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_write_extra_data()
//
// Declaration:
// t_result sm_media_write_extra_data(void) reentrant
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// TBD
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_write_extra_data(void) reentrant
{
uint8 i ;
t_result result ;
trace4(0, sm_media, 0, "sm_media_write_extra_data() - zone:%d WR_PHY:%d log:%d page:%d", g_addr_zone, g_addr_wr_phy_blk, g_addr_log_blk, g_addr_page) ;
result=k_success ;
// issue some custom commands to put card into write redundant data mode
sm_set_write_mode_extra_data() ;
// calculate address
nand_wr_va2pa() ;
// issue command
_sm_wr_cmd_begin(k_sm_write_data) ;
// set page address
_media_set_write_addr() ;
// this transmission is coming to you
for (i=0x00;i<0x10;i++)
{
_sm_data_wr(x_sm_redt_data[i]);
}
// commit the data
#if 1
trace0(0, sm, 0, "cmd: write") ;
_sm_set_wr_cmd(k_sm_write);
#else
if(g_addr_page==(_media_data(pages_per_block)-1))
{
trace0(0, sm, 0, "cmd: write") ;
_sm_set_wr_cmd(k_sm_write);
}
else
{
trace0(0, sm, 0, "cmd: write cache");
_sm_set_wr_cmd(k_nand_cmd_write_cache);
}
#endif
// wait for complete
if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_programming_timeout))
{
trace0(0, sm_media, 0, "error programing extra data") ;
result=k_error;
}
// restore the smart media data pointer mode
sm_set_write_mode_page_data() ;
_sm_hw_set_wr_standby();
_sm_hw_set_rd_standby();
return result ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_clear_redt_buffer()
//
// Declaration:
// void sm_clear_redt_buffer(void) reentrant
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// k_success always
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_clear_extra_data(void) reentrant
{
memset(x_sm_redt_data, 0xff, k_sm_redt_buffer_sz) ;
sm_synch_hw_buff_to_redt_buf() ;
return k_success ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_resolve_conflict()
//
// Declaration:
// t_result sm_media_resolve_conflict(void) reentrant
//
// Purpose:
// resolve a log2phy binding in a media-specific algorithm
//
// Arguments:
// - see Notes
//
// Return:
// k_success always
//
// Notes:
// when called,
// g_addr_rd_phy_blk contains one of the bindings,
// g_addr_wr_phy_blk contains the original mapping
//
// before returning, ensure:
// 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)
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_resolve_conflict() reentrant
{
uint16 temp ;
// call mapper-defined conflict resolver
if (k_success != map_resolve_conflict())
{
// by smart media spec, arbitrarily choose smaller phy_blk as correct binding
temp = _min(g_addr_rd_phy_blk, g_addr_wr_phy_blk) ;
// set wr_phy_blk to the phy_blk to be ignored/erased
g_addr_wr_phy_blk = _max(g_addr_rd_phy_blk, g_addr_wr_phy_blk) ;
// set rd_phy_blk to the correct binding and return
g_addr_rd_phy_blk = temp ;
}
return k_success ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_set_read_addr()
//
// Declaration:
// t_result sm_media_set_read_addr() reentrant
//
// Purpose:
// set media-specific address from internal zone/rd_phy_blk/sector addres
//
// Arguments:
// TBD
//
// Return:
// k_success always
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_set_read_addr() reentrant
{
trace3(0, sm_media, 0, "sm_media_set_read_addr() - page:%02x%02x%02x", g_nand_rd_addr_msb, g_nand_rd_addr_mid, g_nand_rd_addr_lsb) ;
_sm_hw_set_rd_addr();
_sm_data_wr(0x00);
_sm_data_wr(g_nand_rd_addr_lsb) ;
_sm_data_wr(g_nand_rd_addr_mid) ;
if (_lun_data(media)&kbm_sm_media_addr_4cyc)
_sm_data_wr(g_nand_rd_addr_msb);
_sm_hw_set_rd_data(0);
return k_success ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_set_write_addr()
//
// Declaration:
// t_result sm_media_set_write_addr() reentrant
//
// Purpose:
// set media-specific address from internal zone/wr_phy_blk/sector addres
//
// Arguments:
// TBD
//
// Return:
// k_success always
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_set_write_addr() reentrant
{
trace3(0, sm_media, 0, "sm_media_set_write_addr() - page:%02x%02x%02x", g_nand_wr_addr_msb, g_nand_wr_addr_mid, g_nand_wr_addr_lsb) ;
_sm_hw_set_wr_addr();
_sm_data_wr(0x00);
_sm_data_wr(g_nand_wr_addr_lsb) ;
_sm_data_wr(g_nand_wr_addr_mid) ;
if (_lun_data(media)&kbm_sm_media_addr_4cyc)
_sm_data_wr(g_nand_wr_addr_msb);
_sm_hw_set_wr_data(0);
return k_success ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_set_erase_addr()
//
// Declaration:
// t_result sm_media_set_erase_addr() reentrant
//
// Purpose:
// set media-specific address from internal zone/wr_phy_blk
//
// Arguments:
// TBD
//
// Return:
// k_success always
//
// Notes:
// The block to be erased should be in g_addr_wr_phy_blk before this
// function is called
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_set_erase_addr() reentrant
{
trace3(0, sm_media, 0, "sm_media_set_erase_addr() - page:%02x%02x%02x", g_nand_wr_addr_msb, g_nand_wr_addr_mid, g_nand_wr_addr_lsb) ;
_sm_hw_set_wr_addr();
_sm_data_wr(g_nand_wr_addr_lsb) ;
_sm_data_wr(g_nand_wr_addr_mid) ;
if (_lun_data(media)&kbm_sm_media_addr_4cyc)
_sm_data_wr(g_nand_wr_addr_msb);
// always use 0 for smart media... forces compatible timing mode on 242
_sm_hw_set_wr_data(0);
return k_success ;
}
//+-----------------------------------------------------------------------------
// Name:
// media_block_has_bad_data()
//
// Declaration:
// t_result media_block_has_bad_data() reentrant
//
// Purpose:
// scan blocks to find out whether or not a block contains a page that has
// a bad data flag. This is used for smart media controller who must detect
// data-gone-bad flag which can't do so at run-time
//
// Arguments:
//
// Return:
// k_true if a page between 0 and g_addr_rd_page contains extra data with
// 'failed' status
//
// k_false if all pages have good data status
//
// Notes:
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_block_has_bad_data() reentrant
{
trace0(0, sm_media, 0, "sm_media_block_has_bad_data()") ;
return sm_check_data_status(0, _media_data(pages_per_block));
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_is_phyblock_reserved()
//
// Declaration:
// t_result sm_media_is_phyblock_reserved() reentrant
//
// Purpose:
// scan blocks to find out whether or not a block is reserved (i.e. boot area) or
// usable by mapper & user.
//
// Arguments:
//
// Return:
// k_true if physical zone/block can be a user-accessible block
// k_false if physical block should be ignored by the mapper for everything
//
// Notes:
// a reserved block is NOT a factory or user-marked bad block. it is a block reserved
// for storing private data or boot information. (i.e. boot blocks, boot area, etc.)
// blocks marked bad by the factory will be detected in a subsequent call
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_is_phyblock_reserved(void) reentrant
{
if ((!g_addr_zone) && (g_addr_rd_phy_blk <= _media_data(boot_block)))
{
trace2(0, sm_media, 0, "block %d:%d is part of the boot area. tell mapper it is reserved", g_addr_zone, g_addr_rd_phy_blk);
return k_true;
}
return k_false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -