Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
1aaaeabf
Commit
1aaaeabf
authored
Nov 28, 2006
by
David Woodhouse
Browse files
Options
Browse Files
Download
Plain Diff
Merge
git://git.infradead.org/~dwmw2/cafe-2.6
parents
7014568b
cad40654
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
2162 additions
and
1 deletion
+2162
-1
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Kconfig
+7
-0
drivers/mtd/nand/Makefile
drivers/mtd/nand/Makefile
+3
-1
drivers/mtd/nand/cafe.c
drivers/mtd/nand/cafe.c
+771
-0
drivers/mtd/nand/cafe_ecc.c
drivers/mtd/nand/cafe_ecc.c
+1381
-0
No files found.
drivers/mtd/nand/Kconfig
View file @
1aaaeabf
...
@@ -220,6 +220,13 @@ config MTD_NAND_SHARPSL
...
@@ -220,6 +220,13 @@ config MTD_NAND_SHARPSL
tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
depends on MTD_NAND && ARCH_PXA
depends on MTD_NAND && ARCH_PXA
config MTD_NAND_CAFE
tristate "NAND support for OLPC CAFÉ chip"
depends on PCI
help
Use NAND flash attached to the CAFÉ chip designed for the $100
laptop.
config MTD_NAND_CS553X
config MTD_NAND_CS553X
tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH)
depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH)
...
...
drivers/mtd/nand/Makefile
View file @
1aaaeabf
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
obj-$(CONFIG_MTD_NAND)
+=
nand.o nand_ecc.o
obj-$(CONFIG_MTD_NAND)
+=
nand.o nand_ecc.o
obj-$(CONFIG_MTD_NAND_IDS)
+=
nand_ids.o
obj-$(CONFIG_MTD_NAND_IDS)
+=
nand_ids.o
obj-$(CONFIG_MTD_NAND_CAFE)
+=
cafe_nand.o
obj-$(CONFIG_MTD_NAND_SPIA)
+=
spia.o
obj-$(CONFIG_MTD_NAND_SPIA)
+=
spia.o
obj-$(CONFIG_MTD_NAND_AMS_DELTA)
+=
ams-delta.o
obj-$(CONFIG_MTD_NAND_AMS_DELTA)
+=
ams-delta.o
obj-$(CONFIG_MTD_NAND_TOTO)
+=
toto.o
obj-$(CONFIG_MTD_NAND_TOTO)
+=
toto.o
...
@@ -24,4 +25,5 @@ obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
...
@@ -24,4 +25,5 @@ obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
obj-$(CONFIG_MTD_NAND_NDFC)
+=
ndfc.o
obj-$(CONFIG_MTD_NAND_NDFC)
+=
ndfc.o
obj-$(CONFIG_MTD_NAND_AT91)
+=
at91_nand.o
obj-$(CONFIG_MTD_NAND_AT91)
+=
at91_nand.o
nand-objs
=
nand_base.o nand_bbt.o
nand-objs
:=
nand_base.o nand_bbt.o
cafe_nand-objs
:=
cafe.o cafe_ecc.o
drivers/mtd/nand/cafe.c
0 → 100644
View file @
1aaaeabf
/*
* Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01
*
* Copyright © 2006 Red Hat, Inc.
* Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
*/
#define DEBUG
#include <linux/device.h>
#undef DEBUG
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#define CAFE_NAND_CTRL1 0x00
#define CAFE_NAND_CTRL2 0x04
#define CAFE_NAND_CTRL3 0x08
#define CAFE_NAND_STATUS 0x0c
#define CAFE_NAND_IRQ 0x10
#define CAFE_NAND_IRQ_MASK 0x14
#define CAFE_NAND_DATA_LEN 0x18
#define CAFE_NAND_ADDR1 0x1c
#define CAFE_NAND_ADDR2 0x20
#define CAFE_NAND_TIMING1 0x24
#define CAFE_NAND_TIMING2 0x28
#define CAFE_NAND_TIMING3 0x2c
#define CAFE_NAND_NONMEM 0x30
#define CAFE_NAND_ECC_RESULT 0x3C
#define CAFE_NAND_DMA_CTRL 0x40
#define CAFE_NAND_DMA_ADDR0 0x44
#define CAFE_NAND_DMA_ADDR1 0x48
#define CAFE_NAND_ECC_SYN01 0x50
#define CAFE_NAND_ECC_SYN23 0x54
#define CAFE_NAND_ECC_SYN45 0x58
#define CAFE_NAND_ECC_SYN67 0x5c
#define CAFE_NAND_READ_DATA 0x1000
#define CAFE_NAND_WRITE_DATA 0x2000
#define CAFE_GLOBAL_CTRL 0x3004
#define CAFE_GLOBAL_IRQ 0x3008
#define CAFE_GLOBAL_IRQ_MASK 0x300c
#define CAFE_NAND_RESET 0x3034
int
cafe_correct_ecc
(
unsigned
char
*
buf
,
unsigned
short
*
chk_syndrome_list
);
struct
cafe_priv
{
struct
nand_chip
nand
;
struct
pci_dev
*
pdev
;
void
__iomem
*
mmio
;
uint32_t
ctl1
;
uint32_t
ctl2
;
int
datalen
;
int
nr_data
;
int
data_pos
;
int
page_addr
;
dma_addr_t
dmaaddr
;
unsigned
char
*
dmabuf
;
};
static
int
usedma
=
1
;
module_param
(
usedma
,
int
,
0644
);
static
int
skipbbt
=
0
;
module_param
(
skipbbt
,
int
,
0644
);
static
int
debug
=
0
;
module_param
(
debug
,
int
,
0644
);
static
int
regdebug
=
0
;
module_param
(
regdebug
,
int
,
0644
);
static
int
checkecc
=
1
;
module_param
(
checkecc
,
int
,
0644
);
static
int
slowtiming
=
0
;
module_param
(
slowtiming
,
int
,
0644
);
/* Hrm. Why isn't this already conditional on something in the struct device? */
#define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0)
/* Make it easier to switch to PIO if we need to */
#define cafe_readl(cafe, addr) readl((cafe)->mmio + CAFE_##addr)
#define cafe_writel(cafe, datum, addr) writel(datum, (cafe)->mmio + CAFE_##addr)
static
int
cafe_device_ready
(
struct
mtd_info
*
mtd
)
{
struct
cafe_priv
*
cafe
=
mtd
->
priv
;
int
result
=
!!
(
cafe_readl
(
cafe
,
NAND_STATUS
)
|
0x40000000
);
uint32_t
irqs
=
cafe_readl
(
cafe
,
NAND_IRQ
);
cafe_writel
(
cafe
,
irqs
,
NAND_IRQ
);
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"NAND device is%s ready, IRQ %x (%x) (%x,%x)
\n
"
,
result
?
""
:
" not"
,
irqs
,
cafe_readl
(
cafe
,
NAND_IRQ
),
cafe_readl
(
cafe
,
GLOBAL_IRQ
),
cafe_readl
(
cafe
,
GLOBAL_IRQ_MASK
));
return
result
;
}
static
void
cafe_write_buf
(
struct
mtd_info
*
mtd
,
const
uint8_t
*
buf
,
int
len
)
{
struct
cafe_priv
*
cafe
=
mtd
->
priv
;
if
(
usedma
)
memcpy
(
cafe
->
dmabuf
+
cafe
->
datalen
,
buf
,
len
);
else
memcpy_toio
(
cafe
->
mmio
+
CAFE_NAND_WRITE_DATA
+
cafe
->
datalen
,
buf
,
len
);
cafe
->
datalen
+=
len
;
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Copy 0x%x bytes to write buffer. datalen 0x%x
\n
"
,
len
,
cafe
->
datalen
);
}
static
void
cafe_read_buf
(
struct
mtd_info
*
mtd
,
uint8_t
*
buf
,
int
len
)
{
struct
cafe_priv
*
cafe
=
mtd
->
priv
;
if
(
usedma
)
memcpy
(
buf
,
cafe
->
dmabuf
+
cafe
->
datalen
,
len
);
else
memcpy_fromio
(
buf
,
cafe
->
mmio
+
CAFE_NAND_READ_DATA
+
cafe
->
datalen
,
len
);
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Copy 0x%x bytes from position 0x%x in read buffer.
\n
"
,
len
,
cafe
->
datalen
);
cafe
->
datalen
+=
len
;
}
static
uint8_t
cafe_read_byte
(
struct
mtd_info
*
mtd
)
{
struct
cafe_priv
*
cafe
=
mtd
->
priv
;
uint8_t
d
;
cafe_read_buf
(
mtd
,
&
d
,
1
);
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Read %02x
\n
"
,
d
);
return
d
;
}
static
void
cafe_nand_cmdfunc
(
struct
mtd_info
*
mtd
,
unsigned
command
,
int
column
,
int
page_addr
)
{
struct
cafe_priv
*
cafe
=
mtd
->
priv
;
int
adrbytes
=
0
;
uint32_t
ctl1
;
uint32_t
doneint
=
0x80000000
;
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"cmdfunc %02x, 0x%x, 0x%x
\n
"
,
command
,
column
,
page_addr
);
if
(
command
==
NAND_CMD_ERASE2
||
command
==
NAND_CMD_PAGEPROG
)
{
/* Second half of a command we already calculated */
cafe_writel
(
cafe
,
cafe
->
ctl2
|
0x100
|
command
,
NAND_CTRL2
);
ctl1
=
cafe
->
ctl1
;
cafe
->
ctl2
&=
~
(
1
<<
30
);
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Continue command, ctl1 %08x, #data %d
\n
"
,
cafe
->
ctl1
,
cafe
->
nr_data
);
goto
do_command
;
}
/* Reset ECC engine */
cafe_writel
(
cafe
,
0
,
NAND_CTRL2
);
/* Emulate NAND_CMD_READOOB on large-page chips */
if
(
mtd
->
writesize
>
512
&&
command
==
NAND_CMD_READOOB
)
{
column
+=
mtd
->
writesize
;
command
=
NAND_CMD_READ0
;
}
/* FIXME: Do we need to send read command before sending data
for small-page chips, to position the buffer correctly? */
if
(
column
!=
-
1
)
{
cafe_writel
(
cafe
,
column
,
NAND_ADDR1
);
adrbytes
=
2
;
if
(
page_addr
!=
-
1
)
goto
write_adr2
;
}
else
if
(
page_addr
!=
-
1
)
{
cafe_writel
(
cafe
,
page_addr
&
0xffff
,
NAND_ADDR1
);
page_addr
>>=
16
;
write_adr2:
cafe_writel
(
cafe
,
page_addr
,
NAND_ADDR2
);
adrbytes
+=
2
;
if
(
mtd
->
size
>
mtd
->
writesize
<<
16
)
adrbytes
++
;
}
cafe
->
data_pos
=
cafe
->
datalen
=
0
;
/* Set command valid bit */
ctl1
=
0x80000000
|
command
;
/* Set RD or WR bits as appropriate */
if
(
command
==
NAND_CMD_READID
||
command
==
NAND_CMD_STATUS
)
{
ctl1
|=
(
1
<<
26
);
/* rd */
/* Always 5 bytes, for now */
cafe
->
datalen
=
4
;
/* And one address cycle -- even for STATUS, since the controller doesn't work without */
adrbytes
=
1
;
}
else
if
(
command
==
NAND_CMD_READ0
||
command
==
NAND_CMD_READ1
||
command
==
NAND_CMD_READOOB
||
command
==
NAND_CMD_RNDOUT
)
{
ctl1
|=
1
<<
26
;
/* rd */
/* For now, assume just read to end of page */
cafe
->
datalen
=
mtd
->
writesize
+
mtd
->
oobsize
-
column
;
}
else
if
(
command
==
NAND_CMD_SEQIN
)
ctl1
|=
1
<<
25
;
/* wr */
/* Set number of address bytes */
if
(
adrbytes
)
ctl1
|=
((
adrbytes
-
1
)
|
8
)
<<
27
;
if
(
command
==
NAND_CMD_SEQIN
||
command
==
NAND_CMD_ERASE1
)
{
/* Ignore the first command of a pair; the hardware
deals with them both at once, later */
cafe
->
ctl1
=
ctl1
;
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Setup for delayed command, ctl1 %08x, dlen %x
\n
"
,
cafe
->
ctl1
,
cafe
->
datalen
);
return
;
}
/* RNDOUT and READ0 commands need a following byte */
if
(
command
==
NAND_CMD_RNDOUT
)
cafe_writel
(
cafe
,
cafe
->
ctl2
|
0x100
|
NAND_CMD_RNDOUTSTART
,
NAND_CTRL2
);
else
if
(
command
==
NAND_CMD_READ0
&&
mtd
->
writesize
>
512
)
cafe_writel
(
cafe
,
cafe
->
ctl2
|
0x100
|
NAND_CMD_READSTART
,
NAND_CTRL2
);
do_command:
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"dlen %x, ctl1 %x, ctl2 %x
\n
"
,
cafe
->
datalen
,
ctl1
,
cafe_readl
(
cafe
,
NAND_CTRL2
));
/* NB: The datasheet lies -- we really should be subtracting 1 here */
cafe_writel
(
cafe
,
cafe
->
datalen
,
NAND_DATA_LEN
);
cafe_writel
(
cafe
,
0x90000000
,
NAND_IRQ
);
if
(
usedma
&&
(
ctl1
&
(
3
<<
25
)))
{
uint32_t
dmactl
=
0xc0000000
+
cafe
->
datalen
;
/* If WR or RD bits set, set up DMA */
if
(
ctl1
&
(
1
<<
26
))
{
/* It's a read */
dmactl
|=
(
1
<<
29
);
/* ... so it's done when the DMA is done, not just
the command. */
doneint
=
0x10000000
;
}
cafe_writel
(
cafe
,
dmactl
,
NAND_DMA_CTRL
);
}
cafe
->
datalen
=
0
;
if
(
unlikely
(
regdebug
))
{
int
i
;
printk
(
"About to write command %08x to register 0
\n
"
,
ctl1
);
for
(
i
=
4
;
i
<
0x5c
;
i
+=
4
)
printk
(
"Register %x: %08x
\n
"
,
i
,
readl
(
cafe
->
mmio
+
i
));
}
cafe_writel
(
cafe
,
ctl1
,
NAND_CTRL1
);
/* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine. */
ndelay
(
100
);
if
(
1
)
{
int
c
=
500000
;
uint32_t
irqs
;
while
(
c
--
)
{
irqs
=
cafe_readl
(
cafe
,
NAND_IRQ
);
if
(
irqs
&
doneint
)
break
;
udelay
(
1
);
if
(
!
(
c
%
100000
))
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Wait for ready, IRQ %x
\n
"
,
irqs
);
cpu_relax
();
}
cafe_writel
(
cafe
,
doneint
,
NAND_IRQ
);
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Command %x completed after %d usec, irqs %x (%x)
\n
"
,
command
,
500000
-
c
,
irqs
,
cafe_readl
(
cafe
,
NAND_IRQ
));
}
WARN_ON
(
cafe
->
ctl2
&
(
1
<<
30
));
switch
(
command
)
{
case
NAND_CMD_CACHEDPROG
:
case
NAND_CMD_PAGEPROG
:
case
NAND_CMD_ERASE1
:
case
NAND_CMD_ERASE2
:
case
NAND_CMD_SEQIN
:
case
NAND_CMD_RNDIN
:
case
NAND_CMD_STATUS
:
case
NAND_CMD_DEPLETE1
:
case
NAND_CMD_RNDOUT
:
case
NAND_CMD_STATUS_ERROR
:
case
NAND_CMD_STATUS_ERROR0
:
case
NAND_CMD_STATUS_ERROR1
:
case
NAND_CMD_STATUS_ERROR2
:
case
NAND_CMD_STATUS_ERROR3
:
cafe_writel
(
cafe
,
cafe
->
ctl2
,
NAND_CTRL2
);
return
;
}
nand_wait_ready
(
mtd
);
cafe_writel
(
cafe
,
cafe
->
ctl2
,
NAND_CTRL2
);
}
static
void
cafe_select_chip
(
struct
mtd_info
*
mtd
,
int
chipnr
)
{
//struct cafe_priv *cafe = mtd->priv;
// cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
}
static
int
cafe_nand_interrupt
(
int
irq
,
void
*
id
,
struct
pt_regs
*
regs
)
{
struct
mtd_info
*
mtd
=
id
;
struct
cafe_priv
*
cafe
=
mtd
->
priv
;
uint32_t
irqs
=
cafe_readl
(
cafe
,
NAND_IRQ
);
cafe_writel
(
cafe
,
irqs
&
~
0x90000000
,
NAND_IRQ
);
if
(
!
irqs
)
return
IRQ_NONE
;
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"irq, bits %x (%x)
\n
"
,
irqs
,
cafe_readl
(
cafe
,
NAND_IRQ
));
return
IRQ_HANDLED
;
}
static
void
cafe_nand_bug
(
struct
mtd_info
*
mtd
)
{
BUG
();
}
static
int
cafe_nand_write_oob
(
struct
mtd_info
*
mtd
,
struct
nand_chip
*
chip
,
int
page
)
{
int
status
=
0
;
chip
->
cmdfunc
(
mtd
,
NAND_CMD_SEQIN
,
mtd
->
writesize
,
page
);
chip
->
write_buf
(
mtd
,
chip
->
oob_poi
,
mtd
->
oobsize
);
chip
->
cmdfunc
(
mtd
,
NAND_CMD_PAGEPROG
,
-
1
,
-
1
);
status
=
chip
->
waitfunc
(
mtd
,
chip
);
return
status
&
NAND_STATUS_FAIL
?
-
EIO
:
0
;
}
/* Don't use -- use nand_read_oob_std for now */
static
int
cafe_nand_read_oob
(
struct
mtd_info
*
mtd
,
struct
nand_chip
*
chip
,
int
page
,
int
sndcmd
)
{
chip
->
cmdfunc
(
mtd
,
NAND_CMD_READOOB
,
0
,
page
);
chip
->
read_buf
(
mtd
,
chip
->
oob_poi
,
mtd
->
oobsize
);
return
1
;
}
/**
* cafe_nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
*
* The hw generator calculates the error syndrome automatically. Therefor
* we need a special oob layout and handling.
*/
static
int
cafe_nand_read_page
(
struct
mtd_info
*
mtd
,
struct
nand_chip
*
chip
,
uint8_t
*
buf
)
{
struct
cafe_priv
*
cafe
=
mtd
->
priv
;
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"ECC result %08x SYN1,2 %08x
\n
"
,
cafe_readl
(
cafe
,
NAND_ECC_RESULT
),
cafe_readl
(
cafe
,
NAND_ECC_SYN01
));
chip
->
read_buf
(
mtd
,
buf
,
mtd
->
writesize
);
chip
->
read_buf
(
mtd
,
chip
->
oob_poi
,
mtd
->
oobsize
);
if
(
checkecc
&&
cafe_readl
(
cafe
,
NAND_ECC_RESULT
)
&
(
1
<<
18
))
{
unsigned
short
syn
[
8
];
int
i
;
for
(
i
=
0
;
i
<
8
;
i
+=
2
)
{
uint32_t
tmp
=
cafe_readl
(
cafe
,
NAND_ECC_SYN01
+
(
i
*
2
));
syn
[
i
]
=
tmp
&
0xfff
;
syn
[
i
+
1
]
=
(
tmp
>>
16
)
&
0xfff
;
}
if
((
i
=
cafe_correct_ecc
(
buf
,
syn
))
<
0
)
{
dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Failed to correct ECC at %08x
\n
"
,
cafe_readl
(
cafe
,
NAND_ADDR2
)
*
2048
);
for
(
i
=
0
;
i
<
0x5c
;
i
+=
4
)
printk
(
"Register %x: %08x
\n
"
,
i
,
readl
(
cafe
->
mmio
+
i
));
mtd
->
ecc_stats
.
failed
++
;
}
else
{
dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Corrected %d symbol errors
\n
"
,
i
);
mtd
->
ecc_stats
.
corrected
+=
i
;
}
}
return
0
;
}
static
struct
nand_ecclayout
cafe_oobinfo_2048
=
{
.
eccbytes
=
14
,
.
eccpos
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
},
.
oobfree
=
{{
14
,
50
}}
};
/* Ick. The BBT code really ought to be able to work this bit out
for itself from the above, at least for the 2KiB case */
static
uint8_t
cafe_bbt_pattern_2048
[]
=
{
'B'
,
'b'
,
't'
,
'0'
};
static
uint8_t
cafe_mirror_pattern_2048
[]
=
{
'1'
,
't'
,
'b'
,
'B'
};
static
uint8_t
cafe_bbt_pattern_512
[]
=
{
0xBB
};
static
uint8_t
cafe_mirror_pattern_512
[]
=
{
0xBC
};
static
struct
nand_bbt_descr
cafe_bbt_main_descr_2048
=
{
.
options
=
NAND_BBT_LASTBLOCK
|
NAND_BBT_CREATE
|
NAND_BBT_WRITE
|
NAND_BBT_2BIT
|
NAND_BBT_VERSION
|
NAND_BBT_PERCHIP
,
.
offs
=
14
,
.
len
=
4
,
.
veroffs
=
18
,
.
maxblocks
=
4
,
.
pattern
=
cafe_bbt_pattern_2048
};
static
struct
nand_bbt_descr
cafe_bbt_mirror_descr_2048
=
{
.
options
=
NAND_BBT_LASTBLOCK
|
NAND_BBT_CREATE
|
NAND_BBT_WRITE
|
NAND_BBT_2BIT
|
NAND_BBT_VERSION
|
NAND_BBT_PERCHIP
,
.
offs
=
14
,
.
len
=
4
,
.
veroffs
=
18
,
.
maxblocks
=
4
,
.
pattern
=
cafe_mirror_pattern_2048
};
static
struct
nand_ecclayout
cafe_oobinfo_512
=
{
.
eccbytes
=
14
,
.
eccpos
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
},
.
oobfree
=
{{
14
,
2
}}
};
static
struct
nand_bbt_descr
cafe_bbt_main_descr_512
=
{
.
options
=
NAND_BBT_LASTBLOCK
|
NAND_BBT_CREATE
|
NAND_BBT_WRITE
|
NAND_BBT_2BIT
|
NAND_BBT_VERSION
|
NAND_BBT_PERCHIP
,
.
offs
=
14
,
.
len
=
1
,
.
veroffs
=
15
,
.
maxblocks
=
4
,
.
pattern
=
cafe_bbt_pattern_512
};
static
struct
nand_bbt_descr
cafe_bbt_mirror_descr_512
=
{
.
options
=
NAND_BBT_LASTBLOCK
|
NAND_BBT_CREATE
|
NAND_BBT_WRITE
|
NAND_BBT_2BIT
|
NAND_BBT_VERSION
|
NAND_BBT_PERCHIP
,
.
offs
=
14
,
.
len
=
1
,
.
veroffs
=
15
,
.
maxblocks
=
4
,
.
pattern
=
cafe_mirror_pattern_512
};
static
void
cafe_nand_write_page_lowlevel
(
struct
mtd_info
*
mtd
,
struct
nand_chip
*
chip
,
const
uint8_t
*
buf
)
{
struct
cafe_priv
*
cafe
=
mtd
->
priv
;
chip
->
write_buf
(
mtd
,
buf
,
mtd
->
writesize
);
chip
->
write_buf
(
mtd
,
chip
->
oob_poi
,
mtd
->
oobsize
);
/* Set up ECC autogeneration */
cafe
->
ctl2
|=
(
1
<<
30
);
}
static
int
cafe_nand_write_page
(
struct
mtd_info
*
mtd
,
struct
nand_chip
*
chip
,
const
uint8_t
*
buf
,
int
page
,
int
cached
,
int
raw
)
{
int
status
;
chip
->
cmdfunc
(
mtd
,
NAND_CMD_SEQIN
,
0x00
,
page
);
if
(
unlikely
(
raw
))
chip
->
ecc
.
write_page_raw
(
mtd
,
chip
,
buf
);
else
chip
->
ecc
.
write_page
(
mtd
,
chip
,
buf
);
/*
* Cached progamming disabled for now, Not sure if its worth the
* trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
*/
cached
=
0
;
if
(
!
cached
||
!
(
chip
->
options
&
NAND_CACHEPRG
))
{
chip
->
cmdfunc
(
mtd
,
NAND_CMD_PAGEPROG
,
-
1
,
-
1
);
status
=
chip
->
waitfunc
(
mtd
,
chip
);
/*
* See if operation failed and additional status checks are
* available
*/
if
((
status
&
NAND_STATUS_FAIL
)
&&
(
chip
->
errstat
))
status
=
chip
->
errstat
(
mtd
,
chip
,
FL_WRITING
,
status
,
page
);
if
(
status
&
NAND_STATUS_FAIL
)
return
-
EIO
;
}
else
{
chip
->
cmdfunc
(
mtd
,
NAND_CMD_CACHEDPROG
,
-
1
,
-
1
);
status
=
chip
->
waitfunc
(
mtd
,
chip
);
}
#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
/* Send command to read back the data */
chip
->
cmdfunc
(
mtd
,
NAND_CMD_READ0
,
0
,
page
);
if
(
chip
->
verify_buf
(
mtd
,
buf
,
mtd
->
writesize
))
return
-
EIO
;
#endif
return
0
;
}
static
int
cafe_nand_block_bad
(
struct
mtd_info
*
mtd
,
loff_t
ofs
,
int
getchip
)
{
return
0
;
}
static
int
__devinit
cafe_nand_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
struct
mtd_info
*
mtd
;
struct
cafe_priv
*
cafe
;
uint32_t
ctrl
;
int
err
=
0
;
err
=
pci_enable_device
(
pdev
);
if
(
err
)
return
err
;
pci_set_master
(
pdev
);
mtd
=
kzalloc
(
sizeof
(
*
mtd
)
+
sizeof
(
struct
cafe_priv
),
GFP_KERNEL
);
if
(
!
mtd
)
{
dev_warn
(
&
pdev
->
dev
,
"failed to alloc mtd_info
\n
"
);
return
-
ENOMEM
;
}
cafe
=
(
void
*
)(
&
mtd
[
1
]);
mtd
->
priv
=
cafe
;
mtd
->
owner
=
THIS_MODULE
;
cafe
->
pdev
=
pdev
;
cafe
->
mmio
=
pci_iomap
(
pdev
,
0
,
0
);
if
(
!
cafe
->
mmio
)
{
dev_warn
(
&
pdev
->
dev
,
"failed to iomap
\n
"
);
err
=
-
ENOMEM
;
goto
out_free_mtd
;
}
cafe
->
dmabuf
=
dma_alloc_coherent
(
&
cafe
->
pdev
->
dev
,
2112
+
sizeof
(
struct
nand_buffers
),
&
cafe
->
dmaaddr
,
GFP_KERNEL
);
if
(
!
cafe
->
dmabuf
)
{
err
=
-
ENOMEM
;
goto
out_ior
;
}
cafe
->
nand
.
buffers
=
(
void
*
)
cafe
->
dmabuf
+
2112
;
cafe
->
nand
.
cmdfunc
=
cafe_nand_cmdfunc
;
cafe
->
nand
.
dev_ready
=
cafe_device_ready
;
cafe
->
nand
.
read_byte
=
cafe_read_byte
;
cafe
->
nand
.
read_buf
=
cafe_read_buf
;
cafe
->
nand
.
write_buf
=
cafe_write_buf
;
cafe
->
nand
.
select_chip
=
cafe_select_chip
;
cafe
->
nand
.
chip_delay
=
0
;
/* Enable the following for a flash based bad block table */
cafe
->
nand
.
options
=
NAND_USE_FLASH_BBT
|
NAND_NO_AUTOINCR
|
NAND_OWN_BUFFERS
;
if
(
skipbbt
)
{
cafe
->
nand
.
options
|=
NAND_SKIP_BBTSCAN
;
cafe
->
nand
.
block_bad
=
cafe_nand_block_bad
;
}
/* Start off by resetting the NAND controller completely */
cafe_writel
(
cafe
,
1
,
NAND_RESET
);
cafe_writel
(
cafe
,
0
,
NAND_RESET
);
cafe_writel
(
cafe
,
0xffffffff
,
NAND_IRQ_MASK
);
/* Timings from Marvell's test code (not verified or calculated by us) */
if
(
!
slowtiming
)
{
cafe_writel
(
cafe
,
0x01010a0a
,
NAND_TIMING1
);
cafe_writel
(
cafe
,
0x24121212
,
NAND_TIMING2
);
cafe_writel
(
cafe
,
0x11000000
,
NAND_TIMING3
);
}
else
{
cafe_writel
(
cafe
,
0xffffffff
,
NAND_TIMING1
);
cafe_writel
(
cafe
,
0xffffffff
,
NAND_TIMING2
);
cafe_writel
(
cafe
,
0xffffffff
,
NAND_TIMING3
);
}
cafe_writel
(
cafe
,
0xffffffff
,
NAND_IRQ_MASK
);
err
=
request_irq
(
pdev
->
irq
,
&
cafe_nand_interrupt
,
SA_SHIRQ
,
"CAFE NAND"
,
mtd
);
if
(
err
)
{
dev_warn
(
&
pdev
->
dev
,
"Could not register IRQ %d
\n
"
,
pdev
->
irq
);
goto
out_free_dma
;
}
#if 1
/* Disable master reset, enable NAND clock */
ctrl
=
cafe_readl
(
cafe
,
GLOBAL_CTRL
);
ctrl
&=
0xffffeff0
;
ctrl
|=
0x00007000
;
cafe_writel
(
cafe
,
ctrl
|
0x05
,
GLOBAL_CTRL
);
cafe_writel
(
cafe
,
ctrl
|
0x0a
,
GLOBAL_CTRL
);
cafe_writel
(
cafe
,
0
,
NAND_DMA_CTRL
);
cafe_writel
(
cafe
,
0x7006
,
GLOBAL_CTRL
);
cafe_writel
(
cafe
,
0x700a
,
GLOBAL_CTRL
);
/* Set up DMA address */
cafe_writel
(
cafe
,
cafe
->
dmaaddr
&
0xffffffff
,
NAND_DMA_ADDR0
);
if
(
sizeof
(
cafe
->
dmaaddr
)
>
4
)
/* Shift in two parts to shut the compiler up */
cafe_writel
(
cafe
,
(
cafe
->
dmaaddr
>>
16
)
>>
16
,
NAND_DMA_ADDR1
);
else
cafe_writel
(
cafe
,
0
,
NAND_DMA_ADDR1
);
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Set DMA address to %x (virt %p)
\n
"
,
cafe_readl
(
cafe
,
NAND_DMA_ADDR0
),
cafe
->
dmabuf
);
/* Enable NAND IRQ in global IRQ mask register */
cafe_writel
(
cafe
,
0x80000007
,
GLOBAL_IRQ_MASK
);
cafe_dev_dbg
(
&
cafe
->
pdev
->
dev
,
"Control %x, IRQ mask %x
\n
"
,
cafe_readl
(
cafe
,
GLOBAL_CTRL
),
cafe_readl
(
cafe
,
GLOBAL_IRQ_MASK
));
#endif
#if 1
mtd
->
writesize
=
2048
;
mtd
->
oobsize
=
0x40
;
memset
(
cafe
->
dmabuf
,
0x5a
,
2112
);
cafe
->
nand
.
cmdfunc
(
mtd
,
NAND_CMD_READID
,
0
,
-
1
);
cafe
->
nand
.
read_byte
(
mtd
);
cafe
->
nand
.
read_byte
(
mtd
);
cafe
->
nand
.
read_byte
(
mtd
);
cafe
->
nand
.
read_byte
(
mtd
);
cafe
->
nand
.
read_byte
(
mtd
);
#endif
#if 0
cafe->nand.cmdfunc(mtd, NAND_CMD_READ0, 0, 0);
// nand_wait_ready(mtd);
cafe->nand.read_byte(mtd);
cafe->nand.read_byte(mtd);
cafe->nand.read_byte(mtd);
cafe->nand.read_byte(mtd);
#endif
#if 0
writel(0x84600070, cafe->mmio);
udelay(10);
cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", cafe_readl(cafe, NAND_NONMEM));
#endif
/* Scan to find existance of the device */
if
(
nand_scan_ident
(
mtd
,
1
))
{
err
=
-
ENXIO
;
goto
out_irq
;
}
cafe
->
ctl2
=
1
<<
27
;
/* Reed-Solomon ECC */
if
(
mtd
->
writesize
==
2048
)
cafe
->
ctl2
|=
1
<<
29
;
/* 2KiB page size */
/* Set up ECC according to the type of chip we found */
if
(
mtd
->
writesize
==
2048
)
{
cafe
->
nand
.
ecc
.
layout
=
&
cafe_oobinfo_2048
;
cafe
->
nand
.
bbt_td
=
&
cafe_bbt_main_descr_2048
;
cafe
->
nand
.
bbt_md
=
&
cafe_bbt_mirror_descr_2048
;
}
else
if
(
mtd
->
writesize
==
512
)
{
cafe
->
nand
.
ecc
.
layout
=
&
cafe_oobinfo_512
;
cafe
->
nand
.
bbt_td
=
&
cafe_bbt_main_descr_512
;
cafe
->
nand
.
bbt_md
=
&
cafe_bbt_mirror_descr_512
;
}
else
{
printk
(
KERN_WARNING
"Unexpected NAND flash writesize %d. Aborting
\n
"
,
mtd
->
writesize
);
goto
out_irq
;
}
cafe
->
nand
.
ecc
.
mode
=
NAND_ECC_HW_SYNDROME
;
cafe
->
nand
.
ecc
.
size
=
mtd
->
writesize
;
cafe
->
nand
.
ecc
.
bytes
=
14
;
cafe
->
nand
.
ecc
.
hwctl
=
(
void
*
)
cafe_nand_bug
;
cafe
->
nand
.
ecc
.
calculate
=
(
void
*
)
cafe_nand_bug
;
cafe
->
nand
.
ecc
.
correct
=
(
void
*
)
cafe_nand_bug
;
cafe
->
nand
.
write_page
=
cafe_nand_write_page
;
cafe
->
nand
.
ecc
.
write_page
=
cafe_nand_write_page_lowlevel
;
cafe
->
nand
.
ecc
.
write_oob
=
cafe_nand_write_oob
;
cafe
->
nand
.
ecc
.
read_page
=
cafe_nand_read_page
;
cafe
->
nand
.
ecc
.
read_oob
=
cafe_nand_read_oob
;
err
=
nand_scan_tail
(
mtd
);
if
(
err
)
goto
out_irq
;
pci_set_drvdata
(
pdev
,
mtd
);
add_mtd_device
(
mtd
);
goto
out
;
out_irq:
/* Disable NAND IRQ in global IRQ mask register */
cafe_writel
(
cafe
,
~
1
&
cafe_readl
(
cafe
,
GLOBAL_IRQ_MASK
),
GLOBAL_IRQ_MASK
);
free_irq
(
pdev
->
irq
,
mtd
);
out_free_dma:
dma_free_coherent
(
&
cafe
->
pdev
->
dev
,
2112
,
cafe
->
dmabuf
,
cafe
->
dmaaddr
);
out_ior:
pci_iounmap
(
pdev
,
cafe
->
mmio
);
out_free_mtd:
kfree
(
mtd
);
out:
return
err
;
}
static
void
__devexit
cafe_nand_remove
(
struct
pci_dev
*
pdev
)
{
struct
mtd_info
*
mtd
=
pci_get_drvdata
(
pdev
);
struct
cafe_priv
*
cafe
=
mtd
->
priv
;
del_mtd_device
(
mtd
);
/* Disable NAND IRQ in global IRQ mask register */
cafe_writel
(
cafe
,
~
1
&
cafe_readl
(
cafe
,
GLOBAL_IRQ_MASK
),
GLOBAL_IRQ_MASK
);
free_irq
(
pdev
->
irq
,
mtd
);
nand_release
(
mtd
);
pci_iounmap
(
pdev
,
cafe
->
mmio
);
dma_free_coherent
(
&
cafe
->
pdev
->
dev
,
2112
,
cafe
->
dmabuf
,
cafe
->
dmaaddr
);
kfree
(
mtd
);
}
static
struct
pci_device_id
cafe_nand_tbl
[]
=
{
{
0x11ab
,
0x4100
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_CLASS_MEMORY_FLASH
<<
8
,
0xFFFF0
}
};
MODULE_DEVICE_TABLE
(
pci
,
cafe_nand_tbl
);
static
struct
pci_driver
cafe_nand_pci_driver
=
{
.
name
=
"CAFÉ NAND"
,
.
id_table
=
cafe_nand_tbl
,
.
probe
=
cafe_nand_probe
,
.
remove
=
__devexit_p
(
cafe_nand_remove
),
#ifdef CONFIG_PMx
.
suspend
=
cafe_nand_suspend
,
.
resume
=
cafe_nand_resume
,
#endif
};
static
int
cafe_nand_init
(
void
)
{
return
pci_register_driver
(
&
cafe_nand_pci_driver
);
}
static
void
cafe_nand_exit
(
void
)
{
pci_unregister_driver
(
&
cafe_nand_pci_driver
);
}
module_init
(
cafe_nand_init
);
module_exit
(
cafe_nand_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"David Woodhouse <dwmw2@infradead.org>"
);
MODULE_DESCRIPTION
(
"NAND flash driver for OLPC CAFE chip"
);
/* Correct ECC for 2048 bytes of 0xff:
41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */
/* dwmw2's B-test board, in case of completely screwing it:
Bad eraseblock 2394 at 0x12b40000
Bad eraseblock 2627 at 0x14860000
Bad eraseblock 3349 at 0x1a2a0000
*/
drivers/mtd/nand/cafe_ecc.c
0 → 100644
View file @
1aaaeabf
/* Error correction for CAFÉ NAND controller
*
* © 2006 Marvell, Inc.
* Author: Tom Chiou
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
static
unsigned
short
gf4096_mul
(
unsigned
short
,
unsigned
short
);
static
unsigned
short
gf64_mul
(
unsigned
short
,
unsigned
short
);
static
unsigned
short
gf4096_inv
(
unsigned
short
);
static
unsigned
short
err_pos
(
unsigned
short
);
static
void
find_4bit_err_coefs
(
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
*
);
static
void
zero_4x5_col3
(
unsigned
short
[
4
][
5
]);
static
void
zero_4x5_col2
(
unsigned
short
[
4
][
5
]);
static
void
zero_4x5_col1
(
unsigned
short
[
4
][
5
]);
static
void
swap_4x5_rows
(
unsigned
short
[
4
][
5
],
int
,
int
,
int
);
static
void
swap_2x3_rows
(
unsigned
short
m
[
2
][
3
]);
static
void
solve_4x5
(
unsigned
short
m
[
4
][
5
],
unsigned
short
*
,
int
*
);
static
void
sort_coefs
(
int
*
,
unsigned
short
*
,
int
);
static
void
find_4bit_err_pats
(
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
*
);
static
void
find_3bit_err_coefs
(
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
*
);
static
void
zero_3x4_col2
(
unsigned
short
[
3
][
4
]);
static
void
zero_3x4_col1
(
unsigned
short
[
3
][
4
]);
static
void
swap_3x4_rows
(
unsigned
short
[
3
][
4
],
int
,
int
,
int
);
static
void
solve_3x4
(
unsigned
short
[
3
][
4
],
unsigned
short
*
,
int
*
);
static
void
find_3bit_err_pats
(
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
*
);
static
void
find_2bit_err_pats
(
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
*
);
static
void
find_2x2_soln
(
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
,
unsigned
short
*
);
static
void
solve_2x3
(
unsigned
short
[
2
][
3
],
unsigned
short
*
);
static
int
chk_no_err_only
(
unsigned
short
*
,
unsigned
short
*
);
static
int
chk_1_err_only
(
unsigned
short
*
,
unsigned
short
*
);
static
int
chk_2_err_only
(
unsigned
short
*
,
unsigned
short
*
);
static
int
chk_3_err_only
(
unsigned
short
*
,
unsigned
short
*
);
static
int
chk_4_err_only
(
unsigned
short
*
,
unsigned
short
*
);
static
unsigned
short
gf64_mul
(
unsigned
short
a
,
unsigned
short
b
)
{
unsigned
short
tmp1
,
tmp2
,
tmp3
,
tmp4
,
tmp5
;
unsigned
short
c_bit0
,
c_bit1
,
c_bit2
,
c_bit3
,
c_bit4
,
c_bit5
,
c
;
tmp1
=
((
a
)
^
(
a
>>
5
));
tmp2
=
((
a
>>
4
)
^
(
a
>>
5
));
tmp3
=
((
a
>>
3
)
^
(
a
>>
4
));
tmp4
=
((
a
>>
2
)
^
(
a
>>
3
));
tmp5
=
((
a
>>
1
)
^
(
a
>>
2
));
c_bit0
=
((
a
&
b
)
^
((
a
>>
5
)
&
(
b
>>
1
))
^
((
a
>>
4
)
&
(
b
>>
2
))
^
((
a
>>
3
)
&
(
b
>>
3
))
^
((
a
>>
2
)
&
(
b
>>
4
))
^
((
a
>>
1
)
&
(
b
>>
5
)))
&
0x1
;
c_bit1
=
(((
a
>>
1
)
&
b
)
^
(
tmp1
&
(
b
>>
1
))
^
(
tmp2
&
(
b
>>
2
))
^
(
tmp3
&
(
b
>>
3
))
^
(
tmp4
&
(
b
>>
4
))
^
(
tmp5
&
(
b
>>
5
)))
&
0x1
;
c_bit2
=
(((
a
>>
2
)
&
b
)
^
((
a
>>
1
)
&
(
b
>>
1
))
^
(
tmp1
&
(
b
>>
2
))
^
(
tmp2
&
(
b
>>
3
))
^
(
tmp3
&
(
b
>>
4
))
^
(
tmp4
&
(
b
>>
5
)))
&
0x1
;
c_bit3
=
(((
a
>>
3
)
&
b
)
^
((
a
>>
2
)
&
(
b
>>
1
))
^
((
a
>>
1
)
&
(
b
>>
2
))
^
(
tmp1
&
(
b
>>
3
))
^
(
tmp2
&
(
b
>>
4
))
^
(
tmp3
&
(
b
>>
5
)))
&
0x1
;
c_bit4
=
(((
a
>>
4
)
&
b
)
^
((
a
>>
3
)
&
(
b
>>
1
))
^
((
a
>>
2
)
&
(
b
>>
2
))
^
((
a
>>
1
)
&
(
b
>>
3
))
^
(
tmp1
&
(
b
>>
4
))
^
(
tmp2
&
(
b
>>
5
)))
&
0x1
;
c_bit5
=
(((
a
>>
5
)
&
b
)
^
((
a
>>
4
)
&
(
b
>>
1
))
^
((
a
>>
3
)
&
(
b
>>
2
))
^
((
a
>>
2
)
&
(
b
>>
3
))
^
((
a
>>
1
)
&
(
b
>>
4
))
^
(
tmp1
&
(
b
>>
5
)))
&
0x1
;
c
=
c_bit0
|
(
c_bit1
<<
1
)
|
(
c_bit2
<<
2
)
|
(
c_bit3
<<
3
)
|
(
c_bit4
<<
4
)
|
(
c_bit5
<<
5
);
return
c
;
}
static
unsigned
short
gf4096_mul
(
unsigned
short
a
,
unsigned
short
b
)
{
unsigned
short
ah
,
al
,
bh
,
bl
,
alxah
,
blxbh
,
ablh
,
albl
,
ahbh
,
ahbhB
,
c
;
ah
=
(
a
>>
6
)
&
0x3f
;
al
=
a
&
0x3f
;
bh
=
(
b
>>
6
)
&
0x3f
;
bl
=
b
&
0x3f
;
alxah
=
al
^
ah
;
blxbh
=
bl
^
bh
;
ablh
=
gf64_mul
(
alxah
,
blxbh
);
albl
=
gf64_mul
(
al
,
bl
);
ahbh
=
gf64_mul
(
ah
,
bh
);
ahbhB
=
((
ahbh
&
0x1
)
<<
5
)
|
((
ahbh
&
0x20
)
>>
1
)
|
((
ahbh
&
0x10
)
>>
1
)
|
((
ahbh
&
0x8
)
>>
1
)
|
((
ahbh
&
0x4
)
>>
1
)
|
(((
ahbh
>>
1
)
^
ahbh
)
&
0x1
);
c
=
((
ablh
^
albl
)
<<
6
)
|
(
ahbhB
^
albl
);
return
c
;
}
static
void
find_2bit_err_pats
(
unsigned
short
s0
,
unsigned
short
s1
,
unsigned
short
r0
,
unsigned
short
r1
,
unsigned
short
*
pats
)
{
find_2x2_soln
(
0x1
,
0x1
,
r0
,
r1
,
s0
,
s1
,
pats
);
}
static
void
find_3bit_err_coefs
(
unsigned
short
s0
,
unsigned
short
s1
,
unsigned
short
s2
,
unsigned
short
s3
,
unsigned
short
s4
,
unsigned
short
s5
,
unsigned
short
*
coefs
)
{
unsigned
short
m
[
3
][
4
];
int
row_order
[
3
];
row_order
[
0
]
=
0
;
row_order
[
1
]
=
1
;
row_order
[
2
]
=
2
;
m
[
0
][
0
]
=
s2
;
m
[
0
][
1
]
=
s1
;
m
[
0
][
2
]
=
s0
;
m
[
0
][
3
]
=
s3
;
m
[
1
][
0
]
=
s3
;
m
[
1
][
1
]
=
s2
;
m
[
1
][
2
]
=
s1
;
m
[
1
][
3
]
=
s4
;
m
[
2
][
0
]
=
s4
;
m
[
2
][
1
]
=
s3
;
m
[
2
][
2
]
=
s2
;
m
[
2
][
3
]
=
s5
;
if
(
m
[
0
][
2
]
!=
0x0
)
{
zero_3x4_col2
(
m
);
}
else
if
(
m
[
1
][
2
]
!=
0x0
)
{
swap_3x4_rows
(
m
,
0
,
1
,
4
);
zero_3x4_col2
(
m
);
}
else
if
(
m
[
2
][
2
]
!=
0x0
)
{
swap_3x4_rows
(
m
,
0
,
2
,
4
);
zero_3x4_col2
(
m
);
}
else
{
printk
(
KERN_ERR
"Error: find_3bit_err_coefs, s0,s1,s2 all zeros!
\n
"
);
}
if
(
m
[
1
][
1
]
!=
0x0
)
{
zero_3x4_col1
(
m
);
}
else
if
(
m
[
2
][
1
]
!=
0x0
)
{
swap_3x4_rows
(
m
,
1
,
2
,
4
);
zero_3x4_col1
(
m
);
}
else
{
printk
(
KERN_ERR
"Error: find_3bit_err_coefs, cannot resolve col 1!
\n
"
);
}
/* solve coefs */
solve_3x4
(
m
,
coefs
,
row_order
);
}
static
void
zero_3x4_col2
(
unsigned
short
m
[
3
][
4
])
{
unsigned
short
minv1
,
minv2
;
minv1
=
gf4096_mul
(
m
[
1
][
2
],
gf4096_inv
(
m
[
0
][
2
]));
minv2
=
gf4096_mul
(
m
[
2
][
2
],
gf4096_inv
(
m
[
0
][
2
]));
m
[
1
][
0
]
=
m
[
1
][
0
]
^
gf4096_mul
(
m
[
0
][
0
],
minv1
);
m
[
1
][
1
]
=
m
[
1
][
1
]
^
gf4096_mul
(
m
[
0
][
1
],
minv1
);
m
[
1
][
3
]
=
m
[
1
][
3
]
^
gf4096_mul
(
m
[
0
][
3
],
minv1
);
m
[
2
][
0
]
=
m
[
2
][
0
]
^
gf4096_mul
(
m
[
0
][
0
],
minv2
);
m
[
2
][
1
]
=
m
[
2
][
1
]
^
gf4096_mul
(
m
[
0
][
1
],
minv2
);
m
[
2
][
3
]
=
m
[
2
][
3
]
^
gf4096_mul
(
m
[
0
][
3
],
minv2
);
}
static
void
zero_3x4_col1
(
unsigned
short
m
[
3
][
4
])
{
unsigned
short
minv
;
minv
=
gf4096_mul
(
m
[
2
][
1
],
gf4096_inv
(
m
[
1
][
1
]));
m
[
2
][
0
]
=
m
[
2
][
0
]
^
gf4096_mul
(
m
[
1
][
0
],
minv
);
m
[
2
][
3
]
=
m
[
2
][
3
]
^
gf4096_mul
(
m
[
1
][
3
],
minv
);
}
static
void
swap_3x4_rows
(
unsigned
short
m
[
3
][
4
],
int
i
,
int
j
,
int
col_width
)
{
unsigned
short
tmp0
;
int
cnt
;
for
(
cnt
=
0
;
cnt
<
col_width
;
cnt
++
)
{
tmp0
=
m
[
i
][
cnt
];
m
[
i
][
cnt
]
=
m
[
j
][
cnt
];
m
[
j
][
cnt
]
=
tmp0
;
}
}
static
void
solve_3x4
(
unsigned
short
m
[
3
][
4
],
unsigned
short
*
coefs
,
int
*
row_order
)
{
unsigned
short
tmp
[
3
];
tmp
[
0
]
=
gf4096_mul
(
m
[
2
][
3
],
gf4096_inv
(
m
[
2
][
0
]));
tmp
[
1
]
=
gf4096_mul
((
gf4096_mul
(
tmp
[
0
],
m
[
1
][
0
])
^
m
[
1
][
3
]),
gf4096_inv
(
m
[
1
][
1
]));
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
]));
sort_coefs
(
row_order
,
tmp
,
3
);
coefs
[
0
]
=
tmp
[
0
];
coefs
[
1
]
=
tmp
[
1
];
coefs
[
2
]
=
tmp
[
2
];
}
static
void
find_3bit_err_pats
(
unsigned
short
s0
,
unsigned
short
s1
,
unsigned
short
s2
,
unsigned
short
r0
,
unsigned
short
r1
,
unsigned
short
r2
,
unsigned
short
*
pats
)
{
find_2x2_soln
(
r0
^
r2
,
r1
^
r2
,
gf4096_mul
(
r0
,
r0
^
r2
),
gf4096_mul
(
r1
,
r1
^
r2
),
gf4096_mul
(
s0
,
r2
)
^
s1
,
gf4096_mul
(
s1
,
r2
)
^
s2
,
pats
);
pats
[
2
]
=
s0
^
pats
[
0
]
^
pats
[
1
];
}
static
void
find_4bit_err_coefs
(
unsigned
short
s0
,
unsigned
short
s1
,
unsigned
short
s2
,
unsigned
short
s3
,
unsigned
short
s4
,
unsigned
short
s5
,
unsigned
short
s6
,
unsigned
short
s7
,
unsigned
short
*
coefs
)
{
unsigned
short
m
[
4
][
5
];
int
row_order
[
4
];
row_order
[
0
]
=
0
;
row_order
[
1
]
=
1
;
row_order
[
2
]
=
2
;
row_order
[
3
]
=
3
;
m
[
0
][
0
]
=
s3
;
m
[
0
][
1
]
=
s2
;
m
[
0
][
2
]
=
s1
;
m
[
0
][
3
]
=
s0
;
m
[
0
][
4
]
=
s4
;
m
[
1
][
0
]
=
s4
;
m
[
1
][
1
]
=
s3
;
m
[
1
][
2
]
=
s2
;
m
[
1
][
3
]
=
s1
;
m
[
1
][
4
]
=
s5
;
m
[
2
][
0
]
=
s5
;
m
[
2
][
1
]
=
s4
;
m
[
2
][
2
]
=
s3
;
m
[
2
][
3
]
=
s2
;
m
[
2
][
4
]
=
s6
;
m
[
3
][
0
]
=
s6
;
m
[
3
][
1
]
=
s5
;
m
[
3
][
2
]
=
s4
;
m
[
3
][
3
]
=
s3
;
m
[
3
][
4
]
=
s7
;
if
(
m
[
0
][
3
]
!=
0x0
)
{
zero_4x5_col3
(
m
);
}
else
if
(
m
[
1
][
3
]
!=
0x0
)
{
swap_4x5_rows
(
m
,
0
,
1
,
5
);
zero_4x5_col3
(
m
);
}
else
if
(
m
[
2
][
3
]
!=
0x0
)
{
swap_4x5_rows
(
m
,
0
,
2
,
5
);
zero_4x5_col3
(
m
);
}
else
if
(
m
[
3
][
3
]
!=
0x0
)
{
swap_4x5_rows
(
m
,
0
,
3
,
5
);
zero_4x5_col3
(
m
);
}
else
{
printk
(
KERN_ERR
"Error: find_4bit_err_coefs, s0,s1,s2,s3 all zeros!
\n
"
);
}
if
(
m
[
1
][
2
]
!=
0x0
)
{
zero_4x5_col2
(
m
);
}
else
if
(
m
[
2
][
2
]
!=
0x0
)
{
swap_4x5_rows
(
m
,
1
,
2
,
5
);
zero_4x5_col2
(
m
);
}
else
if
(
m
[
3
][
2
]
!=
0x0
)
{
swap_4x5_rows
(
m
,
1
,
3
,
5
);
zero_4x5_col2
(
m
);
}
else
{
printk
(
KERN_ERR
"Error: find_4bit_err_coefs, cannot resolve col 2!
\n
"
);
}
if
(
m
[
2
][
1
]
!=
0x0
)
{
zero_4x5_col1
(
m
);
}
else
if
(
m
[
3
][
1
]
!=
0x0
)
{
swap_4x5_rows
(
m
,
2
,
3
,
5
);
zero_4x5_col1
(
m
);
}
else
{
printk
(
KERN_ERR
"Error: find_4bit_err_coefs, cannot resolve col 1!
\n
"
);
}
solve_4x5
(
m
,
coefs
,
row_order
);
}
static
void
zero_4x5_col3
(
unsigned
short
m
[
4
][
5
])
{
unsigned
short
minv1
,
minv2
,
minv3
;
minv1
=
gf4096_mul
(
m
[
1
][
3
],
gf4096_inv
(
m
[
0
][
3
]));
minv2
=
gf4096_mul
(
m
[
2
][
3
],
gf4096_inv
(
m
[
0
][
3
]));
minv3
=
gf4096_mul
(
m
[
3
][
3
],
gf4096_inv
(
m
[
0
][
3
]));
m
[
1
][
0
]
=
m
[
1
][
0
]
^
gf4096_mul
(
m
[
0
][
0
],
minv1
);
m
[
1
][
1
]
=
m
[
1
][
1
]
^
gf4096_mul
(
m
[
0
][
1
],
minv1
);
m
[
1
][
2
]
=
m
[
1
][
2
]
^
gf4096_mul
(
m
[
0
][
2
],
minv1
);
m
[
1
][
4
]
=
m
[
1
][
4
]
^
gf4096_mul
(
m
[
0
][
4
],
minv1
);
m
[
2
][
0
]
=
m
[
2
][
0
]
^
gf4096_mul
(
m
[
0
][
0
],
minv2
);
m
[
2
][
1
]
=
m
[
2
][
1
]
^
gf4096_mul
(
m
[
0
][
1
],
minv2
);
m
[
2
][
2
]
=
m
[
2
][
2
]
^
gf4096_mul
(
m
[
0
][
2
],
minv2
);
m
[
2
][
4
]
=
m
[
2
][
4
]
^
gf4096_mul
(
m
[
0
][
4
],
minv2
);
m
[
3
][
0
]
=
m
[
3
][
0
]
^
gf4096_mul
(
m
[
0
][
0
],
minv3
);
m
[
3
][
1
]
=
m
[
3
][
1
]
^
gf4096_mul
(
m
[
0
][
1
],
minv3
);
m
[
3
][
2
]
=
m
[
3
][
2
]
^
gf4096_mul
(
m
[
0
][
2
],
minv3
);
m
[
3
][
4
]
=
m
[
3
][
4
]
^
gf4096_mul
(
m
[
0
][
4
],
minv3
);
}
static
void
zero_4x5_col2
(
unsigned
short
m
[
4
][
5
])
{
unsigned
short
minv2
,
minv3
;
minv2
=
gf4096_mul
(
m
[
2
][
2
],
gf4096_inv
(
m
[
1
][
2
]));
minv3
=
gf4096_mul
(
m
[
3
][
2
],
gf4096_inv
(
m
[
1
][
2
]));
m
[
2
][
0
]
=
m
[
2
][
0
]
^
gf4096_mul
(
m
[
1
][
0
],
minv2
);
m
[
2
][
1
]
=
m
[
2
][
1
]
^
gf4096_mul
(
m
[
1
][
1
],
minv2
);
m
[
2
][
4
]
=
m
[
2
][
4
]
^
gf4096_mul
(
m
[
1
][
4
],
minv2
);
m
[
3
][
0
]
=
m
[
3
][
0
]
^
gf4096_mul
(
m
[
1
][
0
],
minv3
);
m
[
3
][
1
]
=
m
[
3
][
1
]
^
gf4096_mul
(
m
[
1
][
1
],
minv3
);
m
[
3
][
4
]
=
m
[
3
][
4
]
^
gf4096_mul
(
m
[
1
][
4
],
minv3
);
}
static
void
zero_4x5_col1
(
unsigned
short
m
[
4
][
5
])
{
unsigned
short
minv
;
minv
=
gf4096_mul
(
m
[
3
][
1
],
gf4096_inv
(
m
[
2
][
1
]));
m
[
3
][
0
]
=
m
[
3
][
0
]
^
gf4096_mul
(
m
[
2
][
0
],
minv
);
m
[
3
][
4
]
=
m
[
3
][
4
]
^
gf4096_mul
(
m
[
2
][
4
],
minv
);
}
static
void
swap_4x5_rows
(
unsigned
short
m
[
4
][
5
],
int
i
,
int
j
,
int
col_width
)
{
unsigned
short
tmp0
;
int
cnt
;
for
(
cnt
=
0
;
cnt
<
col_width
;
cnt
++
)
{
tmp0
=
m
[
i
][
cnt
];
m
[
i
][
cnt
]
=
m
[
j
][
cnt
];
m
[
j
][
cnt
]
=
tmp0
;
}
}
static
void
solve_4x5
(
unsigned
short
m
[
4
][
5
],
unsigned
short
*
coefs
,
int
*
row_order
)
{
unsigned
short
tmp
[
4
];
tmp
[
0
]
=
gf4096_mul
(
m
[
3
][
4
],
gf4096_inv
(
m
[
3
][
0
]));
tmp
[
1
]
=
gf4096_mul
((
gf4096_mul
(
tmp
[
0
],
m
[
2
][
0
])
^
m
[
2
][
4
]),
gf4096_inv
(
m
[
2
][
1
]));
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
]));
tmp
[
3
]
=
gf4096_mul
((
gf4096_mul
(
tmp
[
0
],
m
[
0
][
0
])
^
gf4096_mul
(
tmp
[
1
],
m
[
0
][
1
])
^
gf4096_mul
(
tmp
[
2
],
m
[
0
][
2
])
^
m
[
0
][
4
]),
gf4096_inv
(
m
[
0
][
3
]));
sort_coefs
(
row_order
,
tmp
,
4
);
coefs
[
0
]
=
tmp
[
0
];
coefs
[
1
]
=
tmp
[
1
];
coefs
[
2
]
=
tmp
[
2
];
coefs
[
3
]
=
tmp
[
3
];
}
static
void
sort_coefs
(
int
*
order
,
unsigned
short
*
soln
,
int
len
)
{
int
cnt
,
start_cnt
,
least_ord
,
least_cnt
;
unsigned
short
tmp0
;
for
(
start_cnt
=
0
;
start_cnt
<
len
;
start_cnt
++
)
{
for
(
cnt
=
start_cnt
;
cnt
<
len
;
cnt
++
)
{
if
(
cnt
==
start_cnt
)
{
least_ord
=
order
[
cnt
];
least_cnt
=
start_cnt
;
}
else
{
if
(
least_ord
>
order
[
cnt
])
{
least_ord
=
order
[
cnt
];
least_cnt
=
cnt
;
}
}
}
if
(
least_cnt
!=
start_cnt
)
{
tmp0
=
order
[
least_cnt
];
order
[
least_cnt
]
=
order
[
start_cnt
];
order
[
start_cnt
]
=
tmp0
;
tmp0
=
soln
[
least_cnt
];
soln
[
least_cnt
]
=
soln
[
start_cnt
];
soln
[
start_cnt
]
=
tmp0
;
}
}
}
static
void
find_4bit_err_pats
(
unsigned
short
s0
,
unsigned
short
s1
,
unsigned
short
s2
,
unsigned
short
s3
,
unsigned
short
z1
,
unsigned
short
z2
,
unsigned
short
z3
,
unsigned
short
z4
,
unsigned
short
*
pats
)
{
unsigned
short
z4_z1
,
z3z4_z3z3
,
z4_z2
,
s0z4_s1
,
z1z4_z1z1
,
z4_z3
,
z2z4_z2z2
,
s1z4_s2
,
z3z3z4_z3z3z3
,
z1z1z4_z1z1z1
,
z2z2z4_z2z2z2
,
s2z4_s3
;
unsigned
short
tmp0
,
tmp1
,
tmp2
,
tmp3
;
z4_z1
=
z4
^
z1
;
z3z4_z3z3
=
gf4096_mul
(
z3
,
z4
)
^
gf4096_mul
(
z3
,
z3
);
z4_z2
=
z4
^
z2
;
s0z4_s1
=
gf4096_mul
(
s0
,
z4
)
^
s1
;
z1z4_z1z1
=
gf4096_mul
(
z1
,
z4
)
^
gf4096_mul
(
z1
,
z1
);
z4_z3
=
z4
^
z3
;
z2z4_z2z2
=
gf4096_mul
(
z2
,
z4
)
^
gf4096_mul
(
z2
,
z2
);
s1z4_s2
=
gf4096_mul
(
s1
,
z4
)
^
s2
;
z3z3z4_z3z3z3
=
gf4096_mul
(
gf4096_mul
(
z3
,
z3
),
z4
)
^
gf4096_mul
(
gf4096_mul
(
z3
,
z3
),
z3
);
z1z1z4_z1z1z1
=
gf4096_mul
(
gf4096_mul
(
z1
,
z1
),
z4
)
^
gf4096_mul
(
gf4096_mul
(
z1
,
z1
),
z1
);
z2z2z4_z2z2z2
=
gf4096_mul
(
gf4096_mul
(
z2
,
z2
),
z4
)
^
gf4096_mul
(
gf4096_mul
(
z2
,
z2
),
z2
);
s2z4_s3
=
gf4096_mul
(
s2
,
z4
)
^
s3
;
//find err pat 0,1
find_2x2_soln
(
gf4096_mul
(
z4_z1
,
z3z4_z3z3
)
^
gf4096_mul
(
z1z4_z1z1
,
z4_z3
),
gf4096_mul
(
z4_z2
,
z3z4_z3z3
)
^
gf4096_mul
(
z2z4_z2z2
,
z4_z3
),
gf4096_mul
(
z1z4_z1z1
,
z3z3z4_z3z3z3
)
^
gf4096_mul
(
z1z1z4_z1z1z1
,
z3z4_z3z3
),
gf4096_mul
(
z2z4_z2z2
,
z3z3z4_z3z3z3
)
^
gf4096_mul
(
z2z2z4_z2z2z2
,
z3z4_z3z3
),
gf4096_mul
(
s0z4_s1
,
z3z4_z3z3
)
^
gf4096_mul
(
s1z4_s2
,
z4_z3
),
gf4096_mul
(
s1z4_s2
,
z3z3z4_z3z3z3
)
^
gf4096_mul
(
s2z4_s3
,
z3z4_z3z3
),
pats
);
tmp0
=
pats
[
0
];
tmp1
=
pats
[
1
];
tmp2
=
pats
[
0
]
^
pats
[
1
]
^
s0
;
tmp3
=
gf4096_mul
(
pats
[
0
],
z1
)
^
gf4096_mul
(
pats
[
1
],
z2
)
^
s1
;
//find err pat 2,3
find_2x2_soln
(
0x1
,
0x1
,
z3
,
z4
,
tmp2
,
tmp3
,
pats
);
pats
[
2
]
=
pats
[
0
];
pats
[
3
]
=
pats
[
1
];
pats
[
0
]
=
tmp0
;
pats
[
1
]
=
tmp1
;
}
static
void
find_2x2_soln
(
unsigned
short
c00
,
unsigned
short
c01
,
unsigned
short
c10
,
unsigned
short
c11
,
unsigned
short
lval0
,
unsigned
short
lval1
,
unsigned
short
*
soln
)
{
unsigned
short
m
[
2
][
3
];
m
[
0
][
0
]
=
c00
;
m
[
0
][
1
]
=
c01
;
m
[
0
][
2
]
=
lval0
;
m
[
1
][
0
]
=
c10
;
m
[
1
][
1
]
=
c11
;
m
[
1
][
2
]
=
lval1
;
if
(
m
[
0
][
1
]
!=
0x0
)
{
/* */
}
else
if
(
m
[
1
][
1
]
!=
0x0
)
{
swap_2x3_rows
(
m
);
}
else
{
printk
(
KERN_ERR
"Warning: find_2bit_err_coefs, s0,s1 all zeros!
\n
"
);
}
solve_2x3
(
m
,
soln
);
}
static
void
swap_2x3_rows
(
unsigned
short
m
[
2
][
3
])
{
unsigned
short
tmp0
;
int
cnt
;
for
(
cnt
=
0
;
cnt
<
3
;
cnt
++
)
{
tmp0
=
m
[
0
][
cnt
];
m
[
0
][
cnt
]
=
m
[
1
][
cnt
];
m
[
1
][
cnt
]
=
tmp0
;
}
}
static
void
solve_2x3
(
unsigned
short
m
[
2
][
3
],
unsigned
short
*
coefs
)
{
unsigned
short
minv
;
minv
=
gf4096_mul
(
m
[
1
][
1
],
gf4096_inv
(
m
[
0
][
1
]));
m
[
1
][
0
]
=
m
[
1
][
0
]
^
gf4096_mul
(
m
[
0
][
0
],
minv
);
m
[
1
][
2
]
=
m
[
1
][
2
]
^
gf4096_mul
(
m
[
0
][
2
],
minv
);
coefs
[
0
]
=
gf4096_mul
(
m
[
1
][
2
],
gf4096_inv
(
m
[
1
][
0
]));
coefs
[
1
]
=
gf4096_mul
((
gf4096_mul
(
coefs
[
0
],
m
[
0
][
0
])
^
m
[
0
][
2
]),
gf4096_inv
(
m
[
0
][
1
]));
}
static
unsigned
char
gf64_inv
[
64
]
=
{
0
,
1
,
33
,
62
,
49
,
43
,
31
,
44
,
57
,
37
,
52
,
28
,
46
,
40
,
22
,
25
,
61
,
54
,
51
,
39
,
26
,
35
,
14
,
24
,
23
,
15
,
20
,
34
,
11
,
53
,
45
,
6
,
63
,
2
,
27
,
21
,
56
,
9
,
50
,
19
,
13
,
47
,
48
,
5
,
7
,
30
,
12
,
41
,
42
,
4
,
38
,
18
,
10
,
29
,
17
,
60
,
36
,
8
,
59
,
58
,
55
,
16
,
3
,
32
};
static
unsigned
short
gf4096_inv
(
unsigned
short
din
)
{
unsigned
short
alahxal
,
ah2B
,
deno
,
inv
,
bl
,
bh
;
unsigned
short
ah
,
al
,
ahxal
;
unsigned
short
dout
;
ah
=
(
din
>>
6
)
&
0x3f
;
al
=
din
&
0x3f
;
ahxal
=
ah
^
al
;
ah2B
=
(((
ah
^
(
ah
>>
3
))
&
0x1
)
<<
5
)
|
((
ah
>>
1
)
&
0x10
)
|
((((
ah
>>
5
)
^
(
ah
>>
2
))
&
0x1
)
<<
3
)
|
((
ah
>>
2
)
&
0x4
)
|
((((
ah
>>
4
)
^
(
ah
>>
1
))
&
0x1
)
<<
1
)
|
(
ah
&
0x1
);
alahxal
=
gf64_mul
(
ahxal
,
al
);
deno
=
alahxal
^
ah2B
;
inv
=
gf64_inv
[
deno
];
bl
=
gf64_mul
(
inv
,
ahxal
);
bh
=
gf64_mul
(
inv
,
ah
);
dout
=
((
bh
&
0x3f
)
<<
6
)
|
(
bl
&
0x3f
);
return
(((
bh
&
0x3f
)
<<
6
)
|
(
bl
&
0x3f
));
}
static
unsigned
short
err_pos_lut
[
4096
]
=
{
0xfff
,
0x000
,
0x451
,
0xfff
,
0xfff
,
0x3cf
,
0xfff
,
0x041
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x28a
,
0xfff
,
0x492
,
0xfff
,
0x145
,
0xfff
,
0xfff
,
0x514
,
0xfff
,
0x082
,
0xfff
,
0xfff
,
0xfff
,
0x249
,
0x38e
,
0x410
,
0xfff
,
0x104
,
0x208
,
0x1c7
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2cb
,
0xfff
,
0xfff
,
0xfff
,
0x0c3
,
0x34d
,
0x4d3
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x186
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x30c
,
0x555
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x166
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x385
,
0x14e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4e1
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x538
,
0xfff
,
0x16d
,
0xfff
,
0xfff
,
0xfff
,
0x45b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x29c
,
0x2cc
,
0x30b
,
0x2b3
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0b3
,
0xfff
,
0x2f7
,
0xfff
,
0x32b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0a7
,
0xfff
,
0xfff
,
0x2da
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x07e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x11c
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x22f
,
0xfff
,
0x1f4
,
0xfff
,
0xfff
,
0x2b0
,
0x504
,
0xfff
,
0x114
,
0xfff
,
0xfff
,
0xfff
,
0x21d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x00d
,
0x3c4
,
0x340
,
0x10f
,
0xfff
,
0xfff
,
0x266
,
0x02e
,
0xfff
,
0xfff
,
0xfff
,
0x4f8
,
0x337
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x07b
,
0x168
,
0xfff
,
0xfff
,
0x0fe
,
0xfff
,
0xfff
,
0x51a
,
0xfff
,
0x458
,
0xfff
,
0x36d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x073
,
0x37d
,
0x415
,
0x550
,
0xfff
,
0xfff
,
0xfff
,
0x23b
,
0x4b4
,
0xfff
,
0xfff
,
0xfff
,
0x1a1
,
0xfff
,
0xfff
,
0x3aa
,
0xfff
,
0x117
,
0x04d
,
0x341
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x518
,
0x03e
,
0x0f2
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x363
,
0xfff
,
0x0b9
,
0xfff
,
0xfff
,
0x241
,
0xfff
,
0xfff
,
0x049
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x15f
,
0x52d
,
0xfff
,
0xfff
,
0xfff
,
0x29e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4cf
,
0x0fc
,
0xfff
,
0x36f
,
0x3d3
,
0xfff
,
0x228
,
0xfff
,
0xfff
,
0x45e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x238
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x47f
,
0xfff
,
0xfff
,
0x43a
,
0x265
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3e8
,
0xfff
,
0xfff
,
0x01a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x21e
,
0x1fc
,
0x40b
,
0xfff
,
0xfff
,
0xfff
,
0x2d0
,
0x159
,
0xfff
,
0xfff
,
0x313
,
0xfff
,
0xfff
,
0x05c
,
0x4cc
,
0xfff
,
0xfff
,
0x0f6
,
0x3d5
,
0xfff
,
0xfff
,
0xfff
,
0x54f
,
0xfff
,
0xfff
,
0xfff
,
0x172
,
0x1e4
,
0x07c
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x53c
,
0x1ad
,
0x535
,
0x19b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x092
,
0xfff
,
0x2be
,
0xfff
,
0xfff
,
0x482
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0e6
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x476
,
0xfff
,
0x51d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x342
,
0x2b5
,
0x22e
,
0x09a
,
0xfff
,
0x08d
,
0x44f
,
0x3ed
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3d1
,
0xfff
,
0xfff
,
0x543
,
0xfff
,
0x48f
,
0xfff
,
0x3d2
,
0xfff
,
0x0d5
,
0x113
,
0x0ec
,
0x427
,
0xfff
,
0xfff
,
0xfff
,
0x4c4
,
0xfff
,
0xfff
,
0x50a
,
0xfff
,
0x144
,
0xfff
,
0x105
,
0x39f
,
0x294
,
0x164
,
0xfff
,
0x31a
,
0xfff
,
0xfff
,
0x49a
,
0xfff
,
0x130
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1be
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x49e
,
0x371
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0e8
,
0x49c
,
0x0f4
,
0xfff
,
0x338
,
0x1a7
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x36c
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1ae
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x31b
,
0xfff
,
0xfff
,
0x2dd
,
0x522
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2f4
,
0x3c6
,
0x30d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x34c
,
0x18f
,
0x30a
,
0xfff
,
0x01f
,
0x079
,
0xfff
,
0xfff
,
0x54d
,
0x46b
,
0x28c
,
0x37f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x355
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x14f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x359
,
0x3fe
,
0x3c5
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x423
,
0xfff
,
0xfff
,
0x34a
,
0x22c
,
0xfff
,
0x25a
,
0xfff
,
0xfff
,
0x4ad
,
0xfff
,
0x28d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x547
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2e2
,
0xfff
,
0xfff
,
0x1d5
,
0xfff
,
0x2a8
,
0xfff
,
0xfff
,
0x03f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3eb
,
0x0fa
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x55b
,
0xfff
,
0x08e
,
0xfff
,
0x3ae
,
0xfff
,
0x3a4
,
0xfff
,
0x282
,
0x158
,
0xfff
,
0x382
,
0xfff
,
0xfff
,
0x499
,
0xfff
,
0xfff
,
0x08a
,
0xfff
,
0xfff
,
0xfff
,
0x456
,
0x3be
,
0xfff
,
0x1e2
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x559
,
0xfff
,
0x1a0
,
0xfff
,
0xfff
,
0x0b4
,
0xfff
,
0xfff
,
0xfff
,
0x2df
,
0xfff
,
0xfff
,
0xfff
,
0x07f
,
0x4f5
,
0xfff
,
0xfff
,
0x27c
,
0x133
,
0x017
,
0xfff
,
0x3fd
,
0xfff
,
0xfff
,
0xfff
,
0x44d
,
0x4cd
,
0x17a
,
0x0d7
,
0x537
,
0xfff
,
0xfff
,
0x353
,
0xfff
,
0xfff
,
0x351
,
0x366
,
0xfff
,
0x44a
,
0xfff
,
0x1a6
,
0xfff
,
0xfff
,
0xfff
,
0x291
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1e3
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x389
,
0xfff
,
0x07a
,
0xfff
,
0x1b6
,
0x2ed
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x24e
,
0x074
,
0xfff
,
0xfff
,
0x3dc
,
0xfff
,
0x4e3
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4eb
,
0xfff
,
0xfff
,
0x3b8
,
0x4de
,
0xfff
,
0x19c
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x262
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x076
,
0x4e8
,
0x3da
,
0xfff
,
0x531
,
0xfff
,
0xfff
,
0x14a
,
0xfff
,
0x0a2
,
0x433
,
0x3df
,
0x1e9
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3e7
,
0x285
,
0x2d8
,
0xfff
,
0xfff
,
0xfff
,
0x349
,
0x18d
,
0x098
,
0xfff
,
0x0df
,
0x4bf
,
0xfff
,
0xfff
,
0x0b2
,
0xfff
,
0x346
,
0x24d
,
0xfff
,
0xfff
,
0xfff
,
0x24f
,
0x4fa
,
0x2f9
,
0xfff
,
0xfff
,
0x3c9
,
0xfff
,
0x2b4
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x056
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x179
,
0xfff
,
0x0e9
,
0x3f0
,
0x33d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1fd
,
0xfff
,
0xfff
,
0x526
,
0xfff
,
0xfff
,
0xfff
,
0x53d
,
0xfff
,
0xfff
,
0xfff
,
0x170
,
0x331
,
0xfff
,
0x068
,
0xfff
,
0xfff
,
0xfff
,
0x3f7
,
0xfff
,
0x3d8
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x09f
,
0x556
,
0xfff
,
0xfff
,
0x02d
,
0xfff
,
0xfff
,
0x553
,
0xfff
,
0xfff
,
0xfff
,
0x1f0
,
0xfff
,
0xfff
,
0x4d6
,
0x41e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4d5
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x248
,
0xfff
,
0xfff
,
0xfff
,
0x0a3
,
0xfff
,
0x217
,
0xfff
,
0xfff
,
0xfff
,
0x4f1
,
0x209
,
0xfff
,
0xfff
,
0x475
,
0x234
,
0x52b
,
0x398
,
0xfff
,
0x08b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2c2
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x268
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4a3
,
0xfff
,
0x0aa
,
0xfff
,
0x1d9
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x155
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0bf
,
0x539
,
0xfff
,
0xfff
,
0x2f1
,
0x545
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2a7
,
0x06f
,
0xfff
,
0x378
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x25e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x15d
,
0x02a
,
0xfff
,
0xfff
,
0x0bc
,
0x235
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x150
,
0xfff
,
0x1a9
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x381
,
0xfff
,
0x04e
,
0x270
,
0x13f
,
0xfff
,
0xfff
,
0x405
,
0xfff
,
0x3cd
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2ef
,
0xfff
,
0x06a
,
0xfff
,
0xfff
,
0xfff
,
0x34f
,
0x212
,
0xfff
,
0xfff
,
0x0e2
,
0xfff
,
0x083
,
0x298
,
0xfff
,
0xfff
,
0xfff
,
0x0c2
,
0xfff
,
0xfff
,
0x52e
,
0xfff
,
0x488
,
0xfff
,
0xfff
,
0xfff
,
0x36b
,
0xfff
,
0xfff
,
0xfff
,
0x442
,
0x091
,
0xfff
,
0x41c
,
0xfff
,
0xfff
,
0x3a5
,
0xfff
,
0x4e6
,
0xfff
,
0xfff
,
0x40d
,
0x31d
,
0xfff
,
0xfff
,
0xfff
,
0x4c1
,
0x053
,
0xfff
,
0x418
,
0x13c
,
0xfff
,
0x350
,
0xfff
,
0x0ae
,
0xfff
,
0xfff
,
0x41f
,
0xfff
,
0x470
,
0xfff
,
0x4ca
,
0xfff
,
0xfff
,
0xfff
,
0x02b
,
0x450
,
0xfff
,
0x1f8
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x293
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x411
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0b8
,
0xfff
,
0xfff
,
0xfff
,
0x3e1
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x43c
,
0xfff
,
0x2b2
,
0x2ab
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1ec
,
0xfff
,
0xfff
,
0xfff
,
0x3f8
,
0x034
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x11a
,
0xfff
,
0x541
,
0x45c
,
0x134
,
0x1cc
,
0xfff
,
0xfff
,
0xfff
,
0x469
,
0xfff
,
0xfff
,
0x44b
,
0x161
,
0xfff
,
0xfff
,
0xfff
,
0x055
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x307
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2d1
,
0xfff
,
0xfff
,
0xfff
,
0x124
,
0x37b
,
0x26b
,
0x336
,
0xfff
,
0xfff
,
0x2e4
,
0x3cb
,
0xfff
,
0xfff
,
0x0f8
,
0x3c8
,
0xfff
,
0xfff
,
0xfff
,
0x461
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4b5
,
0x2cf
,
0xfff
,
0xfff
,
0xfff
,
0x20f
,
0xfff
,
0x35a
,
0xfff
,
0x490
,
0xfff
,
0x185
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x42e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x54b
,
0xfff
,
0xfff
,
0xfff
,
0x146
,
0xfff
,
0x412
,
0xfff
,
0xfff
,
0xfff
,
0x1ff
,
0xfff
,
0xfff
,
0x3e0
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2d5
,
0xfff
,
0x4df
,
0x505
,
0xfff
,
0x413
,
0xfff
,
0x1a5
,
0xfff
,
0x3b2
,
0xfff
,
0xfff
,
0xfff
,
0x35b
,
0xfff
,
0x116
,
0xfff
,
0xfff
,
0x171
,
0x4d0
,
0xfff
,
0x154
,
0x12d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x468
,
0x4db
,
0xfff
,
0xfff
,
0x1df
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x05a
,
0xfff
,
0x0f1
,
0x403
,
0xfff
,
0x22b
,
0x2e0
,
0xfff
,
0xfff
,
0xfff
,
0x2b7
,
0x373
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x13e
,
0xfff
,
0xfff
,
0xfff
,
0x0d0
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x329
,
0x1d2
,
0x3fa
,
0x047
,
0xfff
,
0x2f2
,
0xfff
,
0xfff
,
0x141
,
0x0ac
,
0x1d7
,
0xfff
,
0x07d
,
0xfff
,
0xfff
,
0xfff
,
0x1c1
,
0xfff
,
0x487
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x045
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x288
,
0x0cd
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x226
,
0x1d8
,
0xfff
,
0x153
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4cb
,
0x528
,
0xfff
,
0xfff
,
0xfff
,
0x20a
,
0x343
,
0x3a1
,
0xfff
,
0xfff
,
0xfff
,
0x2d7
,
0x2d3
,
0x1aa
,
0x4c5
,
0xfff
,
0xfff
,
0xfff
,
0x42b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3e9
,
0xfff
,
0x20b
,
0x260
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x37c
,
0x2fd
,
0xfff
,
0xfff
,
0x2c8
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x31e
,
0xfff
,
0x335
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x135
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x35c
,
0x4dd
,
0x129
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1ef
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x34e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x407
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3ad
,
0xfff
,
0xfff
,
0xfff
,
0x379
,
0xfff
,
0xfff
,
0x1d0
,
0x38d
,
0xfff
,
0xfff
,
0x1e8
,
0x184
,
0x3c1
,
0x1c4
,
0xfff
,
0x1f9
,
0xfff
,
0xfff
,
0x424
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1d3
,
0x0d4
,
0xfff
,
0x4e9
,
0xfff
,
0xfff
,
0xfff
,
0x530
,
0x107
,
0xfff
,
0x106
,
0x04f
,
0xfff
,
0xfff
,
0x4c7
,
0x503
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x15c
,
0xfff
,
0x23f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4f3
,
0xfff
,
0xfff
,
0x3c7
,
0xfff
,
0x278
,
0xfff
,
0xfff
,
0x0a6
,
0xfff
,
0xfff
,
0xfff
,
0x122
,
0x1cf
,
0xfff
,
0x327
,
0xfff
,
0x2e5
,
0xfff
,
0x29d
,
0xfff
,
0xfff
,
0x3f1
,
0xfff
,
0xfff
,
0x48d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x054
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x178
,
0x27e
,
0x4e0
,
0x352
,
0x02f
,
0x09c
,
0xfff
,
0x2a0
,
0xfff
,
0xfff
,
0x46a
,
0x457
,
0xfff
,
0xfff
,
0x501
,
0xfff
,
0x2ba
,
0xfff
,
0xfff
,
0xfff
,
0x54e
,
0x2e7
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x551
,
0xfff
,
0xfff
,
0x1db
,
0x2aa
,
0xfff
,
0xfff
,
0x4bc
,
0xfff
,
0xfff
,
0x395
,
0xfff
,
0x0de
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x455
,
0xfff
,
0x17e
,
0xfff
,
0x221
,
0x4a7
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x388
,
0xfff
,
0xfff
,
0xfff
,
0x308
,
0xfff
,
0xfff
,
0xfff
,
0x20e
,
0x4b9
,
0xfff
,
0x273
,
0x20c
,
0x09e
,
0xfff
,
0x057
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3f2
,
0xfff
,
0x1a8
,
0x3a6
,
0x14c
,
0xfff
,
0xfff
,
0x071
,
0xfff
,
0xfff
,
0x53a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x109
,
0xfff
,
0xfff
,
0x399
,
0xfff
,
0x061
,
0x4f0
,
0x39e
,
0x244
,
0xfff
,
0x035
,
0xfff
,
0xfff
,
0x305
,
0x47e
,
0x297
,
0xfff
,
0xfff
,
0x2b8
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1bc
,
0xfff
,
0x2fc
,
0xfff
,
0xfff
,
0x554
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3b6
,
0xfff
,
0xfff
,
0xfff
,
0x515
,
0x397
,
0xfff
,
0xfff
,
0x12f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4e5
,
0xfff
,
0x4fc
,
0xfff
,
0xfff
,
0x05e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0a8
,
0x3af
,
0x015
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x138
,
0xfff
,
0xfff
,
0xfff
,
0x540
,
0xfff
,
0xfff
,
0xfff
,
0x027
,
0x523
,
0x2f0
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x16c
,
0xfff
,
0x27d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x04c
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4dc
,
0xfff
,
0xfff
,
0x059
,
0x301
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1a3
,
0xfff
,
0x15a
,
0xfff
,
0xfff
,
0x0a5
,
0xfff
,
0x435
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x051
,
0xfff
,
0xfff
,
0x131
,
0xfff
,
0x4f4
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x441
,
0xfff
,
0x4fb
,
0xfff
,
0x03b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1ed
,
0x274
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0d3
,
0x55e
,
0x1b3
,
0xfff
,
0x0bd
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x225
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4b7
,
0xfff
,
0xfff
,
0x2ff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4c3
,
0xfff
,
0x383
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2f6
,
0xfff
,
0xfff
,
0x1ee
,
0xfff
,
0x03d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x26f
,
0x1dc
,
0xfff
,
0x0db
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0ce
,
0xfff
,
0xfff
,
0x127
,
0x03a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x311
,
0xfff
,
0xfff
,
0x13d
,
0x09d
,
0x47b
,
0x2a6
,
0x50d
,
0x510
,
0x19a
,
0xfff
,
0x354
,
0x414
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x44c
,
0x3b0
,
0xfff
,
0x23d
,
0x429
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4c0
,
0x416
,
0xfff
,
0x05b
,
0xfff
,
0xfff
,
0x137
,
0xfff
,
0x25f
,
0x49f
,
0xfff
,
0x279
,
0x013
,
0xfff
,
0xfff
,
0xfff
,
0x269
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3d0
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x077
,
0xfff
,
0xfff
,
0x3fb
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x271
,
0x3a0
,
0xfff
,
0xfff
,
0x40f
,
0xfff
,
0xfff
,
0x3de
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1ab
,
0x26a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x489
,
0xfff
,
0xfff
,
0x252
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1b7
,
0x42f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3b7
,
0xfff
,
0x2bb
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0f7
,
0x01d
,
0xfff
,
0x067
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4e2
,
0xfff
,
0xfff
,
0x4bb
,
0xfff
,
0xfff
,
0xfff
,
0x17b
,
0xfff
,
0x0ee
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x36e
,
0xfff
,
0xfff
,
0xfff
,
0x533
,
0xfff
,
0xfff
,
0xfff
,
0x4d4
,
0x356
,
0xfff
,
0xfff
,
0x375
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4a4
,
0x513
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4ff
,
0xfff
,
0x2af
,
0xfff
,
0xfff
,
0x026
,
0xfff
,
0x0ad
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x26e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x493
,
0xfff
,
0x463
,
0x4d2
,
0x4be
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4f2
,
0x0b6
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x32d
,
0x315
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x13a
,
0x4a1
,
0xfff
,
0x27a
,
0xfff
,
0xfff
,
0xfff
,
0x47a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x334
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x54c
,
0xfff
,
0xfff
,
0xfff
,
0x0c9
,
0x007
,
0xfff
,
0xfff
,
0x12e
,
0xfff
,
0x0ff
,
0xfff
,
0xfff
,
0x3f5
,
0x509
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1c3
,
0x2ad
,
0xfff
,
0xfff
,
0x47c
,
0x261
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x152
,
0xfff
,
0xfff
,
0xfff
,
0x339
,
0xfff
,
0x243
,
0x1c0
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x063
,
0xfff
,
0xfff
,
0x254
,
0xfff
,
0xfff
,
0x173
,
0xfff
,
0x0c7
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x362
,
0x259
,
0x485
,
0x374
,
0x0dc
,
0x3ab
,
0xfff
,
0x1c5
,
0x534
,
0x544
,
0xfff
,
0xfff
,
0x508
,
0xfff
,
0x402
,
0x408
,
0xfff
,
0x0e7
,
0xfff
,
0xfff
,
0x00a
,
0x205
,
0xfff
,
0xfff
,
0x2b9
,
0xfff
,
0xfff
,
0xfff
,
0x465
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x23a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x147
,
0x19d
,
0x115
,
0x214
,
0xfff
,
0x090
,
0x368
,
0xfff
,
0x210
,
0xfff
,
0xfff
,
0x280
,
0x52a
,
0x163
,
0x148
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x326
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2de
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x206
,
0x2c1
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x189
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x367
,
0xfff
,
0x1a4
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x443
,
0xfff
,
0x27b
,
0xfff
,
0xfff
,
0x251
,
0x549
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x188
,
0x04b
,
0xfff
,
0xfff
,
0xfff
,
0x31f
,
0x4a6
,
0xfff
,
0x246
,
0x1de
,
0x156
,
0xfff
,
0xfff
,
0xfff
,
0x3a9
,
0xfff
,
0xfff
,
0xfff
,
0x2fa
,
0xfff
,
0x128
,
0x0d1
,
0x449
,
0x255
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x258
,
0xfff
,
0xfff
,
0xfff
,
0x532
,
0xfff
,
0xfff
,
0xfff
,
0x303
,
0x517
,
0xfff
,
0xfff
,
0x2a9
,
0x24a
,
0xfff
,
0xfff
,
0x231
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4b6
,
0x516
,
0xfff
,
0xfff
,
0x0e4
,
0x0eb
,
0xfff
,
0x4e4
,
0xfff
,
0x275
,
0xfff
,
0xfff
,
0x031
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x025
,
0x21a
,
0xfff
,
0x0cc
,
0x45f
,
0x3d9
,
0x289
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x23e
,
0xfff
,
0xfff
,
0xfff
,
0x438
,
0x097
,
0x419
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0a9
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x37e
,
0x0e0
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x431
,
0x372
,
0xfff
,
0xfff
,
0xfff
,
0x1ba
,
0x06e
,
0xfff
,
0x1b1
,
0xfff
,
0xfff
,
0x12a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x193
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x10a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x048
,
0x1b4
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x295
,
0x140
,
0x108
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x16f
,
0xfff
,
0x0a4
,
0x37a
,
0xfff
,
0x29a
,
0xfff
,
0x284
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4c6
,
0x2a2
,
0x3a3
,
0xfff
,
0x201
,
0xfff
,
0xfff
,
0xfff
,
0x4bd
,
0x005
,
0x54a
,
0x3b5
,
0x204
,
0x2ee
,
0x11d
,
0x436
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3ec
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x11f
,
0x498
,
0x21c
,
0xfff
,
0xfff
,
0xfff
,
0x3d6
,
0xfff
,
0x4ab
,
0xfff
,
0x432
,
0x2eb
,
0x542
,
0x4fd
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4ce
,
0xfff
,
0xfff
,
0x2fb
,
0xfff
,
0xfff
,
0x2e1
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1b9
,
0x037
,
0x0dd
,
0xfff
,
0xfff
,
0xfff
,
0x2bf
,
0x521
,
0x496
,
0x095
,
0xfff
,
0xfff
,
0x328
,
0x070
,
0x1bf
,
0xfff
,
0x393
,
0xfff
,
0xfff
,
0x102
,
0xfff
,
0xfff
,
0x21b
,
0xfff
,
0x142
,
0x263
,
0x519
,
0xfff
,
0x2a5
,
0x177
,
0xfff
,
0x14d
,
0x471
,
0x4ae
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1f6
,
0xfff
,
0x481
,
0xfff
,
0xfff
,
0xfff
,
0x151
,
0xfff
,
0xfff
,
0xfff
,
0x085
,
0x33f
,
0xfff
,
0xfff
,
0xfff
,
0x084
,
0xfff
,
0xfff
,
0xfff
,
0x345
,
0x3a2
,
0xfff
,
0xfff
,
0x0a0
,
0x0da
,
0x024
,
0xfff
,
0xfff
,
0xfff
,
0x1bd
,
0xfff
,
0x55c
,
0x467
,
0x445
,
0xfff
,
0xfff
,
0xfff
,
0x052
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x51e
,
0xfff
,
0xfff
,
0x39d
,
0xfff
,
0x35f
,
0xfff
,
0x376
,
0x3ee
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x448
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x16a
,
0xfff
,
0x036
,
0x38f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x211
,
0xfff
,
0xfff
,
0xfff
,
0x230
,
0xfff
,
0xfff
,
0x3ba
,
0xfff
,
0xfff
,
0xfff
,
0x3ce
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x229
,
0xfff
,
0x176
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x00b
,
0xfff
,
0x162
,
0x018
,
0xfff
,
0xfff
,
0x233
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x400
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x12b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3f4
,
0xfff
,
0x0f0
,
0xfff
,
0x1ac
,
0xfff
,
0xfff
,
0x119
,
0xfff
,
0x2c0
,
0xfff
,
0xfff
,
0xfff
,
0x49b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x23c
,
0xfff
,
0x4b3
,
0x010
,
0x064
,
0xfff
,
0xfff
,
0x4ba
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3c2
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x006
,
0x196
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x100
,
0x191
,
0xfff
,
0x1ea
,
0x29f
,
0xfff
,
0xfff
,
0xfff
,
0x276
,
0xfff
,
0xfff
,
0x2b1
,
0x3b9
,
0xfff
,
0x03c
,
0xfff
,
0xfff
,
0xfff
,
0x180
,
0xfff
,
0x08f
,
0xfff
,
0xfff
,
0x19e
,
0x019
,
0xfff
,
0x0b0
,
0x0fd
,
0x332
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x06b
,
0x2e8
,
0xfff
,
0x446
,
0xfff
,
0xfff
,
0x004
,
0x247
,
0x197
,
0xfff
,
0x112
,
0x169
,
0x292
,
0xfff
,
0x302
,
0xfff
,
0xfff
,
0x33b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x287
,
0x21f
,
0xfff
,
0x3ea
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4e7
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3a8
,
0xfff
,
0xfff
,
0x2bc
,
0xfff
,
0x484
,
0x296
,
0xfff
,
0x1c9
,
0x08c
,
0x1e5
,
0x48a
,
0xfff
,
0x360
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1ca
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x10d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x066
,
0x2ea
,
0x28b
,
0x25b
,
0xfff
,
0x072
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2b6
,
0xfff
,
0xfff
,
0x272
,
0xfff
,
0xfff
,
0x525
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2ca
,
0xfff
,
0xfff
,
0xfff
,
0x299
,
0xfff
,
0xfff
,
0xfff
,
0x558
,
0x41a
,
0xfff
,
0x4f7
,
0x557
,
0xfff
,
0x4a0
,
0x344
,
0x12c
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x125
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x40e
,
0xfff
,
0xfff
,
0x502
,
0xfff
,
0x103
,
0x3e6
,
0xfff
,
0x527
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x45d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x44e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0d2
,
0x4c9
,
0x35e
,
0x459
,
0x2d9
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x17d
,
0x0c4
,
0xfff
,
0xfff
,
0xfff
,
0x3ac
,
0x390
,
0x094
,
0xfff
,
0x483
,
0x0ab
,
0xfff
,
0x253
,
0xfff
,
0x391
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x123
,
0x0ef
,
0xfff
,
0xfff
,
0xfff
,
0x330
,
0x38c
,
0xfff
,
0xfff
,
0x2ae
,
0xfff
,
0xfff
,
0xfff
,
0x042
,
0x012
,
0x06d
,
0xfff
,
0xfff
,
0xfff
,
0x32a
,
0x3db
,
0x364
,
0x2dc
,
0xfff
,
0x30f
,
0x3d7
,
0x4a5
,
0x050
,
0xfff
,
0xfff
,
0x029
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1d1
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x480
,
0xfff
,
0x4ed
,
0x081
,
0x0a1
,
0xfff
,
0xfff
,
0xfff
,
0x30e
,
0x52f
,
0x257
,
0xfff
,
0xfff
,
0x447
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x401
,
0x3cc
,
0xfff
,
0xfff
,
0x0fb
,
0x2c9
,
0x42a
,
0x314
,
0x33e
,
0x3bd
,
0x318
,
0xfff
,
0x10e
,
0x2a1
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x24c
,
0x506
,
0xfff
,
0x267
,
0xfff
,
0xfff
,
0x219
,
0xfff
,
0x1eb
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x309
,
0x3e2
,
0x46c
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x384
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x50c
,
0xfff
,
0x24b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x038
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x194
,
0x143
,
0x3e3
,
0xfff
,
0xfff
,
0xfff
,
0x4c2
,
0xfff
,
0xfff
,
0x0e1
,
0x25c
,
0xfff
,
0x237
,
0xfff
,
0x1fe
,
0xfff
,
0xfff
,
0xfff
,
0x065
,
0x2a4
,
0xfff
,
0x386
,
0x55a
,
0x11b
,
0xfff
,
0xfff
,
0x192
,
0xfff
,
0x183
,
0x00e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4b2
,
0x18e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x486
,
0x4ef
,
0x0c6
,
0x380
,
0xfff
,
0x4a8
,
0xfff
,
0x0c5
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x093
,
0x1b8
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2e6
,
0xfff
,
0x0f3
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x28e
,
0xfff
,
0x53b
,
0x420
,
0x22a
,
0x33a
,
0xfff
,
0x387
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2a3
,
0xfff
,
0xfff
,
0xfff
,
0x428
,
0x500
,
0xfff
,
0xfff
,
0x120
,
0x2c6
,
0x290
,
0x2f5
,
0x0e3
,
0xfff
,
0x0b7
,
0xfff
,
0x319
,
0x474
,
0xfff
,
0xfff
,
0xfff
,
0x529
,
0x014
,
0xfff
,
0x41b
,
0x40a
,
0x18b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0d9
,
0xfff
,
0x38a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1ce
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3b1
,
0xfff
,
0xfff
,
0x05d
,
0x2c4
,
0xfff
,
0xfff
,
0x4af
,
0xfff
,
0x030
,
0xfff
,
0xfff
,
0x203
,
0xfff
,
0x277
,
0x256
,
0xfff
,
0xfff
,
0xfff
,
0x4f9
,
0xfff
,
0x2c7
,
0xfff
,
0x466
,
0x016
,
0x1cd
,
0xfff
,
0x167
,
0xfff
,
0xfff
,
0x0c8
,
0xfff
,
0x43d
,
0xfff
,
0xfff
,
0x020
,
0xfff
,
0xfff
,
0x232
,
0x1cb
,
0x1e0
,
0xfff
,
0xfff
,
0x347
,
0xfff
,
0x478
,
0xfff
,
0x365
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x358
,
0xfff
,
0x10b
,
0xfff
,
0x35d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x452
,
0x22d
,
0xfff
,
0xfff
,
0x47d
,
0xfff
,
0x2f3
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x460
,
0xfff
,
0xfff
,
0xfff
,
0x50b
,
0xfff
,
0xfff
,
0xfff
,
0x2ec
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4b1
,
0x422
,
0xfff
,
0xfff
,
0xfff
,
0x2d4
,
0xfff
,
0x239
,
0xfff
,
0xfff
,
0xfff
,
0x439
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x491
,
0x075
,
0xfff
,
0xfff
,
0xfff
,
0x06c
,
0xfff
,
0xfff
,
0x0f9
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x139
,
0xfff
,
0x4f6
,
0xfff
,
0xfff
,
0x409
,
0xfff
,
0xfff
,
0x15b
,
0xfff
,
0xfff
,
0x348
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4a2
,
0x49d
,
0xfff
,
0x033
,
0x175
,
0xfff
,
0x039
,
0xfff
,
0x312
,
0x40c
,
0xfff
,
0xfff
,
0x325
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4aa
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x165
,
0x3bc
,
0x48c
,
0x310
,
0x096
,
0xfff
,
0xfff
,
0x250
,
0x1a2
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x20d
,
0x2ac
,
0xfff
,
0xfff
,
0x39b
,
0xfff
,
0x377
,
0xfff
,
0x512
,
0x495
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x357
,
0x4ea
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x198
,
0xfff
,
0xfff
,
0xfff
,
0x434
,
0x04a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x062
,
0xfff
,
0x1d6
,
0x1c8
,
0xfff
,
0x1f3
,
0x281
,
0xfff
,
0x462
,
0xfff
,
0xfff
,
0xfff
,
0x4b0
,
0xfff
,
0x207
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3dd
,
0xfff
,
0xfff
,
0x55d
,
0xfff
,
0x552
,
0x494
,
0x1af
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x227
,
0xfff
,
0xfff
,
0x069
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x43e
,
0x0b5
,
0xfff
,
0x524
,
0x2d2
,
0xfff
,
0xfff
,
0xfff
,
0x28f
,
0xfff
,
0x01b
,
0x50e
,
0xfff
,
0xfff
,
0x1bb
,
0xfff
,
0xfff
,
0x41d
,
0xfff
,
0x32e
,
0x48e
,
0xfff
,
0x1f7
,
0x224
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x394
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x52c
,
0xfff
,
0xfff
,
0xfff
,
0x392
,
0xfff
,
0x1e7
,
0xfff
,
0xfff
,
0x3f9
,
0x3a7
,
0xfff
,
0x51f
,
0xfff
,
0x0bb
,
0x118
,
0x3ca
,
0xfff
,
0x1dd
,
0xfff
,
0x48b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x50f
,
0xfff
,
0x0d6
,
0xfff
,
0x1fa
,
0xfff
,
0x11e
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x4d7
,
0xfff
,
0x078
,
0x008
,
0xfff
,
0x25d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x032
,
0x33c
,
0xfff
,
0x4d9
,
0x160
,
0xfff
,
0xfff
,
0x300
,
0x0b1
,
0xfff
,
0x322
,
0xfff
,
0x4ec
,
0xfff
,
0xfff
,
0x200
,
0x00c
,
0x369
,
0x473
,
0xfff
,
0xfff
,
0x32c
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x53e
,
0x3d4
,
0x417
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x34b
,
0x001
,
0x39a
,
0x02c
,
0xfff
,
0xfff
,
0x2ce
,
0x00f
,
0xfff
,
0x0ba
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x060
,
0xfff
,
0x406
,
0xfff
,
0xfff
,
0xfff
,
0x4ee
,
0x4ac
,
0xfff
,
0x43f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x29b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x216
,
0x190
,
0xfff
,
0x396
,
0x464
,
0xfff
,
0xfff
,
0x323
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2e9
,
0xfff
,
0x26d
,
0x2cd
,
0x040
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x38b
,
0x3c0
,
0xfff
,
0xfff
,
0xfff
,
0x1f2
,
0xfff
,
0x0ea
,
0xfff
,
0xfff
,
0x472
,
0xfff
,
0x1fb
,
0xfff
,
0xfff
,
0x0af
,
0x27f
,
0xfff
,
0xfff
,
0xfff
,
0x479
,
0x023
,
0xfff
,
0x0d8
,
0x3b3
,
0xfff
,
0xfff
,
0xfff
,
0x121
,
0xfff
,
0xfff
,
0x3bf
,
0xfff
,
0xfff
,
0x16b
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x45a
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x0be
,
0xfff
,
0xfff
,
0xfff
,
0x111
,
0xfff
,
0x220
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x09b
,
0x218
,
0xfff
,
0x022
,
0x202
,
0xfff
,
0x4c8
,
0xfff
,
0x0ed
,
0xfff
,
0xfff
,
0x182
,
0xfff
,
0xfff
,
0xfff
,
0x17f
,
0x213
,
0xfff
,
0x321
,
0x36a
,
0xfff
,
0x086
,
0xfff
,
0xfff
,
0xfff
,
0x43b
,
0x088
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x26c
,
0xfff
,
0x2f8
,
0x3b4
,
0xfff
,
0xfff
,
0xfff
,
0x132
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x333
,
0x444
,
0x0c1
,
0x4d8
,
0x46d
,
0x264
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x426
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x2fe
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x011
,
0xfff
,
0x05f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x10c
,
0x101
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x110
,
0xfff
,
0x044
,
0x304
,
0x361
,
0x404
,
0xfff
,
0x51b
,
0x099
,
0xfff
,
0x440
,
0xfff
,
0xfff
,
0xfff
,
0x222
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x1b5
,
0xfff
,
0x136
,
0x430
,
0xfff
,
0x1da
,
0xfff
,
0xfff
,
0xfff
,
0x043
,
0xfff
,
0x17c
,
0xfff
,
0xfff
,
0xfff
,
0x01c
,
0xfff
,
0xfff
,
0xfff
,
0x425
,
0x236
,
0xfff
,
0x317
,
0xfff
,
0xfff
,
0x437
,
0x3fc
,
0xfff
,
0x1f1
,
0xfff
,
0x324
,
0xfff
,
0xfff
,
0x0ca
,
0x306
,
0xfff
,
0x548
,
0xfff
,
0x46e
,
0xfff
,
0xfff
,
0xfff
,
0x4b8
,
0x1c2
,
0x286
,
0xfff
,
0xfff
,
0x087
,
0x18a
,
0x19f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x18c
,
0xfff
,
0x215
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x283
,
0xfff
,
0xfff
,
0xfff
,
0x126
,
0xfff
,
0xfff
,
0x370
,
0xfff
,
0x53f
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x31c
,
0xfff
,
0x4d1
,
0xfff
,
0xfff
,
0xfff
,
0x021
,
0xfff
,
0x157
,
0xfff
,
0xfff
,
0x028
,
0x16e
,
0xfff
,
0x421
,
0xfff
,
0x1c6
,
0xfff
,
0xfff
,
0x511
,
0xfff
,
0xfff
,
0x39c
,
0x46f
,
0x1b2
,
0xfff
,
0xfff
,
0x316
,
0xfff
,
0xfff
,
0x009
,
0xfff
,
0xfff
,
0x195
,
0xfff
,
0x240
,
0x546
,
0xfff
,
0xfff
,
0x520
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x454
,
0xfff
,
0xfff
,
0xfff
,
0x3f3
,
0xfff
,
0xfff
,
0x187
,
0xfff
,
0x4a9
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x51c
,
0x453
,
0x1e6
,
0xfff
,
0xfff
,
0xfff
,
0x1b0
,
0xfff
,
0x477
,
0xfff
,
0xfff
,
0xfff
,
0x4fe
,
0xfff
,
0x32f
,
0xfff
,
0xfff
,
0x15e
,
0x1d4
,
0xfff
,
0x0e5
,
0xfff
,
0xfff
,
0xfff
,
0x242
,
0x14b
,
0x046
,
0xfff
,
0x3f6
,
0x3bb
,
0x3e4
,
0xfff
,
0xfff
,
0x2e3
,
0xfff
,
0x245
,
0xfff
,
0x149
,
0xfff
,
0xfff
,
0xfff
,
0x2db
,
0xfff
,
0xfff
,
0x181
,
0xfff
,
0x089
,
0x2c5
,
0xfff
,
0x1f5
,
0xfff
,
0x2d6
,
0x507
,
0xfff
,
0x42d
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x080
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x3c3
,
0x320
,
0xfff
,
0x1e1
,
0xfff
,
0x0f5
,
0x13b
,
0xfff
,
0xfff
,
0xfff
,
0x003
,
0x4da
,
0xfff
,
0xfff
,
0xfff
,
0x42c
,
0xfff
,
0xfff
,
0x0cb
,
0xfff
,
0x536
,
0x2c3
,
0xfff
,
0xfff
,
0xfff
,
0xfff
,
0x199
,
0xfff
,
0xfff
,
0x0c0
,
0xfff
,
0x01e
,
0x497
,
0xfff
,
0xfff
,
0x3e5
,
0xfff
,
0xfff
,
0xfff
,
0x0cf
,
0xfff
,
0x2bd
,
0xfff
,
0x223
,
0xfff
,
0x3ff
,
0xfff
,
0x058
,
0x174
,
0x3ef
,
0xfff
,
0x002
};
static
unsigned
short
err_pos
(
unsigned
short
din
)
{
BUG_ON
(
din
>
4096
);
return
err_pos_lut
[
din
];
}
static
int
chk_no_err_only
(
unsigned
short
*
chk_syndrome_list
,
unsigned
short
*
err_info
)
{
if
((
chk_syndrome_list
[
0
]
|
chk_syndrome_list
[
1
]
|
chk_syndrome_list
[
2
]
|
chk_syndrome_list
[
3
]
|
chk_syndrome_list
[
4
]
|
chk_syndrome_list
[
5
]
|
chk_syndrome_list
[
6
]
|
chk_syndrome_list
[
7
])
!=
0x0
)
{
return
-
EINVAL
;
}
else
{
err_info
[
0
]
=
0x0
;
return
0
;
}
}
static
int
chk_1_err_only
(
unsigned
short
*
chk_syndrome_list
,
unsigned
short
*
err_info
)
{
unsigned
short
tmp0
,
tmp1
,
tmp2
,
tmp3
,
tmp4
,
tmp5
,
tmp6
;
tmp0
=
gf4096_mul
(
chk_syndrome_list
[
1
],
gf4096_inv
(
chk_syndrome_list
[
0
]));
tmp1
=
gf4096_mul
(
chk_syndrome_list
[
2
],
gf4096_inv
(
chk_syndrome_list
[
1
]));
tmp2
=
gf4096_mul
(
chk_syndrome_list
[
3
],
gf4096_inv
(
chk_syndrome_list
[
2
]));
tmp3
=
gf4096_mul
(
chk_syndrome_list
[
4
],
gf4096_inv
(
chk_syndrome_list
[
3
]));
tmp4
=
gf4096_mul
(
chk_syndrome_list
[
5
],
gf4096_inv
(
chk_syndrome_list
[
4
]));
tmp5
=
gf4096_mul
(
chk_syndrome_list
[
6
],
gf4096_inv
(
chk_syndrome_list
[
5
]));
tmp6
=
gf4096_mul
(
chk_syndrome_list
[
7
],
gf4096_inv
(
chk_syndrome_list
[
6
]));
if
((
tmp0
==
tmp1
)
&
(
tmp1
==
tmp2
)
&
(
tmp2
==
tmp3
)
&
(
tmp3
==
tmp4
)
&
(
tmp4
==
tmp5
)
&
(
tmp5
==
tmp6
))
{
err_info
[
0
]
=
0x1
;
// encode 1-symbol error as 0x1
err_info
[
1
]
=
err_pos
(
tmp0
);
err_info
[
1
]
=
(
unsigned
short
)(
0x55e
-
err_info
[
1
]);
err_info
[
5
]
=
chk_syndrome_list
[
0
];
return
0
;
}
else
return
-
EINVAL
;
}
static
int
chk_2_err_only
(
unsigned
short
*
chk_syndrome_list
,
unsigned
short
*
err_info
)
{
unsigned
short
tmp0
,
tmp1
,
tmp2
,
tmp3
,
tmp4
,
tmp5
,
tmp6
,
tmp7
;
unsigned
short
coefs
[
4
];
unsigned
short
err_pats
[
4
];
int
found_num_root
=
0
;
unsigned
short
bit2_root0
,
bit2_root1
;
unsigned
short
bit2_root0_inv
,
bit2_root1_inv
;
unsigned
short
err_loc_eqn
,
test_root
;
unsigned
short
bit2_loc0
,
bit2_loc1
;
unsigned
short
bit2_pat0
,
bit2_pat1
;
find_2x2_soln
(
chk_syndrome_list
[
1
],
chk_syndrome_list
[
0
],
chk_syndrome_list
[
2
],
chk_syndrome_list
[
1
],
chk_syndrome_list
[
2
],
chk_syndrome_list
[
3
],
coefs
);
for
(
test_root
=
0x1
;
test_root
<
0xfff
;
test_root
++
)
{
err_loc_eqn
=
gf4096_mul
(
coefs
[
1
],
gf4096_mul
(
test_root
,
test_root
))
^
gf4096_mul
(
coefs
[
0
],
test_root
)
^
0x1
;
if
(
err_loc_eqn
==
0x0
)
{
if
(
found_num_root
==
0
)
{
bit2_root0
=
test_root
;
found_num_root
=
1
;
}
else
if
(
found_num_root
==
1
)
{
bit2_root1
=
test_root
;
found_num_root
=
2
;
break
;
}
}
}
if
(
found_num_root
!=
2
)
return
-
EINVAL
;
else
{
bit2_root0_inv
=
gf4096_inv
(
bit2_root0
);
bit2_root1_inv
=
gf4096_inv
(
bit2_root1
);
find_2bit_err_pats
(
chk_syndrome_list
[
0
],
chk_syndrome_list
[
1
],
bit2_root0_inv
,
bit2_root1_inv
,
err_pats
);
bit2_pat0
=
err_pats
[
0
];
bit2_pat1
=
err_pats
[
1
];
//for(x+1)
tmp0
=
gf4096_mul
(
gf4096_mul
(
bit2_root0_inv
,
bit2_root0_inv
),
gf4096_mul
(
bit2_root0_inv
,
bit2_root0_inv
));
//rinv0^4
tmp1
=
gf4096_mul
(
bit2_root0_inv
,
tmp0
);
//rinv0^5
tmp2
=
gf4096_mul
(
bit2_root0_inv
,
tmp1
);
//rinv0^6
tmp3
=
gf4096_mul
(
bit2_root0_inv
,
tmp2
);
//rinv0^7
tmp4
=
gf4096_mul
(
gf4096_mul
(
bit2_root1_inv
,
bit2_root1_inv
),
gf4096_mul
(
bit2_root1_inv
,
bit2_root1_inv
));
//rinv1^4
tmp5
=
gf4096_mul
(
bit2_root1_inv
,
tmp4
);
//rinv1^5
tmp6
=
gf4096_mul
(
bit2_root1_inv
,
tmp5
);
//rinv1^6
tmp7
=
gf4096_mul
(
bit2_root1_inv
,
tmp6
);
//rinv1^7
//check if only 2-bit error
if
((
chk_syndrome_list
[
4
]
==
(
gf4096_mul
(
bit2_pat0
,
tmp0
)
^
gf4096_mul
(
bit2_pat1
,
tmp4
)))
&
(
chk_syndrome_list
[
5
]
==
(
gf4096_mul
(
bit2_pat0
,
tmp1
)
^
gf4096_mul
(
bit2_pat1
,
tmp5
)))
&
(
chk_syndrome_list
[
6
]
==
(
gf4096_mul
(
bit2_pat0
,
tmp2
)
^
gf4096_mul
(
bit2_pat1
,
tmp6
)))
&
(
chk_syndrome_list
[
7
]
==
(
gf4096_mul
(
bit2_pat0
,
tmp3
)
^
gf4096_mul
(
bit2_pat1
,
tmp7
))))
{
if
((
err_pos
(
bit2_root0_inv
)
==
0xfff
)
|
(
err_pos
(
bit2_root1_inv
)
==
0xfff
))
{
return
-
EINVAL
;
}
else
{
bit2_loc0
=
0x55e
-
err_pos
(
bit2_root0_inv
);
bit2_loc1
=
0x55e
-
err_pos
(
bit2_root1_inv
);
err_info
[
0
]
=
0x2
;
// encode 2-symbol error as 0x2
err_info
[
1
]
=
bit2_loc0
;
err_info
[
2
]
=
bit2_loc1
;
err_info
[
5
]
=
bit2_pat0
;
err_info
[
6
]
=
bit2_pat1
;
return
0
;
}
}
else
return
-
EINVAL
;
}
}
static
int
chk_3_err_only
(
unsigned
short
*
chk_syndrome_list
,
unsigned
short
*
err_info
)
{
unsigned
short
tmp0
,
tmp1
,
tmp2
,
tmp3
,
tmp4
,
tmp5
;
unsigned
short
coefs
[
4
];
unsigned
short
err_pats
[
4
];
int
found_num_root
=
0
;
unsigned
short
bit3_root0
,
bit3_root1
,
bit3_root2
;
unsigned
short
bit3_root0_inv
,
bit3_root1_inv
,
bit3_root2_inv
;
unsigned
short
err_loc_eqn
,
test_root
;
find_3bit_err_coefs
(
chk_syndrome_list
[
0
],
chk_syndrome_list
[
1
],
chk_syndrome_list
[
2
],
chk_syndrome_list
[
3
],
chk_syndrome_list
[
4
],
chk_syndrome_list
[
5
],
coefs
);
for
(
test_root
=
0x1
;
test_root
<
0xfff
;
test_root
++
)
{
err_loc_eqn
=
gf4096_mul
(
coefs
[
2
],
gf4096_mul
(
gf4096_mul
(
test_root
,
test_root
),
test_root
))
^
gf4096_mul
(
coefs
[
1
],
gf4096_mul
(
test_root
,
test_root
))
^
gf4096_mul
(
coefs
[
0
],
test_root
)
^
0x1
;
if
(
err_loc_eqn
==
0x0
)
{
if
(
found_num_root
==
0
)
{
bit3_root0
=
test_root
;
found_num_root
=
1
;
}
else
if
(
found_num_root
==
1
)
{
bit3_root1
=
test_root
;
found_num_root
=
2
;
}
else
if
(
found_num_root
==
2
)
{
bit3_root2
=
test_root
;
found_num_root
=
3
;
break
;
}
}
}
if
(
found_num_root
!=
3
)
return
-
EINVAL
;
else
{
bit3_root0_inv
=
gf4096_inv
(
bit3_root0
);
bit3_root1_inv
=
gf4096_inv
(
bit3_root1
);
bit3_root2_inv
=
gf4096_inv
(
bit3_root2
);
find_3bit_err_pats
(
chk_syndrome_list
[
0
],
chk_syndrome_list
[
1
],
chk_syndrome_list
[
2
],
bit3_root0_inv
,
bit3_root1_inv
,
bit3_root2_inv
,
err_pats
);
//check if only 3-bit error
tmp0
=
gf4096_mul
(
bit3_root0_inv
,
bit3_root0_inv
);
tmp0
=
gf4096_mul
(
tmp0
,
tmp0
);
tmp0
=
gf4096_mul
(
tmp0
,
bit3_root0_inv
);
tmp0
=
gf4096_mul
(
tmp0
,
bit3_root0_inv
);
//rinv0^6
tmp1
=
gf4096_mul
(
tmp0
,
bit3_root0_inv
);
//rinv0^7
tmp2
=
gf4096_mul
(
bit3_root1_inv
,
bit3_root1_inv
);
tmp2
=
gf4096_mul
(
tmp2
,
tmp2
);
tmp2
=
gf4096_mul
(
tmp2
,
bit3_root1_inv
);
tmp2
=
gf4096_mul
(
tmp2
,
bit3_root1_inv
);
//rinv1^6
tmp3
=
gf4096_mul
(
tmp2
,
bit3_root1_inv
);
//rinv1^7
tmp4
=
gf4096_mul
(
bit3_root2_inv
,
bit3_root2_inv
);
tmp4
=
gf4096_mul
(
tmp4
,
tmp4
);
tmp4
=
gf4096_mul
(
tmp4
,
bit3_root2_inv
);
tmp4
=
gf4096_mul
(
tmp4
,
bit3_root2_inv
);
//rinv2^6
tmp5
=
gf4096_mul
(
tmp4
,
bit3_root2_inv
);
//rinv2^7
//check if only 3 errors
if
((
chk_syndrome_list
[
6
]
==
(
gf4096_mul
(
err_pats
[
0
],
tmp0
)
^
gf4096_mul
(
err_pats
[
1
],
tmp2
)
^
gf4096_mul
(
err_pats
[
2
],
tmp4
)))
&
(
chk_syndrome_list
[
7
]
==
(
gf4096_mul
(
err_pats
[
0
],
tmp1
)
^
gf4096_mul
(
err_pats
[
1
],
tmp3
)
^
gf4096_mul
(
err_pats
[
2
],
tmp5
))))
{
if
((
err_pos
(
bit3_root0_inv
)
==
0xfff
)
|
(
err_pos
(
bit3_root1_inv
)
==
0xfff
)
|
(
err_pos
(
bit3_root2_inv
)
==
0xfff
))
{
return
-
EINVAL
;
}
else
{
err_info
[
0
]
=
0x3
;
err_info
[
1
]
=
(
0x55e
-
err_pos
(
bit3_root0_inv
));
err_info
[
2
]
=
(
0x55e
-
err_pos
(
bit3_root1_inv
));
err_info
[
3
]
=
(
0x55e
-
err_pos
(
bit3_root2_inv
));
err_info
[
5
]
=
err_pats
[
0
];
err_info
[
6
]
=
err_pats
[
1
];
err_info
[
7
]
=
err_pats
[
2
];
return
0
;
}
}
else
return
-
EINVAL
;
}
}
static
int
chk_4_err_only
(
unsigned
short
*
chk_syndrome_list
,
unsigned
short
*
err_info
)
{
unsigned
short
coefs
[
4
];
unsigned
short
err_pats
[
4
];
int
found_num_root
=
0
;
unsigned
short
bit4_root0
,
bit4_root1
,
bit4_root2
,
bit4_root3
;
unsigned
short
bit4_root0_inv
,
bit4_root1_inv
,
bit4_root2_inv
,
bit4_root3_inv
;
unsigned
short
err_loc_eqn
,
test_root
;
find_4bit_err_coefs
(
chk_syndrome_list
[
0
],
chk_syndrome_list
[
1
],
chk_syndrome_list
[
2
],
chk_syndrome_list
[
3
],
chk_syndrome_list
[
4
],
chk_syndrome_list
[
5
],
chk_syndrome_list
[
6
],
chk_syndrome_list
[
7
],
coefs
);
for
(
test_root
=
0x1
;
test_root
<
0xfff
;
test_root
++
)
{
err_loc_eqn
=
gf4096_mul
(
coefs
[
3
],
gf4096_mul
(
gf4096_mul
(
gf4096_mul
(
test_root
,
test_root
),
test_root
),
test_root
))
^
gf4096_mul
(
coefs
[
2
],
gf4096_mul
(
gf4096_mul
(
test_root
,
test_root
),
test_root
))
^
gf4096_mul
(
coefs
[
1
],
gf4096_mul
(
test_root
,
test_root
))
^
gf4096_mul
(
coefs
[
0
],
test_root
)
^
0x1
;
if
(
err_loc_eqn
==
0x0
)
{
if
(
found_num_root
==
0
)
{
bit4_root0
=
test_root
;
found_num_root
=
1
;
}
else
if
(
found_num_root
==
1
)
{
bit4_root1
=
test_root
;
found_num_root
=
2
;
}
else
if
(
found_num_root
==
2
)
{
bit4_root2
=
test_root
;
found_num_root
=
3
;
}
else
{
found_num_root
=
4
;
bit4_root3
=
test_root
;
break
;
}
}
}
if
(
found_num_root
!=
4
)
{
return
-
EINVAL
;
}
else
{
bit4_root0_inv
=
gf4096_inv
(
bit4_root0
);
bit4_root1_inv
=
gf4096_inv
(
bit4_root1
);
bit4_root2_inv
=
gf4096_inv
(
bit4_root2
);
bit4_root3_inv
=
gf4096_inv
(
bit4_root3
);
find_4bit_err_pats
(
chk_syndrome_list
[
0
],
chk_syndrome_list
[
1
],
chk_syndrome_list
[
2
],
chk_syndrome_list
[
3
],
bit4_root0_inv
,
bit4_root1_inv
,
bit4_root2_inv
,
bit4_root3_inv
,
err_pats
);
err_info
[
0
]
=
0x4
;
err_info
[
1
]
=
(
0x55e
-
err_pos
(
bit4_root0_inv
));
err_info
[
2
]
=
(
0x55e
-
err_pos
(
bit4_root1_inv
));
err_info
[
3
]
=
(
0x55e
-
err_pos
(
bit4_root2_inv
));
err_info
[
4
]
=
(
0x55e
-
err_pos
(
bit4_root3_inv
));
err_info
[
5
]
=
err_pats
[
0
];
err_info
[
6
]
=
err_pats
[
1
];
err_info
[
7
]
=
err_pats
[
2
];
err_info
[
8
]
=
err_pats
[
3
];
return
0
;
}
}
void
correct_12bit_symbol
(
unsigned
char
*
buf
,
unsigned
short
sym
,
unsigned
short
val
)
{
if
(
unlikely
(
sym
>
1366
))
{
printk
(
KERN_ERR
"Error: symbol %d out of range; cannot correct
\n
"
,
sym
);
}
else
if
(
sym
==
0
)
{
buf
[
0
]
^=
val
;
}
else
if
(
sym
&
1
)
{
buf
[
1
+
(
3
*
(
sym
-
1
))
/
2
]
^=
(
val
>>
4
);
buf
[
2
+
(
3
*
(
sym
-
1
))
/
2
]
^=
((
val
&
0xf
)
<<
4
);
}
else
{
buf
[
2
+
(
3
*
(
sym
-
2
))
/
2
]
^=
(
val
>>
8
);
buf
[
3
+
(
3
*
(
sym
-
2
))
/
2
]
^=
(
val
&
0xff
);
}
}
static
int
debugecc
=
0
;
module_param
(
debugecc
,
int
,
0644
);
int
cafe_correct_ecc
(
unsigned
char
*
buf
,
unsigned
short
*
chk_syndrome_list
)
{
unsigned
short
err_info
[
9
];
int
i
;
if
(
debugecc
)
{
printk
(
KERN_WARNING
"cafe_correct_ecc invoked. Syndromes %x %x %x %x %x %x %x %x
\n
"
,
chk_syndrome_list
[
0
],
chk_syndrome_list
[
1
],
chk_syndrome_list
[
2
],
chk_syndrome_list
[
3
],
chk_syndrome_list
[
4
],
chk_syndrome_list
[
5
],
chk_syndrome_list
[
6
],
chk_syndrome_list
[
7
]);
for
(
i
=
0
;
i
<
2048
;
i
+=
16
)
{
printk
(
KERN_WARNING
"D %04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x
\n
"
,
i
,
buf
[
i
],
buf
[
i
+
1
],
buf
[
i
+
2
],
buf
[
i
+
3
],
buf
[
i
+
4
],
buf
[
i
+
5
],
buf
[
i
+
6
],
buf
[
i
+
7
],
buf
[
i
+
8
],
buf
[
i
+
9
],
buf
[
i
+
10
],
buf
[
i
+
11
],
buf
[
i
+
12
],
buf
[
i
+
13
],
buf
[
i
+
14
],
buf
[
i
+
15
]);
}
for
(
;
i
<
2112
;
i
+=
16
)
{
printk
(
KERN_WARNING
"O %02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x
\n
"
,
i
-
2048
,
buf
[
i
],
buf
[
i
+
1
],
buf
[
i
+
2
],
buf
[
i
+
3
],
buf
[
i
+
4
],
buf
[
i
+
5
],
buf
[
i
+
6
],
buf
[
i
+
7
],
buf
[
i
+
8
],
buf
[
i
+
9
],
buf
[
i
+
10
],
buf
[
i
+
11
],
buf
[
i
+
12
],
buf
[
i
+
13
],
buf
[
i
+
14
],
buf
[
i
+
15
]);
}
}
if
(
chk_no_err_only
(
chk_syndrome_list
,
err_info
)
&&
chk_1_err_only
(
chk_syndrome_list
,
err_info
)
&&
chk_2_err_only
(
chk_syndrome_list
,
err_info
)
&&
chk_3_err_only
(
chk_syndrome_list
,
err_info
)
&&
chk_4_err_only
(
chk_syndrome_list
,
err_info
))
{
return
-
EIO
;
}
for
(
i
=
0
;
i
<
err_info
[
0
];
i
++
)
{
if
(
debugecc
)
printk
(
KERN_WARNING
"Correct symbol %d with 0x%03x
\n
"
,
err_info
[
1
+
i
],
err_info
[
5
+
i
]);
correct_12bit_symbol
(
buf
,
err_info
[
1
+
i
],
err_info
[
5
+
i
]);
}
return
err_info
[
0
];
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment