nand.c File Reference


Detailed Description

This module provides NAND Flash support.

REVISION

Definition in file nand.c.

#include "../SYSTEM/sys_hardware.h"
#include "nand.h"
#include "nand_assert.h"
#include "eccutil.h"

Include dependency graph for nand.c:

Include dependency graph

Go to the source code of this file.

Defines

#define MAKER_SANDISK   0x98
 LOCAL DEFINITIONS.
#define FORMAT_RETRY   (10)
 NAND chip format retry times before reporting fatal error.

Functions

BOOL NAND__replaceDataSec (unsigned long *)
 Function tries to replace the defected block where phySec resides in.
BOOL NAND__flushBlock (unsigned short *)
 Function erases block and writes specified data back.
BOOL NAND__buildSysInfo (st_NAND *)
 Function builds and writes the system information to the active flash.
unsigned short NAND__formatChip (unsigned short)
 Function formats NAND flash and returns number of read/writable data blocks.
unsigned short NAND__loadTab (unsigned long, unsigned long, unsigned short)
 Function loads the specified map table and returs of length of the table in words.
BOOL NAND__mount (unsigned short)
 Function initializes NAND flash hardware and read back the system information.
BOOL NAND__swapSec (unsigned long *, unsigned long)
 Function tries to allocate a free block and swap with the one the specified logSec resides in.
BOOL NAND__checkID (void)
 Function checks NAND flash ID and set up chip parameters.
NAND_COPYERR NAND__copySec (unsigned short srcPhyBlock, unsigned short *pDstPhyBlock, unsigned short secOffset, unsigned short secNum)
 Function copies contiguous sector(s) from source block to destination block.
BOOL NAND__eraseBlock (unsigned short phyBlock)
 Function erases specified physical block.
BOOL NAND__flush (BOOL bPARTIAL)
 Function flushes flash data area if any pending block exists.
BOOL NAND__historyCheck (void)
 Function checks to manage the data sector history to yield to operating system while NAND interface is busy.
void NAND__historySet (unsigned short *pBuf, BOOL swap)
 Function records a new history sector.
unsigned long NAND__log2phySec (unsigned long logSec)
 Function maps the logical sector number to physical sector number if it is available.
BOOL NAND__markInvalidBlock (unsigned short phyBlock)
 Function marks the specified block to be invalid if it is already a problematic one, otherwise marks it to be problematic.
BOOL NAND__readRdnt (unsigned long phySec, unsigned short *pData, unsigned short offSet, unsigned short len)
 Function reads byte(s) from redundant area.
BOOL NAND__writeRdnt (unsigned long phySec, unsigned short *pData, unsigned short offSet, unsigned short len)
 Function writes byte(s) to redundant area.
BOOL NAND__readSec (unsigned long phySec, unsigned short *pBuf, BOOL swap)
 Function reads back the specified page/sector.
BOOL NAND__readDataSec (unsigned long phySec, unsigned short *pBuf, BOOL swap)
 Function reads back to verify the specified data page/sector.
BOOL NAND__writeSec (unsigned long phySec, unsigned short *pBuf, BOOL swap)
 Function writes to the specified blank page/sector.
void NAND__writeDataSec (unsigned long phySec, unsigned short *pBuf, BOOL swap)
 Function writes data to the specified blank page/sector.
BOOL NAND__write (unsigned long phySec, unsigned long pData, unsigned short length)
 Function writes the specified data back to specified sector(s), it is the caller's responsibility to make sure the corresponding sector(s) is/are blank and cross block shall never happen.
BOOL NAND__wrSysInfo (void)
 Function checks to write the system info area.
BOOL NAND_flush (void)
 Function flushes the NAND flash and makes all change final.
unsigned long NAND_format (void)
 Function will format the nand flash.
unsigned long NAND_mount (void)
 Function initializes NAND flash interface.
BOOL NAND_readSec (unsigned long sec, unsigned short *pBuf, BOOL swap)
 Function reads back the specified logical sector with disk I/O lock wrapper.
BOOL NAND__rdSec (unsigned long sec, unsigned short *pBuf, BOOL swap)
 Function reads back the specified logical sector, specified by the FAT file system layer.
void NAND_revive (unsigned short blkNum)
 Function erases entire NAND chip, all information will be lost.
BOOL NAND__test (void)
 Function tests NAND interface.
BOOL NAND_unmount (void)
 Function unmounts NAND flash and releases memory allocated to flash driver.
BOOL NAND_writeSec (unsigned long sec, unsigned short *pBuf, BOOL swap)
 Function writes to the logical sector with I/O lock wrapper.
BOOL NAND__wrSec (unsigned long sec, unsigned short *pBuf, BOOL swap)
 Function writes to the logical sector, which is specified by the FAT file system layer, NAND flash will always appear to be contiguous to the FAT file system on a sector level.
BOOL NAND__isBlockValid (unsigned short phyBlock)
 Function checks if specified physical block is valid.
BOOL NAND__isBlockGood (unsigned short phyBlock)
 Function checks if specified physical block is in good status.

Variables

st_SECT_HISTORY sectHistory
 GLOBAL DATA.


Function Documentation

BOOL NAND__buildSysInfo st_NAND pNand  ) 
 

Function builds and writes the system information to the active flash.

There is no block replacement algorithm for this area. If error happens here, it will be treated as a sector 0 failure of a volume disk and reformat is needed to revive flash.

Parameters:
pNand NAND global data structure pointer.
Returns:
TRUE if system info successfully built, otherwise FALSE.

Definition at line 1952 of file nand.c.

References st_NAND::curRpBlkNum, st_NAND::dataBlkNum, st_NAND::fmtCtrl, st_NAND::mapTabPhySecOffset, NAND__eraseBlock(), NAND__writeRdnt(), NAND__writeSec(), st_NAND::pagePerBlk, st_NAND::pageSz, st_NAND::rpTabBackPhyBlk, st_NAND::rpTabPhyBlk, and st_NAND::sysPhySec.

Referenced by NAND__wrSysInfo().

01953 {
01954     unsigned short  buf[256];
01955     unsigned short  ii;
01956     unsigned long   phySec;
01957     
01958     // Rebuild and write the system data block.
01959     for(ii= 0; ii<pNand->pageSz; ii++) buf[ii] = 0xFFFF;
01960 
01961     // Signature.
01962     buf[0] = NAND_MANUFACTURE_ID;   
01963     
01964     // Format control flag.
01965     buf[1] = 0xFF00 | pNand->fmtCtrl;   
01966     
01967     buf[2] = pNand->pageSz;                 
01968     buf[3] = pNand->pagePerBlk;
01969     
01970     // Data block num.
01971     buf[4] = pNand->dataBlkNum[pNand->actvChip];
01972     
01973     // Maximum replacement block num.
01974     buf[64] = pNand->curRpBlkNum;   
01975     
01976     // Replacement table physical block.
01977     buf[65] = pNand->rpTabPhyBlk[pNand->actvChip];
01978     
01979     buf[66] = pNand->mapTabPhySecOffset[pNand->actvChip];
01980     
01981     // Update block map table index. 
01982     buf[67] = pNand->rpTabBackPhyBlk[pNand->actvChip]; 
01983 
01984     buf[255] = NAND_SIGNATURE;
01985 
01986     // Erase the sysinfo block.
01987     if(NAND__eraseBlock(pNand->sysPhySec[pNand->actvChip] >> 6 ))
01988     {
01989         if(NAND__writeSec(pNand->sysPhySec[pNand->actvChip], buf, FALSE))
01990         {   
01991             ii = 0;
01992             //ensure thr downdate of new nand driver
01993             phySec = pNand->sysPhySec[pNand->actvChip] + 1;//
01994             if(NAND__writeRdnt(phySec,&ii,NAND_BLOCK_STATUS_BYTE,1))
01995             {
01996                 phySec += 1;
01997                 if(NAND__writeRdnt(phySec,&ii,NAND_BLOCK_STATUS_BYTE,1))
01998                     return TRUE;
01999             }
02000         }
02001     } 
02002     
02003     return FALSE;
02004 }

Here is the call graph for this function:

BOOL NAND__checkID void   ) 
 

Function checks NAND flash ID and set up chip parameters.

Returns:
TRUE if successfully retrieved chip ID, otherwise FALSE.

Definition at line 100 of file nand.c.

References st_NAND::blkSz, NAND_WAIT4READY, st_NAND::pagePerBlk, st_NAND::pageRednt, st_NAND::pageSz, and st_NAND::totalBlkNum.

Referenced by NAND__formatChip(), and NAND__mount().

00101 {
00102     unsigned short temp0;
00103     
00104     NAND_WAIT4READY(temp0);
00105     
00106     // Assert CLE: write to the port will set CLE to HIGH
00107     CPLD_CLE = 0;   
00108 
00109     // NAND chip 0, write to the port will enable CE0
00110     CPLD_CE0 = 0;
00111 
00112     // send 'Read ID (1)' command 
00113     CPLD_RDWR = NAND_CMD__ID_READ1;
00114 
00115     // Deassert CLE: read from the port will reset CLE to LOW 
00116     temp0 = CPLD_CLE;
00117 
00118     // Assert ALE, TBD by cpld code 
00119     CPLD_ALE = 0;
00120 
00121     // send address to NAND chip 
00122     CPLD_RDWR = 0;
00123     CPLD_RDWR = 0;
00124     CPLD_RDWR = 0;
00125     CPLD_RDWR = 0;
00126 
00127     // Deassert ALE, TBD by cpld code 
00128     temp0 = CPLD_ALE;
00129     
00130     // Wait for Ready/#Busy signal (input on D0) goes to HIGH.
00131     NAND_WAIT4READY(temp0);
00132 
00133     // Read maker code. 
00134     temp0 = CPLD_RDWR & 0x00FF;
00135 
00136     // Disable Sandisk Maker ID check here.
00137     //if(temp0 != MAKER_SANDISK) NAND_Die(kNandErr+978);
00138     
00139     // Read device code. 
00140     temp0 = CPLD_RDWR & 0x00FF;
00141     
00142     // Save the nand size to help calculate various assert limits.
00143     NAND_setSize(temp0);
00144 
00145     //ii = (temp0 == DEVICE_128MB)? 0 : 1;
00146     // Setup total physical block number.
00147     switch( temp0 )
00148     {
00149     case DEVICE_128MB:  /* 128MB */
00150             Nand.totalBlkNum = 0x1000;  break;
00151     case DEVICE_256MB:  /* 256MB */
00152             Nand.totalBlkNum = 0x2000;  break;
00153     default:            /* 64MB */
00154             Nand.totalBlkNum = 0x800;   break;
00155     }
00156     
00157     // Deassert CE, read from the port will disable CE0
00158     temp0 = CPLD_CE0;
00159 
00160     // Nand parameters are hard-coded here.
00161     Nand.pageSz = 0x100;    // in words
00162     Nand.pageRednt = 0x08;
00163     Nand.pagePerBlk = 64;
00164     Nand.blkSz = Nand.pagePerBlk * Nand.pageSz;
00165 
00166     return ( TRUE );
00167 }

NAND_COPYERR NAND__copySec unsigned short  srcPhyBlock,
unsigned short *  pDstPhyBlock,
unsigned short  secOffset,
unsigned short  secNum
 

Function copies contiguous sector(s) from source block to destination block.

it is the caller's responsibility to make sure the destination block is blank. It is also the caller's responsibility to make sure sector will not cross block boundary.

Parameters:
srcPhyBlock source physical block.
pDstPhyBlock pointer to destination physical block.
secOffset starting sector offset.
secNum total sector number.
Returns:
copy error specifier.

Definition at line 187 of file nand.c.

References NAND__readSec(), NAND__writeSec(), st_NAND::pagePerBlk, and st_NAND::pRpTab.

Referenced by NAND__flush(), NAND__replaceDataSec(), and NAND__swapSec().

00191 {
00192     unsigned long   srcPhySec;
00193     unsigned long   dstPhySec;
00194     unsigned short  dstPhyBlock;
00195     unsigned short  block;
00196     unsigned short  buf[256];
00197     unsigned short  ii;
00198     unsigned short  secnumber;
00199     
00200     NAND_assert (pDstPhyBlock != NULL                   , NAND__COPYSEC);
00201     NAND_assert (srcPhyBlock < NAND_BLOCK_CNT           , NAND__COPYSEC2);
00202     NAND_assert (secOffset  <= NAND_SEC_PER_BLOCK       , NAND__COPYSEC3);
00203     NAND_assert (secNum     <= NAND_SEC_PER_BLOCK       , NAND__COPYSEC4);
00204     
00205     // We don't want to cross block boundaries during the copy.  
00206     NAND_assert (secOffset+secNum <= NAND_SEC_PER_BLOCK , NAND__COPYSEC5);
00207 
00208     dstPhyBlock = *pDstPhyBlock;
00209     
00210     //optimization
00211     secnumber = secNum; 
00212 
00213 #ifdef HARD_CODED_OPTIMIZATION  
00214         srcPhySec = ((unsigned long)srcPhyBlock << 6) + secOffset;
00215         dstPhySec = ((unsigned long)dstPhyBlock << 6) + secOffset;
00216 #else
00217         srcPhySec = (unsigned long)srcPhyBlock * Nand.pagePerBlk + secOffset;
00218         dstPhySec = (unsigned long)dstPhyBlock * Nand.pagePerBlk + secOffset;
00219 #endif
00220 
00221     while(1)
00222     {   
00223         for( ii = 0; ii < secnumber; ii++ ) 
00224         {
00225             if(NAND__readSec((long)(srcPhySec+ii), buf, FALSE) == FALSE)
00226             {                   
00227                 // Unable to read source, report error. It will be 
00228                 // the caller's responsibility to erase the destination
00229                 // if necessary. For example, in replace and swap
00230                 // case we need to erase the destination to maintain 
00231                 // a free replacement block list all the time, while
00232                 // we do not want to erase destination if flushing data
00233                 // block is in process. 
00234                 //NAND__markInvalidBlock(srcPhyBlock);
00235                 *pDstPhyBlock = dstPhyBlock;
00236                 return CPYERR_READ;
00237             }
00238 
00239             if(NAND__writeSec(dstPhySec+ii, buf, FALSE) == FALSE )
00240             {                   
00241                 // Unable to write destination, try to replace it
00242                 // before reporting error.
00243                 break;
00244             }
00245         }
00246         
00247         //if(ii == secNum) 
00248         if(ii == secnumber)
00249         {
00250             // Done with the copy, update destination block pointer. 
00251             *pDstPhyBlock = dstPhyBlock;
00252             break;
00253         }
00254         
00255         else 
00256         {
00257             block = dstPhyBlock;
00258 
00259             // linda: in this place, i should record sth to be in case of forget the algorithm
00260             // the copysec is to do data copy and keep the status before the function was called
00261             // OK, two function will call this function,they are swap and flush.
00262             // the difference between them is where the dest_block logined.
00263             // if everything is OK,this structure will not executed
00264             // but if sth goes wrong.
00265             
00266             // swap: when this function was called ,the desti doesnot be swaped,that means it 
00267             // logined in replacement table.so (block == dstPhyBlock) will goes TRUE,so do notify
00268             // this block goes bad,do NAND__wrRpHis(0xFFFE,FALSE),then get the first valid block,
00269             // and every loop,you'll find this justify will go same.so when the function is over,
00270             // the status is the desti-block is in the replacenment table and in the first place.
00271             
00272             // flush: when this function was called, the desti was swapped already, that means it 
00273             // logined in the map table,so the (block == dstPhyBlock) will goes FALSE,so do notify
00274             // this block(donot logined in rep table)does bad,do NAND__wrRpHis(block,FALSE), and 
00275             // that func will do sth to deal with this block and think that the first valid block
00276             // is taken out by the caller,so it do find the other valid block and put it in the 
00277             // first place ( attention this block does not equal to dstPhyBlock. so we can get 
00278             // the conclusion, that from the beginning to the end, dstPhyBlock does not belongs
00279             // to the replacement table, OK, whatever the caller will do does not have sth to do
00280             // with the replacement table  
00281             
00282             // so we get the point: the status does not change
00283             GEN_rdSRAM(Nand.pRpTab,&dstPhyBlock,1);
00284             if(block == dstPhyBlock)
00285             {
00286                 if(!NAND__wrRpHis(0xFFFE,FALSE)) return CPYERR_WRITE;
00287                     
00288                 GEN_rdSRAM(Nand.pRpTab,&dstPhyBlock,1); 
00289             }
00290             else
00291                 if(!NAND__wrRpHis(block,FALSE)) return CPYERR_WRITE;
00292             
00293             // Recover the dst block flushed sectors if there is any. 
00294             // Data shall be read directly from the source block.
00295             
00296 #ifdef HARD_CODED_OPTIMIZATION  
00297             srcPhySec = (unsigned long)srcPhyBlock << 6;
00298             dstPhySec = (unsigned long)dstPhyBlock << 6;
00299 #else
00300             srcPhySec = (unsigned long)srcPhyBlock * Nand.pagePerBlk;
00301             dstPhySec = (unsigned long)dstPhyBlock * Nand.pagePerBlk;
00302 #endif
00303 
00304            secnumber = secNum + secOffset;
00305         }   
00306     }
00307     
00308     return ( CPYERR_NONE );
00309 }

