123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- /* error correcting code for nand flash */
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "io.h"
- #include "../port/error.h"
- #include "nandecc.h"
- #define CORRECTABLEMASK 0x545555
- static uchar ecctab[] = {
- 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
- 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
- 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
- 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
- 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
- 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
- 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
- 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
- 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
- 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
- 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
- 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
- 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
- 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
- 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
- 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
- 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
- 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
- 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
- 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
- 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
- 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
- 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
- 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
- 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
- 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
- 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
- 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
- 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
- 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
- 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
- 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
- };
- ulong
- nandecc(uchar *buf)
- {
- int cp, zeros, ones, im, lp, om, i;
- cp = 0xff;
- zeros = 0xff;
- ones = 0xff;
- for (i = 0; i < 256; i++) {
- int tabent = ecctab[buf[i]];
- cp ^= tabent;
- if (tabent & 1) {
- zeros ^= ~i;
- ones ^= i;
- }
- }
- lp = 0;
- for (im = 0x80, om = 0x8000; im; im >>= 1, om >>= 1) {
- if (ones & im)
- lp |= om;
- om >>= 1;
- if (zeros & im)
- lp |= om;
- }
- return (((cp & 0xff) | 3) << 16) | lp;
- }
- NandEccError
- nandecccorrect(uchar *buf, ulong calcecc, ulong *storedecc, int reportbad)
- {
- ulong xorecc, mask;
- int k;
- if (calcecc == *storedecc)
- return NandEccErrorGood;
- if (reportbad)
- print("nandecccorrect: calculated ecc %.8lux stored ecc %.8lux\n",
- calcecc, *storedecc);
- xorecc = calcecc ^ *storedecc;
- if (((xorecc ^ (xorecc >> 1)) & CORRECTABLEMASK) == CORRECTABLEMASK) {
- ulong imask;
- ushort out, omask;
- int line, col;
- for (imask = 0x800000, omask = 0x800, out = 0; imask;
- imask >>= 2, omask >>= 1)
- if (xorecc & imask)
- out |= omask;
- line = out & 0xff;
- col = out >> 9;
- if (reportbad)
- print("nandecccorrect: single bit error line %d col %d\n",
- line, col);
- buf[line] ^= (1 << col);
- *storedecc = calcecc;
- return NandEccErrorOneBit;
- }
- for (mask = 0x800000, k = 0; mask; mask >>= 1)
- if (mask & xorecc)
- k++;
- if (k == 1) {
- if (reportbad)
- print("nandecccorrect: single bit error in ecc\n");
- /* assume the stored ecc was wrong */
- *storedecc = calcecc;
- return NandEccErrorOneBitInEcc;
- }
- if (reportbad)
- print("nandecccorrect: 2 bit error\n");
- return NandEccErrorBad;
- }
|