aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-11-28 17:43:10 -0500
committerDavid Woodhouse <dwmw2@infradead.org>2006-11-28 17:43:10 -0500
commit1aaaeabf3622eacd45a94ca9943ea2553b8c34f8 (patch)
tree1dbe3c96c8acbff3d81821ac27747ad017551d18 /drivers/mtd/nand
parent7014568bad55c20b7ee4f439d78c9e875912d51f (diff)
parentcad40654c312fc51bdb520e9be91e29a9742bbcb (diff)
Merge git://git.infradead.org/~dwmw2/cafe-2.6
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/Kconfig7
-rw-r--r--drivers/mtd/nand/Makefile4
-rw-r--r--drivers/mtd/nand/cafe.c771
-rw-r--r--drivers/mtd/nand/cafe_ecc.c1381
4 files changed, 2162 insertions, 1 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index c600868658ef..06627757f500 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -220,6 +220,13 @@ config MTD_NAND_SHARPSL
220 tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" 220 tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
221 depends on MTD_NAND && ARCH_PXA 221 depends on MTD_NAND && ARCH_PXA
222 222
223config MTD_NAND_CAFE
224 tristate "NAND support for OLPC CAFÉ chip"
225 depends on PCI
226 help
227 Use NAND flash attached to the CAFÉ chip designed for the $100
228 laptop.
229
223config MTD_NAND_CS553X 230config MTD_NAND_CS553X
224 tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" 231 tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
225 depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH) 232 depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH)
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 27c9f0a1ef83..f7a53f0b7017 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -6,6 +6,7 @@
6obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o 6obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o
7obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o 7obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
8 8
9obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o
9obj-$(CONFIG_MTD_NAND_SPIA) += spia.o 10obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
10obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o 11obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
11obj-$(CONFIG_MTD_NAND_TOTO) += toto.o 12obj-$(CONFIG_MTD_NAND_TOTO) += toto.o
@@ -24,4 +25,5 @@ obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
24obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o 25obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
25obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o 26obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
26 27
27nand-objs = nand_base.o nand_bbt.o 28nand-objs := nand_base.o nand_bbt.o
29cafe_nand-objs := cafe.o cafe_ecc.o
diff --git a/drivers/mtd/nand/cafe.c b/drivers/mtd/nand/cafe.c
new file mode 100644
index 000000000000..fad304bf7b7e
--- /dev/null
+++ b/drivers/mtd/nand/cafe.c
@@ -0,0 +1,771 @@
1/*
2 * Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01
3 *
4 * Copyright © 2006 Red Hat, Inc.
5 * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
6 */
7
8#define DEBUG
9
10#include <linux/device.h>
11#undef DEBUG
12#include <linux/mtd/mtd.h>
13#include <linux/mtd/nand.h>
14#include <linux/pci.h>
15#include <linux/delay.h>
16#include <linux/interrupt.h>
17#include <asm/io.h>
18
19#define CAFE_NAND_CTRL1 0x00
20#define CAFE_NAND_CTRL2 0x04
21#define CAFE_NAND_CTRL3 0x08
22#define CAFE_NAND_STATUS 0x0c
23#define CAFE_NAND_IRQ 0x10
24#define CAFE_NAND_IRQ_MASK 0x14
25#define CAFE_NAND_DATA_LEN 0x18
26#define CAFE_NAND_ADDR1 0x1c
27#define CAFE_NAND_ADDR2 0x20
28#define CAFE_NAND_TIMING1 0x24
29#define CAFE_NAND_TIMING2 0x28
30#define CAFE_NAND_TIMING3 0x2c
31#define CAFE_NAND_NONMEM 0x30
32#define CAFE_NAND_ECC_RESULT 0x3C
33#define CAFE_NAND_DMA_CTRL 0x40
34#define CAFE_NAND_DMA_ADDR0 0x44
35#define CAFE_NAND_DMA_ADDR1 0x48
36#define CAFE_NAND_ECC_SYN01 0x50
37#define CAFE_NAND_ECC_SYN23 0x54
38#define CAFE_NAND_ECC_SYN45 0x58
39#define CAFE_NAND_ECC_SYN67 0x5c
40#define CAFE_NAND_READ_DATA 0x1000
41#define CAFE_NAND_WRITE_DATA 0x2000
42
43#define CAFE_GLOBAL_CTRL 0x3004
44#define CAFE_GLOBAL_IRQ 0x3008
45#define CAFE_GLOBAL_IRQ_MASK 0x300c
46#define CAFE_NAND_RESET 0x3034
47
48int cafe_correct_ecc(unsigned char *buf,
49 unsigned short *chk_syndrome_list);
50
51struct cafe_priv {
52 struct nand_chip nand;
53 struct pci_dev *pdev;
54 void __iomem *mmio;
55 uint32_t ctl1;
56 uint32_t ctl2;
57 int datalen;
58 int nr_data;
59 int data_pos;
60 int page_addr;
61 dma_addr_t dmaaddr;
62 unsigned char *dmabuf;
63
64};
65
66static int usedma = 1;
67module_param(usedma, int, 0644);
68
69static int skipbbt = 0;
70module_param(skipbbt, int, 0644);
71
72static int debug = 0;
73module_param(debug, int, 0644);
74
75static int regdebug = 0;
76module_param(regdebug, int, 0644);
77
78static int checkecc = 1;
79module_param(checkecc, int, 0644);
80
81static int slowtiming = 0;
82module_param(slowtiming, int, 0644);
83
84/* Hrm. Why isn't this already conditional on something in the struct device? */
85#define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0)
86
87/* Make it easier to switch to PIO if we need to */
88#define cafe_readl(cafe, addr) readl((cafe)->mmio + CAFE_##addr)
89#define cafe_writel(cafe, datum, addr) writel(datum, (cafe)->mmio + CAFE_##addr)
90
91static int cafe_device_ready(struct mtd_info *mtd)
92{
93 struct cafe_priv *cafe = mtd->priv;
94 int result = !!(cafe_readl(cafe, NAND_STATUS) | 0x40000000);
95 uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
96
97 cafe_writel(cafe, irqs, NAND_IRQ);
98
99 cafe_dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n",
100 result?"":" not", irqs, cafe_readl(cafe, NAND_IRQ),
101 cafe_readl(cafe, GLOBAL_IRQ), cafe_readl(cafe, GLOBAL_IRQ_MASK));
102
103 return result;
104}
105
106
107static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
108{
109 struct cafe_priv *cafe = mtd->priv;
110
111 if (usedma)
112 memcpy(cafe->dmabuf + cafe->datalen, buf, len);
113 else
114 memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len);
115
116 cafe->datalen += len;
117
118 cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n",
119 len, cafe->datalen);
120}
121
122static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
123{
124 struct cafe_priv *cafe = mtd->priv;
125
126 if (usedma)
127 memcpy(buf, cafe->dmabuf + cafe->datalen, len);
128 else
129 memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len);
130
131 cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from position 0x%x in read buffer.\n",
132 len, cafe->datalen);
133 cafe->datalen += len;
134}
135
136static uint8_t cafe_read_byte(struct mtd_info *mtd)
137{
138 struct cafe_priv *cafe = mtd->priv;
139 uint8_t d;
140
141 cafe_read_buf(mtd, &d, 1);
142 cafe_dev_dbg(&cafe->pdev->dev, "Read %02x\n", d);
143
144 return d;
145}
146
147static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
148 int column, int page_addr)
149{
150 struct cafe_priv *cafe = mtd->priv;
151 int adrbytes = 0;
152 uint32_t ctl1;
153 uint32_t doneint = 0x80000000;
154
155 cafe_dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n",
156 command, column, page_addr);
157
158 if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) {
159 /* Second half of a command we already calculated */
160 cafe_writel(cafe, cafe->ctl2 | 0x100 | command, NAND_CTRL2);
161 ctl1 = cafe->ctl1;
162 cafe->ctl2 &= ~(1<<30);
163 cafe_dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n",
164 cafe->ctl1, cafe->nr_data);
165 goto do_command;
166 }
167 /* Reset ECC engine */
168 cafe_writel(cafe, 0, NAND_CTRL2);
169
170 /* Emulate NAND_CMD_READOOB on large-page chips */
171 if (mtd->writesize > 512 &&
172 command == NAND_CMD_READOOB) {
173 column += mtd->writesize;
174 command = NAND_CMD_READ0;
175 }
176
177 /* FIXME: Do we need to send read command before sending data
178 for small-page chips, to position the buffer correctly? */
179
180 if (column != -1) {
181 cafe_writel(cafe, column, NAND_ADDR1);
182 adrbytes = 2;
183 if (page_addr != -1)
184 goto write_adr2;
185 } else if (page_addr != -1) {
186 cafe_writel(cafe, page_addr & 0xffff, NAND_ADDR1);
187 page_addr >>= 16;
188 write_adr2:
189 cafe_writel(cafe, page_addr, NAND_ADDR2);
190 adrbytes += 2;
191 if (mtd->size > mtd->writesize << 16)
192 adrbytes++;
193 }
194
195 cafe->data_pos = cafe->datalen = 0;
196
197 /* Set command valid bit */
198 ctl1 = 0x80000000 | command;
199
200 /* Set RD or WR bits as appropriate */
201 if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) {
202 ctl1 |= (1<<26); /* rd */
203 /* Always 5 bytes, for now */
204 cafe->datalen = 4;
205 /* And one address cycle -- even for STATUS, since the controller doesn't work without */
206 adrbytes = 1;
207 } else if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 ||
208 command == NAND_CMD_READOOB || command == NAND_CMD_RNDOUT) {
209 ctl1 |= 1<<26; /* rd */
210 /* For now, assume just read to end of page */
211 cafe->datalen = mtd->writesize + mtd->oobsize - column;
212 } else if (command == NAND_CMD_SEQIN)
213 ctl1 |= 1<<25; /* wr */
214
215 /* Set number of address bytes */
216 if (adrbytes)
217 ctl1 |= ((adrbytes-1)|8) << 27;
218
219 if (command == NAND_CMD_SEQIN || command == NAND_CMD_ERASE1) {
220 /* Ignore the first command of a pair; the hardware
221 deals with them both at once, later */
222 cafe->ctl1 = ctl1;
223 cafe_dev_dbg(&cafe->pdev->dev, "Setup for delayed command, ctl1 %08x, dlen %x\n",
224 cafe->ctl1, cafe->datalen);
225 return;
226 }
227 /* RNDOUT and READ0 commands need a following byte */
228 if (command == NAND_CMD_RNDOUT)
229 cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_RNDOUTSTART, NAND_CTRL2);
230 else if (command == NAND_CMD_READ0 && mtd->writesize > 512)
231 cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_READSTART, NAND_CTRL2);
232
233 do_command:
234 cafe_dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n",
235 cafe->datalen, ctl1, cafe_readl(cafe, NAND_CTRL2));
236
237 /* NB: The datasheet lies -- we really should be subtracting 1 here */
238 cafe_writel(cafe, cafe->datalen, NAND_DATA_LEN);
239 cafe_writel(cafe, 0x90000000, NAND_IRQ);
240 if (usedma && (ctl1 & (3<<25))) {
241 uint32_t dmactl = 0xc0000000 + cafe->datalen;
242 /* If WR or RD bits set, set up DMA */
243 if (ctl1 & (1<<26)) {
244 /* It's a read */
245 dmactl |= (1<<29);
246 /* ... so it's done when the DMA is done, not just
247 the command. */
248 doneint = 0x10000000;
249 }
250 cafe_writel(cafe, dmactl, NAND_DMA_CTRL);
251 }
252 cafe->datalen = 0;
253
254 if (unlikely(regdebug)) {
255 int i;
256 printk("About to write command %08x to register 0\n", ctl1);
257 for (i=4; i< 0x5c; i+=4)
258 printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
259 }
260
261 cafe_writel(cafe, ctl1, NAND_CTRL1);
262 /* Apply this short delay always to ensure that we do wait tWB in
263 * any case on any machine. */
264 ndelay(100);
265
266 if (1) {
267 int c = 500000;
268 uint32_t irqs;
269
270 while (c--) {
271 irqs = cafe_readl(cafe, NAND_IRQ);
272 if (irqs & doneint)
273 break;
274 udelay(1);
275 if (!(c % 100000))
276 cafe_dev_dbg(&cafe->pdev->dev, "Wait for ready, IRQ %x\n", irqs);
277 cpu_relax();
278 }
279 cafe_writel(cafe, doneint, NAND_IRQ);
280 cafe_dev_dbg(&cafe->pdev->dev, "Command %x completed after %d usec, irqs %x (%x)\n",
281 command, 500000-c, irqs, cafe_readl(cafe, NAND_IRQ));
282 }
283
284 WARN_ON(cafe->ctl2 & (1<<30));
285
286 switch (command) {
287
288 case NAND_CMD_CACHEDPROG:
289 case NAND_CMD_PAGEPROG:
290 case NAND_CMD_ERASE1:
291 case NAND_CMD_ERASE2:
292 case NAND_CMD_SEQIN:
293 case NAND_CMD_RNDIN:
294 case NAND_CMD_STATUS:
295 case NAND_CMD_DEPLETE1:
296 case NAND_CMD_RNDOUT:
297 case NAND_CMD_STATUS_ERROR:
298 case NAND_CMD_STATUS_ERROR0:
299 case NAND_CMD_STATUS_ERROR1:
300 case NAND_CMD_STATUS_ERROR2:
301 case NAND_CMD_STATUS_ERROR3:
302 cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
303 return;
304 }
305 nand_wait_ready(mtd);
306 cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
307}
308
309static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
310{
311 //struct cafe_priv *cafe = mtd->priv;
312 // cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
313}
314
315static int cafe_nand_interrupt(int irq, void *id, struct pt_regs *regs)
316{
317 struct mtd_info *mtd = id;
318 struct cafe_priv *cafe = mtd->priv;
319 uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
320 cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ);
321 if (!irqs)
322 return IRQ_NONE;
323
324 cafe_dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs, cafe_readl(cafe, NAND_IRQ));
325 return IRQ_HANDLED;
326}
327
328static void cafe_nand_bug(struct mtd_info *mtd)
329{
330 BUG();
331}
332
333static int cafe_nand_write_oob(struct mtd_info *mtd,
334 struct nand_chip *chip, int page)
335{
336 int status = 0;
337
338 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
339 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
340 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
341 status = chip->waitfunc(mtd, chip);
342
343 return status & NAND_STATUS_FAIL ? -EIO : 0;
344}
345
346/* Don't use -- use nand_read_oob_std for now */
347static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
348 int page, int sndcmd)
349{
350 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
351 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
352 return 1;
353}
354/**
355 * cafe_nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
356 * @mtd: mtd info structure
357 * @chip: nand chip info structure
358 * @buf: buffer to store read data
359 *
360 * The hw generator calculates the error syndrome automatically. Therefor
361 * we need a special oob layout and handling.
362 */
363static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
364 uint8_t *buf)
365{
366 struct cafe_priv *cafe = mtd->priv;
367
368 cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
369 cafe_readl(cafe, NAND_ECC_RESULT),
370 cafe_readl(cafe, NAND_ECC_SYN01));
371
372 chip->read_buf(mtd, buf, mtd->writesize);
373 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
374
375 if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) {
376 unsigned short syn[8];
377 int i;
378
379 for (i=0; i<8; i+=2) {
380 uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2));
381 syn[i] = tmp & 0xfff;
382 syn[i+1] = (tmp >> 16) & 0xfff;
383 }
384
385 if ((i = cafe_correct_ecc(buf, syn)) < 0) {
386 dev_dbg(&cafe->pdev->dev, "Failed to correct ECC at %08x\n",
387 cafe_readl(cafe, NAND_ADDR2) * 2048);
388 for (i=0; i< 0x5c; i+=4)
389 printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
390 mtd->ecc_stats.failed++;
391 } else {
392 dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", i);
393 mtd->ecc_stats.corrected += i;
394 }
395 }
396
397
398 return 0;
399}
400
401static struct nand_ecclayout cafe_oobinfo_2048 = {
402 .eccbytes = 14,
403 .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
404 .oobfree = {{14, 50}}
405};
406
407/* Ick. The BBT code really ought to be able to work this bit out
408 for itself from the above, at least for the 2KiB case */
409static uint8_t cafe_bbt_pattern_2048[] = { 'B', 'b', 't', '0' };
410static uint8_t cafe_mirror_pattern_2048[] = { '1', 't', 'b', 'B' };
411
412static uint8_t cafe_bbt_pattern_512[] = { 0xBB };
413static uint8_t cafe_mirror_pattern_512[] = { 0xBC };
414
415
416static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
417 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
418 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
419 .offs = 14,
420 .len = 4,
421 .veroffs = 18,
422 .maxblocks = 4,
423 .pattern = cafe_bbt_pattern_2048
424};
425
426static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = {
427 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
428 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
429 .offs = 14,
430 .len = 4,
431 .veroffs = 18,
432 .maxblocks = 4,
433 .pattern = cafe_mirror_pattern_2048
434};
435
436static struct nand_ecclayout cafe_oobinfo_512 = {
437 .eccbytes = 14,
438 .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
439 .oobfree = {{14, 2}}
440};
441
442static struct nand_bbt_descr cafe_bbt_main_descr_512 = {
443 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
444 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
445 .offs = 14,
446 .len = 1,
447 .veroffs = 15,
448 .maxblocks = 4,
449 .pattern = cafe_bbt_pattern_512
450};
451
452static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
453 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
454 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
455 .offs = 14,
456 .len = 1,
457 .veroffs = 15,
458 .maxblocks = 4,
459 .pattern = cafe_mirror_pattern_512
460};
461
462
463static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
464 struct nand_chip *chip, const uint8_t *buf)
465{
466 struct cafe_priv *cafe = mtd->priv;
467
468 chip->write_buf(mtd, buf, mtd->writesize);
469 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
470
471 /* Set up ECC autogeneration */
472 cafe->ctl2 |= (1<<30);
473}
474
475static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
476 const uint8_t *buf, int page, int cached, int raw)
477{
478 int status;
479
480 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
481
482 if (unlikely(raw))
483 chip->ecc.write_page_raw(mtd, chip, buf);
484 else
485 chip->ecc.write_page(mtd, chip, buf);
486
487 /*
488 * Cached progamming disabled for now, Not sure if its worth the
489 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
490 */
491 cached = 0;
492
493 if (!cached || !(chip->options & NAND_CACHEPRG)) {
494
495 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
496 status = chip->waitfunc(mtd, chip);
497 /*
498 * See if operation failed and additional status checks are
499 * available
500 */
501 if ((status & NAND_STATUS_FAIL) && (chip->errstat))
502 status = chip->errstat(mtd, chip, FL_WRITING, status,
503 page);
504
505 if (status & NAND_STATUS_FAIL)
506 return -EIO;
507 } else {
508 chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
509 status = chip->waitfunc(mtd, chip);
510 }
511
512#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
513 /* Send command to read back the data */
514 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
515
516 if (chip->verify_buf(mtd, buf, mtd->writesize))
517 return -EIO;
518#endif
519 return 0;
520}
521
522static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
523{
524 return 0;
525}
526
527static int __devinit cafe_nand_probe(struct pci_dev *pdev,
528 const struct pci_device_id *ent)
529{
530 struct mtd_info *mtd;
531 struct cafe_priv *cafe;
532 uint32_t ctrl;
533 int err = 0;
534
535 err = pci_enable_device(pdev);
536 if (err)
537 return err;
538
539 pci_set_master(pdev);
540
541 mtd = kzalloc(sizeof(*mtd) + sizeof(struct cafe_priv), GFP_KERNEL);
542 if (!mtd) {
543 dev_warn(&pdev->dev, "failed to alloc mtd_info\n");
544 return -ENOMEM;
545 }
546 cafe = (void *)(&mtd[1]);
547
548 mtd->priv = cafe;
549 mtd->owner = THIS_MODULE;
550
551 cafe->pdev = pdev;
552 cafe->mmio = pci_iomap(pdev, 0, 0);
553 if (!cafe->mmio) {
554 dev_warn(&pdev->dev, "failed to iomap\n");
555 err = -ENOMEM;
556 goto out_free_mtd;
557 }
558 cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers),
559 &cafe->dmaaddr, GFP_KERNEL);
560 if (!cafe->dmabuf) {
561 err = -ENOMEM;
562 goto out_ior;
563 }
564 cafe->nand.buffers = (void *)cafe->dmabuf + 2112;
565
566 cafe->nand.cmdfunc = cafe_nand_cmdfunc;
567 cafe->nand.dev_ready = cafe_device_ready;
568 cafe->nand.read_byte = cafe_read_byte;
569 cafe->nand.read_buf = cafe_read_buf;
570 cafe->nand.write_buf = cafe_write_buf;
571 cafe->nand.select_chip = cafe_select_chip;
572
573 cafe->nand.chip_delay = 0;
574
575 /* Enable the following for a flash based bad block table */
576 cafe->nand.options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR | NAND_OWN_BUFFERS;
577
578 if (skipbbt) {
579 cafe->nand.options |= NAND_SKIP_BBTSCAN;
580 cafe->nand.block_bad = cafe_nand_block_bad;
581 }
582
583 /* Start off by resetting the NAND controller completely */
584 cafe_writel(cafe, 1, NAND_RESET);
585 cafe_writel(cafe, 0, NAND_RESET);
586
587 cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
588
589 /* Timings from Marvell's test code (not verified or calculated by us) */
590 if (!slowtiming) {
591 cafe_writel(cafe, 0x01010a0a, NAND_TIMING1);
592 cafe_writel(cafe, 0x24121212, NAND_TIMING2);
593 cafe_writel(cafe, 0x11000000, NAND_TIMING3);
594 } else {
595 cafe_writel(cafe, 0xffffffff, NAND_TIMING1);
596 cafe_writel(cafe, 0xffffffff, NAND_TIMING2);
597 cafe_writel(cafe, 0xffffffff, NAND_TIMING3);
598 }
599 cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
600 err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd);
601 if (err) {
602 dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
603
604 goto out_free_dma;
605 }
606#if 1
607 /* Disable master reset, enable NAND clock */
608 ctrl = cafe_readl(cafe, GLOBAL_CTRL);
609 ctrl &= 0xffffeff0;
610 ctrl |= 0x00007000;
611 cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
612 cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
613 cafe_writel(cafe, 0, NAND_DMA_CTRL);
614
615 cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
616 cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
617
618 /* Set up DMA address */
619 cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
620 if (sizeof(cafe->dmaaddr) > 4)
621 /* Shift in two parts to shut the compiler up */
622 cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1);
623 else
624 cafe_writel(cafe, 0, NAND_DMA_ADDR1);
625
626 cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
627 cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
628
629 /* Enable NAND IRQ in global IRQ mask register */
630 cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
631 cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
632 cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK));
633#endif
634#if 1
635 mtd->writesize=2048;
636 mtd->oobsize = 0x40;
637 memset(cafe->dmabuf, 0x5a, 2112);
638 cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1);
639 cafe->nand.read_byte(mtd);
640 cafe->nand.read_byte(mtd);
641 cafe->nand.read_byte(mtd);
642 cafe->nand.read_byte(mtd);
643 cafe->nand.read_byte(mtd);
644#endif
645#if 0
646 cafe->nand.cmdfunc(mtd, NAND_CMD_READ0, 0, 0);
647 // nand_wait_ready(mtd);
648 cafe->nand.read_byte(mtd);
649 cafe->nand.read_byte(mtd);
650 cafe->nand.read_byte(mtd);
651 cafe->nand.read_byte(mtd);
652#endif
653#if 0
654 writel(0x84600070, cafe->mmio);
655 udelay(10);
656 cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", cafe_readl(cafe, NAND_NONMEM));
657#endif
658 /* Scan to find existance of the device */
659 if (nand_scan_ident(mtd, 1)) {
660 err = -ENXIO;
661 goto out_irq;
662 }
663
664 cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */
665 if (mtd->writesize == 2048)
666 cafe->ctl2 |= 1<<29; /* 2KiB page size */
667
668 /* Set up ECC according to the type of chip we found */
669 if (mtd->writesize == 2048) {
670 cafe->nand.ecc.layout = &cafe_oobinfo_2048;
671 cafe->nand.bbt_td = &cafe_bbt_main_descr_2048;
672 cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048;
673 } else if (mtd->writesize == 512) {
674 cafe->nand.ecc.layout = &cafe_oobinfo_512;
675 cafe->nand.bbt_td = &cafe_bbt_main_descr_512;
676 cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512;
677 } else {
678 printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n",
679 mtd->writesize);
680 goto out_irq;
681 }
682 cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
683 cafe->nand.ecc.size = mtd->writesize;
684 cafe->nand.ecc.bytes = 14;
685 cafe->nand.ecc.hwctl = (void *)cafe_nand_bug;
686 cafe->nand.ecc.calculate = (void *)cafe_nand_bug;
687 cafe->nand.ecc.correct = (void *)cafe_nand_bug;
688 cafe->nand.write_page = cafe_nand_write_page;
689 cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel;
690 cafe->nand.ecc.write_oob = cafe_nand_write_oob;
691 cafe->nand.ecc.read_page = cafe_nand_read_page;
692 cafe->nand.ecc.read_oob = cafe_nand_read_oob;
693
694 err = nand_scan_tail(mtd);
695 if (err)
696 goto out_irq;
697
698 pci_set_drvdata(pdev, mtd);
699 add_mtd_device(mtd);
700 goto out;
701
702 out_irq:
703 /* Disable NAND IRQ in global IRQ mask register */
704 cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
705 free_irq(pdev->irq, mtd);
706 out_free_dma:
707 dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
708 out_ior:
709 pci_iounmap(pdev, cafe->mmio);
710 out_free_mtd:
711 kfree(mtd);
712 out:
713 return err;
714}
715
716static void __devexit cafe_nand_remove(struct pci_dev *pdev)
717{
718 struct mtd_info *mtd = pci_get_drvdata(pdev);
719 struct cafe_priv *cafe = mtd->priv;
720
721 del_mtd_device(mtd);
722 /* Disable NAND IRQ in global IRQ mask register */
723 cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
724 free_irq(pdev->irq, mtd);
725 nand_release(mtd);
726 pci_iounmap(pdev, cafe->mmio);
727 dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
728 kfree(mtd);
729}
730
731static struct pci_device_id cafe_nand_tbl[] = {
732 { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 }
733};
734
735MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
736
737static struct pci_driver cafe_nand_pci_driver = {
738 .name = "CAFÉ NAND",
739 .id_table = cafe_nand_tbl,
740 .probe = cafe_nand_probe,
741 .remove = __devexit_p(cafe_nand_remove),
742#ifdef CONFIG_PMx
743 .suspend = cafe_nand_suspend,
744 .resume = cafe_nand_resume,
745#endif
746};
747
748static int cafe_nand_init(void)
749{
750 return pci_register_driver(&cafe_nand_pci_driver);
751}
752
753static void cafe_nand_exit(void)
754{
755 pci_unregister_driver(&cafe_nand_pci_driver);
756}
757module_init(cafe_nand_init);
758module_exit(cafe_nand_exit);
759
760MODULE_LICENSE("GPL");
761MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
762MODULE_DESCRIPTION("NAND flash driver for OLPC CAFE chip");
763
764/* Correct ECC for 2048 bytes of 0xff:
765 41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */
766
767/* dwmw2's B-test board, in case of completely screwing it:
768Bad eraseblock 2394 at 0x12b40000
769Bad eraseblock 2627 at 0x14860000
770Bad eraseblock 3349 at 0x1a2a0000
771*/
diff --git a/drivers/mtd/nand/cafe_ecc.c b/drivers/mtd/nand/cafe_ecc.c
new file mode 100644
index 000000000000..2d29265cc904
--- /dev/null
+++ b/drivers/mtd/nand/cafe_ecc.c
@@ -0,0 +1,1381 @@
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
25static unsigned short gf4096_mul(unsigned short, unsigned short);
26static unsigned short gf64_mul(unsigned short, unsigned short);
27static unsigned short gf4096_inv(unsigned short);
28static unsigned short err_pos(unsigned short);
29static 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 *);
32static void zero_4x5_col3(unsigned short[4][5]);
33static void zero_4x5_col2(unsigned short[4][5]);
34static void zero_4x5_col1(unsigned short[4][5]);
35static void swap_4x5_rows(unsigned short[4][5], int, int, int);
36static void swap_2x3_rows(unsigned short m[2][3]);
37static void solve_4x5(unsigned short m[4][5], unsigned short *, int *);
38static void sort_coefs(int *, unsigned short *, int);
39static 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 *);
42static void find_3bit_err_coefs(unsigned short, unsigned short, unsigned short,
43 unsigned short, unsigned short, unsigned short,
44 unsigned short *);
45static void zero_3x4_col2(unsigned short[3][4]);
46static void zero_3x4_col1(unsigned short[3][4]);
47static void swap_3x4_rows(unsigned short[3][4], int, int, int);
48static void solve_3x4(unsigned short[3][4], unsigned short *, int *);
49static void find_3bit_err_pats(unsigned short, unsigned short, unsigned short,
50 unsigned short, unsigned short, unsigned short,
51 unsigned short *);
52
53static void find_2bit_err_pats(unsigned short, unsigned short, unsigned short,
54 unsigned short, unsigned short *);
55static void find_2x2_soln(unsigned short, unsigned short, unsigned short,
56 unsigned short, unsigned short, unsigned short,
57 unsigned short *);
58static void solve_2x3(unsigned short[2][3], unsigned short *);
59static int chk_no_err_only(unsigned short *, unsigned short *);
60static int chk_1_err_only(unsigned short *, unsigned short *);
61static int chk_2_err_only(unsigned short *, unsigned short *);
62static int chk_3_err_only(unsigned short *, unsigned short *);
63static int chk_4_err_only(unsigned short *, unsigned short *);
64
65static 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
99static 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
122static 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
127static 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
174static 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
188static 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
196static 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
207static 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
219static 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
230static 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
304static 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
326static 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
341static 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
351static 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
363static 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
379static 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
406static 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
455static 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
479static 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
491static 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
502static 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
509static 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
531static 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
1046static unsigned short err_pos(unsigned short din)
1047{
1048 BUG_ON(din > 4096);
1049 return err_pos_lut[din];
1050}
1051static 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}
1063static 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}
1082static 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}
1158static 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}
1243static 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
1312void 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
1328static int debugecc = 0;
1329module_param(debugecc, int, 0644);
1330
1331int 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