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

📄 sm_media.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
/*============================================================================
  ____________________________________________________________________________
                                ______________________________________________
   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_media.c - implements smart media-specific routines used by the mapper
               to abstract sector mapping from lun processing
  ____________________________________________________________________________

  comments tbd
  ____________________________________________________________________________

  Revision History
  Date      Who  Comment
  ________  ___  _____________________________________________________________
  03/11/02  cds  initial version - moved from former media.c location
  04/18/02  cds  expanded the macros which issued the command to read extra data
                 to debug why sometimes certain phy_blks would report blank extra data
                 and other times that it would not.  Does not affect functionality.
  04/19/02  cds  derived sm_media_resolve_conflict() which resolves a log2phy binding
                 conflict for the mapper.
  05/16/02  cds  updated the card_repair function and surrounded all card repair
                 tables with #if k_sm_repair_card guards so that repair-specific
                 code is only included with the repair build, not a real, functional build
  05/30/02  cds  added sm_media_copy_sector() override which reads/writes to the sram
                 using the fmdu instead of using pio to move the data.  this 
                 improves write performance (approx 3x) by optimizing copy_head/copy_tail
                 when overwritting buffers
  06/27/02  cds  added smart-media specific overrides for setting read/write/erase
                 addresses when accessing the removable-media type flash cards.
  07/09/02  cds  renamed WorkBuf to g_sector_buffer 
  07/29/02  cds  protected software ecc calls to be included only if a sm-lun is
                 in the build.
  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/20/02  cds  - fixed a potential bug in sm_media_write_extra_data, which
                   checked the wrong value of the media_sts_sm_256_page bit, preventing
                   writes to 512 page extra data. 
                 - added trace points to places where errors could occur
  08/27/02  cds  updated set_phyblock_failed to write a failed block status in the 
                 extra data of every page in the block
  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)
  09/05/02  cds  set g_addr_page to 0 before calculating erase address                    
  10/05/02  cds  fixed a glitch in sm_set_write_address which failed to drop the
                 address latch enable bit after setting the address for smart-media cards.            
  10/14/02  cds  - added ecc correction to sm/nand copy-sector() function
  10/16/02  cds  removed protection of boot block in sm_media_write_sector(), so 
                 nand_boot_write_flush can call it.
  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/23/02  cds  - converted copy-sector to perform read-retries on 2-bit errors.  on second failure,
                   block the destination data-status is marked "bad", new ecc data is generated, and 
                   copy completes with a media_copy_error_src
                 - converted rd/wr_va2pa(...) funcs to use 32-bit math to fix multi-zoned 2k page chip 16-bit overflow error.
  10/29/02  cds  - updated copy_sector to copy data-status field if read phy_block has marked that it has a bad data page in it.                 
                 - overrode media_block_has_bad_data() to check if the data status field shows an error on any pages in a phy block
  10/30/02  cds  - moved nand address and card select into sm.c                 
  11/02/02  cds  - fixed read-retry in sm_media_copy_sector function so that on a read-retry, it flips the ep2 direction to prevent 
                   user lba from being received from the host and lost in the copy.  This should fix the 2-bit ecc compliance issues.
                 - updated resolve conflict for new implementation in the mapper which ALWAYS calls the media resolve conflict when two
                   physical blocks have the same logical binding.  By default, we call the map_resolve_conflict first as was behavior in 
                   previous versions.
  11/03/02  cds  - implemented sm_media_is_phyblock_reserved() to single out boot blocks.  
  11/13/02  ds   added a prototype for check_status                 
                   
==============================================================================*/

#define __sm_media_dot_c__
#include "project.h"

// provide vtable definition '_vtbl_cf'
code _vtbl_defn(sm_media) ;

extern uint8 bit_count16(uint16 val) reentrant ;
extern void sm_dbg_dump_redt_data() reentrant;

extern t_result ecc_check_rd_error() reentrant ;
extern t_result ecc_check_and_correct(unsigned char *buf) reentrant ;

extern void sm_pio_rd_buf(uint8 *databuf) reentrant ;
extern void sm_pio_wr_buf(uint8 *databuf) reentrant ;
extern uint8 bit_count8(uint8 val) reentrant ;
extern t_result sm_redt_is_data_valid( void ) reentrant ;
extern t_result sm_check_status(void) reentrant ;
extern t_result sm_read_sect(uint8 *buf) reentrant ;
extern t_result sm_validate_cis(uint8 *buf) reentrant ;
extern t_result sm_wait_rdy_with_timeout(uint16 ticks) reentrant;
void fmc_dbg_dump_sector(uint8* sector) reentrant;

extern xdata uint8 x_sm_redt_data[] ;
extern xdata uint8 g_sector_buffer[] ;


//------------------------------------------------------------------------------
// NAND Flash configuration.
xdata uint8 g_nand_num_chips ; 
xdata uint8 g_nand_zones_per_chip ;     



//+-----------------------------------------------------------------------------
// Name:
//   sm_media_erase_block()
//
// Declaration:
//   t_result sm_media_erase_block(void) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_erase_block(void) reentrant
{
  uint8 save_page ;
  trace4(0, sm_media, 0, "sm_media_erase_block() - zone:%d wr_phy:%d log:%d page:%d", g_addr_zone, g_addr_wr_phy_blk, g_addr_log_blk, g_addr_page) ;

  if( (g_addr_wr_phy_blk == k_block_free) )
    return k_media_err_illegal_lba ;

  save_page = g_addr_page ;
  g_addr_page=0;
  nand_wr_va2pa() ;
  g_addr_page=save_page ;

  _sm_wr_cmd_begin(k_sm_erase1);
  _media_set_erase_addr() ; 
  _sm_set_wr_cmd(k_sm_erase2);

  if (sm_wait_rdy_with_timeout(k_sm_busy_erase_timeout))
  {
    trace0(0, sm_media, 0, "block erase failed.") ;
    nand_cmd_reset_device();
    return k_error ;
  }
  _sm_hw_set_wr_standby();
  _sm_hw_set_rd_standby();
  return k_success ;
}



//------------------------------------------------------------------------------
//+-----------------------------------------------------------------------------
// Name:
//   sm_media_read_sector()
//
// Declaration:
//   t_result sm_media_read_sector(void) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result  sm_media_read_sector(void) reentrant
{
  uint8*buf ;
  uint8 i ;

  trace4(0, sm_media, 0, "+sm_media_read_sector() - zone:%d RD_PHY:%d log:%d page:%d", g_addr_zone, g_addr_rd_phy_blk, g_addr_log_blk, g_addr_page) ;
  buf = _media_data(sector_buffer) ;

  nand_rd_va2pa() ;

  if(!(_mcu_register_rd(x_media_sts) & kbm_media_sts_sm_256_page) )
  {
    trace0(0, sm_media, 0, "reading sector mode: 512+16") ;
    _sm_rd_cmd_begin(k_sm_read) ;
    _media_set_read_addr() ; 
    trace0(0, sm_media, 0, "waiting for data to be read") ;
    if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
    {
      trace0(0, sm_media, 0, "ssfdc_readsect timeout on busy") ;
      nand_cmd_reset_device();
      return k_error ;
    }
    // read sector
    sm_pio_rd_buf(buf) ;

    // read redundant data
    for (i=0x00;i<k_sm_redt_buffer_sz;i++)
      x_sm_redt_data[i] =_sm_data_rd();

    if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
    {
      trace0(0, sm_media, 0, "ssfdc_readsect timed out busy") ;
      nand_cmd_reset_device();
      return k_error ;
    }
  }
  else
  {
    // read even page
    trace0(0, sm_media, 0, "Read Mode:  256+8") ;
    _sm_rd_cmd_begin(k_sm_read) ;
    _media_set_read_addr() ; 
    if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
    {
      trace0(0, sm_media, 0, "ssfdc_readsect timeout on busy") ;
      nand_cmd_reset_device();
      return k_error ;
    }
    // read sector
    sm_pio_rd_buf(buf) ;
    // read extra data
    for (i=0x00;i<0x08;i++)
      x_sm_redt_data[i] =_sm_data_rd();

    if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
    {
      trace0(0, sm_media, 0, "ssfdc_readsect timed out busy") ;
      nand_cmd_reset_device();
      return k_error ;
    }

    // read the odd page
    nand_incr_addr() ;
    _sm_rd_cmd_begin(k_sm_read) ;
    _media_set_read_addr() ; 
    if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
    {
      trace0(0, sm_media, 0, "ReadSect:  Timed Out") ;
      nand_cmd_reset_device();
      return k_error ;
    }

    // move the data
    sm_pio_rd_buf(buf+0x0100);
    // move redundant data
    for (i=0x08;i<k_sm_redt_buffer_sz;i++)
      x_sm_redt_data[i] =_sm_data_rd();

    if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
    {
      nand_cmd_reset_device();
      return k_error ;
    }
  }

  _sm_hw_set_rd_standby();
  sm_synch_hw_buff_to_redt_buf() ;
  return k_success ;
}