Here is the call graph for this function:

BOOL NAND__eraseBlock unsigned short  phyBlock  ) 
 

Function erases specified physical block.

Parameters:
phyBlock NAND physical block number.
Returns:
TRUE if block successfully erased, otherwise FALSE.

Definition at line 320 of file nand.c.

References NAND_WAIT4READY.

Referenced by NAND__buildSysInfo(), NAND__formatChip(), NAND__markInvalidBlock(), NAND__replaceDataSec(), NAND__swapSec(), NAND__wrSysInfo(), NAND_flush(), NAND_mount(), NAND_revive(), and NAND_unmount().

00321 {
00322     unsigned long   columnAddr;
00323     unsigned short  temp;
00324     unsigned char   addr_9_16;
00325     unsigned char   addr_17_24;
00326     unsigned char   addr_25_27;
00327     
00328     NAND_assert(phyBlock < NAND_BLOCK_CNT, NAND__ERASEBLOCK);
00329 
00330     NAND_WAIT4READY(temp);  
00331 
00332     // remove write protection
00333     //CPLD_nWP = 0;
00334 
00335     // Assert CLE: write to the port will set CLE to HIGH
00336     CPLD_CLE = 0;
00337 
00338     // NAND chip 0, write to the port will enable CE0
00339     CPLD_CE0 = 0;
00340 
00341     // Form the column address on whole blocks
00342     columnAddr = (unsigned long)phyBlock << 15;
00343 
00344     // Parse the column address
00345     addr_9_16 =  (unsigned char)((columnAddr >>  9) & 0xFF);
00346     addr_17_24 = (unsigned char)((columnAddr >> 17) & 0xFF);
00347     addr_25_27 = (unsigned char)((columnAddr >> 25) & 0x07);
00348 
00349     // send 1st byte of 'Auto Block Erase' command
00350     CPLD_RDWR = NAND_CMD__AUTO_BLOCK_ERASE1;
00351 
00352     // Deassert CLE: read from the port will reset CLE to LOW
00353     temp = CPLD_CLE;
00354 
00355     // Assert ALE, TBD by cpld code
00356     CPLD_ALE = 0;
00357 
00358     // send address to NAND chip
00359     CPLD_RDWR = addr_9_16;
00360     CPLD_RDWR = addr_17_24;
00361     CPLD_RDWR = addr_25_27;
00362 
00363     // Deassert ALE, TBD by cpld code
00364     temp = CPLD_ALE;
00365 
00366     // Assert CLE: write to the port will set CLE to HIGH
00367     CPLD_CLE = 0;
00368     
00369     // send 2nd byte of 'Auto Block Erase' command
00370     CPLD_RDWR = NAND_CMD__AUTO_BLOCK_ERASE2;
00371 
00372     // Deassert CLE: read from the port will reset CLE to LOW
00373     temp = CPLD_CLE;
00374 
00375     // Wait for Ready/#Busy signal (input on D0) goes to HIGH.
00376     NAND_WAIT4READY(temp);
00377 
00378     // Assert CLE: write to the port will set CLE to HIGH
00379     CPLD_CLE = 0;
00380     
00381     // send 'Status Read (1)' command 
00382     CPLD_RDWR = NAND_CMD__STATUS_READ1;
00383 
00384     // Deassert CLE: read from the port will reset CLE to LOW
00385     temp = CPLD_CLE;
00386 
00387     // Restore write protection 
00388     //temp = CPLD_nWP;
00389 
00390     // Read status data 
00391     temp = CPLD_RDWR;
00392 
00393     // Deassert CE, read from the port will disable CE0
00394     addr_9_16 = CPLD_CE0;
00395         
00396     if ( (temp & 0x0001 ) == 0 ) 
00397     {
00398         /* Erase pass. */
00399         return (TRUE);
00400     }   
00401     else 
00402     {
00403         /* Erase fail. */
00404         return (FALSE);
00405     }
00406 }

BOOL NAND__flush BOOL  bPARTIAL  ) 
 

Function flushes flash data area if any pending block exists.

Parameters:
bPARTIAL TRUE if partial flush is needed, otherwise FALSE.
Returns:
TRUE if successfully flushed, otherwise FALSE.

Definition at line 416 of file nand.c.

References st_NAND::actvBlk, st_NAND::actvBlkEndSec, st_NAND::actvPhyBlk, st_NAND::actvRpPhyBlk, st_NAND::actvSec, st_NAND::actvSecOffset, st_NAND::flag, NAND__copySec(), NAND_COPYERR, st_NAND::pagePerBlk, st_NAND::pMapTab, and st_NAND::writingSec.

Referenced by NAND__wrSec(), NAND_flush(), and NAND_unmount().

00417 {
00418     NAND_COPYERR    err;
00419     unsigned short  endsect;
00420     
00421     if(TRUE == bPARTIAL)
00422         endsect = Nand.writingSec - Nand.actvSec;
00423     else
00424         endsect = Nand.pagePerBlk - Nand.actvSecOffset;
00425         
00426     err = NAND__copySec(    Nand.actvRpPhyBlk, 
00427                             &Nand.actvPhyBlk,
00428                             (unsigned short)(Nand.actvSecOffset + 1),
00429                             (unsigned short)(endsect - 1) );
00430                                                             
00431     if(err == CPYERR_NONE )
00432     {
00433         GEN_wrSRAM((long)Nand.pMapTab + Nand.actvBlk,&Nand.actvPhyBlk,1);
00434         if(!bPARTIAL)
00435         {
00436             Nand.actvBlkEndSec = NAND_INVALID_SEC;
00437             Nand.actvSec = NAND_INVALID_SEC;
00438             Nand.flag &= ~NAND_FLUSH_DATA_BLOCK_PENDING;
00439         }       
00440         return TRUE;
00441     }
00442 
00443     if( err == CPYERR_WRITE ) 
00444     {
00445         GEN_wrSRAM(Nand.pMapTab + Nand.actvBlk, &Nand.actvRpPhyBlk, 1);
00446         // in case of the inside danger,now there exist two copy of 
00447         // actvrpphyblk in the replace and map table
00448 
00449         Nand.flag &= ~NAND_FLUSH_DATA_BLOCK_PENDING;
00450     }
00451     
00452     else if( err == CPYERR_READ ) 
00453     {   
00454         GEN_wrSRAM((long)Nand.pMapTab + Nand.actvBlk,&Nand.actvPhyBlk,1);
00455         
00456         NAND__wrRpHis(Nand.actvRpPhyBlk,FALSE); 
00457 
00458         Nand.flag |= NAND_FLUSH_REPLACE_TAB_PENDING;
00459     }
00460 
00461     return FALSE;   
00462 }

Here is the call graph for this function:

BOOL NAND__flushBlock unsigned short *  pPhyBlock  ) 
 

Function erases block and writes specified data back.

This function is ONLY called to flush the block map table and the replacement map table.

Parameters:
pPhyBlock physical block pointer.
Returns:
TRUE if successfully flushed, otherwise FALSE.

Definition at line 1890 of file nand.c.

References st_NAND::actvChip, st_NAND::dataBlkNum, st_NAND::flag, st_NAND::mapTabPhySecOffset, st_NAND::maxRpBlkNum, NAND__write(), NAND__writeRdnt(), st_NAND::pagePerBlk, st_NAND::pMapTab, and st_NAND::pRpTab.

Referenced by NAND__wrSysInfo().

01891 {
01892     unsigned long   sec;
01893     unsigned short  tmp;
01894         
01895     NAND_assert (*pPhyBlock < NAND_BLOCK_CNT, NAND__FLUSHBLOCK);
01896     
01897     while(1)
01898     {   
01899         tmp = *pPhyBlock;
01900         
01901 #ifdef HARD_CODED_OPTIMIZATION  
01902         sec = (long)tmp << 6;
01903 #else               
01904         sec = (long)tmp*Nand.pagePerBlk;
01905 #endif
01906         
01907         /* but i think we need it
01908         NAND__readRdnt((sec + Nand.pagePerBlk - 3),&tmp,NAND_BLOCK_STATUS_BYTE,1);
01909         if(tmp != 0xFF)
01910             NAND__eraseBlock(tmp);*/
01911         
01912             
01913         //write into replacement table information
01914         if( NAND__write(sec, Nand.pRpTab, Nand.maxRpBlkNum[Nand.actvChip])) 
01915         {
01916             if(NAND__write(sec + Nand.mapTabPhySecOffset[0], 
01917                     Nand.pMapTab,Nand.dataBlkNum[Nand.actvChip]))
01918             {
01919                 // confusion: the rdnt of the last third sector show this block is valid replace block
01920                 sec = sec + Nand.pagePerBlk - 3;
01921                 tmp = 0;
01922                 NAND__writeRdnt(sec,&tmp,NAND_BLOCK_STATUS_BYTE,1); 
01923                             
01924                 return TRUE;
01925             }
01926         }
01927 
01928         //attention!!!!!!!!!!!!!!!!!
01929         if(Nand.flag & NAND_READ_ONLY)  return FALSE;
01930         
01931         GEN_rdSRAM(Nand.pRpTab, pPhyBlock, 1);      
01932         
01933         NAND__wrRpHis(tmp,FALSE);
01934         
01935         Nand.flag |= NAND_SYSINFO_CHANGE;           
01936     }
01937 }

Here is the call graph for this function:

unsigned short NAND__formatChip unsigned short  startPhyBlock  ) 
 

Function formats NAND flash and returns number of read/writable data blocks.

Function will do low level format of the volume and rebuild the system data in the following format, starting from first valid page. (a page is valid only when it sits in a valid block. )

Parameters:
startPhyBlock starting physical block of current NAND chip.
Returns:
number of data sectors.

Definition at line 2179 of file nand.c.

References GEN_free(), GEN_malloc(), NAND__checkID(), NAND__eraseBlock(), NAND__isBlockValid(), NAND__write(), NAND__writeRdnt(), NAND__writeSec(), NAND_revive(), st_NAND::pagePerBlk, st_NAND::pageSz, and st_NAND::totalBlkNum.

Referenced by NAND_format().

