|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
4: All Rights Reserved
5:
6: Module Name:
7:
8: reedsolo.c
9:
10: Abstract:
11:
12: These routines perform the Reed-Solomon Error correction
13: required for QIC-40 rev D. Spec.
14:
15: Revision History:
16:
17:
18:
19:
20: --*/
21:
22: //
23: // Includes
24: //
25:
26: #include <ntddk.h>
27: #include <ntddtape.h>
28: #include "common.h"
29: #include "q117.h"
30: #include "protos.h"
31:
32: //
33: // Protos for entry points
34: //
35:
36:
37: UCHAR
38: q117RdsMultiplyTuples (
39: IN UCHAR tup1,
40: IN UCHAR tup2
41: );
42:
43: UCHAR
44: q117RdsDivideTuples (
45: IN UCHAR tup1,
46: IN UCHAR tup2
47: );
48:
49: UCHAR
50: q117RdsExpTuple (
51: IN UCHAR tup1,
52: IN UCHAR xpnt
53: );
54:
55: VOID
56: q117RdsGetSyndromes (
57: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
58: IN UCHAR Count, // number of good sectors in segment (4-32)
59: IN UCHAR *ps1,
60: IN UCHAR *ps2,
61: IN UCHAR *ps3
62: );
63:
64: BOOLEAN
65: q117RdsCorrectFailure (
66: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
67: IN UCHAR Count, // number of good sectors in segment (4-32)
68: IN UCHAR s1,
69: IN UCHAR s2,
70: IN UCHAR s3
71: );
72:
73: BOOLEAN
74: q117RdsCorrectOneError (
75: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
76: IN UCHAR Count, // number of good sectors in segment (4-32)
77: IN UCHAR ErrorLocation,
78: IN UCHAR s1,
79: IN UCHAR s2,
80: IN UCHAR s3
81: );
82:
83: BOOLEAN
84: q117RdsCorrectTwoErrors (
85: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
86: IN UCHAR Count, // number of good sectors in segment (4-32)
87: IN UCHAR ErrorLocation1,
88: IN UCHAR ErrorLocation2,
89: IN UCHAR s1,
90: IN UCHAR s2,
91: IN UCHAR s3
92: );
93:
94: BOOLEAN
95: q117RdsCorrectThreeErrors (
96: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
97: IN UCHAR Count, // number of good sectors in segment (4-32)
98: IN UCHAR ErrorLocation1,
99: IN UCHAR ErrorLocation2,
100: IN UCHAR ErrorLocation3,
101: IN UCHAR s1,
102: IN UCHAR s2,
103: UCHAR s3
104: );
105:
106: BOOLEAN
107: q117RdsCorrectOneErrorAndOneFailure (
108: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
109: IN UCHAR Count, // number of good sectors in segment (4-32)
110: IN UCHAR ErrorLocation1,
111: IN UCHAR s1,
112: IN UCHAR s2,
113: IN UCHAR s3
114: );
115:
116:
117: UCHAR rds_exptup[255*2+2];
118: UCHAR rds_tupexp[256];
119: UCHAR rds_xC0[256];
120:
121: #define PASS 0
122: #define FAIL 1
123:
124: #define ADD_TUPLES(a, b) ((UCHAR) ( (a) ^ (b) ))
125:
126:
127: VOID
128: q117RdsInitReed (
129: VOID
130: )
131:
132: /*++
133:
134: Routine Description:
135:
136:
137: Arguments:
138:
139: Context - Current context of driver
140:
141: Return Value:
142:
143: NONE
144:
145: --*/
146:
147: {
148: ULONG i;
149: ULONG tuple = 1, alpha_8 = 0x87;
150:
151: for (i = 0; i <= 254; ++i) {
152: rds_exptup[i] = (UCHAR)tuple;
153: rds_tupexp[tuple] = (UCHAR)i;
154: if (tuple & 0x80) {
155: tuple = ((tuple << 1) ^ alpha_8) & 0xff;
156: } else {
157: tuple <<= 1;
158: }
159: }
160: for (i=0;i<255;++i) {
161: rds_exptup[i+255] = rds_exptup[i];
162: if (i<2) {
163: rds_exptup[i+255+255] = rds_exptup[i];
164: }
165: }
166: for (i = 0; i<=255; ++i) {
167: rds_xC0[i] = q117RdsMultiplyTuples((UCHAR)i,0xc0);
168: }
169: }
170:
171: UCHAR
172: q117RdsMultiplyTuples (
173: IN UCHAR tup1,
174: IN UCHAR tup2
175: )
176:
177: /*++
178:
179: Routine Description:
180:
181: 8-tuples to be multiplied.
182:
183: Arguments:
184:
185:
186: Return Value:
187:
188: Result of multiply
189:
190: --*/
191:
192: {
193:
194: if ( (tup1 == 0) || (tup2 == 0) ) {
195:
196: return(0);
197:
198: }
199:
200: return ( rds_exptup[rds_tupexp[tup1] + rds_tupexp[tup2]] );
201: }
202:
203: UCHAR
204: q117RdsDivideTuples (
205: IN UCHAR tup1,
206: IN UCHAR tup2
207: )
208:
209: /*++
210:
211: Routine Description:
212:
213: 8-tuples to be devided
214:
215: Arguments:
216:
217:
218: Return Value:
219:
220: Result of divide
221:
222: --*/
223:
224: {
225: if (tup2 == 0) {
226: return(0);
227: }
228: if (tup1 == 0) {
229: return(0);
230: }
231:
232: return (UCHAR)((ULONG)rds_exptup[rds_tupexp[tup1] + 255 - rds_tupexp[tup2]]);
233: }
234:
235: UCHAR
236: q117RdsExpTuple (
237: IN UCHAR tup1,
238: IN UCHAR xpnt
239: )
240:
241: /*++
242:
243: Routine Description:
244:
245: Exponent routine.
246:
247: Arguments:
248:
249:
250: Return Value:
251:
252: Result of tup1^xpnt
253:
254: --*/
255:
256: {
257: if (tup1 == 0)
258: return(0);
259:
260: return (UCHAR)((ULONG)rds_exptup[(rds_tupexp[tup1] * xpnt ) % 255]);
261: }
262:
263: VOID
264: q117RdsMakeCRC (
265: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
266: IN UCHAR Count // number of sectors (1K blocks)(1-32)
267: )
268:
269: /*++
270:
271: Routine Description:
272:
273: Add Reed Solomon codes to buffer
274:
275: Arguments:
276:
277:
278: Return Value:
279:
280:
281: --*/
282:
283: {
284: ULONG num;
285: UCHAR i,j,k,p0,p1,p2;
286:
287:
288: for ( num = 0;num < BYTES_PER_SECTOR;++num ) {
289: p0 = p1 = p2 = 0;
290:
291: for ( i = 0; i < (UCHAR)(Count-3); ++i ) {
292:
293: j = rds_xC0[k = (p2 ^ Array[i * BYTES_PER_SECTOR + num])];
294: p2 = j ^ p1;
295: p1 = j ^ p0;
296: p0 = k;
297:
298: }
299:
300: Array[i * BYTES_PER_SECTOR + num] = p2;
301: i++;
302: Array[i * BYTES_PER_SECTOR + num] = p1;
303: i++;
304: Array[i * BYTES_PER_SECTOR + num] = p0;
305: i++;
306: }
307: }
308:
309: BOOLEAN
310: q117RdsReadCheck (
311: IN UCHAR *Array, // pointer to 32K data area (segment)
312: IN UCHAR Count // number of sectors (1K blocks)(1-32)
313: )
314:
315: /*++
316:
317: Routine Description:
318:
319: perform read check on buffer (fast check for CRC failures)
320:
321: Arguments:
322:
323:
324: Return Value:
325:
326: 1 - Success
327:
328: 0 - Failure
329:
330: --*/
331:
332:
333: {
334: LONG num;
335: UCHAR i,sum;
336:
337: for ( num = 0; num < BYTES_PER_SECTOR; ++num ) {
338:
339: sum = 0;
340: for ( i = 0; i < Count; ++i ) {
341:
342: sum ^= Array[i * BYTES_PER_SECTOR + num];
343:
344: }
345: if ( sum != 0 ) {
346:
347: return FAIL;
348:
349: }
350: }
351:
352: return PASS;
353: }
354:
355: BOOLEAN
356: q117RdsCorrect(
357: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
358: IN UCHAR Count, // number of good sectors in segment (4-32)
359: IN UCHAR CRCErrors, // number of crc errors
360: IN UCHAR e1,
361: IN UCHAR e2,
362: IN UCHAR e3 // sectors where errors occurred
363: )
364:
365: /*++
366:
367: Routine Description:
368:
369: perform error Reed-Solomon error correction on segment
370:
371: Arguments:
372:
373:
374: Return Value:
375:
376: 1 - Success
377:
378: 0 - Failure
379:
380: --*/
381:
382: {
383: USHORT num;
384: BOOLEAN ret;
385: UCHAR s1,s2,s3;
386:
387: ret = PASS;
388: Count--;
389: e1 = Count-e1;
390: e2 = Count-e2;
391: e3 = Count-e3;
392:
393: for ( num = 0; num < BYTES_PER_SECTOR; ++num ) {
394: q117RdsGetSyndromes(&Array[num],Count,&s1,&s2,&s3);
395: if ( s1 || s2 || s3 ) {
396:
397: switch( CRCErrors ) {
398:
399: case 0:
400: ret = q117RdsCorrectFailure(&Array[num],Count,s1,s2,s3);
401: break;
402:
403: case 1:
404: ret = q117RdsCorrectOneError(&Array[num],Count,e1,s1,s2,s3);
405: break;
406:
407: case 2:
408: ret = q117RdsCorrectTwoErrors(&Array[num],Count,e1,e2,s1,s2,s3);
409: break;
410:
411: case 3:
412: ret = q117RdsCorrectThreeErrors(&Array[num],Count,e1,e2,e3,s1,s2,s3);
413: break;
414:
415: default:
416: ret = FAIL;
417: break;
418: }
419: }
420: if (ret)
421: return ret;
422: }
423: return ret;
424: }
425:
426:
427: //
428: // Due to bug in CL386 version 0.00.45, turn off optimization
429: //
430: #if i386
431: #pragma optimize("",off)
432: #endif
433:
434:
435: VOID
436: q117RdsGetSyndromes (
437: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
438: IN UCHAR Count, // number of good sectors in segment (4-32)
439: IN UCHAR *ps1,
440: IN UCHAR *ps2,
441: IN UCHAR *ps3
442: )
443:
444: /*++
445:
446: Routine Description:
447:
448: 8-tuples to be multiplied.
449:
450: Arguments:
451:
452:
453: Return Value:
454:
455:
456: --*/
457:
458: {
459: UCHAR q,r,s,s1,s2,s3,cx,al,ah;
460:
461: q = r = s = 0;
462:
463: for ( cx = 0; cx <= Count; ++cx ) {
464:
465: al = rds_xC0[ah = q];
466: q = r ^ al;
467: r = s ^ al;
468: s = ah ^ Array[cx * BYTES_PER_SECTOR];
469:
470: }
471:
472: s1 = q117RdsMultiplyTuples(q,0xa2) ^ q117RdsMultiplyTuples(r,0xc3) ^ s;
473: s2 = q ^ r ^ s;
474: s3 = q117RdsMultiplyTuples(q,0x4) ^ q117RdsMultiplyTuples(r,2) ^ s;
475: *ps1 = s1;
476: *ps2 = s2;
477: *ps3 = s3;
478: }
479: #if i386
480: #pragma optimize("",on)
481: #endif
482:
483:
484: BOOLEAN
485: q117RdsCorrectFailure (
486: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
487: IN UCHAR Count, // number of good sectors in segment (4-32)
488: IN UCHAR s1,
489: IN UCHAR s2,
490: IN UCHAR s3
491: )
492:
493: /*++
494:
495: Routine Description:
496:
497: Correct one failure
498:
499: Arguments:
500:
501:
502: Return Value:
503:
504: 1 - Success
505:
506: 0 - Failure
507:
508: --*/
509:
510: {
511: UCHAR errorloc,c1,y1,x1,ck;
512:
513: //
514: // check for divide by zero
515: //
516: if (s1 == 0) {
517: return FAIL;
518: }
519: errorloc = rds_tupexp[q117RdsDivideTuples(s2,s1)];
520: if (errorloc > Count) {
521: return FAIL;
522: }
523: y1 = s2;
524: x1 = rds_exptup[errorloc];
525: c1 = ADD_TUPLES(s2,Array[(Count-errorloc) * BYTES_PER_SECTOR]);
526: ck = q117RdsMultiplyTuples(y1,x1);
527: if (ck != s3) {
528: return FAIL;
529: } else {
530: Array[(Count-errorloc) * BYTES_PER_SECTOR] = c1;
531: }
532: return PASS;
533: }
534:
535: BOOLEAN
536: q117RdsCorrectOneError (
537: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
538: IN UCHAR Count, // number of good sectors in segment (4-32)
539: IN UCHAR ErrorLocation,
540: IN UCHAR s1,
541: IN UCHAR s2,
542: IN UCHAR s3
543: )
544:
545: /*++
546:
547: Routine Description:
548:
549: Correct one error.
550:
551: Arguments:
552:
553:
554: Return Value:
555:
556: 1 - Success
557:
558: 0 - Failure
559:
560: --*/
561:
562: {
563: UCHAR x1,y1,c1,ck;
564:
565: x1 = rds_exptup[ErrorLocation];
566: y1 = s2;
567: c1 = ADD_TUPLES(s2,Array[(Count-ErrorLocation) * BYTES_PER_SECTOR]);
568: ck = q117RdsMultiplyTuples(y1,x1);
569:
570: if ( ck != s3 ) {
571:
572: return q117RdsCorrectOneErrorAndOneFailure(Array,Count,ErrorLocation,s1,s2,s3);
573:
574: } else {
575:
576: Array[(Count-ErrorLocation) * BYTES_PER_SECTOR] = c1;
577:
578: }
579: return PASS;
580: }
581:
582: BOOLEAN
583: q117RdsCorrectTwoErrors (
584: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
585: IN UCHAR Count, // number of good sectors in segment (4-32)
586: IN UCHAR ErrorLocation1,
587: IN UCHAR ErrorLocation2,
588: IN UCHAR s1,
589: IN UCHAR s2,
590: IN UCHAR s3
591: )
592:
593: /*++
594:
595: Routine Description:
596:
597: Correct two errors.
598:
599: Arguments:
600:
601:
602: Return Value:
603:
604: 1 - Success
605:
606: 0 - Failure
607:
608: --*/
609:
610: {
611: UCHAR y1,y2,x1,x2,c1,c2,ck;
612:
613: x1 = rds_exptup[ErrorLocation1];
614: x2 = rds_exptup[ErrorLocation2];
615:
616: y2 = q117RdsDivideTuples(
617: ADD_TUPLES(
618: q117RdsMultiplyTuples(s2, x1), s3 ), ADD_TUPLES(x1,x2)
619: );
620:
621: y1 = ADD_TUPLES(y2,s2);
622:
623: c1 = ADD_TUPLES( y1, Array[(Count-ErrorLocation1) * BYTES_PER_SECTOR] );
624: c2 = ADD_TUPLES( y2, Array[(Count-ErrorLocation2) * BYTES_PER_SECTOR] );
625:
626: ck =x1 = q117RdsDivideTuples(
627: ADD_TUPLES(
628: q117RdsMultiplyTuples(y1,x2),
629: q117RdsMultiplyTuples(y2,x1)
630: ), q117RdsMultiplyTuples(x1,x2));
631:
632: if ( ck != s1 ) {
633:
634: return FAIL;
635:
636: } else {
637:
638: Array[(Count-ErrorLocation1) * BYTES_PER_SECTOR] = c1;
639: Array[(Count-ErrorLocation2) * BYTES_PER_SECTOR] = c2;
640:
641: }
642:
643: return PASS;
644: }
645:
646: BOOLEAN
647: q117RdsCorrectThreeErrors (
648: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
649: IN UCHAR Count, // number of good sectors in segment (4-32)
650: IN UCHAR ErrorLocation1,
651: IN UCHAR ErrorLocation2,
652: IN UCHAR ErrorLocation3,
653: IN UCHAR s1,
654: IN UCHAR s2,
655: UCHAR s3
656: )
657:
658: /*++
659:
660: Routine Description:
661:
662: Correct three errors.
663:
664: Arguments:
665:
666:
667: Return Value:
668:
669: 1 - Success
670:
671: 0 - Failure
672:
673: --*/
674:
675: {
676: UCHAR y1,y2,y3,z1,z2,z3,x1,x2,x3,c1,c2,c3,q1,q2,q3,q4;
677:
678: x1 = rds_exptup[ErrorLocation1];
679: x2 = rds_exptup[ErrorLocation2];
680: x3 = rds_exptup[ErrorLocation3];
681: z1 = q117RdsDivideTuples(1,x1);
682: z2 = q117RdsDivideTuples(1,x2);
683: z3 = q117RdsDivideTuples(1,x3);
684: q1 = q117RdsDivideTuples(
685: ADD_TUPLES(q117RdsMultiplyTuples(x1,s2),s3),
686: ADD_TUPLES(x1,x2)
687: );
688: q2 = q117RdsDivideTuples(
689: ADD_TUPLES(q117RdsMultiplyTuples(z1,s2),s1),
690: ADD_TUPLES(z1,z2)
691: );
692: q3 = q117RdsDivideTuples(ADD_TUPLES(x1,x3),ADD_TUPLES(x1,x2));
693: q4 = q117RdsDivideTuples(ADD_TUPLES(z1,z3),ADD_TUPLES(z1,z2));
694: y3 = q117RdsDivideTuples(ADD_TUPLES(q1,q2),ADD_TUPLES(q3,q4));
695: y2 = ADD_TUPLES(q2,q117RdsMultiplyTuples(q4,y3));
696: y1 = ADD_TUPLES(ADD_TUPLES(y3,y2),s2);
697: c1 = ADD_TUPLES(y1,Array[(Count-ErrorLocation1) * BYTES_PER_SECTOR]);
698: c2 = ADD_TUPLES(y2,Array[(Count-ErrorLocation2) * BYTES_PER_SECTOR]);
699: c3 = ADD_TUPLES(y3,Array[(Count-ErrorLocation3) * BYTES_PER_SECTOR]);
700:
701: Array[(Count-ErrorLocation1) * BYTES_PER_SECTOR] = c1;
702: Array[(Count-ErrorLocation2) * BYTES_PER_SECTOR] = c2;
703: Array[(Count-ErrorLocation3) * BYTES_PER_SECTOR] = c3;
704:
705: return PASS;
706: }
707:
708: BOOLEAN
709: q117RdsCorrectOneErrorAndOneFailure (
710: IN OUT UCHAR *Array, // pointer to 32K data area (segment)
711: IN UCHAR Count, // number of good sectors in segment (4-32)
712: IN UCHAR ErrorLocation1,
713: IN UCHAR s1,
714: IN UCHAR s2,
715: IN UCHAR s3
716: )
717:
718: /*++
719:
720: Routine Description:
721:
722: Correct one error and one failure.
723:
724: Arguments:
725:
726:
727: Return Value:
728:
729: 1 - Success
730:
731: 0 - Failure
732:
733: --*/
734:
735: {
736: UCHAR y1,y2,x1,x2,c1,c2;
737: UCHAR errorLoc2;
738:
739: x1 = rds_exptup[ErrorLocation1];
740:
741: y1 = q117RdsDivideTuples(
742: q117RdsMultiplyTuples(
743: ADD_TUPLES(
744: q117RdsMultiplyTuples(s1,s3),
745: q117RdsExpTuple(s2,2)
746: ),x1),
747: ADD_TUPLES(s3,
748: q117RdsMultiplyTuples(s1,q117RdsExpTuple(x1,2)))
749: );
750:
751: y2 = ADD_TUPLES(y1,s2);
752:
753: x2 = q117RdsDivideTuples(
754: q117RdsMultiplyTuples(y2,x1),
755: ADD_TUPLES(y1,q117RdsMultiplyTuples(s1,x1))
756: );
757:
758: errorLoc2 = rds_tupexp[x2];
759:
760: if ( errorLoc2 > Count ) {
761:
762: return FAIL;
763:
764: }
765:
766: c1 = ADD_TUPLES(y1,Array[(Count-ErrorLocation1) * BYTES_PER_SECTOR]);
767: c2 = ADD_TUPLES(y2,Array[(Count-errorLoc2) * BYTES_PER_SECTOR]);
768:
769: Array[(Count-ErrorLocation1) * BYTES_PER_SECTOR] = c1;
770: Array[(Count-errorLoc2) * BYTES_PER_SECTOR] = c2;
771:
772: return PASS;
773: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.