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.

1867 lines
58 KiB

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <stdlib.h>
  4. #include <memory.h>
  5. #include <limits.h>
  6. #include "host.h"
  7. #include "tables.h"
  8. #include "tabdecls.h"
  9. #include "nabtsapi.h"
  10. #include "nabtslib.h"
  11. #include "nabtsprv.h"
  12. #if 1
  13. #define DEBUG_PRINT(x) /* nothing */
  14. #else
  15. #define DEBUG_PRINT(x) printf x
  16. #endif
  17. #ifndef DEBUG_FEC
  18. # define DEBUG_FEC_PRINT(x) /* nothing */
  19. #else
  20. # define DEBUG_FEC_PRINT(x) printf x
  21. #endif
  22. #ifdef PROFILE_VALIDATE
  23. int g_nValidate = 0;
  24. #endif
  25. /* A simple routine for computing the number of nonzero bits in an
  26. int. */
  27. int nzbits(unsigned int x) {
  28. int nz = 0;
  29. while (x) {
  30. nz++;
  31. x &= x-1;
  32. }
  33. return nz;
  34. }
  35. /* This table caches the results of nzbits(). */
  36. unsigned char nzbits_arr[256];
  37. /* Fill in nzbits_arr[] */
  38. void init_nzbits_arr() {
  39. int i;
  40. for (i = 0; i < 256; i++) {
  41. nzbits_arr[i] = nzbits(i);
  42. }
  43. }
  44. /* This table is straight out of the NABTS spec. */
  45. unsigned char hamming_encode[16] = {
  46. 0x15,
  47. 0x02,
  48. 0x49,
  49. 0x5e,
  50. 0x64,
  51. 0x73,
  52. 0x38,
  53. 0x2f,
  54. 0xd0,
  55. 0xc7,
  56. 0x8c,
  57. 0x9b,
  58. 0xa1,
  59. 0xb6,
  60. 0xfd,
  61. 0xea,
  62. };
  63. /* Hamming decoding simply looks up values in an array (for speed) */
  64. int decode_hamming(unsigned char val) {
  65. return decode_hamming_tab[val];
  66. }
  67. /* TODO - Dead code...should be removed. */
  68. int nabts_remove_parity(unsigned char *pVal) {
  69. unsigned char val = *pVal;
  70. int b1 = !!(val&1);
  71. int b2 = !!(val&2);
  72. int b3 = !!(val&4);
  73. int b4 = !!(val&8);
  74. int b5 = !!(val&16);
  75. int b6 = !!(val&32);
  76. int b7 = !!(val&64);
  77. int b8 = !!(val&128);
  78. int d = b8^b7^b6^b5^b4^b3^b2^b1;
  79. if (!d) {
  80. return 0;
  81. }
  82. *pVal = val&0x7f;
  83. return 1;
  84. }
  85. /* If the error csum_err was caused by a single-byte error, this
  86. routine will find the error location. See my external
  87. documentation for a description of the math; norpak_delta_inv[]
  88. contains the function P from the document. */
  89. int find_err_byte(int csum_err) {
  90. int pos0 = galois_log[csum_err>>8];
  91. int pos1 = galois_log[csum_err&0xff];
  92. int err_byte;
  93. if (pos0 == 255 || pos1 == 255) return 0xff;
  94. err_byte = norpak_delta_inv[(pos0 + 255 - pos1) % 255];
  95. return err_byte;
  96. }
  97. /* If there is a single-byte error, given the location of that error
  98. (computed by find_err_byte()), either of the checksum error bytes,
  99. and an indication of which checksum byte was passed in,
  100. this routine will compute the error (such that if the error
  101. is XOR'ed into the passed-in location, the checksum error will
  102. be 0). */
  103. int find_err_val(int err_byte, int byte_csum_err, int check_ind) {
  104. int lfsr_pos, offset, base_lfsr_pos;
  105. if (byte_csum_err == 0) return 0;
  106. lfsr_pos = galois_log[byte_csum_err];
  107. offset = log_norpak_coeffs[check_ind][err_byte];
  108. base_lfsr_pos = (lfsr_pos + 255 - offset) % 255;
  109. return galois_exp[base_lfsr_pos];
  110. }
  111. #define GALOIS_LOG0 512 /* == galois_log[0] */
  112. /* Null out a packet */
  113. void erase_packet(Stream *str, int i) {
  114. /* If we haven't seen a packet, it's missing. */
  115. str->horz[i].status = fec_status_missing;
  116. /* The algorithms actually work just as well if vals[] is not cleared;
  117. however, making a consistent initial state aids debugging. */
  118. memset(str->pack[i].vals, 0, 28);
  119. /* There is no horizontal checksum error (the checksum for a packet
  120. of all 0's is 0) */
  121. str->horz[i].err = 0;
  122. str->horz[i].errl[0] = GALOIS_LOG0;
  123. str->horz[i].errl[1] = GALOIS_LOG0;
  124. str->pack[i].not_full = -1;
  125. }
  126. /* When we see a packet, find the stream it belongs to. */
  127. Stream *lookup_stream(int stream_addr, NFECState *pState) {
  128. Stream *str = pState->streams;
  129. int i;
  130. while (str) {
  131. if (str->stream_addr == stream_addr) {
  132. return str;
  133. }
  134. str = str->next;
  135. }
  136. if ( !(str = (Stream*)alloc_mem(sizeof(Stream)) ) )
  137. {
  138. SASSERT(str!=0);
  139. return NULL;
  140. }
  141. /* Clear out the newly allocated Stream structure */
  142. memset(str, 0, sizeof(Stream));
  143. /* Claim that the last packet seen was packet index -1 */
  144. str->last_index = -1;
  145. str->stream_addr = stream_addr;
  146. str->next = pState->streams;
  147. str->count = 0;
  148. /* How long has it been since a packet was last seen on this stream? */
  149. str->dead_time = 0;
  150. for (i = 0; i < 32; i++) {
  151. erase_packet(str, i);
  152. }
  153. pState->streams = str;
  154. return str;
  155. }
  156. /* Write a packet into an NFECBundle structure, to be passed to the
  157. callback. */
  158. int packet_write(NFECBundle *pBundle, Stream *str, int line_no, int len) {
  159. memcpy(pBundle->packets[line_no].data, str->pack[line_no].vals, 28);
  160. /* How much valid data is there in this line? */
  161. pBundle->packets[line_no].len = len;
  162. /* Lines 14 and 15 never have "valid data"...they're always checksums */
  163. if (line_no == 14 || line_no == 15) {
  164. pBundle->packets[line_no].len = 0;
  165. }
  166. #ifdef DEBUG_FEC
  167. pBundle->packets[line_no].line = str->pack[line_no].line;
  168. pBundle->packets[line_no].frame = str->pack[line_no].frame;
  169. #endif //DEBUG_FEC
  170. switch (str->horz[line_no].status) {
  171. case fec_status_ok:
  172. pBundle->packets[line_no].status = NFEC_OK;
  173. return 1;
  174. case fec_status_missing:
  175. default:
  176. pBundle->packets[line_no].status = NFEC_BAD;
  177. pBundle->packets[line_no].len = 0;
  178. return 0;
  179. }
  180. #if 0
  181. #ifndef linux
  182. if (str->stream_addr == 0x242) {
  183. for (i = 0; i < len; i++) {
  184. vbichar_input(str->pack[line_no].vals[i]);
  185. }
  186. }
  187. #if 1
  188. if (str->stream_addr == 0x500) {
  189. for (i = 0; i < len; i++) {
  190. addone(str->pack[line_no].vals[i]);
  191. }
  192. }
  193. #endif
  194. #endif
  195. #endif
  196. }
  197. /* inf->err has just been changed; adjust the status and the error
  198. correction status based on it. len is 26 for horizontal checksums,
  199. 14 for vertical. */
  200. fec_stat update_fec_inf(fec_info *inf, int len) {
  201. int err = inf->err;
  202. int byte;
  203. /* We don't want to change fec_status_missing into another status. */
  204. if (inf->status == fec_status_missing) {
  205. return FEC_UNCORRECTABLE;
  206. }
  207. /* Yay! A good row/column! */
  208. if (err == 0) {
  209. inf->status = fec_status_ok;
  210. return FEC_OK;
  211. }
  212. /* If this is caused by a single-byte error, it's an error in
  213. the checksum itself. */
  214. if (err>>8 == 0) {
  215. inf->status = fec_status_onebyte;
  216. inf->byte[0] = len+1;
  217. inf->byte_val[0] = err;
  218. inf->score = nzbits_arr[err];
  219. /* If the score is <= 2, then no 2-byte correction can have a
  220. better score. */
  221. inf->really_onebyte = (inf->score <= 2);
  222. return FEC_CORRECTABLE;
  223. }
  224. /* If this is caused by a single-byte error, it's an error in
  225. the checksum itself. */
  226. if ((err & 0xff) == 0) {
  227. inf->status = fec_status_onebyte;
  228. inf->byte[0] = len;
  229. inf->byte_val[0] = err>>8;
  230. inf->score = nzbits_arr[err>>8];
  231. /* If the score is <= 2, then no 2-byte correction can have a
  232. better score. */
  233. inf->really_onebyte = (inf->score <= 2);
  234. return FEC_CORRECTABLE;
  235. }
  236. byte = find_err_byte(err);
  237. if (byte < len) {
  238. /* Yes, there is a single-byte error which explains this checksum error. */
  239. int err_val = find_err_val(byte, err>>8, 0);
  240. inf->status = fec_status_onebyte;
  241. inf->byte[0] = byte;
  242. inf->byte_val[0] = err_val;
  243. inf->score = nzbits_arr[err_val];
  244. /* If the score is <= 2, then no 2-byte correction can have a
  245. better score. */
  246. inf->really_onebyte = (inf->score <= 2);
  247. return FEC_CORRECTABLE;
  248. } else {
  249. /* No single-byte error can explain this checksum error. If we
  250. care, we can compute the optimal 2-byte correction later. */
  251. inf->status = fec_status_multibyte;
  252. inf->score = 17;
  253. return FEC_UNCORRECTABLE;
  254. }
  255. }
  256. /* Multiply a Galois coefficient (as in the contents of the
  257. inv2_coeffs struct) by a Galois value. */
  258. #define GALOIS_MULT_COEFF(x, y) (galois_exp[x + galois_log[y]])
  259. typedef struct {
  260. unsigned short v00, v01, v10, v11;
  261. } inv2_coeffs;
  262. inv2_coeffs coeffs_tab[28][28];
  263. /* Given the byte positions b1 and b2, and the packet length len,
  264. fill in coeffs with the coefficients. These coefficients let
  265. you efficiently compute the values to XOR with the bytes at
  266. positions b1 and b2 from the checksum error bytes.
  267. See my external document (the section on "Correcting Double-byte
  268. Erasures") for a description of the math involved here. */
  269. void orig_compute_inv2_coeffs(int b1, int b2, inv2_coeffs *coeffs, int len) {
  270. SASSERT(b1 >= 0);
  271. SASSERT(b1 < len+2);
  272. SASSERT(b2 >= 0);
  273. SASSERT(b2 < len+2);
  274. SASSERT(len == 14 || len == 26);
  275. SASSERT(b1 < b2);
  276. if (b1 >= len) {
  277. /* Both bytes are FEC bytes. The output bytes will simply be
  278. the checksum error bytes. */
  279. coeffs->v00 = 1;
  280. coeffs->v01 = 0;
  281. coeffs->v10 = 0;
  282. coeffs->v11 = 1;
  283. } else if (b2 >= len) {
  284. /* b1 is not FEC, but b2 is. One of the output bytes will be
  285. a checksum error byte; the other will be computed as by
  286. find_err_val(). */
  287. if (b2 == len) {
  288. coeffs->v00 = 0;
  289. coeffs->v01 = galois_exp[255 - log_norpak_coeffs[1][b1]];
  290. coeffs->v10 = 1;
  291. coeffs->v11 = galois_exp[log_norpak_coeffs[0][b1] +
  292. 255 - log_norpak_coeffs[1][b1]];
  293. } else {
  294. coeffs->v00 = galois_exp[255 - log_norpak_coeffs[0][b1]];
  295. coeffs->v01 = 0;
  296. coeffs->v10 = galois_exp[log_norpak_coeffs[1][b1] +
  297. 255 - log_norpak_coeffs[0][b1]];
  298. coeffs->v11 = 1;
  299. }
  300. } else {
  301. /* Neither b1 nor b2 is an FEC byte. */
  302. SASSERT(b2 < len);
  303. {
  304. int err_coeff0_inv;
  305. int e00, e01;
  306. int err_coeff1_inv;
  307. int e10, e11;
  308. err_coeff0_inv = galois_log[galois_exp[log_norpak_coeffs[0][b1] + 255 -
  309. log_norpak_coeffs[0][b2]] ^
  310. galois_exp[log_norpak_coeffs[1][b1] + 255 -
  311. log_norpak_coeffs[1][b2]]];
  312. e00 = 255 + 255 - err_coeff0_inv - log_norpak_coeffs[0][b2];
  313. e01 = 255 + 255 - err_coeff0_inv - log_norpak_coeffs[1][b2];
  314. err_coeff1_inv = galois_log[galois_exp[log_norpak_coeffs[0][b2] + 255 -
  315. log_norpak_coeffs[0][b1]] ^
  316. galois_exp[log_norpak_coeffs[1][b2] + 255 -
  317. log_norpak_coeffs[1][b1]]];
  318. e10 = 255 + 255 - err_coeff1_inv - log_norpak_coeffs[0][b1];
  319. e11 = 255 + 255 - err_coeff1_inv - log_norpak_coeffs[1][b1];
  320. coeffs->v00 = galois_exp[e00];
  321. coeffs->v01 = galois_exp[e01];
  322. coeffs->v10 = galois_exp[e10];
  323. coeffs->v11 = galois_exp[e11];
  324. }
  325. }
  326. /* Precompute the galois_log for slightly more efficient execution
  327. later. */
  328. coeffs->v00 = galois_log[coeffs->v00];
  329. coeffs->v01 = galois_log[coeffs->v01];
  330. coeffs->v10 = galois_log[coeffs->v10];
  331. coeffs->v11 = galois_log[coeffs->v11];
  332. }
  333. /* Cache the result of orig_compute_inv2_coeffs() over all possible
  334. values. */
  335. void init_inv2_coeffs() {
  336. int b1;
  337. int b2;
  338. for (b1 = 0; b1 < 27; b1++) {
  339. for (b2 = b1+1; b2 < 28; b2++) {
  340. orig_compute_inv2_coeffs(b1, b2, &coeffs_tab[b1][b2], 26);
  341. }
  342. }
  343. }
  344. inline void compute_inv2_coeffs(int b1, int b2, inv2_coeffs *coeffs, int len) {
  345. /* comment out ASSERTs for speed */
  346. #if 0
  347. SASSERT(b1 >= 0);
  348. SASSERT(b1 < len+2);
  349. SASSERT(b2 >= 0);
  350. SASSERT(b2 < len+2);
  351. SASSERT(len == 14 || len == 26);
  352. SASSERT(b1 < b2);
  353. #endif
  354. /* If you're looking at the FEC bytes of a column, find the
  355. coefficients that were computed for looking at the corresponding
  356. FEC bytes of a row. */
  357. if (len == 14) {
  358. if (b1 >= 14) {
  359. b1 += 26-14;
  360. }
  361. if (b2 >= 14) {
  362. b2 += 26-14;
  363. }
  364. }
  365. *coeffs = coeffs_tab[b1][b2];
  366. }
  367. /* ANSI C preprocessor magic for creating new names */
  368. #define TOKPASTE(a, b) a##b
  369. #define STRIDE 1
  370. #define STRIDENAM(x) TOKPASTE(x,_horiz)
  371. /* Create "_horiz" versions of checksum functions. */
  372. #include "hvchecks.c"
  373. #undef STRIDE
  374. #undef STRIDENAM
  375. #define STRIDE (sizeof(Packet))
  376. #define STRIDENAM(x) TOKPASTE(x,_vert)
  377. /* Create "_vert" versions of checksum functions. */
  378. #include "hvchecks.c"
  379. #undef STRIDE
  380. #undef STRIDENAM
  381. /* TODO - Dead code...should be removed. */
  382. fec_error_class check_fec(unsigned char data[28]) {
  383. int check = compute_csum_horiz(data, 26);
  384. int err = check ^ (data[26] << 8 | data[27]);
  385. int byte;
  386. if (err == 0) {
  387. return fec_errs_0;
  388. }
  389. if (err>>8 == 0) {
  390. return (nzbits_arr[err&0xff] > 1 ? fec_errs_multiple : fec_errs_1);
  391. }
  392. if ((err & 0xff) == 0) {
  393. return (nzbits_arr[err>>8] > 1 ? fec_errs_multiple : fec_errs_1);
  394. }
  395. byte = find_err_byte(err);
  396. if (byte < 26) {
  397. int err_val = find_err_val(byte, err>>8, 0);
  398. return (nzbits_arr[err_val] > 1 ? fec_errs_multiple : fec_errs_1);
  399. }
  400. return fec_errs_multiple;
  401. }
  402. /* Find the "optimal" corrections for the FEC info, taking into
  403. account that we don't allow ourselves to change a valid row/column.
  404. This function is called twice, once to find the optimal corrections
  405. for the rows and once for the columns; "us" and "them" switch places
  406. for the two calls.
  407. This routine can be quite timeconsuming; and it's worse on somewhat
  408. noisy signals (where it's less likely to be helpful). However, it
  409. can't simply be bypassed, because subsequent code assumes that it
  410. can use the information in the fec_info to correct an arbitrary
  411. row/column (i.e., the status must be either fec_status_onebyte or
  412. fec_status_2byte, and the byte[] and byte_val[] values must be set
  413. correctly). Thus, if the "really_search" flag is set to 0, all
  414. searching is bypassed and the routine simply finds any valid
  415. correction. */
  416. void validate_twobyte_both(fec_info *us, fec_info *them, int us_len, int them_len, int really_search) {
  417. int active[28];
  418. int nActive = 0;
  419. {
  420. int i;
  421. for (i = 0; i < us_len; i++) {
  422. if (us[i].status == fec_status_onebyte) {
  423. if (them[us[i].byte[0]].status == fec_status_ok) {
  424. /* We can't use this correction; it would invalidate the
  425. row/column going in the other direction. */
  426. us[i].status = fec_status_multibyte;
  427. us[i].score = 17;
  428. active[nActive++] = i;
  429. } else {
  430. if (!us[i].really_onebyte) {
  431. /* Check to see if the one-byte correction is optimal. */
  432. active[nActive++] = i;
  433. }
  434. }
  435. } else if (us[i].status == fec_status_multibyte) {
  436. us[i].score = 17;
  437. active[nActive++] = i;
  438. } else if (us[i].status == fec_status_2byte) {
  439. if (them[us[i].byte[0]].status == fec_status_ok ||
  440. them[us[i].byte[1]].status == fec_status_ok) {
  441. /* We can't use this correction; it would invalidate a
  442. row/column going in the other direction. */
  443. us[i].status = fec_status_multibyte;
  444. us[i].score = 17;
  445. active[nActive++] = i;
  446. }
  447. } else if (us[i].status == fec_status_ok) {
  448. /* do nothing */
  449. } else {
  450. SASSERT(us[i].status == fec_status_missing);
  451. }
  452. }
  453. }
  454. if (nActive == 0) {
  455. /* Nothing to do... */
  456. return;
  457. }
  458. {
  459. int b1, b2;
  460. /* Loop over all pairs of byte positions where the row/column
  461. in the other direction is not already valid. Compute
  462. b1c and b2c; this pulls the check for FEC bytes of a column
  463. (in compute_inv2_coeffs()) out of the inner loop. */
  464. for (b1 = 0; b1 < them_len-1; b1++) {
  465. if (them[b1].status != fec_status_ok) {
  466. int b1c = (them_len == 16 && b1 >= 14) ? b1+(28-16) : b1;
  467. for (b2 = b1+1; b2 < them_len; b2++) {
  468. if (them[b2].status != fec_status_ok) {
  469. int b2c = (them_len == 16 && b2 >= 14) ? b2+(28-16) : b2;
  470. int act;
  471. inv2_coeffs coeffs;
  472. #ifdef MISSING_ZERO_COST
  473. int one_missing = (them[b1].status == fec_status_missing ||
  474. them[b2].status == fec_status_missing);
  475. #endif
  476. compute_inv2_coeffs(b1c, b2c, &coeffs, 28-2);
  477. /* Loop through the fec_info's which need to be checked... */
  478. for (act = 0; act < nActive; act++) {
  479. int i = active[act];
  480. /* Compute the two XOR values. */
  481. int ch1 =
  482. galois_exp[coeffs.v00 + us[i].errl[0]] ^
  483. galois_exp[coeffs.v01 + us[i].errl[1]];
  484. int ch2 =
  485. galois_exp[coeffs.v10 + us[i].errl[0]] ^
  486. galois_exp[coeffs.v11 + us[i].errl[1]];
  487. int score;
  488. #ifdef PROFILE_VALIDATE
  489. g_nValidate++;
  490. #endif
  491. #ifdef MISSING_ZERO_COST
  492. /* This code sets the cost of changing a byte in
  493. a missing row to 0. When I tested this, it
  494. wasn't a clear win, so I took it back out. */
  495. if (one_missing) {
  496. if (them[b1].status == fec_status_missing) {
  497. score = nzbits_arr[ch2];
  498. } else {
  499. score = nzbits_arr[ch1];
  500. }
  501. } else {
  502. #endif
  503. /* find the score of the current correction */
  504. score = nzbits_arr[ch1] + nzbits_arr[ch2];
  505. #ifdef MISSING_ZERO_COST
  506. }
  507. #endif
  508. if (score < us[i].score) {
  509. /* We found a better score; record the data. */
  510. us[i].status = fec_status_2byte;
  511. us[i].score = score;
  512. us[i].byte[0] = b1;
  513. us[i].byte_val[0] = ch1;
  514. us[i].byte[1] = b2;
  515. us[i].byte_val[1] = ch2;
  516. }
  517. }
  518. if (!really_search) {
  519. /* We found a single correction; the fec_info is now valid.
  520. Break out of the search. */
  521. goto search_done;
  522. }
  523. }
  524. }
  525. }
  526. }
  527. }
  528. search_done:
  529. {
  530. int i;
  531. for (i = 0; i < us_len; i++) {
  532. /* We'd better have changed all the fec_status_multibyte
  533. to fec_status_2byte... */
  534. SASSERT(us[i].status != fec_status_multibyte);
  535. if (us[i].status == fec_status_onebyte) {
  536. /* If we didn't find a two-byte correction with a better
  537. score than this, then this really is the best correction. */
  538. us[i].really_onebyte = 1;
  539. } else if (us[i].status == fec_status_2byte) {
  540. /* If the best two-byte correction actually only changed
  541. one byte, downgrade it to a one-byte correction.
  542. (TODO - This should never happen, should it? ) */
  543. if (us[i].byte_val[0] == 0) {
  544. us[i].status = fec_status_onebyte;
  545. us[i].really_onebyte = 1;
  546. us[i].byte[0] = us[i].byte[1];
  547. us[i].byte_val[0] = us[i].byte_val[1];
  548. } else if (us[i].byte_val[1] == 0) {
  549. us[i].status = fec_status_onebyte;
  550. us[i].really_onebyte = 1;
  551. }
  552. }
  553. }
  554. }
  555. }
  556. /* We've got all the packets we're going to get in this bundle;
  557. run FEC correction on it and pass it back to the callback. */
  558. void complete_bundle(Stream *str, NFECCallback cb, void *ctx, NFECState *st) {
  559. int i;
  560. int bits_changed = 0;
  561. int total_missing;
  562. {
  563. /* Update the vertical fec_info's. (The horizontal fec_info's were
  564. set as the packets were placed into the bundle.) */
  565. for (i = 0; i < 28; i++) {
  566. check_checksum_vert(&(str->pack[0].vals[i]), 14, &(st->vert[i]));
  567. }
  568. }
  569. {
  570. int n_missing = 0;
  571. /* Count the missing packets */
  572. for (i = 0; i < 16; i++) {
  573. if (str->horz[i].status == fec_status_missing) {
  574. n_missing++;
  575. }
  576. }
  577. total_missing = n_missing;
  578. DEBUG_FEC_PRINT(("|| Completing bundle (%d missing)\n", n_missing));
  579. if (n_missing <= 1) {
  580. /* There are 0 or 1 missing packets; run the standard FEC processing. */
  581. /* How many columns are not valid? */
  582. int vert_nok = 28;
  583. /* How many rows are not valid? */
  584. int horz_nok = 16;
  585. /* Do we need to call validate_twobyte_both()? */
  586. int twobyte_valid = 0;
  587. /* Find the actual values of horz_nok and vert_nok */
  588. for (i = 0; i < 16; i++) {
  589. if (str->horz[i].status == fec_status_ok) {
  590. horz_nok--;
  591. }
  592. }
  593. for (i = 0; i < 28; i++) {
  594. if (st->vert[i].status == fec_status_ok) {
  595. vert_nok--;
  596. }
  597. }
  598. while (vert_nok || horz_nok) {
  599. /* There are at least some rows or columns which are not OK. */
  600. /* The following code is almost exactly the same for rows and
  601. for column. However, it uses too many of the local
  602. variables from this function to be conveniently extracted
  603. out into a separate function. So, I created a macro for it.
  604. (I use this technique later, as well.) */
  605. #define CHECK_ALMOST_OK(us, us_nok, us_len) \
  606. if (us_nok == 0) { \
  607. /* Panic! All our packets are OK, but some packets in the \
  608. other direction are not. According to my assumptions, \
  609. this is extremely unlikely (although it could happen that \
  610. all horizontal packets are OK and vertical packets are \
  611. not OK if packets from two different bundles are mixed). \
  612. Let's just smash the checksums, so that at least we end \
  613. up with a valid bundle. */ \
  614. us[us_len-2].status = fec_status_missing; \
  615. us[us_len-1].status = fec_status_missing; \
  616. us_nok = 2; \
  617. continue; \
  618. } \
  619. \
  620. if (us_nok == 1) { \
  621. /* Again, this is quite unlikely, and I don't handle it well. */ \
  622. if (us[us_len-2].status == fec_status_ok) { \
  623. us[us_len-2].status = fec_status_missing; \
  624. us_nok++; \
  625. } else { \
  626. us[us_len-1].status = fec_status_missing; \
  627. us_nok++; \
  628. } \
  629. continue; \
  630. }
  631. CHECK_ALMOST_OK(st->vert, vert_nok, 28);
  632. CHECK_ALMOST_OK(str->horz, horz_nok, 16);
  633. /* OK, now we're back to the realm in which I'm comfortable:
  634. there are at least two non-OK packets in each direction.
  635. If there are exactly two non-OK packets in either direction,
  636. then we're done...we can just finish it off right now. */
  637. #define horz_byte(h, v) (str->pack[v].vals[h])
  638. #define vert_byte(v, h) (str->pack[v].vals[h])
  639. #define horz_hinf(h, v) (str->horz[v])
  640. #define vert_hinf(v, h) (str->horz[v])
  641. #define CHECK_US_2NOK(us, us_nok, us_len, us_nok_label, them, them_nok, them_len, byte_val, hinf) \
  642. if (us_nok == 2) { \
  643. /* Yes, there are exactly two missing packets in our \
  644. direction. Locate them and fill them in. */ \
  645. int b1, b2; \
  646. int i, j; \
  647. \
  648. for (i = 0; i < us_len; i++) { \
  649. if (us[i].status != fec_status_ok) { \
  650. b1 = i; \
  651. for (j = i+1; j < us_len; j++) { \
  652. if (us[j].status != fec_status_ok) { \
  653. b2 = j; \
  654. goto us_nok_label; \
  655. } \
  656. } \
  657. SASSERT(0); \
  658. } \
  659. } \
  660. SASSERT(0); \
  661. \
  662. us_nok_label: \
  663. /* OK, the two missing packets are at byte positions b1 and b2. \
  664. Let's figure out how to fix these bytes, given the "err" \
  665. values. */ \
  666. { \
  667. inv2_coeffs coeffs; \
  668. \
  669. compute_inv2_coeffs(b1, b2, &coeffs, us_len-2); \
  670. \
  671. for (i = 0; i < them_len; i++) { \
  672. int err = them[i].err; \
  673. int ch1 = \
  674. GALOIS_MULT_COEFF(coeffs.v00, err>>8) ^ \
  675. GALOIS_MULT_COEFF(coeffs.v01, err&0xff); \
  676. int ch2 = \
  677. GALOIS_MULT_COEFF(coeffs.v10, err>>8) ^ \
  678. GALOIS_MULT_COEFF(coeffs.v11, err&0xff); \
  679. byte_val(i, b1) ^= ch1; \
  680. byte_val(i, b2) ^= ch2; \
  681. if (them[i].status != fec_status_ok) { \
  682. if (hinf(i, b1).status != fec_status_missing) { \
  683. bits_changed += nzbits_arr[ch1]; \
  684. } \
  685. if (hinf(i, b2).status != fec_status_missing) { \
  686. bits_changed += nzbits_arr[ch2]; \
  687. } \
  688. them[i].status = fec_status_ok; \
  689. them_nok--; \
  690. } \
  691. } \
  692. } \
  693. \
  694. us[b1].status = fec_status_ok; \
  695. us_nok--; \
  696. us[b2].status = fec_status_ok; \
  697. us_nok--; \
  698. continue; \
  699. }
  700. CHECK_US_2NOK(st->vert, vert_nok, 28, found_vert_nok, str->horz, horz_nok, 16, vert_byte, vert_hinf);
  701. CHECK_US_2NOK(str->horz, horz_nok, 16, found_horz_nok, st->vert, vert_nok, 28, horz_byte, horz_hinf);
  702. /* At this point, there are at least three "not OK" vertical
  703. and horizontal packets. We want to pick one of these and
  704. make it OK.
  705. We want to pick changes which we believe are the most likely
  706. to be correct. To this end, I've divided the possible
  707. changes into a few categories. These are rated from the
  708. best (most likely to be correct) to the worst.
  709. 1) Single-byte changes which fix both a row and a column.
  710. 2) Single-byte changes which fix a column and occur in a
  711. "missing" row.
  712. 3) The change to a row or column which fixes it and which
  713. uses the least numbers of bits.
  714. */
  715. {
  716. int fix_row = 0;
  717. int fix_col = 0;
  718. int fix_val = 0;
  719. #if 1
  720. for (i = 0; i < 16; i++) {
  721. if (str->horz[i].status == fec_status_onebyte &&
  722. st->vert[str->horz[i].byte[0]].status == fec_status_onebyte &&
  723. st->vert[str->horz[i].byte[0]].byte[0] == i &&
  724. st->vert[str->horz[i].byte[0]].byte_val[0] == str->horz[i].byte_val[0]) {
  725. /* Both the row and the column involved here want to make
  726. the same change to the same byte; probably a good idea. */
  727. fix_row = i;
  728. fix_col = str->horz[i].byte[0];
  729. fix_val = str->horz[i].byte_val[0];
  730. SASSERT(fix_val != 0);
  731. goto do_fix;
  732. }
  733. }
  734. #else
  735. #define STATUS_TO_LIMIT(stat) ((stat == fec_status_2byte) ? 2 : 1)
  736. /* This heuristic is not a clear win over the one above;
  737. further experimentation is necessary. */
  738. {
  739. int best_score = INT_MAX;
  740. for (i = 0; i < 16; i++) {
  741. if (str->horz[i].status == fec_status_onebyte ||
  742. str->horz[i].status == fec_status_2byte) {
  743. int hpos;
  744. for (hpos = 0;
  745. hpos < STATUS_TO_LIMIT(str->horz[i].status);
  746. hpos++) {
  747. int hbyte = str->horz[i].byte[hpos];
  748. int hbyte_val = str->horz[i].byte_val[hpos];
  749. if (st->vert[hbyte].status == fec_status_onebyte ||
  750. st->vert[hbyte].status == fec_status_2byte) {
  751. int vpos;
  752. for (vpos = 0;
  753. vpos < STATUS_TO_LIMIT(st->vert[i].status);
  754. vpos++) {
  755. if (st->vert[hbyte].byte[vpos] == i &&
  756. st->vert[hbyte].byte_val[vpos] == hbyte_val) {
  757. int score = 16*((str->horz[i].status == fec_status_2byte) +
  758. (st->vert[hbyte].status == fec_status_2byte)) +
  759. nzbits_arr[hbyte_val];
  760. if (score < best_score) {
  761. fix_row = i;
  762. fix_col = hbyte;
  763. fix_val = hbyte_val;
  764. best_score = score;
  765. }
  766. }
  767. }
  768. }
  769. }
  770. }
  771. }
  772. if (best_score < INT_MAX) {
  773. SASSERT(fix_val != 0);
  774. goto do_fix;
  775. }
  776. }
  777. #endif
  778. for (i = 0; i < 28; i++) {
  779. if (st->vert[i].status == fec_status_onebyte &&
  780. str->horz[st->vert[i].byte[0]].status == fec_status_missing) {
  781. /* This column wants to make a change in a "missing" row.
  782. Let it. */
  783. fix_row = st->vert[i].byte[0];
  784. fix_col = i;
  785. fix_val = st->vert[i].byte_val[0];
  786. SASSERT(fix_val != 0);
  787. goto do_fix;
  788. }
  789. }
  790. {
  791. int prefer_vert;
  792. int best_score = INT_MAX;
  793. /* If there are more invalid columns than rows, then
  794. prefer (slightly) to fix columns. (This is because
  795. it's less likely that random noise in the invalid rows
  796. would make a column with a low-score correction than
  797. vice versa, so if we find a low-score correction, it's
  798. somewhat more likely to be what we want. */
  799. if (vert_nok >= horz_nok) {
  800. prefer_vert = 1;
  801. } else {
  802. prefer_vert = 0;
  803. }
  804. /* Find the best score. As we're searching, determine
  805. whether we might need to call validate_twobyte_both().
  806. We simply find the row or column which needs the fewest
  807. number of bits corrected to become valid; except that
  808. if there's a tie between a row and a column, we break it
  809. according to prefer_vert. */
  810. for (i = 0; i < 16; i++) {
  811. if (str->horz[i].status == fec_status_onebyte) {
  812. if (!str->horz[i].really_onebyte) {
  813. twobyte_valid = 0;
  814. }
  815. if (st->vert[str->horz[i].byte[0]].status != fec_status_ok) {
  816. int score = str->horz[i].score*2 + prefer_vert;
  817. if (score < best_score) {
  818. best_score = score;
  819. fix_row = i;
  820. fix_col = str->horz[i].byte[0];
  821. fix_val = str->horz[i].byte_val[0];
  822. }
  823. } else {
  824. twobyte_valid = 0;
  825. }
  826. } else if (str->horz[i].status == fec_status_2byte) {
  827. if (st->vert[str->horz[i].byte[0]].status != fec_status_ok &&
  828. st->vert[str->horz[i].byte[1]].status != fec_status_ok) {
  829. int score = str->horz[i].score*2 + prefer_vert;
  830. if (score < best_score) {
  831. best_score = score;
  832. fix_row = i;
  833. fix_col = str->horz[i].byte[0];
  834. fix_val = str->horz[i].byte_val[0];
  835. }
  836. } else {
  837. twobyte_valid = 0;
  838. }
  839. }
  840. }
  841. for (i = 0; i < 28; i++) {
  842. if (st->vert[i].status == fec_status_onebyte) {
  843. if (!st->vert[i].really_onebyte) {
  844. twobyte_valid = 0;
  845. }
  846. if (str->horz[st->vert[i].byte[0]].status != fec_status_ok) {
  847. int score = st->vert[i].score*2 + (1-prefer_vert);
  848. if (score < best_score) {
  849. best_score = score;
  850. fix_row = st->vert[i].byte[0];
  851. fix_col = i;
  852. fix_val = st->vert[i].byte_val[0];
  853. }
  854. } else {
  855. twobyte_valid = 0;
  856. }
  857. } else if (st->vert[i].status == fec_status_2byte) {
  858. if (str->horz[st->vert[i].byte[0]].status != fec_status_ok &&
  859. str->horz[st->vert[i].byte[1]].status != fec_status_ok) {
  860. int score = st->vert[i].score*2 + (1-prefer_vert);
  861. if (score < best_score) {
  862. best_score = score;
  863. fix_row = st->vert[i].byte[0];
  864. fix_col = i;
  865. fix_val = st->vert[i].byte_val[0];
  866. }
  867. } else {
  868. twobyte_valid = 0;
  869. }
  870. }
  871. }
  872. if (best_score < 6 ||
  873. (best_score < INT_MAX && twobyte_valid)) {
  874. /* If we found a fix with a score < 6, then it has
  875. either 1 or 2 bit errors; calling
  876. validate_twobyte_both() can't find a better
  877. correction (lower number of bit errors).
  878. (Actually, if we found a fix with a score of 5, we could
  879. potentially improve it by finding a 2 error fix in
  880. the other direction, which would have a score of 4.) */
  881. SASSERT(fix_val != 0);
  882. goto do_fix;
  883. }
  884. /* Don't search if there's more than 10 invalid rows/columns
  885. in the opposite direction (which would mean 55 or more
  886. pairs of error positions). */
  887. validate_twobyte_both(str->horz, st->vert, 16, 28, vert_nok<=10);
  888. validate_twobyte_both(st->vert, str->horz, 28, 16, horz_nok<=10);
  889. twobyte_valid = 1;
  890. continue;
  891. }
  892. /* At this point, there's really not much we can do...we don't
  893. have any plausible changes to make. Let's just change
  894. something at random. */
  895. /* TODO - We should never get here... */
  896. {
  897. int col;
  898. for (col = 0; col < 28; col++) {
  899. if (st->vert[col].status != fec_status_ok) {
  900. int b1, b2;
  901. for (b1 = 0; b1 < 16; b1++) {
  902. if (str->horz[b1].status != fec_status_ok) {
  903. for (b2 = b1+1; b2 < 16; b2++) {
  904. if (str->horz[b2].status != fec_status_ok) {
  905. inv2_coeffs coeffs;
  906. int err = st->vert[col].err;
  907. compute_inv2_coeffs(b1, b2, &coeffs, 14);
  908. fix_row = b1;
  909. fix_col = col;
  910. fix_val = GALOIS_MULT_COEFF(coeffs.v00, err>>8) ^
  911. GALOIS_MULT_COEFF(coeffs.v01, err&0xff);
  912. SASSERT(fix_val != 0);
  913. goto do_fix;
  914. }
  915. }
  916. SASSERT(0);
  917. }
  918. }
  919. SASSERT(0);
  920. }
  921. }
  922. SASSERT(0);
  923. }
  924. do_fix:
  925. SASSERT(str->horz[fix_row].status != fec_status_ok);
  926. SASSERT(st->vert[fix_col].status != fec_status_ok);
  927. SASSERT(fix_val != 0);
  928. {
  929. /* We've decided on a change to make. Update the fec_inf's
  930. and actually make the change. */
  931. int val_log = galois_log[fix_val];
  932. str->pack[fix_row].vals[fix_col] ^= fix_val;
  933. if (str->horz[fix_row].status != fec_status_missing) {
  934. bits_changed += nzbits_arr[fix_val];
  935. }
  936. {
  937. if (fix_col == 26) {
  938. str->horz[fix_row].err ^= fix_val<<8;
  939. } else if (fix_col == 27) {
  940. str->horz[fix_row].err ^= fix_val;
  941. } else {
  942. int offs0 = log_norpak_coeffs[0][fix_col];
  943. int offs1 = log_norpak_coeffs[1][fix_col];
  944. str->horz[fix_row].err ^=
  945. galois_exp[val_log + offs0]<<8 |
  946. galois_exp[val_log + offs1];
  947. }
  948. str->horz[fix_row].errl[0] = galois_log[str->horz[fix_row].err>>8];
  949. str->horz[fix_row].errl[1] = galois_log[str->horz[fix_row].err&0xff];
  950. update_fec_inf(&str->horz[fix_row], 26);
  951. if (str->horz[fix_row].status == fec_status_ok) {
  952. horz_nok--;
  953. }
  954. }
  955. {
  956. if (fix_row == 14) {
  957. st->vert[fix_col].err ^= fix_val<<8;
  958. } else if (fix_row == 15) {
  959. st->vert[fix_col].err ^= fix_val;
  960. } else {
  961. int offs0 = log_norpak_coeffs[0][fix_row];
  962. int offs1 = log_norpak_coeffs[1][fix_row];
  963. st->vert[fix_col].err ^=
  964. galois_exp[val_log + offs0]<<8 |
  965. galois_exp[val_log + offs1];
  966. }
  967. st->vert[fix_col].errl[0] = galois_log[st->vert[fix_col].err>>8];
  968. st->vert[fix_col].errl[1] = galois_log[st->vert[fix_col].err&0xff];
  969. update_fec_inf(&st->vert[fix_col], 14);
  970. if (st->vert[fix_col].status == fec_status_ok) {
  971. vert_nok--;
  972. }
  973. }
  974. }
  975. }
  976. }
  977. } else {
  978. /* There are 2 or more missing rows. In this case, we've lost
  979. most of our error-detecting and error-correcting capability
  980. (unless we've lost exactly 2 rows and the rest are
  981. substantially accurate); even so, we go ahead and smash the
  982. bundle until all the FEC's are valid.
  983. We don't search for optimal two-byte corrections; since we
  984. have no information on column validity, we'd have to search
  985. 278 pairs of error positions, which is too slow. */
  986. int b1 = -1, b2 = -1;
  987. for (i = 0; i < 16; i++) {
  988. switch (str->horz[i].status) {
  989. case fec_status_ok:
  990. /* do nothing */
  991. break;
  992. case fec_status_missing:
  993. if (b1 == -1) {
  994. b1 = i;
  995. } else if (b2 == -1) {
  996. b2 = i;
  997. }
  998. break;
  999. case fec_status_onebyte:
  1000. /* Fix the one-byte error that was detected. */
  1001. str->pack[i].vals[str->horz[i].byte[0]] ^=
  1002. str->horz[i].byte_val[0];
  1003. str->horz[i].status = fec_status_ok;
  1004. str->horz[i].err = 0;
  1005. str->horz[i].errl[0] = GALOIS_LOG0;
  1006. str->horz[i].errl[1] = GALOIS_LOG0;
  1007. bits_changed += nzbits_arr[str->horz[i].byte_val[0]];
  1008. break;
  1009. case fec_status_multibyte:
  1010. /* Smash the checksum bytes. */
  1011. str->pack[i].vals[26] ^= str->horz[i].err >> 8;
  1012. str->pack[i].vals[27] ^= str->horz[i].err & 0xff;
  1013. bits_changed += nzbits_arr[str->horz[i].err >> 8];
  1014. bits_changed += nzbits_arr[str->horz[i].err & 0xff];
  1015. str->horz[i].status = fec_status_ok;
  1016. str->horz[i].err = 0;
  1017. str->horz[i].errl[0] = GALOIS_LOG0;
  1018. str->horz[i].errl[1] = GALOIS_LOG0;
  1019. break;
  1020. }
  1021. }
  1022. /* We've done the best we can at smashing the horizontal rows...
  1023. now it's time to fix the vertical ones */
  1024. {
  1025. /* TODO duplicate code */
  1026. inv2_coeffs coeffs;
  1027. compute_inv2_coeffs(b1, b2, &coeffs, 14);
  1028. for (i = 0; i < 28; i++) {
  1029. int err = st->vert[i].err;
  1030. str->pack[b1].vals[i] ^=
  1031. GALOIS_MULT_COEFF(coeffs.v00, err>>8) ^
  1032. GALOIS_MULT_COEFF(coeffs.v01, err&0xff);
  1033. str->pack[b2].vals[i] ^=
  1034. GALOIS_MULT_COEFF(coeffs.v10, err>>8) ^
  1035. GALOIS_MULT_COEFF(coeffs.v11, err&0xff);
  1036. if (st->vert[i].status != fec_status_ok) {
  1037. st->vert[i].status = fec_status_ok;
  1038. }
  1039. }
  1040. if (n_missing == 2) {
  1041. str->horz[b1].status = fec_status_ok;
  1042. str->horz[b2].status = fec_status_ok;
  1043. }
  1044. }
  1045. }
  1046. }
  1047. {
  1048. /* Now that we've done the FEC processing, actually write out the
  1049. bundle. */
  1050. NFECBundle *pBundle = alloc_mem(sizeof(NFECBundle));
  1051. DEBUG_PRINT((nabtslib_out, "Writing out bundle\n"));
  1052. if (!pBundle) {
  1053. /* TODO - What should I do here? (Note error and up statistics, trap in debug!) */
  1054. DEBUG_PRINT((nabtslib_out, "bundle malloc(%d) failed\n",sizeof(NFECBundle)));
  1055. ASSERT(pBundle);
  1056. return;
  1057. }
  1058. pBundle->lineConfAvg = str->confAvgCount? (str->confAvgSum / str->confAvgCount) : 0;
  1059. for (i = 0; i < 16; i++) {
  1060. if (str->pack[i].not_full == -1) {
  1061. /* We don't know whether this packet is full or not (it was
  1062. reconstructed using the FEC, but this reconstruction doesn't
  1063. include the "not full" flag). Guess. */
  1064. if ((i > 0 && str->pack[i-1].not_full) ||
  1065. (i < 13 && str->pack[i+1].not_full)) {
  1066. /* Our predecessor was not full, or our successor is not full
  1067. or unknown (it might have been reconstructed as well). */
  1068. str->pack[i].not_full = 2;
  1069. } else {
  1070. str->pack[i].not_full = 0;
  1071. }
  1072. }
  1073. if (str->pack[i].not_full) {
  1074. unsigned char *packet_end = &(str->pack[i].vals[25]);
  1075. unsigned char *packet_beg = &(str->pack[i].vals[0]);
  1076. while ((*packet_end > *packet_beg) && *packet_end == 0xea) {
  1077. packet_end--;
  1078. }
  1079. if (*packet_end != 0x15) {
  1080. if (str->pack[i].not_full == 1) {
  1081. /* The packet claimed to be 'not full'. */
  1082. DEBUG_PRINT((nabtslib_out, "Packet %d not in Norpak 'incomplete packet' format\n", i));
  1083. } else {
  1084. /* We guessed that the packet was 'not full'; apparently
  1085. we guessed wrong. */
  1086. }
  1087. packet_write(pBundle, str, i, 26);
  1088. } else {
  1089. packet_write(pBundle, str, i, (packet_end - packet_beg));
  1090. }
  1091. } else {
  1092. packet_write(pBundle, str, i, 26);
  1093. }
  1094. }
  1095. pBundle->nBitErrors = bits_changed;
  1096. cb(ctx, pBundle, str->stream_addr, 16-total_missing);
  1097. }
  1098. /* Move the start of the next bundle down into the current bundle. */
  1099. str->last_index -= 16;
  1100. memcpy(&(str->pack[0]), &(str->pack[16]), 16*sizeof(Packet));
  1101. memcpy(&(str->horz[0]), &(str->horz[16]), 16*sizeof(fec_info));
  1102. for (i = 16; i < 32; i++) {
  1103. erase_packet(str, i);
  1104. }
  1105. }
  1106. #ifdef DEBUG_FEC
  1107. int fec_line;
  1108. int fec_frame;
  1109. #endif
  1110. /* This should probably be called handle_packet(). It takes a packet,
  1111. finds the corresponding stream, and writes the packet into the stream
  1112. structure. */
  1113. int handle_bundle(NFECState *pState, NFECCallback cb, void *ctx,
  1114. int stream_addr, int index, int ps, unsigned char *vals,
  1115. int confidence) {
  1116. int check_ret;
  1117. Stream *str = NULL;
  1118. int i;
  1119. if ((ps>>2 == 2 && index >= 14)
  1120. || (ps>>2 == 3 && index < 14)
  1121. || ((ps & 2) && ps>>2 == 3)
  1122. || (ps & 1)) {
  1123. DEBUG_PRINT((nabtslib_out, "Unhandled combination of index and flags (%d, %d): not Norpak inserter?\n",
  1124. index, ps));
  1125. return 2;
  1126. }
  1127. DEBUG_PRINT((nabtslib_out, "\n"));
  1128. if (pState->pGroupAddrs) {
  1129. for (i = 0; i < pState->nGroupAddrs; i++) {
  1130. if (stream_addr == pState->pGroupAddrs[i]) {
  1131. str = lookup_stream(stream_addr, pState);
  1132. break;
  1133. }
  1134. }
  1135. } else {
  1136. str = lookup_stream(stream_addr, pState);
  1137. }
  1138. if (!str) {
  1139. DEBUG_PRINT((nabtslib_out, "ERROR: Can't allocate stream for %d (or not requested)\n", stream_addr));
  1140. return 2;
  1141. }
  1142. /* Record that this stream is still alive */
  1143. str->dead_time = 0;
  1144. /* There's some complexity in here to deal with out-of-order packets,
  1145. from the broken BT848 driver we were using to collect data
  1146. at the start of this project. It's probably not needed any more. */
  1147. if (index <= str->last_index - 8) {
  1148. index += 16;
  1149. }
  1150. if (str->horz[index].status != fec_status_missing) {
  1151. /* There's already something there. This must be some kind of repeat... */
  1152. DEBUG_PRINT((nabtslib_out, "Ignoring duplicate packet %d\n", (index % 16)));
  1153. return 2;
  1154. }
  1155. if (str->last_index + 1 != index) {
  1156. DEBUG_PRINT((nabtslib_out,
  1157. "Missing lines in stream %d: last was %d, this is %d\n",
  1158. str->stream_addr, (str->last_index % 16), (index % 16)));
  1159. }
  1160. /* Update the fec_inf for this packet */
  1161. check_checksum_horiz(vals, 26, &str->horz[index]);
  1162. check_ret = (str->horz[index].status != fec_status_ok);
  1163. str->confAvgSum += confidence;
  1164. str->confAvgCount += 1;
  1165. str->pack[index].not_full = !!(ps & 2);
  1166. for (i = 0; i < 28; i++) {
  1167. str->pack[index].vals[i] = vals[i];
  1168. }
  1169. #ifdef DEBUG_FEC
  1170. str->pack[index].line = fec_line;
  1171. str->pack[index].frame = fec_frame;
  1172. #endif //DEBUG_FEC
  1173. if (str->last_index < index) {
  1174. str->last_index = index;
  1175. }
  1176. if (index >= 24) {
  1177. complete_bundle(str, cb, ctx, pState);
  1178. }
  1179. return check_ret;
  1180. }
  1181. #define DECODE_HAMMING(var, val, which) \
  1182. { \
  1183. var = decode_hamming(val); \
  1184. if (var == 0xff) {; \
  1185. DEBUG_FEC_PRINT(("ERROR: Bad hamming %02x (%s)\n", val, which)); \
  1186. hamming_err++; \
  1187. } \
  1188. }
  1189. /* This function is called for every stream on exit; it goes ahead and
  1190. sends whatever we've got to the user. */
  1191. void flush_stream(NFECState *pState, Stream *str, NFECCallback cb, void *ctx) {
  1192. int i;
  1193. for (i = str->last_index + 1; i < 16; i++) {
  1194. str->horz[i].status = fec_status_missing;
  1195. memset(str->pack[i].vals, 0, 28);
  1196. str->horz[i].err = 0;
  1197. str->horz[i].errl[0] = GALOIS_LOG0;
  1198. str->horz[i].errl[1] = GALOIS_LOG0;
  1199. str->pack[i].not_full = -1;
  1200. }
  1201. complete_bundle(str, cb, ctx, pState);
  1202. }
  1203. void nabtslib_exit(NFECState *pState, NFECCallback cb, void *ctx) {
  1204. Stream *str = pState->streams;
  1205. while (str) {
  1206. Stream *next_str = str->next;
  1207. flush_stream(pState, str, cb, ctx);
  1208. free_mem(str);
  1209. str = next_str;
  1210. }
  1211. pState->streams = NULL;
  1212. }
  1213. /* This is the implementation of the new API found in nabtsapi.h ... */
  1214. int NFECStateConnectToDSP(NFECState *pFECState, NDSPState *pDSPState) {
  1215. /* This is a no-op for now */
  1216. return 0;
  1217. }
  1218. NFECState *NFECStateNew() {
  1219. NFECState *state = alloc_mem(sizeof(NFECState));
  1220. if ( state )
  1221. {
  1222. state->pGroupAddrs = NULL;
  1223. state->nGroupAddrs = 0;
  1224. state->streams = 0;
  1225. state->n_recent_addrs = 0;
  1226. init_nzbits_arr();
  1227. init_inv2_coeffs();
  1228. }
  1229. else
  1230. {
  1231. SASSERT(state);
  1232. }
  1233. return state;
  1234. }
  1235. void NFECStateDestroy(NFECState *nState) {
  1236. Stream *str = nState->streams;
  1237. while (str) {
  1238. Stream *next_str = str->next;
  1239. free_mem(str);
  1240. str = next_str;
  1241. }
  1242. nState->streams = NULL;
  1243. if (nState->pGroupAddrs) {
  1244. free_mem(nState->pGroupAddrs);
  1245. nState->pGroupAddrs = NULL;
  1246. }
  1247. free_mem(nState);
  1248. }
  1249. int NFECStateSetGroupAddrs(NFECState *pState, int *pGroupAddrs,
  1250. int nGroupAddrs) {
  1251. if (pGroupAddrs) {
  1252. int *new_addrs = alloc_mem(nGroupAddrs * sizeof(int));
  1253. if (!new_addrs) {
  1254. return 0;
  1255. }
  1256. if (pState->pGroupAddrs) {
  1257. free_mem(pState->pGroupAddrs);
  1258. }
  1259. pState->pGroupAddrs = new_addrs;
  1260. memcpy(new_addrs, pGroupAddrs, nGroupAddrs * sizeof(int));
  1261. pState->nGroupAddrs = nGroupAddrs;
  1262. } else {
  1263. if (pState->pGroupAddrs) {
  1264. free_mem(pState->pGroupAddrs);
  1265. }
  1266. pState->pGroupAddrs = NULL;
  1267. pState->nGroupAddrs = 0;
  1268. }
  1269. return 1;
  1270. }
  1271. /* We keep track of the NABTS stream addresses we've seen recently.
  1272. If we find a stream address which we can't correct (due to two-bit
  1273. errors in an address byte), we see if it's close to any of the
  1274. 16 most recent addresses we've seen. If so, we pick the closest
  1275. such address. */
  1276. int find_best_addr(NFECState *pState, unsigned char *indec, int *nBitErrs) {
  1277. int i;
  1278. int hamming_err = 0;
  1279. int loc_biterrs;
  1280. if (nBitErrs == NULL) {
  1281. nBitErrs = &loc_biterrs;
  1282. }
  1283. *nBitErrs = 0;
  1284. if (pState->n_recent_addrs == 0) {
  1285. return -1;
  1286. }
  1287. {
  1288. int best_addr = 0;
  1289. int best_addr_biterrs = INT_MAX;
  1290. int best_addr_count = -1;
  1291. int p1, p2, p3;
  1292. for (i = 0; i < pState->n_recent_addrs; i++) {
  1293. int biterrs = 0;
  1294. int addr = pState->recent_addrs[i].addr;
  1295. biterrs += nzbits_arr[indec[3] ^ (addr >> 16)];
  1296. biterrs += nzbits_arr[indec[4] ^ ((addr >> 8) & 0xff)];
  1297. biterrs += nzbits_arr[indec[5] ^ (addr & 0xff)];
  1298. if ((biterrs < best_addr_biterrs) ||
  1299. (biterrs == best_addr_biterrs &&
  1300. pState->recent_addrs[i].count > best_addr_count)) {
  1301. best_addr = addr;
  1302. best_addr_biterrs = biterrs;
  1303. best_addr_count = pState->recent_addrs[i].count;
  1304. }
  1305. }
  1306. *nBitErrs = best_addr_biterrs;
  1307. if (best_addr_biterrs > 6) {
  1308. /* We want to keep random noise from being a valid address
  1309. (since adding an extra line will mess up a packet worse than
  1310. dropping a line) */
  1311. DEBUG_FEC_PRINT(("Corrupt hamming in address uncorrectable\n"));
  1312. return -1;
  1313. }
  1314. DECODE_HAMMING(p1, best_addr>>16, "p1_best");
  1315. DECODE_HAMMING(p2, (best_addr>>8)&0xff, "p2_best");
  1316. DECODE_HAMMING(p3, best_addr&0xff, "p3_best");
  1317. return (p1<<8) | (p2<<4) | p3;
  1318. }
  1319. }
  1320. /* The main entry point for this file. */
  1321. void NFECDecodeLine(unsigned char *indec,
  1322. int confidence,
  1323. NFECState *pState,
  1324. NFECLineStats *pLineStats,
  1325. NFECCallback *cb,
  1326. void *ctx) {
  1327. int p1, p2, p3, ci, ps;
  1328. int i;
  1329. int stream_addr;
  1330. int encoded_addr;
  1331. int packet_err = 0;
  1332. int hamming_err = 0;
  1333. #if 0
  1334. /* In the old ActiveMovie based driver, this set up the hardcoded
  1335. Intercast and multicast behavior. */
  1336. static int initted = 0;
  1337. if (!initted) {
  1338. initted = 1;
  1339. init_recv();
  1340. init_icast();
  1341. }
  1342. #endif
  1343. if (indec[0] != 0x55 || indec[1] != 0x55 || indec[2] != 0xe7) {
  1344. DEBUG_PRINT((nabtslib_out, "ERROR: bad sync "));
  1345. packet_err = 1;
  1346. }
  1347. #if 0
  1348. /* This is a hack to allow us to decode some strange broadcast
  1349. (possibly Wavephore?) with a bogus group address. */
  1350. if (indec[3] == 0xe0) {indec[3] = 0xea;}
  1351. #endif
  1352. DECODE_HAMMING(p1, indec[3], "p1");
  1353. DECODE_HAMMING(p2, indec[4], "p2");
  1354. DECODE_HAMMING(p3, indec[5], "p3");
  1355. DECODE_HAMMING(ci, indec[6], "ci");
  1356. DECODE_HAMMING(ps, indec[7], "ps");
  1357. if (!hamming_err) {
  1358. stream_addr = p1<<8 | p2<<4 | p3;
  1359. encoded_addr = hamming_encode[p1]<<16 | hamming_encode[p2]<<8 | hamming_encode[p3];
  1360. for (i = 0; i < pState->n_recent_addrs; i++) {
  1361. if (pState->recent_addrs[i].addr == encoded_addr) {
  1362. pState->recent_addrs[i].count++;
  1363. break;
  1364. }
  1365. }
  1366. if (i == pState->n_recent_addrs) {
  1367. /* The address was not found in the list of recent addresses. */
  1368. if (pState->n_recent_addrs < MAX_RECENT_ADDRS) {
  1369. pState->recent_addrs[pState->n_recent_addrs].addr = encoded_addr;
  1370. pState->recent_addrs[pState->n_recent_addrs].count = 1;
  1371. pState->n_recent_addrs++;
  1372. } else {
  1373. /* We've got to retire an existing "recent address". */
  1374. while (1) {
  1375. for (i = 0; i < pState->n_recent_addrs; i++) {
  1376. if (pState->recent_addrs[i].count == 0) {
  1377. pState->recent_addrs[i].addr = encoded_addr;
  1378. pState->recent_addrs[i].count = 1;
  1379. break;
  1380. }
  1381. }
  1382. if (i < pState->n_recent_addrs) {
  1383. break;
  1384. }
  1385. for (i = 0; i < pState->n_recent_addrs; i++) {
  1386. pState->recent_addrs[i].count /= 2;
  1387. }
  1388. }
  1389. }
  1390. }
  1391. } else {
  1392. /* There was a hamming error. Try some heuristics to see what was
  1393. meant. */
  1394. if (p1 == 255 || p2 == 255 || p3 == 255) {
  1395. /* The stream address was corrupt. Let's try to create a valid
  1396. stream address. */
  1397. stream_addr = find_best_addr(pState, indec, NULL);
  1398. if (stream_addr == -1) {
  1399. DEBUG_FEC_PRINT(("Corrupt hamming in address uncorrectable\n"));
  1400. goto corrupt;
  1401. }
  1402. } else {
  1403. stream_addr = p1<<8 | p2<<4 | p3;
  1404. }
  1405. if (ci == 255 || ps == 255) {
  1406. int best_indices[16];
  1407. int n_best_indices = 0;
  1408. int best_index_biterr = INT_MAX;
  1409. goto corrupt;
  1410. // TODO start dead code
  1411. for (i = 0; i < 16; i++) {
  1412. int biterr = 0;
  1413. biterr += nzbits_arr[hamming_encode[i] ^ indec[6]];
  1414. biterr += nzbits_arr[hamming_encode[(i < 14) ? 8 : 12] ^ indec[7]];
  1415. if (biterr < best_index_biterr) {
  1416. best_indices[0] = i;
  1417. n_best_indices = 1;
  1418. best_index_biterr = biterr;
  1419. } else if (biterr == best_index_biterr) {
  1420. best_indices[n_best_indices] = i;
  1421. n_best_indices++;
  1422. }
  1423. }
  1424. if (n_best_indices == 1) {
  1425. ci = best_indices[0];
  1426. ps = (ci < 14) ? 8 : 12;
  1427. } else {
  1428. /* TODO Be a little smarter here... */
  1429. DEBUG_FEC_PRINT(("Bad Hamming for index or structure uncorrectable\n"));
  1430. goto corrupt;
  1431. }
  1432. // TODO End dead code
  1433. }
  1434. }
  1435. DEBUG_PRINT((nabtslib_out, "%04d ", stream_addr));
  1436. DEBUG_PRINT((nabtslib_out, "%01x ", ci));
  1437. #if 0
  1438. #ifdef DEBUG_FEC
  1439. printf("Stream addr: %04d Index: %01x Frame: %4d Line: %2d\n", stream_addr, ci, fec_frame, fec_line);
  1440. #endif
  1441. #endif
  1442. if (ps & 1) {
  1443. DEBUG_PRINT((nabtslib_out, "(group start) "));
  1444. }
  1445. if (ps & 2) {
  1446. DEBUG_PRINT((nabtslib_out, "(packet not full) "));
  1447. for (i = 8; i < 34; i++) {
  1448. DEBUG_PRINT((nabtslib_out, "%02x ", indec[i]));
  1449. }
  1450. }
  1451. switch (ps >> 2) {
  1452. case 0:
  1453. DEBUG_PRINT((nabtslib_out, "28 (unknown checksum)\n"));
  1454. goto corrupt;
  1455. break;
  1456. case 1:
  1457. DEBUG_PRINT((nabtslib_out, "27 "));
  1458. goto corrupt;
  1459. #if 0
  1460. /* This code can correct single-bit errors in 27-byte packets;
  1461. however, we'll never be sending 27-byte packets, so if
  1462. we see one on our group address it's actually a sign of
  1463. a corrupt header byte. */
  1464. {
  1465. int check = 0;
  1466. int parity_err = 0;
  1467. for (i = 8; i < 36; i++) {
  1468. check ^= indec[i];
  1469. if (!nabts_remove_parity(&indec[i])) {
  1470. parity_err++;
  1471. }
  1472. #if 0
  1473. putc(isprint(indec[i]) ? indec[i] : '.', nabtslib_out);
  1474. #endif
  1475. }
  1476. if (parity_err || check != 0xff) {
  1477. if (parity_err) {
  1478. DEBUG_PRINT((nabtslib_out, "ERROR (%d parity error(s)) ", parity_err));
  1479. }
  1480. if (check != 0xff) {
  1481. DEBUG_PRINT((nabtslib_out, "ERROR (bad checksum) "));
  1482. }
  1483. if (parity_err == 1 && nzbits_arr[check] == 7) {
  1484. DEBUG_PRINT((nabtslib_out, "(correctable) "));
  1485. if (packet_err == 0) {
  1486. packet_err = 1;
  1487. }
  1488. } else {
  1489. packet_err = 2;
  1490. }
  1491. }
  1492. }
  1493. #endif
  1494. DEBUG_PRINT((nabtslib_out, "\n"));
  1495. break;
  1496. case 2:
  1497. DEBUG_PRINT((nabtslib_out, "26 "));
  1498. #if 0
  1499. {
  1500. for (i = 8; i < 36; i++) {
  1501. putc(isprint(indec[i]) ? indec[i] : '.', nabtslib_out);
  1502. }
  1503. }
  1504. #endif
  1505. {
  1506. int handle_ret;
  1507. handle_ret = handle_bundle(pState, cb, ctx, stream_addr, ci, ps, indec+8, confidence);
  1508. if (handle_ret > packet_err) {
  1509. packet_err = handle_ret;
  1510. }
  1511. }
  1512. break;
  1513. case 3:
  1514. DEBUG_PRINT((nabtslib_out, " 0 "));
  1515. {
  1516. int handle_ret;
  1517. handle_ret = handle_bundle(pState, cb, ctx, stream_addr, ci, ps, indec+8, confidence);
  1518. if (handle_ret > packet_err) {
  1519. packet_err = handle_ret;
  1520. }
  1521. }
  1522. break;
  1523. }
  1524. if (packet_err) {
  1525. pLineStats->status = NFEC_LINE_CHECKSUM_ERR;
  1526. } else {
  1527. pLineStats->status = NFEC_LINE_OK;
  1528. }
  1529. return;
  1530. corrupt:
  1531. pLineStats->status = NFEC_LINE_CORRUPT;
  1532. return;
  1533. }
  1534. /* Garbage collect streams. Every 50 fields we see, we go through and
  1535. check if any of our streams have been dead (have not received any
  1536. packets) for 300 fields. If so, go ahead and delete that stream
  1537. (forwarding any current data to the callback).
  1538. */
  1539. void NFECGarbageCollect(NFECState *pState, NFECCallback *cb, void *ctx) {
  1540. pState->field_count++;
  1541. if (pState->field_count >= 50) {
  1542. Stream **ppStr = &(pState->streams);
  1543. pState->field_count = 0;
  1544. while (*ppStr != NULL) {
  1545. (*ppStr)->dead_time++;
  1546. if ((*ppStr)->dead_time >= 6) {
  1547. Stream *dying_stream = *ppStr;
  1548. flush_stream(pState, dying_stream, cb, ctx);
  1549. *ppStr = (*ppStr)->next;
  1550. free_mem(dying_stream);
  1551. } else {
  1552. ppStr = &((*ppStr)->next);
  1553. }
  1554. }
  1555. }
  1556. }
  1557. void NFECStateFlush(NFECState *pState, NFECCallback *cb, void *ctx) {
  1558. nabtslib_exit(pState, cb, ctx);
  1559. }
  1560. /* Hamming decode a single byte. */
  1561. int NFECHammingDecode(unsigned char bByte, int *nBitErrors) {
  1562. int decoded = decode_hamming_tab[bByte];
  1563. int encoded;
  1564. if (decoded == 255) {
  1565. *nBitErrors = 2;
  1566. return -1;
  1567. }
  1568. encoded = hamming_encode[decoded];
  1569. if (encoded == bByte) {
  1570. *nBitErrors = 0;
  1571. } else {
  1572. *nBitErrors = 1;
  1573. }
  1574. return decoded;
  1575. }
  1576. /* Hamming decode a group address; if there's a Hamming error, call
  1577. find_best_addr() to match against recently-seen addresses. */
  1578. int NFECGetGroupAddress(NFECState *pState, unsigned char *bData, int *nBitErrors) {
  1579. int a1, a2, a3;
  1580. int myBitErrors;
  1581. *nBitErrors = 0;
  1582. a1 = NFECHammingDecode(bData[3], &myBitErrors);
  1583. *nBitErrors += myBitErrors;
  1584. a2 = NFECHammingDecode(bData[4], &myBitErrors);
  1585. *nBitErrors += myBitErrors;
  1586. a3 = NFECHammingDecode(bData[5], &myBitErrors);
  1587. *nBitErrors += myBitErrors;
  1588. if (a1 != -1 && a2 != -1 && a3 != -1) {
  1589. return a1<<8 | a2<<4 | a3;
  1590. } else {
  1591. return find_best_addr(pState, bData, nBitErrors);
  1592. }
  1593. }