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

📄 nand.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.
  ____________________________________________________________________________
  ____________________________________________________________________________
  nand.c - nand flash fixed media mass storage class implementation
  ____________________________________________________________________________
  comments tbd
  ____________________________________________________________________________
  Revision History
  Date      Who  Comment
  ________  ___  _____________________________________________________________
  06/21/02  cds  initial version - implements the methods for a raw nand-flash
                 fixed media lun.  The NAND lun is derived from the removable
                 smart media lun, but should be able to co-exist with smart
                 media as a separate physical lun.
  06/25/02  cds  incorporated boot block reading/writing for device usb config
                 info
  06/26/02  cds  fixed multi-card reads/writes by adjusting when the card select
                 is called in the fmc xfers, and fixed the chip select to
                 multiply the # of chips by the max zone for the particular type
                 of chip detected, instead of assuming that it was 8 zones per chip.
  06/27/02  cds  - implemented nand-specific set_read/write/erase addr functions
                 that can be called vcalled from the smart media base class.  these
                 functions calculate the chip-based zone from the global g_addr_zone.
                 - fixed select_chip equation to correctly select a chip from g_addr_zone
                 - added new variables g_nand_num_chips and g_nand_max_zones_per_chip
                   to allow future chip auto-detection.
  07/02/02  cds  added auto-detection for 1-chip (no or-gate)/n-chip configurations.
                 After detecting # of chips, detects flash configuration from
                 smart media card-select code.
  07/08/02  cds  updated nand_dfa_write to include write-protect updates that
                 affected smart media.
  07/09/02  cds  - renamed WorkBuf to g_sector_buffer
                 - during read_begin_split, waited until after busy before
                   enabling ecc detection
  07/10/02  cds  updated nand_read_begin_split() to use mcu_register_wr(...)
                 instead of mcu_register_set_bits(...) on the smc_stat register
                 to clear the ecc status bits.
  07/19/02  cds  - protected password-specific code with #ifdef k_opt_password
                 - added definition of g_ix_media_nand, instead of using an array
                 to swap media instances. (similar to sd/mmc lun dynamic subclassing)
  07/19/02  baw  Added initialization of lockable bit in nand_initialize_controller
  07/23/02  baw  moved initialization of removable media from nand_initialize_controller
                 to dev_validate_nvstore
  07/29/02  cds  - added nand_select_media() to switch between nand_media and n2k_media
                   objects based on what was detected
                 - updated nand_identify_media_format() to select appropriate media class
                   before setting any media instance variables
                 - updated card id 0xf1 with Toshiba parameters.  (this will have to
                   be updated again to determine the capacity of the chips)
                 - updated 2k map parameters to be a single zone of 1024 blocks.
                 - updated nand_read_begin_xfer to only do single block read xfers,
                   to prevent sequential reads from freezing the fmc_xfer (to be debugged)
                 - updated nand_read_begin_split to begin reads at the appropriate
                   column offset for 2k page sized chips.
                 - added entire new dfa_write to handle fmc xfers to 2k paged media
                 - removed bogus init_unit()
  07/31/02  cds  called media_set_active(...) instead of setting g_active_media
                 to select a new media object.
  08/06/02  cds  - fixed a bug in the n2k_write_begin_xfer() by doing a chip select
                   before calling the copy_head function.
                 - added extra smarts to distinguish between Toshiba & Samsung
                   2k page nand chips.
  08/09/02  cds  - used attribute flag to determine whether to force Smart Media
                   compatible rw cycle timing for a data xfer.
  08/13/02  cds  - identify Samsung vs Toshiba chips.
                 - identify & setup 2 Mbit chips
                 - removed some debug code which erased cards on boot-up...  whoops
  08/20/02  cds  added functions to test read cache functions of 2k page media types
  08/21/02  cds  altered nand select chip to use detect the mcu and pick correct gpiob scheme
  08/27/02  cds  - fixed a glitch where 2k page nands were not correctly initializing
                   the read cycle speed bit.
                 - added code to report media change whenever a test-unit-ready or
                   write command comes down from the host and the write-protect bit
                   has changed.  This forces the host to detect the new state of the bit
                 - added attribute bit to determine how the device should enumerate.
                   if set, always enumerate as a removable-media type drive
                   if clear & write protected, enumerate as removable media drive
                   if clear & not write protected, enumerate as normal fixed media drive
  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)
                 - nand_select_card moved to sm.c to allow sm to switch between
                   nand cards and smart media slot when necessary
  09/05/02  cds  - n2k read & writes working again (but code bloated up to 50K)
                 - added password check to determine if lun reports itself as removable or fixed
                   before the inquiry data.
  09/10/02  cds  combined duplicated calculation code to one spot to save code space
  09/12/02  tbh  replaced strncpy() with memcpy() to save data space.
  09/19/02  cds  - unified n2k & nand fmc write code
                 - set location to enable media optimization options (erase caching... currently off)
                 fixed nand corruption (same place as sm corruption)
  09/22/02  cds  - added idle_process hook to flush cache on an idle message,
                 - added call to flush cache on nand_dfa_read, and on idle processing
                 - added flag to enable/disable whether write-caching (independently of erase-caching)
                 - enabled erase caching by default for nand devices
                 - defined buffer for use by the erase cache code for this lun
                 - #if'd out calls to write-caching functions to save code space
  10/01/02  cds  - surrounded nand_erase_block() with critical section to avoid
                   an intervening isr from causing a stack overrun.
  10/11/02  cds  - fixed check_wp() to only look at write-protect bit when determining if the wp has changed.
                   (this fixes a bug in WinME/Win98 that was failed to unlock the media after validating a password)
  10/15/02  cds  - added new code for Samsung 2GB chips so that they are properly identified.
  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 data status bits to see if data is good on all lbas before starting a split                 
  11/13/02  ds   intialized g_addr_segment to zero in order to select the right chip for interleave demo.                   
  11/19/02  ds   fixed the corner case with reads crossing block boundaries.
  11/19/02  cds  created polling loop in read_begin_split to quickly start fmc_xfers w/o fmc loop overhead for interleaving
                 created polling loop in write_begin_split to quickly start fmc_xfers w/o fmc loop overhead for interleaving
  11/20/02  ds   Fixed a bug in read_begin_split where the wrong chip was selected on a zone change.               
  11/20/02  ds   Fixed a minor bug in read_begin_split where it does not return immediately on a abort conditions.
  11/20/02  ds   Ensured proper chip select for nand_int.
                 Enabled interrupts around data xfer loop.
  ============================================================================*/
