aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/cafe_ecc.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-10-21 21:18:48 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-10-21 21:18:48 -0400
commit04459d7c6239193fa8de4a5107ee8fdb0f366e35 (patch)
tree6ff38851ff638eb6eaa4aa64e31ed909ae887827 /drivers/mtd/nand/cafe_ecc.c
parentc45aa055c32b488fc3fd73c760df372b09acf69a (diff)
[MTD] NAND: Add hardware ECC correction support to CAFÉ NAND driver
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd/nand/cafe_ecc.c')
-rw-r--r--drivers/mtd/nand/cafe_ecc.c1348
1 files changed, 1348 insertions, 0 deletions
diff --git a/drivers/mtd/nand/cafe_ecc.c b/drivers/mtd/nand/cafe_ecc.c
new file mode 100644
index 000000000000..4df28a846fbc
--- /dev/null
+++ b/drivers/mtd/nand/cafe_ecc.c
@@ -0,0 +1,1348 @@
1/* Error correction for CAFÉ NAND controller
2 *
3 * © 2006 Marvell, Inc.
4 * Author: Tom Chiou
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/errno.h>
23
24static unsigned short gf4096_mul(unsigned short, unsigned short);
25static unsigned short gf64_mul(unsigned short, unsigned short);
26static unsigned short gf4096_inv(unsigned short);
27static unsigned short err_pos(unsigned short);
28static void find_4bit_err_coefs(unsigned short, unsigned short, unsigned short,
29 unsigned short, unsigned short, unsigned short,
30 unsigned short, unsigned short, unsigned short *);
31static void zero_4x5_col3(unsigned short[4][5]);
32static void zero_4x5_col2(unsigned short[4][5]);
33static void zero_4x5_col1(unsigned short[4][5]);
34static void swap_4x5_rows(unsigned short[4][5], int, int, int);
35static void swap_2x3_rows(unsigned short m[2][3]);
36static void solve_4x5(unsigned short m[4][5], unsigned short *, int *);
37static void sort_coefs(int *, unsigned short *, int);
38static void find_4bit_err_pats(unsigned short, unsigned short, unsigned short,
39 unsigned short, unsigned short, unsigned short,
40 unsigned short, unsigned short, unsigned short *);
41static void find_3bit_err_coefs(unsigned short, unsigned short, unsigned short,
42 unsigned short, unsigned short, unsigned short,
43 unsigned short *);
44static void zero_3x4_col2(unsigned short[3][4]);
45static void zero_3x4_col1(unsigned short[3][4]);
46static void swap_3x4_rows(unsigned short[3][4], int, int, int);
47static void solve_3x4(unsigned short[3][4], unsigned short *, int *);
48static void find_3bit_err_pats(unsigned short, unsigned short, unsigned short,
49 unsigned short, unsigned short, unsigned short,
50 unsigned short *);
51
52static void find_2bit_err_pats(unsigned short, unsigned short, unsigned short,
53 unsigned short, unsigned short *);
54static void find_2x2_soln(unsigned short, unsigned short, unsigned short,
55 unsigned short, unsigned short, unsigned short,
56 unsigned short *);
57static void solve_2x3(unsigned short[2][3], unsigned short *);
58static int chk_no_err_only(unsigned short *, unsigned short *);
59static int chk_1_err_only(unsigned short *, unsigned short *);
60static int chk_2_err_only(unsigned short *, unsigned short *);
61static int chk_3_err_only(unsigned short *, unsigned short *);
62static int chk_4_err_only(unsigned short *, unsigned short *);
63
64static unsigned short gf64_mul(unsigned short a, unsigned short b)
65{
66 unsigned short tmp1, tmp2, tmp3, tmp4, tmp5;
67 unsigned short c_bit0, c_bit1, c_bit2, c_bit3, c_bit4, c_bit5, c;
68
69 tmp1 = ((a) ^ (a >> 5));
70 tmp2 = ((a >> 4) ^ (a >> 5));
71 tmp3 = ((a >> 3) ^ (a >> 4));
72 tmp4 = ((a >> 2) ^ (a >> 3));
73 tmp5 = ((a >> 1) ^ (a >> 2));
74
75 c_bit0 = ((a & b) ^ ((a >> 5) & (b >> 1)) ^ ((a >> 4) & (b >> 2)) ^
76 ((a >> 3) & (b >> 3)) ^ ((a >> 2) & (b >> 4)) ^ ((a >> 1) & (b >> 5))) & 0x1;
77
78 c_bit1 = (((a >> 1) & b) ^ (tmp1 & (b >> 1)) ^ (tmp2 & (b >> 2)) ^
79 (tmp3 & (b >> 3)) ^ (tmp4 & (b >> 4)) ^ (tmp5 & (b >> 5))) & 0x1;
80
81 c_bit2 = (((a >> 2) & b) ^ ((a >> 1) & (b >> 1)) ^ (tmp1 & (b >> 2)) ^
82 (tmp2 & (b >> 3)) ^ (tmp3 & (b >> 4)) ^ (tmp4 & (b >> 5))) & 0x1;
83
84 c_bit3 = (((a >> 3) & b) ^ ((a >> 2) & (b >> 1)) ^ ((a >> 1) & (b >> 2)) ^
85 (tmp1 & (b >> 3)) ^ (tmp2 & (b >> 4)) ^ (tmp3 & (b >> 5))) & 0x1;
86
87 c_bit4 = (((a >> 4) & b) ^ ((a >> 3) & (b >> 1)) ^ ((a >> 2) & (b >> 2)) ^
88 ((a >> 1) & (b >> 3)) ^ (tmp1 & (b >> 4)) ^ (tmp2 & (b >> 5))) & 0x1;
89
90 c_bit5 = (((a >> 5) & b) ^ ((a >> 4) & (b >> 1)) ^ ((a >> 3) & (b >> 2)) ^
91 ((a >> 2) & (b >> 3)) ^ ((a >> 1) & (b >> 4)) ^ (tmp1 & (b >> 5))) & 0x1;
92
93 c = c_bit0 | (c_bit1 << 1) | (c_bit2 << 2) | (c_bit3 << 3) | (c_bit4 << 4) | (c_bit5 << 5);
94
95 return c;
96}
97
98static unsigned short gf4096_mul(unsigned short a, unsigned short b)
99{
100 unsigned short ah, al, bh, bl, alxah, blxbh, ablh, albl, ahbh, ahbhB, c;
101
102 ah = (a >> 6) & 0x3f;
103 al = a & 0x3f;
104 bh = (b >> 6) & 0x3f;
105 bl = b & 0x3f;
106 alxah = al ^ ah;
107 blxbh = bl ^ bh;
108
109 ablh = gf64_mul(alxah, blxbh);
110 albl = gf64_mul(al, bl);
111 ahbh = gf64_mul(ah, bh);
112
113 ahbhB = ((ahbh & 0x1) << 5) |
114 ((ahbh & 0x20) >> 1) |
115 ((ahbh & 0x10) >> 1) | ((ahbh & 0x8) >> 1) | ((ahbh & 0x4) >> 1) | (((ahbh >> 1) ^ ahbh) & 0x1);
116
117 c = ((ablh ^ albl) << 6) | (ahbhB ^ albl);
118 return c;
119}
120
121static void find_2bit_err_pats(unsigned short s0, unsigned short s1, unsigned short r0, unsigned short r1, unsigned short *pats)
122{
123 find_2x2_soln(0x1, 0x1, r0, r1, s0, s1, pats);
124}
125
126static void find_3bit_err_coefs(unsigned short s0, unsigned short s1,
127 unsigned short s2, unsigned short s3, unsigned short s4, unsigned short s5, unsigned short *coefs)
128{
129 unsigned short m[3][4];
130 int row_order[3];
131
132 row_order[0] = 0;
133 row_order[1] = 1;
134 row_order[2] = 2;
135 m[0][0] = s2;
136 m[0][1] = s1;
137 m[0][2] = s0;
138 m[0][3] = s3;
139 m[1][0] = s3;
140 m[1][1] = s2;
141 m[1][2] = s1;
142 m[1][3] = s4;
143 m[2][0] = s4;
144 m[2][1] = s3;
145 m[2][2] = s2;
146 m[2][3] = s5;
147
148 if (m[0][2] != 0x0) {
149 zero_3x4_col2(m);
150 } else if (m[1][2] != 0x0) {
151 swap_3x4_rows(m, 0, 1, 4);
152 zero_3x4_col2(m);
153 } else if (m[2][2] != 0x0) {
154 swap_3x4_rows(m, 0, 2, 4);
155 zero_3x4_col2(m);
156 } else {
157 printk(KERN_ERR "Error: find_3bit_err_coefs, s0,s1,s2 all zeros!\n");
158 }
159
160 if (m[1][1] != 0x0) {
161 zero_3x4_col1(m);
162 } else if (m[2][1] != 0x0) {
163 swap_3x4_rows(m, 1, 2, 4);
164 zero_3x4_col1(m);
165 } else {
166 printk(KERN_ERR "Error: find_3bit_err_coefs, cannot resolve col 1!\n");
167 }
168
169 /* solve coefs */
170 solve_3x4(m, coefs, row_order);
171}
172
173static void zero_3x4_col2(unsigned short m[3][4])
174{
175 unsigned short minv1, minv2;
176
177 minv1 = gf4096_mul(m[1][2], gf4096_inv(m[0][2]));
178 minv2 = gf4096_mul(m[2][2], gf4096_inv(m[0][2]));
179 m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
180 m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
181 m[1][3] = m[1][3] ^ gf4096_mul(m[0][3], minv1);
182 m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
183 m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
184 m[2][3] = m[2][3] ^ gf4096_mul(m[0][3], minv2);
185}
186
187static void zero_3x4_col1(unsigned short m[3][4])
188{
189 unsigned short minv;
190 minv = gf4096_mul(m[2][1], gf4096_inv(m[1][1]));
191 m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv);
192 m[2][3] = m[2][3] ^ gf4096_mul(m[1][3], minv);
193}
194
195static void swap_3x4_rows(unsigned short m[3][4], int i, int j, int col_width)
196{
197 unsigned short tmp0;
198 int cnt;
199 for (cnt = 0; cnt < col_width; cnt++) {
200 tmp0 = m[i][cnt];
201 m[i][cnt] = m[j][cnt];
202 m[j][cnt] = tmp0;
203 }
204}
205
206static void solve_3x4(unsigned short m[3][4], unsigned short *coefs, int *row_order)
207{
208 unsigned short tmp[3];
209 tmp[0] = gf4096_mul(m[2][3], gf4096_inv(m[2][0]));
210 tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ m[1][3]), gf4096_inv(m[1][1]));
211 tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ gf4096_mul(tmp[1], m[0][1]) ^ m[0][3]), gf4096_inv(m[0][2]));
212 sort_coefs(row_order, tmp, 3);
213 coefs[0] = tmp[0];
214 coefs[1] = tmp[1];
215 coefs[2] = tmp[2];
216}
217
218static void find_3bit_err_pats(unsigned short s0, unsigned short s1,
219 unsigned short s2, unsigned short r0,
220 unsigned short r1, unsigned short r2,
221 unsigned short *pats)
222{
223 find_2x2_soln(r0 ^ r2, r1 ^ r2,
224 gf4096_mul(r0, r0 ^ r2), gf4096_mul(r1, r1 ^ r2),
225 gf4096_mul(s0, r2) ^ s1, gf4096_mul(s1, r2) ^ s2, pats);
226 pats[2] = s0 ^ pats[0] ^ pats[1];
227}
228
229static void find_4bit_err_coefs(unsigned short s0, unsigned short s1,
230 unsigned short s2, unsigned short s3,
231 unsigned short s4, unsigned short s5,
232 unsigned short s6, unsigned short s7,
233 unsigned short *coefs)
234{
235 unsigned short m[4][5];
236 int row_order[4];
237
238 row_order[0] = 0;
239 row_order[1] = 1;
240 row_order[2] = 2;
241 row_order[3] = 3;
242
243 m[0][0] = s3;
244 m[0][1] = s2;
245 m[0][2] = s1;
246 m[0][3] = s0;
247 m[0][4] = s4;
248 m[1][0] = s4;
249 m[1][1] = s3;
250 m[1][2] = s2;
251 m[1][3] = s1;
252 m[1][4] = s5;
253 m[2][0] = s5;
254 m[2][1] = s4;
255 m[2][2] = s3;
256 m[2][3] = s2;
257 m[2][4] = s6;
258 m[3][0] = s6;
259 m[3][1] = s5;
260 m[3][2] = s4;
261 m[3][3] = s3;
262 m[3][4] = s7;
263
264 if (m[0][3] != 0x0) {
265 zero_4x5_col3(m);
266 } else if (m[1][3] != 0x0) {
267 swap_4x5_rows(m, 0, 1, 5);
268 zero_4x5_col3(m);
269 } else if (m[2][3] != 0x0) {
270 swap_4x5_rows(m, 0, 2, 5);
271 zero_4x5_col3(m);
272 } else if (m[3][3] != 0x0) {
273 swap_4x5_rows(m, 0, 3, 5);
274 zero_4x5_col3(m);
275 } else {
276 printk(KERN_ERR "Error: find_4bit_err_coefs, s0,s1,s2,s3 all zeros!\n");
277 }
278
279 if (m[1][2] != 0x0) {
280 zero_4x5_col2(m);
281 } else if (m[2][2] != 0x0) {
282 swap_4x5_rows(m, 1, 2, 5);
283 zero_4x5_col2(m);
284 } else if (m[3][2] != 0x0) {
285 swap_4x5_rows(m, 1, 3, 5);
286 zero_4x5_col2(m);
287 } else {
288 printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 2!\n");
289 }
290
291 if (m[2][1] != 0x0) {
292 zero_4x5_col1(m);
293 } else if (m[3][1] != 0x0) {
294 swap_4x5_rows(m, 2, 3, 5);
295 zero_4x5_col1(m);
296 } else {
297 printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 1!\n");
298 }
299
300 solve_4x5(m, coefs, row_order);
301}
302
303static void zero_4x5_col3(unsigned short m[4][5])
304{
305 unsigned short minv1, minv2, minv3;
306
307 minv1 = gf4096_mul(m[1][3], gf4096_inv(m[0][3]));
308 minv2 = gf4096_mul(m[2][3], gf4096_inv(m[0][3]));
309 minv3 = gf4096_mul(m[3][3], gf4096_inv(m[0][3]));
310
311 m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
312 m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
313 m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv1);
314 m[1][4] = m[1][4] ^ gf4096_mul(m[0][4], minv1);
315 m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
316 m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
317 m[2][2] = m[2][2] ^ gf4096_mul(m[0][2], minv2);
318 m[2][4] = m[2][4] ^ gf4096_mul(m[0][4], minv2);
319 m[3][0] = m[3][0] ^ gf4096_mul(m[0][0], minv3);
320 m[3][1] = m[3][1] ^ gf4096_mul(m[0][1], minv3);
321 m[3][2] = m[3][2] ^ gf4096_mul(m[0][2], minv3);
322 m[3][4] = m[3][4] ^ gf4096_mul(m[0][4], minv3);
323}
324
325static void zero_4x5_col2(unsigned short m[4][5])
326{
327 unsigned short minv2, minv3;
328
329 minv2 = gf4096_mul(m[2][2], gf4096_inv(m[1][2]));
330 minv3 = gf4096_mul(m[3][2], gf4096_inv(m[1][2]));
331
332 m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv2);
333 m[2][1] = m[2][1] ^ gf4096_mul(m[1][1], minv2);
334 m[2][4] = m[2][4] ^ gf4096_mul(m[1][4], minv2);
335 m[3][0] = m[3][0] ^ gf4096_mul(m[1][0], minv3);
336 m[3][1] = m[3][1] ^ gf4096_mul(m[1][1], minv3);
337 m[3][4] = m[3][4] ^ gf4096_mul(m[1][4], minv3);
338}
339
340static void zero_4x5_col1(unsigned short m[4][5])
341{
342 unsigned short minv;
343
344 minv = gf4096_mul(m[3][1], gf4096_inv(m[2][1]));
345
346 m[3][0] = m[3][0] ^ gf4096_mul(m[2][0], minv);
347 m[3][4] = m[3][4] ^ gf4096_mul(m[2][4], minv);
348}
349
350static void swap_4x5_rows(unsigned short m[4][5], int i, int j, int col_width)
351{
352 unsigned short tmp0;
353 int cnt;
354
355 for (cnt = 0; cnt < col_width; cnt++) {
356 tmp0 = m[i][cnt];
357 m[i][cnt] = m[j][cnt];
358 m[j][cnt] = tmp0;
359 }
360}
361
362static void solve_4x5(unsigned short m[4][5], unsigned short *coefs, int *row_order)
363{
364 unsigned short tmp[4];
365
366 tmp[0] = gf4096_mul(m[3][4], gf4096_inv(m[3][0]));
367 tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[2][0]) ^ m[2][4]), gf4096_inv(m[2][1]));
368 tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ gf4096_mul(tmp[1], m[1][1]) ^ m[1][4]), gf4096_inv(m[1][2]));
369 tmp[3] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^
370 gf4096_mul(tmp[1], m[0][1]) ^ gf4096_mul(tmp[2], m[0][2]) ^ m[0][4]), gf4096_inv(m[0][3]));
371 sort_coefs(row_order, tmp, 4);
372 coefs[0] = tmp[0];
373 coefs[1] = tmp[1];
374 coefs[2] = tmp[2];
375 coefs[3] = tmp[3];
376}
377
378static void sort_coefs(int *order, unsigned short *soln, int len)
379{
380 int cnt, start_cnt, least_ord, least_cnt;
381 unsigned short tmp0;
382 for (start_cnt = 0; start_cnt < len; start_cnt++) {
383 for (cnt = start_cnt; cnt < len; cnt++) {
384 if (cnt == start_cnt) {
385 least_ord = order[cnt];
386 least_cnt = start_cnt;
387 } else {
388 if (least_ord > order[cnt]) {
389 least_ord = order[cnt];
390 least_cnt = cnt;
391 }
392 }
393 }
394 if (least_cnt != start_cnt) {
395 tmp0 = order[least_cnt];
396 order[least_cnt] = order[start_cnt];
397 order[start_cnt] = tmp0;
398 tmp0 = soln[least_cnt];
399 soln[least_cnt] = soln[start_cnt];
400 soln[start_cnt] = tmp0;
401 }
402 }
403}
404
405static void find_4bit_err_pats(unsigned short s0, unsigned short s1,
406 unsigned short s2, unsigned short s3,
407 unsigned short z1, unsigned short z2,
408 unsigned short z3, unsigned short z4,
409 unsigned short *pats)
410{
411 unsigned short z4_z1, z3z4_z3z3, z4_z2, s0z4_s1, z1z4_z1z1,
412 z4_z3, z2z4_z2z2, s1z4_s2, z3z3z4_z3z3z3, z1z1z4_z1z1z1, z2z2z4_z2z2z2, s2z4_s3;
413 unsigned short tmp0, tmp1, tmp2, tmp3;
414
415 z4_z1 = z4 ^ z1;
416 z3z4_z3z3 = gf4096_mul(z3, z4) ^ gf4096_mul(z3, z3);
417 z4_z2 = z4 ^ z2;
418 s0z4_s1 = gf4096_mul(s0, z4) ^ s1;
419 z1z4_z1z1 = gf4096_mul(z1, z4) ^ gf4096_mul(z1, z1);
420 z4_z3 = z4 ^ z3;
421 z2z4_z2z2 = gf4096_mul(z2, z4) ^ gf4096_mul(z2, z2);
422 s1z4_s2 = gf4096_mul(s1, z4) ^ s2;
423 z3z3z4_z3z3z3 = gf4096_mul(gf4096_mul(z3, z3), z4) ^ gf4096_mul(gf4096_mul(z3, z3), z3);
424 z1z1z4_z1z1z1 = gf4096_mul(gf4096_mul(z1, z1), z4) ^ gf4096_mul(gf4096_mul(z1, z1), z1);
425 z2z2z4_z2z2z2 = gf4096_mul(gf4096_mul(z2, z2), z4) ^ gf4096_mul(gf4096_mul(z2, z2), z2);
426 s2z4_s3 = gf4096_mul(s2, z4) ^ s3;
427
428 //find err pat 0,1
429 find_2x2_soln(gf4096_mul(z4_z1, z3z4_z3z3) ^
430 gf4096_mul(z1z4_z1z1, z4_z3), gf4096_mul(z4_z2,
431 z3z4_z3z3) ^
432 gf4096_mul(z2z4_z2z2, z4_z3), gf4096_mul(z1z4_z1z1,
433 z3z3z4_z3z3z3) ^
434 gf4096_mul(z1z1z4_z1z1z1, z3z4_z3z3),
435 gf4096_mul(z2z4_z2z2,
436 z3z3z4_z3z3z3) ^ gf4096_mul(z2z2z4_z2z2z2,
437 z3z4_z3z3),
438 gf4096_mul(s0z4_s1, z3z4_z3z3) ^ gf4096_mul(s1z4_s2,
439 z4_z3),
440 gf4096_mul(s1z4_s2, z3z3z4_z3z3z3) ^ gf4096_mul(s2z4_s3, z3z4_z3z3), pats);
441 tmp0 = pats[0];
442 tmp1 = pats[1];
443 tmp2 = pats[0] ^ pats[1] ^ s0;
444 tmp3 = gf4096_mul(pats[0], z1) ^ gf4096_mul(pats[1], z2) ^ s1;
445
446 //find err pat 2,3
447 find_2x2_soln(0x1, 0x1, z3, z4, tmp2, tmp3, pats);
448 pats[2] = pats[0];
449 pats[3] = pats[1];
450 pats[0] = tmp0;
451 pats[1] = tmp1;
452}
453
454static void find_2x2_soln(unsigned short c00, unsigned short c01,
455 unsigned short c10, unsigned short c11,
456 unsigned short lval0, unsigned short lval1,
457 unsigned short *soln)
458{
459 unsigned short m[2][3];
460 m[0][0] = c00;
461 m[0][1] = c01;
462 m[0][2] = lval0;
463 m[1][0] = c10;
464 m[1][1] = c11;
465 m[1][2] = lval1;
466
467 if (m[0][1] != 0x0) {
468 /* */
469 } else if (m[1][1] != 0x0) {
470 swap_2x3_rows(m);
471 } else {
472 printk(KERN_ERR "Warning: find_2bit_err_coefs, s0,s1 all zeros!\n");
473 }
474
475 solve_2x3(m, soln);
476}
477
478static void swap_2x3_rows(unsigned short m[2][3])
479{
480 unsigned short tmp0;
481 int cnt;
482
483 for (cnt = 0; cnt < 3; cnt++) {
484 tmp0 = m[0][cnt];
485 m[0][cnt] = m[1][cnt];
486 m[1][cnt] = tmp0;
487 }
488}
489
490static void solve_2x3(unsigned short m[2][3], unsigned short *coefs)
491{
492 unsigned short minv;
493
494 minv = gf4096_mul(m[1][1], gf4096_inv(m[0][1]));
495 m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv);
496 m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv);
497 coefs[0] = gf4096_mul(m[1][2], gf4096_inv(m[1][0]));
498 coefs[1] = gf4096_mul((gf4096_mul(coefs[0], m[0][0]) ^ m[0][2]), gf4096_inv(m[0][1]));
499}
500
501static unsigned char gf64_inv[64] = {
502 0, 1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25,
503 61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45, 6,
504 63, 2, 27, 21, 56, 9, 50, 19, 13, 47, 48, 5, 7, 30, 12, 41,
505 42, 4, 38, 18, 10, 29, 17, 60, 36, 8, 59, 58, 55, 16, 3, 32};
506
507static unsigned short gf4096_inv(unsigned short din)
508{
509 unsigned short alahxal, ah2B, deno, inv, bl, bh;
510 unsigned short ah, al, ahxal;
511 unsigned short dout;
512
513 ah = (din >> 6) & 0x3f;
514 al = din & 0x3f;
515 ahxal = ah ^ al;
516 ah2B = (((ah ^ (ah >> 3)) & 0x1) << 5) |
517 ((ah >> 1) & 0x10) |
518 ((((ah >> 5) ^ (ah >> 2)) & 0x1) << 3) |
519 ((ah >> 2) & 0x4) | ((((ah >> 4) ^ (ah >> 1)) & 0x1) << 1) | (ah & 0x1);
520 alahxal = gf64_mul(ahxal, al);
521 deno = alahxal ^ ah2B;
522 inv = gf64_inv[deno];
523 bl = gf64_mul(inv, ahxal);
524 bh = gf64_mul(inv, ah);
525 dout = ((bh & 0x3f) << 6) | (bl & 0x3f);
526 return (((bh & 0x3f) << 6) | (bl & 0x3f));
527}
528
529static unsigned short err_pos_lut[4096] = {
530 0xfff, 0x000, 0x451, 0xfff, 0xfff, 0x3cf, 0xfff, 0x041,
531 0xfff, 0xfff, 0xfff, 0xfff, 0x28a, 0xfff, 0x492, 0xfff,
532 0x145, 0xfff, 0xfff, 0x514, 0xfff, 0x082, 0xfff, 0xfff,
533 0xfff, 0x249, 0x38e, 0x410, 0xfff, 0x104, 0x208, 0x1c7,
534 0xfff, 0xfff, 0xfff, 0xfff, 0x2cb, 0xfff, 0xfff, 0xfff,
535 0x0c3, 0x34d, 0x4d3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
536 0xfff, 0xfff, 0xfff, 0x186, 0xfff, 0xfff, 0xfff, 0xfff,
537 0xfff, 0x30c, 0x555, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
538 0xfff, 0xfff, 0xfff, 0x166, 0xfff, 0xfff, 0xfff, 0xfff,
539 0x385, 0x14e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e1,
540 0xfff, 0xfff, 0xfff, 0xfff, 0x538, 0xfff, 0x16d, 0xfff,
541 0xfff, 0xfff, 0x45b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
542 0xfff, 0xfff, 0xfff, 0x29c, 0x2cc, 0x30b, 0x2b3, 0xfff,
543 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0b3, 0xfff, 0x2f7,
544 0xfff, 0x32b, 0xfff, 0xfff, 0xfff, 0xfff, 0x0a7, 0xfff,
545 0xfff, 0x2da, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
546 0xfff, 0x07e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
547 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x11c, 0xfff, 0xfff,
548 0xfff, 0xfff, 0xfff, 0x22f, 0xfff, 0x1f4, 0xfff, 0xfff,
549 0x2b0, 0x504, 0xfff, 0x114, 0xfff, 0xfff, 0xfff, 0x21d,
550 0xfff, 0xfff, 0xfff, 0xfff, 0x00d, 0x3c4, 0x340, 0x10f,
551 0xfff, 0xfff, 0x266, 0x02e, 0xfff, 0xfff, 0xfff, 0x4f8,
552 0x337, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
553 0xfff, 0xfff, 0xfff, 0x07b, 0x168, 0xfff, 0xfff, 0x0fe,
554 0xfff, 0xfff, 0x51a, 0xfff, 0x458, 0xfff, 0x36d, 0xfff,
555 0xfff, 0xfff, 0xfff, 0x073, 0x37d, 0x415, 0x550, 0xfff,
556 0xfff, 0xfff, 0x23b, 0x4b4, 0xfff, 0xfff, 0xfff, 0x1a1,
557 0xfff, 0xfff, 0x3aa, 0xfff, 0x117, 0x04d, 0x341, 0xfff,
558 0xfff, 0xfff, 0xfff, 0x518, 0x03e, 0x0f2, 0xfff, 0xfff,
559 0xfff, 0xfff, 0xfff, 0x363, 0xfff, 0x0b9, 0xfff, 0xfff,
560 0x241, 0xfff, 0xfff, 0x049, 0xfff, 0xfff, 0xfff, 0xfff,
561 0x15f, 0x52d, 0xfff, 0xfff, 0xfff, 0x29e, 0xfff, 0xfff,
562 0xfff, 0xfff, 0x4cf, 0x0fc, 0xfff, 0x36f, 0x3d3, 0xfff,
563 0x228, 0xfff, 0xfff, 0x45e, 0xfff, 0xfff, 0xfff, 0xfff,
564 0x238, 0xfff, 0xfff, 0xfff, 0xfff, 0x47f, 0xfff, 0xfff,
565 0x43a, 0x265, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e8,
566 0xfff, 0xfff, 0x01a, 0xfff, 0xfff, 0xfff, 0xfff, 0x21e,
567 0x1fc, 0x40b, 0xfff, 0xfff, 0xfff, 0x2d0, 0x159, 0xfff,
568 0xfff, 0x313, 0xfff, 0xfff, 0x05c, 0x4cc, 0xfff, 0xfff,
569 0x0f6, 0x3d5, 0xfff, 0xfff, 0xfff, 0x54f, 0xfff, 0xfff,
570 0xfff, 0x172, 0x1e4, 0x07c, 0xfff, 0xfff, 0xfff, 0xfff,
571 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x53c, 0x1ad, 0x535,
572 0x19b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
573 0xfff, 0xfff, 0x092, 0xfff, 0x2be, 0xfff, 0xfff, 0x482,
574 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0e6, 0xfff, 0xfff,
575 0xfff, 0xfff, 0xfff, 0x476, 0xfff, 0x51d, 0xfff, 0xfff,
576 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
577 0xfff, 0xfff, 0x342, 0x2b5, 0x22e, 0x09a, 0xfff, 0x08d,
578 0x44f, 0x3ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d1, 0xfff,
579 0xfff, 0x543, 0xfff, 0x48f, 0xfff, 0x3d2, 0xfff, 0x0d5,
580 0x113, 0x0ec, 0x427, 0xfff, 0xfff, 0xfff, 0x4c4, 0xfff,
581 0xfff, 0x50a, 0xfff, 0x144, 0xfff, 0x105, 0x39f, 0x294,
582 0x164, 0xfff, 0x31a, 0xfff, 0xfff, 0x49a, 0xfff, 0x130,
583 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
584 0x1be, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
585 0xfff, 0xfff, 0x49e, 0x371, 0xfff, 0xfff, 0xfff, 0xfff,
586 0xfff, 0xfff, 0xfff, 0xfff, 0x0e8, 0x49c, 0x0f4, 0xfff,
587 0x338, 0x1a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
588 0xfff, 0x36c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
589 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
590 0xfff, 0x1ae, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
591 0xfff, 0x31b, 0xfff, 0xfff, 0x2dd, 0x522, 0xfff, 0xfff,
592 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f4,
593 0x3c6, 0x30d, 0xfff, 0xfff, 0xfff, 0xfff, 0x34c, 0x18f,
594 0x30a, 0xfff, 0x01f, 0x079, 0xfff, 0xfff, 0x54d, 0x46b,
595 0x28c, 0x37f, 0xfff, 0xfff, 0xfff, 0xfff, 0x355, 0xfff,
596 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x14f, 0xfff, 0xfff,
597 0xfff, 0xfff, 0xfff, 0x359, 0x3fe, 0x3c5, 0xfff, 0xfff,
598 0xfff, 0xfff, 0x423, 0xfff, 0xfff, 0x34a, 0x22c, 0xfff,
599 0x25a, 0xfff, 0xfff, 0x4ad, 0xfff, 0x28d, 0xfff, 0xfff,
600 0xfff, 0xfff, 0xfff, 0x547, 0xfff, 0xfff, 0xfff, 0xfff,
601 0x2e2, 0xfff, 0xfff, 0x1d5, 0xfff, 0x2a8, 0xfff, 0xfff,
602 0x03f, 0xfff, 0xfff, 0xfff, 0xfff, 0x3eb, 0x0fa, 0xfff,
603 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x55b, 0xfff,
604 0x08e, 0xfff, 0x3ae, 0xfff, 0x3a4, 0xfff, 0x282, 0x158,
605 0xfff, 0x382, 0xfff, 0xfff, 0x499, 0xfff, 0xfff, 0x08a,
606 0xfff, 0xfff, 0xfff, 0x456, 0x3be, 0xfff, 0x1e2, 0xfff,
607 0xfff, 0xfff, 0xfff, 0xfff, 0x559, 0xfff, 0x1a0, 0xfff,
608 0xfff, 0x0b4, 0xfff, 0xfff, 0xfff, 0x2df, 0xfff, 0xfff,
609 0xfff, 0x07f, 0x4f5, 0xfff, 0xfff, 0x27c, 0x133, 0x017,
610 0xfff, 0x3fd, 0xfff, 0xfff, 0xfff, 0x44d, 0x4cd, 0x17a,
611 0x0d7, 0x537, 0xfff, 0xfff, 0x353, 0xfff, 0xfff, 0x351,
612 0x366, 0xfff, 0x44a, 0xfff, 0x1a6, 0xfff, 0xfff, 0xfff,
613 0x291, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1e3,
614 0xfff, 0xfff, 0xfff, 0xfff, 0x389, 0xfff, 0x07a, 0xfff,
615 0x1b6, 0x2ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x24e, 0x074,
616 0xfff, 0xfff, 0x3dc, 0xfff, 0x4e3, 0xfff, 0xfff, 0xfff,
617 0xfff, 0x4eb, 0xfff, 0xfff, 0x3b8, 0x4de, 0xfff, 0x19c,
618 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x262,
619 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x076, 0x4e8, 0x3da,
620 0xfff, 0x531, 0xfff, 0xfff, 0x14a, 0xfff, 0x0a2, 0x433,
621 0x3df, 0x1e9, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e7, 0x285,
622 0x2d8, 0xfff, 0xfff, 0xfff, 0x349, 0x18d, 0x098, 0xfff,
623 0x0df, 0x4bf, 0xfff, 0xfff, 0x0b2, 0xfff, 0x346, 0x24d,
624 0xfff, 0xfff, 0xfff, 0x24f, 0x4fa, 0x2f9, 0xfff, 0xfff,
625 0x3c9, 0xfff, 0x2b4, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
626 0xfff, 0x056, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
627 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
628 0xfff, 0x179, 0xfff, 0x0e9, 0x3f0, 0x33d, 0xfff, 0xfff,
629 0xfff, 0xfff, 0xfff, 0x1fd, 0xfff, 0xfff, 0x526, 0xfff,
630 0xfff, 0xfff, 0x53d, 0xfff, 0xfff, 0xfff, 0x170, 0x331,
631 0xfff, 0x068, 0xfff, 0xfff, 0xfff, 0x3f7, 0xfff, 0x3d8,
632 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
633 0xfff, 0x09f, 0x556, 0xfff, 0xfff, 0x02d, 0xfff, 0xfff,
634 0x553, 0xfff, 0xfff, 0xfff, 0x1f0, 0xfff, 0xfff, 0x4d6,
635 0x41e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d5, 0xfff, 0xfff,
636 0xfff, 0xfff, 0xfff, 0x248, 0xfff, 0xfff, 0xfff, 0x0a3,
637 0xfff, 0x217, 0xfff, 0xfff, 0xfff, 0x4f1, 0x209, 0xfff,
638 0xfff, 0x475, 0x234, 0x52b, 0x398, 0xfff, 0x08b, 0xfff,
639 0xfff, 0xfff, 0xfff, 0x2c2, 0xfff, 0xfff, 0xfff, 0xfff,
640 0xfff, 0xfff, 0x268, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
641 0xfff, 0x4a3, 0xfff, 0x0aa, 0xfff, 0x1d9, 0xfff, 0xfff,
642 0xfff, 0xfff, 0x155, 0xfff, 0xfff, 0xfff, 0xfff, 0x0bf,
643 0x539, 0xfff, 0xfff, 0x2f1, 0x545, 0xfff, 0xfff, 0xfff,
644 0xfff, 0xfff, 0xfff, 0x2a7, 0x06f, 0xfff, 0x378, 0xfff,
645 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x25e, 0xfff,
646 0xfff, 0xfff, 0xfff, 0x15d, 0x02a, 0xfff, 0xfff, 0x0bc,
647 0x235, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
648 0x150, 0xfff, 0x1a9, 0xfff, 0xfff, 0xfff, 0xfff, 0x381,
649 0xfff, 0x04e, 0x270, 0x13f, 0xfff, 0xfff, 0x405, 0xfff,
650 0x3cd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
651 0xfff, 0x2ef, 0xfff, 0x06a, 0xfff, 0xfff, 0xfff, 0x34f,
652 0x212, 0xfff, 0xfff, 0x0e2, 0xfff, 0x083, 0x298, 0xfff,
653 0xfff, 0xfff, 0x0c2, 0xfff, 0xfff, 0x52e, 0xfff, 0x488,
654 0xfff, 0xfff, 0xfff, 0x36b, 0xfff, 0xfff, 0xfff, 0x442,
655 0x091, 0xfff, 0x41c, 0xfff, 0xfff, 0x3a5, 0xfff, 0x4e6,
656 0xfff, 0xfff, 0x40d, 0x31d, 0xfff, 0xfff, 0xfff, 0x4c1,
657 0x053, 0xfff, 0x418, 0x13c, 0xfff, 0x350, 0xfff, 0x0ae,
658 0xfff, 0xfff, 0x41f, 0xfff, 0x470, 0xfff, 0x4ca, 0xfff,
659 0xfff, 0xfff, 0x02b, 0x450, 0xfff, 0x1f8, 0xfff, 0xfff,
660 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x293, 0xfff,
661 0xfff, 0xfff, 0xfff, 0x411, 0xfff, 0xfff, 0xfff, 0xfff,
662 0xfff, 0xfff, 0xfff, 0xfff, 0x0b8, 0xfff, 0xfff, 0xfff,
663 0x3e1, 0xfff, 0xfff, 0xfff, 0xfff, 0x43c, 0xfff, 0x2b2,
664 0x2ab, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ec,
665 0xfff, 0xfff, 0xfff, 0x3f8, 0x034, 0xfff, 0xfff, 0xfff,
666 0xfff, 0xfff, 0xfff, 0x11a, 0xfff, 0x541, 0x45c, 0x134,
667 0x1cc, 0xfff, 0xfff, 0xfff, 0x469, 0xfff, 0xfff, 0x44b,
668 0x161, 0xfff, 0xfff, 0xfff, 0x055, 0xfff, 0xfff, 0xfff,
669 0xfff, 0x307, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d1, 0xfff,
670 0xfff, 0xfff, 0x124, 0x37b, 0x26b, 0x336, 0xfff, 0xfff,
671 0x2e4, 0x3cb, 0xfff, 0xfff, 0x0f8, 0x3c8, 0xfff, 0xfff,
672 0xfff, 0x461, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4b5,
673 0x2cf, 0xfff, 0xfff, 0xfff, 0x20f, 0xfff, 0x35a, 0xfff,
674 0x490, 0xfff, 0x185, 0xfff, 0xfff, 0xfff, 0xfff, 0x42e,
675 0xfff, 0xfff, 0xfff, 0xfff, 0x54b, 0xfff, 0xfff, 0xfff,
676 0x146, 0xfff, 0x412, 0xfff, 0xfff, 0xfff, 0x1ff, 0xfff,
677 0xfff, 0x3e0, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d5, 0xfff,
678 0x4df, 0x505, 0xfff, 0x413, 0xfff, 0x1a5, 0xfff, 0x3b2,
679 0xfff, 0xfff, 0xfff, 0x35b, 0xfff, 0x116, 0xfff, 0xfff,
680 0x171, 0x4d0, 0xfff, 0x154, 0x12d, 0xfff, 0xfff, 0xfff,
681 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x468, 0x4db, 0xfff,
682 0xfff, 0x1df, 0xfff, 0xfff, 0xfff, 0xfff, 0x05a, 0xfff,
683 0x0f1, 0x403, 0xfff, 0x22b, 0x2e0, 0xfff, 0xfff, 0xfff,
684 0x2b7, 0x373, 0xfff, 0xfff, 0xfff, 0xfff, 0x13e, 0xfff,
685 0xfff, 0xfff, 0x0d0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
686 0x329, 0x1d2, 0x3fa, 0x047, 0xfff, 0x2f2, 0xfff, 0xfff,
687 0x141, 0x0ac, 0x1d7, 0xfff, 0x07d, 0xfff, 0xfff, 0xfff,
688 0x1c1, 0xfff, 0x487, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
689 0xfff, 0xfff, 0xfff, 0x045, 0xfff, 0xfff, 0xfff, 0xfff,
690 0x288, 0x0cd, 0xfff, 0xfff, 0xfff, 0xfff, 0x226, 0x1d8,
691 0xfff, 0x153, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4cb,
692 0x528, 0xfff, 0xfff, 0xfff, 0x20a, 0x343, 0x3a1, 0xfff,
693 0xfff, 0xfff, 0x2d7, 0x2d3, 0x1aa, 0x4c5, 0xfff, 0xfff,
694 0xfff, 0x42b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
695 0xfff, 0xfff, 0xfff, 0xfff, 0x3e9, 0xfff, 0x20b, 0x260,
696 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x37c, 0x2fd,
697 0xfff, 0xfff, 0x2c8, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
698 0xfff, 0x31e, 0xfff, 0x335, 0xfff, 0xfff, 0xfff, 0xfff,
699 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
700 0xfff, 0xfff, 0x135, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
701 0xfff, 0xfff, 0x35c, 0x4dd, 0x129, 0xfff, 0xfff, 0xfff,
702 0xfff, 0xfff, 0x1ef, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
703 0xfff, 0x34e, 0xfff, 0xfff, 0xfff, 0xfff, 0x407, 0xfff,
704 0xfff, 0xfff, 0xfff, 0xfff, 0x3ad, 0xfff, 0xfff, 0xfff,
705 0x379, 0xfff, 0xfff, 0x1d0, 0x38d, 0xfff, 0xfff, 0x1e8,
706 0x184, 0x3c1, 0x1c4, 0xfff, 0x1f9, 0xfff, 0xfff, 0x424,
707 0xfff, 0xfff, 0xfff, 0xfff, 0x1d3, 0x0d4, 0xfff, 0x4e9,
708 0xfff, 0xfff, 0xfff, 0x530, 0x107, 0xfff, 0x106, 0x04f,
709 0xfff, 0xfff, 0x4c7, 0x503, 0xfff, 0xfff, 0xfff, 0xfff,
710 0xfff, 0x15c, 0xfff, 0x23f, 0xfff, 0xfff, 0xfff, 0xfff,
711 0xfff, 0xfff, 0xfff, 0xfff, 0x4f3, 0xfff, 0xfff, 0x3c7,
712 0xfff, 0x278, 0xfff, 0xfff, 0x0a6, 0xfff, 0xfff, 0xfff,
713 0x122, 0x1cf, 0xfff, 0x327, 0xfff, 0x2e5, 0xfff, 0x29d,
714 0xfff, 0xfff, 0x3f1, 0xfff, 0xfff, 0x48d, 0xfff, 0xfff,
715 0xfff, 0xfff, 0x054, 0xfff, 0xfff, 0xfff, 0xfff, 0x178,
716 0x27e, 0x4e0, 0x352, 0x02f, 0x09c, 0xfff, 0x2a0, 0xfff,
717 0xfff, 0x46a, 0x457, 0xfff, 0xfff, 0x501, 0xfff, 0x2ba,
718 0xfff, 0xfff, 0xfff, 0x54e, 0x2e7, 0xfff, 0xfff, 0xfff,
719 0xfff, 0xfff, 0x551, 0xfff, 0xfff, 0x1db, 0x2aa, 0xfff,
720 0xfff, 0x4bc, 0xfff, 0xfff, 0x395, 0xfff, 0x0de, 0xfff,
721 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x455, 0xfff, 0x17e,
722 0xfff, 0x221, 0x4a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
723 0x388, 0xfff, 0xfff, 0xfff, 0x308, 0xfff, 0xfff, 0xfff,
724 0x20e, 0x4b9, 0xfff, 0x273, 0x20c, 0x09e, 0xfff, 0x057,
725 0xfff, 0xfff, 0xfff, 0xfff, 0x3f2, 0xfff, 0x1a8, 0x3a6,
726 0x14c, 0xfff, 0xfff, 0x071, 0xfff, 0xfff, 0x53a, 0xfff,
727 0xfff, 0xfff, 0xfff, 0x109, 0xfff, 0xfff, 0x399, 0xfff,
728 0x061, 0x4f0, 0x39e, 0x244, 0xfff, 0x035, 0xfff, 0xfff,
729 0x305, 0x47e, 0x297, 0xfff, 0xfff, 0x2b8, 0xfff, 0xfff,
730 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1bc, 0xfff, 0x2fc,
731 0xfff, 0xfff, 0x554, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b6,
732 0xfff, 0xfff, 0xfff, 0x515, 0x397, 0xfff, 0xfff, 0x12f,
733 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e5,
734 0xfff, 0x4fc, 0xfff, 0xfff, 0x05e, 0xfff, 0xfff, 0xfff,
735 0xfff, 0xfff, 0x0a8, 0x3af, 0x015, 0xfff, 0xfff, 0xfff,
736 0xfff, 0x138, 0xfff, 0xfff, 0xfff, 0x540, 0xfff, 0xfff,
737 0xfff, 0x027, 0x523, 0x2f0, 0xfff, 0xfff, 0xfff, 0xfff,
738 0xfff, 0xfff, 0x16c, 0xfff, 0x27d, 0xfff, 0xfff, 0xfff,
739 0xfff, 0x04c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4dc,
740 0xfff, 0xfff, 0x059, 0x301, 0xfff, 0xfff, 0xfff, 0xfff,
741 0xfff, 0xfff, 0xfff, 0x1a3, 0xfff, 0x15a, 0xfff, 0xfff,
742 0x0a5, 0xfff, 0x435, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
743 0xfff, 0x051, 0xfff, 0xfff, 0x131, 0xfff, 0x4f4, 0xfff,
744 0xfff, 0xfff, 0xfff, 0x441, 0xfff, 0x4fb, 0xfff, 0x03b,
745 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ed, 0x274,
746 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d3, 0x55e, 0x1b3,
747 0xfff, 0x0bd, 0xfff, 0xfff, 0xfff, 0xfff, 0x225, 0xfff,
748 0xfff, 0xfff, 0xfff, 0xfff, 0x4b7, 0xfff, 0xfff, 0x2ff,
749 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c3, 0xfff,
750 0x383, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f6,
751 0xfff, 0xfff, 0x1ee, 0xfff, 0x03d, 0xfff, 0xfff, 0xfff,
752 0xfff, 0xfff, 0x26f, 0x1dc, 0xfff, 0x0db, 0xfff, 0xfff,
753 0xfff, 0xfff, 0xfff, 0x0ce, 0xfff, 0xfff, 0x127, 0x03a,
754 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x311, 0xfff,
755 0xfff, 0x13d, 0x09d, 0x47b, 0x2a6, 0x50d, 0x510, 0x19a,
756 0xfff, 0x354, 0x414, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
757 0xfff, 0xfff, 0x44c, 0x3b0, 0xfff, 0x23d, 0x429, 0xfff,
758 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
759 0x4c0, 0x416, 0xfff, 0x05b, 0xfff, 0xfff, 0x137, 0xfff,
760 0x25f, 0x49f, 0xfff, 0x279, 0x013, 0xfff, 0xfff, 0xfff,
761 0x269, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
762 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d0, 0xfff, 0xfff,
763 0xfff, 0xfff, 0xfff, 0xfff, 0x077, 0xfff, 0xfff, 0x3fb,
764 0xfff, 0xfff, 0xfff, 0xfff, 0x271, 0x3a0, 0xfff, 0xfff,
765 0x40f, 0xfff, 0xfff, 0x3de, 0xfff, 0xfff, 0xfff, 0xfff,
766 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ab, 0x26a,
767 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x489, 0xfff, 0xfff,
768 0x252, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b7, 0x42f, 0xfff,
769 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b7,
770 0xfff, 0x2bb, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
771 0xfff, 0xfff, 0xfff, 0x0f7, 0x01d, 0xfff, 0x067, 0xfff,
772 0xfff, 0xfff, 0xfff, 0x4e2, 0xfff, 0xfff, 0x4bb, 0xfff,
773 0xfff, 0xfff, 0x17b, 0xfff, 0x0ee, 0xfff, 0xfff, 0xfff,
774 0xfff, 0xfff, 0x36e, 0xfff, 0xfff, 0xfff, 0x533, 0xfff,
775 0xfff, 0xfff, 0x4d4, 0x356, 0xfff, 0xfff, 0x375, 0xfff,
776 0xfff, 0xfff, 0xfff, 0x4a4, 0x513, 0xfff, 0xfff, 0xfff,
777 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4ff, 0xfff, 0x2af,
778 0xfff, 0xfff, 0x026, 0xfff, 0x0ad, 0xfff, 0xfff, 0xfff,
779 0xfff, 0x26e, 0xfff, 0xfff, 0xfff, 0xfff, 0x493, 0xfff,
780 0x463, 0x4d2, 0x4be, 0xfff, 0xfff, 0xfff, 0xfff, 0x4f2,
781 0x0b6, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
782 0xfff, 0x32d, 0x315, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
783 0xfff, 0x13a, 0x4a1, 0xfff, 0x27a, 0xfff, 0xfff, 0xfff,
784 0x47a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
785 0x334, 0xfff, 0xfff, 0xfff, 0xfff, 0x54c, 0xfff, 0xfff,
786 0xfff, 0x0c9, 0x007, 0xfff, 0xfff, 0x12e, 0xfff, 0x0ff,
787 0xfff, 0xfff, 0x3f5, 0x509, 0xfff, 0xfff, 0xfff, 0xfff,
788 0x1c3, 0x2ad, 0xfff, 0xfff, 0x47c, 0x261, 0xfff, 0xfff,
789 0xfff, 0xfff, 0xfff, 0x152, 0xfff, 0xfff, 0xfff, 0x339,
790 0xfff, 0x243, 0x1c0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
791 0x063, 0xfff, 0xfff, 0x254, 0xfff, 0xfff, 0x173, 0xfff,
792 0x0c7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
793 0xfff, 0x362, 0x259, 0x485, 0x374, 0x0dc, 0x3ab, 0xfff,
794 0x1c5, 0x534, 0x544, 0xfff, 0xfff, 0x508, 0xfff, 0x402,
795 0x408, 0xfff, 0x0e7, 0xfff, 0xfff, 0x00a, 0x205, 0xfff,
796 0xfff, 0x2b9, 0xfff, 0xfff, 0xfff, 0x465, 0xfff, 0xfff,
797 0xfff, 0xfff, 0xfff, 0xfff, 0x23a, 0xfff, 0xfff, 0xfff,
798 0xfff, 0x147, 0x19d, 0x115, 0x214, 0xfff, 0x090, 0x368,
799 0xfff, 0x210, 0xfff, 0xfff, 0x280, 0x52a, 0x163, 0x148,
800 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x326, 0xfff, 0xfff,
801 0xfff, 0xfff, 0xfff, 0x2de, 0xfff, 0xfff, 0xfff, 0xfff,
802 0x206, 0x2c1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
803 0x189, 0xfff, 0xfff, 0xfff, 0xfff, 0x367, 0xfff, 0x1a4,
804 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x443, 0xfff, 0x27b,
805 0xfff, 0xfff, 0x251, 0x549, 0xfff, 0xfff, 0xfff, 0xfff,
806 0xfff, 0xfff, 0x188, 0x04b, 0xfff, 0xfff, 0xfff, 0x31f,
807 0x4a6, 0xfff, 0x246, 0x1de, 0x156, 0xfff, 0xfff, 0xfff,
808 0x3a9, 0xfff, 0xfff, 0xfff, 0x2fa, 0xfff, 0x128, 0x0d1,
809 0x449, 0x255, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
810 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
811 0xfff, 0xfff, 0xfff, 0xfff, 0x258, 0xfff, 0xfff, 0xfff,
812 0x532, 0xfff, 0xfff, 0xfff, 0x303, 0x517, 0xfff, 0xfff,
813 0x2a9, 0x24a, 0xfff, 0xfff, 0x231, 0xfff, 0xfff, 0xfff,
814 0xfff, 0xfff, 0x4b6, 0x516, 0xfff, 0xfff, 0x0e4, 0x0eb,
815 0xfff, 0x4e4, 0xfff, 0x275, 0xfff, 0xfff, 0x031, 0xfff,
816 0xfff, 0xfff, 0xfff, 0xfff, 0x025, 0x21a, 0xfff, 0x0cc,
817 0x45f, 0x3d9, 0x289, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
818 0xfff, 0xfff, 0x23e, 0xfff, 0xfff, 0xfff, 0x438, 0x097,
819 0x419, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
820 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
821 0xfff, 0xfff, 0x0a9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
822 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
823 0x37e, 0x0e0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x431,
824 0x372, 0xfff, 0xfff, 0xfff, 0x1ba, 0x06e, 0xfff, 0x1b1,
825 0xfff, 0xfff, 0x12a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
826 0xfff, 0xfff, 0x193, 0xfff, 0xfff, 0xfff, 0xfff, 0x10a,
827 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x048, 0x1b4,
828 0xfff, 0xfff, 0xfff, 0xfff, 0x295, 0x140, 0x108, 0xfff,
829 0xfff, 0xfff, 0xfff, 0x16f, 0xfff, 0x0a4, 0x37a, 0xfff,
830 0x29a, 0xfff, 0x284, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c6,
831 0x2a2, 0x3a3, 0xfff, 0x201, 0xfff, 0xfff, 0xfff, 0x4bd,
832 0x005, 0x54a, 0x3b5, 0x204, 0x2ee, 0x11d, 0x436, 0xfff,
833 0xfff, 0xfff, 0xfff, 0xfff, 0x3ec, 0xfff, 0xfff, 0xfff,
834 0xfff, 0xfff, 0xfff, 0xfff, 0x11f, 0x498, 0x21c, 0xfff,
835 0xfff, 0xfff, 0x3d6, 0xfff, 0x4ab, 0xfff, 0x432, 0x2eb,
836 0x542, 0x4fd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
837 0xfff, 0xfff, 0xfff, 0x4ce, 0xfff, 0xfff, 0x2fb, 0xfff,
838 0xfff, 0x2e1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
839 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b9, 0x037, 0x0dd,
840 0xfff, 0xfff, 0xfff, 0x2bf, 0x521, 0x496, 0x095, 0xfff,
841 0xfff, 0x328, 0x070, 0x1bf, 0xfff, 0x393, 0xfff, 0xfff,
842 0x102, 0xfff, 0xfff, 0x21b, 0xfff, 0x142, 0x263, 0x519,
843 0xfff, 0x2a5, 0x177, 0xfff, 0x14d, 0x471, 0x4ae, 0xfff,
844 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
845 0x1f6, 0xfff, 0x481, 0xfff, 0xfff, 0xfff, 0x151, 0xfff,
846 0xfff, 0xfff, 0x085, 0x33f, 0xfff, 0xfff, 0xfff, 0x084,
847 0xfff, 0xfff, 0xfff, 0x345, 0x3a2, 0xfff, 0xfff, 0x0a0,
848 0x0da, 0x024, 0xfff, 0xfff, 0xfff, 0x1bd, 0xfff, 0x55c,
849 0x467, 0x445, 0xfff, 0xfff, 0xfff, 0x052, 0xfff, 0xfff,
850 0xfff, 0xfff, 0x51e, 0xfff, 0xfff, 0x39d, 0xfff, 0x35f,
851 0xfff, 0x376, 0x3ee, 0xfff, 0xfff, 0xfff, 0xfff, 0x448,
852 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x16a,
853 0xfff, 0x036, 0x38f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
854 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x211,
855 0xfff, 0xfff, 0xfff, 0x230, 0xfff, 0xfff, 0x3ba, 0xfff,
856 0xfff, 0xfff, 0x3ce, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
857 0xfff, 0xfff, 0xfff, 0x229, 0xfff, 0x176, 0xfff, 0xfff,
858 0xfff, 0xfff, 0xfff, 0x00b, 0xfff, 0x162, 0x018, 0xfff,
859 0xfff, 0x233, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
860 0x400, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
861 0xfff, 0xfff, 0xfff, 0x12b, 0xfff, 0xfff, 0xfff, 0xfff,
862 0xfff, 0x3f4, 0xfff, 0x0f0, 0xfff, 0x1ac, 0xfff, 0xfff,
863 0x119, 0xfff, 0x2c0, 0xfff, 0xfff, 0xfff, 0x49b, 0xfff,
864 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x23c, 0xfff,
865 0x4b3, 0x010, 0x064, 0xfff, 0xfff, 0x4ba, 0xfff, 0xfff,
866 0xfff, 0xfff, 0xfff, 0x3c2, 0xfff, 0xfff, 0xfff, 0xfff,
867 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x006, 0x196, 0xfff,
868 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x100, 0x191, 0xfff,
869 0x1ea, 0x29f, 0xfff, 0xfff, 0xfff, 0x276, 0xfff, 0xfff,
870 0x2b1, 0x3b9, 0xfff, 0x03c, 0xfff, 0xfff, 0xfff, 0x180,
871 0xfff, 0x08f, 0xfff, 0xfff, 0x19e, 0x019, 0xfff, 0x0b0,
872 0x0fd, 0x332, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
873 0xfff, 0x06b, 0x2e8, 0xfff, 0x446, 0xfff, 0xfff, 0x004,
874 0x247, 0x197, 0xfff, 0x112, 0x169, 0x292, 0xfff, 0x302,
875 0xfff, 0xfff, 0x33b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
876 0xfff, 0xfff, 0xfff, 0x287, 0x21f, 0xfff, 0x3ea, 0xfff,
877 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e7, 0xfff, 0xfff,
878 0xfff, 0xfff, 0xfff, 0x3a8, 0xfff, 0xfff, 0x2bc, 0xfff,
879 0x484, 0x296, 0xfff, 0x1c9, 0x08c, 0x1e5, 0x48a, 0xfff,
880 0x360, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
881 0x1ca, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
882 0xfff, 0xfff, 0xfff, 0x10d, 0xfff, 0xfff, 0xfff, 0xfff,
883 0xfff, 0xfff, 0x066, 0x2ea, 0x28b, 0x25b, 0xfff, 0x072,
884 0xfff, 0xfff, 0xfff, 0xfff, 0x2b6, 0xfff, 0xfff, 0x272,
885 0xfff, 0xfff, 0x525, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
886 0x2ca, 0xfff, 0xfff, 0xfff, 0x299, 0xfff, 0xfff, 0xfff,
887 0x558, 0x41a, 0xfff, 0x4f7, 0x557, 0xfff, 0x4a0, 0x344,
888 0x12c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x125,
889 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
890 0x40e, 0xfff, 0xfff, 0x502, 0xfff, 0x103, 0x3e6, 0xfff,
891 0x527, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
892 0xfff, 0xfff, 0xfff, 0x45d, 0xfff, 0xfff, 0xfff, 0xfff,
893 0x44e, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d2, 0x4c9, 0x35e,
894 0x459, 0x2d9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x17d,
895 0x0c4, 0xfff, 0xfff, 0xfff, 0x3ac, 0x390, 0x094, 0xfff,
896 0x483, 0x0ab, 0xfff, 0x253, 0xfff, 0x391, 0xfff, 0xfff,
897 0xfff, 0xfff, 0x123, 0x0ef, 0xfff, 0xfff, 0xfff, 0x330,
898 0x38c, 0xfff, 0xfff, 0x2ae, 0xfff, 0xfff, 0xfff, 0x042,
899 0x012, 0x06d, 0xfff, 0xfff, 0xfff, 0x32a, 0x3db, 0x364,
900 0x2dc, 0xfff, 0x30f, 0x3d7, 0x4a5, 0x050, 0xfff, 0xfff,
901 0x029, 0xfff, 0xfff, 0xfff, 0xfff, 0x1d1, 0xfff, 0xfff,
902 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x480, 0xfff,
903 0x4ed, 0x081, 0x0a1, 0xfff, 0xfff, 0xfff, 0x30e, 0x52f,
904 0x257, 0xfff, 0xfff, 0x447, 0xfff, 0xfff, 0xfff, 0xfff,
905 0xfff, 0xfff, 0xfff, 0x401, 0x3cc, 0xfff, 0xfff, 0x0fb,
906 0x2c9, 0x42a, 0x314, 0x33e, 0x3bd, 0x318, 0xfff, 0x10e,
907 0x2a1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x24c,
908 0x506, 0xfff, 0x267, 0xfff, 0xfff, 0x219, 0xfff, 0x1eb,
909 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
910 0x309, 0x3e2, 0x46c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
911 0x384, 0xfff, 0xfff, 0xfff, 0xfff, 0x50c, 0xfff, 0x24b,
912 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x038,
913 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x194,
914 0x143, 0x3e3, 0xfff, 0xfff, 0xfff, 0x4c2, 0xfff, 0xfff,
915 0x0e1, 0x25c, 0xfff, 0x237, 0xfff, 0x1fe, 0xfff, 0xfff,
916 0xfff, 0x065, 0x2a4, 0xfff, 0x386, 0x55a, 0x11b, 0xfff,
917 0xfff, 0x192, 0xfff, 0x183, 0x00e, 0xfff, 0xfff, 0xfff,
918 0xfff, 0xfff, 0xfff, 0x4b2, 0x18e, 0xfff, 0xfff, 0xfff,
919 0xfff, 0x486, 0x4ef, 0x0c6, 0x380, 0xfff, 0x4a8, 0xfff,
920 0x0c5, 0xfff, 0xfff, 0xfff, 0xfff, 0x093, 0x1b8, 0xfff,
921 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e6,
922 0xfff, 0x0f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
923 0x28e, 0xfff, 0x53b, 0x420, 0x22a, 0x33a, 0xfff, 0x387,
924 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2a3, 0xfff, 0xfff,
925 0xfff, 0x428, 0x500, 0xfff, 0xfff, 0x120, 0x2c6, 0x290,
926 0x2f5, 0x0e3, 0xfff, 0x0b7, 0xfff, 0x319, 0x474, 0xfff,
927 0xfff, 0xfff, 0x529, 0x014, 0xfff, 0x41b, 0x40a, 0x18b,
928 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d9,
929 0xfff, 0x38a, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ce, 0xfff,
930 0xfff, 0xfff, 0xfff, 0xfff, 0x3b1, 0xfff, 0xfff, 0x05d,
931 0x2c4, 0xfff, 0xfff, 0x4af, 0xfff, 0x030, 0xfff, 0xfff,
932 0x203, 0xfff, 0x277, 0x256, 0xfff, 0xfff, 0xfff, 0x4f9,
933 0xfff, 0x2c7, 0xfff, 0x466, 0x016, 0x1cd, 0xfff, 0x167,
934 0xfff, 0xfff, 0x0c8, 0xfff, 0x43d, 0xfff, 0xfff, 0x020,
935 0xfff, 0xfff, 0x232, 0x1cb, 0x1e0, 0xfff, 0xfff, 0x347,
936 0xfff, 0x478, 0xfff, 0x365, 0xfff, 0xfff, 0xfff, 0xfff,
937 0x358, 0xfff, 0x10b, 0xfff, 0x35d, 0xfff, 0xfff, 0xfff,
938 0xfff, 0xfff, 0x452, 0x22d, 0xfff, 0xfff, 0x47d, 0xfff,
939 0x2f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x460, 0xfff,
940 0xfff, 0xfff, 0x50b, 0xfff, 0xfff, 0xfff, 0x2ec, 0xfff,
941 0xfff, 0xfff, 0xfff, 0xfff, 0x4b1, 0x422, 0xfff, 0xfff,
942 0xfff, 0x2d4, 0xfff, 0x239, 0xfff, 0xfff, 0xfff, 0x439,
943 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
944 0xfff, 0x491, 0x075, 0xfff, 0xfff, 0xfff, 0x06c, 0xfff,
945 0xfff, 0x0f9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
946 0xfff, 0x139, 0xfff, 0x4f6, 0xfff, 0xfff, 0x409, 0xfff,
947 0xfff, 0x15b, 0xfff, 0xfff, 0x348, 0xfff, 0xfff, 0xfff,
948 0xfff, 0x4a2, 0x49d, 0xfff, 0x033, 0x175, 0xfff, 0x039,
949 0xfff, 0x312, 0x40c, 0xfff, 0xfff, 0x325, 0xfff, 0xfff,
950 0xfff, 0xfff, 0xfff, 0xfff, 0x4aa, 0xfff, 0xfff, 0xfff,
951 0xfff, 0xfff, 0xfff, 0x165, 0x3bc, 0x48c, 0x310, 0x096,
952 0xfff, 0xfff, 0x250, 0x1a2, 0xfff, 0xfff, 0xfff, 0xfff,
953 0x20d, 0x2ac, 0xfff, 0xfff, 0x39b, 0xfff, 0x377, 0xfff,
954 0x512, 0x495, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
955 0xfff, 0xfff, 0xfff, 0xfff, 0x357, 0x4ea, 0xfff, 0xfff,
956 0xfff, 0xfff, 0x198, 0xfff, 0xfff, 0xfff, 0x434, 0x04a,
957 0xfff, 0xfff, 0xfff, 0xfff, 0x062, 0xfff, 0x1d6, 0x1c8,
958 0xfff, 0x1f3, 0x281, 0xfff, 0x462, 0xfff, 0xfff, 0xfff,
959 0x4b0, 0xfff, 0x207, 0xfff, 0xfff, 0xfff, 0xfff, 0x3dd,
960 0xfff, 0xfff, 0x55d, 0xfff, 0x552, 0x494, 0x1af, 0xfff,
961 0xfff, 0xfff, 0xfff, 0xfff, 0x227, 0xfff, 0xfff, 0x069,
962 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x43e,
963 0x0b5, 0xfff, 0x524, 0x2d2, 0xfff, 0xfff, 0xfff, 0x28f,
964 0xfff, 0x01b, 0x50e, 0xfff, 0xfff, 0x1bb, 0xfff, 0xfff,
965 0x41d, 0xfff, 0x32e, 0x48e, 0xfff, 0x1f7, 0x224, 0xfff,
966 0xfff, 0xfff, 0xfff, 0xfff, 0x394, 0xfff, 0xfff, 0xfff,
967 0xfff, 0x52c, 0xfff, 0xfff, 0xfff, 0x392, 0xfff, 0x1e7,
968 0xfff, 0xfff, 0x3f9, 0x3a7, 0xfff, 0x51f, 0xfff, 0x0bb,
969 0x118, 0x3ca, 0xfff, 0x1dd, 0xfff, 0x48b, 0xfff, 0xfff,
970 0xfff, 0xfff, 0x50f, 0xfff, 0x0d6, 0xfff, 0x1fa, 0xfff,
971 0x11e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d7, 0xfff, 0x078,
972 0x008, 0xfff, 0x25d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
973 0x032, 0x33c, 0xfff, 0x4d9, 0x160, 0xfff, 0xfff, 0x300,
974 0x0b1, 0xfff, 0x322, 0xfff, 0x4ec, 0xfff, 0xfff, 0x200,
975 0x00c, 0x369, 0x473, 0xfff, 0xfff, 0x32c, 0xfff, 0xfff,
976 0xfff, 0xfff, 0xfff, 0xfff, 0x53e, 0x3d4, 0x417, 0xfff,
977 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
978 0x34b, 0x001, 0x39a, 0x02c, 0xfff, 0xfff, 0x2ce, 0x00f,
979 0xfff, 0x0ba, 0xfff, 0xfff, 0xfff, 0xfff, 0x060, 0xfff,
980 0x406, 0xfff, 0xfff, 0xfff, 0x4ee, 0x4ac, 0xfff, 0x43f,
981 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x29b, 0xfff, 0xfff,
982 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x216,
983 0x190, 0xfff, 0x396, 0x464, 0xfff, 0xfff, 0x323, 0xfff,
984 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e9, 0xfff, 0x26d,
985 0x2cd, 0x040, 0xfff, 0xfff, 0xfff, 0xfff, 0x38b, 0x3c0,
986 0xfff, 0xfff, 0xfff, 0x1f2, 0xfff, 0x0ea, 0xfff, 0xfff,
987 0x472, 0xfff, 0x1fb, 0xfff, 0xfff, 0x0af, 0x27f, 0xfff,
988 0xfff, 0xfff, 0x479, 0x023, 0xfff, 0x0d8, 0x3b3, 0xfff,
989 0xfff, 0xfff, 0x121, 0xfff, 0xfff, 0x3bf, 0xfff, 0xfff,
990 0x16b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
991 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
992 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
993 0x45a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
994 0xfff, 0x0be, 0xfff, 0xfff, 0xfff, 0x111, 0xfff, 0x220,
995 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
996 0xfff, 0xfff, 0x09b, 0x218, 0xfff, 0x022, 0x202, 0xfff,
997 0x4c8, 0xfff, 0x0ed, 0xfff, 0xfff, 0x182, 0xfff, 0xfff,
998 0xfff, 0x17f, 0x213, 0xfff, 0x321, 0x36a, 0xfff, 0x086,
999 0xfff, 0xfff, 0xfff, 0x43b, 0x088, 0xfff, 0xfff, 0xfff,
1000 0xfff, 0x26c, 0xfff, 0x2f8, 0x3b4, 0xfff, 0xfff, 0xfff,
1001 0x132, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x333, 0x444,
1002 0x0c1, 0x4d8, 0x46d, 0x264, 0xfff, 0xfff, 0xfff, 0xfff,
1003 0x426, 0xfff, 0xfff, 0xfff, 0xfff, 0x2fe, 0xfff, 0xfff,
1004 0xfff, 0xfff, 0x011, 0xfff, 0x05f, 0xfff, 0xfff, 0xfff,
1005 0xfff, 0x10c, 0x101, 0xfff, 0xfff, 0xfff, 0xfff, 0x110,
1006 0xfff, 0x044, 0x304, 0x361, 0x404, 0xfff, 0x51b, 0x099,
1007 0xfff, 0x440, 0xfff, 0xfff, 0xfff, 0x222, 0xfff, 0xfff,
1008 0xfff, 0xfff, 0x1b5, 0xfff, 0x136, 0x430, 0xfff, 0x1da,
1009 0xfff, 0xfff, 0xfff, 0x043, 0xfff, 0x17c, 0xfff, 0xfff,
1010 0xfff, 0x01c, 0xfff, 0xfff, 0xfff, 0x425, 0x236, 0xfff,
1011 0x317, 0xfff, 0xfff, 0x437, 0x3fc, 0xfff, 0x1f1, 0xfff,
1012 0x324, 0xfff, 0xfff, 0x0ca, 0x306, 0xfff, 0x548, 0xfff,
1013 0x46e, 0xfff, 0xfff, 0xfff, 0x4b8, 0x1c2, 0x286, 0xfff,
1014 0xfff, 0x087, 0x18a, 0x19f, 0xfff, 0xfff, 0xfff, 0xfff,
1015 0x18c, 0xfff, 0x215, 0xfff, 0xfff, 0xfff, 0xfff, 0x283,
1016 0xfff, 0xfff, 0xfff, 0x126, 0xfff, 0xfff, 0x370, 0xfff,
1017 0x53f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x31c, 0xfff,
1018 0x4d1, 0xfff, 0xfff, 0xfff, 0x021, 0xfff, 0x157, 0xfff,
1019 0xfff, 0x028, 0x16e, 0xfff, 0x421, 0xfff, 0x1c6, 0xfff,
1020 0xfff, 0x511, 0xfff, 0xfff, 0x39c, 0x46f, 0x1b2, 0xfff,
1021 0xfff, 0x316, 0xfff, 0xfff, 0x009, 0xfff, 0xfff, 0x195,
1022 0xfff, 0x240, 0x546, 0xfff, 0xfff, 0x520, 0xfff, 0xfff,
1023 0xfff, 0xfff, 0xfff, 0xfff, 0x454, 0xfff, 0xfff, 0xfff,
1024 0x3f3, 0xfff, 0xfff, 0x187, 0xfff, 0x4a9, 0xfff, 0xfff,
1025 0xfff, 0xfff, 0xfff, 0xfff, 0x51c, 0x453, 0x1e6, 0xfff,
1026 0xfff, 0xfff, 0x1b0, 0xfff, 0x477, 0xfff, 0xfff, 0xfff,
1027 0x4fe, 0xfff, 0x32f, 0xfff, 0xfff, 0x15e, 0x1d4, 0xfff,
1028 0x0e5, 0xfff, 0xfff, 0xfff, 0x242, 0x14b, 0x046, 0xfff,
1029 0x3f6, 0x3bb, 0x3e4, 0xfff, 0xfff, 0x2e3, 0xfff, 0x245,
1030 0xfff, 0x149, 0xfff, 0xfff, 0xfff, 0x2db, 0xfff, 0xfff,
1031 0x181, 0xfff, 0x089, 0x2c5, 0xfff, 0x1f5, 0xfff, 0x2d6,
1032 0x507, 0xfff, 0x42d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
1033 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
1034 0x080, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
1035 0xfff, 0xfff, 0xfff, 0xfff, 0x3c3, 0x320, 0xfff, 0x1e1,
1036 0xfff, 0x0f5, 0x13b, 0xfff, 0xfff, 0xfff, 0x003, 0x4da,
1037 0xfff, 0xfff, 0xfff, 0x42c, 0xfff, 0xfff, 0x0cb, 0xfff,
1038 0x536, 0x2c3, 0xfff, 0xfff, 0xfff, 0xfff, 0x199, 0xfff,
1039 0xfff, 0x0c0, 0xfff, 0x01e, 0x497, 0xfff, 0xfff, 0x3e5,
1040 0xfff, 0xfff, 0xfff, 0x0cf, 0xfff, 0x2bd, 0xfff, 0x223,
1041 0xfff, 0x3ff, 0xfff, 0x058, 0x174, 0x3ef, 0xfff, 0x002
1042};
1043
1044static unsigned short err_pos(unsigned short din)
1045{
1046 BUG_ON(din > 4096);
1047 BUG_ON(err_pos_lut[din] == 0xfff);
1048 return err_pos_lut[din];
1049}
1050static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
1051{
1052 if ((chk_syndrome_list[0] | chk_syndrome_list[1] |
1053 chk_syndrome_list[2] | chk_syndrome_list[3] |
1054 chk_syndrome_list[4] | chk_syndrome_list[5] |
1055 chk_syndrome_list[6] | chk_syndrome_list[7]) != 0x0) {
1056 return -EINVAL;
1057 } else {
1058 err_info[0] = 0x0;
1059 return 0;
1060 }
1061}
1062static int chk_1_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
1063{
1064 unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
1065 tmp0 = gf4096_mul(chk_syndrome_list[1], gf4096_inv(chk_syndrome_list[0]));
1066 tmp1 = gf4096_mul(chk_syndrome_list[2], gf4096_inv(chk_syndrome_list[1]));
1067 tmp2 = gf4096_mul(chk_syndrome_list[3], gf4096_inv(chk_syndrome_list[2]));
1068 tmp3 = gf4096_mul(chk_syndrome_list[4], gf4096_inv(chk_syndrome_list[3]));
1069 tmp4 = gf4096_mul(chk_syndrome_list[5], gf4096_inv(chk_syndrome_list[4]));
1070 tmp5 = gf4096_mul(chk_syndrome_list[6], gf4096_inv(chk_syndrome_list[5]));
1071 tmp6 = gf4096_mul(chk_syndrome_list[7], gf4096_inv(chk_syndrome_list[6]));
1072 if ((tmp0 == tmp1) & (tmp1 == tmp2) & (tmp2 == tmp3) & (tmp3 == tmp4) & (tmp4 == tmp5) & (tmp5 == tmp6)) {
1073 err_info[0] = 0x1; // encode 1-symbol error as 0x1
1074 err_info[1] = err_pos(tmp0);
1075 err_info[1] = (unsigned short)(0x55e - err_info[1]);
1076 err_info[5] = chk_syndrome_list[0];
1077 return 0;
1078 } else
1079 return -EINVAL;
1080}
1081static int chk_2_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
1082{
1083 unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
1084 unsigned short coefs[4];
1085 unsigned short err_pats[4];
1086 int found_num_root = 0;
1087 unsigned short bit2_root0, bit2_root1;
1088 unsigned short bit2_root0_inv, bit2_root1_inv;
1089 unsigned short err_loc_eqn, test_root;
1090 unsigned short bit2_loc0, bit2_loc1;
1091 unsigned short bit2_pat0, bit2_pat1;
1092
1093 find_2x2_soln(chk_syndrome_list[1],
1094 chk_syndrome_list[0],
1095 chk_syndrome_list[2], chk_syndrome_list[1], chk_syndrome_list[2], chk_syndrome_list[3], coefs);
1096 for (test_root = 0x1; test_root < 0xfff; test_root++) {
1097 err_loc_eqn =
1098 gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) ^ 0x1;
1099 if (err_loc_eqn == 0x0) {
1100 if (found_num_root == 0) {
1101 bit2_root0 = test_root;
1102 found_num_root = 1;
1103 } else if (found_num_root == 1) {
1104 bit2_root1 = test_root;
1105 found_num_root = 2;
1106 break;
1107 }
1108 }
1109 }
1110 if (found_num_root != 2)
1111 return -EINVAL;
1112 else {
1113 bit2_root0_inv = gf4096_inv(bit2_root0);
1114 bit2_root1_inv = gf4096_inv(bit2_root1);
1115 find_2bit_err_pats(chk_syndrome_list[0],
1116 chk_syndrome_list[1], bit2_root0_inv, bit2_root1_inv, err_pats);
1117 bit2_pat0 = err_pats[0];
1118 bit2_pat1 = err_pats[1];
1119 //for(x+1)
1120 tmp0 = gf4096_mul(gf4096_mul(bit2_root0_inv, bit2_root0_inv), gf4096_mul(bit2_root0_inv, bit2_root0_inv)); //rinv0^4
1121 tmp1 = gf4096_mul(bit2_root0_inv, tmp0); //rinv0^5
1122 tmp2 = gf4096_mul(bit2_root0_inv, tmp1); //rinv0^6
1123 tmp3 = gf4096_mul(bit2_root0_inv, tmp2); //rinv0^7
1124 tmp4 = gf4096_mul(gf4096_mul(bit2_root1_inv, bit2_root1_inv), gf4096_mul(bit2_root1_inv, bit2_root1_inv)); //rinv1^4
1125 tmp5 = gf4096_mul(bit2_root1_inv, tmp4); //rinv1^5
1126 tmp6 = gf4096_mul(bit2_root1_inv, tmp5); //rinv1^6
1127 tmp7 = gf4096_mul(bit2_root1_inv, tmp6); //rinv1^7
1128 //check if only 2-bit error
1129 if ((chk_syndrome_list[4] ==
1130 (gf4096_mul(bit2_pat0, tmp0) ^
1131 gf4096_mul(bit2_pat1,
1132 tmp4))) & (chk_syndrome_list[5] ==
1133 (gf4096_mul(bit2_pat0, tmp1) ^
1134 gf4096_mul(bit2_pat1,
1135 tmp5))) &
1136 (chk_syndrome_list[6] ==
1137 (gf4096_mul(bit2_pat0, tmp2) ^
1138 gf4096_mul(bit2_pat1,
1139 tmp6))) & (chk_syndrome_list[7] ==
1140 (gf4096_mul(bit2_pat0, tmp3) ^ gf4096_mul(bit2_pat1, tmp7)))) {
1141 if ((err_pos(bit2_root0_inv) == 0xfff) | (err_pos(bit2_root1_inv) == 0xfff)) {
1142 return -EINVAL;
1143 } else {
1144 bit2_loc0 = 0x55e - err_pos(bit2_root0_inv);
1145 bit2_loc1 = 0x55e - err_pos(bit2_root1_inv);
1146 err_info[0] = 0x2; // encode 2-symbol error as 0x2
1147 err_info[1] = bit2_loc0;
1148 err_info[2] = bit2_loc1;
1149 err_info[5] = bit2_pat0;
1150 err_info[6] = bit2_pat1;
1151 return 0;
1152 }
1153 } else
1154 return -EINVAL;
1155 }
1156}
1157static int chk_3_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
1158{
1159 unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
1160 unsigned short coefs[4];
1161 unsigned short err_pats[4];
1162 int found_num_root = 0;
1163 unsigned short bit3_root0, bit3_root1, bit3_root2;
1164 unsigned short bit3_root0_inv, bit3_root1_inv, bit3_root2_inv;
1165 unsigned short err_loc_eqn, test_root;
1166
1167 find_3bit_err_coefs(chk_syndrome_list[0], chk_syndrome_list[1],
1168 chk_syndrome_list[2], chk_syndrome_list[3],
1169 chk_syndrome_list[4], chk_syndrome_list[5], coefs);
1170
1171 for (test_root = 0x1; test_root < 0xfff; test_root++) {
1172 err_loc_eqn = gf4096_mul(coefs[2],
1173 gf4096_mul(gf4096_mul(test_root, test_root),
1174 test_root)) ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root))
1175 ^ gf4096_mul(coefs[0], test_root) ^ 0x1;
1176
1177 if (err_loc_eqn == 0x0) {
1178 if (found_num_root == 0) {
1179 bit3_root0 = test_root;
1180 found_num_root = 1;
1181 } else if (found_num_root == 1) {
1182 bit3_root1 = test_root;
1183 found_num_root = 2;
1184 } else if (found_num_root == 2) {
1185 bit3_root2 = test_root;
1186 found_num_root = 3;
1187 break;
1188 }
1189 }
1190 }
1191 if (found_num_root != 3)
1192 return -EINVAL;
1193 else {
1194 bit3_root0_inv = gf4096_inv(bit3_root0);
1195 bit3_root1_inv = gf4096_inv(bit3_root1);
1196 bit3_root2_inv = gf4096_inv(bit3_root2);
1197
1198 find_3bit_err_pats(chk_syndrome_list[0], chk_syndrome_list[1],
1199 chk_syndrome_list[2], bit3_root0_inv,
1200 bit3_root1_inv, bit3_root2_inv, err_pats);
1201
1202 //check if only 3-bit error
1203 tmp0 = gf4096_mul(bit3_root0_inv, bit3_root0_inv);
1204 tmp0 = gf4096_mul(tmp0, tmp0);
1205 tmp0 = gf4096_mul(tmp0, bit3_root0_inv);
1206 tmp0 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^6
1207 tmp1 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^7
1208 tmp2 = gf4096_mul(bit3_root1_inv, bit3_root1_inv);
1209 tmp2 = gf4096_mul(tmp2, tmp2);
1210 tmp2 = gf4096_mul(tmp2, bit3_root1_inv);
1211 tmp2 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^6
1212 tmp3 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^7
1213 tmp4 = gf4096_mul(bit3_root2_inv, bit3_root2_inv);
1214 tmp4 = gf4096_mul(tmp4, tmp4);
1215 tmp4 = gf4096_mul(tmp4, bit3_root2_inv);
1216 tmp4 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^6
1217 tmp5 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^7
1218
1219 //check if only 3 errors
1220 if ((chk_syndrome_list[6] == (gf4096_mul(err_pats[0], tmp0) ^
1221 gf4096_mul(err_pats[1], tmp2) ^
1222 gf4096_mul(err_pats[2], tmp4))) &
1223 (chk_syndrome_list[7] == (gf4096_mul(err_pats[0], tmp1) ^
1224 gf4096_mul(err_pats[1], tmp3) ^ gf4096_mul(err_pats[2], tmp5)))) {
1225 if ((err_pos(bit3_root0_inv) == 0xfff) |
1226 (err_pos(bit3_root1_inv) == 0xfff) | (err_pos(bit3_root2_inv) == 0xfff)) {
1227 return -EINVAL;
1228 } else {
1229 err_info[0] = 0x3;
1230 err_info[1] = (0x55e - err_pos(bit3_root0_inv));
1231 err_info[2] = (0x55e - err_pos(bit3_root1_inv));
1232 err_info[3] = (0x55e - err_pos(bit3_root2_inv));
1233 err_info[5] = err_pats[0];
1234 err_info[6] = err_pats[1];
1235 err_info[7] = err_pats[2];
1236 return 0;
1237 }
1238 } else
1239 return -EINVAL;
1240 }
1241}
1242static int chk_4_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
1243{
1244 unsigned short coefs[4];
1245 unsigned short err_pats[4];
1246 int found_num_root = 0;
1247 unsigned short bit4_root0, bit4_root1, bit4_root2, bit4_root3;
1248 unsigned short bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv;
1249 unsigned short err_loc_eqn, test_root;
1250
1251 find_4bit_err_coefs(chk_syndrome_list[0],
1252 chk_syndrome_list[1],
1253 chk_syndrome_list[2],
1254 chk_syndrome_list[3],
1255 chk_syndrome_list[4],
1256 chk_syndrome_list[5], chk_syndrome_list[6], chk_syndrome_list[7], coefs);
1257
1258 for (test_root = 0x1; test_root < 0xfff; test_root++) {
1259 err_loc_eqn =
1260 gf4096_mul(coefs[3],
1261 gf4096_mul(gf4096_mul
1262 (gf4096_mul(test_root, test_root),
1263 test_root),
1264 test_root)) ^ gf4096_mul(coefs[2],
1265 gf4096_mul
1266 (gf4096_mul(test_root, test_root), test_root))
1267 ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root)
1268 ^ 0x1;
1269 if (err_loc_eqn == 0x0) {
1270 if (found_num_root == 0) {
1271 bit4_root0 = test_root;
1272 found_num_root = 1;
1273 } else if (found_num_root == 1) {
1274 bit4_root1 = test_root;
1275 found_num_root = 2;
1276 } else if (found_num_root == 2) {
1277 bit4_root2 = test_root;
1278 found_num_root = 3;
1279 } else {
1280 found_num_root = 4;
1281 bit4_root3 = test_root;
1282 break;
1283 }
1284 }
1285 }
1286 if (found_num_root != 4) {
1287 return -EINVAL;
1288 } else {
1289 bit4_root0_inv = gf4096_inv(bit4_root0);
1290 bit4_root1_inv = gf4096_inv(bit4_root1);
1291 bit4_root2_inv = gf4096_inv(bit4_root2);
1292 bit4_root3_inv = gf4096_inv(bit4_root3);
1293 find_4bit_err_pats(chk_syndrome_list[0],
1294 chk_syndrome_list[1],
1295 chk_syndrome_list[2],
1296 chk_syndrome_list[3],
1297 bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv, err_pats);
1298 err_info[0] = 0x4;
1299 err_info[1] = (0x55e - err_pos(bit4_root0_inv));
1300 err_info[2] = (0x55e - err_pos(bit4_root1_inv));
1301 err_info[3] = (0x55e - err_pos(bit4_root2_inv));
1302 err_info[4] = (0x55e - err_pos(bit4_root3_inv));
1303 err_info[5] = err_pats[0];
1304 err_info[6] = err_pats[1];
1305 err_info[7] = err_pats[2];
1306 err_info[8] = err_pats[3];
1307 return 0;
1308 }
1309}
1310
1311void correct_12bit_symbol(unsigned char *buf, unsigned short sym,
1312 unsigned short val)
1313{
1314 if (unlikely(sym > 1366)) {
1315 printk(KERN_ERR "Error: symbol %d out of range; cannot correct\n", sym);
1316 } else if (sym == 0) {
1317 buf[0] ^= val;
1318 } else if (sym & 1) {
1319 buf[1+(3*(sym-1))/2] ^= (val >> 4);
1320 buf[2+(3*(sym-1))/2] ^= ((val & 0xf) << 4);
1321 } else {
1322 buf[2+(3*(sym-2))/2] ^= (val >> 8);
1323 buf[3+(3*(sym-2))/2] ^= (val & 0xff);
1324 }
1325
1326
1327}
1328
1329int cafe_correct_ecc(unsigned char *buf,
1330 unsigned short *chk_syndrome_list)
1331{
1332 unsigned short err_info[9];
1333 int i;
1334
1335 if (chk_no_err_only(chk_syndrome_list, err_info) &&
1336 chk_1_err_only(chk_syndrome_list, err_info) &&
1337 chk_2_err_only(chk_syndrome_list, err_info) &&
1338 chk_3_err_only(chk_syndrome_list, err_info) &&
1339 chk_4_err_only(chk_syndrome_list, err_info)) {
1340 return -EIO;
1341 }
1342
1343 for (i=0; i < err_info[0]; i++)
1344 correct_12bit_symbol(buf, err_info[1+i], err_info[5+i]);
1345
1346 return err_info[0];
1347}
1348