ccci_ringbuf.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. #include <linux/skbuff.h>
  2. #include <linux/wait.h>
  3. #include <linux/sched.h>
  4. #include <linux/delay.h>
  5. #include <linux/module.h>
  6. #include "ccci_ringbuf.h"
  7. #include "ccci_debug.h"
  8. #define TAG "rbf"
  9. #define CCIF_HEADER_LEN 8
  10. #define CCIF_FOOTER_LEN 8
  11. #define CCCI_HEADER_LEN 16
  12. #define CCCI_RBF_HEADER 0xEE0000EE
  13. #define CCCI_RBF_FOOTER 0xFF0000FF
  14. #define CCIF_PKG_HEADER 0xAABBAABB
  15. #define CCIF_PKG_FOOTER 0xCCDDEEFF
  16. static inline void *rbf_memcpy(void *__dest, __const void *__src, size_t __n)
  17. {
  18. int i = 0;
  19. unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
  20. for (i = __n >> 3; i > 0; i--) {
  21. *d++ = *s++;
  22. *d++ = *s++;
  23. *d++ = *s++;
  24. *d++ = *s++;
  25. *d++ = *s++;
  26. *d++ = *s++;
  27. *d++ = *s++;
  28. *d++ = *s++;
  29. }
  30. if (__n & 1 << 2) {
  31. *d++ = *s++;
  32. *d++ = *s++;
  33. *d++ = *s++;
  34. *d++ = *s++;
  35. }
  36. if (__n & 1 << 1) {
  37. *d++ = *s++;
  38. *d++ = *s++;
  39. }
  40. if (__n & 1)
  41. *d++ = *s++;
  42. return __dest;
  43. }
  44. /* #define rbf_memcpy memcpy */
  45. #define CCIF_RBF_READ(bufaddr, output_addr, read_size, read_pos, buflen)\
  46. do {\
  47. if (read_pos + read_size < buflen) {\
  48. rbf_memcpy((unsigned char *)output_addr,\
  49. (unsigned char *)(bufaddr) + read_pos, read_size);\
  50. } else {\
  51. rbf_memcpy((unsigned char *)output_addr,\
  52. (unsigned char *)(bufaddr) + read_pos, buflen - read_pos);\
  53. output_addr = (unsigned char *)output_addr + buflen - read_pos;\
  54. rbf_memcpy((unsigned char *)output_addr, (unsigned char *)(bufaddr),\
  55. read_size - (buflen - read_pos));\
  56. } \
  57. } while (0)
  58. #define CCIF_RBF_WRITE(bufaddr, data_addr, data_size, write_pos, buflen)\
  59. do {\
  60. if (write_pos + data_size < buflen) {\
  61. rbf_memcpy((unsigned char *)(bufaddr) + write_pos,\
  62. (unsigned char *)data_addr, data_size);\
  63. } else {\
  64. rbf_memcpy((unsigned char *)(bufaddr) + write_pos,\
  65. (unsigned char *)data_addr , buflen - write_pos);\
  66. data_addr = (unsigned char *)data_addr + buflen - write_pos;\
  67. rbf_memcpy((unsigned char *)(bufaddr), (unsigned char *)data_addr,\
  68. data_size - (buflen - write_pos));\
  69. } \
  70. } while (0)
  71. static void ccci_ringbuf_dump(int md_id, unsigned char *title,
  72. unsigned char *buffer, unsigned int read,
  73. unsigned int length, int dump_size)
  74. {
  75. int i, j;
  76. unsigned char tmp_buf[256];
  77. unsigned int write = read + dump_size;
  78. if (write >= length)
  79. write -= length;
  80. CCCI_INF_MSG(md_id, TAG, "%s rbdump: buf=0x%p, read=%d, write=%d\n",
  81. title, buffer, read, write);
  82. read = (read >> 3) << 3;
  83. /* 8byte align*/
  84. write = ((write + 7) >> 3) << 3;
  85. if (write >= length)
  86. write -= length;
  87. CCCI_INF_MSG(md_id, TAG, "rbdump:aligned read=%d,write=%d\n", read,
  88. write);
  89. i = read;
  90. while (1) {
  91. memset(tmp_buf, 0, sizeof(tmp_buf));
  92. snprintf(tmp_buf, sizeof(tmp_buf), "%08X:", i);
  93. for (j = 0; j < 4; j++) {
  94. snprintf(tmp_buf, sizeof(tmp_buf),
  95. "%s %02X%02X%02X%02X", tmp_buf, *(buffer + i),
  96. *(buffer + i + 1), *(buffer + i + 2),
  97. *(buffer + i + 3));
  98. i += sizeof(unsigned int);
  99. if (i >= length)
  100. i -= length;
  101. if (i == write)
  102. goto OUT;
  103. }
  104. CCCI_INF_MSG(md_id, TAG, "%s\n", tmp_buf);
  105. }
  106. OUT:
  107. CCCI_INF_MSG(md_id, TAG, "%s\n", tmp_buf);
  108. }
  109. struct ccci_ringbuf *ccci_create_ringbuf(int md_id, unsigned char *buf, int buf_size, int rx_size, int tx_size)
  110. {
  111. int buflen;
  112. struct ccci_ringbuf *ringbuf = NULL;
  113. buflen = CCCI_RINGBUF_CTL_LEN + rx_size + tx_size;
  114. CCCI_INF_MSG(md_id, TAG,
  115. "crb:buf=0x%p, buf_size=%d,buflen=%d,rx_size=%d,tx_size=%d,ctr_len=%zu\n",
  116. buf, buf_size, buflen, rx_size, tx_size, CCCI_RINGBUF_CTL_LEN);
  117. if (buf_size < buflen)
  118. return NULL;
  119. memset_io(buf, 0x0, buflen);
  120. /*set ccif header */
  121. *((unsigned int *)buf) = CCCI_RBF_HEADER;
  122. *((unsigned int *)(buf + sizeof(unsigned int))) = CCCI_RBF_HEADER;
  123. CCCI_INF_MSG(md_id, TAG, "crb:Header(0x%p)=0x%x %x\n", buf,
  124. *((unsigned int *)buf), *((unsigned int *)(buf + sizeof(unsigned int))));
  125. /*set ccif footer */
  126. *((unsigned int *)(buf + buflen - sizeof(unsigned int))) = CCCI_RBF_FOOTER;
  127. *((unsigned int *)(buf + buflen - 2 * sizeof(unsigned int))) = CCCI_RBF_FOOTER;
  128. CCCI_INF_MSG(md_id, TAG, "crb:Footer(0x%p)=0x%x %x\n",
  129. buf + buflen - sizeof(int),
  130. *((unsigned int *)(buf + buflen - sizeof(unsigned int))),
  131. *((unsigned int *)(buf + buflen - 2 * sizeof(unsigned int))));
  132. buf += sizeof(int) * 2;
  133. ringbuf = (struct ccci_ringbuf *)buf;
  134. ringbuf->rx_control.length = rx_size;
  135. ringbuf->rx_control.read = 0;
  136. ringbuf->rx_control.write = 0;
  137. ringbuf->tx_control.length = tx_size;
  138. ringbuf->tx_control.read = 0;
  139. ringbuf->tx_control.write = 0;
  140. CCCI_INF_MSG(md_id, TAG, "crb:rbf=0x%p\n", ringbuf);
  141. return ringbuf;
  142. }
  143. int ccci_ringbuf_writeable(int md_id, struct ccci_ringbuf *ringbuf, unsigned int write_size)
  144. {
  145. int read, write, size, length;
  146. if (ringbuf == NULL) {
  147. CCCI_ERR_MSG(md_id, TAG, "rbwb param error,ringbuf == NULL\n");
  148. return -CCCI_RINGBUF_PARAM_ERR;
  149. }
  150. read = (unsigned int)(ringbuf->tx_control.read);
  151. write = (unsigned int)(ringbuf->tx_control.write);
  152. length = (unsigned int)(ringbuf->tx_control.length);
  153. if (write_size > length) {
  154. CCCI_ERR_MSG(md_id, TAG, "rbwb param error,writesize(%d) > length(%d)\n", write_size, length);
  155. return -CCCI_RINGBUF_PARAM_ERR;
  156. }
  157. write_size += CCIF_HEADER_LEN + CCIF_FOOTER_LEN;
  158. /* 8 byte align */
  159. write_size = (((write_size + 7) >> 3) << 3);
  160. if (read == write) {
  161. size = length - 1;
  162. } else if (read < write) {
  163. size = length - write - 1;
  164. size += read;
  165. } else {
  166. size = read - write - 1;
  167. }
  168. /* if (write_size > size) {
  169. CCCI_INF_MSG(-1, TAG, "rbwb:rbf=%p write_size(%d)>size(%d) r=%d,w=%d\n",
  170. ringbuf,write_size,size,read,write);
  171. } */
  172. return (write_size < size) ? write_size : -(write_size - size);
  173. }
  174. int ccci_ringbuf_write(int md_id, struct ccci_ringbuf *ringbuf, unsigned char *data, int data_len)
  175. {
  176. int aligned_data_len;
  177. unsigned int read, write, length;
  178. unsigned char *tx_buffer;
  179. unsigned char *h_ptr;
  180. unsigned int header[2] = { CCIF_PKG_HEADER, 0x0 };
  181. unsigned int footer[2] = { CCIF_PKG_FOOTER, CCIF_PKG_FOOTER };
  182. if (ringbuf == NULL || data_len == 0 || data == NULL)
  183. return -CCCI_RINGBUF_PARAM_ERR;
  184. if (ccci_ringbuf_writeable(md_id, ringbuf, data_len) <= 0)
  185. return -CCCI_RINGBUF_NOT_ENOUGH;
  186. read = (unsigned int)(ringbuf->tx_control.read);
  187. write = (unsigned int)(ringbuf->tx_control.write);
  188. length = (unsigned int)(ringbuf->tx_control.length);
  189. tx_buffer = ringbuf->buffer + ringbuf->rx_control.length;
  190. header[1] = data_len;
  191. h_ptr = (unsigned char *)header;
  192. CCIF_RBF_WRITE(tx_buffer, h_ptr, CCIF_HEADER_LEN, write, length);
  193. write += CCIF_HEADER_LEN;
  194. if (write >= length)
  195. write -= length;
  196. CCIF_RBF_WRITE(tx_buffer, data, data_len, write, length);
  197. /* 8 byte align */
  198. aligned_data_len = (((data_len + 7) >> 3) << 3);
  199. write += aligned_data_len;
  200. if (write >= length)
  201. write -= length;
  202. h_ptr = (unsigned char *)footer;
  203. CCIF_RBF_WRITE(tx_buffer, h_ptr, CCIF_FOOTER_LEN, write, length);
  204. write += CCIF_FOOTER_LEN;
  205. if (write >= length)
  206. write -= length;
  207. CCCI_DBG_MSG(md_id, TAG,
  208. "rbw: rbf=0x%p,tx_buf=0x%p,o_write=%d,n_write=%d,datalen=%d,algined_data_len=%d,HLEN=%d,LEN=%d,read=%d\n",
  209. ringbuf, tx_buffer, ringbuf->tx_control.write, write,
  210. data_len, aligned_data_len, 16, length, ringbuf->tx_control.read);
  211. ringbuf->tx_control.write = write;
  212. return data_len;
  213. }
  214. int ccci_ringbuf_readable(int md_id, struct ccci_ringbuf *ringbuf)
  215. {
  216. unsigned char *rx_buffer, *outptr;
  217. unsigned int read, write, ccci_pkg_len, ccif_pkg_len;
  218. unsigned int footer_pos, length;
  219. unsigned int header[2] = { 0 };
  220. unsigned int footer[2] = { 0 };
  221. int size;
  222. if (ringbuf == NULL) {
  223. CCCI_ERR_MSG(md_id, TAG, "rbrdb param error,ringbuf==NULL\n");
  224. return -CCCI_RINGBUF_PARAM_ERR;
  225. }
  226. read = (unsigned int)(ringbuf->rx_control.read);
  227. write = (unsigned int)(ringbuf->rx_control.write);
  228. length = (unsigned int)(ringbuf->rx_control.length);
  229. rx_buffer = ringbuf->buffer;
  230. size = write - read;
  231. if (size < 0)
  232. size += length;
  233. CCCI_DBG_MSG(md_id, TAG,
  234. "rbrdb:rbf=%p,rx_buf=0x%p,read=%d,write=%d,len=%d\n", ringbuf, rx_buffer, read, write, length);
  235. if (size < CCIF_HEADER_LEN + CCIF_FOOTER_LEN + CCCI_HEADER_LEN)
  236. return -CCCI_RINGBUF_EMPTY;
  237. outptr = (unsigned char *)header;
  238. CCIF_RBF_READ(rx_buffer, outptr, CCIF_HEADER_LEN, read, length);
  239. if (header[0] != CCIF_PKG_HEADER) {
  240. CCCI_INF_MSG(md_id, TAG,
  241. "rbrdb:rbf=%p,rx_buf=0x%p,read=%d,write=%d,len=%d\n",
  242. ringbuf, rx_buffer, read, write, length);
  243. CCCI_ERR_MSG(md_id, TAG, "rbrdb:rx_buffer=0x%p header 0x%x!=0xAABBAABB\n", rx_buffer, header[0]);
  244. ccci_ringbuf_dump(md_id, "readable", rx_buffer, read, length, size);
  245. return -CCCI_RINGBUF_BAD_HEADER;
  246. }
  247. ccci_pkg_len = header[1];
  248. ccif_pkg_len = CCIF_HEADER_LEN + ccci_pkg_len + CCIF_FOOTER_LEN;
  249. /* 8 byte align */
  250. ccif_pkg_len = (((ccif_pkg_len + 7) >> 3) << 3);
  251. if (ccif_pkg_len > size) {
  252. CCCI_ERR_MSG(md_id, TAG, "rbrdb:header ccif_pkg_len(%d) > all data size(%d)\n", ccif_pkg_len, size);
  253. return -CCCI_RINGBUF_NOT_COMPLETE;
  254. }
  255. footer_pos = read + ccif_pkg_len - CCIF_FOOTER_LEN;
  256. if (footer_pos >= length)
  257. footer_pos -= length;
  258. outptr = (unsigned char *)footer;
  259. CCIF_RBF_READ(rx_buffer, outptr, CCIF_FOOTER_LEN, footer_pos, length);
  260. if (footer[0] != CCIF_PKG_FOOTER || footer[1] != CCIF_PKG_FOOTER) {
  261. CCCI_ERR_MSG(md_id, TAG,
  262. "rbrdb:ccif_pkg_len=0x%x,footer_pos=0x%x, footer 0x%x %x!=0xCCDDEEFF CCDDEEFF\n",
  263. ccif_pkg_len, footer_pos, footer[0], footer[1]);
  264. ccci_ringbuf_dump(md_id, "readable", rx_buffer, read, length, ccif_pkg_len + 8);
  265. return -CCCI_RINGBUF_BAD_FOOTER;
  266. }
  267. return ccci_pkg_len;
  268. }
  269. int ccci_ringbuf_read(int md_id, struct ccci_ringbuf *ringbuf, unsigned char *buf, int read_size)
  270. {
  271. unsigned int read, write, length;
  272. if (ringbuf == NULL || read_size == 0 || buf == NULL)
  273. return -CCCI_RINGBUF_PARAM_ERR;
  274. read = (unsigned int)(ringbuf->rx_control.read);
  275. write = (unsigned int)(ringbuf->rx_control.write);
  276. length = (unsigned int)(ringbuf->rx_control.length);
  277. /* skip header */
  278. read += CCIF_HEADER_LEN;
  279. if (read >= length)
  280. read -= length;
  281. CCIF_RBF_READ(ringbuf->buffer, buf, read_size, read, length);
  282. return read_size;
  283. }
  284. void ccci_ringbuf_move_rpointer(int md_id, struct ccci_ringbuf *ringbuf, int read_size)
  285. {
  286. unsigned int read, length;
  287. read = (unsigned int)(ringbuf->rx_control.read);
  288. length = (unsigned int)(ringbuf->rx_control.length);
  289. /* Update read pointer */
  290. read += read_size + CCIF_HEADER_LEN + CCIF_FOOTER_LEN;
  291. /* 8 byte align */
  292. read = (((read + 7) >> 3) << 3);
  293. if (read >= length)
  294. read -= length;
  295. ringbuf->rx_control.read = read;
  296. }
  297. void ccci_ringbuf_reset(int md_id, struct ccci_ringbuf *ringbuf, int dir)
  298. {
  299. if (dir == 0) {
  300. ringbuf->rx_control.read = 0;
  301. ringbuf->rx_control.write = 0;
  302. CCCI_DBG_MSG(md_id, TAG, "rbrst:rbf=%p rx\n", ringbuf);
  303. } else {
  304. ringbuf->tx_control.read = 0;
  305. ringbuf->tx_control.write = 0;
  306. CCCI_DBG_MSG(md_id, TAG, "rbrst:rbf=%p tx\n", ringbuf);
  307. }
  308. }