Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

552 lines
14 KiB

  1. /* HOOK. Fixed comments; otherwise impossible to compile */
  2. /*
  3. * $Log: V:/Flite/archives/TrueFFS5/Src/REEDSOL.C_V $
  4. *
  5. * Rev 1.3 Jul 13 2001 01:10:00 oris
  6. * Moved saved syndrome array definition (used by d2tst).
  7. *
  8. * Rev 1.2 Apr 09 2001 15:10:20 oris
  9. * End with an empty line.
  10. *
  11. * Rev 1.1 Apr 01 2001 08:00:14 oris
  12. * copywrite notice.
  13. *
  14. * Rev 1.0 Feb 04 2001 12:37:38 oris
  15. * Initial revision.
  16. *
  17. */
  18. /************************************************************************/
  19. /* */
  20. /* FAT-FTL Lite Software Development Kit */
  21. /* Copyright (C) M-Systems Ltd. 1995-2001 */
  22. /* */
  23. /************************************************************************/
  24. #include "reedsol.h"
  25. #define T 2 /* Number of recoverable errors */
  26. #define SYND_LEN (T*2) /* length of syndrom vector */
  27. #define K512 (((512+1)*8+6)/10) /* number of inf symbols for record
  28. of 512 bytes (K512=411) */
  29. #define N512 (K512 + SYND_LEN) /* code word length for record of 512 bytes */
  30. #define INIT_DEG 510
  31. #define MOD 1023
  32. #define BLOCK_SIZE 512
  33. #ifdef D2TST
  34. byte saveSyndromForDumping[SYNDROM_BYTES];
  35. #endif /* D2TST */
  36. static short gfi(short val);
  37. static short gfmul( short f, short s );
  38. static short gfdiv( short f, short s );
  39. static short flog(short val);
  40. static short alog(short val);
  41. /*------------------------------------------------------------------------------*/
  42. /* Function Name: RTLeightToTen */
  43. /* Purpose......: convert an array of five 8-bit values into an array of */
  44. /* four 10-bit values, from right to left. */
  45. /* Returns......: Nothing */
  46. /*------------------------------------------------------------------------------*/
  47. static void RTLeightToTen(char *reg8, unsigned short reg10[])
  48. {
  49. reg10[0] = (reg8[0] & 0xFF) | ((reg8[1] & 0x03) << 8);
  50. reg10[1] = ((reg8[1] & 0xFC) >> 2) | ((reg8[2] & 0x0F) << 6);
  51. reg10[2] = ((reg8[2] & 0xF0) >> 4) | ((reg8[3] & 0x3F) << 4);
  52. reg10[3] = ((reg8[3] & 0xC0) >> 6) | ((reg8[4] & 0xFF) << 2);
  53. }
  54. /*----------------------------------------------------------------------------*/
  55. static void unpack( short word, short length, short vector[] )
  56. /* */
  57. /* Function unpacks word into vector */
  58. /* */
  59. /* Parameters: */
  60. /* word - word to be unpacked */
  61. /* vector - array to be filled */
  62. /* length - number of bits in word */
  63. {
  64. short i, *ptr;
  65. ptr = vector + length - 1;
  66. for( i = 0; i < length; i++ )
  67. {
  68. *ptr-- = word & 1;
  69. word >>= 1;
  70. }
  71. }
  72. /*----------------------------------------------------------------------------*/
  73. static short pack( short *vector, short length )
  74. /* */
  75. /* Function packs vector into word */
  76. /* */
  77. /* Parameters: */
  78. /* vector - array to be packed */
  79. /* length - number of bits in word */
  80. {
  81. short tmp, i;
  82. vector += length - 1;
  83. tmp = 0;
  84. i = 1;
  85. while( length-- > 0 )
  86. {
  87. if( *vector-- )
  88. tmp |= i;
  89. i <<= 1;
  90. }
  91. return( tmp );
  92. }
  93. /*----------------------------------------------------------------------------*/
  94. static short gfi( short val) /* GF inverse */
  95. {
  96. return alog((short)(MOD-flog(val)));
  97. }
  98. /*----------------------------------------------------------------------------*/
  99. static short gfmul( short f, short s ) /* GF multiplication */
  100. {
  101. short i;
  102. if( f==0 || s==0 )
  103. return 0;
  104. else
  105. {
  106. i = flog(f) + flog(s);
  107. if( i > MOD ) i -= MOD;
  108. return( alog(i) );
  109. }
  110. }
  111. /*----------------------------------------------------------------------------*/
  112. static short gfdiv( short f, short s ) /* GF division */
  113. {
  114. return gfmul(f,gfi(s));
  115. }
  116. /*----------------------------------------------------------------------------*/
  117. static void residue_to_syndrom( short reg[], short realsynd[] )
  118. {
  119. short i,l,alpha,x,s,x4;
  120. short deg,deg4;
  121. for(i=0,deg=INIT_DEG;i<SYND_LEN;i++,deg++)
  122. {
  123. s = reg[0];
  124. alpha = x = alog(deg);
  125. deg4 = deg+deg;
  126. if( deg4 >= MOD ) deg4 -= MOD;
  127. deg4 += deg4;
  128. if( deg4 >= MOD ) deg4 -= MOD;
  129. x4 = alog(deg4);
  130. for(l=1;l<SYND_LEN;l++)
  131. {
  132. s ^= gfmul( reg[l], x );
  133. x = gfmul( alpha, x );
  134. }
  135. realsynd[i] = gfdiv( s, x4 );
  136. }
  137. }
  138. /*----------------------------------------------------------------------------*/
  139. static short alog(short i)
  140. {
  141. short j=0, val=1;
  142. for( ; j < i ; j++ )
  143. {
  144. val <<= 1 ;
  145. if ( val > 0x3FF )
  146. {
  147. if ( val & 8 ) val -= (0x400+7);
  148. else val -= (0x400-9);
  149. }
  150. }
  151. return val ;
  152. }
  153. static short flog(short val)
  154. {
  155. short j, val1;
  156. if (val == 0)
  157. return (short)0xFFFF;
  158. j=0;
  159. val1=1;
  160. for( ; j <= MOD ; j++ )
  161. {
  162. if (val1 == val)
  163. return j;
  164. val1 <<= 1 ;
  165. if ( val1 > 0x3FF )
  166. {
  167. if ( val1 & 8 ) val1 -= (0x400+7);
  168. else val1 -= (0x400-9);
  169. }
  170. }
  171. return 0;
  172. }
  173. /*----------------------------------------------------------------------------*/
  174. static short convert_to_byte_patterns( short *locators, short *values,
  175. short noferr, short *blocs, short *bvals )
  176. {
  177. static short mask[] = { 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };
  178. short i,j,n, n0, n1, tmp;
  179. short n_bit, n_byte, k_bit, nb;
  180. for( i = 0, nb = 0; i< noferr; i++)
  181. {
  182. n = locators[i];
  183. tmp = values[i];
  184. n_bit = n *10 - 6 ;
  185. n_byte = n_bit >> 3;
  186. k_bit = n_bit - (n_byte<<3);
  187. n_byte++;
  188. if( k_bit == 7 )
  189. {
  190. /* 3 corrupted bytes */
  191. blocs[nb] = n_byte+1;
  192. bvals[nb++] = tmp & 1 ? 0x80 : 0;
  193. tmp >>= 1;
  194. blocs[nb] = n_byte;
  195. bvals[nb++] = tmp & 0xff;
  196. tmp >>= 8;
  197. bvals[nb++] = tmp & 0xff;
  198. }
  199. else
  200. {
  201. n0 = 8 - k_bit;
  202. n1 = 10 - n0;
  203. blocs[nb] = n_byte;
  204. bvals[nb++] = (tmp & mask[n1]) << (8 - n1);
  205. tmp >>= n1;
  206. blocs[nb] = n_byte - 1;
  207. bvals[nb++] = (tmp & mask[n0]);
  208. }
  209. }
  210. for( i = 0, j = -1; i < nb; i++ )
  211. {
  212. if( bvals[i] == 0 ) continue;
  213. if( (blocs[i] == blocs[j]) && ( j>= 0 ) )
  214. {
  215. bvals[j] |= bvals[i];
  216. }
  217. else
  218. {
  219. j++;
  220. blocs[j] = blocs[i];
  221. bvals[j] = bvals[i];
  222. }
  223. }
  224. return j+1;
  225. }
  226. /*----------------------------------------------------------------------------*/
  227. static short deg512( short x )
  228. {
  229. short i;
  230. short l,m;
  231. l = flog(x);
  232. for( i=0;i<9;i++)
  233. {
  234. m = 0;
  235. if( (l & 0x200) )
  236. m = 1;
  237. l = ( ( l << 1 ) & 0x3FF ) | m;
  238. }
  239. return alog(l);
  240. }
  241. /*----------------------------------------------------------------------------*/
  242. static short decoder_for_2_errors( short s[], short lerr[], short verr[] )
  243. {
  244. /* decoder for correcting up to 2 errors */
  245. short i,j,k,temp,delta;
  246. short ind, x1, x2;
  247. short r1, r2, r3, j1, j2;
  248. short sigma1, sigma2;
  249. short xu[10], ku[10];
  250. short yd, yn;
  251. ind = 0;
  252. for(i=0;i<SYND_LEN;i++)
  253. if( s[i] != 0 )
  254. ind++; /* ind = number of nonzero syndrom symbols */
  255. if( ind == 0 ) return 0; /* no errors */
  256. if( ind < 4 )
  257. goto two_or_more_errors;
  258. /* checking s1/s0 = s2/s1 = s3/s2 = alpha**j for some j */
  259. r1 = gfdiv( s[1], s[0] );
  260. r2 = gfdiv( s[2], s[1] );
  261. r3 = gfdiv( s[3], s[2] );
  262. if( r1 != r2 || r2 != r3)
  263. goto two_or_more_errors;
  264. j = flog(r1);
  265. if( j > 414 )
  266. goto two_or_more_errors;
  267. lerr[0] = j;
  268. /* pattern = (s0/s1)**(510+1) * s1
  269. or
  270. pattern = (s0/s1)**(512 - 1 ) * s1 */
  271. temp = gfi( r1 );
  272. #ifndef NT5PORT
  273. {
  274. int i;
  275. for (i = 0; i < 9; i++)
  276. temp = gfmul( temp, temp ); /* deg = 512 */
  277. }
  278. #else /*NT5PORT*/
  279. for (i = 0; i < 9; i++)
  280. {
  281. temp = gfmul( temp, temp ); /* deg = 512 */
  282. }
  283. #endif /*NT5PORT*/
  284. verr[0] = gfmul( gfmul(temp, r1), s[1] );
  285. return 1; /* 1 error */
  286. two_or_more_errors:
  287. delta = gfmul( s[0], s[2] ) ^ gfmul( s[1], s[1] );
  288. if( delta == 0 )
  289. return -1; /* uncorrectable error */
  290. temp = gfmul( s[1], s[3] ) ^ gfmul( s[2], s[2] );
  291. if( temp == 0 )
  292. return -1; /* uncorrectable error */
  293. sigma2 = gfdiv( temp, delta );
  294. temp = gfmul( s[1], s[2] ) ^ gfmul( s[0], s[3] );
  295. if( temp == 0 )
  296. return -1; /* uncorrectable error */
  297. sigma1 = gfdiv( temp, delta );
  298. k = gfdiv( sigma2, gfmul( sigma1, sigma1 ) );
  299. unpack( k, 10, ku );
  300. if( ku[2] != 0 )
  301. return -1;
  302. xu[4] = ku[9];
  303. xu[5] = ku[0] ^ ku[1];
  304. xu[6] = ku[6] ^ ku[9];
  305. xu[3] = ku[4] ^ ku[9];
  306. xu[1] = ku[3] ^ ku[4] ^ ku[6];
  307. xu[0] = ku[0] ^ xu[1];
  308. xu[8] = ku[8] ^ xu[0];
  309. xu[7] = ku[7] ^ xu[3] ^ xu[8];
  310. xu[2] = ku[5] ^ xu[7] ^ xu[5] ^ xu[0];
  311. xu[9] = 0;
  312. x1 = pack( xu, 10 );
  313. x2 = x1 | 1;
  314. x1 = gfmul( sigma1, x1 );
  315. x2 = gfmul( sigma1, x2 );
  316. j1 = flog(x1);
  317. j2 = flog(x2);
  318. if( (j1 > 414) || (j2 > 414) )
  319. return -1;
  320. r1 = x1 ^ x2;
  321. r2 = deg512( x1 );
  322. temp = gfmul( x1, x1 );
  323. r2 = gfdiv( r2, temp );
  324. yd = gfmul( r2, r1 );
  325. if( yd == 0 )
  326. return -1;
  327. yn = gfmul( s[0], x2 ) ^ s[1];
  328. if( yn == 0 )
  329. return -1;
  330. verr[0] = gfdiv( yn, yd );
  331. r2 = deg512( x2 );
  332. temp = gfmul( x2, x2 );
  333. r2 = gfdiv( r2, temp );
  334. yd = gfmul( r2, r1 );
  335. if( yd == 0 )
  336. return -1;
  337. yn = gfmul( s[0], x1 ) ^ s[1];
  338. if( yn == 0 )
  339. return -1;
  340. verr[1] = gfdiv( yn, yd );
  341. if( j1 > j2 ) {
  342. lerr[0] = j2;
  343. lerr[1] = j1;
  344. temp = verr[0];
  345. verr[0] = verr[1];
  346. verr[1] = temp;
  347. }
  348. else
  349. {
  350. lerr[0] = j1;
  351. lerr[1] = j2;
  352. }
  353. return 2;
  354. }
  355. /*------------------------------------------------------------------------------*/
  356. /* Function Name: flDecodeEDC */
  357. /* Purpose......: Trys to correct errors. */
  358. /* errorSyndrom[] should contain the syndrom as 5 bytes and one */
  359. /* parity byte. (identical to the output of calcEDCSyndrom()). */
  360. /* Upon returning, errorNum will contain the number of errors, */
  361. /* errorLocs[] will contain error locations, and */
  362. /* errorVals[] will contain error values (to be XORed with the */
  363. /* data). */
  364. /* Parity error is relevant only if there are other errors, and */
  365. /* the EDC code fails parity check. */
  366. /* NOTE! Only the first errorNum indexes of the above two arrays */
  367. /* are relevant. The others contain garbage. */
  368. /* Returns......: The error status. */
  369. /* NOTE! If the error status is NO_EDC_ERROR upon return, ignore */
  370. /* the value of the arguments. */
  371. /*------------------------------------------------------------------------------*/
  372. EDCstatus flDecodeEDC(char *errorSyndrom, char *errorsNum,
  373. short errorLocs[3*T], short errorVals[3*T])
  374. {
  375. short noferr; /* number of errors */
  376. short dec_parity; /* parity byte of decoded word */
  377. short rec_parity; /* parity byte of received word */
  378. short realsynd[SYND_LEN]; /* real syndrom calculated from residue */
  379. short locators[T], /* error locators */
  380. values[T]; /* error values */
  381. short reg[SYND_LEN]; /* register for main division procedure */
  382. int i;
  383. RTLeightToTen(errorSyndrom, (unsigned short *)reg);
  384. rec_parity = errorSyndrom[5] & 0xFF; /* The parity byte */
  385. residue_to_syndrom(reg, realsynd);
  386. noferr = decoder_for_2_errors(realsynd, locators, values);
  387. if(noferr == 0)
  388. return NO_EDC_ERROR; /* No error found */
  389. if(noferr < 0) /* If an uncorrectable error was found */
  390. return UNCORRECTABLE_ERROR;
  391. for (i=0;i<noferr;i++)
  392. locators[i] = N512 - 1 - locators[i];
  393. *errorsNum = (char)convert_to_byte_patterns(locators, values, noferr, errorLocs, errorVals);
  394. for(dec_parity=i=0; i < *errorsNum; i++)/* Calculate the parity for all the */
  395. { /* errors found: */
  396. if(errorLocs[i] <= 512)
  397. dec_parity ^= errorVals[i];
  398. }
  399. if(dec_parity != rec_parity)
  400. return UNCORRECTABLE_ERROR; /* Parity error */
  401. else
  402. return CORRECTABLE_ERROR;
  403. }
  404. /*------------------------------------------------------------------------------*/
  405. /* Function Name: flCheckAndFixEDC */
  406. /* Purpose......: Decodes the EDC syndrom and fixs the errors if possible. */
  407. /* block[] should contain 512 bytes of data. */
  408. /* NOTE! Call this function only if errors where detected by */
  409. /* syndCalc or by the ASIC module. */
  410. /* Returns......: The error status. */
  411. /*------------------------------------------------------------------------------*/
  412. EDCstatus flCheckAndFixEDC(char FAR1 *block, char *syndrom, FLBoolean byteSwap)
  413. {
  414. char errorsNum;
  415. short errorLocs[3*T];
  416. short errorVals[3*T];
  417. EDCstatus status;
  418. status = flDecodeEDC(syndrom, &errorsNum, errorLocs, errorVals);
  419. if(status == CORRECTABLE_ERROR) /* Fix the errors if possible */
  420. {
  421. int i;
  422. for (i=0; i < errorsNum; i++)
  423. if( (errorLocs[i] ^ byteSwap) < BLOCK_SIZE ) /* Fix only in Data Area */
  424. block[errorLocs[i] ^ byteSwap] ^= errorVals[i];
  425. return NO_EDC_ERROR; /* All errors are fixed */
  426. }
  427. else
  428. return status; /* Uncorrectable error */
  429. }