1 /* @(#)edc_ecc_dec.c	1.14 16/04/01 Copyright 1998-2001 Heiko Eissfeldt, Copyright 2006-2013 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)edc_ecc_dec.c	1.14 16/04/01 Copyright 1998-2001 Heiko Eissfeldt, Copyright 2006-2013 J. Schilling";
6 #endif
7 
8 /*
9  * This file contains protected intellectual property.
10  *
11  * reed-solomon encoder / decoder for compact discs.
12  *
13  * Copyright 1998-2001 by Heiko Eissfeldt
14  * Copyright 2006-2013 by Joerg Schilling
15  */
16 /*
17  * The contents of this file are subject to the terms of the
18  * Common Development and Distribution License, Version 1.0 only
19  * (the "License").  You may not use this file except in compliance
20  * with the License.
21  *
22  * See the file CDDL.Schily.txt in this distribution for details.
23  * A copy of the CDDL is also available via the Internet at
24  * http://www.opensource.org/licenses/cddl1.txt
25  *
26  * When distributing Covered Code, include this CDDL HEADER in each
27  * file and include the License file CDDL.Schily.txt from this distribution.
28  */
29 
30 #include <schily/stdio.h>
31 #include <schily/stdlib.h>
32 #include <schily/string.h>
33 #include <assert.h>
34 #include <schily/utypes.h>
35 
36 #define	EDC_DECODER_HACK	/* Hack to allow using edc.h with ecc.h */
37 #define	EDC_DECODER
38 #define	EDC_SUBCHANNEL
39 #define	EDC_LAYER2
40 #include "edc.h"
41 
42 #ifndef	HAVE_MEMMOVE
43 #include <schily/libport.h>	/* Define missing prototypes */
44 /*#define	memmove(dst, src, size)		movebytes((src), (dst), (size))*/
45 #define	memmove(d, s, n)	bcopy((s), (d), (n))
46 #endif
47 
48 #include "edc_code_tables"
49 
50 #define	DEBUG	-2
51 #define	TELLME	0
52 
53 #if	DEBUG < 0
54 #define	NDEBUG	1	/* turn assertions off */
55 #endif
56 
57 #ifdef	EDC_DECODER
58 
59 /* macros for high level functionality */
60 
61 /* initialize the Berlekamp-Massey decoder */
62 #define	INIT_BMD \
63 	memset(err_locations, 0, sizeof (err_locations));			\
64 	memset(err_values, 0, sizeof (err_values));				\
65 	memset(tmp_loc, 0, sizeof (tmp_loc));					\
66 	err_locations[0] = 1;							\
67 	err_values[0] = 1;
68 
69 /* create an error location polynomial from given erasures. */
70 #define	INIT_ERASURES(ERAS, ERRORS, MODUL, LOG, ALOG)				\
71 		err_locations[1] = ALOG[MODUL - (ERAS[0]+1)];			\
72 		for (i = 1; i < min(erasures, ERRORS*2); i++) {			\
73 			for (j = i+1; j > 0; j--) { 				\
74 				if (err_locations[j - 1] != 0) {		\
75 					err_locations[j] ^= ALOG[		\
76 						LOG[err_locations[j - 1]]	\
77 						+ MODUL - (ERAS[i]+1)];		\
78 				}						\
79 			}							\
80 		}
81 
82 /* the condition for ignoring this root */
83 #define	FIND_ROOTS_TABOO(SECTORMACRO, UNIT, SKIPPED) \
84 			((SECTORMACRO(UNIT, (i-SKIPPED))) >= low_taboo &&	\
85 			(SECTORMACRO(UNIT, (i-SKIPPED))) <= high_taboo)
86 
87 /* debugging code for the error location polynomial. */
88 #define	DEBUG_ERASURE_POLY(LOG, ALOG, MODUL, ERRORS, SKIPPED, TABOO) \
89 		if (DEBUG > 4) { \
90 			fprintf(stderr, " Errloc coeff.: "); \
91 			for (i = 0; i <= min(erasures, ERRORS); i++) { \
92 				fprintf(stderr, "%d (%d), ", err_locations[i], LOG[err_locations[i]]); \
93 			} \
94 			fprintf(stderr, "\n"); \
95 		} \
96 		for (roots_found = 0, i = SKIPPED; i < MODUL; i++) { \
97 			int pval = 0; \
98 			if (TABOO) { \
99 				fprintf(stderr, "QLOCK(%u)\t", i-SKIPPED); \
100 				continue; \
101 			} \
102 			for (j = min(erasures, ERRORS*2); ; j--) { \
103 				if (err_locations[j] != 0) \
104 					pval ^= ALOG[LOG[err_locations[j]] + j*(i+1) % MODUL ]; \
105 				if (j == 0) \
106 					break; \
107 			} \
108 			if (pval != 0) continue; \
109 			roots_found++; \
110 			if (DEBUG > 4) fprintf(stderr, "root at %d\n", i - SKIPPED); \
111 		} \
112 		if (min(erasures, ERRORS*2) != roots_found) \
113 			fprintf(stderr, "error location poly is wrong erasures=%d, roots=%d\n", erasures, roots_found);
114 
115 /* calculate the 'discrepancy' in the Berlekmap-Massey decoder. */
116 #define	CALC_DISCREPANCY(LOG, ALOG) \
117 		discrepancy = SYND(j); \
118 		for (i = 1; i <= j; i++) { \
119 			if (err_locations[i] == 0 || SYND(j-i) == 0) \
120 				continue; \
121 			discrepancy ^= \
122 				ALOG[LOG[err_locations[i]]+ \
123 					    LOG[SYND(j-i)]]; \
124 		}
125 
126 /* build a stage of the shift register. */
127 #define	BUILD_SHIFT_REGISTER(LOG, ALOG, MODUL, ERRORS) \
128 			int	ld = LOG[discrepancy]; \
129 			if (l+l <= j + erasures) { \
130 				/*						\
131 				 * complex case			\
132 				 * err_locations and tmp_loc needs to be changed \
133 				 */						\
134 				unsigned char	tmp_errl[2*ERRORS+1];		\
135 				int		lnd = MODUL - ld;		\
136 				/*						\
137 				 * change shift register length			\
138 				 */						\
139 				memcpy(tmp_errl, err_locations+k, l);		\
140 				for (i = 0; i < k + l; i++) {			\
141 					int	c = err_locations[i];		\
142 					if (i < l) {				\
143 						int	e = tmp_loc[i];		\
144 						if (e != 0) \
145 							tmp_errl[i] ^= ALOG[ LOG[e] + ld]; \
146 					}					\
147 					if (c != 0)				\
148 						tmp_loc[i] = ALOG[LOG[c] + lnd]; \
149 					else					\
150 						tmp_loc[i] = 0;			\
151 				}						\
152 				memcpy(err_locations+k, tmp_errl, l);		\
153 				l = j - l + erasures + 1;			\
154 				k = 0;						\
155 			} else {						\
156 				/*						\
157 				 * increase order of shift register		\
158 				 */						\
159 				for (i = k; i < k + l; i++) {			\
160 					if (tmp_loc[i-k] != 0)			\
161 						err_locations[i] ^= ALOG[ LOG[tmp_loc[i-k]] + ld]; \
162 				}						\
163 			}
164 
165 /* do a chien search to find roots of the error location polynomial. */
166 #define	FIND_ROOTS(LOG, ALOG, MODUL, ERRORS, SKIPPED, TABOOMACRO) \
167 	for (roots_found = 0, i = SKIPPED; i < MODUL; i++) { \
168 		unsigned pval; \
169 		if (TABOOMACRO) { \
170 			continue; \
171 		} \
172 		pval = 0; \
173 		for (j = l; ; j--) { \
174 			if (err_locations[j] != 0) { \
175 				pval ^= ALOG[LOG[err_locations[j]] + j*(i+1) % MODUL ]; \
176 			} \
177 			if (j == 0) \
178 				break; \
179 		} \
180 		if (pval == 0) { \
181 			if (roots_found < 2*ERRORS) { \
182 				roots[roots_found] = (unsigned char)i; \
183 			} \
184 			roots_found++; \
185 if (DEBUG > 3) fprintf(stderr, "%d. root=%d\t", roots_found, i - SKIPPED); \
186 		} \
187 	}
188 
189 /* calculate the error valuator. */
190 #define	CALC_ERROR_VALUATOR(LOG, ALOG) \
191 	for (j = 0; j < l; j++) { \
192 		err_values[j] = 0; \
193 		for (i = 0; i <= j; i++) { \
194 			if (err_locations[i] != 0 && SYND(j-i) != 0) \
195 				err_values[j] ^= ALOG[ LOG[err_locations[i]] + LOG[SYND(j-i)]]; \
196 		} \
197 	}
198 
199 /*
200  * do the correction in the 'msb' part of the p layer
201  * at column 'column' and row 'i'
202  * with an error of 'ERROR'
203  */
204 #define	DO_L2_P_CORRECTION(ERROR, SKIPPED) \
205 		{ \
206 			unsigned position; \
207 			unsigned dia; \
208 			position = SECBPL(column, i-SKIPPED); \
209 			assert(position < 2352-12); \
210 			if (NO_DECODING_FAILURES) { \
211 				if (gdp->global_erasures != NULL &&\
212 				    gdp->global_erasures[position+msb] == 0) return (1); \
213 			} \
214 			dia = DIALO(position/2); \
215 			if	(STOP_FAILURE) { \
216 				if (gdp->Qcorrcount[msb][dia] == 0 && \
217 				    gdp->Pcorrcount[msb][dia] == 0 && \
218 					gdp->corrcount[position+msb] == 0) { \
219 					calc_L2_Q_syndrome(inout-msb, dia, &gdp->Qsyndromes[2*dia]); \
220 					if (gdp->Qsyndromes[2*dia+msb] == 0 &&\
221 					    gdp->Qsyndromes[2*dia+msb+L2_Q/2] == 0) { \
222 						/* probably a decoding failure */ \
223 						if (TELLME)	{ \
224 							fprintf(stderr, "FAILURE (@%d) Dia %d is clean\n", position+12+msb, dia); \
225 						} \
226 						return (1); \
227 					} \
228 				} \
229 			} \
230 			if (gdp->corrcount[position+msb] < MAX_TOGGLE) { \
231 				inout[position] ^= (unsigned char)ERROR; \
232 				if (DEBUG > 1) { \
233 					fprintf(stderr, "\t-%d-", 12+position + msb); \
234 				} \
235 				gdp->corrcount[position+msb]++; \
236 				gdp->Pcorrcount[msb][column]++; \
237 				kill_erasure(position, msb, gdp); \
238 				if (loops != 0) check_P_for_decoding_failures(gdp->Qsyndromes, msb, position/2, gdp); \
239 			} else return (1); \
240 		}
241 
242 /*
243  * do the correction in the 'msb' part of the q layer
244  * at diagonal 'diagonal' and offset 'i'
245  * with an error of 'ERROR'
246  */
247 #define	DO_L2_Q_CORRECTION(ERROR, SKIPPED) \
248 		{ \
249 			unsigned position; \
250 			position = SECBQL(diagonal, i-SKIPPED); \
251 			assert(position < 2352-12); \
252 			if (NO_DECODING_FAILURES) { \
253 				if (gdp->global_erasures != NULL &&\
254 				    gdp->global_erasures[position+msb] == 0) return (1); \
255 			} \
256 			if	(STOP_FAILURE2) { \
257 				if (position < 2236) { \
258 					unsigned col = COL(position/2); \
259 					if ((gdp->Pcorrcount[msb][col] > 0 && \
260 						gdp->corrcount[position+msb] > 0) || \
261 					    (gdp->Pcorrcount[msb][col] == 0 && \
262 						gdp->corrcount[position+msb] > 0)) { \
263 						calc_L2_P_syndrome(inout-msb, col, &gdp->Psyndromes[2*col]); \
264 						if (gdp->Psyndromes[2*col+msb] == 0 &&\
265 						    gdp->Psyndromes[2*col+msb+L2_P/2] == 0) { \
266 							/* probably a decoding failure */	\
267 							if (TELLME)	{			\
268 								fprintf(stderr,			\
269 									"FAILURE (@%d) col %d is clean\n", \
270 									position+12+msb, col);	\
271 							}					\
272 							return (1);				\
273 						} \
274 					} \
275 				} \
276 			} \
277 			if (gdp->corrcount[position+msb] < MAX_TOGGLE) { \
278 				inout[position] ^= (unsigned char)ERROR; \
279 				gdp->corrcount[position+msb]++; \
280 				gdp->Qcorrcount[msb][diagonal]++; \
281 				if (DEBUG > 1) { \
282 					fprintf(stderr, "\t-%d-", 12+position + msb); \
283 				} \
284 				kill_erasure(position, msb, gdp); \
285 				if (i-SKIPPED < L12_P_LENGTH) *q_changed_p = 1; \
286 				check_Q_for_decoding_failures(gdp->Psyndromes, msb, position/2, gdp); \
287 			} else return (1); \
288 		}
289 
290 
291 /*
292  * do the correction in one of the subchannel layers
293  * at offset 'i'
294  * with an error of 'ERROR'
295  */
296 #define	DO_SUB_CORRECTION(ERROR, SKIPPED) \
297 					{ \
298 						unsigned position; \
299 						position = (i-SKIPPED); \
300 						if (DEBUG > 1) \
301 								fprintf(stderr, \
302 									"Position %d=0x%x has error 0x%x giving 0x%x\n", \
303 									position, inout[position], ERROR, \
304 									inout[position] ^ ERROR); \
305 						inout[position] ^= (unsigned char)ERROR; \
306 					}
307 
308 /*
309  * apply the forney algorithm on error valuator and error location
310  * polynomial in order to do the corrections.
311  */
312 #define	APPLY_FORNEY_ALGORITHM(LOG, ALOG, MODUL, SKIPPED, DO_CORRECTION) \
313 	for (j = 0; j < roots_found; j++) { \
314 			/* \
315 			 * root in error location polynomial is found! \
316 			 * apply Forney algorithm to get error value \
317 			 */ \
318 			int	numerator; \
319 			i = roots[j]; \
320 			numerator = 0; \
321 			for (k = l-1; ; k--) { \
322 				if (err_values[k] != 0) { \
323 					numerator ^= ALOG[LOG[err_values[k]] + (i+1)*k]; \
324 				} \
325 				if (k == 0) \
326 					break; \
327 			} \
328 			if (l > 1) { \
329 					int	error; \
330 					int	denominator; \
331 					denominator = 0; \
332 					for (k = (l-1) & ~1; ; k -= 2) { \
333 						if (err_locations[k+1] != 0) { \
334 							denominator ^= ALOG[LOG[err_locations[k+1]] + (k+1)*(i+1)]; \
335 						} \
336 						if (k == 0) \
337 							break; \
338 					} \
339 					assert(denominator != 0); \
340 					error = ALOG[(MODUL - LOG[denominator] + LOG[numerator]) % MODUL]; \
341 					DO_CORRECTION(error, SKIPPED) \
342 			} else { \
343 					DO_CORRECTION(numerator, SKIPPED) \
344 			} \
345 	}
346 
347 #endif
348 
349 #ifdef	EDC_LAYER2
350 #ifdef	EDC_DECODER
351 
352 /*
353  * set THOROUGH to 1 for maximum correction capabilities.
354  * set THOROUGH to 0 for maximum speed.
355  *
356  * maximum speed: P and Q corrections are done once
357  *
358  * maximum capabilities: iteration between layers are used with several
359  *		  heuristics. Error positions are deduced and supplied to
360  *		  the next layer.
361  *
362  */
363 #define	THOROUGH	1
364 
365 #if	THOROUGH
366 #ifndef	MAXLOOPS
367 #define	MAXLOOPS	15
368 #endif
369 #else
370 #define	MAXLOOPS	1
371 #endif
372 
373 #define	MAX_TOGGLE	((MAXLOOPS + 1) & ~1)
374 #define	STOP_FAILURE	1
375 #define	STOP_FAILURE2	0
376 
377 #define	NO_DECODING_FAILURES	0
378 
379 
380 typedef struct globdata {
381 	unsigned char Qsyndromes[L2_Q];	/* all syndromes of Q */
382 	unsigned char Psyndromes[L2_P];	/* all syndromes of P */
383 
384 	/******************** erasure related stuff *********************/
385 
386 	unsigned char *global_erasures;	/* pointer to the erasure array */
387 	unsigned char Perapos[2][L2_P/4][L12_Q_LENGTH]; /* erasures in columns */
388 	unsigned char Qerapos[2][L2_Q/4][L12_P_LENGTH+2]; /* erasures in diagonals */
389 	unsigned char Pcount[2][L2_P/4]; /* count for corrections */
390 	unsigned char Qcount[2][L2_Q/4];
391 	unsigned char Pfailed[2][L2_P/4]; /* count for uncorrectables */
392 	unsigned char Qfailed[2][L2_Q/4];
393 
394 	unsigned char corrcount[2352]; /* count for corrections */
395 	unsigned char Pcorrcount[2][L2_P/4]; /* count for P corrections */
396 	unsigned char Qcorrcount[2][L2_Q/4]; /* count for Q corrections */
397 } gdat, *gdatp;
398 
399 
400 static void kill_erasure __PR((unsigned position, unsigned msb, gdatp gdp));
401 
402 
403 /***************** cyclic redundancy check function **************/
404 
405 
406 /*
407  * calculate the crc checksum depending on the sector type.
408  *
409  * parameters:
410  *   input:
411  *		inout is the data sector as a byte array at offset 0
412  *		type is the sector type (MODE_1, MODE_2_FORM_1 or MODE_2_FORM_2)
413  *		loops is a flag indicating erasure initialization, when 0.
414  *			      Should be set to 0 at the very first time.
415  *		gdp is a pointer to auxiliary book keeping data.
416  *   output: none
417  *
418  * return value:	1, if cyclic redundancy checksum is 0 (no errors)
419  *			0, if errors are present.
420  *
421  */
422 
423 static int do_crc_check __PR((unsigned char inout[(L2_RAW + L2_Q + L2_P)], int type, int loops, gdatp gdp));
424 
do_crc_check(inout,type,loops,gdp)425 static int do_crc_check(inout, type, loops, gdp)
426 	unsigned char inout[(L2_RAW + L2_Q + L2_P)];
427 	int type;
428 	int loops;
429 	gdatp	gdp;
430 {
431 	unsigned result;
432 	unsigned low;
433 	unsigned high;
434 
435 	/*
436 	 * Verify the checksum.
437 	 * This is dependent on the sector type being used!
438 	 */
439 	switch (type) {
440 		case EDC_MODE_1:
441 			low = 0;
442 			high = 16 + 2048 + 4 - 1;
443 		break;
444 		case EDC_MODE_2_FORM_1:
445 			low = 16;
446 			high = 16 + 8 + 2048 + 4 - 1;
447 		break;
448 		case EDC_MODE_2_FORM_2:
449 			low = 16;
450 			high = 16 + 8 + 2324 + 4 - 1;
451 			loops = 1;
452 		break;
453 		default:
454 			return (0);
455 	}
456 	result = build_edc(inout, low, high);
457 	if (loops == 0 && result == 0 && gdp->global_erasures != NULL) {
458 		unsigned i;
459 		/* kill all erasures for this range */
460 		for (i = max(low, 12)-12; i <= high-12; i++) {
461 			if (gdp->global_erasures[i] == 1)
462 				kill_erasure(i, i & 1, gdp);
463 		}
464 	}
465 	return (result == 0);	/* failed, if result != 0 */
466 }
467 
468 
469 
470 /*
471  * calculate the crc checksum depending on the sector type.
472  *
473  * parameters:
474  *   input:
475  *		inout is the data sector as a byte array at offset 0
476  *		type is the sector type (MODE_1 or MODE_2_FORM_1)
477  *
478  * return value:	1, if cyclic redundancy checksum is 0 (no errors)
479  *			0, if errors are present.
480  *
481  */
482 int crc_check __PR((unsigned char inout[(L2_RAW + L2_Q + L2_P)], int type));
483 int
crc_check(inout,type)484 crc_check(inout, type)
485 	unsigned char inout[(L2_RAW + L2_Q + L2_P)];
486 	int type;
487 {
488 	return (do_crc_check(inout, type, 1, NULL));
489 }
490 
491 /******************* SYNDROM FUNCTIONS ************************/
492 
493 
494 /*
495  * calculate the syndrome for one diagonal of the Q parity layer of data sectors
496  * One diagonal consists of words (least significant byte first and most
497  * significant byte last).
498  *
499  * parameters:
500  *   input:
501  *	inout		the content of the data sector as a byte array
502  *			at offset 12.
503  *	diagonal	0..25, the diagonal to calculate the syndrome for.
504  *   output:
505  *	syndrome	the byte array beginning at the syndrome position for
506  *			that diagonal.
507  * return value:	1, if the syndrome is 0 (the diagonal shows no errors)
508  *			0, if errors are present.
509  */
510 static int
511 calc_L2_Q_syndrome __PR((unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q],
512 	unsigned diagonal, unsigned char syndrome[L2_Q/2+2]));
513 
514 static int
calc_L2_Q_syndrome(inout,diagonal,syndrome)515 calc_L2_Q_syndrome(inout, diagonal, syndrome)
516 	unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q];
517 	unsigned diagonal;
518 	unsigned char syndrome[L2_Q/2+2];
519 {
520 	register unsigned		dp0, dp1;
521 	register const	unsigned	short	*qa;
522 	register unsigned char		*Q;
523 
524 	qa = &qacc[diagonal][44];
525 	Q = syndrome;
526 	Q[0] = Q[2*L12_Q_LENGTH] = 0;
527 	Q[1] = Q[2*L12_Q_LENGTH+1] = 0;
528 
529 #define	QBODYEND(i) \
530 		dp0 = inout[*qa];			\
531 		dp1 = inout[*qa+1]; 			\
532 							\
533 		*Q++ ^= (unsigned char)dp0;		\
534 		*Q   ^= (unsigned char)dp1;		\
535 		Q += 26*2-1;				\
536 		*Q++ ^= L2syn[i][dp0];			\
537 		*Q   ^= L2syn[i][dp1];
538 
539 #define	QBODY(i)   \
540 		QBODYEND(i) \
541 		qa--;       \
542 		Q -= 26*2+1;
543 
544 		QBODY(0);  QBODY(1);  QBODY(2);  QBODY(3);  QBODY(4);
545 		QBODY(5);  QBODY(6);  QBODY(7);  QBODY(8);  QBODY(9);
546 		QBODY(10); QBODY(11); QBODY(12); QBODY(13); QBODY(14);
547 		QBODY(15); QBODY(16); QBODY(17); QBODY(18); QBODY(19);
548 		QBODY(20); QBODY(21); QBODY(22); QBODY(23); QBODY(24);
549 		QBODY(25); QBODY(26); QBODY(27); QBODY(28); QBODY(29);
550 		QBODY(30); QBODY(31); QBODY(32); QBODY(33); QBODY(34);
551 		QBODY(35); QBODY(36); QBODY(37); QBODY(38); QBODY(39);
552 		QBODY(40); QBODY(41); QBODY(42); QBODY(43); QBODYEND(44);
553 #undef  QBODY
554 #undef  QBODYEND
555 	return (0 == syndrome[0] &&
556 	    0 == syndrome[1] &&
557 	    0 == syndrome[0 + L12_Q_LENGTH * 2] &&
558 	    0 == syndrome[1 + L12_Q_LENGTH * 2]);
559 }
560 
561 /*
562  * calculate the syndrome for one column of the P parity layer of data sectors
563  * One column consists of words (least significant byte first and most
564  * significant byte last).
565  *
566  * parameters:
567  *   input:
568  *	inout		the content of the data sector as a byte array
569  *			at offset 12.
570  *	column		0..43, the column to calculate the syndrome for.
571  *   output:
572  *	syndrome	the byte array beginning at the syndrome position for
573  *			that column.
574  * return value:	1, if the syndrome is 0 (the column shows no errors)
575  *			0, if errors are present.
576  */
577 static int
578 calc_L2_P_syndrome __PR((unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P],
579 	unsigned column, unsigned char syndrome[L2_P/2+2]));
580 
581 static int
calc_L2_P_syndrome(inout,column,syndrome)582 calc_L2_P_syndrome(inout, column, syndrome)
583 	unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P];
584 	unsigned column;
585 	unsigned char syndrome[L2_P/2+2];
586 {
587 	register unsigned char  *P;
588 	register unsigned dp0, dp1;
589 
590 	P = syndrome;
591 	P[0] = P[1] = P[L12_P_LENGTH*2] = P[1+L12_P_LENGTH*2] = 0;
592 	inout += 2*column + (L12_Q_LENGTH-1)*L12_P_LENGTH*2 + 1;
593 
594 #define	PBODYEND(i)					\
595 	dp1 = *inout--;					\
596 	dp0 = *inout;					\
597 							\
598 	*P++ ^= (unsigned char)dp0;			\
599 	*P   ^= (unsigned char)dp1;			\
600 	P   += L12_P_LENGTH*2-1;			\
601 	*P++ ^= L2syn[i][dp0];				\
602 	*P   ^= L2syn[i][dp1];
603 
604 #define	PBODY(i)					\
605 			PBODYEND(i)			\
606 			inout -= L12_P_LENGTH*2-1;	\
607 			P   -= L12_P_LENGTH*2+1;
608 
609     PBODY(0)   PBODY(1)   PBODY(2)   PBODY(3)   PBODY(4)
610     PBODY(5)   PBODY(6)   PBODY(7)   PBODY(8)   PBODY(9)
611     PBODY(10)  PBODY(11)  PBODY(12)  PBODY(13)  PBODY(14)
612     PBODY(15)  PBODY(16)  PBODY(17)  PBODY(18)  PBODY(19)
613     PBODY(20)  PBODY(21)  PBODY(22)  PBODY(23)  PBODY(24)
614     PBODYEND(25)
615 #undef	PBODY
616 #undef	PBODYEND
617 	return (0 == syndrome[0] &&
618 	    0 == syndrome[1] &&
619 	    0 == syndrome[0 + L12_P_LENGTH * 2] &&
620 	    0 == syndrome[1 + L12_P_LENGTH * 2]);
621 }
622 
623 
624 /*
625  * set an erasure at the given position.
626  *
627  * Input parameters:
628  *  position: even offset in the sector after the sync header.
629  *  msb:		1 for the most significant byte.
630  *				0 for the least significant byte.
631  *  gdp:	  pointer to auxiliary structure.
632  */
633 static void set_erasure __PR((unsigned position, unsigned msb, gdatp gdp));
634 
set_erasure(position,msb,gdp)635 static void set_erasure(position, msb, gdp)
636 	unsigned position;
637 	unsigned	msb;
638 	gdatp	gdp;
639 {
640 	unsigned	dia;
641 	unsigned	cpos;
642 	unsigned	dpos;
643 	unsigned	k;
644 
645 	dia = DIA(position/2);
646 	dpos = POSQ(position/2) + L12_Q_SKIPPED;
647 
648 	if (position < 2*L12_P_LENGTH*L12_Q_LENGTH) {
649 		unsigned col;
650 		col = COL(position >> 1);
651 		cpos = POSP(position >> 1) + L12_P_SKIPPED;
652 
653 		/* look if erasure exists. */
654 		for (k = 0; k < gdp->Pcount[msb][col]; k++) {
655 			if (cpos == gdp->Perapos[msb][col][k]) break;
656 		}
657 
658 		if (k == gdp->Pcount[msb][col])
659 			gdp->Perapos[msb][col][gdp->Pcount[msb][col]++] = (unsigned char)cpos;
660 
661 #if	DEBUG >= 0
662 	fprintf(stderr, "\t+%d(c%u,d%u)", position+12+msb, col, dia);
663 	if (gdp->global_erasures[position+msb] == 0)	fprintf(stderr, "??");
664 	} else {
665 	fprintf(stderr, "\t+%d(c??,d%u)", position+12+msb, dia);
666 	if (gdp->global_erasures[position+msb] == 0)	fprintf(stderr, "??");
667 #endif
668 	}
669 
670 	for (k = 0; k < gdp->Qcount[msb][dia]; k++) {
671 		if (dpos == gdp->Qerapos[msb][dia][k]) break;
672 	}
673 
674 	if (k == gdp->Qcount[msb][dia])
675 		gdp->Qerapos[msb][dia][gdp->Qcount[msb][dia]++] = (unsigned char)dpos;
676 
677 	if (gdp->global_erasures == NULL)
678 		return;
679 
680 	/* set the erasure at the given position. */
681 	gdp->global_erasures[position+msb] = 1;
682 }
683 
684 
685 /*
686  * delete the erasure at the given position.
687  *
688  * Input parameters:
689  *  position: even offset in the sector after the sync header.
690  *  msb:		1 for the most significant byte.
691  *				0 for the least significant byte.
692  *		gdp is a pointer to auxiliary book keeping data.
693  */
694 
695 static void
kill_erasure(position,msb,gdp)696 kill_erasure(position, msb, gdp)
697 	unsigned position;
698 	unsigned msb;
699 	gdatp gdp;
700 {
701 	unsigned i, j;
702 	unsigned dia;
703 	unsigned pos;
704 	unsigned col;
705 	unsigned char *p, *q;
706 
707 	if (gdp->global_erasures == NULL)
708 		return;
709 
710 #if	DEBUG >= 7
711 	if (global_erasures[position + msb] == 0) {
712 		fprintf(stderr, "<WRONG(c%d,d%d)\t",
713 		position < 2*L12_P_LENGTH*L12_Q_LENGTH ? COL(position/2) : -1, DIA(position/2));
714 	}
715 #endif
716 
717 #if	DEBUG >= 0
718 	/* is the erasure really defined once? */
719 	if (position < 2*L12_P_LENGTH*L12_Q_LENGTH) {
720 		col = COL(position/2);
721 		pos = POSP(position/2);
722 		p =  gdp->Perapos[msb][col];
723 		for (dia = 0, j = gdp->Pcount[msb][col]; j > 0; j--, p++)
724 			if (*p == pos + L12_P_SKIPPED) {
725 				dia++;
726 			}
727 		if (dia > 1)
728 			fprintf(stderr, "\nkill:P position %d %d times, count=%d!\n", position+12+msb, dia, gdp->Pcount[msb][col]);
729 	}
730 	dia = DIA(position/2);
731 	pos = POSQ(position/2);
732 	q =  gdp->Qerapos[msb][dia];
733 	for (col = 0, i = gdp->Qcount[msb][dia]; i > 0; i--, q++)
734 		if (*q == pos + L12_Q_SKIPPED) {
735 			col++;
736 		}
737 	if (col > 1)
738 		fprintf(stderr, "\nkill:Q position %d %d times!\n", position+12+msb, col);
739 #endif
740 
741 	gdp->global_erasures[position+msb] ^= 1;
742 
743 
744 	if (position < 2*L12_P_LENGTH*L12_Q_LENGTH) {
745 		col = COL(position/2);
746 		pos = POSP(position/2) + L12_P_SKIPPED;
747 		p =  gdp->Perapos[msb][col];
748 
749 		for (j = gdp->Pcount[msb][col]; j > 0 && *p != pos; j--, p++)
750 			;
751 
752 		if (j > 1)
753 			memmove(p, p+1, j-1);
754 		else if (j == 1)
755 			*p = 0;
756 
757 		if (gdp->Pcount[msb][col] > 0)
758 			gdp->Pcount[msb][col]--;
759 	}
760 	dia = DIA(position/2);
761 	q =  gdp->Qerapos[msb][dia];
762 	pos = POSQ(position/2) + L12_Q_SKIPPED;
763 
764 	for (i = gdp->Qcount[msb][dia]; i > 0 && *q != pos; i--, q++)
765 		;
766 
767 	if (i > 1)
768 		memmove(q, q+1, i-1);
769 	else if (i == 1)
770 		*q = 0;
771 
772 	if (gdp->Qcount[msb][dia] > 0)
773 		gdp->Qcount[msb][dia]--;
774 
775 #if	DEBUG >= 0
776 	/* has the erasure really been deleted? */
777 	pos = POSP(position/2);
778 	p =  gdp->Perapos[msb][col];
779 	for (j = gdp->Pcount[msb][col]; j > 0; j--, p++)
780 		if (*p == pos + L12_P_SKIPPED) {
781 			fprintf(stderr, "\nkill_era: error in p (pos=%d,dia=%d,col=%d)!\n", position+12+msb, dia, col);
782 		}
783 	pos = POSQ(position/2);
784 	q =  gdp->Qerapos[msb][dia];
785 	for (i = gdp->Qcount[msb][dia]; i > 0; i--, q++)
786 		if (*q == pos + L12_Q_SKIPPED) {
787 			fprintf(stderr, "\nkill_era: error in q (pos=%d,dia=%d,col=%d)!\n", position+12+msb, dia, col);
788 		}
789 #endif
790 }
791 
792 
793 /*
794  * translate the erasures in p and q coordinates.
795  *
796  * Input parameters:
797  *  have_erasures:	the number of erasures
798  *					set in the erasures array.
799  *	inout:			the content of the data sector as a byte array
800  *					at offset 12.
801  *	gdp:			is a pointer to auxiliary book keeping data.
802  *
803  * Return
804  */
805 
806 static unsigned	unify_erasures __PR((int have_erasures, unsigned char *inout, gdatp gdp));
807 static unsigned
unify_erasures(have_erasures,inout,gdp)808 unify_erasures(have_erasures, inout, gdp)
809 	int	have_erasures;
810 	unsigned char	*inout;
811 	gdatp gdp;
812 {
813 	unsigned	i;
814 	unsigned	msb;
815 	unsigned	retval = 0;
816 
817 	if (have_erasures != 0)
818 		return (0);
819 
820 	/*
821 	 * We assume the q layer has just been done. This possibly changed
822 	 * something, so we update the status for the p layer.
823 	 */
824 	for (i = 0; i < L2_P/4; i++) {
825 		unsigned char	synd[L2_P];
826 
827 		calc_L2_P_syndrome(inout, i, synd);
828 		if (synd[0] == 0 && synd[L2_P/2] == 0) {
829 			gdp->Pfailed[0][i] = 0;
830 		}
831 
832 		if (synd[1] == 0 && synd[L2_P/2+1] == 0) {
833 			gdp->Pfailed[1][i] = 0;
834 		}
835 	}
836 
837 	/*
838 	 * loop for both byte layers (most and least significant)
839 	 */
840 	for (msb = 0; msb < 2; msb++) {
841 		int	pcounter = 0;
842 		int	qcounter = 0;
843 		int	j;
844 
845 		/*
846 		 * count columns in P with failures
847 		 */
848 		for (j = 0; j < L2_P/4; j++) {
849 			if (gdp->Pfailed[msb][j] != 0) {
850 				pcounter++;
851 #if	DEBUG	>= 0
852 	fprintf(stderr, " p%2d ", j);
853 #endif
854 			}
855 		}
856 
857 		/*
858 		 * count diagonals in Q with failures
859 		 */
860 		for (j = 0; j < L2_Q/4; j++) {
861 			if (gdp->Qfailed[msb][j] != 0) {
862 				qcounter++;
863 #if	DEBUG	>= 0
864 	fprintf(stderr, " q%2d ", j);
865 #endif
866 			}
867 		}
868 #if	DEBUG	>= 0
869 	fprintf(stderr, " pc%d qc%d\n", pcounter, qcounter);
870 #endif
871 
872 		/*
873 		 * If Q is clean, but P is not, this is
874 		 * considered as decoding failures introduced from Q
875 		 */
876 		if (pcounter > 0 && qcounter == 0) {
877 			/* decoding failure */
878 #if	DEBUG	>= 0
879 			fprintf(stderr, "\n");
880 #endif
881 			return (1);
882 		}
883 
884 		/*
885 		 * if P is clean (and the CRC too), we consider all
886 		 * remaining errors located in the Q parity part.
887 		 */
888 		if (pcounter == 0) {
889 			for (i = 0; i < L2_Q/4; i++) {
890 				if (gdp->Qfailed[msb][i] != 0) {
891 					if (gdp->global_erasures != NULL &&
892 					    (gdp->global_erasures[SECBQL(i, L2_P/4)+msb] == 0 ||
893 					    gdp->global_erasures[SECBQL(i, L2_P/4 + 1)+msb] == 0)) {
894 						set_erasure(SECBQL(i, L2_P/4), msb, gdp);
895 						set_erasure(SECBQL(i, L2_P/4 + 1), msb, gdp);
896 						retval = 1;
897 					}
898 				}
899 			}
900 #if	0
901 		} else if (pcounter  <= 2) {
902 			/* P has one or two errors */
903 			for (i = 0; i < L2_Q/4; i++) {
904 				if (gdp->Qfailed[msb][i] != 0) {
905 					for (j = 0; j < L2_P/4; j++) {
906 						if (gdp->Pfailed[msb][j] != 0) {
907 							set_erasure(SECBQL(i, j)+msb, gdp);
908 							retval = 1;
909 #if	DEBUG	>= 0
910 	fprintf(stderr, " 2P%d\n", j);
911 #endif
912 						}
913 					}
914 				}
915 			}
916 #endif
917 		}
918 
919 		/*
920 		 * If max 2 diagonals have errors, we assume
921 		 * the errors are located in the common part with P.
922 		 */
923 		if (qcounter <= 2) {
924 			for (i = 0; i < L2_P/4; i++) {
925 				if (gdp->Pfailed[msb][i] != 0) {
926 					for (j = 0; j < L2_Q/4; j++) {
927 						if (gdp->Qfailed[msb][j] != 0) {
928 							set_erasure(SECBQL(j, i), msb, gdp);
929 							retval = 1;
930 #if	DEBUG	>= 0
931 	fprintf(stderr, " 2Q%d\n", j);
932 #endif
933 						}
934 					}
935 				}
936 			}
937 		}
938 		if (0) {
939 		    for (i = 0; i < L2_Q/4; i++) {
940 				if (gdp->Qfailed[msb][i] != 0) {
941 					/* look for P status */
942 					for (j = 0; j < L2_P/4; j++) {
943 						if (pcounter == 0) {
944 							set_erasure(SECBQL(i, L2_P/4), msb, gdp);
945 							set_erasure(SECBQL(i, L2_P/4 + 1), msb, gdp);
946 							break;
947 #if 0
948 						} else if (gdp->Pcount[msb][j] > 0 &&
949 							    gdp->Pcount[msb][j] <= 2) {
950 							int	k;
951 							for (k = 0; k < gdp->Pcount[msb][j]; k++) {
952 								set_erasure(SECBQL(i,
953 										gdp->Perapos[msb][j][k] - P_SKIPPED)+msb,
954 										gdp);
955 #if	DEBUG	>= 0
956 		fprintf(stderr, " P%d,%d ", j, k);
957 #endif
958 							}
959 #endif
960 						}
961 					}
962 				}
963 		    }
964 		}
965 	}
966 #if	DEBUG	>= 0
967 	fprintf(stderr, " ->%d\n", retval);
968 #endif
969 	return (retval);
970 }
971 
972 /*
973  * Initialize our separated p and q erasure arrays.
974  *
975  * Input parameters:
976  *  have_erasures:	the number of erasures
977  *					set in the erasures array.
978  *  erasures:		the byte array for the erasures. Each byte
979  *					corresponds to a data byte in the L2 sector.
980  *	gdp:			is a pointer to auxiliary book keeping data.
981  */
982 static void
983 init_erasures __PR((int have_erasures, unsigned char erasures[(L2_RAW + L2_Q + L2_P)], gdatp gdp));
984 
985 static void
init_erasures(have_erasures,erasures,gdp)986 init_erasures(have_erasures, erasures, gdp)
987 	int	have_erasures;
988 	unsigned char	erasures[(L2_RAW + L2_Q + L2_P)];
989 	gdatp gdp;
990 {
991 	int	i;
992 
993 	memset(gdp->Perapos, 0, sizeof (gdp->Perapos));
994 	memset(gdp->Qerapos, 0, sizeof (gdp->Qerapos));
995 	memset(gdp->Pcount, 0, sizeof (gdp->Pcount));
996 	memset(gdp->Qcount, 0, sizeof (gdp->Qcount));
997 
998 	if (erasures == NULL) {
999 		have_erasures = 0;
1000 		gdp->global_erasures = NULL;
1001 	} else {
1002 		gdp->global_erasures = erasures+12;
1003 	}
1004 #if DEBUG > 2
1005 	if (gdp->global_erasures != NULL) {
1006 #else
1007 	if (have_erasures != 0) {
1008 #endif
1009 		memset(erasures, 0, 12);
1010 
1011 		/*
1012 		 * We can only use erasures at offset 12 and above.
1013 		 *  Further we need the number/positions of erasures separated
1014 		 *  for LSB and MSB. So count them.
1015 		 */
1016 
1017 
1018 		for (i = 0; i < 2*L12_P_LENGTH*L12_Q_LENGTH; i += 2) {
1019 			if (gdp->global_erasures[i  ] != 0) {
1020 				gdp->Perapos[0][COL(i/2)]
1021 					[gdp->Pcount[0][COL(i/2)]]
1022 						= (unsigned char)(POSP(i/2) + L12_P_SKIPPED);
1023 #if DEBUG > 2
1024 	fprintf(stderr, "off %d -> col %d pos %d   dia %d pos %d\n", i+12, COL(i/2), POSP(i/2), DIA(i/2), POSQ(i/2));
1025 	if (have_erasures != 0)
1026 #endif
1027 				gdp->Pcount[0][COL(i/2)]++;
1028 			}
1029 			if (gdp->global_erasures[i+1] != 0) {
1030 				gdp->Perapos[1][COL(i/2)]
1031 					[gdp->Pcount[1][COL(i/2)]]
1032 						= (unsigned char)(POSP(i/2) + L12_P_SKIPPED);
1033 #if DEBUG > 2
1034 	fprintf(stderr, "off %d -> col %d pos %d   dia %d pos %d\n", i+12+1, COL(i/2), POSP(i/2), DIA(i/2), POSQ(i/2));
1035 	if (have_erasures != 0)
1036 #endif
1037 				gdp->Pcount[1][COL(i/2)]++;
1038 			}
1039 		}
1040 		for (i = 0; i < L12_Q_LENGTH; i++) {
1041 			int j;
1042 			for (j = 0; j < L12_P_LENGTH; j++) {
1043 				int ind = SECBQLLO(i, j);
1044 
1045 				if (gdp->global_erasures[ind  ] != 0) {
1046 					gdp->Qerapos[0][i][gdp->Qcount[0][i]]
1047 							= (unsigned char)(j + L12_Q_SKIPPED);
1048 #if DEBUG > 2
1049 	fprintf(stderr, "off %d -> dia %d pos %d   col %d pos %d\n", ind+12, i, j, COL(ind/2), POSP(ind/2));
1050 	if (have_erasures != 0)
1051 #endif
1052 					gdp->Qcount[0][i]++;
1053 				}
1054 				if (gdp->global_erasures[ind+1] != 0) {
1055 					gdp->Qerapos[1][i][gdp->Qcount[1][i]]
1056 							= (unsigned char)(j + L12_Q_SKIPPED);
1057 #if DEBUG > 2
1058 	fprintf(stderr, "off %d -> dia %d pos %d   col %d pos %d\n", ind+12+1, i, j, COL(ind/2), POSP(ind/2));
1059 	if (have_erasures != 0)
1060 #endif
1061 					gdp->Qcount[1][i]++;
1062 				}
1063 			}
1064 		}
1065 		for (i = 0; i < L12_Q_LENGTH; i++) {
1066 			int j;
1067 			for (j = L12_P_LENGTH; j < L12_P_LENGTH + 2; j++) {
1068 				int ind = SECBQLHI(i, j);
1069 
1070 				if (gdp->global_erasures[ind  ] != 0) {
1071 					gdp->Qerapos[0][i][gdp->Qcount[0][i]]
1072 							= (unsigned char)(j + L12_Q_SKIPPED);
1073 #if DEBUG > 2
1074 	fprintf(stderr, "off %d -> dia %d pos %d   col -- pos --\n", ind+12, i, j);
1075 	if (have_erasures != 0)
1076 #endif
1077 					gdp->Qcount[0][i]++;
1078 				}
1079 				if (gdp->global_erasures[ind+1] != 0) {
1080 					gdp->Qerapos[1][i][gdp->Qcount[1][i]]
1081 							= (unsigned char)(j + L12_Q_SKIPPED);
1082 #if DEBUG > 2
1083 	fprintf(stderr, "off %d -> dia %d pos %d   col -- pos --\n", ind+12+1, i, j);
1084 	if (have_erasures != 0)
1085 #endif
1086 					gdp->Qcount[1][i]++;
1087 				}
1088 			}
1089 		}
1090 	}
1091 }
1092 
1093 /*
1094  *	Check the P layer for inconsistencies at a given position.
1095  *
1096  * Input parameters:
1097  *  syndrome:   a byte array with the precalculated syndrome.
1098  *  msb:        true, for the most significant bytes
1099  *              false for the least significant bytes
1100  *  position:   the offset in the sector (after byte 12)
1101  *	gdp:		is a pointer to auxiliary book keeping data.
1102  */
1103 
1104 static
1105 void check_P_for_decoding_failures __PR((unsigned char syndrome[],
1106 	unsigned msb, unsigned position, gdatp gdp));
1107 
1108 static
1109 void
check_P_for_decoding_failures(syndrome,msb,position,gdp)1110 check_P_for_decoding_failures(syndrome, msb, position, gdp)
1111 	unsigned char syndrome[];
1112 	unsigned	msb;
1113 	unsigned	position;
1114 	gdatp gdp;
1115 {
1116 	unsigned	pos = msb+2*DIALO(position);
1117 	/* check Q syndrome at that position */
1118 	if (syndrome[pos] == 0 && syndrome[pos+L2_Q/2] == 0) {
1119 #if	DEBUG > 1
1120 fprintf(stderr, " inval Q d %d", DIALO(position));
1121 #endif
1122 		syndrome[pos] = 1;
1123 		gdp->Pfailed[msb][COL(position)] = 1;
1124 		/* mark_erasure too */
1125 		/*set_erasure(2*position+msb);*/
1126 	}
1127 }
1128 
1129 /*
1130  *	Check the Q layer for inconsistencies at a given position.
1131  *
1132  * Input parameters:
1133  *  syndrome:   a byte array with the precalculated syndrome.
1134  *  msb:        true, for the most significant bytes
1135  *              false for the least significant bytes
1136  *  position:   the offset in the sector (after byte 12)
1137  *	gdp:		is a pointer to auxiliary book keeping data.
1138  */
1139 
1140 static
1141 void check_Q_for_decoding_failures __PR((unsigned char syndrome[],
1142 	unsigned msb, unsigned position, gdatp gdp));
1143 
1144 static
1145 void
check_Q_for_decoding_failures(syndrome,msb,position,gdp)1146 check_Q_for_decoding_failures(syndrome, msb, position, gdp)
1147 	unsigned char syndrome[];
1148 	unsigned	msb;
1149 	unsigned	position;
1150 	gdatp gdp;
1151 {
1152 	unsigned	pos;
1153 
1154 	if (position >= L12_P_LENGTH*L12_Q_LENGTH)
1155 		return;
1156 
1157 	pos = msb+2*COL(position);
1158 	/* check P syndrome at that position */
1159 	if (syndrome[pos] == 0 && syndrome[pos+L2_P/2] == 0) {
1160 #if	DEBUG > 1
1161 fprintf(stderr, " inval P c %d", COL(position));
1162 #endif
1163 		syndrome[pos] = 1;
1164 		gdp->Qfailed[msb][DIALO(position)] = 1;
1165 		/* mark_erasure too */
1166 		/*if (loops) set_erasure(2*position+msb);*/
1167 	}
1168 }
1169 
1170 
1171 
1172 /*
1173  * implements Berlekamp-Massey-Decoders.
1174  */
1175 
1176 /* get the a'th syndrome byte. We translate to the sector structure */
1177 #define	SYND(a)		syndrome[(a)*L12_P_LENGTH*2]
1178 
1179 /*
1180  * Correct one column in the p parity layer.
1181  *
1182  * Input/Output parameters:
1183  *  inout:      the byte array holding the sector after the sync header.
1184  *              A correction will change the array.
1185  *
1186  * Input parameters:
1187  *  msb:        true, for the most significant bytes
1188  *              false for the least significant bytes
1189  *  column:     the column number (0 - 42)
1190  *  syndrome:   a byte array with the precalculated syndrome.
1191  *  erasures:   the number of given error positions for this column.
1192  *  Perasures:  the byte array holding the error positions
1193  *              for this column.
1194  *  low_taboo:  the lower limit of a range left to be unchanged.
1195  *  high_taboo: the upper limit of a range left to be unchanged.
1196  *  loops:		>= 0, the loop count of the iteration
1197  *	gdp:		is a pointer to auxiliary book keeping data.
1198  */
1199 static int
1200 correct_P __PR((unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P],
1201 	unsigned msb,
1202 	unsigned column, unsigned char syndrome[L2_P/2+2],
1203 	unsigned erasures, unsigned char Perasures[L12_Q_LENGTH],
1204 	unsigned low_taboo, unsigned high_taboo, int loops, gdatp gdp));
1205 
1206 static int
correct_P(inout,msb,column,syndrome,erasures,Perasures,low_taboo,high_taboo,loops,gdp)1207 correct_P(inout, msb, column, syndrome, erasures, Perasures, low_taboo, high_taboo, loops, gdp)
1208 	unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P];
1209 	unsigned msb;
1210 	unsigned column;
1211 	unsigned char syndrome[L2_P/2+2];
1212 	unsigned erasures;
1213 	unsigned char Perasures[L12_Q_LENGTH];
1214 	unsigned low_taboo;
1215 	unsigned high_taboo;
1216 	int loops;
1217 	gdatp gdp;
1218 {
1219 	unsigned	i;
1220 	unsigned	j;
1221 	unsigned	l;
1222 	unsigned	k;
1223 	unsigned	roots_found;
1224 	unsigned char	err_locations[2*L12_P_ERRORS+1];
1225 	unsigned char	err_values[2*L12_P_ERRORS+1];
1226 	unsigned char	tmp_loc[2*L12_P_ERRORS+1];
1227 	unsigned char	roots[2*L12_P_ERRORS];
1228 	unsigned char	discrepancy;
1229 
1230 	INIT_BMD
1231 
1232 #if	DEBUG > 0
1233 fprintf(stderr, "tab(%u-%u), era(%u)", low_taboo, high_taboo, erasures);
1234 #endif
1235 
1236 	/*
1237 	 * initialize error location polynomial with roots from given
1238 	 * erasure locations.
1239 	 */
1240 	if (erasures > 0) {
1241 
1242 		INIT_ERASURES(Perasures, L12_P_ERRORS, L12_MODUL,
1243 						rs_l12_log, rs_l12_alog)
1244 
1245 		if (DEBUG > 2) { DEBUG_ERASURE_POLY(rs_l12_log, rs_l12_alog,
1246 				L12_MODUL, L12_P_ERRORS, L12_P_SKIPPED, 0) }
1247 	}
1248 
1249 	/*
1250 	 * calculate the final error location polynomial.
1251 	 */
1252 	for (j = l = erasures, k = 1; j < 2*L12_P_ERRORS; j++, k++) {
1253 
1254 		/* calculate the 'discrepancy' */
1255 		CALC_DISCREPANCY(rs_l12_log, rs_l12_alog)
1256 
1257 		/* test discrepancy for zero */
1258 		if (discrepancy != 0) {
1259 			BUILD_SHIFT_REGISTER(rs_l12_log, rs_l12_alog,
1260 					L12_MODUL, L12_P_ERRORS)
1261 		}
1262 #if	DEBUG > 4
1263 		fprintf(stderr, " Pdisc=%d, ", discrepancy);
1264 		fprintf(stderr, "j=%d, ", j);
1265 		fprintf(stderr, "k=%d, l(errors)=%d, e0=%d, e1=%d, B0=%d, B1=%d\n",
1266 				k, l, err_locations[0], err_locations[1], tmp_loc[0], tmp_loc[1]);
1267 #endif
1268 	}
1269 
1270 #if	DEBUG > 0
1271 	fprintf(stderr, ",l(%d)   ", l);
1272 	if (gdp->global_erasures != NULL) {
1273 		int b;
1274 		for (b = 0; b < L12_Q_LENGTH; b++) {
1275 			if (gdp->global_erasures[SECBPL(column, b)+ msb] == 1) {
1276 				fprintf(stderr, "%4d, ", 12+SECBPL(column, b) + msb);
1277 			}
1278 		}
1279 		for (b = 0; b < gdp->Pcount[msb][column]; b++) {
1280 			if (gdp->global_erasures[SECBPL(column, gdp->Perapos[msb][column][b] - L12_P_SKIPPED) + msb] == 0) {
1281 				fprintf(stderr, " :%4d: ", 12+SECBPL(column, gdp->Perapos[msb][column][b] - L12_P_SKIPPED) + msb);
1282 			}
1283 		}
1284 	}
1285 #endif
1286 	if (l > L12_P_ERRORS+erasures/2) {
1287 #if	DEBUG > 0
1288 		fprintf(stderr, "\tl > 2+era/2  ");
1289 #endif
1290 		return (1);
1291 	}
1292 
1293 	/* find roots of err_locations */
1294 	FIND_ROOTS(rs_l12_log, rs_l12_alog, L12_MODUL, L12_P_ERRORS,
1295 		L12_P_SKIPPED, (FIND_ROOTS_TABOO(SECWP, column, L12_P_SKIPPED)))
1296 
1297 	/* too many errors if the number of roots is not what we expected */
1298 	if (roots_found != l) {
1299 #if	DEBUG > 0
1300 		fprintf(stderr, "roots(%d)!=l(%d)\t", roots_found, l);
1301 #endif
1302 		return (1);
1303 	}
1304 
1305 	/*
1306 	 * l holds the number of errors
1307 	 *
1308 	 * now calculate the error valuator
1309 	 */
1310 	CALC_ERROR_VALUATOR(rs_l12_log, rs_l12_alog)
1311 
1312 	/* use roots of err_locations */
1313 	APPLY_FORNEY_ALGORITHM(rs_l12_log, rs_l12_alog, L12_MODUL,
1314 			L12_P_SKIPPED, DO_L2_P_CORRECTION)
1315 
1316 	return (0);
1317 }
1318 #undef	SYND
1319 
1320 
1321 
1322 
1323 /*
1324  * Correct one diagonal in the q parity layer.
1325  *
1326  * Input/Output parameters:
1327  *  inout:      the byte array holding the sector after the sync header.
1328  *              A correction will change the array.
1329  *
1330  * Input parameters:
1331  *  msb:        true, for the most significant bytes
1332  *              false for the least significant bytes
1333  *  diagonal:   the diagonal number (0 - 25)
1334  *  syndrome:   a byte array with the precalculated syndrome.
1335  *  erasures:   the number of given error positions for this column.
1336  *  Qerasures:  the byte array holding the error positions
1337  *              for this column.
1338  *  low_taboo:  the lower limit of a range left to be unchanged.
1339  *  high_taboo: the upper limit of a range left to be unchanged.
1340  *  q_changed_p: pointer to int; the integer is set true, if a
1341  *				correction affects the part covered by the
1342  *				p parity layer.
1343  *  loops:		>= 0, the loop count of the iteration
1344  *	gdp:		is a pointer to auxiliary book keeping data.
1345  */
1346 
1347 #define	SYND(a)		syndrome[(a)*L12_Q_LENGTH*2]
1348 static int
1349 correct_Q __PR((unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q],
1350 	unsigned msb,
1351 	unsigned diagonal, unsigned char syndrome[L2_Q/2+2],
1352 	unsigned erasures, unsigned char Qerasures[L12_P_LENGTH],
1353 	unsigned low_taboo, unsigned high_taboo, unsigned *q_changed_p, gdatp gdp));
1354 
1355 static int
correct_Q(inout,msb,diagonal,syndrome,erasures,Qerasures,low_taboo,high_taboo,q_changed_p,gdp)1356 correct_Q(inout, msb, diagonal, syndrome, erasures, Qerasures, low_taboo, high_taboo,
1357 	q_changed_p, gdp)
1358 	unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q];
1359 	unsigned msb;
1360 	unsigned diagonal;
1361 	unsigned char syndrome[L2_Q/2+2];
1362 	unsigned erasures;
1363 	unsigned char Qerasures[L12_P_LENGTH];
1364 	unsigned low_taboo;
1365 	unsigned high_taboo;
1366 	unsigned *q_changed_p;
1367 	gdatp gdp;
1368 {
1369 	unsigned	i;
1370 	unsigned	j;
1371 	unsigned	l;
1372 	unsigned	k;
1373 	unsigned	roots_found;
1374 	unsigned char	err_locations[2*L12_Q_ERRORS+1];
1375 	unsigned char	err_values[2*L12_Q_ERRORS+1];
1376 	unsigned char	tmp_loc[2*L12_Q_ERRORS+1];
1377 	unsigned char	roots[2*L12_Q_ERRORS];
1378 	unsigned char	discrepancy;
1379 
1380 	INIT_BMD
1381 
1382 #if	DEBUG > 0
1383 fprintf(stderr, "tab(%u-%u), era(%u)", low_taboo, high_taboo, erasures);
1384 #endif
1385 
1386 	/*
1387 	 * initialize error location polynomial with roots from given
1388 	 * erasure locations.
1389 	 */
1390 	if (erasures > 0) {
1391 
1392 		INIT_ERASURES(Qerasures, L12_Q_ERRORS, L12_MODUL,
1393 						rs_l12_log, rs_l12_alog)
1394 
1395 		if (DEBUG > 2) { DEBUG_ERASURE_POLY(rs_l12_log, rs_l12_alog,
1396 				L12_MODUL, L12_Q_ERRORS, L12_Q_SKIPPED,
1397 				(FIND_ROOTS_TABOO(SECWQ, diagonal, L12_Q_SKIPPED))) }
1398 	}
1399 
1400 	/*
1401 	 * calculate the final error location polynomial.
1402 	 */
1403 	for (j = l = erasures, k = 1; j < 2*L12_Q_ERRORS; j++, k++) {
1404 
1405 		/* calculate the 'discrepancy' */
1406 		CALC_DISCREPANCY(rs_l12_log, rs_l12_alog)
1407 
1408 		/* test discrepancy for zero */
1409 		if (discrepancy != 0) {
1410 			BUILD_SHIFT_REGISTER(rs_l12_log, rs_l12_alog,
1411 					L12_MODUL, L12_Q_ERRORS)
1412 		}
1413 #if	DEBUG > 4
1414 		fprintf(stderr, " Qdisc=%d, ", discrepancy);
1415 		fprintf(stderr, "j=%d, ", j);
1416 		fprintf(stderr, "k=%d, l(errors)=%d, e0=%d, e1=%d, B0=%d, B1=%d\n",
1417 				k, l, err_locations[0], err_locations[1], tmp_loc[0], tmp_loc[1]);
1418 #endif
1419 	}
1420 
1421 #if	DEBUG > 0
1422 	fprintf(stderr, ",l(%d)   ", l);
1423 	if (gdp->global_erasures != NULL) {
1424 		int b;
1425 		for (b = 0; b < L12_P_LENGTH+2; b++) {
1426 			if (gdp->global_erasures[SECBQL(diagonal, b)+ msb] == 1) {
1427 				fprintf(stderr, "%4d, ", 12+SECBQL(diagonal, b) + msb);
1428 			}
1429 		}
1430 		for (b = 0; b < gdp->Qcount[msb][diagonal]; b++) {
1431 			if (gdp->global_erasures[SECBQL(diagonal, gdp->Qerapos[msb][diagonal][b] - L12_Q_SKIPPED) + msb] == 0) {
1432 				fprintf(stderr, " :%4d: ",
1433 						12+SECBQL(diagonal, gdp->Qerapos[msb][diagonal][b] - L12_Q_SKIPPED) + msb);
1434 			}
1435 		}
1436 	}
1437 #endif
1438 	if (l > L12_Q_ERRORS+erasures/2) {
1439 #if	DEBUG > 0
1440 		fprintf(stderr, "l > 2+era/2  ");
1441 #endif
1442 		return (1);
1443 	}
1444 
1445 	/* find roots of err_locations */
1446 	FIND_ROOTS(rs_l12_log, rs_l12_alog, L12_MODUL, L12_Q_ERRORS,
1447 		L12_Q_SKIPPED, (FIND_ROOTS_TABOO(SECWQ, diagonal, L12_Q_SKIPPED)))
1448 
1449 	/* too many errors if the number of roots are not what we expected */
1450 	if (roots_found != l) {
1451 #if	DEBUG > 0
1452 		fprintf(stderr, "roots(%d)!=l(%d)\t", roots_found, l);
1453 #endif
1454 		return (1);
1455 	}
1456 
1457 	/*
1458 	 * l holds the number of errors
1459 	 *
1460 	 * now calculate the error valuator
1461 	 */
1462 	CALC_ERROR_VALUATOR(rs_l12_log, rs_l12_alog)
1463 
1464 	/* use roots of err_locations */
1465 	APPLY_FORNEY_ALGORITHM(rs_l12_log, rs_l12_alog, L12_MODUL,
1466 			L12_Q_SKIPPED, DO_L2_Q_CORRECTION)
1467 
1468 	return (0);
1469 }
1470 #undef	SYND
1471 
1472 
1473 /*
1474  * p_correct_all: do the correction for all columns
1475  * in the p parity layer.
1476  *
1477  * Input/output parameters:
1478  *  inout_pq:	the byte array with the sector data
1479  *				after the sync header to be corrected.
1480  *  p_changed:	pointer to int; set true, if a
1481  *				correction (change) has been done.
1482  *
1483  * Input parameters:
1484  *  low_taboo:  the lower limit of a range left to be unchanged.
1485  *  high_taboo: the upper limit of a range left to be unchanged.
1486  *  loops:		>= 0, the loop count of the iteration
1487  *	gdp:		is a pointer to auxiliary book keeping data.
1488  *
1489  */
1490 
1491 static int
1492 p_correct_all __PR((unsigned char inout_pq[], unsigned *p_changed,
1493 	unsigned low_taboo, unsigned high_taboo, int loops, gdatp gdp));
1494 
1495 static int
p_correct_all(inout_pq,p_changed,low_taboo,high_taboo,loops,gdp)1496 p_correct_all(inout_pq, p_changed, low_taboo, high_taboo, loops, gdp)
1497 	unsigned char	inout_pq[];
1498 	unsigned	*p_changed;
1499 	unsigned	low_taboo;
1500 	unsigned	high_taboo;
1501 	int	loops;
1502 	gdatp gdp;
1503 {
1504 	int	have_error[2];
1505 	unsigned	i;
1506 	unsigned	lowcol = COL(low_taboo);
1507 	unsigned	higcol = COL(high_taboo);
1508 	unsigned	lowpos = POSP(low_taboo);
1509 	unsigned	higpos = POSP(high_taboo);
1510 
1511 	have_error[0] = have_error[1] = 0;
1512 	for (*p_changed = i = 0; i < L2_P/4; i++) {
1513 
1514 		gdp->Pfailed[0][i] = gdp->Pfailed[1][i] = 0;
1515 
1516 		if (loops > 0 &&
1517 		    gdp->Psyndromes[2*i] == 0 &&
1518 		    gdp->Psyndromes[2*i+1] == 0 &&
1519 		    gdp->Psyndromes[2*i+L2_P/2] == 0 &&
1520 		    gdp->Psyndromes[2*i+L2_P/2+1] == 0) continue;
1521 
1522 		if (!calc_L2_P_syndrome(inout_pq, i, &gdp->Psyndromes[2*i])) {
1523 			unsigned	msb;
1524 			/*
1525 			 * error(s) in column i in layer of p (LSB and MSB)
1526 			 */
1527 			for (msb = 0; msb < 2; msb++) {
1528 				int	retval;
1529 
1530 				if (gdp->Psyndromes[2*i+msb] != 0 ||
1531 				    gdp->Psyndromes[2*i+msb+L2_P/2] != 0) {
1532 					if (TELLME) fprintf(stderr, "%2d p %s c %2d: ", loops, msb ? "MSB" : "LSB", i);
1533 if (0) fprintf(stderr, "\nP taboo:%u-%u, c/p:%u/%u - %u/%u\n",
1534 low_taboo, high_taboo, lowcol, lowpos, higcol, higpos);
1535 					retval = correct_P(inout_pq+msb, msb, i,
1536 							&gdp->Psyndromes[2*i+msb], gdp->Pcount[msb][i],
1537 							gdp->Perapos[msb][i],
1538 							i >= lowcol ? lowpos : lowpos+1,
1539 							i <= higcol || higpos == 0 ? higpos : higpos-1,
1540 							loops, gdp);
1541 					*p_changed |= !retval;
1542 					have_error[msb] |= retval;
1543 					if (retval == 0) {
1544 #if DEBUG >= 0
1545 						/* recheck */
1546 						calc_L2_P_syndrome(inout_pq, i, &gdp->Psyndromes[2*i]);
1547 						if (gdp->Psyndromes[2*i+msb] != 0 ||
1548 							gdp->Psyndromes[2*i+msb+L2_P/2] != 0) {
1549 fprintf(stderr, "\n P %s internal error in %s, %d\n", msb ? "MSB" : "LSB", __FILE__, __LINE__);
1550 						}
1551 #endif
1552 						gdp->Psyndromes[2*i+msb] = 0;
1553 						gdp->Psyndromes[2*i+msb+L2_P/2] = 0;
1554 					} else {
1555 						gdp->Pfailed[msb][i] = 1;
1556 					}
1557 					if (TELLME) fputs("\n", stderr);
1558 				} /* error in byte layer */
1559 #if	DEBUG >= 0
1560 				else {
1561 					/*
1562 					 * if this column is clean,
1563 					 * there should be no erasures left
1564 					 */
1565 					if (gdp->Pcount[msb][i] != 0) {
1566 fprintf(stderr, "p: %d stale erasures in column %d, MSB=%d\n", gdp->Pcount[msb][i], i, msb);
1567 					}
1568 				}
1569 #endif
1570 			} /* for LSB and MSB */
1571 		} /* error in column */
1572 	} /* for all columns */
1573 	return (have_error[0] == 0 && have_error[1] == 0);
1574 }
1575 
1576 
1577 /*
1578  * q_correct_all: do the correction for all diagonals
1579  * in the q parity layer.
1580  *
1581  * Input/output parameters:
1582  *  inout_pq:	the byte array with the sector data
1583  *				after the sync header to be corrected.
1584  *  q_changed:	pointer to int; set true, if a
1585  *				correction (change) has been done.
1586  *  q_changed_p: pointer to int; set true, if a
1587  *				correction (change) has been done that
1588  *				affects the range of the p parity layer.
1589  *
1590  * Input parameters:
1591  *  low_taboo:  the lower limit of a range left to be unchanged.
1592  *  high_taboo: the upper limit of a range left to be unchanged.
1593  *  loops:		>= 0, the loop count of the iteration
1594  *	gdp:		is a pointer to auxiliary book keeping data.
1595  *
1596  */
1597 
1598 static int
1599 q_correct_all __PR((unsigned char inout_pq[], unsigned *q_changed, unsigned *q_changed_p,
1600 	unsigned low_taboo, unsigned high_taboo, int loops, gdatp gdp));
1601 
1602 static int
q_correct_all(inout_pq,q_changed,q_changed_p,low_taboo,high_taboo,loops,gdp)1603 q_correct_all(inout_pq, q_changed, q_changed_p, low_taboo, high_taboo, loops, gdp)
1604 	unsigned char	inout_pq[];
1605 	unsigned *q_changed;
1606 	unsigned *q_changed_p;
1607 	unsigned	low_taboo;
1608 	unsigned	high_taboo;
1609 	int	loops;
1610 	gdatp gdp;
1611 {
1612 	int	have_error[2];
1613 	unsigned	i;
1614 
1615 	have_error[0] = have_error[1] = 0;
1616 	for (*q_changed = *q_changed_p = i = 0; i < L2_Q/4; i++) {
1617 
1618 		gdp->Qfailed[0][i] = gdp->Qfailed[1][i] = 0;
1619 
1620 		if (loops > 0 &&
1621 		    gdp->Qsyndromes[2*i] == 0 &&
1622 		    gdp->Qsyndromes[2*i+1] == 0 &&
1623 		    gdp->Qsyndromes[2*i+L2_Q/2] == 0 &&
1624 		    gdp->Qsyndromes[2*i+L2_Q/2+1] == 0) continue;
1625 
1626 		if (!calc_L2_Q_syndrome(inout_pq, i, &gdp->Qsyndromes[2*i])) {
1627 			unsigned msb;
1628 			/*
1629 			 * error(s) in diagonal i in layer of q (LSB and MSB)
1630 			 */
1631 			for (msb = 0; msb < 2; msb++) {
1632 				if (gdp->Qsyndromes[2*i+msb] != 0 ||
1633 				    gdp->Qsyndromes[2*i+msb+L2_Q/2] != 0) {
1634 					int	retval;
1635 
1636 					if (TELLME) fprintf(stderr, "%2d q %s d %2d: ", loops, msb ? "MSB" : "LSB", i);
1637 
1638 					retval = correct_Q(inout_pq+msb, msb, i,
1639 							&gdp->Qsyndromes[2*i+msb], gdp->Qcount[msb][i],
1640 							gdp->Qerapos[msb][i],
1641 							low_taboo,
1642 							high_taboo,
1643 							q_changed_p,
1644 							gdp);
1645 					*q_changed |= !retval;
1646 					have_error[msb] |= retval;
1647 					if (retval == 0) {
1648 #if DEBUG >= 0
1649 						/* recheck */
1650 						calc_L2_Q_syndrome(inout_pq, i, &gdp->Qsyndromes[2*i]);
1651 						if (gdp->Qsyndromes[2*i+msb] != 0 ||
1652 						    gdp->Qsyndromes[2*i+msb+L2_Q/2] != 0) {
1653 fprintf(stderr, "\n Q %s internal error in %s, %d\n", msb ? "MSB" : "LSB", __FILE__, __LINE__);
1654 						}
1655 #endif
1656 						gdp->Qsyndromes[2*i+msb] = 0;
1657 						gdp->Qsyndromes[2*i+msb+L2_Q/2] = 0;
1658 					} else {
1659 						gdp->Qfailed[msb][i] = 1;
1660 					}
1661 					if (TELLME) fputs("\n", stderr);
1662 				} /* error in byte layer */
1663 #if	DEBUG >= 0
1664 				else {
1665 					/*
1666 					 * if this column is clean,
1667 					 * there should be no erasures left
1668 					 */
1669 					if (gdp->Qcount[msb][i] != 0) {
1670 fprintf(stderr, "q: %d stale erasures in diagonal %d, MSB=%d\n", gdp->Qcount[msb][i], i, msb);
1671 					}
1672 				}
1673 #endif
1674 			} /* for LSB and MSB */
1675 		} /* error in column */
1676 	} /* for all columns */
1677 	return (have_error[0] == 0 && have_error[1] == 0);
1678 }
1679 
1680 
1681 /*
1682  * do_decode_L2: main entry point for correction of one
1683  *		Layer 2 data sector.
1684  *
1685  * Input/output parameters:
1686  *  inout: the byte array holding the raw data sector.
1687  *			The corrections modify the array.
1688  *
1689  * Input parameters:
1690  *  sectortype: one of MODE_1, MODE_2_FORM_1
1691  *  have_erasures: the number of given error positions in the
1692  *				'erasures' byte array.
1693  *  erasures: a byte array with the size of a raw data sector. Each
1694  *			byte unequal 0 indicates a position of an error in the
1695  *			data sector. The number of nonzero bytes should equal
1696  *			the value of the 'have_erasures' parameter.
1697  *
1698  */
1699 
1700 int
1701 do_decode_L2 __PR((unsigned char inout[(L2_RAW + L2_Q + L2_P)],
1702 			int sectortype,
1703 			int have_erasures,
1704 			unsigned char erasures[(L2_RAW + L2_Q + L2_P)]));
1705 
1706 int
do_decode_L2(inout,sectortype,have_erasures,erasures)1707 do_decode_L2(inout, sectortype, have_erasures, erasures)
1708 	unsigned char	inout[(L2_RAW + L2_Q + L2_P)];
1709 	int		sectortype;
1710 	int		have_erasures;
1711 	unsigned char	erasures[(L2_RAW + L2_Q + L2_P)];
1712 {
1713 	int	crc_ok;
1714 	int	q_ok = -1;
1715 	int	p_ok = -1;
1716 	unsigned p_changed = 0;
1717 	unsigned q_changed = 0;
1718 	unsigned q_changed_p = 0;
1719 	int	loops;
1720 	unsigned 	low_taboo;
1721 	unsigned 	high_taboo;
1722 	gdat	gdata;
1723 	gdatp	gdp = &gdata;
1724 
1725 	if (sectortype != EDC_MODE_1 && sectortype != EDC_MODE_2_FORM_1)
1726 		return (WRONG_TYPE);
1727 
1728 	memcpy(inout, "\000\377\377\377\377\377\377\377\377\377\377\000", 12);
1729 	if (sectortype == EDC_MODE_1) {
1730 		low_taboo  = 1;
1731 		high_taboo = 0;
1732 	} else {
1733 		memcpy(inout+12, "\000\000\000\000", 4);
1734 		low_taboo  = 0;
1735 		high_taboo = (4-1)/2;
1736 	}
1737 
1738 
1739 	init_erasures(have_erasures, erasures, gdp);
1740 	memset(gdp->corrcount, 0, sizeof (gdp->corrcount));
1741 	memset(gdp->Pcorrcount, 0, sizeof (gdp->Pcorrcount));
1742 	memset(gdp->Qcorrcount, 0, sizeof (gdp->Qcorrcount));
1743 
1744 	loops = 0;
1745 	do {
1746 
1747 		crc_ok = do_crc_check(inout, sectortype, loops, gdp);
1748 
1749 		/* we are satisfied, when the crc is correct. */
1750 		if (crc_ok) {
1751 #if	DEBUG >= 3
1752 fprintf(stderr, "loop1:%d crc=%d, p=%d, p_chan=%d, q=%d, q_chan=%d, q_chan_p=%d lo=%d, hi=%d\n",
1753 	loops, crc_ok, p_ok, p_changed, q_ok, q_changed, q_changed_p, low_taboo, high_taboo);
1754 #endif
1755 			break;
1756 		}
1757 
1758 
1759 		p_ok = p_correct_all(inout+12, &p_changed, low_taboo, high_taboo, loops, gdp);
1760 
1761 		if (p_ok && p_changed) {
1762 			crc_ok = do_crc_check(inout, sectortype, loops, gdp);
1763 			/* we are satisfied, when the crc is correct. */
1764 			if (crc_ok) {
1765 #if	DEBUG >= 3
1766 fprintf(stderr, "loop2:%d crc=%d, p=%d, p_chan=%d, q=%d, q_chan=%d, q_chan_p=%d lo=%d, hi=%d\n",
1767 	loops, crc_ok, p_ok, p_changed, q_ok, q_changed, q_changed_p, low_taboo, high_taboo);
1768 #endif
1769 				break;
1770 			}
1771 		}
1772 
1773 		if (loops > 0 && !crc_ok && q_ok && p_ok) {
1774 			memset(gdp->Psyndromes, 1, sizeof (gdp->Psyndromes));
1775 			memset(gdp->Qsyndromes, 1, sizeof (gdp->Qsyndromes));
1776 		}
1777 		q_ok = q_correct_all(inout+12, &q_changed, &q_changed_p,
1778 					low_taboo, high_taboo, loops, gdp);
1779 
1780 #if	DEBUG >= 2
1781 fprintf(stderr, "loop :%d crc=%d, p=%d, p_chan=%d, q=%d, q_chan=%d, q_chan_p=%d lo=%d, hi=%d\n",
1782 	loops, crc_ok, p_ok, p_changed, q_ok, q_changed, q_changed_p, low_taboo, high_taboo);
1783 #endif
1784 		if (!q_changed_p && crc_ok && q_ok) {
1785 			if (loops == 0 && !q_changed && !p_changed && p_ok)
1786 				return (NO_ERRORS);
1787 
1788 			if (p_ok)
1789 				return (FULLY_CORRECTED);
1790 		}
1791 		if ((!q_ok) && !q_changed_p)
1792 			q_changed_p |= unify_erasures(have_erasures, inout+12, gdp);
1793 
1794 		loops++;
1795 	} while (q_changed_p && loops < MAXLOOPS);
1796 
1797 	if (crc_ok) {
1798 		unsigned	i;
1799 
1800 #if	1
1801 		if (!q_changed && !p_changed && loops == 0) {
1802 			for (i = 0, p_ok = 1; i < L2_P/4; i++) {
1803 				p_ok &= calc_L2_P_syndrome(inout+12, i, &gdp->Psyndromes[2*i]);
1804 			}
1805 			for (i = 0, q_ok = 1; i < L2_Q/4; i++) {
1806 				q_ok &= calc_L2_Q_syndrome(inout+12, i, &gdp->Qsyndromes[2*i]);
1807 			}
1808 #if	DEBUG >= 2
1809 fprintf(stderr, "loop :%d crc=%d, p=%d, p_chan=%d, q=%d, q_chan=%d, q_chan_p=%d lo=%d, hi=%d\n",
1810 	-1, crc_ok, p_ok, p_changed, q_ok, q_changed, q_changed_p, low_taboo, high_taboo);
1811 #endif
1812 			if (p_ok && q_ok)
1813 				return (NO_ERRORS);
1814 		}
1815 #endif
1816 
1817 		if (p_ok && q_ok && !q_changed_p)
1818 			return (FULLY_CORRECTED);
1819 
1820 		/* restore unused, p and q portions */
1821 		if (sectortype == EDC_MODE_1)
1822 			memset(inout + 2064 + 4, 0, 8);
1823 		encode_L2_P(inout + 12);
1824 		encode_L2_Q(inout + 12);
1825 
1826 		return (FULLY_CORRECTED);
1827 	}
1828 
1829 	crc_ok = do_crc_check(inout, sectortype, 1, gdp);
1830 
1831 #if	DEBUG >= 2
1832 fprintf(stderr, "loop:%d crc=%d, p=%d, p_chan=%d, q=%d, q_chan=%d, q_chan_p=%d lo=%d, hi=%d\n",
1833 	99, crc_ok, p_ok, p_changed, q_ok, q_changed, q_changed_p, low_taboo, high_taboo);
1834 #endif
1835 	if (crc_ok) {
1836 		if (p_ok && q_ok)
1837 			return (FULLY_CORRECTED);
1838 
1839 		/* restore unused, p and q portions */
1840 		if (sectortype == EDC_MODE_1) memset(inout + 2064 + 4, 0, 8);
1841 		encode_L2_P(inout + 12);
1842 		encode_L2_Q(inout + 12);
1843 
1844 		return (FULLY_CORRECTED);
1845 	}
1846 	return (UNCORRECTABLE);
1847 }
1848 #endif
1849 #endif
1850 
1851 #ifdef	EDC_SUBCHANNEL
1852 /************************** SUBCHANNEL *********************************/
1853 #ifdef	EDC_DECODER
1854 
1855 #undef L12_MODUL
1856 #undef	L12_P_ERRORS
1857 #undef	L12_Q_ERRORS
1858 #undef	P_LENGTH
1859 #undef	Q_LENGTH
1860 #undef	P_SKIPPED
1861 #undef	Q_SKIPPED
1862 
1863 #define	LSUB_MODUL	63
1864 #define	LSUB_P_ERRORS	2
1865 #define	LSUB_Q_ERRORS	1
1866 #define	LSUB_P_LENGTH	20
1867 #define	LSUB_Q_LENGTH	2
1868 #define	LSUB_P_SKIPPED	(LSUB_MODUL-LSUB_P_LENGTH-2*LSUB_P_ERRORS)
1869 #define	LSUB_Q_SKIPPED	(LSUB_MODUL-LSUB_Q_LENGTH-2*LSUB_Q_ERRORS)
1870 
1871 
1872 static int
1873 calc_LSUB_Q_syndrome __PR((unsigned char inout[LSUB_QRAW + LSUB_Q],
1874 unsigned char syndrome[LSUB_Q]));
1875 
1876 static int
calc_LSUB_Q_syndrome(inout,syndrome)1877 calc_LSUB_Q_syndrome(inout, syndrome)
1878 	unsigned char inout[LSUB_QRAW + LSUB_Q];
1879 	unsigned char syndrome[LSUB_Q];
1880 {
1881 	unsigned    data;
1882     unsigned char *Q = syndrome;
1883 
1884 	syndrome[0] = syndrome[1] = 0;
1885 	inout += 4-1;
1886 
1887 #define	QBODYEND(i)   					\
1888 		data = *inout & (unsigned)0x3f;		\
1889 							\
1890 		*Q++ ^= (unsigned char)data;		\
1891 		*Q   ^= SUBsyn[i][0][data];
1892 
1893 #define	QBODY(i)					\
1894 		QBODYEND(i)				\
1895 		inout--; 				\
1896 		Q--;
1897 
1898 	QBODY(0)
1899 	QBODY(1)
1900 	QBODY(2)
1901 	QBODYEND(3)
1902 	return ((syndrome[0] | syndrome[1]) != 0);
1903 }
1904 
1905 static int
1906 calc_LSUB_P_syndrome __PR((unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P],
1907 unsigned char syndrome[LSUB_P]));
1908 
1909 static int
calc_LSUB_P_syndrome(inout,syndrome)1910 calc_LSUB_P_syndrome(inout, syndrome)
1911 	unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P];
1912 	unsigned char syndrome[LSUB_P];
1913 {
1914 	unsigned    data;
1915     unsigned char *P = syndrome;
1916 
1917 	syndrome[0] = syndrome[1] = syndrome[2] = syndrome[3] = 0;
1918 	inout += 24-1;
1919 
1920 #define	PBODYEND(i)   					\
1921 		data = *inout & (unsigned)0x3f;		\
1922 							\
1923 		*P++ ^= (unsigned char)data;		\
1924 		*P++ ^= SUBsyn[i][0][data]; 		\
1925 		*P++ ^= SUBsyn[i][1][data]; 		\
1926 		*P   ^= SUBsyn[i][2][data];
1927 
1928 #define	PBODY(i)   	\
1929 		PBODYEND(i) \
1930 		inout--; \
1931 		P -= 3;
1932 
1933 	PBODY(0)  PBODY(1)  PBODY(2)  PBODY(3)  PBODY(4)
1934 	PBODY(5)  PBODY(6)  PBODY(7)  PBODY(8)  PBODY(9)
1935 	PBODY(10) PBODY(11) PBODY(12) PBODY(13) PBODY(14)
1936 	PBODY(15) PBODY(16) PBODY(17) PBODY(18) PBODY(19)
1937 	PBODY(20) PBODY(21) PBODY(22) PBODYEND(23)
1938 
1939 	return ((syndrome[0] | syndrome[1] |
1940 		    syndrome[2] | syndrome[3]) != 0);
1941 }
1942 
1943 #ifdef	__needed__
1944 #define	SYND(a)		syndrome[a]
1945 static int
1946 correct_QSUB __PR((unsigned char inout[LSUB_RAW + LSUB_P + LSUB_Q],
1947 	unsigned char syndrome[LSUB_Q],
1948 	unsigned erasures, unsigned char Qerasures[LSUB_Q_LENGTH]));
1949 
1950 static int
correct_QSUB(inout,syndrome,erasures,Qerasures)1951 correct_QSUB(inout, syndrome, erasures, Qerasures)
1952 	unsigned char inout[LSUB_RAW + LSUB_P + LSUB_Q];
1953 	unsigned char syndrome[LSUB_Q];
1954 	unsigned erasures;
1955 	unsigned char Qerasures[LSUB_Q_LENGTH];
1956 {
1957 	unsigned	i;
1958 	unsigned	j;
1959 	unsigned	l;
1960 	unsigned	k;
1961 	unsigned	roots_found;
1962 	unsigned char	err_locations[2*LSUB_Q_ERRORS+1];
1963 	unsigned char	err_values[2*LSUB_Q_ERRORS+1];
1964 	unsigned char	tmp_loc[2*LSUB_Q_ERRORS+1];
1965 	unsigned char	roots[2*LSUB_Q_ERRORS];
1966 	unsigned char	discrepancy;
1967 
1968 	INIT_BMD
1969 
1970 	if (erasures > 2*LSUB_Q_ERRORS) erasures = 0;
1971 	/*
1972 	 * initialize error location polynomial with roots from given
1973 	 * erasure locations.
1974 	 */
1975 	if (erasures > 0) {
1976 
1977 		INIT_ERASURES(Qerasures, LSUB_Q_ERRORS, LSUB_MODUL,
1978 						rs_sub_rw_log, rs_sub_rw_alog)
1979 
1980 		if (DEBUG > 2) { DEBUG_ERASURE_POLY(rs_sub_rw_log, rs_sub_rw_alog,
1981 				LSUB_MODUL, LSUB_Q_ERRORS, LSUB_Q_SKIPPED, 0) }
1982 	} /* erasure initialisation */
1983 
1984 	/*
1985 	 * calculate the final error location polynomial.
1986 	 */
1987 	for (j = l = erasures, k = 1; j < 2*LSUB_Q_ERRORS; j++, k++) {
1988 
1989 		/* calculate the 'discrepancy' */
1990 		CALC_DISCREPANCY(rs_sub_rw_log, rs_sub_rw_alog)
1991 
1992 		/* test discrepancy for zero */
1993 		if (discrepancy != 0) {
1994 			BUILD_SHIFT_REGISTER(rs_sub_rw_log, rs_sub_rw_alog,
1995 					LSUB_MODUL, LSUB_Q_ERRORS)
1996 		}
1997 
1998 #if	DEBUG > 2
1999 		fprintf(stderr, "Qdisc=%d, ", discrepancy);
2000 		fprintf(stderr, "j=%d, ", j);
2001 		fprintf(stderr, "k=%d, l(errors)=%d, e0=%d, e1=%d, B0=%d, B1=%d\n",
2002 				k, l, err_locations[0], err_locations[1], tmp_loc[0], tmp_loc[1]);
2003 #endif
2004 	}
2005 
2006 	if (l > LSUB_Q_ERRORS+erasures/2)
2007 		return (1);
2008 
2009 	/* find roots of err_locations */
2010 	FIND_ROOTS(rs_sub_rw_log, rs_sub_rw_alog, LSUB_MODUL, LSUB_Q_ERRORS,
2011 		LSUB_Q_SKIPPED, 0)
2012 
2013 	if (roots_found != l) {
2014 		return (1);
2015 	}
2016 
2017 	/*
2018 	 * l holds the number of errors
2019 	 *
2020 	 * now calculate the error valuator
2021 	 */
2022 	CALC_ERROR_VALUATOR(rs_sub_rw_log, rs_sub_rw_alog)
2023 
2024 	APPLY_FORNEY_ALGORITHM(rs_sub_rw_log, rs_sub_rw_alog, LSUB_MODUL,
2025 		LSUB_Q_SKIPPED, DO_SUB_CORRECTION)
2026 
2027 	return (roots_found ? 0 : 1);
2028 }
2029 #undef	SYND
2030 #endif	/* __needed__ */
2031 
2032 #ifdef	__needed__
2033 #define	SYND(a)		syndrome[a]
2034 static int
2035 correct_PSUB __PR((unsigned char inout[LSUB_RAW + LSUB_P + LSUB_Q],
2036 	unsigned char syndrome[LSUB_P],
2037 	unsigned erasures, unsigned char Perasures[LSUB_P_LENGTH]));
2038 
2039 static int
correct_PSUB(inout,syndrome,erasures,Perasures)2040 correct_PSUB(inout, syndrome, erasures, Perasures)
2041 	unsigned char inout[LSUB_RAW + LSUB_P + LSUB_Q];
2042 	unsigned char syndrome[LSUB_P];
2043 	unsigned erasures;
2044 	unsigned char Perasures[LSUB_P_LENGTH];
2045 {
2046 	unsigned	i;
2047 	unsigned	j;
2048 	unsigned	l;
2049 	unsigned	k;
2050 	unsigned	roots_found;
2051 	unsigned char	err_locations[2*LSUB_P_ERRORS+1];
2052 	unsigned char	err_values[2*LSUB_P_ERRORS+1];
2053 	unsigned char	tmp_loc[2*LSUB_P_ERRORS+1];
2054 	unsigned char	roots[2*LSUB_P_ERRORS];
2055 	unsigned char	discrepancy;
2056 
2057 	INIT_BMD
2058 
2059 	if (erasures > 2*LSUB_P_ERRORS) erasures = 0;
2060 	/*
2061 	 * initialize error location polynomial with roots from given
2062 	 * erasure locations.
2063 	 */
2064 	if (erasures > 0) {
2065 
2066 		INIT_ERASURES(Perasures, LSUB_P_ERRORS, LSUB_MODUL,
2067 						rs_sub_rw_log, rs_sub_rw_alog)
2068 
2069 		if (DEBUG > 2) { DEBUG_ERASURE_POLY(rs_sub_rw_log, rs_sub_rw_alog,
2070 				LSUB_MODUL, LSUB_P_ERRORS, LSUB_P_SKIPPED, 0) }
2071 	} /* erasure initialisation */
2072 
2073 	/*
2074 	 * calculate the final error location polynomial.
2075 	 */
2076 	for (j = l = erasures, k = 1; j < 2*LSUB_P_ERRORS; j++, k++) {
2077 
2078 		/* calculate the 'discrepancy' */
2079 		CALC_DISCREPANCY(rs_sub_rw_log, rs_sub_rw_alog)
2080 
2081 		/* test discrepancy for zero */
2082 		if (discrepancy != 0) {
2083 			BUILD_SHIFT_REGISTER(rs_sub_rw_log, rs_sub_rw_alog,
2084 					LSUB_MODUL, LSUB_P_ERRORS)
2085 		}
2086 #if	DEBUG > 2
2087 fprintf(stderr, "Pdisc=%d, ", discrepancy);
2088 fprintf(stderr, "j=%d, ", j);
2089 fprintf(stderr, "k=%d, l(errors)=%d, e0=%d, e1=%d, B0=%d, B1=%d\n",
2090 	k, l, err_locations[0], err_locations[1], tmp_loc[0], tmp_loc[1]);
2091 #endif
2092 	}
2093 
2094 	if (l > LSUB_P_ERRORS+erasures/2)
2095 		return (1);
2096 
2097 	/* find roots of err_locations */
2098 	FIND_ROOTS(rs_sub_rw_log, rs_sub_rw_alog, LSUB_MODUL, LSUB_P_ERRORS,
2099 		LSUB_P_SKIPPED, 0)
2100 
2101 	if (roots_found != l) {
2102 		return (1);
2103 	}
2104 
2105 	/*
2106 	 * l holds the number of errors
2107 	 *
2108 	 * now calculate the error valuator
2109 	 */
2110 	CALC_ERROR_VALUATOR(rs_sub_rw_log, rs_sub_rw_alog)
2111 
2112 	/*
2113 	 * apply the forney algorithm
2114 	 */
2115 	APPLY_FORNEY_ALGORITHM(rs_sub_rw_log, rs_sub_rw_alog, LSUB_MODUL,
2116 		LSUB_P_SKIPPED, DO_SUB_CORRECTION)
2117 
2118 	return (roots_found ? 0 : 1);
2119 }
2120 #undef	SYND
2121 #endif	/* __needed__ */
2122 
2123 
2124 #ifdef	DECODE_SUB_IN_ENCODER	/* XXX we need to fix this in edc_ecc.c */
2125 int
2126 do_decode_sub __PR((
2127 	unsigned char inout[(LSUB_RAW + LSUB_Q + LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
2128 	int have_erasures,
2129 	unsigned char erasures[(LSUB_RAW +LSUB_Q +LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
2130 	int results[PACKETS_PER_SUBCHANNELFRAME]
2131 ));
2132 
2133 int
do_decode_sub(inout,have_erasures,erasures,results)2134 do_decode_sub(inout, have_erasures, erasures, results)
2135 	unsigned char inout[(LSUB_RAW + LSUB_Q + LSUB_P) * PACKETS_PER_SUBCHANNELFRAME];
2136 	int have_erasures;
2137 	unsigned char erasures[(LSUB_RAW + LSUB_Q + LSUB_P) * PACKETS_PER_SUBCHANNELFRAME];
2138 	int results[PACKETS_PER_SUBCHANNELFRAME];
2139 {
2140 	static unsigned char Psyndromes[LSUB_P * PACKETS_PER_SUBCHANNELFRAME];
2141 	static unsigned char Qsyndromes[LSUB_Q * PACKETS_PER_SUBCHANNELFRAME];
2142 	static unsigned char Perapos[(LSUB_RAW+LSUB_Q+LSUB_P) * PACKETS_PER_SUBCHANNELFRAME];
2143 	static unsigned char Qerapos[(LSUB_QRAW+LSUB_Q) * PACKETS_PER_SUBCHANNELFRAME];
2144 	static unsigned char Pcount[PACKETS_PER_SUBCHANNELFRAME];
2145 	static unsigned char Qcount[PACKETS_PER_SUBCHANNELFRAME];
2146 	unsigned char *Psyndromesp = Psyndromes;
2147 	unsigned char *Qsyndromesp = Qsyndromes;
2148 	unsigned char *Peraposp = Perapos;
2149 	unsigned char *Qeraposp = Qerapos;
2150 	unsigned char *Pcountp = Pcount;
2151 	unsigned char *Qcountp = Qcount;
2152 	int	packet;
2153 	int	have_error = 1;
2154 	int 	error = 0;
2155 	int 	changed_Q;
2156 	int 	changed_P;
2157 	int 	retval = -12;
2158 
2159 	memset(Perapos, 0, sizeof (Perapos));
2160 	memset(Qerapos, 0, sizeof (Qerapos));
2161 	memset(Pcount, 0, sizeof (Pcount));
2162 	memset(Qcount, 0, sizeof (Qcount));
2163 	if (have_erasures != 0) {
2164 		unsigned char i;
2165 		/*
2166 		 * separate erasures for Q and P level.
2167 		 */
2168 		for (i = 0; i < (LSUB_QRAW + LSUB_Q)* PACKETS_PER_SUBCHANNELFRAME; i++) {
2169 			if (erasures[i] != 0) {
2170 				Qerapos[i] = (unsigned char)(i + LSUB_Q_SKIPPED);
2171 				Qcount[i/(LSUB_QRAW + LSUB_Q)]++;
2172 			}
2173 			if ((i % (LSUB_QRAW + LSUB_Q)) == LSUB_QRAW + LSUB_Q - 1) {
2174 				erasures += LSUB_RAW + LSUB_P + LSUB_Q;
2175 			}
2176 		}
2177 		erasures -= (LSUB_RAW + LSUB_P + LSUB_Q)* PACKETS_PER_SUBCHANNELFRAME;
2178 		for (i = 0; i < (LSUB_RAW + LSUB_P + LSUB_Q)* PACKETS_PER_SUBCHANNELFRAME; i++) {
2179 			if (erasures[i] != 0) {
2180 				Perapos[i] = (unsigned char)(i + LSUB_P_SKIPPED);
2181 				Pcount[i/(LSUB_QRAW + LSUB_Q)]++;
2182 			}
2183 		}
2184 	}
2185 	for (have_error = 1, packet = 0;
2186 		packet < PACKETS_PER_SUBCHANNELFRAME;
2187 		packet++,
2188 		Qsyndromesp += LSUB_Q, Psyndromesp += LSUB_P,
2189 		Qcountp++, Pcountp++,
2190 		Qeraposp += LSUB_QRAW + LSUB_Q,
2191 		Peraposp += LSUB_RAW + LSUB_Q + LSUB_P,
2192 		inout += 24) {
2193 		int iCnt;
2194 
2195 		for (iCnt = 0; have_error && iCnt < 2; iCnt++) {
2196 			unsigned i = 0;
2197 			changed_Q = have_error = 0;
2198 
2199 			if (calc_LSUB_P_syndrome(inout, Psyndromesp)) {
2200 				error |= 2 << (2*i);
2201 
2202 				retval = correct_PSUB(inout, Psyndromesp, 0, NULL);
2203 				have_error |= retval;
2204 				changed_P = !retval;
2205 				if (retval == 0) {
2206 					Pcountp[0] = 0;
2207 #if DEBUG >= 0
2208 					calc_LSUB_P_syndrome(inout, Psyndromesp);
2209 					if (Psyndromesp[0] != 0 ||
2210 					    Psyndromesp[1] != 0 ||
2211 					    Psyndromesp[2] != 0 ||
2212 					    Psyndromesp[3] != 0) {
2213 fprintf(stderr, "\nSubP internal error in %s, %d\n", __FILE__, __LINE__);
2214 					}
2215 #endif
2216 				}
2217 			}
2218 			if (calc_LSUB_Q_syndrome(inout, Qsyndromesp)) {
2219 				error |= 1 << (2*i);
2220 				retval = correct_QSUB(inout, Qsyndromesp, 0, NULL);
2221 				have_error |= retval;
2222 				changed_Q = !retval;
2223 				if (retval == 0) {
2224 					Qcountp[0] = 0;
2225 #if DEBUG >= 0
2226 					calc_LSUB_Q_syndrome(inout, Qsyndromesp);
2227 					if (Qsyndromesp[0] != 0 ||
2228 					    Qsyndromesp[1] != 0) {
2229 fprintf(stderr, "\nSubQ internal error in %s, %d\n", __FILE__, __LINE__);
2230 					}
2231 #endif
2232 				}
2233 			}
2234 			if (results != NULL) {
2235 				results[packet] = (error & (3 << (2*i))) != 0;
2236 			}
2237 		}
2238 	}
2239 	return (have_error);
2240 }
2241 #endif	/* DECODE_SUB_IN_ENCODER	XXX we need to fix this in edc_ecc.c */
2242 
2243 int check_sub __PR((unsigned char input[]));
2244 
2245 int
check_sub(input)2246 check_sub(input)
2247 	unsigned char input[];
2248 {
2249 	int error = 0;
2250 	int packet;
2251 
2252 	for (packet = 0;
2253 		!error && packet < PACKETS_PER_SUBCHANNELFRAME;
2254 		packet++, input += 24) {
2255 		unsigned char syndromes[4];
2256 
2257 		error |= calc_LSUB_P_syndrome(input, syndromes);
2258 		error |= calc_LSUB_Q_syndrome(input, syndromes);
2259 	}
2260 	return (error);
2261 }
2262 #endif
2263 #endif
2264