#define __nand_dot_c__
#include "project.h"
#include "dev.h"

// provide vtable definition 'nand'
code _vtbl_defn(nand) ;

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
xdata uint8 g_ix_media_nand ;

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
static xdata uint8 _nand_media_status ;

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void n2k_test_read_sequential() reentrant;

//-----------------------------------------------------------------------------
// 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_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 ;

//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
void util_trace_media() reentrant;
void util_trace_map_media() reentrant;
void util_trace_phy_block() reentrant;
void util_trace_log_media() reentrant;
void util_safe_erase_media() reentrant;
void util_test_hardware_ecc() reentrant;
void util_test_copy_double_bit_ecc(uint32 lba) reentrant;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
xdata uint16 _nand_log2phy[k_nand_max_zones_per_table*k_nand_max_lb_per_zone] ;
xdata uint8  _nand_assign_map[k_nand_max_zones_per_table*k_nand_max_pb_per_zone/8] ;
xdata uint8  _nand_erase_cache_map[k_nand_max_zones_per_table*k_nand_max_pb_per_zone/8] ;



//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
static void nand_select_media(t_ix_media sel)
{
  TRACE1(361, nand, 0, "selecting new nand media media class:%d", sel) ;
  g_ix_media_nand = sel ;
  media_set_active(g_ix_media_nand) ;
}

