reed_solomon.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * lib/reed_solomon/rslib.c
  3. *
  4. * Overview:
  5. * Generic Reed Solomon encoder / decoder library
  6. *
  7. * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
  8. *
  9. * Reed Solomon code lifted from reed solomon library written by Phil Karn
  10. * Copyright 2002 Phil Karn, KA9Q
  11. *
  12. * $Id: rslib.c,v 1.5 2004/10/22 15:41:47 gleixner Exp $
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License version 2 as
  16. * published by the Free Software Foundation.
  17. *
  18. * Description:
  19. *
  20. * The generic Reed Solomon library provides runtime configurable
  21. * encoding / decoding of RS codes.
  22. * Each user must call init_rs to get a pointer to a rs_control
  23. * structure for the given rs parameters. This structure is either
  24. * generated or a already available matching control structure is used.
  25. * If a structure is generated then the polynomial arrays for
  26. * fast encoding / decoding are built. This can take some time so
  27. * make sure not to call this function from a time critical path.
  28. * Usually a module / driver should initialize the necessary
  29. * rs_control structure on module / driver init and release it
  30. * on exit.
  31. * The encoding puts the calculated syndrome into a given syndrome
  32. * buffer.
  33. * The decoding is a two step process. The first step calculates
  34. * the syndrome over the received (data + syndrome) and calls the
  35. * second stage, which does the decoding / error correction itself.
  36. * Many hw encoders provide a syndrome calculation over the received
  37. * data + syndrome and can call the second stage directly.
  38. *
  39. */
  40. #include <linux/errno.h>
  41. #include <linux/kernel.h>
  42. #include <linux/init.h>
  43. #include <linux/module.h>
  44. #include <linux/rslib.h>
  45. #include <linux/slab.h>
  46. #include <asm/semaphore.h>
  47. /* This list holds all currently allocated rs control structures */
  48. static LIST_HEAD (rslist);
  49. /* Protection for the list */
  50. static DECLARE_MUTEX(rslistlock);
  51. /**
  52. * rs_init - Initialize a Reed-Solomon codec
  53. *
  54. * @symsize: symbol size, bits (1-8)
  55. * @gfpoly: Field generator polynomial coefficients
  56. * @fcr: first root of RS code generator polynomial, index form
  57. * @prim: primitive element to generate polynomial roots
  58. * @nroots: RS code generator polynomial degree (number of roots)
  59. *
  60. * Allocate a control structure and the polynom arrays for faster
  61. * en/decoding. Fill the arrays according to the given parameters
  62. */
  63. static struct rs_control *rs_init(int symsize, int gfpoly, int fcr,
  64. int prim, int nroots)
  65. {
  66. struct rs_control *rs;
  67. int i, j, sr, root, iprim;
  68. /* Allocate the control structure */
  69. rs = kmalloc(sizeof (struct rs_control), GFP_KERNEL);
  70. if (rs == NULL)
  71. return NULL;
  72. INIT_LIST_HEAD(&rs->list);
  73. rs->mm = symsize;
  74. rs->nn = (1 << symsize) - 1;
  75. rs->fcr = fcr;
  76. rs->prim = prim;
  77. rs->nroots = nroots;
  78. rs->gfpoly = gfpoly;
  79. /* Allocate the arrays */
  80. rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL);
  81. if (rs->alpha_to == NULL)
  82. goto errrs;
  83. rs->index_of = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL);
  84. if (rs->index_of == NULL)
  85. goto erralp;
  86. rs->genpoly = kmalloc(sizeof(uint16_t) * (rs->nroots + 1), GFP_KERNEL);
  87. if(rs->genpoly == NULL)
  88. goto erridx;
  89. /* Generate Galois field lookup tables */
  90. rs->index_of[0] = rs->nn; /* log(zero) = -inf */
  91. rs->alpha_to[rs->nn] = 0; /* alpha**-inf = 0 */
  92. sr = 1;
  93. for (i = 0; i < rs->nn; i++) {
  94. rs->index_of[sr] = i;
  95. rs->alpha_to[i] = sr;
  96. sr <<= 1;
  97. if (sr & (1 << symsize))
  98. sr ^= gfpoly;
  99. sr &= rs->nn;
  100. }
  101. /* If it's not primitive, exit */
  102. if(sr != 1)
  103. goto errpol;
  104. /* Find prim-th root of 1, used in decoding */
  105. for(iprim = 1; (iprim % prim) != 0; iprim += rs->nn);
  106. /* prim-th root of 1, index form */
  107. rs->iprim = iprim / prim;
  108. /* Form RS code generator polynomial from its roots */
  109. rs->genpoly[0] = 1;
  110. for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) {
  111. rs->genpoly[i + 1] = 1;
  112. /* Multiply rs->genpoly[] by @**(root + x) */
  113. for (j = i; j > 0; j--) {
  114. if (rs->genpoly[j] != 0) {
  115. rs->genpoly[j] = rs->genpoly[j -1] ^
  116. rs->alpha_to[rs_modnn(rs,
  117. rs->index_of[rs->genpoly[j]] + root)];
  118. } else
  119. rs->genpoly[j] = rs->genpoly[j - 1];
  120. }
  121. /* rs->genpoly[0] can never be zero */
  122. rs->genpoly[0] =
  123. rs->alpha_to[rs_modnn(rs,
  124. rs->index_of[rs->genpoly[0]] + root)];
  125. }
  126. /* convert rs->genpoly[] to index form for quicker encoding */
  127. for (i = 0; i <= nroots; i++)
  128. rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
  129. return rs;
  130. /* Error exit */
  131. errpol:
  132. kfree(rs->genpoly);
  133. erridx:
  134. kfree(rs->index_of);
  135. erralp:
  136. kfree(rs->alpha_to);
  137. errrs:
  138. kfree(rs);
  139. return NULL;
  140. }
  141. /**
  142. * free_rs - Free the rs control structure, if its not longer used
  143. *
  144. * @rs: the control structure which is not longer used by the
  145. * caller
  146. */
  147. void free_rs(struct rs_control *rs)
  148. {
  149. down(&rslistlock);
  150. rs->users--;
  151. if(!rs->users) {
  152. list_del(&rs->list);
  153. kfree(rs->alpha_to);
  154. kfree(rs->index_of);
  155. kfree(rs->genpoly);
  156. kfree(rs);
  157. }
  158. up(&rslistlock);
  159. }
  160. /**
  161. * init_rs - Find a matching or allocate a new rs control structure
  162. *
  163. * @symsize: the symbol size (number of bits)
  164. * @gfpoly: the extended Galois field generator polynomial coefficients,
  165. * with the 0th coefficient in the low order bit. The polynomial
  166. * must be primitive;
  167. * @fcr: the first consecutive root of the rs code generator polynomial
  168. * in index form
  169. * @prim: primitive element to generate polynomial roots
  170. * @nroots: RS code generator polynomial degree (number of roots)
  171. */
  172. struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
  173. int nroots)
  174. {
  175. struct list_head *tmp;
  176. struct rs_control *rs;
  177. /* Sanity checks */
  178. if (symsize < 1)
  179. return NULL;
  180. if (fcr < 0 || fcr >= (1<<symsize))
  181. return NULL;
  182. if (prim <= 0 || prim >= (1<<symsize))
  183. return NULL;
  184. if (nroots < 0 || nroots >= (1<<symsize) || nroots > 8)
  185. return NULL;
  186. down(&rslistlock);
  187. /* Walk through the list and look for a matching entry */
  188. list_for_each(tmp, &rslist) {
  189. rs = list_entry(tmp, struct rs_control, list);
  190. if (symsize != rs->mm)
  191. continue;
  192. if (gfpoly != rs->gfpoly)
  193. continue;
  194. if (fcr != rs->fcr)
  195. continue;
  196. if (prim != rs->prim)
  197. continue;
  198. if (nroots != rs->nroots)
  199. continue;
  200. /* We have a matching one already */
  201. rs->users++;
  202. goto out;
  203. }
  204. /* Create a new one */
  205. rs = rs_init(symsize, gfpoly, fcr, prim, nroots);
  206. if (rs) {
  207. rs->users = 1;
  208. list_add(&rs->list, &rslist);
  209. }
  210. out:
  211. up(&rslistlock);
  212. return rs;
  213. }
  214. #ifdef CONFIG_REED_SOLOMON_ENC8
  215. /**
  216. * encode_rs8 - Calculate the parity for data values (8bit data width)
  217. *
  218. * @rs: the rs control structure
  219. * @data: data field of a given type
  220. * @len: data length
  221. * @par: parity data, must be initialized by caller (usually all 0)
  222. * @invmsk: invert data mask (will be xored on data)
  223. *
  224. * The parity uses a uint16_t data type to enable
  225. * symbol size > 8. The calling code must take care of encoding of the
  226. * syndrome result for storage itself.
  227. */
  228. int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par,
  229. uint16_t invmsk)
  230. {
  231. #include "encode_rs.c"
  232. }
  233. EXPORT_SYMBOL_GPL(encode_rs8);
  234. #endif
  235. #ifdef CONFIG_REED_SOLOMON_DEC8
  236. /**
  237. * decode_rs8 - Decode codeword (8bit data width)
  238. *
  239. * @rs: the rs control structure
  240. * @data: data field of a given type
  241. * @par: received parity data field
  242. * @len: data length
  243. * @s: syndrome data field (if NULL, syndrome is calculated)
  244. * @no_eras: number of erasures
  245. * @eras_pos: position of erasures, can be NULL
  246. * @invmsk: invert data mask (will be xored on data, not on parity!)
  247. * @corr: buffer to store correction bitmask on eras_pos
  248. *
  249. * The syndrome and parity uses a uint16_t data type to enable
  250. * symbol size > 8. The calling code must take care of decoding of the
  251. * syndrome result and the received parity before calling this code.
  252. */
  253. int decode_rs8(struct rs_control *rs, uint8_t *data, uint16_t *par, int len,
  254. uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
  255. uint16_t *corr)
  256. {
  257. #include "decode_rs.c"
  258. }
  259. EXPORT_SYMBOL_GPL(decode_rs8);
  260. #endif
  261. #ifdef CONFIG_REED_SOLOMON_ENC16
  262. /**
  263. * encode_rs16 - Calculate the parity for data values (16bit data width)
  264. *
  265. * @rs: the rs control structure
  266. * @data: data field of a given type
  267. * @len: data length
  268. * @par: parity data, must be initialized by caller (usually all 0)
  269. * @invmsk: invert data mask (will be xored on data, not on parity!)
  270. *
  271. * Each field in the data array contains up to symbol size bits of valid data.
  272. */
  273. int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par,
  274. uint16_t invmsk)
  275. {
  276. #include "encode_rs.c"
  277. }
  278. EXPORT_SYMBOL_GPL(encode_rs16);
  279. #endif
  280. #ifdef CONFIG_REED_SOLOMON_DEC16
  281. /**
  282. * decode_rs16 - Decode codeword (16bit data width)
  283. *
  284. * @rs: the rs control structure
  285. * @data: data field of a given type
  286. * @par: received parity data field
  287. * @len: data length
  288. * @s: syndrome data field (if NULL, syndrome is calculated)
  289. * @no_eras: number of erasures
  290. * @eras_pos: position of erasures, can be NULL
  291. * @invmsk: invert data mask (will be xored on data, not on parity!)
  292. * @corr: buffer to store correction bitmask on eras_pos
  293. *
  294. * Each field in the data array contains up to symbol size bits of valid data.
  295. */
  296. int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len,
  297. uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
  298. uint16_t *corr)
  299. {
  300. #include "decode_rs.c"
  301. }
  302. EXPORT_SYMBOL_GPL(decode_rs16);
  303. #endif
  304. EXPORT_SYMBOL_GPL(init_rs);
  305. EXPORT_SYMBOL_GPL(free_rs);
  306. MODULE_LICENSE("GPL");
  307. MODULE_DESCRIPTION("Reed Solomon encoder/decoder");
  308. MODULE_AUTHOR("Phil Karn, Thomas Gleixner");