nand emulation fixes
[qemu] / hw / ecc.c
1 /*
2  * Calculate Error-correcting Codes. Used by NAND Flash controllers
3  * (not by NAND chips).
4  *
5  * Copyright (c) 2006 Openedhand Ltd.
6  * Written by Andrzej Zaborowski <balrog@zabor.org>
7  *
8  * This code is licensed under the GNU GPL v2.
9  */
10
11 #include "hw.h"
12 #include "flash.h"
13
14 /*
15  * Pre-calculated 256-way 1 byte column parity.  Table borrowed from Linux.
16  */
17 static const uint8_t nand_ecc_precalc_table[] = {
18     0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
19     0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
20     0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
21     0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
22     0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
23     0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
24     0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
25     0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
26     0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
27     0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
28     0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
29     0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
30     0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
31     0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
32     0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
33     0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
34     0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
35     0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
36     0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
37     0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
38     0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
39     0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
40     0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
41     0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
42     0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
43     0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
44     0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
45     0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
46     0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
47     0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
48     0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
49     0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
50 };
51
52 /* Update ECC parity count.  */
53 uint8_t ecc_digest(ECCState *s, uint8_t sample)
54 {
55     uint8_t idx = nand_ecc_precalc_table[sample];
56
57     s->cp ^= idx & 0x3f;
58     if (idx & 0x40) {
59         s->lp[0] ^= ~s->count;
60         s->lp[1] ^= s->count;
61     }
62     s->count ++;
63
64     return sample;
65 }
66
67 /* Reinitialise the counters.  */
68 void ecc_reset(ECCState *s)
69 {
70     s->lp[0] = 0x0000;
71     s->lp[1] = 0x0000;
72     s->cp = 0x00;
73     s->count = 0;
74 }
75
76 /* Save/restore */
77 void ecc_put(QEMUFile *f, ECCState *s)
78 {
79     qemu_put_8s(f, &s->cp);
80     qemu_put_be16s(f, &s->lp[0]);
81     qemu_put_be16s(f, &s->lp[1]);
82     qemu_put_be16s(f, &s->count);
83 }
84
85 void ecc_get(QEMUFile *f, ECCState *s)
86 {
87     qemu_get_8s(f, &s->cp);
88     qemu_get_be16s(f, &s->lp[0]);
89     qemu_get_be16s(f, &s->lp[1]);
90     qemu_get_be16s(f, &s->count);
91 }