|  
 
 
  
/* driver for K9K8G08U0A use addr lines as ale cle r/b signels :     ale--BA29     cle--BA30     r/b--PA15           row 13bit --block                 6bit  --page               col   1bit  --spare           2bit  --sector           9bit  --offset(512byte)           block0 info     block 1~4096 data     block 4097~8191 for replace bad block     ecc save in spare area byte 1-3 (byte 0 is bad block mark)           我们提供了         虚拟块号写函数 nand_write_vblock :由vblock块的头开始写len长度(len<=64*2048)且该块将被整块覆盖         虚拟块号读函数 nand_read_vblock :由vblock块的头开始读len长度(len<=64*2048)         虚拟地址读函数 nand_read_vaddr :由虚拟地址vaddr(0~0x1FFFFFFF)读len长度(vaddr+len<=0x20000000)         虚拟块号到虚拟地址转化函数 nand_vblocknum2vaddr :                   由于要写的块都要先擦除,所以仅提供了以虚拟块号为参数的写函数,而没有提供以虚拟地址为参数的写函数,         为方便起见,提供了 虚拟块号到虚拟地址转化函数 和 虚拟地址到虚拟块号转化函数                 */ /* 09.6.30  检测busy管脚添加超时退出 */ #pragma pack(1) #include "vxWorks.h"   #define TIMEOUT_LOOP 99999  /*待测*/   #define DEBUG #ifdef  DEBUG #define DEBUG_READ     0x00000001 #define DEBUG_ERROR    0x00000002 #define DEBUG_PROGRAM  0x00000004 #define DEBUG_ERASE    0x00000008 #define DEBUG_ID       0x00000010 #define DEBUG_MAP      0x00000020 #define DEBUG_ECC      0x00000040 #define DEBUG_ADDR     0x00000080 #define DEBUG_BLKCHK   0x00000100 #define DEBUG_ALWAYS   0xffffffff         LOCAL UINT32 debug = DEBUG_READ | DEBUG_BLKCHK | DEBUG_ERASE;     #define DEBUG_PRINT(mask, string) \                 if ((debug & mask) || (mask == DEBUG_ALWAYS)) \                 printf string #else     #define DEBUG_PRINT(mask, string) #endif   #define     NAND_CMD     0x50000002 #define     NAND_ADDR     0x50000004 #define        PAPAR        *((volatile UINT32*)0xf0010D06) #define        PADIR        *((volatile UINT32*)0xf0010D02) #define        PADAT        *((volatile UINT32*)0xf0010D10) #define        PA15        0x00010000 typedef struct {     UCHAR checked;     UCHAR badBlockTable[8192];     union      {         UINT16 map_short[4096];         UCHAR map_char[8192];     }map;     UCHAR bottomHaltInValid[4095]; }NAND_INFO; LOCAL NAND_INFO nand_info; 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; LOCAL void make_ecc_512(unsigned char * ecc_buf, unsigned char * data_buf); LOCAL eccdiff_t compare_ecc_512(unsigned char *iEccdata1, unsigned char *iEccdata2,            unsigned char *pPagedata, long * pOffset, unsigned char * pCorrected); LOCAL BOOL isBusy(); LOCAL void set_command(UCHAR cmd); LOCAL void set_addr(UCHAR addr); LOCAL UCHAR nand_read(void); LOCAL void nand_write(UCHAR c);   LOCAL UINT32 make_addr(UINT32 blocknum,UINT32 page,UINT32 sector,UINT32 offset,int flag); LOCAL int set_data_addr(UINT32 addr,int flag);   int nand_erase(UINT32 blocknum); LOCAL int nand_program_block(UCHAR* src,UINT32 blocknum,UINT32 len); LOCAL int nand_program_sector(UCHAR* src,UINT32 blocknum,UINT32 page,UINT32 sector); BOOL isChecked(); LOCAL void reset_nand(); LOCAL void initalBadBlockCheck(); LOCAL int read_id(); LOCAL int nand_read_sector(UCHAR* buf,UINT32 blocknum,UINT32 page,UINT32 sector); LOCAL int load_info(); LOCAL int program_info(); LOCAL int nand_read_block0(UCHAR* buf,UINT32 len); LOCAL int wait(); void nand_init();/*初始化*/ int nand_write_vblock(UINT32 vblocknum,UCHAR* buf,UINT32 len);/*vblocknum: 0~4095*//*虚拟块号写函数*/ int nand_read_vblock(UINT32 vblocknum,UCHAR* buf,UINT32 len);/*vblocknum: 0~4095*//*虚拟块号读函数*/ int nand_read_vaddr(UINT32 vaddr,UCHAR* buf,UINT32 len);/*vaddr : 0~0x1FFFFFFF*//*虚拟地址读函数*/ int nand_vblocknum2vaddr(UINT32 vblocknum,UINT32* pvaddr);/*虚拟块号到虚拟地址转化函数*/ int nand_vaddr2vblocknum(UINT32 vaddr,UINT32 * pvblock,UINT32 * poffset);/*虚拟地址到虚拟块号转化函数,poffset为块内偏移量*/     int nand_vblocknum2vaddr(UINT32 vblocknum,UINT32* pvaddr) {           if(vblocknum>4095)     {         printf("error : vblocknum>4095\n");         return -1;     }     else     {         * pvaddr = (vblocknum<<17);         return 0;     }           } int nand_vaddr2vblocknum(UINT32 vaddr,UINT32 * pvblock,UINT32 * poffset) {           if(vaddr>0x1FFFFFFF)     {         printf("error : vaddr>0x1FFFFFFF\n");         return -1;     }     else     {         *pvblock = (vaddr & 0x1FFE0000)>>17;         *poffset = (vaddr & 0x1FFFF);         return 0;     }           }   LOCAL 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;          tmp = (parityCol4343 >> 16) ^ parityCol4343;     tmp = (tmp >> 8) ^ tmp;     tmp = (tmp << 4) ^ tmp;     tmp = (tmp << 2) ^ tmp;     ecc |= ((tmp << 1) ^ tmp) & 0x80;          tmp = (parityCol4242 >> 16) ^ parityCol4242;     tmp = (tmp >> 8) ^ tmp;     tmp = (tmp << 4) ^ tmp;     tmp = (tmp >> 2) ^ tmp;     ecc |= ((tmp << 1) ^ tmp) & 0x20;            tmp = parityColTot & 0xFFFF0000;     tmp = tmp >> 16;     tmp = (tmp >> 8) ^ tmp;     tmp = (tmp >> 4) ^ tmp;     tmp = (tmp << 2) ^ tmp;     ecc |= ((tmp << 1) ^ tmp) & 0x08;          tmp = parityColTot & 0xFF00FF00;     tmp = (tmp >> 16) ^ tmp;     tmp = (tmp >> 8);     tmp = (tmp >> 4) ^ tmp;     tmp = (tmp >> 2) ^ tmp;     ecc |= ((tmp << 1) ^ tmp) & 0x02;          tmp = parityColTot & 0xF0F0F0F0 ;     tmp = (tmp << 16) ^ tmp;     tmp = (tmp >> 8) ^ tmp;     tmp = (tmp << 2) ^ tmp;     ecc |= ((tmp << 1) ^ tmp) & 0x800000;          tmp = parityColTot & 0xCCCCCCCC ;     tmp = (tmp << 16) ^ tmp;     tmp = (tmp >> 8) ^ tmp;     tmp = (tmp << 4) ^ tmp;     tmp = (tmp >> 2);     ecc |= ((tmp << 1) ^ tmp) & 0x200000;          tmp = parityColTot & 0xAAAAAAAA ;     tmp = (tmp << 16) ^ tmp;     tmp = (tmp >> 8) ^ tmp;     tmp = (tmp >> 4) ^ tmp;     tmp = (tmp << 2) ^ tmp;     ecc |= (tmp & 0x80000);          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. ****/ LOCAL 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 :             DEBUG_PRINT(DEBUG_ECC, ("RESULT : no error\n"));             return ECC_NO_ERROR;           case 1 :             DEBUG_PRINT(DEBUG_ECC,("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));                   DEBUG_PRINT(DEBUG_ECC,("iCompecc = %d\n",iCompecc));                 DEBUG_PRINT(DEBUG_ECC,("RESULT : one bit error\r\n"));                 DEBUG_PRINT(DEBUG_ECC,("byte = %d, bit = %d\r\n", iFindbyte, iFindbit));                 DEBUG_PRINT(DEBUG_ECC,("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 :             DEBUG_PRINT(DEBUG_ECC,("RESULT : unrecoverable error\n"));             return ECC_UNCORRECTABLE_ERROR;     }    } 
上一页  [1] [2] [3] [4] 下一页  
 |