📄 nand.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.
____________________________________________________________________________
____________________________________________________________________________
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 + -