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