Statistics
| Branch: | Revision:

root / hw / ecc.c @ bc24a225

History | View | Annotate | Download (2.8 kB)

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
}