📄 sm.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.
____________________________________________________________________________
____________________________________________________________________________
sm.c - smart media mass storage class implementation file
____________________________________________________________________________
comments tbd
____________________________________________________________________________
Revision History
Date Who Comment
________ ___ _____________________________________________________________
11/##/01 cds initial version
11/27/01 cds overrode _lun_enable_mux with fmc code to enable lun data mux
without caller needing to know what specific device is at that
lun.
01/##/02 cds ported smil library. reads work, writes do not.
01/08/02 cds modified test_unit_ready to simply return "ok", and created
sm_init_controller to initialize smart media-only state
variables
01/15/02 cds - fixed bug in max lba computation. 32 bit value was only
using 16-bit and 8-bit operands and result was being truncated
- adjusted fmc read transfer interaction to only read 1
lba per split until the end of the physical block. at that
point, the max lba per split is set to be equal to physical
block for all remaining lbas. (fmc handles sector remainder
in final phyblock)
02/26/02 tbh added NULL placeholder in _fmc_set_callback() invocations
changed strcpy to strncpy for safety
04/18/02 cds - removed hardware ecc calculations during auto read blk_xfers
to help debug read crc errors.
- Added stub code to switch between
multi-block reads, single-block reads and pio single-block reads
- Added mode sense override to be able to correctly report write-protect
status to the host, so that it never even attempts to send a
write command.
- Added fmc_options() and fmc_timeout() to routines using xfer
routines to ensure fmc behaves properly for our device
- Added entry points that allow you to attempt to 'restore' damaged
cards. by default, these are #if 0'd out.
04/24/02 tbh set sensep to sense_media_change when media becomes known
04/28/02 cds - issued a soft-reset when a zone-change occurs (and possily a
new sector-map built) between write splits.
05/16/02 cds moved k_smart_media_eraser option into sm.h
05/24/02 cds fixed addressing bug when calculating offset of error byte
when a 1-bit error is detected during fmc blk xfer. Also
created compile-time option to turn error correction code
on or off.
05/30/02 cds turned off auto-xfer in sm_write_end_xfer, before calling write_flush
so that the write_flush could make use of the sram buffers
when doing sector copies.
06/03/02 cds checked for error before turning off auto-xfer bit & doing
copy_flush() in sm_write_end_xfer.
06/26/02 cds fixed a typo in read_end_burst to trap both single-bit error cases
06/27/02 cds removed sm_set_rd_addr() and sm_set_wr_addr(), and replaced
calling code to instead call the virtual media method to
do it.
06/29/02 ds Removed check for write-protection on write commands.
07/01/02 tbh write-protect is now handled at the lun layer, but since SM
uses primordial code to detect wp i put the test back in here
to be safe.
07/02/02 cds separated sm_read_id() command from sm_identify_media flash
configuration detection case statement. This allows derived
nand.c to get an id-code w/o an interpretation for auto-detection
or for non-smart media codes that may get returned.
07/09/02 cds renamed WorkBuf to g_sector_buffer
07/12/02 tbh lun string name change caued by mandate from on high
07/29/02 cds - removed g_media_err_code references
- protected software ecc calls to only be included if
there is a smart media lun, since the nand code does not
do software ecc
- reduced sm_identify_media_format by detecting parameters,
then copying them into the media structure at the end.
07/31/02 cds called media_set_active(...) instead of setting g_active_media
to select a new media object.
08/06/02 cds added code to "write protect" 256+8 page smart media cards,
so that existing cards can be read, but not written to.
08/09/02 cds - used attribute flag to determine whether to force Smart Media
compatible rw cycle timing for a data xfer.
- separated setting the device address from code that calculates
a the physical address from the mapper's virtual address.
- converted physical address variable into 3 separate xdata bytes
for quick-access when incrementing & writing to the device.
08/13/02 cds added support for a new identify media command that describes a
smart media card with the ability write/erase multiple blocks
simultaneously
08/14/02 cds fixed a bug with write/erase functionality that was caused by
not initializing g_nand_rw_speed... there by sending garbage
commands to the smc.
08/20/02 cds - updated k_trace_hw_sm tracepoints to be more readable
- removed #if/#endif statements from around the hardware ECC (must be used now!)
- re-added a line of code that drops CE after every WRITE split
(need to test if this can be safely removed to improve n2k performance)
09/04/02 cds - address name & usage change-over
g_addr_sector => g_addr_page,
g_addr_page => g_addr_segment,
_media_data(sectors_per_block) => _media_data(pages_per_block)
_media_data(cis_phy_block) => _media_data(boot_block)
_media_data(cis_sector) => _media_data(boot_sector)
(new item) => _media_data(segments_per_page)
- debugging hooks added into new nand_utils.c module
09/11/02 cds added a sm_soft_reset() call in write_begin_first_split, in case
a write begins on the first page of a new zone that needed to be
paged in.
09/12/02 tbh replaced strncpy() with memcpy() to save data space.
09/19/02 cds set default media optimization options to none, and general
codecleaning.
09/22/02 cds set lun_media_process_idle flag after a write to indicate that
cache needs flushing when device goes idle
checks for write-caching on dfa_read
10/03/02 cds - fixed 1-bit ecc code to correctly resume a transfer by turning off
auto-transfer, correcting the bit, transmitting the buffer, waiting
for tx interrupt bit, then re-enabling auto-xfer. This fixed
code is a bit dangerous, for it waits infinitely for the host
to accept the corrected packet.
- extracted sram bit correction code into a function to conserve
code space
- updated ecc detection code to use ramwr toggle to determine
which buffer has the error bit, instead of trying to detect
it from the isr0 ram wr/rd a/b toggles.
10/05/02 cds - fixed repair card to call nand_util code to repair a smart media
card if the boot block becomes corrupted.
(update) force book block repair if the k_sm_repair_flag is set, whether
a valid one is found or not.
10/14/02 cds - fixed sm_read_end_burst() to only issue a k_resume if there is more blk xfer to do.
10/15/02 cds - updated sm_read_end_burst() to return immediately with error in case of double-bit error detected, or
if single-bit error detected in full-speed mode.
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
10/29/02 cds - checked mapper to verify all data pages are valid before staring a split
- added function sm_check_data_status(..) to check range of pages for bad data_status fields.
if any field has less than 4 bits set, it is considered to be 'bad'
10/30/02 cds - worked around hardware glitch that doesn't bother to tell us which buffer contains the
1-bit ecc error it told us about. The buffer is calculated by comparing the fmc_cnt with
what it was originally. This only works as long as subsequent xfers are either even in count, or the last one.
(which it happens to for our purposes)
10/31/02 cds - fixed 1-bit ecc error buffer detection by reading the bit BEFORE turning off auto-xfer. This simplifies the code
11/02/02 cds - minor tweaks to code that set and cleared bits,
- updated tracepoint categories
- removed remnants of 1-bit ecc buffer determination code.
11/13/02 ds added bit_count fns that are referred to but not compiled in. fixed it.
11/13/02 ds modified sm_wait_rdy_with_timeout to incorporate nand_interleave_media's check for busy signal.
============================================================================*/
#define __sm_dot_c__
#include "project.h"
// provide vtable definition '_vtbl_cf'
code _vtbl_defn(sm) ;
extern xdata uint8 x_sm_redt_data[] ;
//-----------------------------------------------------------------------------
// smart media 'media layer" routines
//-----------------------------------------------------------------------------
t_result sm_media_check_format(void)reentrant;
t_result sm_media_seek_cis(void) reentrant;
t_result sm_read_cis_sect(uint8 *)reentrant;
t_result sm_validate_cis(uint8 *) reentrant ;
t_result sm_media_erase_block(void)reentrant;
t_result sm_media_erase_card(void)reentrant;
t_result sm_wait_rdy_with_timeout(uint16 ) reentrant;
//-----------------------------------------------------------------------------
// read fmc xfer callbacks
//-----------------------------------------------------------------------------
t_result sm_read_begin_xfer(void) reentrant;
t_result sm_read_end_xfer(void) reentrant ;
t_result sm_read_begin_split(void) reentrant;
t_result sm_read_end_split(void) reentrant ;
t_result sm_read_end_burst(void) reentrant ;
//-----------------------------------------------------------------------------
// write fmc xfer callbacks
//-----------------------------------------------------------------------------
t_result sm_write_begin_xfer(void) reentrant;
t_result sm_write_end_xfer(void) reentrant ;
t_result sm_write_begin_split(void) reentrant;
t_result sm_write_begin_first_split() reentrant ;
t_result sm_write_end_split(void) reentrant ;
t_result sm_write_begin_burst(void) reentrant;
t_result sm_write_end_burst(void) reentrant ;
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
t_result nand_cmd_read_id(void) reentrant;
t_result nand_cmd_read_id_ex(void) reentrant;
t_result nand_cmd_check_status(void) reentrant;
t_result nand_cmd_reset_device(void) reentrant;
//+------------------------------------------------------------------------
// redundant data buffer functions
//-------------------------------------------------------------------------
extern xdata uint8 g_sector_buffer[k_sm_sector_sz] ;
uint8 bit_count8 ( uint8 ) reentrant ;
uint8 bit_count16( uint16 ) reentrant ;
//+------------------------------------------------------------------------
// utility (debug) functions
//-------------------------------------------------------------------------
t_result util_blank_smart_media_card(void) reentrant ;
void util_trace_buffer(uint8* sector, uint16 size) reentrant;
void util_trace_ms_extra_data() reentrant;
void util_trace_nand_extra_data() reentrant;
void util_trace_page() reentrant;
void util_trace_map_data() reentrant;
void util_trace_phy_block() reentrant;
void util_trace_zone() reentrant;
void util_trace_media() reentrant;
void util_trace_map_media() reentrant ;
void util_safe_erase_media() reentrant ;
void util_trace_log_media() reentrant ;
void util_create_bad_128mb_media(void) reentrant;
void util_test_hardware_ecc(uint32 lba, uint16 ix_bit) reentrant;
void util_create_1bit_error(uint32 lba) reentrant;
void util_create_2bit_error(uint32 lba) reentrant;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#define _hdw_clk_domain_bug_workaround() { _nop_(); _nop_(); }
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
xdata uint8 x_sm_redt_data[k_sm_redt_buffer_sz] ;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
xdata uint16 _sm_log2phy[k_sm_max_zones_per_table*k_sm_max_lb_per_zone];
xdata uint8 _sm_assign_map[k_sm_max_zones_per_table*k_sm_max_block_num/8];
xdata uint8 _sm_valid_data_map[k_sm_max_zones_per_table*k_sm_max_block_num/8];
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
xdata uint8 g_nand_rw_speed ;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
xdata uint8 g_nand_rd_addr_msb ;
xdata uint8 g_nand_rd_addr_mid ;
xdata uint8 g_nand_rd_addr_lsb ;
xdata uint8 g_nand_wr_addr_msb ;
xdata uint8 g_nand_wr_addr_mid ;
xdata uint8 g_nand_wr_addr_lsb ;
#ifdef k_trace_hw_smc
// trace functions
void sm_set_rd_cmd(uint8 cmd) reentrant ;
void sm_set_wr_cmd(uint8 cmd) reentrant ;
void _sm_set_rd_cmd(uint8 cmd) reentrant
{
trace1(0, sm, 50, "sm_set_rd_cmd(%02x)", cmd) ;
_sm_hw_set_rd_cmd();
_sm_data_wr(cmd);
_sm_hw_set_rd_data(g_nand_rw_speed);
}
void _sm_set_wr_cmd(uint8 cmd) reentrant
{
trace1(0, sm, 50, "_sm_set_wr_cmd(%02x)", cmd) ;
_sm_hw_set_wr_cmd() ;
_sm_data_wr(cmd);
_sm_hw_set_wr_data(g_nand_rw_speed);
}
uint8 _sm_data_rd() reentrant
{
uint8 val ;
val = sm_data ;
trace1(0, sm, 50, "sm_data_rd(): %02x", val) ;
return (val );
}
void _sm_data_wr(uint8 val) reentrant
{
trace1(0, sm, 50, "sm_data_wr(): %02x", val) ;
sm_data=val ;
}
void _sm_hw_set_rd_data(uint8 msk) reentrant
{
sm_mode_ctl=(uint8)(kbm_wr_data|kbm_enable_wp|msk);
trace1(0, sm, 50, "_sm_hw_set_rd_data() - sm_mode_ctl:%02x", (kbm_wr_data|kbm_enable_wp|msk)) ;
}
void _sm_hw_set_rd_cmd() reentrant
{
trace1(0, sm, 50, "_sm_hw_set_rd_cmd() - sm_mode_ctl:%02x", (kbm_wr_cmd|kbm_enable_wp)) ;
sm_mode_ctl=(uint8)(kbm_wr_cmd| kbm_enable_wp);
}
void _sm_hw_set_rd_addr() reentrant
{
sm_mode_ctl=(uint8)(kbm_wr_addr|kbm_enable_wp) ;
trace1(0, sm, 50, "_sm_hw_set_rd_addr() - sm_mode_ctl:%02x", (kbm_wr_addr|kbm_enable_wp)) ;
}
void _sm_hw_set_rd_standby() reentrant
{
sm_mode_ctl=(uint8)(kbm_standby|kbm_enable_wp) ;
trace1(0, sm, 50, "_sm_hw_set_rd_standby() - sm_mode_ctl:%02x", (kbm_standby|kbm_enable_wp)) ;
}
void _sm_hw_set_wr_data(uint8 msk) reentrant
{
sm_mode_ctl=(uint8)(kbm_wr_data|kbm_disable_wp|msk);
trace1(0, sm, 50, "_sm_hw_set_wr_data() - sm_mode_ctl:%02x", (kbm_wr_data|kbm_disable_wp|msk) ) ;
}
void _sm_hw_set_wr_cmd() reentrant
{
sm_mode_ctl=(uint8)(kbm_wr_cmd|kbm_disable_wp) ;
trace1(0, sm, 50, "_sm_hw_set_wr_cmd() - sm_mode_ctl:%02x", (kbm_wr_cmd|kbm_disable_wp)) ;
}
void _sm_hw_set_wr_addr() reentrant
{
sm_mode_ctl=(uint8)(kbm_wr_addr|kbm_disable_wp) ;
trace1(0, sm, 50, "_sm_hw_set_wr_addr() - sm_mode_ctl:%02x", (kbm_wr_addr|kbm_disable_wp)) ;
}
void _sm_hw_set_wr_standby() reentrant
{
sm_mode_ctl=(uint8)(kbm_standby|kbm_disable_wp);
trace1(0, sm, 50, "_sm_hw_set_wr_standby() - sm_mode_ctl:%02x", (kbm_standby|kbm_disable_wp)) ;
}
void _sm_rd_cmd_begin(uint8 cmd) reentrant
{
trace1(0, sm, 50, "_sm_rd_cmd_begin(%02x).", cmd) ;
x_smc_stat = kbm_smc_stat_rdy ;
trace1(0, sm, 0, "x_smc_stat = %02x", kbm_smc_stat_rdy) ;
sm_set_rd_cmd(cmd);
}
\void _sm_wr_cmd_begin(uint8 cmd) reentrant
{
trace1(0, sm, 50, "_sm_wr_cmd_begin(%02x)", cmd) ;
x_smc_stat = kbm_smc_stat_rdy ;
trace1(0, sm, 0, "x_smc_stat = %02x", kbm_smc_stat_rdy) ;
sm_set_wr_cmd(cmd);
}
t_bool _sm_hw_bsy() reentrant
{
uint8 val ;
val = (!(x_smc_stat & kbm_smc_stat_rdy))?k_true:k_false ;
trace1(0, sm, 50, "_sm_hw_bsy? %c", (val?'Y':'N')) ;
return (val );
}
#endif
//+-----------------------------------------------------------------------------
// Name:
// sm_dbg_dump_redt_data()
//
// Declaration:
// void sm_dbg_dump_redt_data(uint8 cmd) reentrant
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// TBD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -