acts_ringbuf.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. /*
  2. * Copyright (c) 1997-2015, Actions Semi Co., Inc.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <os_common_api.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. #include <stdint.h>
  10. #include <mem_manager.h>
  11. #include <acts_ringbuf.h>
  12. #ifdef CONFIG_DSP
  13. #include <soc_dsp.h>
  14. #endif
  15. int acts_ringbuf_init(struct acts_ringbuf *buf, void *data, uint32_t size)
  16. {
  17. buf->head = 0;
  18. buf->head_offset = 0;
  19. buf->tail = 0;
  20. buf->tail_offset = 0;
  21. buf->size = size;
  22. if (is_power_of_two(size)) {
  23. buf->mask = size - 1;
  24. } else {
  25. buf->mask = 0;
  26. }
  27. buf->cpu_ptr = (uint32_t)data;
  28. #ifdef CONFIG_DSP
  29. buf->dsp_ptr = mcu_to_dsp_data_address(buf->cpu_ptr);
  30. #else
  31. buf->dsp_ptr = 0;
  32. #endif
  33. return 0;
  34. }
  35. struct acts_ringbuf *acts_ringbuf_init_ext(void *data, uint32_t size)
  36. {
  37. struct acts_ringbuf *buf;
  38. buf = mem_malloc(sizeof(*buf));
  39. if (buf)
  40. acts_ringbuf_init(buf, data, size);
  41. return buf;
  42. }
  43. void acts_ringbuf_destroy_ext(struct acts_ringbuf *buf)
  44. {
  45. if (buf)
  46. mem_free(buf);
  47. }
  48. struct acts_ringbuf *acts_ringbuf_alloc(uint32_t size)
  49. {
  50. struct acts_ringbuf *buf = NULL;
  51. void *data = NULL;
  52. buf = mem_malloc(sizeof(*buf));
  53. if (buf == NULL)
  54. return NULL;
  55. data = mem_malloc(ACTS_RINGBUF_SIZE8(size));
  56. if (data == NULL) {
  57. mem_free(buf);
  58. return NULL;
  59. }
  60. acts_ringbuf_init(buf, data, size);
  61. return buf;
  62. }
  63. void acts_ringbuf_free(struct acts_ringbuf *buf)
  64. {
  65. if (buf) {
  66. mem_free((void *)(buf->cpu_ptr));
  67. mem_free(buf);
  68. }
  69. }
  70. uint32_t acts_ringbuf_peek(struct acts_ringbuf *buf, void *data, uint32_t size)
  71. {
  72. uint32_t offset, len;
  73. len = acts_ringbuf_length(buf);
  74. if (size > len)
  75. return 0;
  76. offset = buf->head_offset;
  77. len = buf->size - offset;
  78. if (data) {
  79. if (len >= size) {
  80. memcpy(data, (void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset)), ACTS_RINGBUF_SIZE8(size));
  81. } else {
  82. memcpy(data, (void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset)), ACTS_RINGBUF_SIZE8(len));
  83. memcpy((uint8_t *)data + ACTS_RINGBUF_SIZE8(len), (void *)(buf->cpu_ptr), ACTS_RINGBUF_SIZE8(size - len));
  84. }
  85. }
  86. return size;
  87. }
  88. uint32_t acts_ringbuf_get(struct acts_ringbuf *buf, void *data, uint32_t size)
  89. {
  90. size = acts_ringbuf_peek(buf, data, size);
  91. buf->head += size;
  92. buf->head_offset += size;
  93. if (buf->head_offset >= buf->size)
  94. buf->head_offset -= buf->size;
  95. return size;
  96. }
  97. uint32_t acts_ringbuf_get_claim(struct acts_ringbuf *buf, void **data, uint32_t size)
  98. {
  99. uint32_t offset = buf->head_offset;
  100. uint32_t max_size = min(buf->size - offset, acts_ringbuf_length(buf));
  101. *data = (void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset));
  102. return (size <= max_size) ? size : max_size;
  103. }
  104. int acts_ringbuf_get_finish(struct acts_ringbuf *buf, uint32_t size)
  105. {
  106. uint32_t offset = buf->head_offset;
  107. uint32_t max_size = min(buf->size - offset, acts_ringbuf_length(buf));
  108. if (size > max_size)
  109. return -EINVAL;
  110. buf->head += size;
  111. buf->head_offset += size;
  112. if (buf->head_offset >= buf->size)
  113. buf->head_offset -= buf->size;
  114. return 0;
  115. }
  116. uint32_t acts_ringbuf_put(struct acts_ringbuf *buf, const void *data, uint32_t size)
  117. {
  118. uint32_t offset, len;
  119. len = acts_ringbuf_space(buf);
  120. if (size > len)
  121. return 0;
  122. offset = buf->tail_offset;
  123. len = buf->size - offset;
  124. if (data) {
  125. if (len >= size) {
  126. memcpy((void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset)), data, ACTS_RINGBUF_SIZE8(size));
  127. } else {
  128. memcpy((void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset)), data, ACTS_RINGBUF_SIZE8(len));
  129. memcpy((void *)(buf->cpu_ptr), (uint8_t *)data + ACTS_RINGBUF_SIZE8(len), ACTS_RINGBUF_SIZE8(size - len));
  130. }
  131. }
  132. buf->tail += size;
  133. buf->tail_offset += size;
  134. if (buf->tail_offset >= buf->size)
  135. buf->tail_offset -= buf->size;
  136. return size;
  137. }
  138. uint32_t acts_ringbuf_put_claim(struct acts_ringbuf *buf, void **data, uint32_t size)
  139. {
  140. uint32_t offset = buf->tail_offset;
  141. uint32_t max_size = min(buf->size - offset, acts_ringbuf_space(buf));
  142. *data = (void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset));
  143. return (size <= max_size) ? size : max_size;
  144. }
  145. int acts_ringbuf_put_finish(struct acts_ringbuf *buf, uint32_t size)
  146. {
  147. uint32_t offset = buf->tail_offset;
  148. uint32_t max_size = min(buf->size - offset, acts_ringbuf_space(buf));
  149. if (size > max_size)
  150. return -EINVAL;
  151. buf->tail += size;
  152. buf->tail_offset += size;
  153. if (buf->tail_offset >= buf->size)
  154. buf->tail_offset -= buf->size;
  155. return 0;
  156. }
  157. uint32_t acts_ringbuf_copy(struct acts_ringbuf *dst_buf, struct acts_ringbuf *src_buf, uint32_t size)
  158. {
  159. uint32_t src_length = acts_ringbuf_length(src_buf);
  160. uint32_t dst_space = acts_ringbuf_space(dst_buf);
  161. uint32_t src_offset, dst_offset;
  162. uint32_t len, copy_len;
  163. if (size > src_length)
  164. size = src_length;
  165. if (size > dst_space)
  166. size = dst_space;
  167. if (size == 0)
  168. return 0;
  169. src_offset = src_buf->head_offset;
  170. dst_offset = dst_buf->tail_offset;
  171. copy_len = size;
  172. do {
  173. len = min(src_buf->size - src_offset, dst_buf->size - dst_offset);
  174. if (len > size)
  175. len = size;
  176. memcpy((void *)(dst_buf->cpu_ptr + ACTS_RINGBUF_SIZE8(dst_offset)),
  177. (void *)(src_buf->cpu_ptr + ACTS_RINGBUF_SIZE8(src_offset)),
  178. ACTS_RINGBUF_SIZE8(len));
  179. size -= len;
  180. if (size == 0)
  181. break;
  182. src_offset += len;
  183. if (src_offset >= src_buf->size)
  184. src_offset = 0;
  185. dst_offset += len;
  186. if (dst_offset >= dst_buf->size)
  187. dst_offset = 0;
  188. } while (1);
  189. src_buf->head += copy_len;
  190. src_buf->head_offset += copy_len;
  191. if (src_buf->head_offset >= src_buf->size)
  192. src_buf->head_offset -= src_buf->size;
  193. dst_buf->tail += copy_len;
  194. dst_buf->tail_offset += copy_len;
  195. if (dst_buf->tail_offset >= dst_buf->size)
  196. dst_buf->tail_offset -= dst_buf->size;
  197. return copy_len;
  198. }
  199. uint32_t acts_ringbuf_read(struct acts_ringbuf *buf,
  200. void *stream, uint32_t size, acts_ringbuf_write_fn stream_write)
  201. {
  202. uint32_t offset, len;
  203. int stream_len = 0;
  204. len = acts_ringbuf_length(buf);
  205. if (size > len)
  206. return 0;
  207. offset = buf->head_offset;
  208. len = buf->size - offset;
  209. if (len >= size) {
  210. stream_len = stream_write(stream,
  211. (void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset)),
  212. ACTS_RINGBUF_SIZE8(size));
  213. } else {
  214. stream_len = stream_write(stream,
  215. (void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset)),
  216. ACTS_RINGBUF_SIZE8(len));
  217. if (stream_len == ACTS_RINGBUF_SIZE8(len)) {
  218. uint32_t tmp = stream_write(stream, (void *)(buf->cpu_ptr),
  219. ACTS_RINGBUF_SIZE8(size - len));
  220. if (tmp > 0)
  221. stream_len += tmp;
  222. }
  223. }
  224. if (stream_len > 0) {
  225. stream_len = ACTS_RINGBUF_NELEM(stream_len);
  226. buf->head += stream_len;
  227. buf->head_offset += stream_len;
  228. if (buf->head_offset >= buf->size)
  229. buf->head_offset -= buf->size;
  230. return stream_len;
  231. }
  232. return 0;
  233. }
  234. uint32_t acts_ringbuf_write(struct acts_ringbuf *buf,
  235. void *stream, uint32_t size, acts_ringbuf_read_fn stream_read)
  236. {
  237. uint32_t offset, len;
  238. int stream_len = 0;
  239. len = acts_ringbuf_space(buf);
  240. if (size > len)
  241. return 0;
  242. offset = buf->tail_offset;
  243. len = buf->size - offset;
  244. if (len >= size) {
  245. stream_len = stream_read(stream,
  246. (void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset)),
  247. ACTS_RINGBUF_SIZE8(size));
  248. } else {
  249. stream_len = stream_read(stream,
  250. (void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset)),
  251. ACTS_RINGBUF_SIZE8(len));
  252. if (stream_len == ACTS_RINGBUF_SIZE8(len)) {
  253. uint32_t tmp = stream_read(stream, (void *)(buf->cpu_ptr),
  254. ACTS_RINGBUF_SIZE8(size - len));
  255. if (tmp > 0)
  256. stream_len += tmp;
  257. }
  258. }
  259. if (stream_len > 0) {
  260. stream_len = ACTS_RINGBUF_NELEM(stream_len);
  261. buf->tail += stream_len;
  262. buf->tail_offset += stream_len;
  263. if (buf->tail_offset >= buf->size)
  264. buf->tail_offset -= buf->size;
  265. return stream_len;
  266. }
  267. return 0;
  268. }
  269. uint32_t acts_ringbuf_drop(struct acts_ringbuf *buf, uint32_t size)
  270. {
  271. uint32_t length = acts_ringbuf_length(buf);
  272. if (size > length)
  273. return 0;
  274. buf->head += size;
  275. buf->head_offset += size;
  276. if (buf->head_offset >= buf->size)
  277. buf->head_offset -= buf->size;
  278. return size;
  279. }
  280. uint32_t acts_ringbuf_drop_all(struct acts_ringbuf *buf)
  281. {
  282. uint32_t length = acts_ringbuf_length(buf);
  283. buf->head += length;
  284. buf->head_offset += length;
  285. if (buf->head_offset >= buf->size)
  286. buf->head_offset -= buf->size;
  287. return length;
  288. }
  289. uint32_t acts_ringbuf_fill(struct acts_ringbuf *buf, uint8_t c, uint32_t size)
  290. {
  291. uint32_t offset, len;
  292. len = acts_ringbuf_space(buf);
  293. if (size > len)
  294. return 0;
  295. offset = buf->tail_offset;
  296. len = buf->size - offset;
  297. if (len >= size) {
  298. memset((void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset)), c, ACTS_RINGBUF_SIZE8(size));
  299. } else {
  300. memset((void *)(buf->cpu_ptr + ACTS_RINGBUF_SIZE8(offset)), c, ACTS_RINGBUF_SIZE8(len));
  301. memset((void *)(buf->cpu_ptr), c, ACTS_RINGBUF_SIZE8(size - len));
  302. }
  303. buf->tail += size;
  304. buf->tail_offset += size;
  305. if (buf->tail_offset >= buf->size)
  306. buf->tail_offset -= buf->size;
  307. return size;
  308. }
  309. uint32_t acts_ringbuf_fill_none(struct acts_ringbuf *buf, uint32_t size)
  310. {
  311. uint32_t space = acts_ringbuf_space(buf);
  312. if (size > space)
  313. return 0;
  314. buf->tail += size;
  315. buf->tail_offset += size;
  316. if (buf->tail_offset >= buf->size)
  317. buf->tail_offset -= buf->size;
  318. return size;
  319. }
  320. void *acts_ringbuf_head_ptr(struct acts_ringbuf *buf, uint32_t *len)
  321. {
  322. void *data = NULL;
  323. uint32_t size;
  324. size = acts_ringbuf_get_claim(buf, &data, acts_ringbuf_length(buf));
  325. if (len)
  326. *len = size;
  327. return data;
  328. }
  329. void *acts_ringbuf_tail_ptr(struct acts_ringbuf *buf, uint32_t *len)
  330. {
  331. void *data = NULL;
  332. uint32_t size;
  333. size = acts_ringbuf_put_claim(buf, &data, acts_ringbuf_space(buf));
  334. if (len)
  335. *len = size;
  336. return data;
  337. }
  338. void acts_ringbuf_defrag(struct acts_ringbuf *buf)
  339. {
  340. uint32_t roff, woff;
  341. if (buf->head_offset == 0 || acts_ringbuf_is_empty(buf))
  342. goto out_exit;
  343. if (buf->head_offset >= buf->tail_offset) {
  344. buf->head = buf->head_offset;
  345. buf->tail = buf->tail_offset + buf->size;
  346. return;
  347. }
  348. roff = ACTS_RINGBUF_SIZE8(buf->head_offset);
  349. woff = ACTS_RINGBUF_SIZE8(buf->tail_offset);
  350. memcpy((void *)buf->cpu_ptr, (void *)(buf->cpu_ptr + roff), woff - roff);
  351. out_exit:
  352. buf->tail -= buf->head;
  353. buf->tail_offset = buf->tail;
  354. buf->head = 0;
  355. buf->head_offset = 0;
  356. }
  357. void acts_ringbuf_dump(struct acts_ringbuf *buf, const char *name, const char *line_prefix)
  358. {
  359. os_printk("%s%s: %p\n", line_prefix, name, buf);
  360. os_printk("%s\thead: 0x%x\n", line_prefix, buf->head);
  361. os_printk("%s\ttail: 0x%x\n", line_prefix, buf->tail);
  362. os_printk("%s\tlength: 0x%x\n", line_prefix, acts_ringbuf_length(buf));
  363. os_printk("%s\tsize: 0x%x\n", line_prefix, buf->size);
  364. os_printk("%s\tmask: 0x%x\n", line_prefix, buf->mask);
  365. os_printk("%s\tcpuptr: 0x%x\n", line_prefix, buf->cpu_ptr);
  366. os_printk("%s\tdspptr: 0x%x\n", line_prefix, buf->dsp_ptr);
  367. os_printk("%s\thoffset:0x%x\n", line_prefix, buf->head_offset);
  368. os_printk("%s\ttoffset:0x%x\n", line_prefix, buf->tail_offset);
  369. }