02180 {
02181     // Format retry counter to recursively handle format error. 
02182     static  short       retry = 0;  
02183     
02184     unsigned short      secoffset;
02185     unsigned short      tmp;
02186     unsigned short      ii;
02187     unsigned short      phyBlock;
02188     unsigned short      logBlock;
02189     unsigned short      maxReplaceBlockNum;
02190     unsigned short      dataBlockNum;
02191     unsigned short *    pBuf;
02192     
02193     unsigned long       pMapTab;
02194     unsigned long       pTab;
02195     unsigned long       phySec;
02196     BOOL                status;
02197     
02198     // Remove write protection. 
02199     CPLD_nWP = 0;
02200     
02201     // Check ID to get physical parameters. 
02202     if( NAND__checkID() == FALSE ) return 0L;
02203 
02204     // Allocate map table buffer and initialize it to all 0xFFFFs, 
02205     if( (pMapTab = GEN_malloc(Nand.totalBlkNum) ) == 0L ) return 0L;
02206     
02207     else 
02208     {       
02209         // Initialize block map table. 
02210         
02211         // Let's speed this up if memory is available. 
02212         pBuf = (unsigned short *)malloc(Nand.totalBlkNum*sizeof(unsigned short));
02213         if(pBuf)
02214         {
02215             for(ii=0; ii<Nand.totalBlkNum; ii++) pBuf[ii] = 0xFFFF;
02216             GEN_wrSRAM(pMapTab, pBuf, Nand.totalBlkNum);
02217             free(pBuf);
02218         }
02219         
02220         else
02221         {
02222             tmp = 0xFFFF;
02223             for(ii=0; ii<Nand.totalBlkNum; ii++) GEN_wrSRAM(pMapTab + ii, &tmp, 1);
02224         }       
02225     }
02226 
02227 
02228     // Check to build the entire block map table for all valid blocks if any. 
02229     phyBlock = startPhyBlock;
02230 
02231     logBlock = 0;
02232     
02233     while(1)
02234     {
02235         if( NAND__isBlockValid(phyBlock) ) 
02236         {       
02237             if( NAND__eraseBlock(phyBlock) )
02238             {               
02239                 GEN_wrSRAM(pMapTab + logBlock++, &phyBlock, 1);
02240             }
02241             
02242             else
02243             {
02244                 // Mark this block to be bad.
02245 #ifdef HARD_CODED_OPTIMIZATION  
02246                 phySec = ((unsigned long)phyBlock << 6) + 63;
02247 #else
02248                 phySec = ((unsigned long)Nand.pagePerBlk * phyBlock) + Nand.pagePerBlk - 1;
02249 #endif
02250                 
02251                 ii = NAND_BLOCK_STATUS_BAD;
02252                 
02253                 NAND__writeRdnt(phySec, &ii, NAND_BLOCK_STATUS_BYTE, 1);
02254             }
02255         }
02256         
02257         if(++phyBlock >= (startPhyBlock + Nand.totalBlkNum) ) break;
02258 
02259     }
02260 
02261     // If less than (256)??? blocks left, flash is considered 
02262     // permanently damaged or worn out.
02263     // We'll try to revive it anyway, knowing that this revival
02264     // will bring the NAND to an unstable state by loosing all 
02265     // block information. But it is better than leaving the player dead.
02266     if( logBlock < 256 ) 
02267     {
02268         GEN_free(pMapTab);
02269         NAND_revive(Nand.totalBlkNum);      
02270         return (NAND__formatChip(startPhyBlock));
02271     }
02272     
02273     // Allocate sector buffer and initialize to all 0xFFFFs. 
02274     if ( (pBuf = (unsigned short *) 
02275             malloc(Nand.pageSz * sizeof(unsigned short)) ) 
02276             == NULL )
02277     {
02278         GEN_free(pMapTab);
02279         return 0L;
02280     }
02281 
02282     else 
02283     {
02284         // Initialize buffer to all empty. 
02285         for(ii= 0; ii<Nand.pageSz; ii++) *pBuf++ = 0xFFFF;
02286         pBuf -= Nand.pageSz;
02287     }
02288 
02289     // Rebuild and write the system data block hereafter, this
02290     // will revive the flash if there is valid blocks left. 
02291     
02292     pBuf[0] = NAND_MANUFACTURE_ID;  
02293     
02294     // Format control flag. 
02295     pBuf[1] = 0xFF00;               
02296     
02297     pBuf[2] = Nand.pageSz;          
02298     pBuf[3] = Nand.pagePerBlk;
02299     
02300     // Reserve 3.125% (1/32) of valid blocks for replacement and 
02301     // storing map table, system info etc. 
02302     dataBlockNum = logBlock - (logBlock >> 5);
02303     
02304     // Data block num. 
02305     pBuf[4] = dataBlockNum;         
02306 
02307     // System info, replacement map table, and block map table
02308     // take 3 blocks. 
02309     maxReplaceBlockNum = logBlock - dataBlockNum - 3;
02310     
02311     // Maximum replacement block num. 
02312     pBuf[64] = maxReplaceBlockNum;  
02313     
02314     // Replacement table physical block. 
02315     GEN_rdSRAM(pMapTab + 1, &pBuf[65], 1);
02316     
02317     // Block num per block map table. 
02318     //pBuf[66] = blockPerMapTab;        
02319 
02320     //the sector offset of map table in the replacement block
02321 #ifdef HARD_CODED_OPTIMIZATION  
02322     secoffset =((64 - 2)>>5) + 2;
02323 #else
02324     secoffset = ((Nand.pagePerBlk - 2)>>5) + 2; 
02325 #endif
02326 
02327     pBuf[66] = secoffset;
02328     
02329     // backup table of data block map table. 
02330     GEN_rdSRAM(pMapTab + 2, &pBuf[67], 1);
02331         
02332     pBuf[255] = NAND_SIGNATURE;     
02333 
02334     status = TRUE;
02335     pTab = pMapTab + dataBlockNum + 3;
02336     GEN_rdSRAM(pMapTab + 1, &tmp, 1);
02337     phySec = (unsigned long)tmp*Nand.pagePerBlk;
02338 
02339     if(status &= NAND__write(phySec, pTab, maxReplaceBlockNum))
02340     {
02341         pTab = pMapTab + 3;
02342         phySec = phySec + secoffset;
02343         
02344         if(status &= NAND__write(phySec, pTab, dataBlockNum))
02345         {
02346             phySec = (unsigned long)tmp*Nand.pagePerBlk + Nand.pagePerBlk - 3;//2
02347             tmp = 0;
02348             NAND__writeRdnt(phySec,&tmp,NAND_BLOCK_STATUS_BYTE,1);
02349             
02350             GEN_rdSRAM(pMapTab, &tmp, 1);
02351             phySec = (unsigned long)tmp*Nand.pagePerBlk;    
02352         
02353             if( status &= NAND__writeSec(phySec, pBuf, FALSE))
02354             {
02355                 tmp = 0;
02356                 phySec = phySec + 1;//1
02357                 NAND__writeRdnt(phySec,&tmp,NAND_BLOCK_STATUS_BYTE,1);
02358                 
02359                 phySec += 1;//1
02360                 NAND__writeRdnt(phySec,&tmp,NAND_BLOCK_STATUS_BYTE,1);
02361             }
02362         }
02363     }
02364     
02365     if(!status)
02366     {
02367         GEN_free(pMapTab);  
02368         free(pBuf);
02369                 
02370         if(++retry < FORMAT_RETRY ) 
02371                 return NAND__formatChip(startPhyBlock);
02372 
02373         else return 0;
02374     }
02375     
02376     // End of chip formatting, reset retry counter. 
02377     retry = 0;
02378     GEN_free(pMapTab);
02379     free(pBuf);
02380 
02381     // return available data blocks. 
02382     return( dataBlockNum );
02383 }

Here is the call graph for this function:

BOOL NAND__historyCheck void   ) 
 

Function checks to manage the data sector history to yield to operating system while NAND interface is busy.

Returns:
TRUE if history successfully managed, otherwise FALSE.

Definition at line 474 of file nand.c.

References st_NAND::flag, NAND__readDataSec(), NAND__replaceDataSec(), NAND__writeSec(), NAND_WAIT4READY, st_SECT_HISTORY::phySec, st_SECT_HISTORY::secBuf, sectHistory, and st_SECT_HISTORY::swap.

Referenced by NAND__rdSec(), NAND__wrSec(), NAND_flush(), and NAND_unmount().

00475 {   
00476     BOOL                    ret = TRUE;
00477     unsigned long           phySec; 
00478     
00479     if(Nand.flag & NAND_HISTORY_AVAILABLE)
00480     {       
00481         // Check to see if there was any error.
00482 #ifdef NAND_PWR_SUPPORT     
00483         ret = NAND__readDataSec(sectHistory.phySec, 
00484                                         sectHistory.secBuf,
00485                                         sectHistory.swap);
00486                                         
00487 #else       
00488         NAND_WAIT4READY(temp);
00489         
00490         // NAND chip 0, write to the port will enable CE0
00491         CPLD_CE0 = 0;
00492 
00493         CPLD_CLE = 0;
00494         
00495         // send 'Status Read (1)' command 
00496         CPLD_RDWR = NAND_CMD__STATUS_READ1;
00497 
00498         // Deassert CLE: read from the port will reset CLE to LOW 
00499         temp = CPLD_CLE;
00500 
00501         // Read status data
00502         temp = CPLD_RDWR;
00503         
00504         // Deassert CE, read from the port will disable CE0
00505         ret = CPLD_CE0; 
00506 
00507         ret = ( (temp & 0x0001 ) == 0 )? TRUE: FALSE; 
00508 #endif  
00509     }
00510     
00511     if( ret == FALSE )
00512     {
00513         // Error detected, let's replace it.
00514         phySec = sectHistory.phySec;        
00515         ret = TRUE;     
00516         do
00517         {
00518             if( NAND__replaceDataSec(&phySec) == FALSE)
00519             {
00520                 ret = FALSE;                
00521                 break;
00522             }           
00523         } while(NAND__writeSec( phySec, 
00524                                 sectHistory.secBuf, 
00525                                 sectHistory.swap) == FALSE );
00526     }
00527     
00528     Nand.flag &= ~NAND_HISTORY_AVAILABLE;
00529     return ret;
00530 }

Here is the call graph for this function:

void NAND__historySet unsigned short *  pBuf,
BOOL  swap
 

Function records a new history sector.

Parameters:
pBuf Sector data buffer.
swap Byte swap control.

Definition at line 542 of file nand.c.

References st_NAND::actvBlk, st_NAND::actvPhyBlk, st_NAND::actvPhySec, st_NAND::actvSecOffset, st_NAND::flag, st_SECT_HISTORY::logBlk, st_SECT_HISTORY::phyBlk, st_SECT_HISTORY::phySec, st_SECT_HISTORY::secBuf, st_SECT_HISTORY::secOffset, sectHistory, and st_SECT_HISTORY::swap.

Referenced by NAND__wrSec().

00543 {
00544     unsigned short      ii;
00545     unsigned short *    pSrc;
00546     unsigned short *    pDst;
00547     
00548     NAND_assert (pBuf != NULL, NAND__HISTORYSET);   
00549 
00550     pSrc = pBuf;
00551     pDst = sectHistory.secBuf;
00552     for(ii = 0; ii<256; ii++) *pDst++ = *pSrc++; 
00553             
00554     sectHistory.phyBlk = Nand.actvPhyBlk;
00555     sectHistory.phySec = Nand.actvPhySec;
00556     sectHistory.secOffset = Nand.actvSecOffset;
00557     sectHistory.logBlk = Nand.actvBlk;
00558     sectHistory.swap = swap;
00559     
00560     Nand.flag |= NAND_HISTORY_AVAILABLE;
00561 }

BOOL NAND__isBlockGood unsigned short  phyBlock  ) 
 

Function checks if specified physical block is in good status.

@ param phyBlock physical block number. @ return TRUE if block is in good status, otherwise FALSE.

Definition at line 3275 of file nand.c.

References NAND__readRdnt(), and st_NAND::pagePerBlk.

Referenced by NAND__mount().

03276 {
03277     unsigned long   phySec;
03278     unsigned short  byte;
03279 
03280     NAND_assert(phyBlock < NAND_BLOCK_CNT, NAND__ISBLOCKGOOD);
03281     
03282 #ifdef HARD_CODED_OPTIMIZATION  
03283     phySec = ((long)phyBlock<<6) + 63;
03284 #else
03285     phySec = ((long)Nand.pagePerBlk * phyBlock) + Nand.pagePerBlk - 1;  
03286 #endif  
03287 
03288     NAND__readRdnt( phySec, &byte, NAND_BLOCK_STATUS_BYTE, 1 );
03289 
03290     if( byte == NAND_BLOCK_STATUS_GOOD ) return TRUE;
03291     
03292     else return FALSE;
03293 }

Here is the call graph for this function:

BOOL NAND__isBlockValid unsigned short  phyBlock  ) 
 

Function checks if specified physical block is valid.

A block is considered valid if it is good or problematic. A block will be marked invalid when an error is detected on a problematic one.

@ param phyBlock physical block number. @ return TRUE if block is valid, otherwise FALSE.

Definition at line 3244 of file nand.c.

References NAND__readRdnt(), and st_NAND::pagePerBlk.

Referenced by NAND__formatChip(), and NAND_mount().

03245 {
03246 
03247     unsigned long   phySec;
03248     unsigned short  byte;
03249 
03250     NAND_assert(phyBlock < NAND_BLOCK_CNT, NAND__ISBLOCKVALID);
03251     
03252 #ifdef HARD_CODED_OPTIMIZATION  
03253     phySec = ((long)phyBlock<<6) + 63;
03254 #else
03255     phySec = ((long)Nand.pagePerBlk * phyBlock) + Nand.pagePerBlk - 1;  
03256 #endif  
03257     
03258     NAND__readRdnt( phySec, &byte, NAND_BLOCK_STATUS_BYTE, 1 );
03259 
03260     if(byte >= NAND_BLOCK_STATUS_PROBLEMATIC)   return TRUE;
03261     
03262     else return FALSE;
03263 }

Here is the call graph for this function:

unsigned short NAND__loadTab unsigned long  physec,
unsigned long  pTab,
unsigned short  maxLen
 

Function loads the specified map table and returs of length of the table in words.

It is the caller's responsibility to make sure that read will NOT cross block boundary.

Parameters:
physec table starting physical block.
pTab SRAM table pointer.
maxLen maximum table length in words.
Returns:
length of table in words.

Definition at line 2727 of file nand.c.

References NAND__readSec(), and st_NAND::pageSz.

Referenced by NAND_mount().

02730 {
02731     unsigned short  count;
02732     unsigned short  ii;
02733     unsigned short  buf[256];
02734     unsigned short  temp;
02735 
02736     ii = 0;
02737     count = maxLen;
02738     while(count)
02739     {
02740         if(NAND__readSec(physec + ii, buf, FALSE) == FALSE ) return 0;
02741         
02742         if(count > Nand.pageSz)
02743             temp = Nand.pageSz;
02744         else
02745             temp = count;
02746         
02747         GEN_wrSRAM(pTab, buf, temp);
02748 
02749         pTab += temp;
02750         count -= temp;
02751         ii++;
02752     }
02753     
02754     while(temp--)
02755     {
02756         // if buf[temp] equal to 0xFFFF or 0xFFFE, the following will equal to zero,
02757         // else it doesnot
02758         if((~buf[temp])>>1) break;
02759         count++;
02760     }
02761     
02762     return (maxLen - count);
02763 }

Here is the call graph for this function:

unsigned long NAND__log2phySec unsigned long  logSec  ) 
 

Function maps the logical sector number to physical sector number if it is available.

This function call ONLY be called from NAND_readSec and NAND_writeSec.

Return of this function shall set up the following NAND globals, Nand.actvSec Nand.actvSecOffset Nand.actvBlk Nand.actvPhyBlk Nand.actvPhySec

Parameters:
logSec logical sector number.
Returns:
mapped physical sector number.

Definition at line 639 of file nand.c.

References st_NAND::actvBlk, st_NAND::actvPhyBlk, st_NAND::actvPhySec, st_NAND::actvSec, st_NAND::actvSecOffset, st_NAND::pagePerBlk, and st_NAND::pMapTab.

Referenced by NAND__wrSec().

00640 {
00641     unsigned long   phySec;
00642     
00643     NAND_assert (logSec < NAND_SEC_CNT, NAND__LOG2PHYSEC);
00644     
00645     // Record active sector.
00646     Nand.actvSec = logSec;  
00647 
00648     // Record active sector offset in block.
00649 #ifdef HARD_CODED_OPTIMIZATION  
00650     Nand.actvSecOffset = (unsigned long)logSec & 0x003F;
00651 #else
00652     Nand.actvSecOffset = (unsigned long)logSec % Nand.pagePerBlk;
00653 #endif
00654     
00655     // Record active logical block number.
00656 #ifdef HARD_CODED_OPTIMIZATION  
00657     Nand.actvBlk = (unsigned long)(logSec) >> 6;
00658 #else
00659     Nand.actvBlk = (unsigned long)(logSec) / Nand.pagePerBlk;
00660 #endif
00661 
00662     // Look up block map table and map logical to physical.
00663     GEN_rdSRAM(Nand.pMapTab + Nand.actvBlk, &Nand.actvPhyBlk, 1);
00664 
00665     // Calculate active physical sector.
00666     Nand.actvPhySec =
00667     phySec =
00668 
00669 #ifdef HARD_CODED_OPTIMIZATION  
00670     ((unsigned long)Nand.actvPhyBlk << 6) + Nand.actvSecOffset;         
00671 #else           
00672     (unsigned long)Nand.actvPhyBlk * Nand.pagePerBlk + Nand.actvSecOffset;          
00673 #endif
00674 
00675     return phySec;
00676 }

BOOL NAND__markInvalidBlock unsigned short  phyBlock  ) 
 

Function marks the specified block to be invalid if it is already a problematic one, otherwise marks it to be problematic.

Parameters:
phyBlock physical block number.
Returns:
TRUE if block is marked to be invalid, otherwise FALSE.

Definition at line 688 of file nand.c.

References NAND__eraseBlock(), NAND__readRdnt(), NAND__writeRdnt(), and st_NAND::pagePerBlk.

Referenced by NAND__readSec().

00689 {
00690     unsigned long   phySec;
00691     unsigned short  byte;
00692     BOOL            ret;
00693 
00694     NAND_assert(phyBlock < NAND_BLOCK_CNT, NAND__MARKINVALIDBLOCK);
00695     
00696     // Block status stores in the last sector.
00697       
00698 #ifdef HARD_CODED_OPTIMIZATION  
00699     phySec = ((unsigned long)phyBlock << 6) + 63;
00700 #else
00701     phySec = ((unsigned long)Nand.pagePerBlk * phyBlock) + Nand.pagePerBlk - 1;
00702 #endif
00703 
00704     NAND_assert(phySec < NAND_SEC_CNT, NAND__MARKINVALIDBLOCK2);
00705     
00706     // Check current block status.    
00707     NAND__readRdnt(phySec, &byte, NAND_BLOCK_STATUS_BYTE, 1);
00708     
00709     if( byte == NAND_BLOCK_STATUS_GOOD)
00710     {
00711         ret = FALSE;        
00712         byte = NAND_BLOCK_STATUS_PROBLEMATIC;
00713     }   
00714     else
00715     {
00716         ret = TRUE;     
00717         byte = NAND_BLOCK_STATUS_BAD;
00718     }
00719         
00720     // Erase block to prvent partial programming.     
00721     NAND__eraseBlock(phyBlock);
00722     
00723     // Mark block to proper state.    
00724     NAND__writeRdnt(phySec, &byte, NAND_BLOCK_STATUS_BYTE, 1);
00725 
00726     return ret;
00727 }

Here is the call graph for this function:

BOOL NAND__mount unsigned short  chip  ) 
 

Function initializes NAND flash hardware and read back the system information.

Parameters:
chip NAND chip index.
Returns:
TRUE if successfully mounted, otherwise FALSE.

Definition at line 2587 of file nand.c.

References st_NAND::currentpipo, st_NAND::dataBlkNum, st_NAND::flag, st_NAND::fmtCtrl, st_NAND::mapTabPhySecOffset, st_NAND::maxRpBlkNum, NAND__checkID(), NAND__isBlockGood(), NAND__readRdnt(), NAND__readSec(), st_NAND::pagePerBlk, st_NAND::pageSz, st_NAND::rpTabBackPhyBlk, st_NAND::rpTabPhyBlk, st_NAND::sysPhySec, and st_NAND::totalBlkNum.

Referenced by NAND_mount().

02588 {
02589     unsigned short      phyBlock;
02590     unsigned long       phySec;
02591     unsigned short      buf[256];
02592     unsigned short      ii;
02593     unsigned short      startPhyBlock[NAND_CHIP_NUM];
02594 
02595     Nand.flag = 0;
02596     
02597     // remove write protection, make the entire chip writable. 
02598     CPLD_nWP = 0;
02599     
02600     if( NAND__checkID() == FALSE )  return FALSE;
02601 
02602     // Physical block addresses of multiple chips might not
02603     // be contiguous.
02604     NAND__hwBlockMap(startPhyBlock);
02605 
02606     phyBlock = startPhyBlock[chip];
02607     
02608     // Search for the first valid block, which should 
02609     // contain system info sector. 
02610     while(NAND__isBlockGood(phyBlock) == FALSE)
02611     {       
02612         // No valid block available, volume damaged or unformatted. 
02613         if(++phyBlock > (Nand.totalBlkNum + startPhyBlock[chip]) )  
02614             return FALSE;
02615     }
02616 
02617 #ifdef HARD_CODED_OPTIMIZATION  
02618     Nand.sysPhySec[chip] = (unsigned long)phyBlock<<6;
02619 #else
02620     Nand.sysPhySec[chip] = phyBlock*Nand.pagePerBlk;
02621 #endif
02622 
02623     NAND__readRdnt(Nand.sysPhySec[chip] + 2,&ii,NAND_BLOCK_STATUS_BYTE,1);
02624     if(ii != 0x00)  return FALSE;
02625         
02626     // Read back system info sector. 
02627     if(NAND__readSec(Nand.sysPhySec[chip], buf, FALSE) == FALSE)
02628     {
02629         /* Fatal error!, system area is unreadable. */
02630         return FALSE;
02631     }
02632 
02633     
02634     // Check manufacture ID and disk signature. 
02635     if( (buf[0] != NAND_MANUFACTURE_ID) || 
02636         (buf[255] != NAND_SIGNATURE) )  return FALSE;
02637     
02638     // Check if format control flag has been set. 
02639     if( (Nand.fmtCtrl = buf[1] & 0x00FF) != 0)
02640     {           
02641         // Format flag has been set, there is no replacement 
02642         // block left, entire flash will be read only. 
02643         Nand.flag |= NAND_READ_ONLY;        
02644     }
02645     
02646     Nand.pageSz = buf[2];
02647 
02648     // Page size other than 0x100 words is not supported. 
02649     if(Nand.pageSz != 0x100) return FALSE;
02650 
02651     Nand.pagePerBlk = buf[3];
02652 
02653     Nand.dataBlkNum[chip] = buf[4];
02654     
02655     Nand.maxRpBlkNum[chip] = buf[64];
02656 
02657     Nand.rpTabPhyBlk[chip] = buf[65];
02658     
02659     Nand.mapTabPhySecOffset[chip] = buf[66];
02660     
02661     // Read the map table of data block map table. 
02662     Nand.rpTabBackPhyBlk[chip] = buf[67];
02663     
02664 #ifdef HARD_CODED_OPTIMIZATION  
02665         //phySec = ((unsigned long)(Nand.rpTabPhyBlk[chip]))<<6;
02666         phySec = ((unsigned long)buf[65])<<6;
02667 #else
02668         //phySec = ((unsigned long)(Nand.rpTabPhyBlk[chip]))*((unsigned long)Nand.pagePerBlk);
02669         phySec = ((unsigned long)buf[65])*((unsigned long)Nand.pagePerBlk);
02670 #endif
02671 
02672     NAND__readRdnt(phySec + Nand.pagePerBlk - 3, &ii, NAND_BLOCK_STATUS_BYTE, 1);
02673 
02674     Nand.currentpipo[chip] = (ii != 0xFF);
02675     if(!(Nand.currentpipo[chip]))
02676     // too complicate, unreadable
02677     //if(!(Nand.currentpipo[chip] = (ii != 0xFF)))
02678     {   
02679 #ifdef HARD_CODED_OPTIMIZATION  
02680         //phySec = ((unsigned long)(Nand.rpTabBackPhyBlk[chip]))<<6;
02681         phySec = ((unsigned long)buf[67])<<6;
02682 #else
02683         //phySec = ((unsigned long)(Nand.rpTabBackPhyBlk[chip]))*((unsigned long)Nand.pagePerBlk);
02684         phySec = ((unsigned long)buf[67])*((unsigned long)Nand.pagePerBlk);
02685 #endif
02686     
02687     }
02688     phySec = phySec + Nand.pagePerBlk - 2;
02689     
02690     /*if(ii != 0xFF)
02691         Nand.currentpipo[chip] = TRUE;
02692     else
02693         Nand.currentpipo[chip] = FALSE;
02694     */  
02695     
02696     // Read back FlushFlag. 
02697     //phySec = Nand.sysPhySec[chip] + Nand.pagePerBlk - 2;
02698     NAND__readRdnt(Nand.sysPhySec[chip] + Nand.pagePerBlk - 2, &ii, NAND_BLOCK_STATUS_BYTE, 1);
02699     
02700     if(ii != 0xFF)
02701     {
02702         NAND__readRdnt(phySec, &ii, NAND_BLOCK_STATUS_BYTE, 1);
02703         if(ii != 0xFF)
02704             Nand.flag |= NAND_ERASEALL_NEED;
02705         else
02706             Nand.flag |= NAND_ERASE_NEED;
02707     }
02708     
02709     return (TRUE);
02710 }

Here is the call graph for this function:

BOOL NAND__rdSec unsigned long  sec,
unsigned short *  pBuf,
BOOL  swap
 

Function reads back the specified logical sector, specified by the FAT file system layer.

Parameters:
sec logical NAND sector.
pBuf sector data buffer pointer.
swap byte swap cotrol.
Returns:
TRUE if successfully read, otherwise FALSE.

Definition at line 2807 of file nand.c.

References st_NAND::actvBlkEndSec, st_NAND::actvPhyBlk, st_NAND::actvRpPhyBlk, st_NAND::flag, NAND__historyCheck(), NAND__readSec(), st_NAND::pagePerBlk, st_NAND::pMapTab, and st_NAND::writingSec.

Referenced by NAND_readSec().

02808 {
02809     unsigned long   phySec;
02810     USHORT          phyBlk;
02811     BOOL            ret = FALSE;
02812     
02813     if( TRUE == NAND__historyCheck() )
02814     {
02815         // Always flush if flag is set before any reading. 
02816         if(Nand.flag & NAND_FLUSH_DATA_BLOCK_PENDING) 
02817         {           
02818             // Shall NOT flush if sector is still in current block range. 
02819             // directly read from the replaced block or current writing
02820             // block.
02821             if( ((unsigned long)sec >= (unsigned long)(Nand.actvBlkEndSec - 64)) && 
02822                 ((unsigned long)sec < (unsigned long)Nand.actvBlkEndSec) )
02823             {
02824                 
02825                 if( sec > Nand.writingSec ) 
02826                     // Read from replaced block. 
02827                     phyBlk = Nand.actvRpPhyBlk;
02828                 else 
02829                      phyBlk = Nand.actvPhyBlk;
02830                             
02831                     // Read from current block.
02832                 #ifdef HARD_CODED_OPTIMIZATION          
02833                     phySec = ((unsigned long)phyBlk<<6) + ((unsigned long)sec & 0x003F);
02834                 #else
02835                     phySec = (unsigned long)phyBlk * Nand.pagePerBlk + (unsigned long)sec % Nand.pagePerBlk;
02836                 #endif
02837                 
02838                 // Report any error directly to upper file system layer. 
02839                 ret = NAND__readSec(phySec, pBuf, swap);    
02840                 
02841                 return ret;
02842             }
02843         }
02844     
02845         // Look up block map table and map logical to physical.
02846         GEN_rdSRAM(Nand.pMapTab + ((unsigned long)sec>>6), &phyBlk, 1);
02847     
02848         // Calculate active physical sector.
02849         phySec =    ((unsigned long)phyBlk << 6) + ((unsigned long)sec & 0x003F);
02850     
02851         // Report any error directly to upper file system layer. 
02852         ret = NAND__readSec(phySec, pBuf, swap);    
02853     }
02854     
02855     return ret;
02856 }

Here is the call graph for this function:

BOOL NAND__readDataSec unsigned long  phySec,
unsigned short *  pBuf,
BOOL  swap
 

Function reads back to verify the specified data page/sector.

Parameters:
phySec physical NAND sector number.
pBuf pointer to data sent to sector.
swap (undocumented).
Returns:
TRUE if no error found, otherwise FALSE.

Definition at line 1076 of file nand.c.

References NAND_WAIT4READY.

Referenced by NAND__historyCheck(), and NAND__writeSec().

01077 {
01078 
01079     unsigned short  ii;
01080     unsigned long   columnAddr;
01081 
01082     unsigned short  temp0, temp1, value;
01083     unsigned char   addr_0_7;
01084     unsigned char   addr_9_16;
01085     unsigned char   addr_17_24;
01086     unsigned char   addr_25_27;
01087     BOOL            ret;
01088 
01089     NAND_assert (phySec < NAND_SEC_CNT, NAND__READDATASEC);
01090     NAND_assert (pBuf != NULL, NAND__READDATASEC2);
01091     
01092     NAND_WAIT4READY(temp0);
01093     
01094     // Assert CLE: write to the port will set CLE to HIGH
01095     CPLD_CLE = 0;   
01096 
01097     // NAND chip 0, write to the port will enable CE0
01098     CPLD_CE0 = 0;
01099 
01100     // Form the column address on whole pages 
01101     columnAddr = (unsigned long) (phySec << 9);
01102 
01103     // Parse the column address
01104     //addr_0_7 =    (unsigned char)(columnAddr) & 0xFF;
01105     addr_0_7 =  0;
01106     addr_9_16 = (unsigned char)((unsigned long)columnAddr >> 9) & 0xFF;
01107     addr_17_24 = (unsigned char)((unsigned long)columnAddr >> 17) & 0xFF;
01108     addr_25_27 = (unsigned char)((unsigned long)columnAddr >> 25) & 0x7;
01109 
01110     // send 'Read Mode (1)' command
01111     CPLD_RDWR = NAND_CMD__READ1;
01112 
01113     // Deassert CLE: read from the port will reset CLE to LOW
01114     temp0 = CPLD_CLE;
01115 
01116     // Assert ALE, TBD by cpld code
01117     CPLD_ALE = 0;
01118 
01119     // send address to NAND chip
01120     CPLD_RDWR = addr_0_7;
01121     CPLD_RDWR = addr_9_16;
01122     CPLD_RDWR = addr_17_24;
01123     CPLD_RDWR = addr_25_27;
01124 
01125     // Deassert ALE, TBD by cpld code
01126     temp0 = CPLD_ALE;
01127     
01128     ret = TRUE; 
01129     // Wait for Ready/#Busy signal (input on D0) goes to HIGH.  
01130     NAND_WAIT4READY(temp0);
01131 
01132     // Read sector to verify.
01133     for(ii = 0; ii < 256; ii++)
01134     {
01135         temp0 = CPLD_RDWR;
01136         temp1 = CPLD_RDWR;
01137 
01138         value = (swap == TRUE)? (temp1<<8)|(temp0 & 0x00ff):
01139                                 (temp0<<8)|(temp1 & 0x00ff);
01140         
01141         if(*pBuf != value) 
01142         {
01143             ret = FALSE;            
01144             break;
01145         }
01146         
01147         pBuf++;
01148     }
01149 
01150 
01151     // Deassert CE, read from the port will disable CE0
01152     temp1 = CPLD_CE0;
01153 
01154     return ret;
01155 } //BOOL NAND__readDataSec( unsigned long phySec, unsigned short * pBuf, BOOL swap)

