virtqueue.h 7.9 KB

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