xref: /inferno-os/libnandfs/hamming31_26.c (revision 28942ead413418b56c5be78e8c4c400881fba72e)
1 #include "logfsos.h"
2 #include "logfs.h"
3 #include "nandfs.h"
4 
5 static unsigned long row4 = 0x001fffc0;
6 static unsigned long row3 = 0x0fe03fc0;
7 static unsigned long row2 = 0x71e3c3c0;
8 static unsigned long row1 = 0xb66cccc0;
9 static unsigned long row0 = 0xdab55540;
10 
11 static char map[] = {
12 	-5, -4, 0, -3, 1, 2, 3, -2,
13 	4, 5, 6, 7, 8, 9, 10, -1, 11,
14 	12, 13, 14, 15, 16, 17, 18,
15 	19, 20, 21, 22, 23, 24, 25,
16 };
17 
18 #define mashbits(rown) \
19 	c = (in) & (rown); \
20 	c ^= c >> 16; \
21 	c ^= c >> 8; \
22 	c ^= c >> 4; \
23 	c ^= c >> 2; \
24 	c = (c ^ (c >> 1)) & 1; \
25 
26 static uchar
_nandfshamming31_26calcparity(ulong in)27 _nandfshamming31_26calcparity(ulong in)
28 {
29 	ulong c;
30 	uchar out;
31 	mashbits(row4); out = c;
32 	mashbits(row3); out = (out << 1) | c;
33 	mashbits(row2); out = (out << 1) | c;
34 	mashbits(row1); out = (out << 1) | c;
35 	mashbits(row0); out = (out << 1) | c;
36 	return out;
37 }
38 
39 ulong
_nandfshamming31_26calc(ulong in)40 _nandfshamming31_26calc(ulong in)
41 {
42 	in &= 0xffffffc0;
43 	return in | _nandfshamming31_26calcparity(in);
44 }
45 
46 int
_nandfshamming31_26correct(ulong * in)47 _nandfshamming31_26correct(ulong *in)
48 {
49 	uchar eparity, parity;
50 	ulong e;
51 	eparity = _nandfshamming31_26calcparity(*in);
52 	parity = (*in) & 0x1f;
53 	e = eparity ^ parity;
54 	if (e == 0)
55 		return 0;
56 	e--;
57 	if (map[e] < 0)
58 		return 1;		// error in parity bits
59 	e = map[e];
60 	*in ^= 1 << (31 - e);
61 	return 1;
62 }
63