2 * lib/reed_solomon/decode_rs.c
5 * Generic Reed Solomon encoder / decoder library
7 * Copyright 2002, Phil Karn, KA9Q
8 * May be used under the terms of the GNU General Public License (GPL)
10 * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
12 * $Id: decode_rs.c,v 1.7 2005/11/07 11:14:59 gleixner Exp $
16 /* Generic data width independent code which is included by the
20 int deg_lambda
, el
, deg_omega
;
23 int nroots
= rs
->nroots
;
26 int iprim
= rs
->iprim
;
27 uint16_t *alpha_to
= rs
->alpha_to
;
28 uint16_t *index_of
= rs
->index_of
;
29 uint16_t u
, q
, tmp
, num1
, num2
, den
, discr_r
, syn_error
;
30 /* Err+Eras Locator poly and syndrome poly The maximum value
31 * of nroots is 8. So the necessary stack size will be about
34 uint16_t lambda
[nroots
+ 1], syn
[nroots
];
35 uint16_t b
[nroots
+ 1], t
[nroots
+ 1], omega
[nroots
+ 1];
36 uint16_t root
[nroots
], reg
[nroots
+ 1], loc
[nroots
];
38 uint16_t msk
= (uint16_t) rs
->nn
;
40 /* Check length parameter for validity */
41 pad
= nn
- nroots
- len
;
42 BUG_ON(pad
< 0 || pad
>= nn
);
44 /* Does the caller provide the syndrome ? */
48 /* form the syndromes; i.e., evaluate data(x) at roots of
50 for (i
= 0; i
< nroots
; i
++)
51 syn
[i
] = (((uint16_t) data
[0]) ^ invmsk
) & msk
;
53 for (j
= 1; j
< len
; j
++) {
54 for (i
= 0; i
< nroots
; i
++) {
56 syn
[i
] = (((uint16_t) data
[j
]) ^
59 syn
[i
] = ((((uint16_t) data
[j
]) ^
61 alpha_to
[rs_modnn(rs
, index_of
[syn
[i
]] +
67 for (j
= 0; j
< nroots
; j
++) {
68 for (i
= 0; i
< nroots
; i
++) {
70 syn
[i
] = ((uint16_t) par
[j
]) & msk
;
72 syn
[i
] = (((uint16_t) par
[j
]) & msk
) ^
73 alpha_to
[rs_modnn(rs
, index_of
[syn
[i
]] +
80 /* Convert syndromes to index form, checking for nonzero condition */
82 for (i
= 0; i
< nroots
; i
++) {
84 s
[i
] = index_of
[s
[i
]];
88 /* if syndrome is zero, data[] is a codeword and there are no
89 * errors to correct. So return data[] unmodified
96 memset(&lambda
[1], 0, nroots
* sizeof(lambda
[0]));
100 /* Init lambda to be the erasure locator polynomial */
101 lambda
[1] = alpha_to
[rs_modnn(rs
,
102 prim
* (nn
- 1 - eras_pos
[0]))];
103 for (i
= 1; i
< no_eras
; i
++) {
104 u
= rs_modnn(rs
, prim
* (nn
- 1 - eras_pos
[i
]));
105 for (j
= i
+ 1; j
> 0; j
--) {
106 tmp
= index_of
[lambda
[j
- 1]];
109 alpha_to
[rs_modnn(rs
, u
+ tmp
)];
115 for (i
= 0; i
< nroots
+ 1; i
++)
116 b
[i
] = index_of
[lambda
[i
]];
119 * Begin Berlekamp-Massey algorithm to determine error+erasure
124 while (++r
<= nroots
) { /* r is the step number */
125 /* Compute discrepancy at the r-th step in poly-form */
127 for (i
= 0; i
< r
; i
++) {
128 if ((lambda
[i
] != 0) && (s
[r
- i
- 1] != nn
)) {
130 alpha_to
[rs_modnn(rs
,
131 index_of
[lambda
[i
]] +
135 discr_r
= index_of
[discr_r
]; /* Index form */
137 /* 2 lines below: B(x) <-- x*B(x) */
138 memmove (&b
[1], b
, nroots
* sizeof (b
[0]));
141 /* 7 lines below: T(x) <-- lambda(x)-discr_r*x*b(x) */
143 for (i
= 0; i
< nroots
; i
++) {
145 t
[i
+ 1] = lambda
[i
+ 1] ^
146 alpha_to
[rs_modnn(rs
, discr_r
+
149 t
[i
+ 1] = lambda
[i
+ 1];
151 if (2 * el
<= r
+ no_eras
- 1) {
152 el
= r
+ no_eras
- el
;
154 * 2 lines below: B(x) <-- inv(discr_r) *
157 for (i
= 0; i
<= nroots
; i
++) {
158 b
[i
] = (lambda
[i
] == 0) ? nn
:
159 rs_modnn(rs
, index_of
[lambda
[i
]]
163 /* 2 lines below: B(x) <-- x*B(x) */
164 memmove(&b
[1], b
, nroots
* sizeof(b
[0]));
167 memcpy(lambda
, t
, (nroots
+ 1) * sizeof(t
[0]));
171 /* Convert lambda to index form and compute deg(lambda(x)) */
173 for (i
= 0; i
< nroots
+ 1; i
++) {
174 lambda
[i
] = index_of
[lambda
[i
]];
178 /* Find roots of error+erasure locator polynomial by Chien search */
179 memcpy(®
[1], &lambda
[1], nroots
* sizeof(reg
[0]));
180 count
= 0; /* Number of roots of lambda(x) */
181 for (i
= 1, k
= iprim
- 1; i
<= nn
; i
++, k
= rs_modnn(rs
, k
+ iprim
)) {
182 q
= 1; /* lambda[0] is always 0 */
183 for (j
= deg_lambda
; j
> 0; j
--) {
185 reg
[j
] = rs_modnn(rs
, reg
[j
] + j
);
186 q
^= alpha_to
[reg
[j
]];
190 continue; /* Not a root */
191 /* store root (index-form) and error location number */
194 /* If we've already found max possible roots,
195 * abort the search to save time
197 if (++count
== deg_lambda
)
200 if (deg_lambda
!= count
) {
202 * deg(lambda) unequal to number of roots => uncorrectable
209 * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
210 * x**nroots). in index form. Also find deg(omega).
212 deg_omega
= deg_lambda
- 1;
213 for (i
= 0; i
<= deg_omega
; i
++) {
215 for (j
= i
; j
>= 0; j
--) {
216 if ((s
[i
- j
] != nn
) && (lambda
[j
] != nn
))
218 alpha_to
[rs_modnn(rs
, s
[i
- j
] + lambda
[j
])];
220 omega
[i
] = index_of
[tmp
];
224 * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
225 * inv(X(l))**(fcr-1) and den = lambda_pr(inv(X(l))) all in poly-form
227 for (j
= count
- 1; j
>= 0; j
--) {
229 for (i
= deg_omega
; i
>= 0; i
--) {
231 num1
^= alpha_to
[rs_modnn(rs
, omega
[i
] +
234 num2
= alpha_to
[rs_modnn(rs
, root
[j
] * (fcr
- 1) + nn
)];
237 /* lambda[i+1] for i even is the formal derivative
238 * lambda_pr of lambda[i] */
239 for (i
= min(deg_lambda
, nroots
- 1) & ~1; i
>= 0; i
-= 2) {
240 if (lambda
[i
+ 1] != nn
) {
241 den
^= alpha_to
[rs_modnn(rs
, lambda
[i
+ 1] +
245 /* Apply error to data */
246 if (num1
!= 0 && loc
[j
] >= pad
) {
247 uint16_t cor
= alpha_to
[rs_modnn(rs
,index_of
[num1
] +
249 nn
- index_of
[den
])];
250 /* Store the error correction pattern, if a
251 * correction buffer is available */
255 /* If a data buffer is given and the
256 * error is inside the message,
258 if (data
&& (loc
[j
] < (nn
- nroots
)))
259 data
[loc
[j
] - pad
] ^= cor
;
265 if (eras_pos
!= NULL
) {
266 for (i
= 0; i
< count
; i
++)
267 eras_pos
[i
] = loc
[i
] - pad
;