diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /libnandfs/hamming31_26.c | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'libnandfs/hamming31_26.c')
| -rw-r--r-- | libnandfs/hamming31_26.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/libnandfs/hamming31_26.c b/libnandfs/hamming31_26.c new file mode 100644 index 00000000..a94262b7 --- /dev/null +++ b/libnandfs/hamming31_26.c @@ -0,0 +1,62 @@ +#include "lib9.h" +#include "logfs.h" +#include "nandfs.h" + +static unsigned long row4 = 0x001fffc0; +static unsigned long row3 = 0x0fe03fc0; +static unsigned long row2 = 0x71e3c3c0; +static unsigned long row1 = 0xb66cccc0; +static unsigned long row0 = 0xdab55540; + +static char map[] = { + -5, -4, 0, -3, 1, 2, 3, -2, + 4, 5, 6, 7, 8, 9, 10, -1, 11, + 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, +}; + +#define mashbits(rown) \ + c = (in) & (rown); \ + c ^= c >> 16; \ + c ^= c >> 8; \ + c ^= c >> 4; \ + c ^= c >> 2; \ + c = (c ^ (c >> 1)) & 1; \ + +static uchar +_nandfshamming31_26calcparity(ulong in) +{ + ulong c; + uchar out; + mashbits(row4); out = c; + mashbits(row3); out = (out << 1) | c; + mashbits(row2); out = (out << 1) | c; + mashbits(row1); out = (out << 1) | c; + mashbits(row0); out = (out << 1) | c; + return out; +} + +ulong +_nandfshamming31_26calc(ulong in) +{ + in &= 0xffffffc0; + return in | _nandfshamming31_26calcparity(in); +} + +int +_nandfshamming31_26correct(ulong *in) +{ + uchar eparity, parity; + ulong e; + eparity = _nandfshamming31_26calcparity(*in); + parity = (*in) & 0x1f; + e = eparity ^ parity; + if (e == 0) + return 0; + e--; + if (map[e] < 0) + return 1; // error in parity bits + e = map[e]; + *in ^= 1 << (31 - e); + return 1; +} |