BOOL NAND__readRdnt unsigned long  phySec,
unsigned short *  pData,
unsigned short  offSet,
unsigned short  len
 

Function reads byte(s) from redundant area.

Parameters:
phySec physical sector specifier.
pData pointer to byte array ( lower 8 bits only ).
offSet start byte offset.
len number of data bytes.
Returns:
TRUE if successfully written, otherwise FALSE.

Definition at line 743 of file nand.c.

References NAND_WAIT4READY.

Referenced by NAND__isBlockGood(), NAND__isBlockValid(), NAND__markInvalidBlock(), and NAND__mount().

00747 {
00748     unsigned long   columnAddr;
00749     unsigned long   RdntByteAddr;
00750     unsigned short  ii;
00751     unsigned short  temp0;
00752     unsigned char   addr_0_7;
00753     unsigned char   addr_9_16;
00754     unsigned char   addr_17_24;
00755     unsigned char   addr_25_27;
00756 
00757     NAND_assert (phySec < NAND_SEC_CNT, NAND__READRDNT);
00758     NAND_assert (pData != NULL, NAND__READRDNT2);
00759     
00760     NAND_WAIT4READY(temp0);
00761 
00762     // Assert CLE: write to the port will set CLE to HIGH  
00763     CPLD_CLE = 0;
00764     
00765     // Currently one single 128M chip is used.  
00766     // NAND chip 0, write to the port will enable CE0  
00767     CPLD_CE0 = 0;
00768 
00769     // Form the column address on whole pages  
00770     columnAddr = (unsigned long) (phySec << 9);
00771 
00772     // Form the redundant byte (column) address:
00773     //      columnAddr                          (= phySec<<9) + 
00774     //      in-page main storage byte-offset    (= 512) +
00775     //      redundant byte offset               ( = offSet);
00776     RdntByteAddr = columnAddr + (unsigned long) offSet;
00777 
00778     // Parse the column address  
00779     addr_0_7 =  (unsigned char)(RdntByteAddr & 0xFF);
00780     addr_9_16 = (unsigned char)(((unsigned long)RdntByteAddr >> 9) & 0xFF);
00781     addr_17_24 = (unsigned char)(((unsigned long)RdntByteAddr >> 17) & 0xFF);
00782     addr_25_27 = (unsigned char)(((unsigned long)RdntByteAddr >> 25) & 0x7);
00783 
00784     // send 'Read Mode (3)' command  
00785     CPLD_RDWR = NAND_CMD__READ3;
00786 
00787     // Deassert CLE: read from the port will reset CLE to LOW  
00788     temp0 = CPLD_CLE;
00789 
00790     // Assert ALE, TBD by cpld code  
00791     CPLD_ALE = 0;
00792 
00793     // send address to NAND chip  
00794     CPLD_RDWR = addr_0_7;
00795     CPLD_RDWR = addr_9_16;
00796     CPLD_RDWR = addr_17_24;
00797     CPLD_RDWR = addr_25_27;
00798 
00799     // Deassert ALE, TBD by cpld code  
00800     temp0 = CPLD_ALE;
00801 
00802     // Wait for Ready/#Busy signal (input on D0) goes to HIGH.  
00803     NAND_WAIT4READY(temp0);
00804 
00805     // Read byte  
00806     for(ii = 0; ii < len; ii++) *pData++ = (CPLD_RDWR & 0x00FF);
00807 
00808     // Deassert CE, read from the port will disable CE0 
00809     addr_0_7 = CPLD_CE0;  
00810 
00811     return TRUE;
00812 }

BOOL NAND__readSec unsigned long  phySec,
unsigned short *  pBuf,
BOOL  swap
 

Function reads back the specified page/sector.

Parameters:
phySec physical NAND sector number.
pBuf sector data buffer pointer.
swap byte swap control.
Returns:
TRUE if successfully read, otherwise FALSE.

Definition at line 945 of file nand.c.

References NAND__markInvalidBlock(), NAND_WAIT4READY, and st_NAND::pagePerBlk.

Referenced by NAND__copySec(), NAND__loadTab(), NAND__mount(), and NAND__rdSec().

00946 {
00947 
00948     unsigned short   ii;
00949     unsigned long    columnAddr;
00950 
00951     unsigned short   temp0, temp1;
00952     unsigned char    addr_0_7;
00953     unsigned char    addr_9_16;
00954     unsigned char    addr_17_24;
00955     unsigned char    addr_25_27;
00956 
00957     unsigned char    redundant[16];
00958     unsigned char    ecc1_1, ecc1_2, ecc1_3;
00959     unsigned char    ecc2_1, ecc2_2, ecc2_3;
00960 
00961     unsigned short * pData = pBuf;
00962     
00963     NAND_assert (phySec < NAND_SEC_CNT, NAND__READSEC);
00964     NAND_assert (pBuf != NULL, NAND__READSEC2);
00965 
00966     NAND_WAIT4READY(temp0);
00967 
00968     // Assert CLE: write to the port will set CLE to HIGH.
00969     CPLD_CLE = 0;
00970 
00971     // NAND chip 0, write to the port will enable CE0
00972     CPLD_CE0 = 0;
00973 
00974     // Form the column address on whole pages  
00975     columnAddr = (unsigned long) (phySec << 9);
00976 
00977     // Parse the column address  
00978     //addr_0_7 =    (unsigned char)(columnAddr) & 0xFF;
00979     addr_0_7 =  0;
00980     addr_9_16 = (unsigned char)((unsigned long)columnAddr >> 9) & 0xFF;
00981     addr_17_24 = (unsigned char)((unsigned long)columnAddr >> 17) & 0xFF;
00982     addr_25_27 = (unsigned char)((unsigned long)columnAddr >> 25) & 0x7;
00983 
00984     // send 'Read Mode (1)' command  
00985     CPLD_RDWR = NAND_CMD__READ1;
00986 
00987     // Deassert CLE: read from the port will reset CLE to LOW  
00988     temp0 = CPLD_CLE;
00989 
00990     // Assert ALE, TBD by cpld code  
00991     CPLD_ALE = 0;
00992 
00993     // send address to NAND chip  
00994     CPLD_RDWR = addr_0_7;
00995     CPLD_RDWR = addr_9_16;
00996     CPLD_RDWR = addr_17_24;
00997     CPLD_RDWR = addr_25_27;
00998 
00999     // Deassert ALE, TBD by cpld code  
01000     temp0 = CPLD_ALE;
01001     
01002     // Wait for Ready/#Busy signal (input on D0) goes to HIGH.      
01003     NAND_WAIT4READY(temp0);
01004 
01005 
01006     // Read sector  
01007     ReadAndEncode256bytes( pBuf, swap, &ecc1_1, &ecc1_2, &ecc1_3);
01008     ReadAndEncode256bytes( pBuf+128, swap, &ecc2_1, &ecc2_2, &ecc2_3);
01009 
01010     //Read redundant area.    
01011     pBuf = (unsigned short *)redundant;
01012     
01013     for(ii = 0; ii < 16; ii++)
01014     {
01015         *pBuf++ = (CPLD_RDWR & 0x00FF);
01016     }
01017     
01018     if( eccCorrectDataRedundant((UCHAR SDFAR *)redundant, 
01019                                 (UCHAR SDFAR *)&redundant[NAND_ECC3_1_OFFSET],
01020                                 (UCHAR SDFAR *)&redundant[NAND_ECC3_2_OFFSET] ) == YES )
01021     {
01022         // Deassert CE, read from the port will disable CE0
01023         temp1 = CPLD_CE0;
01024 
01025         if( eccCorrectDataCommon(   (UCHAR SDFAR *)pData, swap,
01026                                     (UCHAR SDFAR *)&redundant[NAND_ECC1_1_OFFSET],
01027                                     (UCHAR SDFAR *)&redundant[NAND_ECC1_2_OFFSET],
01028                                     (UCHAR SDFAR *)&redundant[NAND_ECC1_3_OFFSET], 
01029                                      ecc1_1, ecc1_2,  ecc1_3) == YES )
01030         {
01031             if( eccCorrectDataCommon(   (UCHAR SDFAR *)pData + 128, swap,
01032                                         (UCHAR SDFAR *)&redundant[NAND_ECC2_1_OFFSET],
01033                                         (UCHAR SDFAR *)&redundant[NAND_ECC2_2_OFFSET],
01034                                         (UCHAR SDFAR *)&redundant[NAND_ECC2_3_OFFSET],
01035                                          ecc2_1, ecc2_2, ecc2_3) == YES )
01036             {
01037                 return TRUE;
01038             }
01039         }
01040     }
01041 
01042     // Mark the block to be invalid, the caller will then try to handle the error.
01043     // Well, nobody can handle the read error, the caller will eventually reformat
01044     // the chip.
01045       
01046 #ifdef HARD_CODED_OPTIMIZATION  
01047     if(NAND__markInvalidBlock((unsigned long)phySec>>6) == FALSE )
01048     {
01049         NAND__markInvalidBlock((unsigned long)phySec>>6);
01050     }
01051 #else
01052     if(NAND__markInvalidBlock((unsigned long)(phySec) / Nand.pagePerBlk) == FALSE)
01053     {
01054         NAND__markInvalidBlock((unsigned long)(phySec) / Nand.pagePerBlk);
01055     }
01056 #endif
01057     
01058     return FALSE;
01059 
01060 }// BOOL NAND__readSec( unsigned long phySec, unsigned short * pBuf, BOOL swap )  

Here is the call graph for this function:

BOOL NAND__replaceDataSec unsigned long *  pPhySec  ) 
 

Function tries to replace the defected block where phySec resides in.

This function assumes that any sectors prior to the defectd one ( pPhySec ) are still be readable.

Parameters:
pPhySec pointer to physical sector.
Returns:
TRUE if defected block is successfully replaced, otherwise FALSE.

Definition at line 575 of file nand.c.

References st_NAND::actvPhyBlk, st_NAND::actvPhySec, st_NAND::actvRpPhyBlk, st_NAND::actvSecOffset, st_NAND::flag, st_SECT_HISTORY::logBlk, NAND__copySec(), NAND__eraseBlock(), NAND_COPYERR, st_NAND::pagePerBlk, st_SECT_HISTORY::phyBlk, st_NAND::pMapTab, st_NAND::pRpTab, st_SECT_HISTORY::secOffset, and sectHistory.

Referenced by NAND__historyCheck().

00576 {
00577     NAND_COPYERR    err;
00578     unsigned short  tmp;
00579     
00580     GEN_rdSRAM(Nand.pRpTab, &tmp, 1);
00581     err = NAND__copySec(sectHistory.phyBlk, 
00582                         &tmp, 
00583                         0, 
00584                         Nand.actvSecOffset );
00585                         
00586     if(err == CPYERR_NONE)
00587     {
00588 #ifdef HARD_CODED_OPTIMIZATION
00589         Nand.actvPhySec =
00590             *pPhySec = ((long)tmp<<6) + sectHistory.secOffset;
00591 #else               
00592         Nand.actvPhySec =
00593             *pPhySec = (long)tmp*Nand.pagePerBlk + sectHistory.secOffset;
00594 #endif
00595 
00596         Nand.actvPhyBlk = tmp;
00597         GEN_wrSRAM(Nand.pMapTab + sectHistory.logBlk, &tmp, 1);
00598                 
00599         NAND__wrRpHis(sectHistory.phyBlk,FALSE);
00600         return TRUE;
00601     }
00602     
00603     if(err == CPYERR_READ)  NAND__eraseBlock(tmp);
00604         
00605     NAND__getLastRpInsert();
00606     
00607     GEN_wrSRAM(Nand.pMapTab + sectHistory.logBlk, 
00608                &Nand.actvRpPhyBlk, 
00609                1);
00610          
00611     GEN_wrSRAM(Nand.pRpTab, &(sectHistory.phyBlk), 1);
00612         
00613     NAND__wrRpHis(0xFFFE,FALSE);
00614 
00615     Nand.flag &=  ~NAND_FLUSH_DATA_BLOCK_PENDING;
00616     return FALSE;
00617 }

Here is the call graph for this function:

BOOL NAND__swapSec unsigned long *  pPhySec,
unsigned long  logSec
 

Function tries to allocate a free block and swap with the one the specified logSec resides in.

It is the caller's responsibility to make sure there is no pending data block before this function gets called.

Parameters:
pPhySec physical sector pointer.
logSec logical sector number.
Returns:
TRUE if block successfully swapped, otherwise FALSE.

Definition at line 3137 of file nand.c.

References st_NAND::actvBlk, st_NAND::actvBlkEndSec, st_NAND::actvPhyBlk, st_NAND::actvPhySec, st_NAND::actvRpPhyBlk, st_NAND::actvSecOffset, CPYERR_NONE, CPYERR_READ, CPYERR_WRITE, st_NAND::flag, NAND__copySec(), NAND__eraseBlock(), NAND_COPYERR, st_NAND::pagePerBlk, st_NAND::pMapTab, and st_NAND::pRpTab.

Referenced by NAND__wrSec().

