]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/ecc.c
pc kernel: fix wrong simd exception mask (fixes go bootstrap)
[plan9front.git] / sys / src / 9 / port / ecc.c
1 /* error correcting code for nand flash */
2 #include        "u.h"
3 #include        "../port/lib.h"
4 #include        "mem.h"
5 #include        "dat.h"
6 #include        "fns.h"
7 #include        "io.h"
8 #include        "../port/error.h"
9 #include        "nandecc.h"
10
11 #define CORRECTABLEMASK 0x545555
12
13 static uchar ecctab[] = {
14         0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
15         0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
16         0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
17         0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
18         0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
19         0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
20         0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
21         0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
22         0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
23         0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
24         0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
25         0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
26         0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
27         0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
28         0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
29         0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
30         0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
31         0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
32         0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
33         0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
34         0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
35         0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
36         0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
37         0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
38         0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
39         0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
40         0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
41         0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
42         0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
43         0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
44         0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
45         0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
46 };
47
48 ulong
49 nandecc(uchar *buf)
50 {
51         int cp, zeros, ones, im, lp, om, i;
52
53         cp = 0xff;
54         zeros = 0xff;
55         ones = 0xff;
56         for (i = 0; i < 256; i++) {
57                 int tabent = ecctab[buf[i]];
58
59                 cp ^= tabent;
60                 if (tabent & 1) {
61                         zeros ^= ~i;
62                         ones ^= i;
63                 }
64         }
65         lp = 0;
66         for (im = 0x80, om = 0x8000; im; im >>= 1, om >>= 1) {
67                 if (ones & im)
68                         lp |= om;
69                 om >>= 1;
70                 if (zeros & im)
71                         lp |= om;
72         }
73         return (((cp & 0xff) | 3) << 16) | lp;
74 }
75
76 NandEccError
77 nandecccorrect(uchar *buf, ulong calcecc, ulong *storedecc, int reportbad)
78 {
79         ulong xorecc, mask;
80         int k;
81
82         if (calcecc == *storedecc)
83                 return NandEccErrorGood;
84         if (reportbad)
85                 print("nandecccorrect: calculated ecc %.8lux stored ecc %.8lux\n",
86                         calcecc, *storedecc);
87         xorecc = calcecc ^ *storedecc;
88         if (((xorecc ^ (xorecc >> 1)) & CORRECTABLEMASK) == CORRECTABLEMASK) {
89                 ulong imask;
90                 ushort out, omask;
91                 int line, col;
92
93                 for (imask = 0x800000, omask = 0x800, out = 0; imask;
94                     imask >>= 2, omask >>= 1)
95                         if (xorecc & imask)
96                                 out |= omask;
97                 line = out & 0xff;
98                 col = out >> 9;
99                 if (reportbad)
100                         print("nandecccorrect: single bit error line %d col %d\n",
101                                 line, col);
102                 buf[line] ^= (1 << col);
103                 *storedecc = calcecc;
104                 return NandEccErrorOneBit;
105         }
106         for (mask = 0x800000, k = 0; mask; mask >>= 1)
107                 if (mask & xorecc)
108                         k++;
109         if (k == 1) {
110                 if (reportbad)
111                         print("nandecccorrect: single bit error in ecc\n");
112                 /* assume the stored ecc was wrong */
113                 *storedecc = calcecc;
114                 return NandEccErrorOneBitInEcc;
115         }
116         if (reportbad)
117                 print("nandecccorrect: 2 bit error\n");
118         return NandEccErrorBad;
119 }