/* HOOK. Fixed comments; otherwise impossible to compile */ /* * $Log: V:/Flite/archives/TrueFFS5/Src/REEDSOL.C_V $ * * Rev 1.3 Jul 13 2001 01:10:00 oris * Moved saved syndrome array definition (used by d2tst). * * Rev 1.2 Apr 09 2001 15:10:20 oris * End with an empty line. * * Rev 1.1 Apr 01 2001 08:00:14 oris * copywrite notice. * * Rev 1.0 Feb 04 2001 12:37:38 oris * Initial revision. * */ /************************************************************************/ /* */ /* FAT-FTL Lite Software Development Kit */ /* Copyright (C) M-Systems Ltd. 1995-2001 */ /* */ /************************************************************************/ #include "reedsol.h" #define T 2 /* Number of recoverable errors */ #define SYND_LEN (T*2) /* length of syndrom vector */ #define K512 (((512+1)*8+6)/10) /* number of inf symbols for record of 512 bytes (K512=411) */ #define N512 (K512 + SYND_LEN) /* code word length for record of 512 bytes */ #define INIT_DEG 510 #define MOD 1023 #define BLOCK_SIZE 512 #ifdef D2TST byte saveSyndromForDumping[SYNDROM_BYTES]; #endif /* D2TST */ static short gfi(short val); static short gfmul( short f, short s ); static short gfdiv( short f, short s ); static short flog(short val); static short alog(short val); /*------------------------------------------------------------------------------*/ /* Function Name: RTLeightToTen */ /* Purpose......: convert an array of five 8-bit values into an array of */ /* four 10-bit values, from right to left. */ /* Returns......: Nothing */ /*------------------------------------------------------------------------------*/ static void RTLeightToTen(char *reg8, unsigned short reg10[]) { reg10[0] = (reg8[0] & 0xFF) | ((reg8[1] & 0x03) << 8); reg10[1] = ((reg8[1] & 0xFC) >> 2) | ((reg8[2] & 0x0F) << 6); reg10[2] = ((reg8[2] & 0xF0) >> 4) | ((reg8[3] & 0x3F) << 4); reg10[3] = ((reg8[3] & 0xC0) >> 6) | ((reg8[4] & 0xFF) << 2); } /*----------------------------------------------------------------------------*/ static void unpack( short word, short length, short vector[] ) /* */ /* Function unpacks word into vector */ /* */ /* Parameters: */ /* word - word to be unpacked */ /* vector - array to be filled */ /* length - number of bits in word */ { short i, *ptr; ptr = vector + length - 1; for( i = 0; i < length; i++ ) { *ptr-- = word & 1; word >>= 1; } } /*----------------------------------------------------------------------------*/ static short pack( short *vector, short length ) /* */ /* Function packs vector into word */ /* */ /* Parameters: */ /* vector - array to be packed */ /* length - number of bits in word */ { short tmp, i; vector += length - 1; tmp = 0; i = 1; while( length-- > 0 ) { if( *vector-- ) tmp |= i; i <<= 1; } return( tmp ); } /*----------------------------------------------------------------------------*/ static short gfi( short val) /* GF inverse */ { return alog((short)(MOD-flog(val))); } /*----------------------------------------------------------------------------*/ static short gfmul( short f, short s ) /* GF multiplication */ { short i; if( f==0 || s==0 ) return 0; else { i = flog(f) + flog(s); if( i > MOD ) i -= MOD; return( alog(i) ); } } /*----------------------------------------------------------------------------*/ static short gfdiv( short f, short s ) /* GF division */ { return gfmul(f,gfi(s)); } /*----------------------------------------------------------------------------*/ static void residue_to_syndrom( short reg[], short realsynd[] ) { short i,l,alpha,x,s,x4; short deg,deg4; for(i=0,deg=INIT_DEG;i= MOD ) deg4 -= MOD; deg4 += deg4; if( deg4 >= MOD ) deg4 -= MOD; x4 = alog(deg4); for(l=1;l 0x3FF ) { if ( val & 8 ) val -= (0x400+7); else val -= (0x400-9); } } return val ; } static short flog(short val) { short j, val1; if (val == 0) return (short)0xFFFF; j=0; val1=1; for( ; j <= MOD ; j++ ) { if (val1 == val) return j; val1 <<= 1 ; if ( val1 > 0x3FF ) { if ( val1 & 8 ) val1 -= (0x400+7); else val1 -= (0x400-9); } } return 0; } /*----------------------------------------------------------------------------*/ static short convert_to_byte_patterns( short *locators, short *values, short noferr, short *blocs, short *bvals ) { static short mask[] = { 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff }; short i,j,n, n0, n1, tmp; short n_bit, n_byte, k_bit, nb; for( i = 0, nb = 0; i< noferr; i++) { n = locators[i]; tmp = values[i]; n_bit = n *10 - 6 ; n_byte = n_bit >> 3; k_bit = n_bit - (n_byte<<3); n_byte++; if( k_bit == 7 ) { /* 3 corrupted bytes */ blocs[nb] = n_byte+1; bvals[nb++] = tmp & 1 ? 0x80 : 0; tmp >>= 1; blocs[nb] = n_byte; bvals[nb++] = tmp & 0xff; tmp >>= 8; bvals[nb++] = tmp & 0xff; } else { n0 = 8 - k_bit; n1 = 10 - n0; blocs[nb] = n_byte; bvals[nb++] = (tmp & mask[n1]) << (8 - n1); tmp >>= n1; blocs[nb] = n_byte - 1; bvals[nb++] = (tmp & mask[n0]); } } for( i = 0, j = -1; i < nb; i++ ) { if( bvals[i] == 0 ) continue; if( (blocs[i] == blocs[j]) && ( j>= 0 ) ) { bvals[j] |= bvals[i]; } else { j++; blocs[j] = blocs[i]; bvals[j] = bvals[i]; } } return j+1; } /*----------------------------------------------------------------------------*/ static short deg512( short x ) { short i; short l,m; l = flog(x); for( i=0;i<9;i++) { m = 0; if( (l & 0x200) ) m = 1; l = ( ( l << 1 ) & 0x3FF ) | m; } return alog(l); } /*----------------------------------------------------------------------------*/ static short decoder_for_2_errors( short s[], short lerr[], short verr[] ) { /* decoder for correcting up to 2 errors */ short i,j,k,temp,delta; short ind, x1, x2; short r1, r2, r3, j1, j2; short sigma1, sigma2; short xu[10], ku[10]; short yd, yn; ind = 0; for(i=0;i 414 ) goto two_or_more_errors; lerr[0] = j; /* pattern = (s0/s1)**(510+1) * s1 or pattern = (s0/s1)**(512 - 1 ) * s1 */ temp = gfi( r1 ); #ifndef NT5PORT { int i; for (i = 0; i < 9; i++) temp = gfmul( temp, temp ); /* deg = 512 */ } #else /*NT5PORT*/ for (i = 0; i < 9; i++) { temp = gfmul( temp, temp ); /* deg = 512 */ } #endif /*NT5PORT*/ verr[0] = gfmul( gfmul(temp, r1), s[1] ); return 1; /* 1 error */ two_or_more_errors: delta = gfmul( s[0], s[2] ) ^ gfmul( s[1], s[1] ); if( delta == 0 ) return -1; /* uncorrectable error */ temp = gfmul( s[1], s[3] ) ^ gfmul( s[2], s[2] ); if( temp == 0 ) return -1; /* uncorrectable error */ sigma2 = gfdiv( temp, delta ); temp = gfmul( s[1], s[2] ) ^ gfmul( s[0], s[3] ); if( temp == 0 ) return -1; /* uncorrectable error */ sigma1 = gfdiv( temp, delta ); k = gfdiv( sigma2, gfmul( sigma1, sigma1 ) ); unpack( k, 10, ku ); if( ku[2] != 0 ) return -1; xu[4] = ku[9]; xu[5] = ku[0] ^ ku[1]; xu[6] = ku[6] ^ ku[9]; xu[3] = ku[4] ^ ku[9]; xu[1] = ku[3] ^ ku[4] ^ ku[6]; xu[0] = ku[0] ^ xu[1]; xu[8] = ku[8] ^ xu[0]; xu[7] = ku[7] ^ xu[3] ^ xu[8]; xu[2] = ku[5] ^ xu[7] ^ xu[5] ^ xu[0]; xu[9] = 0; x1 = pack( xu, 10 ); x2 = x1 | 1; x1 = gfmul( sigma1, x1 ); x2 = gfmul( sigma1, x2 ); j1 = flog(x1); j2 = flog(x2); if( (j1 > 414) || (j2 > 414) ) return -1; r1 = x1 ^ x2; r2 = deg512( x1 ); temp = gfmul( x1, x1 ); r2 = gfdiv( r2, temp ); yd = gfmul( r2, r1 ); if( yd == 0 ) return -1; yn = gfmul( s[0], x2 ) ^ s[1]; if( yn == 0 ) return -1; verr[0] = gfdiv( yn, yd ); r2 = deg512( x2 ); temp = gfmul( x2, x2 ); r2 = gfdiv( r2, temp ); yd = gfmul( r2, r1 ); if( yd == 0 ) return -1; yn = gfmul( s[0], x1 ) ^ s[1]; if( yn == 0 ) return -1; verr[1] = gfdiv( yn, yd ); if( j1 > j2 ) { lerr[0] = j2; lerr[1] = j1; temp = verr[0]; verr[0] = verr[1]; verr[1] = temp; } else { lerr[0] = j1; lerr[1] = j2; } return 2; } /*------------------------------------------------------------------------------*/ /* Function Name: flDecodeEDC */ /* Purpose......: Trys to correct errors. */ /* errorSyndrom[] should contain the syndrom as 5 bytes and one */ /* parity byte. (identical to the output of calcEDCSyndrom()). */ /* Upon returning, errorNum will contain the number of errors, */ /* errorLocs[] will contain error locations, and */ /* errorVals[] will contain error values (to be XORed with the */ /* data). */ /* Parity error is relevant only if there are other errors, and */ /* the EDC code fails parity check. */ /* NOTE! Only the first errorNum indexes of the above two arrays */ /* are relevant. The others contain garbage. */ /* Returns......: The error status. */ /* NOTE! If the error status is NO_EDC_ERROR upon return, ignore */ /* the value of the arguments. */ /*------------------------------------------------------------------------------*/ EDCstatus flDecodeEDC(char *errorSyndrom, char *errorsNum, short errorLocs[3*T], short errorVals[3*T]) { short noferr; /* number of errors */ short dec_parity; /* parity byte of decoded word */ short rec_parity; /* parity byte of received word */ short realsynd[SYND_LEN]; /* real syndrom calculated from residue */ short locators[T], /* error locators */ values[T]; /* error values */ short reg[SYND_LEN]; /* register for main division procedure */ int i; RTLeightToTen(errorSyndrom, (unsigned short *)reg); rec_parity = errorSyndrom[5] & 0xFF; /* The parity byte */ residue_to_syndrom(reg, realsynd); noferr = decoder_for_2_errors(realsynd, locators, values); if(noferr == 0) return NO_EDC_ERROR; /* No error found */ if(noferr < 0) /* If an uncorrectable error was found */ return UNCORRECTABLE_ERROR; for (i=0;i