Blame view

hw/ecc.c 2.81 KB
1
2
3
4
5
6
7
8
9
10
/*
 * Calculate Error-correcting Codes. Used by NAND Flash controllers
 * (not by NAND chips).
 *
 * Copyright (c) 2006 Openedhand Ltd.
 * Written by Andrzej Zaborowski <balrog@zabor.org>
 *
 * This code is licensed under the GNU GPL v2.
 */
pbrook authored
11
12
#include "hw.h"
#include "flash.h"
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

/*
 * Pre-calculated 256-way 1 byte column parity.  Table borrowed from Linux.
 */
static const uint8_t nand_ecc_precalc_table[] = {
    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
};

/* Update ECC parity count.  */
Paul Brook authored
53
uint8_t ecc_digest(ECCState *s, uint8_t sample)
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{
    uint8_t idx = nand_ecc_precalc_table[sample];

    s->cp ^= idx & 0x3f;
    if (idx & 0x40) {
        s->lp[0] ^= ~s->count;
        s->lp[1] ^= s->count;
    }
    s->count ++;

    return sample;
}

/* Reinitialise the counters.  */
Paul Brook authored
68
void ecc_reset(ECCState *s)
69
70
71
72
73
74
{
    s->lp[0] = 0x0000;
    s->lp[1] = 0x0000;
    s->cp = 0x00;
    s->count = 0;
}
75
76

/* Save/restore */
Paul Brook authored
77
void ecc_put(QEMUFile *f, ECCState *s)
78
79
80
81
82
83
84
{
    qemu_put_8s(f, &s->cp);
    qemu_put_be16s(f, &s->lp[0]);
    qemu_put_be16s(f, &s->lp[1]);
    qemu_put_be16s(f, &s->count);
}
Paul Brook authored
85
void ecc_get(QEMUFile *f, ECCState *s)
86
87
88
89
90
91
{
    qemu_get_8s(f, &s->cp);
    qemu_get_be16s(f, &s->lp[0]);
    qemu_get_be16s(f, &s->lp[1]);
    qemu_get_be16s(f, &s->count);
}