03138 {
03139     NAND_COPYERR    err;
03140     unsigned short  tmp;
03141     
03142     NAND_assert (pPhySec != NULL                 , NAND__SWAPSEC);
03143     NAND_assert (logSec < NAND_SEC_CNT           , NAND__SWAPSEC2);
03144     
03145     // If replacement block is used up, return immediately. 
03146     //if(Nand.curRpBlkNum == 0) return FALSE;
03147 
03148     // Calculate block end sector. 
03149 #ifdef HARD_CODED_OPTIMIZATION
03150     Nand.actvBlkEndSec = (unsigned long)((unsigned long)logSec & 0xFFFFFFC0L)
03151                                 + Nand.pagePerBlk;  
03152 #else
03153     Nand.actvBlkEndSec = (unsigned long)((unsigned long)logSec/Nand.pagePerBlk)*Nand.pagePerBlk
03154                                 + Nand.pagePerBlk;  
03155 #endif  
03156 
03157     // Set flag to flush data block and block map table. 
03158     //Nand.flag |= (    NAND_FLUSH_DATA_BLOCK_PENDING |
03159                         //NAND_FLUSH_REPLACE_TAB_PENDING |
03160                         //NAND_FLUSH_MAP_TABLE_PENDING  );
03161                         
03162     // If not marked FLUSH_PENDING already, mark it. 
03163     /*if( !(Nand.flag & NAND_FLUSH_PENDING) )
03164     {       
03165         Nand.flag |= NAND_FLUSH_PENDING;
03166         
03167         tmp = 0;
03168         
03169         NAND_Assert (Nand.actvChip < _N, kNandErr+431);
03170         
03171         NAND__writeRdnt(    Nand.sysPhySec[Nand.actvChip] + 1, 
03172                                 &tmp, 
03173                                 NAND_BLOCK_STATUS_BYTE, 
03174                                 1);
03175     }*/
03176 
03177     // Remember which block is swaped. 
03178     Nand.actvRpPhyBlk = Nand.actvPhyBlk;
03179     
03180     // Reserve the first replacement block. 
03181     //Nand.rsvRpBlk = 1;
03182 
03183     // Attempt to replace it with the first available 
03184     // replacement block.
03185     GEN_rdSRAM(Nand.pRpTab, &tmp, 1);
03186     
03187     // Copy from src to dst, function returns the dst block in tmp. 
03188     err = NAND__copySec(    Nand.actvPhyBlk, 
03189                             &tmp, 
03190                             0, 
03191                             Nand.actvSecOffset );
03192                         
03193     switch(err)
03194     {
03195         case CPYERR_WRITE:  return FALSE;
03196 
03197         case CPYERR_READ:
03198             // Error read the source block, unable to swap.
03199             // Erase the destination block to maintain free 
03200             // replacement block all the time.
03201             NAND__eraseBlock(tmp);
03202             
03203             // we'll go ahead and replace the bad block if
03204             // there is any replacement block available thus to make
03205             // the entire flash to be as contiguous as possible. 
03206             GEN_wrSRAM(Nand.pMapTab + Nand.actvBlk, &tmp, 1);
03207             
03208             NAND__wrRpHis(Nand.actvPhyBlk,FALSE);
03209             return FALSE;
03210 
03211         case CPYERR_NONE:
03212         default:
03213 #ifdef HARD_CODED_OPTIMIZATION          
03214             Nand.actvPhySec =
03215             *pPhySec = ((unsigned long)tmp<<6) + Nand.actvSecOffset;
03216 #else
03217             Nand.actvPhySec =
03218             *pPhySec = (unsigned long)tmp*Nand.pagePerBlk + Nand.actvSecOffset;
03219 #endif
03220         
03221             //block = Nand.actvPhyBlk;
03222 
03223             Nand.actvPhyBlk = tmp;
03224             
03225             GEN_wrSRAM(Nand.pMapTab + Nand.actvBlk, &tmp, 1);
03226             
03227             Nand.flag |= NAND_FLUSH_DATA_BLOCK_PENDING;
03228             
03229             return NAND__wrRpHis((Nand.actvRpPhyBlk),TRUE);         
03230     }   
03231 }

Here is the call graph for this function:

BOOL NAND__test void   ) 
 

Function tests NAND interface.

Returns:
TRUE if tests pass, otherwise FALSE.

Definition at line 2887 of file nand.c.

References NAND_format(), NAND_mount(), NAND_readSec(), NAND_unmount(), and NAND_writeSec().

02888 {
02889     unsigned long maxAddr, jj, kk;
02890     unsigned short buf[256];
02891     unsigned short ii;
02892     unsigned short a, b, c;
02893     
02894     a = 0;
02895     b = 0;
02896     c = 0;
02897     kk = 0x33333;
02898 
02899     if(a == 0) return TRUE;
02900     
02901     if(c) NAND_format();
02902     
02903     maxAddr = NAND_mount();
02904     if(0 == maxAddr) return FALSE;
02905 
02906     {
02907         for(ii = 0; ii < 256; ii++) buf[ii] = ii;
02908         
02909         if(b)
02910         {
02911             for(jj = 0; jj < kk; jj++)
02912             {
02913                 NAND_writeSec(jj, buf, TRUE);
02914             }
02915         }
02916                 
02917         for(jj = 0; jj < kk; jj++)
02918         {           
02919             NAND_readSec(jj, buf, TRUE);
02920             for(ii = 0; ii < 256; ii++) 
02921             {
02922                 if(buf[ii] != ii) break;
02923             }
02924         }
02925     }   
02926     NAND_unmount();
02927     
02928     return (ii == 256)? TRUE:FALSE;
02929 }

Here is the call graph for this function:

BOOL NAND__write unsigned long  phySec,
unsigned long  pData,
unsigned short  length
 

Function writes the specified data back to specified sector(s), it is the caller's responsibility to make sure the corresponding sector(s) is/are blank and cross block shall never happen.

Parameters:
phySec starting physical sector.
pData SRAM data pointer.
length data length in words.
Returns:
TRUE if successfully written, otherwise FALSE.

Definition at line 1581 of file nand.c.

References NAND__writeSec(), and st_NAND::pageSz.

Referenced by NAND__flushBlock(), and NAND__formatChip().

01584 {
01585     unsigned short  ii;
01586     unsigned short  jj;
01587     unsigned short *pBuf;
01588     unsigned short  modlen;
01589     unsigned short  buf[256];
01590     
01591     NAND_assert (phySec < NAND_SEC_CNT                         , NAND__WRITE);
01592     NAND_assert (pData != 0                                    , NAND__WRITE2);
01593     
01594     ii = 0;
01595     while(length)
01596     {
01597         modlen = (length > Nand.pageSz)? Nand.pageSz : length;
01598         
01599     #ifdef HARD_CODED_OPTIMIZATION          
01600         GEN_rdSRAM((unsigned long)((unsigned long)pData + (ii<<8)), buf, modlen);
01601     #else
01602         GEN_rdSRAM((unsigned long)((unsigned long)pData + ii*Nand.pageSz), buf, modlen);
01603     #endif  
01604                 
01605         pBuf = &buf[modlen];
01606         for(jj = modlen; jj < Nand.pageSz; jj++) *pBuf++ = 0xFFFF;
01607 
01608         if(NAND__writeSec(phySec + ii, buf, FALSE) == FALSE ) return FALSE;
01609 
01610         ii++;
01611         
01612         length -= modlen;   
01613     }
01614     
01615     return TRUE;
01616 }

Here is the call graph for this function:

void NAND__writeDataSec unsigned long  phySec,
unsigned short *  pBuf,
BOOL  swap
 

Function writes data to the specified blank page/sector.

Parameters:
phySec physical NAND sector number.
pBuf sector data buffer pointer.
swap byte swap control.
Returns:
TRUE if successfully written, otherwise FALSE.

Definition at line 1317 of file nand.c.

References NAND_WAIT4READY.

Referenced by NAND__wrSec().

01318 {
01319     unsigned short  ii;
01320     unsigned long   columnAddr;
01321 
01322     unsigned short  temp;
01323     unsigned char   addr_0_7;
01324     unsigned char   addr_9_16;
01325     unsigned char   addr_17_24;
01326     unsigned char   addr_25_27;
01327     unsigned char   redundant[16];  // 16 redundant bytes.
01328     unsigned char * pC;
01329     
01330     NAND_assert (phySec < NAND_SEC_CNT, NAND__WRITEDATASEC);
01331     NAND_assert (pBuf != NULL, NAND__WRITEDATASEC2);
01332     
01333     ii = 16;
01334     pC = &redundant[0];
01335     while(ii--)*pC++ = 0x00ff;
01336     
01337     // Wait till interface is ready.     
01338     NAND_WAIT4READY(temp);
01339     
01340     // Remove write protection
01341     //CPLD_nWP = 0;
01342 
01343     // Assert CLE: write to the port will set CLE to HIGH
01344     CPLD_CLE = 0;
01345 
01346     // NAND chip 0, write to the port will enable CE0 
01347     CPLD_CE0 = 0;
01348 
01349     // Form the column address on whole pages 
01350     columnAddr = (unsigned long) ((unsigned long)phySec << 9);
01351 
01352     // Parse the column address 
01353     //addr_0_7 =    (unsigned char)(columnAddr) & 0xFF;
01354     addr_0_7 =  0;
01355     addr_9_16 = (unsigned char)((unsigned long)columnAddr >> 9) & 0xFF;
01356     addr_17_24 = (unsigned char)((unsigned long)columnAddr >> 17) & 0xFF;
01357     addr_25_27 = (unsigned char)((unsigned long)columnAddr >> 25) & 0x7;
01358 
01359     // send 'Read Mode (1)' command to set the pointer
01360     // in A area on NAND chip
01361     CPLD_RDWR = NAND_CMD__READ1;
01362 
01363     // send 'Serial Data input' command
01364     CPLD_RDWR = NAND_CMD__DATAIN;
01365 
01366     // Deassert CLE: read from the port will reset CLE to LOW
01367     temp = CPLD_CLE;
01368 
01369     // Assert ALE, TBD by cpld code
01370     CPLD_ALE = 0;
01371 
01372     // send address to NAND chip
01373     CPLD_RDWR = addr_0_7;
01374     CPLD_RDWR = addr_9_16;
01375     CPLD_RDWR = addr_17_24;
01376     CPLD_RDWR = addr_25_27;
01377 
01378     // Deassert ALE, TBD by cpld code 
01379     temp = CPLD_ALE;
01380 
01381     // send data
01382     // Send and encode first 256 bytes
01383     WriteAndEncode256bytes(pBuf,swap,
01384                             (UCHAR SDFAR *) &redundant[NAND_ECC1_1_OFFSET],
01385                             (UCHAR SDFAR *) &redundant[NAND_ECC1_2_OFFSET],
01386                             (UCHAR SDFAR *) &redundant[NAND_ECC1_3_OFFSET] );
01387 
01388     // Send and encode second 256 bytes
01389     WriteAndEncode256bytes(pBuf+128,swap,
01390                             (UCHAR SDFAR *) &redundant[NAND_ECC2_1_OFFSET],
01391                             (UCHAR SDFAR *) &redundant[NAND_ECC2_2_OFFSET],
01392                             (UCHAR SDFAR *) &redundant[NAND_ECC2_3_OFFSET] );
01393     
01394     eccEncodeRedundant((UCHAR SDFAR *)redundant,
01395                             (UCHAR SDFAR *)&redundant[NAND_ECC3_1_OFFSET],
01396                             (UCHAR SDFAR *)&redundant[NAND_ECC3_2_OFFSET]);
01397 
01398     // Sending out redundant data.
01399     pBuf = (unsigned short *)redundant; 
01400     for( ii = 0; ii < 16; ii++) CPLD_RDWR = *pBuf++;
01401     
01402 
01403     // Assert CLE: write to the port will set CLE to HIGH
01404     CPLD_CLE = 0;
01405     
01406     // send 'Auto Program (True)' command
01407     CPLD_RDWR = NAND_CMD__AUTO_PROGRAM_TRUE;
01408 
01409     // Deassert CLE: read from the port will reset CLE to LOW
01410     temp = CPLD_CLE;
01411     temp = 0;
01412 
01413     // Deassert CE, read from the port will disable CE0
01414     addr_0_7 = CPLD_CE0;
01415 }// void NAND__writeDataSec( unsigned long phySec, unsigned short * pBuf, BOOL swap )

BOOL NAND__writeRdnt unsigned long  phySec,
unsigned short *  pData,
unsigned short  offSet,
unsigned short  len
 

Function writes byte(s) to redundant area.

Parameters:
phySec physical sector specifier.
pData pointer to byte array ( lower 8 bits only ).
offSet start byte offset.
len number of data bytes.
Returns:
TRUE if successfully written, otherwise FALSE.

Definition at line 828 of file nand.c.

References NAND_WAIT4READY.

Referenced by NAND__buildSysInfo(), NAND__flushBlock(), NAND__formatChip(), NAND__markInvalidBlock(), and NAND_mount().

00832 {
00833     unsigned short  temp;
00834     unsigned short  ii; 
00835     unsigned long   columnAddr;
00836     unsigned long   RdntByteAddr;
00837     unsigned char   addr_0_7;
00838     unsigned char   addr_9_16;
00839     unsigned char   addr_17_24;
00840     unsigned char   addr_25_27;
00841     
00842     NAND_assert (phySec < NAND_SEC_CNT, NAND__WRITERDNT);
00843     NAND_assert (pData != NULL, NAND__WRITERDNT2);
00844     
00845     NAND_WAIT4READY(temp);
00846 
00847     // Remove write protection  
00848     //CPLD_nWP = 0;
00849 
00850     // Assert CLE: write to the port will set CLE to HIGH  
00851     CPLD_CLE = 0;
00852 
00853     // NAND chip 0, write to the port will enable CE0  
00854     CPLD_CE0 = 0;
00855 
00856     // Form the column address on whole pages  
00857     columnAddr = (unsigned long) ((unsigned long)phySec << 9);
00858 
00859     // Form the redundant byte (column) address:
00860     //      columnAddr                          (= phySec<<9) + 
00861     //      in-page main storage byte-offset    (= 512) +
00862     //      redundant byte offset               ( = offSet);
00863     RdntByteAddr = columnAddr + (unsigned long) offSet;
00864 
00865     // Parse the column address  
00866     addr_0_7 =  (unsigned char)(RdntByteAddr & 0xFF);
00867     addr_9_16 = (unsigned char)(((unsigned long)RdntByteAddr >> 9) & 0xFF);
00868     addr_17_24 = (unsigned char)(((unsigned long)RdntByteAddr >> 17) & 0xFF);
00869     addr_25_27 = (unsigned char)(((unsigned long)RdntByteAddr >> 25) & 0x7);
00870 
00871     // send 'Read Mode (3)' command to set pointer to region C
00872     // (between 512 to 527 byte address in-page) on NAND chip.    
00873     CPLD_RDWR = NAND_CMD__READ3;
00874 
00875     // send 'Serial Data input' command  
00876     CPLD_RDWR = NAND_CMD__DATAIN;
00877 
00878     // Deassert CLE: read from the port will reset CLE to LOW  
00879     temp = CPLD_CLE;
00880 
00881     // Assert ALE, TBD by cpld code  
00882     CPLD_ALE = 0;
00883 
00884     // send address to NAND chip  
00885     CPLD_RDWR = addr_0_7;
00886     CPLD_RDWR = addr_9_16;
00887     CPLD_RDWR = addr_17_24;
00888     CPLD_RDWR = addr_25_27;
00889 
00890     // Deassert ALE  
00891     temp = CPLD_ALE;
00892 
00893     // send data  
00894     for( ii = 0; ii < len; ii++) CPLD_RDWR = *pData++;
00895     
00896     // Assert CLE: write to the port will set CLE to HIGH  
00897     CPLD_CLE = 0;
00898     
00899     // send 'Auto Program (True)' command  
00900     CPLD_RDWR = NAND_CMD__AUTO_PROGRAM_TRUE;
00901     
00902     // Wait for Ready/#Busy signal (input on D0) goes to HIGH.  
00903     NAND_WAIT4READY(temp);
00904 
00905     // send 'Status Read (1)' command  
00906     CPLD_RDWR = NAND_CMD__STATUS_READ1;
00907 
00908     // Deassert CLE: read from the port will reset CLE to LOW  
00909     temp = CPLD_CLE;
00910 
00911     // Restore write protection  
00912     //addr_0_7 = CPLD_nWP;
00913 
00914     // Read status data  
00915     temp = CPLD_RDWR;
00916 
00917     // Deassert CE  
00918     addr_0_7 = CPLD_CE0;    // read from the port will disable CE0  
00919 
00920     if ( (temp & 0x0001 ) == 0 ) 
00921     {
00922         // programming pass  
00923         return (TRUE);
00924     }
00925     else 
00926     {
00927         // programming fail  
00928         return (FALSE);
00929     }
00930 }

BOOL NAND__writeSec unsigned long  phySec,
unsigned short *  pBuf,
BOOL  swap
 

Function writes to the specified blank page/sector.

Parameters:
phySec physical NAND sector number.
pBuf sector data buffer pointer.
swap byte swap control.
Returns:
TRUE if successfully written, otherwise FALSE.

Definition at line 1170 of file nand.c.

References NAND__readDataSec(), and NAND_WAIT4READY.

Referenced by NAND__buildSysInfo(), NAND__copySec(), NAND__formatChip(), NAND__historyCheck(), and NAND__write().

01171 {
01172     unsigned short   ii;
01173     unsigned long    columnAddr;
01174     unsigned short   temp;
01175     unsigned char    addr_0_7;
01176     unsigned char    addr_9_16;
01177     unsigned char    addr_17_24;
01178     unsigned char    addr_25_27;
01179     unsigned short * pData; 
01180     unsigned char    redundant[16]; // 16 redundant bytes.
01181 
01182     NAND_assert (phySec < NAND_SEC_CNT, NAND__WRITESEC);
01183     NAND_assert (pBuf != NULL, NAND__WRITESEC2);
01184     
01185     ii = 16;
01186     pData = (unsigned short *)&redundant[0];
01187     while(ii--)*pData++ = 0x00ff;
01188     
01189     NAND_WAIT4READY(temp);
01190 
01191     // Remove write protection  
01192     //CPLD_nWP = 0;
01193 
01194     // Assert CLE: write to the port will set CLE to HIGH  
01195     CPLD_CLE = 0;
01196 
01197     // NAND chip 0, write to the port will enable CE0  
01198     CPLD_CE0 = 0;
01199 
01200     // Form the column address on whole pages  
01201     columnAddr = (unsigned long) ((unsigned long)phySec << 9);
01202 
01203     // Parse the column address  
01204     //addr_0_7 =    (unsigned char)(columnAddr) & 0xFF;
01205     addr_0_7 =  0;
01206     addr_9_16 = (unsigned char)((unsigned long)columnAddr >> 9) & 0xFF;
01207     addr_17_24 = (unsigned char)((unsigned long)columnAddr >> 17) & 0xFF;
01208     addr_25_27 = (unsigned char)((unsigned long)columnAddr >> 25) & 0x7;
01209 
01210 
01211     // send 'Read Mode (1)' command to set the pointer in A area on NAND chip     
01212     CPLD_RDWR = NAND_CMD__READ1;
01213 
01214     // send 'Serial Data input' command  
01215     CPLD_RDWR = NAND_CMD__DATAIN;
01216 
01217     // Deassert CLE: read from the port will reset CLE to LOW  
01218     temp = CPLD_CLE;
01219 
01220     // Assert ALE, TBD by cpld code  
01221     CPLD_ALE = 0;
01222 
01223     // send address to NAND chip  
01224     CPLD_RDWR = addr_0_7;
01225     CPLD_RDWR = addr_9_16;
01226     CPLD_RDWR = addr_17_24;
01227     CPLD_RDWR = addr_25_27;
01228 
01229     // Deassert ALE, TBD by cpld code  
01230     temp = CPLD_ALE;
01231 
01232     // send data    
01233     // Send and encode first 256 bytes  
01234     WriteAndEncode256bytes(pBuf,swap,
01235                             (UCHAR SDFAR *) &redundant[NAND_ECC1_1_OFFSET],
01236                             (UCHAR SDFAR *) &redundant[NAND_ECC1_2_OFFSET],
01237                             (UCHAR SDFAR *) &redundant[NAND_ECC1_3_OFFSET] );
01238 
01239     // Send and encode second 256 bytes  
01240     WriteAndEncode256bytes(pBuf+128,swap,
01241                             (UCHAR SDFAR *) &redundant[NAND_ECC2_1_OFFSET],
01242                             (UCHAR SDFAR *) &redundant[NAND_ECC2_2_OFFSET],
01243                             (UCHAR SDFAR *) &redundant[NAND_ECC2_3_OFFSET] );
01244     
01245 
01246     eccEncodeRedundant((UCHAR SDFAR *)redundant,
01247                             (UCHAR SDFAR *)&redundant[NAND_ECC3_1_OFFSET],
01248                             (UCHAR SDFAR *)&redundant[NAND_ECC3_2_OFFSET]);
01249 
01250     // Sending out redundant data.     
01251     pData = (unsigned short *)&redundant[0];
01252     ii = 16;    
01253     while(ii--) CPLD_RDWR = *pData++;
01254     
01255 
01256     // Assert CLE: write to the port will set CLE to HIGH  
01257     CPLD_CLE = 0;
01258     
01259     // send 'Auto Program (True)' command  
01260     CPLD_RDWR = NAND_CMD__AUTO_PROGRAM_TRUE;
01261 
01262 
01263     // Wait for Ready/#Busy signal (input on D0) goes to HIGH.  
01264     NAND_WAIT4READY(temp);
01265 
01266     
01267     // Restore write protection  
01268     //temp = CPLD_nWP;  
01269 #ifdef NAND_PWR_SUPPORT
01270     // Check to see if there was any error.   
01271     return NAND__readDataSec(phySec, pBuf, swap);
01272 #else
01273     // send 'Status Read (1)' command  
01274     CPLD_RDWR = NAND_CMD__STATUS_READ1;
01275 
01276     // Deassert CLE: read from the port will reset CLE to LOW  
01277     temp = CPLD_CLE;
01278 
01279     // Restore write protection  
01280     //addr_0_7 = CPLD_nWP;
01281 
01282     // Read status data  
01283     temp = CPLD_RDWR;
01284 
01285     // Deassert CE, read from the port will disable CE0  
01286     addr_0_7 = CPLD_CE0;
01287 
01288     NAND_ClearReadWriteBusy();
01289     
01290     if ( (temp & 0x0001 ) == 0 ) 
01291     {
01292         // programming pass  
01293         return (TRUE);
01294     }   
01295     else 
01296     {
01297         // programming fail  
01298         return (FALSE);
01299     }
01300 #endif
01301 }

Here is the call graph for this function:

BOOL NAND__wrSec unsigned long  sec,
unsigned short *  pBuf,
BOOL  swap
 

Function writes to the logical sector, which is specified by the FAT file system layer, NAND flash will always appear to be contiguous to the FAT file system on a sector level.

Parameters:
sec logical NAND sector.
pBuf sector data buffer pointer.
swap byte swap cotrol.
Returns:
TRUE if successfully written, otherwise FALSE.

Definition at line 3025 of file nand.c.

References st_NAND::actvBlkEndSec, st_NAND::actvPhyBlk, st_NAND::actvPhySec, st_NAND::actvSec, st_NAND::actvSecOffset, st_NAND::flag, NAND__flush(), NAND__historyCheck(), NAND__historySet(), NAND__log2phySec(), NAND__swapSec(), NAND__writeDataSec(), and st_NAND::writingSec.

Referenced by NAND_writeSec().

03026 {
03027     unsigned long   phySec;
03028     BOOL            bBLANK = FALSE;
03029     BOOL            ret = FALSE;
03030 
03031     if(Nand.flag & NAND_READ_ONLY ) return FALSE;
03032     
03033     // Remember the writing sector. 
03034     Nand.writingSec = sec;
03035 
03036     if( TRUE == NAND__historyCheck() )
03037     {
03038         // First to check if there is any data block is pending to be flushed, 
03039         // which means block might have been remapped and only been partially 
03040         // written.
03041         if(Nand.flag & NAND_FLUSH_DATA_BLOCK_PENDING) 
03042         {
03043             // Check if we really need to flush.
03044             if( ( (unsigned long)sec != (unsigned long)(Nand.actvSec + 1) ) ||
03045                  ( (unsigned long)sec == Nand.actvBlkEndSec) )
03046             {
03047                 // Flush only if sectors are not contiguous or sector 
03048                 // is cross block boundary. If unable to flush, 
03049                 // report error. 
03050                 if( ((unsigned long)sec > (unsigned long)(Nand.actvSec + 1)) && 
03051                     ((unsigned long)sec < (unsigned long)Nand.actvBlkEndSec) )
03052                 {
03053                         
03054                     // Partial flush needed.
03055                     if(NAND__flush(TRUE) == FALSE)
03056                     {
03057                         return FALSE;
03058                     }
03059                     
03060                     // If it is partial flush, block shall not be swapped.
03061                     Nand.actvSec = sec;
03062                         
03063                     Nand.actvSecOffset = (unsigned long)sec & 0x003F;
03064                         
03065                     phySec = 
03066                     Nand.actvPhySec = ((unsigned long)Nand.actvPhyBlk << 6) + Nand.actvSecOffset;   
03067                         
03068                     bBLANK = TRUE;              
03069                 }
03070                 
03071                 // Full flush is needed.
03072                 else if(NAND__flush(FALSE) == FALSE)
03073                 {
03074                     return FALSE;
03075                 }
03076             }
03077             
03078             else
03079             {
03080                 // Sector is contiguous, increase active sector offset. 
03081                 Nand.actvSecOffset++;
03082                 Nand.actvSec++;                         
03083                 Nand.actvPhySec++;              
03084                 phySec = Nand.actvPhySec;
03085     
03086                 // Sector has to be blank.
03087                 bBLANK = TRUE;
03088             }
03089         }
03090     
03091         if(bBLANK == FALSE )
03092         {
03093             // Map to physical sector.
03094             phySec = NAND__log2phySec(sec);
03095     
03096             // As long as it is NOT contiguous writing, we'll swap the block
03097             // no matter the target sector is blank or not.
03098             if( NAND__swapSec(&phySec, sec) == FALSE )
03099             {                   
03100                 // Can not find replacement block or source is 
03101                 // unreadable, report error. If it was due source block 
03102                 // read error, that block gets replaced anyway if we can.
03103                 // Note that if a static block buffer is available in RAM, 
03104                 // this might not be the case.
03105                 return FALSE;
03106             }
03107         }
03108         
03109         // By now, a blank physical sector has been successfully mapped 
03110         // to the specified logical sector.
03111         NAND__historySet(pBuf, swap);
03112     
03113         // Write data sector function has delayed status check, always 
03114         // return TRUE here.
03115         NAND__writeDataSec(phySec, pBuf, swap);
03116     
03117         ret = TRUE;
03118     }
03119     
03120     return ret;
03121 }

Here is the call graph for this function:

BOOL NAND__wrSysInfo void   ) 
 

Function checks to write the system info area.

Returns:
TRUE if successfully written, otherwise FALSE.

Definition at line 1830 of file nand.c.

References st_NAND::currentpipo, st_NAND::flag, NAND__buildSysInfo(), NAND__eraseBlock(), NAND__flushBlock(), st_NAND::rpTabBackPhyBlk, and st_NAND::rpTabPhyBlk.

Referenced by NAND_flush(), and NAND_unmount().

01831 {
01832     unsigned short  temp;
01833     unsigned short* pphyblk;
01834 
01835     if((Nand.flag&NAND_FLUSH_MAP_TABLE_PENDING)|(Nand.flag&NAND_FLUSH_REPLACE_TAB_PENDING))
01836     {
01837         // Uable to flush map table, replacement blocks have been used up.
01838         if(Nand.currentpipo[0])
01839         {
01840             pphyblk = &Nand.rpTabBackPhyBlk[0];
01841             //ret = NAND__flushBlock(&Nand.rpTabBackPhyBlk[Nand.actvChip]);
01842             temp = Nand.rpTabPhyBlk[0];
01843         }
01844         else
01845         {
01846             pphyblk = &Nand.rpTabPhyBlk[0];
01847             //ret = NAND__flushBlock(&Nand.rpTabPhyBlk[Nand.actvChip]);
01848             temp = Nand.rpTabBackPhyBlk[0];
01849         }
01850         
01851         if(NAND__flushBlock(pphyblk))
01852         {   
01853             NAND__eraseBlock(temp);     
01854             Nand.currentpipo[0] = !Nand.currentpipo[0];
01855         
01856             Nand.flag &= ~(NAND_FLUSH_MAP_TABLE_PENDING|NAND_FLUSH_REPLACE_TAB_PENDING|NAND_FLUSH_PENDING);
01857         }
01858         else
01859             return FALSE;
01860         
01861     }
01862                 
01863     if(Nand.flag & NAND_SYSINFO_CHANGE)
01864     {
01865         // Flush the system info. If unable to flush, volume 
01866         // sector 0 is corrupted, thus volume needs a low 
01867         // level format to revive. To make system more robust, 
01868         // we could reserve more than one block for the 
01869         // system area, and report error only when all of them
01870         // are defected.
01871         if(!NAND__buildSysInfo(&Nand))  return FALSE;
01872             
01873         Nand.flag &= ~(NAND_FLUSH_SYSINFO_PENDING|NAND_SYSINFO_CHANGE);
01874     }
01875         
01876     return TRUE;
01877 }

Here is the call graph for this function:

BOOL NAND_flush void   ) 
 

Function flushes the NAND flash and makes all change final.

Returns:
TRUE if successfully flushed, otherwise FALSE.

Definition at line 2013 of file nand.c.

References st_NAND::flag, NAND__eraseBlock(), NAND__flush(), NAND__historyCheck(), NAND__wrSysInfo(), and st_NAND::pRpTab.

Referenced by FAT_flushDisk(), and NAND_unmount().

02014 {
02015     BOOL            ret = TRUE;
02016     unsigned short  phyblk;
02017     unsigned short  ii;
02018     int             pri;
02019     
02020     NAND_lock(&pri, 1); 
02021     
02022     if( NAND__historyCheck() == TRUE )
02023     {
02024     
02025         if(Nand.flag & NAND_FLUSH_DATA_BLOCK_PENDING)
02026         {
02027             // Flush the entire block. 
02028             if( NAND__flush(FALSE) == FALSE) ret = FALSE;
02029         }
02030     
02031         if( TRUE == ret )
02032         {
02033             if(Nand.flag & NAND_FLUSH_SYSINFO_PENDING)  Nand.flag |= NAND_SYSINFO_CHANGE;
02034             
02035             //erase all the occupied block
02036             for(ii=0;ii<NAND_PRESERVE_NUM;ii++)
02037             {
02038                 GEN_rdSRAM(Nand.pRpTab + 1 + ii, &phyblk , 1);      
02039                 //donot consider the block is bad
02040                 NAND__eraseBlock(phyblk);       
02041             }
02042             
02043             Nand.flag &= ~NAND_ERASE_NEED;      
02044         
02045             ret = NAND__wrSysInfo();
02046         }
02047     }   
02048     
02049     NAND_unlock(pri, 1);
02050     return ret;
02051 }

Here is the call graph for this function:

unsigned long NAND_format void   ) 
 

Function will format the nand flash.

This function is built to support multiple NAND chips.

Returns:
number of data sectors.

Definition at line 2061 of file nand.c.

References NAND__formatChip(), and st_NAND::pagePerBlk.

Referenced by FAT__format(), and NAND__test().

02062 {
02063     unsigned short  num = 0;
02064     unsigned short  ii;
02065     unsigned short  startPhyBlock[NAND_CHIP_NUM];
02066 
02067     // Physical block addresses of multiple chips might not
02068     // be contiguous.
02069     NAND__hwBlockMap(startPhyBlock);
02070 
02071     for( ii = 0; ii < NAND_CHIP_NUM; ii++ ) 
02072     {
02073             // Format chips. 
02074             num += NAND__formatChip(startPhyBlock[ii]);
02075     }
02076 
02077     // return total available data sectors.
02078     return( (unsigned long) num * Nand.pagePerBlk );
02079 }

Here is the call graph for this function:

unsigned long NAND_mount void   ) 
 

Function initializes NAND flash interface.

Returns:
The max address can be accessed to.

Definition at line 2392 of file nand.c.

References st_NAND::actvBlkEndSec, st_NAND::actvChip, st_NAND::actvSec, st_NAND::currentpipo, st_NAND::curRpBlkNum, st_NAND::dataBlkNum, st_NAND::flag, GEN_free(), GEN_malloc(), st_NAND::mapTabPhySecOffset, st_NAND::maxRpBlkNum, NAND__eraseBlock(), NAND__isBlockValid(), NAND__loadTab(), NAND__mount(), NAND__writeRdnt(), st_NAND::nativeMaxAddr, st_NAND::pagePerBlk, st_NAND::pMapTab, st_NAND::pRpTab, st_NAND::rpTabBackPhyBlk, st_NAND::rpTabPhyBlk, and SYS_die().

Referenced by FAT__format(), and NAND__test().

02393 {
02394     unsigned int    i;
02395     unsigned int    count;
02396     unsigned long   phySec;
02397     unsigned short  ii;
02398     unsigned short  temp;
02399     unsigned long   pRpTab;
02400     unsigned short  dataBlkNum;
02401     unsigned short  rpBlkNum;
02402     unsigned short *pD1;
02403     unsigned short *pD2;
02404 
02405     // See comment in NAND_wrRpHis.c.
02406     internpresvnum = 0;
02407 
02408     Nand.flag = 0;
02409     dataBlkNum = 0;
02410     rpBlkNum = 0;
02411 
02412     // Initialize the hardware interface. 
02413     pD1 = &Nand.dataBlkNum[0];
02414     pD2 = &Nand.maxRpBlkNum[0];
02415     for(ii = 0; ii < NAND_CHIP_NUM; ii++) 
02416     {
02417         if( NAND__mount(ii)==FALSE) return 0L;
02418 
02419         if (*pD1 > dataBlkNum ) 
02420             dataBlkNum = *pD1;
02421 
02422             // Search the max number of replacement blocks.
02423         if (*pD2 > rpBlkNum ) 
02424             rpBlkNum = *pD2;
02425         
02426         pD1++; pD2++;
02427     }   
02428     
02429 
02430     // Allocate data block map table, buffer map table upto
02431     // one block.
02432     if ( (Nand.pMapTab = GEN_malloc(dataBlkNum) ) == 0L )
02433     {
02434         // Out of memory, fatal error.
02435         SYS_die(NAND_MOUNT);
02436     }
02437 
02438     
02439     // Allocate replace block table, assuming replacement block
02440     // map table is always less than one block. 
02441     if( (Nand.pRpTab = GEN_malloc(rpBlkNum) ) == 0L)
02442     {
02443         GEN_free(Nand.pMapTab);
02444         // Out of memory, fatal error.
02445         SYS_die(NAND_MOUNT2);
02446     }
02447 
02448     // Load the replacement block table of the first chip. 
02449      if(Nand.currentpipo[0])
02450         temp = Nand.rpTabPhyBlk[0];
02451      else
02452         temp = Nand.rpTabBackPhyBlk[0];
02453      
02454 #ifdef HARD_CODED_OPTIMIZATION  
02455         phySec = (unsigned long)temp<<6;
02456 #else
02457         phySec = (unsigned long)temp*Nand.pagePerBlk;
02458 #endif  
02459         
02460     if( (Nand.curRpBlkNum = NAND__loadTab(phySec,Nand.pRpTab, rpBlkNum) ) == 0 ) 
02461     {
02462         // No replacement blocks, flash is read-only.
02463         Nand.flag |= NAND_READ_ONLY;
02464         
02465         // Current no GUI support for a read-only NAND. we'll simply return 
02466         // failure here.
02467         GEN_free(Nand.pMapTab);         
02468         GEN_free(Nand.pRpTab);
02469         return 0L;      
02470     }
02471     
02472     // Read the first map table block if map table covers multiple blocks,
02473     // otherwise read back the entire map table. 
02474     if( NAND__loadTab(phySec + Nand.mapTabPhySecOffset[0], Nand.pMapTab, dataBlkNum) == 0 )
02475     {
02476         GEN_free(Nand.pMapTab);         
02477         GEN_free(Nand.pRpTab);
02478         return 0L;
02479     }
02480 
02481     if(Nand.flag & NAND_ERASEALL_NEED)
02482     {
02483         if ((pRpTab = GEN_malloc(Nand.curRpBlkNum)) == 0L )
02484         {
02485             // Out of memory, fatal error.
02486             SYS_die(NAND_MOUNT3);
02487         }
02488         
02489         count=0;
02490         
02491         for(i=0;i<Nand.curRpBlkNum;i++)
02492         {
02493             GEN_rdSRAM(Nand.pRpTab + i, &temp, 1);
02494             
02495             if(temp >= NAND_BLOCK_CNT)
02496             {
02497                 GEN_free(Nand.pMapTab);         
02498                 GEN_free(Nand.pRpTab);
02499                 GEN_free(pRpTab);
02500                 return 0L;
02501             }
02502             
02503             if(NAND__isBlockValid(temp))
02504             {
02505                 if( NAND__eraseBlock(temp))
02506                 {   
02507                     GEN_wrSRAM(pRpTab+count, &temp, 1);
02508                     count++;
02509                 }
02510                 
02511                 else
02512                 {
02513                 #ifdef HARD_CODED_OPTIMIZATION  
02514                     phySec = ((unsigned long)temp << 6) + 63;
02515                 #else
02516                     phySec = ((unsigned long)Nand.pagePerBlk * temp) + Nand.pagePerBlk - 1;
02517                 #endif
02518                 
02519                     ii = NAND_BLOCK_STATUS_BAD;
02520                 
02521                     NAND__writeRdnt(phySec, &ii, NAND_BLOCK_STATUS_BYTE, 1);
02522                 }
02523             }
02524         }       
02525         
02526         GEN_free(Nand.pRpTab);      
02527         Nand.pRpTab = pRpTab;       
02528         Nand.curRpBlkNum = count;
02529                 
02530         Nand.flag &= ~NAND_ERASEALL_NEED;   
02531     }
02532     
02533     else if(Nand.flag & NAND_ERASE_NEED)
02534     {
02535         for(ii=0;ii<NAND_PRESERVE_NUM;ii++)
02536         {
02537             GEN_rdSRAM(Nand.pRpTab + 1 + ii, &temp , 1);
02538         
02539             if(temp >= NAND_BLOCK_CNT)
02540             {
02541                 GEN_free(Nand.pMapTab);         
02542                 GEN_free(Nand.pRpTab);
02543                 return 0L;
02544             }
02545             // do not consider the block as bad
02546             NAND__eraseBlock(temp);
02547         }
02548         
02549         Nand.flag &= ~NAND_ERASE_NEED;
02550     }
02551 
02552     // Initialize global controls. 
02553     Nand.actvBlkEndSec = (unsigned long)NAND_INVALID_SEC;
02554     Nand.actvSec = (unsigned long)NAND_INVALID_SEC;
02555 
02556     Nand.actvChip = 0;
02557 
02558     // Calculate valid flash size. 
02559     dataBlkNum = 0;
02560     pD1 = &Nand.dataBlkNum[0];
02561     for(ii = 0; ii < NAND_CHIP_NUM; ii++) 
02562     {
02563         dataBlkNum += *pD1;
02564         pD1++;
02565     }
02566 
02567 
02568 #ifdef HARD_CODED_OPTIMIZATION  
02569     Nand.nativeMaxAddr = ( (unsigned long)dataBlkNum << 6 ) - 1;
02570 #else
02571     Nand.nativeMaxAddr = ( (unsigned long)dataBlkNum * Nand.pagePerBlk ) - 1;
02572 #endif
02573 
02574     return Nand.nativeMaxAddr;
02575 }

Here is the call graph for this function:

BOOL NAND_readSec unsigned long  sec,
unsigned short *  pBuf,
BOOL  swap
 

Function reads back the specified logical sector with disk I/O lock wrapper.

Parameters:
sec logical NAND sector.
pBuf sector data buffer pointer.
swap byte swap cotrol.
Returns:
TRUE if successfully read, otherwise FALSE.

Definition at line 2779 of file nand.c.

References NAND__rdSec().

Referenced by ENCODER_cache(), NAND__test(), SYS_getParams(), and SYS_setParams().

02780 {
02781     BOOL ret;
02782     int  pri;
02783     
02784     NAND_lock(&pri, 1);     
02785     ret = NAND__rdSec(sec, pBuf, swap);
02786     NAND_unlock(pri, 1);
02787     
02788     return ret;
02789 }

Here is the call graph for this function:

void NAND_revive unsigned short  blkNum  ) 
 

Function erases entire NAND chip, all information will be lost.

Parameters:
blkNum Total chip block number.

Definition at line 2866 of file nand.c.

References NAND__eraseBlock().

Referenced by NAND__formatChip().

02867 {   
02868     int kk;
02869     
02870     // remove write protection
02871     CPLD_nWP = 0;
02872     for(kk = 0; kk < blkNum; kk++)
02873     {
02874         NAND__eraseBlock(kk);
02875     }
02876     // Apply write protection.
02877     kk = CPLD_nWP;
02878 }

Here is the call graph for this function:

BOOL NAND_unmount void   ) 
 

Function unmounts NAND flash and releases memory allocated to flash driver.

Returns:
TRUE if successfully unmounted, otherwise FALSE.

Definition at line 2938 of file nand.c.

References st_NAND::flag, GEN_free(), NAND__eraseBlock(), NAND__flush(), NAND__historyCheck(), NAND__wrSysInfo(), NAND_flush(), st_NAND::pMapTab, and st_NAND::pRpTab.

Referenced by FAT__unmountDisk(), and NAND__test().

02939 {
02940     BOOL            ret = TRUE;
02941     unsigned short  ii;
02942 #if 0
02943     unsigned short  phyblk;
02944     
02945     if( NAND__historyCheck() == FALSE)
02946     {
02947         // restore write protection 
02948         ii = CPLD_nWP;  
02949         return FALSE;
02950     }
02951     
02952     
02953     if(Nand.flag & NAND_FLUSH_DATA_BLOCK_PENDING)
02954     {
02955         // Flush the entire block. 
02956         ret = NAND__flush(FALSE);
02957     }
02958 
02959     if(Nand.flag & NAND_FLUSH_SYSINFO_PENDING)  Nand.flag |= NAND_SYSINFO_CHANGE;
02960     
02961     //erase all the occupied block
02962     for(ii=0;ii<NAND_PRESERVE_NUM;ii++)
02963     {
02964         GEN_rdSRAM(Nand.pRpTab + 1 + ii, &phyblk , 1);      
02965         //donot consider the block is bad
02966         NAND__eraseBlock(phyblk);       
02967     }
02968     
02969     Nand.flag &= ~NAND_ERASE_NEED;      
02970     NAND__wrSysInfo();
02971 #else
02972     ret = NAND_flush();
02973 #endif  
02974     // Release data objects. 
02975     GEN_free(Nand.pMapTab);
02976     GEN_free(Nand.pRpTab);
02977 
02978     // restore write protection
02979     ii = CPLD_nWP;
02980     return ret;
02981 }

Here is the call graph for this function:

BOOL NAND_writeSec unsigned long  sec,
unsigned short *  pBuf,
BOOL  swap
 

Function writes to the logical sector with I/O lock wrapper.

Parameters:
sec logical NAND sector.
pBuf sector data buffer pointer.
swap byte swap cotrol.
Returns:
TRUE if successfully written, otherwise FALSE.

Definition at line 2997 of file nand.c.

References NAND__wrSec().

Referenced by DECODER_cache(), ENCODER_putData(), NAND__test(), and SYS_setParams().

02998 {
02999     BOOL ret;
03000     int  pri;
03001     
03002     NAND_lock(&pri, 1);
03003     ret = NAND__wrSec(sec, pBuf, swap);
03004     NAND_unlock(pri, 1);
03005     
03006     return ret;
03007 }

Here is the call graph for this function:


Generated on Wed Jan 19 01:13:14 2005 for neuros-firmware by  doxygen 1.3.9.1