Chinaunix首页 | 论坛 | 博客
  • 博客访问: 394598
  • 博文数量: 82
  • 博客积分: 2085
  • 博客等级: 大尉
  • 技术积分: 808
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-10 10:28
文章分类

全部博文(82)

文章存档

2014年(1)

2013年(4)

2012年(2)

2011年(3)

2010年(10)

2009年(36)

2008年(26)

我的朋友

分类:

2010-10-07 02:05:05

/*
 Change from n2048.c 2004-08-28, by wangtao
 */
/************************************************************************/
/*                                                                      */
/*  FAT-FTL Lite Software Development Kit   */
/*  Copyright (C) M-Systems Ltd. 1995-1997   */
/*         */
/************************************************************************/
#include "tffs/flflash.h"
#include "tffs/reedsol.h"
#include "vxWorks.h"
#include "stdio.h"
#include "cacheLib.h"
#include "tyLib.h" 
#include "sysLib.h"
#include "logLib.h"
#include "stdlib.h"
#include "string.h"
#include "intLib.h"
#include "taskLib.h"
#include "iv.h"
/*******************************************************************************
* 调试环境:
* K9F2808U0C_Y,IBM-PPC405EP,Tornado2.2
*
* 硬件说明:
* CLE和ALE分别由A3和A2控制,CE连接到RCS2,Ready/Busy需要外接上拉电阻;
* Read操作时,K9F2808U0C_Y,P型号在Busy状态时必须保持CS低电平状态;
* /WP写保护信号应该连接到复位信号,保证在上电或掉电时为低电平的写保护状态;
* FLASH芯片是8bit接口,而硬件是16bit接口,因此涉及到char和short的强制转换;
*
* 软件:
* 为了解决16bit操作的Endian问题,采用sysPciOutWord和sysPciInWord函数作为端口访问函数;
* 如果RCS2的配置是8bit模式,就不需要考虑Endian问题,否则需要做char和short的强制转换;
*******************************************************************************/
#define FADDR_BASE  0xfd800000
#define FADDR_CLE (FADDR_BASE + 0x8)
#define FADDR_ALE (FADDR_BASE + 0x4)
#define PAGES_PER_BLOCK     32          /* 32 pages per block on a single chip*/
#define NFLASH_K9F_SECTORSIZE   0x200
#define NFLASH_K9F_TAILSIZE   16
#define NFLASH_K9F_SECTORHALFSIZE  0x100
#define NFLASH_K9F2808U0X    0xEC73  
#define NFL_K9F2808_CHIPSIZE (15 * 1024 * 1024)  /* Total 16MB on K9F2808 chip. */
#define NFL_K9F2808_PAGENUM (NFL_K9F2808_CHIPSIZE / 512)
#define NFL_K9F2808_BLOCKNUM (NFL_K9F2808_PAGENUM / PAGES_PER_BLOCK)
#define NFLASH_K9F5608U0X    0xEC75
#define NFL_K9F5608_CHIPSIZE (32 * 1024 * 1024)  /* Total 32MB on K9F5608 chip. */
#define NFL_K9F5608_PAGENUM (NFL_K9F5608_CHIPSIZE / 512)
#define NFL_K9F5608_BLOCKNUM (NFL_K9F2808_PAGENUM / PAGES_PER_BLOCK)
#define OUT_WORD(addr, data) sysPciOutWord(addr, data)
#define IN_WORD(addr)   sysPciInWord(addr)
#define FLASH_DEBUG
    #ifdef FLASH_DEBUG
 int glFlashDebugLevel=0;
 #define DEBUG_FL(fmt,args...)  if(glFlashDebugLevel>0) printf(fmt,##args);
    #else
 #define DEBUG_FL(fmt,args...)
    #endif
LOCAL char flDataBuffer[10000]; /* define a map buffer. */
#define VERIFY_AFTER_WRITE
#ifdef VERIFY_AFTER_WRITE
LOCAL unsigned char flReadback[NFLASH_K9F_SECTORSIZE];
LOCAL unsigned char flExtraReadBack[NFLASH_K9F_TAILSIZE];
#endif
/* The following is the ecc function. */
typedef enum {
 ECC_NO_ERROR    = 0,  /* no error */
 ECC_CORRECTABLE_ERROR = 1,  /* one bit data error */
 ECC_ECC_ERROR    = 2,  /* one bit ECC error */
 ECC_UNCORRECTABLE_ERROR = 3  /* uncorrectable error */
} eccdiff_t;
/****************************************************************************
* NAME  make_ecc_512
* DESCRIPTION
*  This function generates 3 byte ECC for 512 byte data.
*      (Software ECC)
* PARAMETERS                                       
*  ecc_buf   the location where ECC should be stored
*  data_buf  given data
* RETURN VALUES    none
*
****/
void make_ecc_512(unsigned char * ecc_buf, unsigned char * data_buf)
{
 
 unsigned long i, ALIGN_FACTOR;
 unsigned long tmp;
 unsigned long uiparity = 0;
 unsigned long parityCol, ecc = 0;
 unsigned long parityCol4321 = 0, parityCol4343 = 0, parityCol4242 = 0, parityColTot = 0;
 unsigned long *Data;
 unsigned long Xorbit=0;
 ALIGN_FACTOR = (unsigned long)data_buf % 4 ;
 Data = (unsigned long *)(data_buf + ALIGN_FACTOR);
 for( i = 0; i < 16; i++)
 {
  parityCol = *Data++;
  tmp = *Data++; parityCol ^= tmp; parityCol4242 ^= tmp;
  tmp = *Data++; parityCol ^= tmp; parityCol4343 ^= tmp;
  tmp = *Data++; parityCol ^= tmp; parityCol4343 ^= tmp; parityCol4242 ^= tmp;
  tmp = *Data++; parityCol ^= tmp; parityCol4321 ^= tmp;
  tmp = *Data++; parityCol ^= tmp; parityCol4242 ^= tmp; parityCol4321 ^= tmp;
  tmp = *Data++; parityCol ^= tmp; parityCol4343 ^= tmp; parityCol4321 ^= tmp;
  tmp = *Data++; parityCol ^= tmp; parityCol4242 ^= tmp; parityCol4343 ^= tmp; parityCol4321 ^= tmp;
  parityColTot ^= parityCol;
  tmp = (parityCol >> 16) ^ parityCol;
  tmp = (tmp >> 8) ^ tmp;
  tmp = (tmp >> 4) ^ tmp;
  tmp = ((tmp >> 2) ^ tmp) & 0x03;
  if ((tmp == 0x01) || (tmp == 0x02))
  {
   uiparity ^= i;
   Xorbit ^= 0x01;
  }
 }
 tmp = (parityCol4321 >> 16) ^ parityCol4321;
 tmp = (tmp << 8) ^ tmp;
 tmp = (tmp >> 4) ^ tmp;
 tmp = (tmp >> 2) ^ tmp;
 ecc |= ((tmp << 1) ^ tmp) & 0x200; // p128
 tmp = (parityCol4343 >> 16) ^ parityCol4343;
 tmp = (tmp >> 8) ^ tmp;
 tmp = (tmp << 4) ^ tmp;
 tmp = (tmp << 2) ^ tmp;
 ecc |= ((tmp << 1) ^ tmp) & 0x80; // p64
 tmp = (parityCol4242 >> 16) ^ parityCol4242;
 tmp = (tmp >> 8) ^ tmp;
 tmp = (tmp << 4) ^ tmp;
 tmp = (tmp >> 2) ^ tmp;
 ecc |= ((tmp << 1) ^ tmp) & 0x20; // p32

 tmp = parityColTot & 0xFFFF0000;
 tmp = tmp >> 16;
 tmp = (tmp >> 8) ^ tmp;
 tmp = (tmp >> 4) ^ tmp;
 tmp = (tmp << 2) ^ tmp;
 ecc |= ((tmp << 1) ^ tmp) & 0x08; // p16
 tmp = parityColTot & 0xFF00FF00;
 tmp = (tmp >> 16) ^ tmp;
 tmp = (tmp >> 8);
 tmp = (tmp >> 4) ^ tmp;
 tmp = (tmp >> 2) ^ tmp;
 ecc |= ((tmp << 1) ^ tmp) & 0x02; // p8
 tmp = parityColTot & 0xF0F0F0F0 ;
 tmp = (tmp << 16) ^ tmp;
 tmp = (tmp >> 8) ^ tmp;
 tmp = (tmp << 2) ^ tmp;
 ecc |= ((tmp << 1) ^ tmp) & 0x800000; // p4
 tmp = parityColTot & 0xCCCCCCCC ;
 tmp = (tmp << 16) ^ tmp;
 tmp = (tmp >> 8) ^ tmp;
 tmp = (tmp << 4) ^ tmp;
 tmp = (tmp >> 2);
 ecc |= ((tmp << 1) ^ tmp) & 0x200000; // p2
 tmp = parityColTot & 0xAAAAAAAA ;
 tmp = (tmp << 16) ^ tmp;
 tmp = (tmp >> 8) ^ tmp;
 tmp = (tmp >> 4) ^ tmp;
 tmp = (tmp << 2) ^ tmp;
 ecc |= (tmp & 0x80000); // p1
 ecc |= (uiparity & 0x01) <<11; 
 ecc |= (uiparity & 0x02) <<12; 
 ecc |= (uiparity & 0x04) <<13;
 ecc |= (uiparity & 0x08) <<14;
 if (Xorbit)
 {
  ecc |= (ecc ^ 0x00AAAAAA)>>1;
 }
 else
 {
  ecc |= (ecc >> 1);
 }
 ecc = ~ecc;
 *(ecc_buf + 2) = (unsigned char) (ecc >> 16);
 *(ecc_buf + 1) = (unsigned char) (ecc >> 8);
 *(ecc_buf + 0) = (unsigned char) (ecc);
}
/****************************************************************************
* NAME  compare_ecc_512 
* DESCRIPTION
*  This function compares two ECCs and indicates if there is an error.
* PARAMETERS    
*  ecc_data1  one ECC to be compared
*  ecc_data2  the other ECC to be compared
*  page_data  content of data page 
*  offset   where the error occurred
*  corrected  correct data
* RETURN VALUES
*  Upon successful completion, compare_ecc returns SSR_SUCCESS.
*      Otherwise, corresponding error code is returned.
****/
eccdiff_t compare_ecc_512(unsigned char *iEccdata1, unsigned char *iEccdata2,
          unsigned char *pPagedata, long pOffset, unsigned char pCorrected)
{
 unsigned long  iCompecc = 0, iEccsum = 0;
 unsigned long  iFindbyte   = 0;
 unsigned long  iIndex;
 unsigned long  nT1 = 0, nT2 =0;
 unsigned char   iNewvalue;
 unsigned char   iFindbit    = 0;
 unsigned char   *pEcc1 = (unsigned char *)iEccdata1;
 unsigned char   *pEcc2 = (unsigned char *)iEccdata2;
 for ( iIndex = 0; iIndex <2; iIndex++)
 {
  nT1 ^= (((*pEcc1) >> iIndex) & 0x01);
  nT2 ^= (((*pEcc2) >> iIndex) & 0x01);
 }
 for (iIndex = 0; iIndex < 3; iIndex++)
  iCompecc |= ((~(*pEcc1++) ^ ~(*pEcc2++)) << iIndex * 8);
   
 for(iIndex = 0; iIndex < 24; iIndex++)
  iEccsum += ((iCompecc >> iIndex) & 0x01);
 switch (iEccsum)
 {
  case 0 :
   printf("RESULT : no error\n");
   return ECC_NO_ERROR;
  case 1 :
   printf("RESULT : ECC code 1 bit fail\n");
   return ECC_ECC_ERROR;
  case 12 :
   if (nT1 != nT2)
   {
    iFindbyte = ((iCompecc >> 17 & 1) << 8) + ((iCompecc >> 15 & 1) << 7) + ((iCompecc >> 13 & 1) << 6)
     + ((iCompecc >> 11 & 1) << 5) + ((iCompecc >> 9 & 1) << 4) + ((iCompecc >> 7 & 1) << 3)
     + ((iCompecc >> 5 & 1) << 2) + ((iCompecc >> 3 & 1) << 1) + (iCompecc >> 1 & 1);
    iFindbit =  (unsigned char)(((iCompecc >> 23 & 1) << 2) + ((iCompecc >> 21 & 1) << 1) + (iCompecc >> 19 & 1));
    iNewvalue = (unsigned char)(pPagedata[iFindbyte] ^ (1 << iFindbit));
    printf("iCompecc = %d\n",iCompecc);
    printf("RESULT : one bit error\r\n");
    printf("byte = %d, bit = %d\r\n", iFindbyte, iFindbit);
    printf("corrupted = %x, corrected = %x\r\n", pPagedata[iFindbyte], iNewvalue);
    if (pOffset != NULL)  pOffset = iFindbyte;
    if (pCorrected != NULL)  pCorrected = iNewvalue;
           
    return ECC_CORRECTABLE_ERROR;
   }
   else
    return ECC_UNCORRECTABLE_ERROR;
  default :
   printf("RESULT : unrecoverable error\n");
   return ECC_UNCORRECTABLE_ERROR;
 }  
}

/*****************************************************************************
* readOnePage, call by MTD read routine.
*
* Parameters:
* vol  : Pointer identifying drive
*  address : Address to read from. 
* buffer : buffer to Write from. 
* length : number of bytes to read (up to sector size).
* modes : EDC flag etc. 
*/
LOCAL FLStatus readOnePage (FLFlash* pVol,
  CardAddress address, char FAR1 *buffer, int length, int modes)
{
 short command, addressLSB;
 int i;
 /* Set Read Pointer first. */
 if (modes & EXTRA)   
 {         /* Read spare area. */
  command = 0x50;  
  addressLSB = address & 0x0F;  /* Only have 16 bytes. */
 }
 else if(address & NFLASH_K9F_SECTORHALFSIZE)
 {         /* 256-512 area. */
  command = 0x01;  
  addressLSB = address & 0xFF;  
 }
 else
 {         /* 0-256 area. */
  command = 0x00;  
  addressLSB = address & 0xFF; 
 } 
 OUT_WORD(FADDR_CLE, command); 
 OUT_WORD(FADDR_ALE, addressLSB);
 OUT_WORD(FADDR_ALE, (unsigned short)(address >> 9));
 OUT_WORD(FADDR_ALE, (unsigned short)(address >> 17)); 
 sysUsDelay(20);
 
 for(i=0; i  *buffer++ = (unsigned char)IN_WORD(FADDR_BASE);
 return flOK;
}

/*****************************************************************************
* writeOnePage, call by MTD Write routine.
*
* Parameters:
* vol  : Pointer identifying drive
*  address : Address to read from. 
* buffer : buffer to Write from. 
* length : number of bytes to read (up to sector size).
* modes : EDC flag etc. 
*
*/
LOCAL FLStatus writeOnePage(FLFlash* pVol,
  CardAddress address, const char FAR1 *buffer, int length, int modes)
{
 short command, addressLSB;
 int i;
 if (flWriteProtected(pVol->socket))
  return flWriteProtect;
 /* Set Write Pointer first. */
 if (modes & EXTRA)   /* Program spare area. */
 {
  command = 0x50;  
  addressLSB = address & 0x0F;  /* Only have 16 bytes. */
 }
 else if(address & NFLASH_K9F_SECTORHALFSIZE)
 {         /* 256-512 area. */
  command = 0x01;  
  addressLSB = address & 0xFF;  
 }
 else
 {         /* 0-256 area. */
  command = 0x00;  
  addressLSB = address & 0xFF; 
 } 
 OUT_WORD(FADDR_CLE, command); 
 OUT_WORD(FADDR_CLE, 0x80); 
 OUT_WORD(FADDR_ALE, addressLSB);
 OUT_WORD(FADDR_ALE, (unsigned short)(address >> 9));
 OUT_WORD(FADDR_ALE, (unsigned short)(address >> 17)); 
 for(i=0; i  OUT_WORD(FADDR_BASE, (short)*buffer++);
 
 OUT_WORD(FADDR_CLE, 0x10);
 OUT_WORD(FADDR_CLE, 0x70);
 while(1)
 {
  command = IN_WORD(FADDR_BASE);
  if(command & 0x40) break;
 }
 
 /* Check status register. */
 if(command & 0x1) return flWriteFault;
 return flOK;
}
/* The Following is Core MTD methods - read, write and erase */
/*****************************************************************************
* nandMTDRead, Read data from flash. This routine is registered as MTD read routine.
*
* Parameters:
* vol  : Pointer identifying drive
*  address : Address to read from. 
* buffer : buffer to read to. 
* length : number of bytes to read (up to sector size).
* modes : EDC flag etc. 
*
* Returns:  
* FLStatus: 0 on success, otherwise failed.
*/
static FLStatus nandMTDRead( FLFlash* pVol,
  CardAddress address, void FAR1 *buffer, int length, int modes)
{
 char FAR1 *pReadPtr;
 int readLen, i;
 unsigned char verifyByte, verifyMask;
 FLStatus status = flOK;
 /* read in sectors; first and last might be partial */
 int pagesize = modes & EXTRA ? NFLASH_K9F_TAILSIZE : NFLASH_K9F_SECTORSIZE;
 DEBUG_FL("Read, addr:%x, buf:%x, len:%x, mode:%x.\n", address, buffer, length, modes);
 if(address > pVol->chipSize)
  printf("************************************ Read PTR exceed the chip size 0x%0x.\n******************", address);
 readLen = pagesize - (address & (pagesize - 1));
 pReadPtr = (char FAR1 *)buffer;
 
 while(length > 0)
 {
  if (readLen > length) readLen = length;
  readOnePage(pVol, address, pReadPtr, readLen, modes);
  
     #ifdef VERIFY_AFTER_WRITE
  readOnePage (pVol, address, (char FAR1 *)flReadback, readLen, modes); // Read again for compare.
  for(i=0; i < readLen; i++)
  {
   if(pReadPtr[i] != flReadback[i])       // Compare, if error, try to correct it.
   {
    readOnePage (pVol, address+i, &verifyByte, 1, modes);   // Read 3rd times.
    verifyMask = pReadPtr[i] ^ flReadback[i];       // Mask right bit.
    if((pReadPtr[i] & verifyMask) == (verifyByte & verifyMask))
    {
     printf("Read Error, 1st is right. At 0x%x, Read1=0x%x, Read2=0x%x, len=0x%x.\n", address+i, pReadPtr[i], flReadback[i], readLen);
     taskDelay(100);
     continue; // 1st == 3rd, 1st is right.
    }
    if((flReadback[i] & verifyMask) == (verifyByte & verifyMask))   // 2nd == 3rd, 2nd and 3rd is right, replace 1st data.
    {
     printf("Read Error, 2nd is right. At 0x%x, Read1=0x%x, Read2=0x%x, len=0x%x.\n", address+i, pReadPtr[i], flReadback[i], readLen);
     taskDelay(100);     
     pReadPtr[i] = flReadback[i];
     continue;
    }
    else
    {
     printf("Read Error, return faule. At 0x%x, Read1=0x%x, Read2=0x%x, len=0x%x.\n", address+i, pReadPtr[i], flReadback[i], readLen );
     taskDelay(100);
     return flReadFault;       // 3 times not equal, return fault.
    }
   }    
  }              // Verify OK.
     #endif
  length -= readLen;
  address += readLen;
  pReadPtr += readLen;
  readLen = pagesize;
 }
 return status ;
}
/*****************************************************************************
* nandMTDWrite, Write datas to chip. This routine is registered as MTD write routine.
*
* Parameter:
* vol : Pointer identifying drive
*  address : Address of sector to write to.
* buffer : buffer to write from.
* length : number of bytes to write (May larger than sector size).
* modes : OVERWRITE, EDC flags etc.
*
* Returns:
* FLStatus: 0 on success, otherwise failed.
*/
static FLStatus nandMTDWrite( FLFlash* pVol,
 CardAddress address, const char FAR1 *buffer, int length, int modes)
{
 int writeLen, i, verifyCount;
 const char FAR1 *pWritePtr;
 unsigned char verifyByte, verifyMask;
 FLStatus      status = flOK;
 
 /* write in sectors; first and last might be partial sector*/
 int pagesize = modes & EXTRA ? NFLASH_K9F_TAILSIZE : NFLASH_K9F_SECTORSIZE;
 DEBUG_FL("Write, addr:%x, buf:%x, len:%x, mode:%x. ", address, buffer, length, modes);
 if(address > pVol->chipSize)
  printf("************************************ Write PTR exceed the chip size, 0x%x.\n******************", address);
 writeLen = pagesize - ((unsigned short)address & (pagesize - 1));
 pWritePtr = (const char FAR1 *)buffer;
 for ( ; length > 0 ; )
 {
  if (writeLen > length) writeLen = length;
  status = writeOnePage(pVol, address, pWritePtr, writeLen, modes);
  if (status != flOK)
  {
   printf("\n\n************************Write Error at %x, %x, %x, %x. **********************\n\n",
    address, buffer, length, modes);  
   taskDelay(100);
   break;
  }
  
     #ifdef VERIFY_AFTER_WRITE
  readOnePage (pVol, address, (char FAR1 *)flReadback, writeLen, modes); // Read back 1st for compare.
  readOnePage (pVol, (address & 0xFFFFFFF0), (char FAR1 *)flExtraReadBack, NFLASH_K9F_TAILSIZE, EXTRA);
  verifyCount=0;
  for(i=0; i < writeLen; i++)
  {
   if(pWritePtr[i] != flReadback[i])       // Compare, if error, try to verify it.
   {
    readOnePage (pVol, address+i, &verifyByte, 1, modes);   // Read 2rd times.
    verifyMask = pWritePtr[i] ^ flReadback[i];       // Mask right bit.
    if((pWritePtr[i] & verifyMask) == (verifyByte & verifyMask)) 
    {
     printf("Write verify Error, Corrected. At 0x%x, Write to = 0x%x.\n", address+i, pWritePtr[i]);
     taskDelay(100);
     continue;          // Write == 2nd Read, Write is correct.
    }
    if((flReadback[i] & verifyMask) == (verifyByte & verifyMask))  // 1st Read == 2nd Read, Write is Error, Correct it at Extra area.
    {
       while(1)
     if ((flExtraReadBack[verifyCount * 4] != 0xFF) && (flExtraReadBack[verifyCount*4 + 1] != 0xFF))
     { 
      verifyCount ++;     // This is ocuppied by other, Find next.
      if(verifyCount > 3)
      {
       printf("Write Error, This page 0x%x must be bad.\n", (address >> 9));
       taskDelay(100);
       return flWriteFault; // This page must be bad.
      }
     }
     else
     {
      flExtraReadBack[verifyCount*4] = 0;           // Store Mark;
      flExtraReadBack[verifyCount*4 + 1] = (unsigned char)(((address+i) & 0x100) ? 0x1 : 0); // Store Address MSB      
      flExtraReadBack[verifyCount*4 + 2] = (unsigned char)((address+i) & 0xFF);  // Store Address LSB
      flExtraReadBack[verifyCount*4 + 3] = pWritePtr[i]; // Store Data.
      printf("Write Error, Store data 0x%x at 0x%x, Read back=0x%x.\n", pWritePtr[i], address+i, flReadback[i]);
      taskDelay(100);
      break;
     }
    }
    else            // 2 times read is not equal, return fault.
    {
     printf("Write Error At 0x%x, Write to = 0x%x, Read back = 0x%x.\n", address+i, pWritePtr[i], flReadback[i] );
     taskDelay(100);
     return flWriteFault;
    }    
   }    
  }
  if(verifyCount)   // Write Back verify value.
   writeOnePage(pVol, (address & 0xFFFFFFF0), (char FAR1 *)flExtraReadBack, NFLASH_K9F_TAILSIZE, EXTRA);
  
     #endif
  length -= writeLen;
  address += writeLen;
  pWritePtr += writeLen;
  writeLen = pagesize;
 }
 DEBUG_FL("Done.\n");
 return status;
}
/*****************************************************************************
* nandMTDErase, Erase number of blocks. This routine is registered as MTD erase routine.
*
* Parameters:
* vol  : Pointer identifying drive
* blockNo  : First block to erase.    
* blocksToErase   : Number of blocks to erase.   
*
* Returns:                                                           
* FLStatus : 0 on success, otherwise failed.
*         
*/
static FLStatus nandMTDErase( FLFlash* pVol, int blockNo, int blocksToErase)
{
 int i;
 char status;
 DEBUG_FL("Erase, from:%x, num:%x. ", blockNo, blocksToErase);
 if (flWriteProtected(pVol->socket)) return flWriteProtect;
/*
 if ((blockNo + blocksToErase) > BLOCK_NUM )
  return flBadParameter;
*/
 blockNo *= PAGES_PER_BLOCK;     /* Change to page. */
 for ( i=0; i < blocksToErase; i++, blockNo+=PAGES_PER_BLOCK )
 {
  OUT_WORD(FADDR_CLE, 0x60);
  OUT_WORD(FADDR_ALE, (short)(blockNo & 0xff)); /* A9-A23 */
  OUT_WORD(FADDR_ALE, (short)(blockNo >> 8));
  OUT_WORD(FADDR_CLE, 0xD0); 
  OUT_WORD(FADDR_CLE, 0x70);
  while(1)
  {
   taskDelay(1);
   status = IN_WORD(FADDR_BASE);
   if(status & 0x40) break;
  }  
  if(status & 0x1)    
  {   
   DEBUG_FL("\n\n*****************************Debug: erase block 0x%x failed.**************************\n\n", (blockNo/PAGES_PER_BLOCK));
   /*nfChipReset();    If Erase Error, Reset Chip. */
   return flWriteFault;
  }
 }       /* block loop */
 DEBUG_FL("Done.\n");
 return flOK;
}

/*****************************************************************************
* nandMTDMap, Map through buffer. This routine is registered as MTD map routine.
*
* Parameters: 
* vol : Pointer identifying drive
* address : Flash address to be mapped.
* length : number of bytes to map.
*
* Returns:
*  Pointer to the buffer data was mapped to.
*/
static void FAR0 * nandMTDMap ( FLFlash* pVol, CardAddress address, int length )
{
 DEBUG_FL("Map___");
 
 nandMTDRead(pVol, address, flDataBuffer, length, 0);
 pVol->socket->remapped = TRUE;
 return (void FAR0 *)flDataBuffer;
}
/*****************************************************************************
* cdsnIdentify, Identify flash. This routine is registered as MTD identification routine.
*
* Returns:
* FLStatus: 0 on success, otherwise failed.
*/
FLStatus cdsnIdentify(FLFlash* pVol)
{
 unsigned char byte;
 unsigned short value;
 OUT_WORD(FADDR_CLE, 0xFF);  /* Reset chip first. */
 taskDelay(1);
 OUT_WORD(FADDR_CLE, 0x90);
 OUT_WORD(FADDR_ALE, 0x00);
 byte = (char)IN_WORD(FADDR_BASE);
 value = byte * 256;
 byte = (char)IN_WORD(FADDR_BASE);
 value += byte;
 
 DEBUG_FL("Identfy, Flash ID:%04x.\n", value);
 switch(value)
 {
  case  NFLASH_K9F2808U0X: 
   pVol->type = NFLASH_K9F2808U0X;
   pVol->chipSize = NFL_K9F2808_CHIPSIZE; /* 16MB */
   pVol->flags |= BIG_PAGE;
   break;
  case NFLASH_K9F5608U0X:
   pVol->type = NFLASH_K9F5608U0X;
   pVol->chipSize = NFL_K9F5608_CHIPSIZE;  /* 32MB */
   pVol->flags |= BIG_PAGE;   
   break;
   
  default:   /* No chip identified */
   DEBUG_FL("Debug: Did not identify flash media, id:0x%x.\n", value); 
   return flUnknownMedia;
 }
 
 /* set flash parameters*/
 flSetWindowBusWidth(pVol->socket, 8);/* use 8-bits bus */
 flSetWindowSpeed(pVol->socket, 120);  /* 120 nsec. */
 flSetWindowSize(pVol->socket, 2); /* 64KB, 4 KBytes unit */
 pVol->interleaving = 1; /* */
 pVol->noOfChips = 1;   /* Only have 1 chip */
 pVol->erasableBlockSize = PAGES_PER_BLOCK * NFLASH_K9F_SECTORSIZE;
 
 /* Register our flash handlers */
 pVol->write = nandMTDWrite;
 pVol->erase = nandMTDErase;
/* pVol->read = nandMTDRead;*/
 pVol->map = nandMTDMap;
 pVol->flags |= SUSPEND_FOR_WRITE; /*NFTL_ENABLED; mask at 20040905*/
 return flOK;
}
阅读(1607) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~