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