Statistics
| Branch: | Revision:

root / hw / ecc.c @ dbe7fb91

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 "vl.h"
12

    
13
/*
14
 * Pre-calculated 256-way 1 byte column parity.  Table borrowed from Linux.
15
 */
16
static const uint8_t nand_ecc_precalc_table[] = {
17
    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
18
    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
19
    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
20
    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
21
    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
22
    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
23
    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
24
    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
25
    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
26
    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
27
    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
28
    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
29
    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
30
    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
31
    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
32
    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
33
    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
34
    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
35
    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
36
    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
37
    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
38
    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
39
    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
40
    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
41
    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
42
    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
43
    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
44
    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
45
    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
46
    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
47
    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
48
    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
49
};
50

    
51
/* Update ECC parity count.  */
52
uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample)
53
{
54
    uint8_t idx = nand_ecc_precalc_table[sample];
55

    
56
    s->cp ^= idx & 0x3f;
57
    if (idx & 0x40) {
58
        s->lp[0] ^= ~s->count;
59
        s->lp[1] ^= s->count;
60
    }
61
    s->count ++;
62

    
63
    return sample;
64
}
65

    
66
/* Reinitialise the counters.  */
67
void ecc_reset(struct ecc_state_s *s)
68
{
69
    s->lp[0] = 0x0000;
70
    s->lp[1] = 0x0000;
71
    s->cp = 0x00;
72
    s->count = 0;
73
}
74

    
75
/* Save/restore */
76
void ecc_put(QEMUFile *f, struct ecc_state_s *s)
77
{
78
    qemu_put_8s(f, &s->cp);
79
    qemu_put_be16s(f, &s->lp[0]);
80
    qemu_put_be16s(f, &s->lp[1]);
81
    qemu_put_be16s(f, &s->count);
82
}
83

    
84
void ecc_get(QEMUFile *f, struct ecc_state_s *s)
85
{
86
    qemu_get_8s(f, &s->cp);
87
    qemu_get_be16s(f, &s->lp[0]);
88
    qemu_get_be16s(f, &s->lp[1]);
89
    qemu_get_be16s(f, &s->count);
90
}