Statistics
| Branch: | Revision:

root / hw / ecc.c @ c6ee607c

History | View | Annotate | Download (2.8 kB)

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