Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* error correcting code for nand flash */
2
#include	"u.h"
3
#include	"../port/lib.h"
4
#include	"mem.h"
5
#include	"dat.h"
6
#include	"fns.h"
7
#include	"io.h"
8
#include	"../port/error.h"
9
#include	"nandecc.h"
10
 
11
#define CORRECTABLEMASK 0x545555
12
 
13
static uchar ecctab[] = {
14
	0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
15
	0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
16
	0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
17
	0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
18
	0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
19
	0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
20
	0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
21
	0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
22
	0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
23
	0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
24
	0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
25
	0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
26
	0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
27
	0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
28
	0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
29
	0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
30
	0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
31
	0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
32
	0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
33
	0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
34
	0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
35
	0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
36
	0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
37
	0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
38
	0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
39
	0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
40
	0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
41
	0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
42
	0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
43
	0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
44
	0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
45
	0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
46
};
47
 
48
ulong
49
nandecc(uchar *buf)
50
{
51
	int cp, zeros, ones, im, lp, om, i;
52
 
53
	cp = 0xff;
54
	zeros = 0xff;
55
	ones = 0xff;
56
	for (i = 0; i < 256; i++) {
57
		int tabent = ecctab[buf[i]];
58
 
59
		cp ^= tabent;
60
		if (tabent & 1) {
61
			zeros ^= ~i;
62
			ones ^= i;
63
		}
64
	}
65
	lp = 0;
66
	for (im = 0x80, om = 0x8000; im; im >>= 1, om >>= 1) {
67
		if (ones & im)
68
			lp |= om;
69
		om >>= 1;
70
		if (zeros & im)
71
			lp |= om;
72
	}
73
	return (((cp & 0xff) | 3) << 16) | lp;
74
}
75
 
76
NandEccError
77
nandecccorrect(uchar *buf, ulong calcecc, ulong *storedecc, int reportbad)
78
{
79
	ulong xorecc, mask;
80
	int k;
81
 
82
	if (calcecc == *storedecc)
83
		return NandEccErrorGood;
84
	if (reportbad)
85
		print("nandecccorrect: calculated ecc %.8lux stored ecc %.8lux\n",
86
			calcecc, *storedecc);
87
	xorecc = calcecc ^ *storedecc;
88
	if (((xorecc ^ (xorecc >> 1)) & CORRECTABLEMASK) == CORRECTABLEMASK) {
89
		ulong imask;
90
		ushort out, omask;
91
		int line, col;
92
 
93
		for (imask = 0x800000, omask = 0x800, out = 0; imask;
94
		    imask >>= 2, omask >>= 1)
95
			if (xorecc & imask)
96
				out |= omask;
97
		line = out & 0xff;
98
		col = out >> 9;
99
		if (reportbad)
100
			print("nandecccorrect: single bit error line %d col %d\n",
101
				line, col);
102
		buf[line] ^= (1 << col);
103
		*storedecc = calcecc;
104
		return NandEccErrorOneBit;
105
	}
106
	for (mask = 0x800000, k = 0; mask; mask >>= 1)
107
		if (mask & xorecc)
108
			k++;
109
	if (k == 1) {
110
		if (reportbad)
111
			print("nandecccorrect: single bit error in ecc\n");
112
		/* assume the stored ecc was wrong */
113
		*storedecc = calcecc;
114
		return NandEccErrorOneBitInEcc;
115
	}
116
	if (reportbad)
117
		print("nandecccorrect: 2 bit error\n");
118
	return NandEccErrorBad;
119
}