⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sm.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
/*============================================================================
  ____________________________________________________________________________
                                ______________________________________________
   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 + -