📄 nand.c
字号:
//
// Purpose:
// Read data from sm media
//
// Arguments:
// None.
// Uses _lun_data and g_bot_cbw to get its parameters.
//
// Return:
// No return value.
// However, on exit the DFA's argument pointer is written with a t_csw_status indicating:
// k_command_passed - command completed.
// k_command_failed - an error occurred.
//
// Notes:
// This is the start STATE of the dfa_ata_read DFA.
// It overrides dfa_lun_read.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void nand_dfa_read(void) reentrant
{
trace0(0, nand, 0, "nand_dfa_read()");
_fmc_set_options(0);
_fmc_set_timeout(10000);
_fmc_set_callback(nand_read_begin_xfer, sm_read_end_xfer,
nand_read_begin_split, nand_read_end_first_split,
fmc_dflt_callback, fmc_dflt_callback, sm_read_end_burst);
#ifdef k_enable_write_caching
// flush write cache
if (_media_data(options)&kbm_media_data_opt_write_cache)
map_write_cache_flush_all() ;
#endif
dfa_lun_read();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//+-----------------------------------------------------------------------------
// Name:
// nand_write_begin_first_split
//
// Declaration:
// t_result nand_write_begin_first_split(void);
//
// Purpose:
// Issue the write command to the smart media device.
//
// Arguments:
// None.
//
// Return:
// A t_result indicating:
// k_success - command completed.
//
// Notes:
// This is a FUNCTION, not a DFA.
// Do not yeild, or run a DFA, from within this callback.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result nand_write_begin_first_split() reentrant
{
trace0(0, nand, 1, "nand_write_begin_first_split()");
// compute phy addresses in case this is the first sector
nand_select_card() ;
nand_wr_va2pa() ;
nand_rd_va2pa() ;
if(k_ix_media_nand==g_active_media)
{
g_fmc_begin_split_callback = (t_fmc_callback) sm_write_begin_split;
// $$$ old n busted
// sm_set_write_mode_page_data();
// $$$ new hotness
sm_rd_cmd_begin(k_sm_reset_chip);
sm_wait_rdy_with_timeout(k_sm_busy_reset_timeout);
}
else
{
g_fmc_begin_split_callback = (t_fmc_callback) n2k_write_begin_split;
trace2(0, n2k, 0, "beginning split at page:%d segment:%d", g_addr_page, g_addr_segment) ;
// check to see if we are starting in middle of a page
if(g_addr_segment)
{
// pre-read the old page into chip cache
n2k_page_read_for_copy() ;
// write the full destination address
n2k_page_write_cache_data() ;
n2k_page_set_wr_offset( _n2k_data_offset( g_addr_segment ) ) ;
}
}
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// n2k_write_begin_xfer
//
// Declaration:
// void n2k_write_begin_xfer(void) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result n2k_write_begin_xfer() reentrant
{
t_result result ;
uint16 max_split_size ;
TRACE4(271, sm, 10, "n2k_write_begin_xfer() - start:0x%04X%04X count:0x%04X%04X" , _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), _hw(_fmc_get_lb_count_32()), _lw(_fmc_get_lb_count_32()));
_lun_data(sensep) = &sense_write_error;
// get virtual addr
map_lba2addr_rd(_fmc_get_start_lb_32()) ;
// enable the correct card
nand_select_card() ;
// copy head
result = map_write_begin( _fmc_get_start_lb_32() ) ;
// make sure we're in the right mode - fixes a bug where
// the first burst of the first split of the xfer begins
// on a zone that needed to be paged in...
sm_set_write_mode_page_data();
// precompute max split size
max_split_size = (_media_data(pages_per_block)-g_addr_page)*_media_data(segments_per_page)-g_addr_segment ;
_lun_data(max_lb_per_split) = _min( max_split_size, _fmc_get_lb_count_32());
trace5(0, n2k, 10, "-----write begin xfer - zone:%d phy:%d log:%d page:%d count:%d", g_addr_zone, g_addr_wr_phy_blk, g_addr_log_blk, g_addr_page, _lun_data(max_lb_per_split) );
// burst size needs to be 1, because the sm controller can't
// handle more than 512 bytes out at a time.
_lun_data(max_lb_per_burst) = 1;
return result ;
}
//+-----------------------------------------------------------------------------
// Name:
// n2k_write_begin_split
//
// Declaration:
// t_result n2k_write_begin_split(void);
//
// Purpose:
// Issue the write command to the smart media device.
//
// Arguments:
// None.
//
// Return:
// A t_result indicating:
// k_success - command completed.
//
// Notes:
// This is a FUNCTION, not a DFA.
// Do not yeild, or run a DFA, from within this callback.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result n2k_write_begin_split() reentrant
{
uint8 zone_before ;
trace0(0, n2k, 1, "sm_write_begin_split()");
trace1(0, n2k, 0, "g_addr_rd_phy_blk: %d", g_addr_rd_phy_blk) ;
zone_before = g_addr_zone ;
// if a new physical block, tell the mapper to go git us one.
if (k_success != map_lba2addr_rd(_fmc_get_start_lb_32()))
return(k_error);
if(g_addr_zone != zone_before)
{
// we've crossed a boundry on a split, do a reset
trace0(0, n2k, 0, "zone-change detected.") ;
nand_select_card() ;
sm_set_write_mode_page_data() ;
}
if(!g_addr_page)
{
if (k_success != map_alloc_wr_blk())
return(k_error);
}
// convert virtual address zone/block/sector into page/offsets
nand_rd_va2pa() ;
nand_wr_va2pa() ;
TRACE0(272, sm, 0, "ready to begin writing sectors") ;
return k_success;
}
//+-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result n2k_write_end_split(void) reentrant
{
trace0(0, n2k, 0, "n2k_write_end_split()") ;
trace2(0, n2k, 0, "split ended on to page %d segment %d", g_addr_page, g_addr_segment) ;
if( g_addr_segment )
{
trace0(0, n2k, 0, "last split. need to flush current page cache") ;
if( k_success != n2k_page_program() )
{
trace0(0, n2k, 0, "n2k_cache_program failed") ;
return k_error ;
}
g_addr_page++;
g_addr_segment=0;
nand_incr_addr() ;
}
return sm_write_end_split() ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_write_begin_burst
//
// Declaration:
// t_result sm_write_begin_burst(void);
//
// Purpose:
// Issue the write command to the smart media device.
//
// Arguments:
// None.
//
// Return:
// A t_result indicating:
// k_success - command completed.
//
// Notes:
// This is a FUNCTION, not a DFA.
// Do not yeild, or run a DFA, from within this callback.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result n2k_write_begin_burst() reentrant
{
trace5(0, n2k, 0, "n2k_write_begin_burst() - zone:%d log:%d-phy:%d page:%d seg:%d", g_addr_zone, g_addr_log_blk, g_addr_wr_phy_blk, g_addr_page, g_addr_segment) ;
trace1(0, n2k, 0, " - n_lbs_this_xfer:%d", g_n_lb_this_xfer.u32) ;
// check to see if we are starting in middle of a page
if(!g_addr_segment)
{
// pre-read the old page into chip cache
n2k_page_read_for_copy() ;
// write data into the on-chip cache, starting at the beginning of the page
n2k_page_write_cache_data() ;
}
_mcu_register_set_bits(sm_mode_ctl,kbm_sm_mode_ecc_blk_xfer_en) ;
_sm_hw_ecc_wr_start() ;
trace0(0, n2k, 0, "bursting") ;
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_write_end_burst
//
// Declaration:
// t_result sm_write_end_burst(void);
//
// Purpose:
// TBD
//
// Arguments:
// None.
//
// Return:
// A t_result indicating:
// k_success - command completed.
//
// Notes:
// This is a FUNCTION, not a DFA.
// Do not yeild, or run a DFA, from within this callback.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result n2k_write_end_burst(void) reentrant
{
TRACE0(273, sm, 0, "n2k_write_end_burst()") ;
_sm_hw_ecc_wr_stop() ;
sm_mode_ctl &= ~kbm_sm_mode_ecc_blk_xfer_en;
TRACE0(274, sm, 0, "ecc_en off") ;
g_addr_segment++ ;
if( g_addr_segment==_media_data(segments_per_page) )
{
trace0(0, n2k, 0, "last burst in the page. program the page cache") ;
if( k_success != n2k_page_program() )
{
TRACE0(275, sm, 0, "n2k_cache_program failed") ;
return k_error ;
}
g_addr_page++;
g_addr_segment=0;
nand_incr_addr() ;
}
return k_success ;
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_sm_write
//
// Declaration:
// void dfa_sm_write(void) reentrant
//
// Purpose:
// Read data from sm media
//
// Arguments:
// None.
// Uses _lun_data and g_bot_cbw to get its parameters.
//
// Return:
// No return value.
// However, on exit the DFA's argument pointer is written with a t_csw_status indicating:
// k_command_passed - command completed.
// k_command_failed - an error occurred.
//
// Notes:
// This is the start STATE of the dfa_ata_write DFA.
// It overrides dfa_lun_write.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void nand_dfa_write(void) reentrant
{
trace0(0, nand, 0, "nand_dfa_write()");
// check for write protection change
if( nand_check_wp() )
{
trace0(0, nand, 0, "error: write protection state changed") ;
__thread_return_dfa(k_error) ;
}
// check for write protection state
if( _mcu_register_rd(x_media_sts)&kbm_media_sts_sm_wp)
{
trace0(0, nand, 0, "error: write protection enabled") ;
_lun_data(sensep) = &sense_media_change ;
__thread_return_dfa(k_error) ;
}
_fmc_set_options(0);
_fmc_set_timeout(10000);
if(k_ix_media_nand == g_ix_media_nand)
{
trace0(0, nand, 0, "preparing for 512-byte per page writes") ;
_fmc_set_callback(sm_write_begin_xfer, sm_write_end_xfer,
nand_write_begin_first_split, sm_write_end_split,
sm_write_begin_burst, fmc_dflt_callback, sm_write_end_burst);
}
else
{
trace0(0, n2k, 0, "preparing for 2048-byte-per-page writes") ;
_fmc_set_callback(n2k_write_begin_xfer, sm_write_end_xfer,
nand_write_begin_first_split, n2k_write_end_split,
n2k_write_begin_burst, fmc_dflt_callback, n2k_write_end_burst);
}
dfa_lun_write();
}
//+-----------------------------------------------------------------------------
// Name:
// sm_power_dn()
//
// Declaration:
// t_result sm_power_dn() reentrant
//
// Purpose:
// erase all physical blocks on media card, then
// rebuild sector mapping table
//
// Arguments:
// none
//
// Return:
// k_success - on successful completion
//
// Notes:
// currently, not a dfa
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result nand_power_dn() reentrant
{
trace0(0, nand, 0, "nand_power_dn()") ;
_sm_hw_set_rd_standby();
return k_success ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -