virtqueue.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #ifndef VIRTQUEUE_H_
  2. #define VIRTQUEUE_H_
  3. /*-
  4. * Copyright (c) 2011, Bryan Venteicher <bryanv@FreeBSD.org>
  5. * Copyright (c) 2016 Freescale Semiconductor, Inc.
  6. * Copyright 2016-2019 NXP
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice unmodified, this list of conditions, and the following
  14. * disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  20. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. * $FreeBSD$
  31. */
  32. #include <stdbool.h>
  33. #include <stdint.h>
  34. #include "rpmsg_default_config.h"
  35. typedef uint8_t boolean;
  36. #include "virtio_ring.h"
  37. #include "llist.h"
  38. /*Error Codes*/
  39. #define VQ_ERROR_BASE (-3000)
  40. #define ERROR_VRING_FULL (VQ_ERROR_BASE - 1)
  41. #define ERROR_INVLD_DESC_IDX (VQ_ERROR_BASE - 2)
  42. #define ERROR_EMPTY_RING (VQ_ERROR_BASE - 3)
  43. #define ERROR_NO_MEM (VQ_ERROR_BASE - 4)
  44. #define ERROR_VRING_MAX_DESC (VQ_ERROR_BASE - 5)
  45. #define ERROR_VRING_ALIGN (VQ_ERROR_BASE - 6)
  46. #define ERROR_VRING_NO_BUFF (VQ_ERROR_BASE - 7)
  47. #define ERROR_VQUEUE_INVLD_PARAM (VQ_ERROR_BASE - 8)
  48. #define VQUEUE_SUCCESS (0)
  49. #define VQUEUE_DEBUG (false)
  50. /* This is temporary macro to replace C NULL support.
  51. * At the moment all the RTL specific functions are present in env.
  52. * */
  53. #define VQ_NULL ((void *)0)
  54. /* The maximum virtqueue size is 2^15. Use that value as the end of
  55. * descriptor chain terminator since it will never be a valid index
  56. * in the descriptor table. This is used to verify we are correctly
  57. * handling vq_free_cnt.
  58. */
  59. #define VQ_RING_DESC_CHAIN_END (32768)
  60. #define VIRTQUEUE_FLAG_INDIRECT (0x0001U)
  61. #define VIRTQUEUE_FLAG_EVENT_IDX (0x0002U)
  62. #define VIRTQUEUE_MAX_NAME_SZ (32) /* mind the alignment */
  63. /* Support for indirect buffer descriptors. */
  64. #define VIRTIO_RING_F_INDIRECT_DESC (1 << 28)
  65. /* Support to suppress interrupt until specific index is reached. */
  66. #define VIRTIO_RING_F_EVENT_IDX (1 << 29)
  67. /*
  68. * Hint on how long the next interrupt should be postponed. This is
  69. * only used when the EVENT_IDX feature is negotiated.
  70. */
  71. typedef enum
  72. {
  73. VQ_POSTPONE_SHORT,
  74. VQ_POSTPONE_LONG,
  75. VQ_POSTPONE_EMPTIED /* Until all available desc are used. */
  76. } vq_postpone_t;
  77. /* local virtqueue representation, not in shared memory */
  78. struct virtqueue
  79. {
  80. /* 32bit aligned { */
  81. char vq_name[VIRTQUEUE_MAX_NAME_SZ];
  82. uint32_t vq_flags;
  83. int32_t vq_alignment;
  84. int32_t vq_ring_size;
  85. void *vq_ring_mem;
  86. void (*callback_fc)(struct virtqueue *vq);
  87. void (*notify_fc)(struct virtqueue *vq);
  88. int32_t vq_max_indirect_size;
  89. int32_t vq_indirect_mem_size;
  90. struct vring vq_ring;
  91. /* } 32bit aligned */
  92. /* 16bit aligned { */
  93. uint16_t vq_queue_index;
  94. uint16_t vq_nentries;
  95. uint16_t vq_free_cnt;
  96. uint16_t vq_queued_cnt;
  97. /*
  98. * Head of the free chain in the descriptor table. If
  99. * there are no free descriptors, this will be set to
  100. * VQ_RING_DESC_CHAIN_END.
  101. */
  102. uint16_t vq_desc_head_idx;
  103. /*
  104. * Last consumed descriptor in the used table,
  105. * trails vq_ring.used->idx.
  106. */
  107. uint16_t vq_used_cons_idx;
  108. /*
  109. * Last consumed descriptor in the available table -
  110. * used by the consumer side.
  111. */
  112. uint16_t vq_available_idx;
  113. /* } 16bit aligned */
  114. boolean avail_read; /* 8bit wide */
  115. boolean avail_write; /* 8bit wide */
  116. boolean used_read; /* 8bit wide */
  117. boolean used_write; /* 8bit wide */
  118. uint16_t padd; /* aligned to 32bits after this: */
  119. void *priv; /* private pointer, upper layer instance pointer */
  120. #if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1)
  121. void *env; /* private pointer to environment layer internal context */
  122. #endif
  123. };
  124. /* struct to hold vring specific information */
  125. struct vring_alloc_info
  126. {
  127. void *phy_addr;
  128. uint32_t align;
  129. uint16_t num_descs;
  130. uint16_t pad;
  131. };
  132. #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
  133. struct vq_static_context
  134. {
  135. struct virtqueue vq;
  136. };
  137. #endif
  138. typedef void vq_callback(struct virtqueue *vq);
  139. typedef void vq_notify(struct virtqueue *vq);
  140. #if (VQUEUE_DEBUG == true)
  141. #define VQASSERT_BOOL(_vq, _exp, _msg) \
  142. do \
  143. { \
  144. if (!(_exp)) \
  145. { \
  146. env_print("%s: %s - "(_msg), __func__, (_vq)->vq_name); \
  147. while (1) \
  148. { \
  149. }; \
  150. } \
  151. } while (0)
  152. #define VQASSERT(_vq, _exp, _msg) VQASSERT_BOOL(_vq, (_exp) != 0, _msg)
  153. #define VQ_RING_ASSERT_VALID_IDX(_vq, _idx) VQASSERT((_vq), (_idx) < (_vq)->vq_nentries, "invalid ring index")
  154. #define VQ_PARAM_CHK(condition, status_var, status_err) \
  155. if ((status_var == 0) && (condition)) \
  156. { \
  157. status_var = status_err; \
  158. }
  159. #define VQUEUE_BUSY(vq, dir) \
  160. if ((vq)->dir == false) \
  161. { \
  162. (vq)->dir = true; \
  163. } \
  164. else \
  165. { \
  166. VQASSERT(vq, (vq)->dir == false, "VirtQueue already in use") \
  167. }
  168. #define VQUEUE_IDLE(vq, dir) ((vq)->dir = false)
  169. #else
  170. #define KASSERT(cond, str)
  171. #define VQASSERT(_vq, _exp, _msg)
  172. #define VQ_RING_ASSERT_VALID_IDX(_vq, _idx)
  173. #define VQ_PARAM_CHK(condition, status_var, status_err)
  174. #define VQUEUE_BUSY(vq, dir)
  175. #define VQUEUE_IDLE(vq, dir)
  176. #endif
  177. #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
  178. int32_t virtqueue_create_static(uint16_t id,
  179. const char *name,
  180. struct vring_alloc_info *ring,
  181. void (*callback_fc)(struct virtqueue *vq),
  182. void (*notify_fc)(struct virtqueue *vq),
  183. struct virtqueue **v_queue,
  184. struct vq_static_context *vq_ctxt);
  185. #else
  186. int32_t virtqueue_create(uint16_t id,
  187. const char *name,
  188. struct vring_alloc_info *ring,
  189. void (*callback_fc)(struct virtqueue *vq),
  190. void (*notify_fc)(struct virtqueue *vq),
  191. struct virtqueue **v_queue);
  192. #endif
  193. int32_t virtqueue_add_buffer(struct virtqueue *vq, uint16_t head_idx);
  194. int32_t virtqueue_fill_used_buffers(struct virtqueue *vq, void *buffer, uint32_t len);
  195. int32_t virtqueue_fill_avail_buffers(struct virtqueue *vq, void *buffer, uint32_t len);
  196. void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx);
  197. void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx, uint32_t *len);
  198. int32_t virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx, uint32_t len);
  199. void virtqueue_disable_cb(struct virtqueue *vq);
  200. int32_t virtqueue_enable_cb(struct virtqueue *vq);
  201. void virtqueue_kick(struct virtqueue *vq);
  202. #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
  203. void virtqueue_free_static(struct virtqueue *vq);
  204. #else
  205. void virtqueue_free(struct virtqueue *vq);
  206. #endif
  207. void virtqueue_dump(struct virtqueue *vq);
  208. void virtqueue_notification(struct virtqueue *vq);
  209. uint32_t virtqueue_get_desc_size(struct virtqueue *vq);
  210. uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx);
  211. void vq_ring_init(struct virtqueue *vq);
  212. #endif /* VIRTQUEUE_H_ */