1*28942eadSforsyth #include "logfsos.h"
237da2899SCharles.Forsyth #include "nandecc.h"
337da2899SCharles.Forsyth
437da2899SCharles.Forsyth static uchar ecctab[] = {
537da2899SCharles.Forsyth 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
637da2899SCharles.Forsyth 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
737da2899SCharles.Forsyth 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
837da2899SCharles.Forsyth 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
937da2899SCharles.Forsyth 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
1037da2899SCharles.Forsyth 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
1137da2899SCharles.Forsyth 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
1237da2899SCharles.Forsyth 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
1337da2899SCharles.Forsyth 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
1437da2899SCharles.Forsyth 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
1537da2899SCharles.Forsyth 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
1637da2899SCharles.Forsyth 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
1737da2899SCharles.Forsyth 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
1837da2899SCharles.Forsyth 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
1937da2899SCharles.Forsyth 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
2037da2899SCharles.Forsyth 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
2137da2899SCharles.Forsyth };
2237da2899SCharles.Forsyth
2337da2899SCharles.Forsyth ulong
nandecc(uchar * buf)2437da2899SCharles.Forsyth nandecc(uchar *buf)
2537da2899SCharles.Forsyth {
2637da2899SCharles.Forsyth int cp, zeros, ones, im;
2737da2899SCharles.Forsyth int lp, om;
2837da2899SCharles.Forsyth int i;
2937da2899SCharles.Forsyth
3037da2899SCharles.Forsyth cp = 0xff;
3137da2899SCharles.Forsyth zeros = 0xff;
3237da2899SCharles.Forsyth ones = 0xff;
3337da2899SCharles.Forsyth for (i = 0; i < 256; i++) {
3437da2899SCharles.Forsyth int tabent = ecctab[buf[i]];
3537da2899SCharles.Forsyth cp ^= tabent;
3637da2899SCharles.Forsyth if (tabent & 1) {
3737da2899SCharles.Forsyth zeros ^= ~i;
3837da2899SCharles.Forsyth ones ^= i;
3937da2899SCharles.Forsyth }
4037da2899SCharles.Forsyth }
4137da2899SCharles.Forsyth lp = 0;
4237da2899SCharles.Forsyth for (im = 0x80, om = 0x8000; im; im >>= 1, om >>= 1) {
4337da2899SCharles.Forsyth if (ones & im)
4437da2899SCharles.Forsyth lp |= om;
4537da2899SCharles.Forsyth om >>= 1;
4637da2899SCharles.Forsyth if (zeros & im)
4737da2899SCharles.Forsyth lp |= om;
4837da2899SCharles.Forsyth }
4937da2899SCharles.Forsyth return (((cp & 0xff) | 3) << 16) | lp;
5037da2899SCharles.Forsyth }
5137da2899SCharles.Forsyth
5237da2899SCharles.Forsyth #define CORRECTABLEMASK 0x545555
5337da2899SCharles.Forsyth
5437da2899SCharles.Forsyth NandEccError
nandecccorrect(uchar * buf,ulong calcecc,ulong * storedecc,int reportbad)5537da2899SCharles.Forsyth nandecccorrect(uchar *buf, ulong calcecc, ulong *storedecc, int reportbad)
5637da2899SCharles.Forsyth {
5737da2899SCharles.Forsyth ulong xorecc;
5837da2899SCharles.Forsyth ulong mask;
5937da2899SCharles.Forsyth int k;
6037da2899SCharles.Forsyth
6137da2899SCharles.Forsyth if (calcecc == *storedecc)
6237da2899SCharles.Forsyth return NandEccErrorGood;
6337da2899SCharles.Forsyth if (reportbad)
6437da2899SCharles.Forsyth print("nandecccorrect: calculated ecc %.8lux stored ecc %.8lux\n", calcecc, *storedecc);
6537da2899SCharles.Forsyth xorecc = calcecc ^ *storedecc;
6637da2899SCharles.Forsyth if (((xorecc ^ (xorecc >> 1)) & CORRECTABLEMASK) == CORRECTABLEMASK) {
6737da2899SCharles.Forsyth ulong imask;
6837da2899SCharles.Forsyth ushort out;
6937da2899SCharles.Forsyth ushort omask;
7037da2899SCharles.Forsyth int line, col;
7137da2899SCharles.Forsyth
7237da2899SCharles.Forsyth for (imask = 0x800000, omask = 0x800, out = 0; imask; imask >>= 2, omask >>= 1) {
7337da2899SCharles.Forsyth if (xorecc & imask)
7437da2899SCharles.Forsyth out |= omask;
7537da2899SCharles.Forsyth }
7637da2899SCharles.Forsyth line = out & 0xff;
7737da2899SCharles.Forsyth col = out >> 9;
7837da2899SCharles.Forsyth if (reportbad)
7937da2899SCharles.Forsyth print("nandecccorrect: single bit error line %d col %d\n", line, col);
8037da2899SCharles.Forsyth buf[line] ^= (1 << col);
8137da2899SCharles.Forsyth *storedecc = calcecc;
8237da2899SCharles.Forsyth return NandEccErrorOneBit;
8337da2899SCharles.Forsyth }
8437da2899SCharles.Forsyth for (mask = 0x800000, k = 0; mask; mask >>= 1)
8537da2899SCharles.Forsyth if (mask & xorecc)
8637da2899SCharles.Forsyth k++;
8737da2899SCharles.Forsyth if (k == 1) {
8837da2899SCharles.Forsyth if (reportbad)
8937da2899SCharles.Forsyth print("nandecccorrect: single bit error in ecc\n");
9037da2899SCharles.Forsyth // assume the stored ecc was wrong
9137da2899SCharles.Forsyth *storedecc = calcecc;
9237da2899SCharles.Forsyth return NandEccErrorOneBitInEcc;
9337da2899SCharles.Forsyth }
9437da2899SCharles.Forsyth if (reportbad)
9537da2899SCharles.Forsyth print("nandecccorrect: 2 bit error\n");
9637da2899SCharles.Forsyth return NandEccErrorBad;
9737da2899SCharles.Forsyth }
9837da2899SCharles.Forsyth
99