?? inand.c
字號:
//-----------------------------------------------------------------------------
// Copyright (c) 2005 Cypress Semiconductor, Inc. All rights reserved
//
// File: inand.c
// Contents:
// Interleave NAND support the bInterLeave Flag will enable
// Odd number NAND chips, the interleave FW will be disable
// Even number NAND chips, then interleave FW will be enable
//
// Support: Both 512 NAND and 2K NAND
// To support 2K NAND use the compiler switch NAND_2K
//
// indent 4. NO TABS!
//--------------------------------------------------------------------------
//
// Copyright 2005, Cypress Semiconductor Corporation.
//
// This software is owned by Cypress Semiconductor Corporation (Cypress)
// and is protected by and subject to worldwide patent protection (United
// States and foreign), United States copyright laws and international
// treaty provisions. Cypress hereby grants to licensee a personal,
// non-exclusive, non-transferable license to copy, use, modify, create
// derivative works of, and compile the Cypress Source Code and derivative
// works for the sole purpose of creating custom software in support of
// licensee product to be used only in conjunction with a Cypress integrated
// circuit as specified in the applicable agreement. Any reproduction,
// modification, translation, compilation, or representation of this
// software except as specified above is prohibited without the express
// written permission of Cypress.
//
// Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,
// WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
// Cypress reserves the right to make changes without further notice to the
// materials described herein. Cypress does not assume any liability arising
// out of the application or use of any product or circuit described herein.
// Cypress does not authorize its products for use as critical components in
// life-support systems where a malfunction or failure may reasonably be
// expected to result in significant injury to the user. The inclusion of
// Cypress' product in a life-support systems application implies that the
// manufacturer assumes all risk of such use and in doing so indemnifies
// Cypress against all charges.
//
// Use may be limited by and subject to the applicable Cypress software
// license agreement.
//
//--------------------------------------------------------------------------
//
// Note:
// This code has been optimized for Performance, so there are global variables
// have been used instead of passing variables to subroutines.
// Any variables start with the prefix letter "g" indicates "Global" variable.
//
// pragma OT(7, SPEED) should not be removed. If remove, the compiler might generate
// the code which will result slower performance
//
// The design of this code does not follow Smart Media standard for the following:
//
// 1. Redundant structure
// BYTE data_status = 0xff = good, else bad block
// BYTE boot_loader_status = 0xff = free block else used block
// BYTE ECC[6]
// WORD Address1, Address2
// BYTE Reserved[4] = 0xff
//
// 2. The "Address1" and "Address2" do not have parity bit. The BuidTable does
// support error bit checking via compare these address fields. If not mach
// if will continue to search for good address fields in the next page until
// 3 times of retry.
//
// 3. Zone table size is 1000
//
// $Workfile: inand.c $
// $Date: 8/08/05 10:49a $
// $Revision: 1 $
// History: May/12/05 Initial Release to customer
//-----------------------------------------------------------------------------
#include "globals.h"
xdata WORD gLog2Phy[cMaxBlock]; // bit0-11 addr map, bit12=1=free, 0=used
BYTE gCurZone, gZones, gBankSel, gPartialCpy; // Use this byte to reload the Table
WORD gDst, gSrc, gFreeBlk; // These variable will be shared
DWORD gSrcAdd, gPhyAdd, gNextLBA; // sharing variables in multiple subrountines
BYTE ecc0[6], ecc1[6]; // Optimize ECC variables
BYTE gSrcBlk0; // use for EraseBlock
xword *pDst;
#ifndef USE_2NAND
// fast coding for bank select
const char code aBanks[4]={0xfc, 0xf3, 0xcf, 0x3f}; // interleave bank
const char code aBank0[4]={0xfe, 0xfb, 0xef, 0xbf}; // interleave bank
const char code aBank1[4]={0xfd, 0xf7, 0xdf, 0x7f}; // interleave bank
const char code nBank[8]={0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
BYTE gEnableBanks;
#ifndef NAND_2K
BYTE gEnableBank0, gEnableBank1; // optimize variables
#endif
#endif
// Note: These variables below will be used to optimize speed
// These variables use in conjunction with MPAGE that map to 0xE6xx
pbyte P_GPIFTCB0 _at_ 0xd1; // GPIFTCB0
pbyte P_GPIFTCB1 _at_ 0xd0; // GPIFTCB1
pbyte P_XAUTODAT1 _at_ 0x7b; // XAUTODAT1
pbyte P_XAUTODAT2 _at_ 0x7c; // XAUTODAT2
pbyte P_ECC1B0[6] _at_ 0x2a; // 6 bytes ECC registers
pbyte P_INPKTEND _at_ 0x48; // INPKTEND
pbyte P_OUTPKTEND _at_ 0x49; // OUTPKTEND
pbyte P_ECCCFG _at_ 0x28; // ECCCFG
pbyte P_ECCRESET _at_ 0x29; // ECCRESET
pbyte P_EP6BCH _at_ 0x98; // EP6BCH
pbyte P_EP6BCL _at_ 0x99; // EP6BCL
pbyte P_EP4BCH _at_ 0x94; // EP4BCH
pbyte P_EP4BCL _at_ 0x95; // EP4BCL
pbyte P_GPIFREADYSTAT _at_ 0xf4; // GPIFREADYSTAT
pbyte P_FIFORESET _at_ 0x04; // FIFORESET
pbyte P_EP6CFG _at_ 0x14; // EP6CFG
pbyte P_EP2FIFOCFG _at_ 0x18; // EP2FIFOCFG
pbyte P_XGPIFSGLDATLX _at_ 0xf1; // XGPIFSGLDATLX
pbyte P_XGPIFSGLDATLNOX _at_ 0xf2; // XGPIFSGLDATLNOX
pbyte P_EP2CS _at_ 0xa3; // EP2CS
pbyte P_EP4CS _at_ 0xa4; // EP4CS
//==========================================================================
// NAND Hardware/software init
// Donot call this subroutine during the SOFT RESET (i.e. softReset)
//==========================================================================
void InitNAND()
{
gNandBits = 0; // all the NAND bits variables = 0
FwCfg = 0;
NandCfg = 0;
gFreeBlk = 0;
gPartialCpy = 0;
dwLBA = 0;
GetNandCfg(); // Get NAND Configuration from MFG TOOL
directionIn=1; // Compute Log2Phy Table at init time
NAND_WP = 1;
gCurZone = 0xff; // Load current zone
Log2Phy();
ready_default(); // restore default value
#ifndef NO_WP
bWPSwitchState = NAND_WP_SWITCH;
#endif
DISABLE_NAND();
}
//==========================================================================
// Get Free block from LUT
// This search always return a free block
//==========================================================================
void nGetFreeBlk()
{
while (!bFreeFound) // search until found free block
nSearchFreeBlock(0); // will search for 256 entries
bFreeFound = 0;
}
//==========================================================================
// NAND EraseBlocks on both banks
// input: gSrcAdd = Current Src Block
//==========================================================================
void nEraseBlock()
{
if (bNeedErase) // only erase if needed
{ // erase both banks in the interleave mode
#ifndef NAND_2K
#ifdef USE_2NAND
CE0_ON(), CE1_ON(); // Enable both banks for interleave mode
#else
IOD=gEnableBanks; // non-interleave this should be only 1 bank
#endif
#endif
xSrcAdd = gSrcBlk0;
nand_blk_erase(gSrcAdd);
// after erasing the NAND, there are some spare time for background search
nSearchFreeBlock(0); // will search for 256 entries
}
}
#pragma OT(7, SPEED) // Use this optimize for the speed
//==========================================================================
// Clear 16-byte each pass.
// Maximun 4K buffer
//==========================================================================
void memset16(BYTE xdata *dest, BYTE c, BYTE len)
{
AUTOPTR1H = MSB(dest); AUTOPTR1L = LSB(dest);
do
{ // Unrole the loop to speed up memory fill
P_XAUTODAT1 = P_XAUTODAT1 = P_XAUTODAT1 = P_XAUTODAT1 =
P_XAUTODAT1 = P_XAUTODAT1 = P_XAUTODAT1 = P_XAUTODAT1 =
P_XAUTODAT1 = P_XAUTODAT1 = P_XAUTODAT1 = P_XAUTODAT1 =
P_XAUTODAT1 = P_XAUTODAT1 = P_XAUTODAT1 = P_XAUTODAT1 = c;
} while (--len>0);
}
//==========================================================================
// Read NAND Pages: Supports for both interleave and non-interleave
// return bErr and b2BitErr, which will send STALL to USB Host
// Modify:
// ecc0[] and ecc1[]
// bMsk, bCnt
//==========================================================================
void nReadPages()
{
#ifdef NAND_2K
Log2Phy(); // remap logical blocks
// Read the first 512 byte data and save all the ECC data in ecc0[]
// and ecc1[] buffers. The CheckECC will be called to verify the ECC
// during the polling for GPIF DMA done (USB data transfer to USB Host)
P_GPIFTCB1 = MSB(cNAND_PSIZE); // Setup GPIF count high
P_ECCRESET = P_GPIFTCB0 = LSB(cNAND_PSIZE); // Reset ECC and GPIF low count
GPIFTRIG = 0x04 | cEP4; // Arm EP4
// Compute while GPIF Busy
ECCSetup(EP4FIFO); // Poll GPIF and store ECC data
if (!bMsk)
{
if (bReload) { CheckECC(); Log2Phy(); } // check if need to remap page
else n2k_set_radd();
}
if (bCnt)
{
do
{
P_GPIFTCB1 = MSB(cNAND_PSIZE); // Setup GPIF count high
P_ECCRESET = P_GPIFTCB0 = LSB(cNAND_PSIZE); // Reset ECC and GPIF low count
GPIFTRIG = 0x04 | cEP4; // Arm EP4
//=========================================================================
// local computation while polling GPIF done to optimize the speed
//=========================================================================
CheckECC(); // Verify previous ECC data
ECCSetup(EP4FIFO);
if (!bMsk)
{
if (bReload) Log2Phy();
else n2k_set_radd();
}
} while (bCnt);
}
CheckECC(); // Verify last ECC data
#else
Log2Phy(); // remap logical blocks
if (bInterLeave) // interleave FW
{
bank_select(cBank0); // select bank 0
if (bLBA0) // if Odd sector, need aligment
{
FifoRd(cEP6, 528); // dummy read-> next sector
bank_select(cBank1);
}
}
// Read the first 512 byte data and save all the ECC data in ecc0[]
// and ecc1[] buffers. The CheckECC will be called to verify the ECC
// during the polling for GPIF DMA done (USB data transfer to USB Host)
P_GPIFTCB1 = MSB(cNAND_PSIZE); // Setup GPIF count high
P_ECCRESET = P_GPIFTCB0 = LSB(cNAND_PSIZE); // Reset ECC and GPIF low count
GPIFTRIG = 0x04 | cEP4; // Arm EP4
// Compute while GPIF Busy
ECCSetup(EP4FIFO);
if (bReload) { CheckECC(); Log2Phy(); } // check if need to remap page
if (bCnt)
{
AUTOPTRH2 = MSB(cGPIFBANK);
AUTOPTRL2 = LSB(cGPIFBANK);
do
{
P_GPIFTCB1 = MSB(cNAND_PSIZE); // Setup GPIF count high
P_ECCRESET = P_GPIFTCB0 = LSB(cNAND_PSIZE); // Reset ECC and GPIF low count
fast_bank_sel(gBankSel); // use AUTO PTR2
GPIFTRIG = 0x04 | cEP4; // Arm EP4
AUTOPTRL2 = LSB(cGPIFBANK); // init again
//=========================================================================
// local computation while polling GPIF done to optimize the speed
//=========================================================================
CheckECC();
ECCSetup(EP4FIFO);
if (bReload) Log2Phy();
} while (bCnt);
AUTOPTRH2 = MSB(EP4FIFOBUF);
}
CheckECC(); // if ECC error, will send stall
bank_default();
#endif
DISABLE_NAND();
}
//==========================================================================
// Setup AUTO pointer for P_XAUTODAT1
// Read ECC registers when first 256 ECC calculation done
// Read 512 byte data and save:
// ecc0[] contains GPIF HW generate 6 ECC bytes
// ecc1[] contains ECC data from redundant area
//==========================================================================
void ECCSetup(WORD offset)
{
dwLBA++; // next sector
bCnt = --gSectorcount && !bErr;
// Loading the Pointer of stored 6-bytes ECC data
AUTOPTR1H = MSB(offset);
AUTOPTR1L = LSB(offset);
#ifdef NAND_2K
bReload = xLBA3 ==0 && bCnt; // compute bReload
bMsk = xLBA3 & 3;
if (!bMsk) xPhyAdd++; // 2K NAND address inc
#else
if (bInterLeave)
{
// Set this flag when all the pages in the block are done
// Interleave total pages are 64
// Non-Interleave total pages are 32
bReload = (xLBA3 & cInterLeaveMsk)==0 && bCnt; // compute bReload
// Select bank base on the dwLBA bit 0
if (bLBA0) gBankSel = cBank1; else gBankSel = cBank0;
}
else
{
gBankSel = cBank3; // non interleave keep the default value
bReload = (xLBA3 & (c512PageSize-1))==0 && bCnt; // compute bReload
}
#endif
while (P_GPIFTCB1); // Read the first 256 ECC registers
ecc0[0] = P_ECC1B0[0]; // save to local buffers
ecc0[1] = P_ECC1B0[1];
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -