2 * Copyright (c) 2014 ETH Zurich.
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
10 #ifndef VIRTIO_VIRTQUEUE_H
11 #define VIRTIO_VIRTQUEUE_H
13 #include <barrelfish/barrelfish.h>
16 * Extracted from the Virtio Specification 1.0
17 * http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf
21 * Size is determined by a 16bit integer.
22 * The queue consists of a descriptor table, available ring, used ring
23 * Each of the three parts are physically-contiguous in guest memory.
30 /// interrupt handler for virtqueue interrupts
31 typedef void (*virtq_intr_hander_t)(struct virtqueue *, void *);
33 /// the maximum length of the name field
34 #define VIRTQUEUE_NAME_SIZE 32
36 /// the maximum number of elements in a vring
37 #define VIRTQUEUE_SIZE_MAX (1<<15)
39 /// this value marks the end of a descriptor chain
40 #define VIRTQUEUE_CHAIN_END VIRTQUEUE_SIZE_MAX
42 /// Feature flag indicating that the ring supports indirect descriptors
43 #define VIRTIO_RING_F_INDIRECT_DESC (1 << 28)
45 /// Feature flag indicating that the ring supports interrupt suppression
46 #define VIRTIO_RING_F_EVENT_IDX (1 << 29)
50 * this structure holds necessary data to allocate a new virtqueue
52 struct virtqueue_setup {
53 char name[VIRTQUEUE_NAME_SIZE]; ///< the name of the queue
54 struct virtio_device *device; ///< device this queue belongs to
55 uint16_t queue_id; ///< queue id of this queue
56 uint16_t vring_ndesc; ///< size of the vring
57 lvaddr_t vring_align; ///< alignment of the vring
58 virtq_intr_hander_t intr_handler; ///< interrupt handler function
59 void *intr_arg; ///< argument for the interrupt handler
60 uint16_t max_indirect; ///< maximum indirect descriptors
66 enum virtqueue_intr_postpone {
67 VIRTQUEUE_INTR_POSTPONE_SHORT,
68 VIRTQUEUE_INTR_POSTPONE_LONG,
69 VIRTQUEUE_INTR_POSTPONE_EMPTIED,
74 * \brief allocates and initiates a new virtqueue structure
76 * \param setup pointer to the setup information
77 * \param vq pointer where to store the new virtqueue pointer
79 * \returns SYS_ERR_OK on success
81 errval_t virtio_virtqueue_alloc(struct virtqueue_setup *setup,
82 struct virtqueue **vq);
85 * \brief allocates and initiates a new virtqueue structure
87 * \param setup pointer to the setup information
88 * \param vring_cap capability to be used for the vring
89 * \param vq pointer where to store the new virtqueue pointer
91 * \returns SYS_ERR_OK on success
93 errval_t virtio_virtqueue_alloc_with_caps(struct virtqueue_setup *setup,
94 struct capref vring_cap,
95 struct virtqueue **vq);
98 * \brief frees the resources of previously allocated virtqueues
100 * \param vq pointer to the virtqueue memory to be freed
102 * \returns SYS_ERR_OK on success
104 errval_t virtio_virtqueue_free(struct virtqueue *vq);
107 void *virtqueue_drain(struct virtqueue *vq, int *last);
108 int virtqueue_reinit(struct virtqueue *vq, uint16_t size);
113 * ===========================================================================
114 * Getter functions for certain values of the virtqueue structure
118 * \brief Returns the physical address of the vring.
120 * \param vq pointer to the virtqueue structure
122 * \returns the physical address of the vring
124 lpaddr_t virtio_virtqueue_get_vring_paddr(struct virtqueue *vq);
128 * \brief Returns the frame capability of the vring
130 * \param vq pointer to the virtqueue structure
131 * \param ret_cap memory location where to store the capref
133 void virtio_virtqueue_get_vring_cap(struct virtqueue *vq,
134 struct capref *ret_cap);
137 * \brief Returns the queue index of the virtqueue of the device
139 * \param vq pointer to the virtqueue structure
141 * \returns queue index
143 uint16_t virtio_virtqueue_get_queue_index(struct virtqueue *vq);
146 * \brief returns the alignment of the vring
148 * \param the virtqueue to get the alignment from
150 * \returns vring alignment
152 lvaddr_t virtio_virtqueue_get_vring_align(struct virtqueue *vq);
155 * \brief Returns the number of elements (number of descriptors)in the vring of
158 * \param vq pointer to the virtqueue structure
160 * \returns number of elements in the vring
162 uint16_t virtio_virtqueue_get_num_desc(struct virtqueue *vq);
165 * \brief Checks if the virtqueue is empty
167 * \param vq pointer to the virtqueue structure
169 * \returns 0 the queue is not empty
170 * 1 the queue is empty
172 bool virtio_virtqueue_is_empty(struct virtqueue *vq);
175 * \brief Checks if the virtqueue is full
177 * \param vq pointer to the virtqueue structure
179 * \returns 0 the queue is not full
180 * 1 the queue is full
182 bool virtio_virtqueue_is_full(struct virtqueue *vq);
185 * \brief Calculates the number of used descriptors in this queue
187 * \param vq pointer to the virtqueue structure
189 * \returns number of used descriptors
191 uint16_t virtio_virtqueue_get_num_used(struct virtqueue *vq);
195 * ===========================================================================
200 * \brief enables the interrupts on the next descriptor processed
202 * \param vq the virtqueue to enable the interrupts
204 * \returns 1 if the interrupts have been enabled
205 * 0 if the interrupts have not been enabled
207 bool virtio_virtqueue_intr_enable(struct virtqueue *vq);
210 * \brief postpones the interrupt to a later point of time
212 * \param vq the virtqueue to enable the interrupts
215 * \returns 1 if the interrupts have been enabled
216 * 0 if the interrupts have not been enabled
218 bool virtio_virtqueue_intr_postpone(struct virtqueue *vq,
219 enum virtqueue_intr_postpone hint);
222 * \brief checks if the interrupts can be disabled
224 * \param vq virtual queue to check
226 * \returns 1 if the interrupts have been disabled
227 * 0 if the interrupts are not changed
230 bool virtio_virtqueue_intr_filter(struct virtqueue *vq);
233 * \brief calls the interrupt handler for this virtqueue
235 * \param vq virtqueue to call the intr handler for
237 void virtio_virtqueue_intr_handle(struct virtqueue *vq);
240 * \brief disables the interrupts for the given virtqueue by giving a hint
243 * \param vq virtqueue to disable the interrupts
245 void virtio_virtqueue_intr_disable(struct virtqueue *vq);
249 * \brief notifies the host about the new queued descriptors
251 * \param vq virtqueue to notify the host
253 void virtio_virtqueue_notify_host(struct virtqueue *vq);
257 * \brief masks the ring features out of a features bit mask
259 * \param features the features to mask
261 * \returns bitmask of masked features
263 static inline uint64_t virtio_virtqueue_mask_features(uint64_t features)
267 mask = (1 << VIRTIO_TRANSPORT_F_START) - 1;
268 mask |= VIRTIO_RING_F_INDIRECT_DESC;
269 mask |= VIRTIO_RING_F_EVENT_IDX;
271 return (features & mask);
275 * ===========================================================================
276 * Virtqueue Queue Management
279 errval_t virtio_virtqueue_desc_enqueue(struct virtqueue *vq,
280 struct virtio_buffer *buf,
286 int virtqueue_enqueue(struct virtqueue *vq, void *cookie,
287 struct sglist *sg, int readable, int writable);
288 void *virtqueue_dequeue(struct virtqueue *vq, uint32_t *len);
289 void *virtqueue_poll(struct virtqueue *vq, uint32_t *len);
293 uint64_t virtqueue_filter_features(uint64_t features);
295 void virtqueue_dump(struct virtqueue *vq);
299 #endif // VIRTIO_VIRTQUEUE_H