//+-----------------------------------------------------------------------------
// Name:
//   sm_media_validate_sector()
//
// Declaration:
//   t_result sm_media_validate_sector(void) reentrant
//
// Purpose:
//   TBD
//
// Arguments:
//   TBD
//
// Return:
//   TBD
//
// Notes:
//   TBD
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_validate_sector(uint8* buf) reentrant ;
t_result sm_media_validate_sector(uint8* buf) reentrant
{
  
#if (k_log_lun_sm < k_max_log_lun)
  // if we're doing sofware ecc, calculate it now
  mcu_begin_critical_section() ;
  ecc_sw_calculate(buf);
  x_eccbuf[1]=ecc_lp_hi;
  x_eccbuf[0]=ecc_lp_lo;
  x_eccbuf[2]=ecc_cp;

  ecc_sw_calculate(buf+0x0100);
  x_eccbuf[4]=ecc_lp_hi;
  x_eccbuf[3]=ecc_lp_lo;
  x_eccbuf[5]=ecc_cp;
  mcu_end_critical_section() ;


  // check buffer for ecc error detection
  if (k_success != ecc_check_rd_error())
  {
    // try to correct the buffer
    if (k_success != ecc_check_and_correct(buf))
      return k_error ;
  }
  return k_success ;
#else
  trace0(0, sm_media, 0, "sm_media_validate_sector():  warning - software ecc disabled") ;
  buf=buf ; // quiet the compiler
  return k_error ;
#endif
}


//+-----------------------------------------------------------------------------
// Name:
//   sm_media_write_sector()
//
// Declaration:
// t_result sm_media_write_sector(uint8 *buf) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_write_sector() reentrant
{
  uint8 i ;
  uint8* buf ;

  trace4(0, sm_media, 0, "+sm_media_write_sector() zone:%d WR_PHY:%d log:%d page:%d", g_addr_zone, g_addr_wr_phy_blk, g_addr_log_blk, g_addr_page) ;

  if( (g_addr_wr_phy_blk == k_block_free) )
    return k_media_err_illegal_lba ;

  buf = _media_data(sector_buffer) ;
  nand_wr_va2pa() ;

  // issue start-of-write command
  _sm_wr_cmd_begin(k_sm_write_data);
  // set the address
  _media_set_write_addr() ; 
  // send the even page
  sm_pio_wr_buf(buf);
  // send even page extra data
  for (i=0x00;i<((_mcu_register_rd(x_media_sts)&kbm_media_sts_sm_256_page)?0x08:0x10);i++)
    _sm_data_wr(x_sm_redt_data[i]);

  // issue the end-of-write command
#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


  if (sm_wait_rdy_with_timeout(k_sm_busy_programming_timeout))
  {
    trace0(0, sm_media, 0, "error waiting for sm to program") ;
    nand_cmd_reset_device();
    return k_error ;
  }

  // for odd pages (on devices that use 'em) do it again.
  if (( _mcu_register_rd(x_media_sts)&kbm_media_sts_sm_256_page))
  {
    _sm_wr_cmd_begin(k_sm_write_data);
    _media_set_write_addr() ; 
    sm_pio_wr_buf(buf+0x0100);

    for (i=0x08;i<k_sm_redt_buffer_sz;i++)
      _sm_data_wr(x_sm_redt_data[i]);

    _sm_set_wr_cmd(k_sm_write);
    if (sm_wait_rdy_with_timeout(k_sm_busy_programming_timeout))
    {
      nand_cmd_reset_device();
      return k_error ;
    }
  }

  _sm_hw_set_wr_standby();
  _sm_hw_set_rd_standby();
  return k_success;
}

//+-----------------------------------------------------------------------------
// Name:
//   sm_media_copy_sector()
//
// Declaration:
// t_result sm_media_copy_sector() reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_copy_sector() reentrant
{
  uint8   err_byte;
  t_bool  retry;
  uint8   data_status;
  t_result result;

  trace4(0, sm_media, 0, "+sm_media_copy_sector() zone:%d SRC_BLK:%d DEST_BLK:%d page:%d", g_addr_zone, g_addr_rd_phy_blk, g_addr_wr_phy_blk, g_addr_page) ;

  if( (g_addr_wr_phy_blk == k_block_free) )
  {
    trace0(0, sm_media, 0, "  error. invalid wr_phy_block: 0xffff") ;
    return k_media_err_illegal_lba ;
  }

  nand_rd_va2pa() ;

  // read retries and data status
  retry=k_false;
  // data status is good
  data_status=0xff;
  result=k_success;
  do
  {
    // TRACE0(164, sm_media, 0, "reading sector mode: 512+16") ;
    _sm_rd_cmd_begin(k_sm_read) ;
    _media_set_read_addr() ; 
    _mcu_register_wr(x_smc_stat, (kbm_smc_stat_ecc_err_d_a|kbm_smc_stat_ecc_err_d_b|kbm_smc_stat_ecc_err_c_a|kbm_smc_stat_ecc_err_c_b));
    _mcu_register_clr_bits(x_smc_stat_msk, (kbm_smc_stat_ecc_err_d_a|kbm_smc_stat_ecc_err_d_b|kbm_smc_stat_ecc_err_c_a|kbm_smc_stat_ecc_err_c_b));
    _mcu_register_set_bits(sm_mode_ctl, kbm_sm_mode_ecc_blk_xfer_en) ;

    x_isr0 = kbm_isr0_fmc_irq ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -