/* 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] 下一页
|