ftape-ecc.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. /*
  2. *
  3. * Copyright (c) 1993 Ning and David Mosberger.
  4. This is based on code originally written by Bas Laarhoven (bas@vimec.nl)
  5. and David L. Brown, Jr., and incorporates improvements suggested by
  6. Kai Harrekilde-Petersen.
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License as
  9. published by the Free Software Foundation; either version 2, or (at
  10. your option) any later version.
  11. This program is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; see the file COPYING. If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
  18. USA.
  19. *
  20. * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ecc.c,v $
  21. * $Revision: 1.3 $
  22. * $Date: 1997/10/05 19:18:10 $
  23. *
  24. * This file contains the Reed-Solomon error correction code
  25. * for the QIC-40/80 floppy-tape driver for Linux.
  26. */
  27. #include <linux/ftape.h>
  28. #include "../lowlevel/ftape-tracing.h"
  29. #include "../lowlevel/ftape-ecc.h"
  30. /* Machines that are big-endian should define macro BIG_ENDIAN.
  31. * Unfortunately, there doesn't appear to be a standard include file
  32. * that works for all OSs.
  33. */
  34. #if defined(__sparc__) || defined(__hppa)
  35. #define BIG_ENDIAN
  36. #endif /* __sparc__ || __hppa */
  37. #if defined(__mips__)
  38. #error Find a smart way to determine the Endianness of the MIPS CPU
  39. #endif
  40. /* Notice: to minimize the potential for confusion, we use r to
  41. * denote the independent variable of the polynomials in the
  42. * Galois Field GF(2^8). We reserve x for polynomials that
  43. * that have coefficients in GF(2^8).
  44. *
  45. * The Galois Field in which coefficient arithmetic is performed are
  46. * the polynomials over Z_2 (i.e., 0 and 1) modulo the irreducible
  47. * polynomial f(r), where f(r)=r^8 + r^7 + r^2 + r + 1. A polynomial
  48. * is represented as a byte with the MSB as the coefficient of r^7 and
  49. * the LSB as the coefficient of r^0. For example, the binary
  50. * representation of f(x) is 0x187 (of course, this doesn't fit into 8
  51. * bits). In this field, the polynomial r is a primitive element.
  52. * That is, r^i with i in 0,...,255 enumerates all elements in the
  53. * field.
  54. *
  55. * The generator polynomial for the QIC-80 ECC is
  56. *
  57. * g(x) = x^3 + r^105*x^2 + r^105*x + 1
  58. *
  59. * which can be factored into:
  60. *
  61. * g(x) = (x-r^-1)(x-r^0)(x-r^1)
  62. *
  63. * the byte representation of the coefficients are:
  64. *
  65. * r^105 = 0xc0
  66. * r^-1 = 0xc3
  67. * r^0 = 0x01
  68. * r^1 = 0x02
  69. *
  70. * Notice that r^-1 = r^254 as exponent arithmetic is performed
  71. * modulo 2^8-1 = 255.
  72. *
  73. * For more information on Galois Fields and Reed-Solomon codes, refer
  74. * to any good book. I found _An Introduction to Error Correcting
  75. * Codes with Applications_ by S. A. Vanstone and P. C. van Oorschot
  76. * to be a good introduction into the former. _CODING THEORY: The
  77. * Essentials_ I found very useful for its concise description of
  78. * Reed-Solomon encoding/decoding.
  79. *
  80. */
  81. typedef __u8 Matrix[3][3];
  82. /*
  83. * gfpow[] is defined such that gfpow[i] returns r^i if
  84. * i is in the range [0..255].
  85. */
  86. static const __u8 gfpow[] =
  87. {
  88. 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
  89. 0x87, 0x89, 0x95, 0xad, 0xdd, 0x3d, 0x7a, 0xf4,
  90. 0x6f, 0xde, 0x3b, 0x76, 0xec, 0x5f, 0xbe, 0xfb,
  91. 0x71, 0xe2, 0x43, 0x86, 0x8b, 0x91, 0xa5, 0xcd,
  92. 0x1d, 0x3a, 0x74, 0xe8, 0x57, 0xae, 0xdb, 0x31,
  93. 0x62, 0xc4, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0x67,
  94. 0xce, 0x1b, 0x36, 0x6c, 0xd8, 0x37, 0x6e, 0xdc,
  95. 0x3f, 0x7e, 0xfc, 0x7f, 0xfe, 0x7b, 0xf6, 0x6b,
  96. 0xd6, 0x2b, 0x56, 0xac, 0xdf, 0x39, 0x72, 0xe4,
  97. 0x4f, 0x9e, 0xbb, 0xf1, 0x65, 0xca, 0x13, 0x26,
  98. 0x4c, 0x98, 0xb7, 0xe9, 0x55, 0xaa, 0xd3, 0x21,
  99. 0x42, 0x84, 0x8f, 0x99, 0xb5, 0xed, 0x5d, 0xba,
  100. 0xf3, 0x61, 0xc2, 0x03, 0x06, 0x0c, 0x18, 0x30,
  101. 0x60, 0xc0, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0,
  102. 0x47, 0x8e, 0x9b, 0xb1, 0xe5, 0x4d, 0x9a, 0xb3,
  103. 0xe1, 0x45, 0x8a, 0x93, 0xa1, 0xc5, 0x0d, 0x1a,
  104. 0x34, 0x68, 0xd0, 0x27, 0x4e, 0x9c, 0xbf, 0xf9,
  105. 0x75, 0xea, 0x53, 0xa6, 0xcb, 0x11, 0x22, 0x44,
  106. 0x88, 0x97, 0xa9, 0xd5, 0x2d, 0x5a, 0xb4, 0xef,
  107. 0x59, 0xb2, 0xe3, 0x41, 0x82, 0x83, 0x81, 0x85,
  108. 0x8d, 0x9d, 0xbd, 0xfd, 0x7d, 0xfa, 0x73, 0xe6,
  109. 0x4b, 0x96, 0xab, 0xd1, 0x25, 0x4a, 0x94, 0xaf,
  110. 0xd9, 0x35, 0x6a, 0xd4, 0x2f, 0x5e, 0xbc, 0xff,
  111. 0x79, 0xf2, 0x63, 0xc6, 0x0b, 0x16, 0x2c, 0x58,
  112. 0xb0, 0xe7, 0x49, 0x92, 0xa3, 0xc1, 0x05, 0x0a,
  113. 0x14, 0x28, 0x50, 0xa0, 0xc7, 0x09, 0x12, 0x24,
  114. 0x48, 0x90, 0xa7, 0xc9, 0x15, 0x2a, 0x54, 0xa8,
  115. 0xd7, 0x29, 0x52, 0xa4, 0xcf, 0x19, 0x32, 0x64,
  116. 0xc8, 0x17, 0x2e, 0x5c, 0xb8, 0xf7, 0x69, 0xd2,
  117. 0x23, 0x46, 0x8c, 0x9f, 0xb9, 0xf5, 0x6d, 0xda,
  118. 0x33, 0x66, 0xcc, 0x1f, 0x3e, 0x7c, 0xf8, 0x77,
  119. 0xee, 0x5b, 0xb6, 0xeb, 0x51, 0xa2, 0xc3, 0x01
  120. };
  121. /*
  122. * This is a log table. That is, gflog[r^i] returns i (modulo f(r)).
  123. * gflog[0] is undefined and the first element is therefore not valid.
  124. */
  125. static const __u8 gflog[256] =
  126. {
  127. 0xff, 0x00, 0x01, 0x63, 0x02, 0xc6, 0x64, 0x6a,
  128. 0x03, 0xcd, 0xc7, 0xbc, 0x65, 0x7e, 0x6b, 0x2a,
  129. 0x04, 0x8d, 0xce, 0x4e, 0xc8, 0xd4, 0xbd, 0xe1,
  130. 0x66, 0xdd, 0x7f, 0x31, 0x6c, 0x20, 0x2b, 0xf3,
  131. 0x05, 0x57, 0x8e, 0xe8, 0xcf, 0xac, 0x4f, 0x83,
  132. 0xc9, 0xd9, 0xd5, 0x41, 0xbe, 0x94, 0xe2, 0xb4,
  133. 0x67, 0x27, 0xde, 0xf0, 0x80, 0xb1, 0x32, 0x35,
  134. 0x6d, 0x45, 0x21, 0x12, 0x2c, 0x0d, 0xf4, 0x38,
  135. 0x06, 0x9b, 0x58, 0x1a, 0x8f, 0x79, 0xe9, 0x70,
  136. 0xd0, 0xc2, 0xad, 0xa8, 0x50, 0x75, 0x84, 0x48,
  137. 0xca, 0xfc, 0xda, 0x8a, 0xd6, 0x54, 0x42, 0x24,
  138. 0xbf, 0x98, 0x95, 0xf9, 0xe3, 0x5e, 0xb5, 0x15,
  139. 0x68, 0x61, 0x28, 0xba, 0xdf, 0x4c, 0xf1, 0x2f,
  140. 0x81, 0xe6, 0xb2, 0x3f, 0x33, 0xee, 0x36, 0x10,
  141. 0x6e, 0x18, 0x46, 0xa6, 0x22, 0x88, 0x13, 0xf7,
  142. 0x2d, 0xb8, 0x0e, 0x3d, 0xf5, 0xa4, 0x39, 0x3b,
  143. 0x07, 0x9e, 0x9c, 0x9d, 0x59, 0x9f, 0x1b, 0x08,
  144. 0x90, 0x09, 0x7a, 0x1c, 0xea, 0xa0, 0x71, 0x5a,
  145. 0xd1, 0x1d, 0xc3, 0x7b, 0xae, 0x0a, 0xa9, 0x91,
  146. 0x51, 0x5b, 0x76, 0x72, 0x85, 0xa1, 0x49, 0xeb,
  147. 0xcb, 0x7c, 0xfd, 0xc4, 0xdb, 0x1e, 0x8b, 0xd2,
  148. 0xd7, 0x92, 0x55, 0xaa, 0x43, 0x0b, 0x25, 0xaf,
  149. 0xc0, 0x73, 0x99, 0x77, 0x96, 0x5c, 0xfa, 0x52,
  150. 0xe4, 0xec, 0x5f, 0x4a, 0xb6, 0xa2, 0x16, 0x86,
  151. 0x69, 0xc5, 0x62, 0xfe, 0x29, 0x7d, 0xbb, 0xcc,
  152. 0xe0, 0xd3, 0x4d, 0x8c, 0xf2, 0x1f, 0x30, 0xdc,
  153. 0x82, 0xab, 0xe7, 0x56, 0xb3, 0x93, 0x40, 0xd8,
  154. 0x34, 0xb0, 0xef, 0x26, 0x37, 0x0c, 0x11, 0x44,
  155. 0x6f, 0x78, 0x19, 0x9a, 0x47, 0x74, 0xa7, 0xc1,
  156. 0x23, 0x53, 0x89, 0xfb, 0x14, 0x5d, 0xf8, 0x97,
  157. 0x2e, 0x4b, 0xb9, 0x60, 0x0f, 0xed, 0x3e, 0xe5,
  158. 0xf6, 0x87, 0xa5, 0x17, 0x3a, 0xa3, 0x3c, 0xb7
  159. };
  160. /* This is a multiplication table for the factor 0xc0 (i.e., r^105 (mod f(r)).
  161. * gfmul_c0[f] returns r^105 * f(r) (modulo f(r)).
  162. */
  163. static const __u8 gfmul_c0[256] =
  164. {
  165. 0x00, 0xc0, 0x07, 0xc7, 0x0e, 0xce, 0x09, 0xc9,
  166. 0x1c, 0xdc, 0x1b, 0xdb, 0x12, 0xd2, 0x15, 0xd5,
  167. 0x38, 0xf8, 0x3f, 0xff, 0x36, 0xf6, 0x31, 0xf1,
  168. 0x24, 0xe4, 0x23, 0xe3, 0x2a, 0xea, 0x2d, 0xed,
  169. 0x70, 0xb0, 0x77, 0xb7, 0x7e, 0xbe, 0x79, 0xb9,
  170. 0x6c, 0xac, 0x6b, 0xab, 0x62, 0xa2, 0x65, 0xa5,
  171. 0x48, 0x88, 0x4f, 0x8f, 0x46, 0x86, 0x41, 0x81,
  172. 0x54, 0x94, 0x53, 0x93, 0x5a, 0x9a, 0x5d, 0x9d,
  173. 0xe0, 0x20, 0xe7, 0x27, 0xee, 0x2e, 0xe9, 0x29,
  174. 0xfc, 0x3c, 0xfb, 0x3b, 0xf2, 0x32, 0xf5, 0x35,
  175. 0xd8, 0x18, 0xdf, 0x1f, 0xd6, 0x16, 0xd1, 0x11,
  176. 0xc4, 0x04, 0xc3, 0x03, 0xca, 0x0a, 0xcd, 0x0d,
  177. 0x90, 0x50, 0x97, 0x57, 0x9e, 0x5e, 0x99, 0x59,
  178. 0x8c, 0x4c, 0x8b, 0x4b, 0x82, 0x42, 0x85, 0x45,
  179. 0xa8, 0x68, 0xaf, 0x6f, 0xa6, 0x66, 0xa1, 0x61,
  180. 0xb4, 0x74, 0xb3, 0x73, 0xba, 0x7a, 0xbd, 0x7d,
  181. 0x47, 0x87, 0x40, 0x80, 0x49, 0x89, 0x4e, 0x8e,
  182. 0x5b, 0x9b, 0x5c, 0x9c, 0x55, 0x95, 0x52, 0x92,
  183. 0x7f, 0xbf, 0x78, 0xb8, 0x71, 0xb1, 0x76, 0xb6,
  184. 0x63, 0xa3, 0x64, 0xa4, 0x6d, 0xad, 0x6a, 0xaa,
  185. 0x37, 0xf7, 0x30, 0xf0, 0x39, 0xf9, 0x3e, 0xfe,
  186. 0x2b, 0xeb, 0x2c, 0xec, 0x25, 0xe5, 0x22, 0xe2,
  187. 0x0f, 0xcf, 0x08, 0xc8, 0x01, 0xc1, 0x06, 0xc6,
  188. 0x13, 0xd3, 0x14, 0xd4, 0x1d, 0xdd, 0x1a, 0xda,
  189. 0xa7, 0x67, 0xa0, 0x60, 0xa9, 0x69, 0xae, 0x6e,
  190. 0xbb, 0x7b, 0xbc, 0x7c, 0xb5, 0x75, 0xb2, 0x72,
  191. 0x9f, 0x5f, 0x98, 0x58, 0x91, 0x51, 0x96, 0x56,
  192. 0x83, 0x43, 0x84, 0x44, 0x8d, 0x4d, 0x8a, 0x4a,
  193. 0xd7, 0x17, 0xd0, 0x10, 0xd9, 0x19, 0xde, 0x1e,
  194. 0xcb, 0x0b, 0xcc, 0x0c, 0xc5, 0x05, 0xc2, 0x02,
  195. 0xef, 0x2f, 0xe8, 0x28, 0xe1, 0x21, 0xe6, 0x26,
  196. 0xf3, 0x33, 0xf4, 0x34, 0xfd, 0x3d, 0xfa, 0x3a
  197. };
  198. /* Returns V modulo 255 provided V is in the range -255,-254,...,509.
  199. */
  200. static inline __u8 mod255(int v)
  201. {
  202. if (v > 0) {
  203. if (v < 255) {
  204. return v;
  205. } else {
  206. return v - 255;
  207. }
  208. } else {
  209. return v + 255;
  210. }
  211. }
  212. /* Add two numbers in the field. Addition in this field is equivalent
  213. * to a bit-wise exclusive OR operation---subtraction is therefore
  214. * identical to addition.
  215. */
  216. static inline __u8 gfadd(__u8 a, __u8 b)
  217. {
  218. return a ^ b;
  219. }
  220. /* Add two vectors of numbers in the field. Each byte in A and B gets
  221. * added individually.
  222. */
  223. static inline unsigned long gfadd_long(unsigned long a, unsigned long b)
  224. {
  225. return a ^ b;
  226. }
  227. /* Multiply two numbers in the field:
  228. */
  229. static inline __u8 gfmul(__u8 a, __u8 b)
  230. {
  231. if (a && b) {
  232. return gfpow[mod255(gflog[a] + gflog[b])];
  233. } else {
  234. return 0;
  235. }
  236. }
  237. /* Just like gfmul, except we have already looked up the log of the
  238. * second number.
  239. */
  240. static inline __u8 gfmul_exp(__u8 a, int b)
  241. {
  242. if (a) {
  243. return gfpow[mod255(gflog[a] + b)];
  244. } else {
  245. return 0;
  246. }
  247. }
  248. /* Just like gfmul_exp, except that A is a vector of numbers. That
  249. * is, each byte in A gets multiplied by gfpow[mod255(B)].
  250. */
  251. static inline unsigned long gfmul_exp_long(unsigned long a, int b)
  252. {
  253. __u8 t;
  254. if (sizeof(long) == 4) {
  255. return (
  256. ((t = (__u32)a >> 24 & 0xff) ?
  257. (((__u32) gfpow[mod255(gflog[t] + b)]) << 24) : 0) |
  258. ((t = (__u32)a >> 16 & 0xff) ?
  259. (((__u32) gfpow[mod255(gflog[t] + b)]) << 16) : 0) |
  260. ((t = (__u32)a >> 8 & 0xff) ?
  261. (((__u32) gfpow[mod255(gflog[t] + b)]) << 8) : 0) |
  262. ((t = (__u32)a >> 0 & 0xff) ?
  263. (((__u32) gfpow[mod255(gflog[t] + b)]) << 0) : 0));
  264. } else if (sizeof(long) == 8) {
  265. return (
  266. ((t = (__u64)a >> 56 & 0xff) ?
  267. (((__u64) gfpow[mod255(gflog[t] + b)]) << 56) : 0) |
  268. ((t = (__u64)a >> 48 & 0xff) ?
  269. (((__u64) gfpow[mod255(gflog[t] + b)]) << 48) : 0) |
  270. ((t = (__u64)a >> 40 & 0xff) ?
  271. (((__u64) gfpow[mod255(gflog[t] + b)]) << 40) : 0) |
  272. ((t = (__u64)a >> 32 & 0xff) ?
  273. (((__u64) gfpow[mod255(gflog[t] + b)]) << 32) : 0) |
  274. ((t = (__u64)a >> 24 & 0xff) ?
  275. (((__u64) gfpow[mod255(gflog[t] + b)]) << 24) : 0) |
  276. ((t = (__u64)a >> 16 & 0xff) ?
  277. (((__u64) gfpow[mod255(gflog[t] + b)]) << 16) : 0) |
  278. ((t = (__u64)a >> 8 & 0xff) ?
  279. (((__u64) gfpow[mod255(gflog[t] + b)]) << 8) : 0) |
  280. ((t = (__u64)a >> 0 & 0xff) ?
  281. (((__u64) gfpow[mod255(gflog[t] + b)]) << 0) : 0));
  282. } else {
  283. TRACE_FUN(ft_t_any);
  284. TRACE_ABORT(-1, ft_t_err, "Error: size of long is %d bytes",
  285. (int)sizeof(long));
  286. }
  287. }
  288. /* Divide two numbers in the field. Returns a/b (modulo f(x)).
  289. */
  290. static inline __u8 gfdiv(__u8 a, __u8 b)
  291. {
  292. if (!b) {
  293. TRACE_FUN(ft_t_any);
  294. TRACE_ABORT(0xff, ft_t_bug, "Error: division by zero");
  295. } else if (a == 0) {
  296. return 0;
  297. } else {
  298. return gfpow[mod255(gflog[a] - gflog[b])];
  299. }
  300. }
  301. /* The following functions return the inverse of the matrix of the
  302. * linear system that needs to be solved to determine the error
  303. * magnitudes. The first deals with matrices of rank 3, while the
  304. * second deals with matrices of rank 2. The error indices are passed
  305. * in arguments L0,..,L2 (0=first sector, 31=last sector). The error
  306. * indices must be sorted in ascending order, i.e., L0<L1<L2.
  307. *
  308. * The linear system that needs to be solved for the error magnitudes
  309. * is A * b = s, where s is the known vector of syndromes, b is the
  310. * vector of error magnitudes and A in the ORDER=3 case:
  311. *
  312. * A_3 = {{1/r^L[0], 1/r^L[1], 1/r^L[2]},
  313. * { 1, 1, 1},
  314. * { r^L[0], r^L[1], r^L[2]}}
  315. */
  316. static inline int gfinv3(__u8 l0,
  317. __u8 l1,
  318. __u8 l2,
  319. Matrix Ainv)
  320. {
  321. __u8 det;
  322. __u8 t20, t10, t21, t12, t01, t02;
  323. int log_det;
  324. /* compute some intermediate results: */
  325. t20 = gfpow[l2 - l0]; /* t20 = r^l2/r^l0 */
  326. t10 = gfpow[l1 - l0]; /* t10 = r^l1/r^l0 */
  327. t21 = gfpow[l2 - l1]; /* t21 = r^l2/r^l1 */
  328. t12 = gfpow[l1 - l2 + 255]; /* t12 = r^l1/r^l2 */
  329. t01 = gfpow[l0 - l1 + 255]; /* t01 = r^l0/r^l1 */
  330. t02 = gfpow[l0 - l2 + 255]; /* t02 = r^l0/r^l2 */
  331. /* Calculate the determinant of matrix A_3^-1 (sometimes
  332. * called the Vandermonde determinant):
  333. */
  334. det = gfadd(t20, gfadd(t10, gfadd(t21, gfadd(t12, gfadd(t01, t02)))));
  335. if (!det) {
  336. TRACE_FUN(ft_t_any);
  337. TRACE_ABORT(0, ft_t_err,
  338. "Inversion failed (3 CRC errors, >0 CRC failures)");
  339. }
  340. log_det = 255 - gflog[det];
  341. /* Now, calculate all of the coefficients:
  342. */
  343. Ainv[0][0]= gfmul_exp(gfadd(gfpow[l1], gfpow[l2]), log_det);
  344. Ainv[0][1]= gfmul_exp(gfadd(t21, t12), log_det);
  345. Ainv[0][2]= gfmul_exp(gfadd(gfpow[255 - l1], gfpow[255 - l2]),log_det);
  346. Ainv[1][0]= gfmul_exp(gfadd(gfpow[l0], gfpow[l2]), log_det);
  347. Ainv[1][1]= gfmul_exp(gfadd(t20, t02), log_det);
  348. Ainv[1][2]= gfmul_exp(gfadd(gfpow[255 - l0], gfpow[255 - l2]),log_det);
  349. Ainv[2][0]= gfmul_exp(gfadd(gfpow[l0], gfpow[l1]), log_det);
  350. Ainv[2][1]= gfmul_exp(gfadd(t10, t01), log_det);
  351. Ainv[2][2]= gfmul_exp(gfadd(gfpow[255 - l0], gfpow[255 - l1]),log_det);
  352. return 1;
  353. }
  354. static inline int gfinv2(__u8 l0, __u8 l1, Matrix Ainv)
  355. {
  356. __u8 det;
  357. __u8 t1, t2;
  358. int log_det;
  359. t1 = gfpow[255 - l0];
  360. t2 = gfpow[255 - l1];
  361. det = gfadd(t1, t2);
  362. if (!det) {
  363. TRACE_FUN(ft_t_any);
  364. TRACE_ABORT(0, ft_t_err,
  365. "Inversion failed (2 CRC errors, >0 CRC failures)");
  366. }
  367. log_det = 255 - gflog[det];
  368. /* Now, calculate all of the coefficients:
  369. */
  370. Ainv[0][0] = Ainv[1][0] = gfpow[log_det];
  371. Ainv[0][1] = gfmul_exp(t2, log_det);
  372. Ainv[1][1] = gfmul_exp(t1, log_det);
  373. return 1;
  374. }
  375. /* Multiply matrix A by vector S and return result in vector B. M is
  376. * assumed to be of order NxN, S and B of order Nx1.
  377. */
  378. static inline void gfmat_mul(int n, Matrix A,
  379. __u8 *s, __u8 *b)
  380. {
  381. int i, j;
  382. __u8 dot_prod;
  383. for (i = 0; i < n; ++i) {
  384. dot_prod = 0;
  385. for (j = 0; j < n; ++j) {
  386. dot_prod = gfadd(dot_prod, gfmul(A[i][j], s[j]));
  387. }
  388. b[i] = dot_prod;
  389. }
  390. }
  391. /* The Reed Solomon ECC codes are computed over the N-th byte of each
  392. * block, where N=SECTOR_SIZE. There are up to 29 blocks of data, and
  393. * 3 blocks of ECC. The blocks are stored contiguously in memory. A
  394. * segment, consequently, is assumed to have at least 4 blocks: one or
  395. * more data blocks plus three ECC blocks.
  396. *
  397. * Notice: In QIC-80 speak, a CRC error is a sector with an incorrect
  398. * CRC. A CRC failure is a sector with incorrect data, but
  399. * a valid CRC. In the error control literature, the former
  400. * is usually called "erasure", the latter "error."
  401. */
  402. /* Compute the parity bytes for C columns of data, where C is the
  403. * number of bytes that fit into a long integer. We use a linear
  404. * feed-back register to do this. The parity bytes P[0], P[STRIDE],
  405. * P[2*STRIDE] are computed such that:
  406. *
  407. * x^k * p(x) + m(x) = 0 (modulo g(x))
  408. *
  409. * where k = NBLOCKS,
  410. * p(x) = P[0] + P[STRIDE]*x + P[2*STRIDE]*x^2, and
  411. * m(x) = sum_{i=0}^k m_i*x^i.
  412. * m_i = DATA[i*SECTOR_SIZE]
  413. */
  414. static inline void set_parity(unsigned long *data,
  415. int nblocks,
  416. unsigned long *p,
  417. int stride)
  418. {
  419. unsigned long p0, p1, p2, t1, t2, *end;
  420. end = data + nblocks * (FT_SECTOR_SIZE / sizeof(long));
  421. p0 = p1 = p2 = 0;
  422. while (data < end) {
  423. /* The new parity bytes p0_i, p1_i, p2_i are computed
  424. * from the old values p0_{i-1}, p1_{i-1}, p2_{i-1}
  425. * recursively as:
  426. *
  427. * p0_i = p1_{i-1} + r^105 * (m_{i-1} - p0_{i-1})
  428. * p1_i = p2_{i-1} + r^105 * (m_{i-1} - p0_{i-1})
  429. * p2_i = (m_{i-1} - p0_{i-1})
  430. *
  431. * With the initial condition: p0_0 = p1_0 = p2_0 = 0.
  432. */
  433. t1 = gfadd_long(*data, p0);
  434. /*
  435. * Multiply each byte in t1 by 0xc0:
  436. */
  437. if (sizeof(long) == 4) {
  438. t2= (((__u32) gfmul_c0[(__u32)t1 >> 24 & 0xff]) << 24 |
  439. ((__u32) gfmul_c0[(__u32)t1 >> 16 & 0xff]) << 16 |
  440. ((__u32) gfmul_c0[(__u32)t1 >> 8 & 0xff]) << 8 |
  441. ((__u32) gfmul_c0[(__u32)t1 >> 0 & 0xff]) << 0);
  442. } else if (sizeof(long) == 8) {
  443. t2= (((__u64) gfmul_c0[(__u64)t1 >> 56 & 0xff]) << 56 |
  444. ((__u64) gfmul_c0[(__u64)t1 >> 48 & 0xff]) << 48 |
  445. ((__u64) gfmul_c0[(__u64)t1 >> 40 & 0xff]) << 40 |
  446. ((__u64) gfmul_c0[(__u64)t1 >> 32 & 0xff]) << 32 |
  447. ((__u64) gfmul_c0[(__u64)t1 >> 24 & 0xff]) << 24 |
  448. ((__u64) gfmul_c0[(__u64)t1 >> 16 & 0xff]) << 16 |
  449. ((__u64) gfmul_c0[(__u64)t1 >> 8 & 0xff]) << 8 |
  450. ((__u64) gfmul_c0[(__u64)t1 >> 0 & 0xff]) << 0);
  451. } else {
  452. TRACE_FUN(ft_t_any);
  453. TRACE(ft_t_err, "Error: long is of size %d",
  454. (int) sizeof(long));
  455. TRACE_EXIT;
  456. }
  457. p0 = gfadd_long(t2, p1);
  458. p1 = gfadd_long(t2, p2);
  459. p2 = t1;
  460. data += FT_SECTOR_SIZE / sizeof(long);
  461. }
  462. *p = p0;
  463. p += stride;
  464. *p = p1;
  465. p += stride;
  466. *p = p2;
  467. return;
  468. }
  469. /* Compute the 3 syndrome values. DATA should point to the first byte
  470. * of the column for which the syndromes are desired. The syndromes
  471. * are computed over the first NBLOCKS of rows. The three bytes will
  472. * be placed in S[0], S[1], and S[2].
  473. *
  474. * S[i] is the value of the "message" polynomial m(x) evaluated at the
  475. * i-th root of the generator polynomial g(x).
  476. *
  477. * As g(x)=(x-r^-1)(x-1)(x-r^1) we evaluate the message polynomial at
  478. * x=r^-1 to get S[0], at x=r^0=1 to get S[1], and at x=r to get S[2].
  479. * This could be done directly and efficiently via the Horner scheme.
  480. * However, it would require multiplication tables for the factors
  481. * r^-1 (0xc3) and r (0x02). The following scheme does not require
  482. * any multiplication tables beyond what's needed for set_parity()
  483. * anyway and is slightly faster if there are no errors and slightly
  484. * slower if there are errors. The latter is hopefully the infrequent
  485. * case.
  486. *
  487. * To understand the alternative algorithm, notice that set_parity(m,
  488. * k, p) computes parity bytes such that:
  489. *
  490. * x^k * p(x) = m(x) (modulo g(x)).
  491. *
  492. * That is, to evaluate m(r^m), where r^m is a root of g(x), we can
  493. * simply evaluate (r^m)^k*p(r^m). Also, notice that p is 0 if and
  494. * only if s is zero. That is, if all parity bytes are 0, we know
  495. * there is no error in the data and consequently there is no need to
  496. * compute s(x) at all! In all other cases, we compute s(x) from p(x)
  497. * by evaluating (r^m)^k*p(r^m) for m=-1, m=0, and m=1. The p(x)
  498. * polynomial is evaluated via the Horner scheme.
  499. */
  500. static int compute_syndromes(unsigned long *data, int nblocks, unsigned long *s)
  501. {
  502. unsigned long p[3];
  503. set_parity(data, nblocks, p, 1);
  504. if (p[0] | p[1] | p[2]) {
  505. /* Some of the checked columns do not have a zero
  506. * syndrome. For simplicity, we compute the syndromes
  507. * for all columns that we have computed the
  508. * remainders for.
  509. */
  510. s[0] = gfmul_exp_long(
  511. gfadd_long(p[0],
  512. gfmul_exp_long(
  513. gfadd_long(p[1],
  514. gfmul_exp_long(p[2], -1)),
  515. -1)),
  516. -nblocks);
  517. s[1] = gfadd_long(gfadd_long(p[2], p[1]), p[0]);
  518. s[2] = gfmul_exp_long(
  519. gfadd_long(p[0],
  520. gfmul_exp_long(
  521. gfadd_long(p[1],
  522. gfmul_exp_long(p[2], 1)),
  523. 1)),
  524. nblocks);
  525. return 0;
  526. } else {
  527. return 1;
  528. }
  529. }
  530. /* Correct the block in the column pointed to by DATA. There are NBAD
  531. * CRC errors and their indices are in BAD_LOC[0], up to
  532. * BAD_LOC[NBAD-1]. If NBAD>1, Ainv holds the inverse of the matrix
  533. * of the linear system that needs to be solved to determine the error
  534. * magnitudes. S[0], S[1], and S[2] are the syndrome values. If row
  535. * j gets corrected, then bit j will be set in CORRECTION_MAP.
  536. */
  537. static inline int correct_block(__u8 *data, int nblocks,
  538. int nbad, int *bad_loc, Matrix Ainv,
  539. __u8 *s,
  540. SectorMap * correction_map)
  541. {
  542. int ncorrected = 0;
  543. int i;
  544. __u8 t1, t2;
  545. __u8 c0, c1, c2; /* check bytes */
  546. __u8 error_mag[3], log_error_mag;
  547. __u8 *dp, l, e;
  548. TRACE_FUN(ft_t_any);
  549. switch (nbad) {
  550. case 0:
  551. /* might have a CRC failure: */
  552. if (s[0] == 0) {
  553. /* more than one error */
  554. TRACE_ABORT(-1, ft_t_err,
  555. "ECC failed (0 CRC errors, >1 CRC failures)");
  556. }
  557. t1 = gfdiv(s[1], s[0]);
  558. if ((bad_loc[nbad++] = gflog[t1]) >= nblocks) {
  559. TRACE(ft_t_err,
  560. "ECC failed (0 CRC errors, >1 CRC failures)");
  561. TRACE_ABORT(-1, ft_t_err,
  562. "attempt to correct data at %d", bad_loc[0]);
  563. }
  564. error_mag[0] = s[1];
  565. break;
  566. case 1:
  567. t1 = gfadd(gfmul_exp(s[1], bad_loc[0]), s[2]);
  568. t2 = gfadd(gfmul_exp(s[0], bad_loc[0]), s[1]);
  569. if (t1 == 0 && t2 == 0) {
  570. /* one erasure, no error: */
  571. Ainv[0][0] = gfpow[bad_loc[0]];
  572. } else if (t1 == 0 || t2 == 0) {
  573. /* one erasure and more than one error: */
  574. TRACE_ABORT(-1, ft_t_err,
  575. "ECC failed (1 erasure, >1 error)");
  576. } else {
  577. /* one erasure, one error: */
  578. if ((bad_loc[nbad++] = gflog[gfdiv(t1, t2)])
  579. >= nblocks) {
  580. TRACE(ft_t_err, "ECC failed "
  581. "(1 CRC errors, >1 CRC failures)");
  582. TRACE_ABORT(-1, ft_t_err,
  583. "attempt to correct data at %d",
  584. bad_loc[1]);
  585. }
  586. if (!gfinv2(bad_loc[0], bad_loc[1], Ainv)) {
  587. /* inversion failed---must have more
  588. * than one error
  589. */
  590. TRACE_EXIT -1;
  591. }
  592. }
  593. /* FALL THROUGH TO ERROR MAGNITUDE COMPUTATION:
  594. */
  595. case 2:
  596. case 3:
  597. /* compute error magnitudes: */
  598. gfmat_mul(nbad, Ainv, s, error_mag);
  599. break;
  600. default:
  601. TRACE_ABORT(-1, ft_t_err,
  602. "Internal Error: number of CRC errors > 3");
  603. }
  604. /* Perform correction by adding ERROR_MAG[i] to the byte at
  605. * offset BAD_LOC[i]. Also add the value of the computed
  606. * error polynomial to the syndrome values. If the correction
  607. * was successful, the resulting check bytes should be zero
  608. * (i.e., the corrected data is a valid code word).
  609. */
  610. c0 = s[0];
  611. c1 = s[1];
  612. c2 = s[2];
  613. for (i = 0; i < nbad; ++i) {
  614. e = error_mag[i];
  615. if (e) {
  616. /* correct the byte at offset L by magnitude E: */
  617. l = bad_loc[i];
  618. dp = &data[l * FT_SECTOR_SIZE];
  619. *dp = gfadd(*dp, e);
  620. *correction_map |= 1 << l;
  621. ++ncorrected;
  622. log_error_mag = gflog[e];
  623. c0 = gfadd(c0, gfpow[mod255(log_error_mag - l)]);
  624. c1 = gfadd(c1, e);
  625. c2 = gfadd(c2, gfpow[mod255(log_error_mag + l)]);
  626. }
  627. }
  628. if (c0 || c1 || c2) {
  629. TRACE_ABORT(-1, ft_t_err,
  630. "ECC self-check failed, too many errors");
  631. }
  632. TRACE_EXIT ncorrected;
  633. }
  634. #if defined(ECC_SANITY_CHECK) || defined(ECC_PARANOID)
  635. /* Perform a sanity check on the computed parity bytes:
  636. */
  637. static int sanity_check(unsigned long *data, int nblocks)
  638. {
  639. TRACE_FUN(ft_t_any);
  640. unsigned long s[3];
  641. if (!compute_syndromes(data, nblocks, s)) {
  642. TRACE_ABORT(0, ft_bug,
  643. "Internal Error: syndrome self-check failed");
  644. }
  645. TRACE_EXIT 1;
  646. }
  647. #endif /* defined(ECC_SANITY_CHECK) || defined(ECC_PARANOID) */
  648. /* Compute the parity for an entire segment of data.
  649. */
  650. int ftape_ecc_set_segment_parity(struct memory_segment *mseg)
  651. {
  652. int i;
  653. __u8 *parity_bytes;
  654. parity_bytes = &mseg->data[(mseg->blocks - 3) * FT_SECTOR_SIZE];
  655. for (i = 0; i < FT_SECTOR_SIZE; i += sizeof(long)) {
  656. set_parity((unsigned long *) &mseg->data[i], mseg->blocks - 3,
  657. (unsigned long *) &parity_bytes[i],
  658. FT_SECTOR_SIZE / sizeof(long));
  659. #ifdef ECC_PARANOID
  660. if (!sanity_check((unsigned long *) &mseg->data[i],
  661. mseg->blocks)) {
  662. return -1;
  663. }
  664. #endif /* ECC_PARANOID */
  665. }
  666. return 0;
  667. }
  668. /* Checks and corrects (if possible) the segment MSEG. Returns one of
  669. * ECC_OK, ECC_CORRECTED, and ECC_FAILED.
  670. */
  671. int ftape_ecc_correct_data(struct memory_segment *mseg)
  672. {
  673. int col, i, result;
  674. int ncorrected = 0;
  675. int nerasures = 0; /* # of erasures (CRC errors) */
  676. int erasure_loc[3]; /* erasure locations */
  677. unsigned long ss[3];
  678. __u8 s[3];
  679. Matrix Ainv;
  680. TRACE_FUN(ft_t_flow);
  681. mseg->corrected = 0;
  682. /* find first column that has non-zero syndromes: */
  683. for (col = 0; col < FT_SECTOR_SIZE; col += sizeof(long)) {
  684. if (!compute_syndromes((unsigned long *) &mseg->data[col],
  685. mseg->blocks, ss)) {
  686. /* something is wrong---have to fix things */
  687. break;
  688. }
  689. }
  690. if (col >= FT_SECTOR_SIZE) {
  691. /* all syndromes are ok, therefore nothing to correct */
  692. TRACE_EXIT ECC_OK;
  693. }
  694. /* count the number of CRC errors if there were any: */
  695. if (mseg->read_bad) {
  696. for (i = 0; i < mseg->blocks; i++) {
  697. if (BAD_CHECK(mseg->read_bad, i)) {
  698. if (nerasures >= 3) {
  699. /* this is too much for ECC */
  700. TRACE_ABORT(ECC_FAILED, ft_t_err,
  701. "ECC failed (>3 CRC errors)");
  702. } /* if */
  703. erasure_loc[nerasures++] = i;
  704. }
  705. }
  706. }
  707. /*
  708. * If there are at least 2 CRC errors, determine inverse of matrix
  709. * of linear system to be solved:
  710. */
  711. switch (nerasures) {
  712. case 2:
  713. if (!gfinv2(erasure_loc[0], erasure_loc[1], Ainv)) {
  714. TRACE_EXIT ECC_FAILED;
  715. }
  716. break;
  717. case 3:
  718. if (!gfinv3(erasure_loc[0], erasure_loc[1],
  719. erasure_loc[2], Ainv)) {
  720. TRACE_EXIT ECC_FAILED;
  721. }
  722. break;
  723. default:
  724. /* this is not an error condition... */
  725. break;
  726. }
  727. do {
  728. for (i = 0; i < sizeof(long); ++i) {
  729. s[0] = ss[0];
  730. s[1] = ss[1];
  731. s[2] = ss[2];
  732. if (s[0] | s[1] | s[2]) {
  733. #ifdef BIG_ENDIAN
  734. result = correct_block(
  735. &mseg->data[col + sizeof(long) - 1 - i],
  736. mseg->blocks,
  737. nerasures,
  738. erasure_loc,
  739. Ainv,
  740. s,
  741. &mseg->corrected);
  742. #else
  743. result = correct_block(&mseg->data[col + i],
  744. mseg->blocks,
  745. nerasures,
  746. erasure_loc,
  747. Ainv,
  748. s,
  749. &mseg->corrected);
  750. #endif
  751. if (result < 0) {
  752. TRACE_EXIT ECC_FAILED;
  753. }
  754. ncorrected += result;
  755. }
  756. ss[0] >>= 8;
  757. ss[1] >>= 8;
  758. ss[2] >>= 8;
  759. }
  760. #ifdef ECC_SANITY_CHECK
  761. if (!sanity_check((unsigned long *) &mseg->data[col],
  762. mseg->blocks)) {
  763. TRACE_EXIT ECC_FAILED;
  764. }
  765. #endif /* ECC_SANITY_CHECK */
  766. /* find next column with non-zero syndromes: */
  767. while ((col += sizeof(long)) < FT_SECTOR_SIZE) {
  768. if (!compute_syndromes((unsigned long *)
  769. &mseg->data[col], mseg->blocks, ss)) {
  770. /* something is wrong---have to fix things */
  771. break;
  772. }
  773. }
  774. } while (col < FT_SECTOR_SIZE);
  775. if (ncorrected && nerasures == 0) {
  776. TRACE(ft_t_warn, "block contained error not caught by CRC");
  777. }
  778. TRACE((ncorrected > 0) ? ft_t_noise : ft_t_any, "number of corrections: %d", ncorrected);
  779. TRACE_EXIT ncorrected ? ECC_CORRECTED : ECC_OK;
  780. }