#include typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; static const u_char nand_ecc_precalc_table[] = { 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 }; int nand_calculate_ecc(const u_char *dat, u_char *ecc_code) { uint8_t idx, reg1, reg2, reg3, tmp1, tmp2; int i; reg1 = reg2 = reg3 = 0; for(i = 0; i < 256; i++) { idx = nand_ecc_precalc_table[*dat++]; reg1 ^= (idx & 0x3f); if (idx & 0x40) { reg3 ^= (uint8_t) i; reg2 ^= ~((uint8_t) i); } } tmp1 = (reg3 & 0x80) >> 0; tmp1 |= (reg2 & 0x80) >> 1; tmp1 |= (reg3 & 0x40) >> 1; tmp1 |= (reg2 & 0x40) >> 2; tmp1 |= (reg3 & 0x20) >> 2; tmp1 |= (reg2 & 0x20) >> 3; tmp1 |= (reg3 & 0x10) >> 3; tmp1 |= (reg2 & 0x10) >> 4; tmp2 = (reg3 & 0x08) << 4; tmp2 |= (reg2 & 0x08) << 3; tmp2 |= (reg3 & 0x04) << 3; tmp2 |= (reg2 & 0x04) << 2; tmp2 |= (reg3 & 0x02) << 2; tmp2 |= (reg2 & 0x02) << 1; tmp2 |= (reg3 & 0x01) << 1; tmp2 |= (reg2 & 0x01) << 0; #ifdef CONFIG_MTD_NAND_ECC_SMC ecc_code[0] = ~tmp2; ecc_code[1] = ~tmp1; #else ecc_code[0] = ~tmp1; ecc_code[1] = ~tmp2; #endif
ecc_code[2] = ((~reg1) << 2) | 0x03; return 0; } EXPORT_SYMBOL(nand_calculate_ecc); static inline int countbits(uint32_t byte) { int res = 0; for (;byte; byte >>= 1) res += byte & 0x01; return res; } int nand_correct_data(u_char *dat, u_char *read_ecc, u_char *calc_ecc) { uint8_t s0, s1, s2; #ifdef CONFIG_MTD_NAND_ECC_SMC s0 = calc_ecc[0] ^ read_ecc[0]; s1 = calc_ecc[1] ^ read_ecc[1]; s2 = calc_ecc[2] ^ read_ecc[2]; #else s1 = calc_ecc[0] ^ read_ecc[0]; s0 = calc_ecc[1] ^ read_ecc[1]; s2 = calc_ecc[2] ^ read_ecc[2]; #endif if ((s0 | s1 | s2) == 0) return 0; if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 && ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 && ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) { uint32_t byteoffs, bitnum; byteoffs = (s1 << 0) & 0x80; byteoffs |= (s1 << 1) & 0x40; byteoffs |= (s1 << 2) & 0x20; byteoffs |= (s1 << 3) & 0x10; byteoffs |= (s0 >> 4) & 0x08; byteoffs |= (s0 >> 3) & 0x04; byteoffs |= (s0 >> 2) & 0x02; byteoffs |= (s0 >> 1) & 0x01; bitnum = (s2 >> 5) & 0x04; bitnum |= (s2 >> 4) & 0x02; bitnum |= (s2 >> 3) & 0x01; dat[byteoffs] ^= (1 << bitnum); return 1; }
if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1) return 1; return -1; }
|