//+-----------------------------------------------------------------------------
// Name:
//   nand_identify_media_format()
//
// Declaration:
//   t_result nand_erase_all(void) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result nand_identify_media_format(void) reentrant
{
  uint8 id ;
  uint8 id_test ;
  uint8 addr_segment;
  TRACE0(362, nand, 0, "nand_identify_media_format()") ;

  g_addr_zone=0 ;
  g_nand_zones_per_chip = 1 ;
  //ds set to segment 0 to start up
  g_addr_segment = 0;
  nand_int_select_chip(g_addr_segment);
  id = sm_read_id() ;

  // check to see if this is a one-chip, which no chip-select hanging off gpiob
  // if we disable all chips, then issue the command on a one-chip board, and
  // match the first id, either we see none, or one.
  // read-id command,
//#ifndef k_interleave_demo
  if (_mcu_register_rd(x_chip_id) == 0x18)
  {
    //this has to change depending on chip!! for 242 $$$
    _mcu_register_wr(x_gpiob_out, 0x00) ;
  }
  else
  {
    //this has to change depending on chip!! for 211/210 $$$
    _mcu_register_wr(x_gpiob_out, 0xff) ;
  }
//#endif
  id_test=sm_read_id() ;
  if (id == id_test)
  {
    TRACE0(363, nand, 0, "Single NAND Flash version detected.") ;
    g_nand_num_chips=1 ;
  }
  else
  {
    // loop through cards until we don't have a match for the ID
    for (g_addr_zone=1;g_addr_zone<8;g_addr_zone++)
    {
      nand_select_card() ;
      id_test=sm_read_id() ;
      TRACE2(364, nand, 0, "chip %d id: %02x", g_addr_zone, id_test) ;
      if ( id_test != id )
        break;
    }
    g_nand_num_chips=g_addr_zone ;
    /*  for (addr_segment=1;addr_segment<3;addr_segment++)
      {
        nand_int_select_chip(addr_segment);
        id_test=sm_read_id() ;
        TRACE2(365, nand, 0, "chip %d id: %02x", addr_segment, id_test) ;
        if ( id_test != id )
          break;
      }
      g_nand_num_chips=addr_segment;*/

  }

  TRACE1(366, nand, 0, "detected %d chips", g_nand_num_chips) ;

  g_addr_zone=0 ;
  nand_int_select_chip(0);
  sm_read_id() ;
  switch (nand_id_maker)
  {
    case 0x98:
      {
        TRACE0(367, nand, 0, "Toshiba NAND Flash Chip") ;
        switch (nand_id_device)
        {
          case 0xf1:
            {
              nand_select_media(k_ix_media_nand_2k) ;
              TRACE0(368, nand, 0, "128MB Capacity - Zones:1, PB/Zone:1024, LB/Zone:1000, Pages/Blk:64 Bytes/Page:2112") ;
              _media_data(options)=kbm_media_data_opt_none;
              _media_data(num_zones)                    = 1;
              _media_data(physical_blocks_per_zone)     = 1024;
              _media_data(logical_blocks_per_zone)      = 1000;
              _media_data(logical_blocks_per_boot_zone) = 1000;
              _media_data(pages_per_block)              = 64;
              _media_data(segments_per_page)            = 4 ;
              _mcu_register_clr_bits(x_media_sts, kbm_media_sts_sm_256_page) ;
            }
            break;

          case 0xAA:
          case 0xDA:
            {
              TRACE0(369, nand, 0, "256MB Capacity - Zones:2, PB/Zone:1024, LB/Zone:1000, Pages/Blk:64 Bytes/Page:2112") ;
              nand_select_media(k_ix_media_nand_2k) ;
              _media_data(options)=kbm_media_data_opt_none;
              _media_data(num_zones)                    = 2;
              _media_data(physical_blocks_per_zone)     = 1024;
              _media_data(logical_blocks_per_zone)      = 1000;
              _media_data(logical_blocks_per_boot_zone) = 1000;
              _media_data(pages_per_block)              = 64;
              _media_data(segments_per_page)            = 4 ;
              _mcu_register_clr_bits(x_media_sts, kbm_media_sts_sm_256_page) ;
            }
            break;

          default:
            {
              nand_select_media(k_ix_media_nand) ;
              sm_identify_media_format() ;
            }
            break;
        }
      }
      break;

    case 0xec:
      {
        TRACE0(370, nand, 0, "Samsung NAND Flash Chip") ;
        switch (nand_id_device)
        {
          case 0xf1:
            {
              nand_select_media(k_ix_media_nand_2k) ;
              TRACE0(371, nand, 0, "128MB Capacity - Zones:1, PB/Zone:1024, LB/Zone:1000, Pages/Blk:64 Seg/Page:4") ;
              _media_data(options)=kbm_media_data_opt_none;
              _media_data(num_zones)                    = 1;
              _media_data(physical_blocks_per_zone)     = 1024;
              _media_data(logical_blocks_per_zone)      = 1000;
              _media_data(logical_blocks_per_boot_zone) = 1000;
              _media_data(pages_per_block)              = 64;
              _media_data(segments_per_page)            = 4;
              _mcu_register_clr_bits(x_media_sts, kbm_media_sts_sm_256_page) ;
              break;
            }
          case 0xAA:
          case 0xDA:
            {
              nand_select_media(k_ix_media_nand_2k) ;
              TRACE0(372, nand, 0, "256MB Capacity - Zones:2, PB/Zone:1024, LB/Zone:1000, Pages/Blk:64 Seg/Page:4") ;

⌨️ 快捷键说明

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