ecc.c 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Calculate Error-correcting Codes. Used by NAND Flash controllers
  3. * (not by NAND chips).
  4. *
  5. * Copyright (c) 2006 Openedhand Ltd.
  6. * Written by Andrzej Zaborowski <balrog@zabor.org>
  7. *
  8. * This code is licensed under the GNU GPL v2.
  9. */
  10. #include "hw.h"
  11. #include "flash.h"
  12. /*
  13. * Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
  14. */
  15. static const uint8_t nand_ecc_precalc_table[] = {
  16. 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
  17. 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
  18. 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
  19. 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
  20. 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
  21. 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
  22. 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
  23. 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
  24. 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
  25. 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
  26. 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
  27. 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
  28. 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
  29. 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
  30. 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
  31. 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
  32. 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
  33. 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
  34. 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
  35. 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
  36. 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
  37. 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
  38. 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
  39. 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
  40. 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
  41. 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
  42. 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
  43. 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
  44. 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
  45. 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
  46. 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
  47. 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
  48. };
  49. /* Update ECC parity count. */
  50. uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample)
  51. {
  52. uint8_t idx = nand_ecc_precalc_table[sample];
  53. s->cp ^= idx & 0x3f;
  54. if (idx & 0x40) {
  55. s->lp[0] ^= ~s->count;
  56. s->lp[1] ^= s->count;
  57. }
  58. s->count ++;
  59. return sample;
  60. }
  61. /* Reinitialise the counters. */
  62. void ecc_reset(struct ecc_state_s *s)
  63. {
  64. s->lp[0] = 0x0000;
  65. s->lp[1] = 0x0000;
  66. s->cp = 0x00;
  67. s->count = 0;
  68. }
  69. /* Save/restore */
  70. void ecc_put(QEMUFile *f, struct ecc_state_s *s)
  71. {
  72. qemu_put_8s(f, &s->cp);
  73. qemu_put_be16s(f, &s->lp[0]);
  74. qemu_put_be16s(f, &s->lp[1]);
  75. qemu_put_be16s(f, &s->count);
  76. }
  77. void ecc_get(QEMUFile *f, struct ecc_state_s *s)
  78. {
  79. qemu_get_8s(f, &s->cp);
  80. qemu_get_be16s(f, &s->lp[0]);
  81. qemu_get_be16s(f, &s->lp[1]);
  82. qemu_get_be16s(f, &s->count);
  83. }