Bugfixes Xeon Phi Driver startup - removed check for boot info - added initialization...
[barrelfish] / lib / virtio / virtqueue.c
1 /*
2  * Copyright (c) 2014 ETH Zurich.
3  * All rights reserved.
4  *
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.
8  */
9 #include <string.h>
10
11 #include <barrelfish/barrelfish.h>
12
13 #include <virtio/virtio.h>
14 #include <virtio/virtio_ring.h>
15 #include <virtio/virtqueue.h>
16 #include <virtio/virtio_device.h>
17
18 #include "debug.h"
19
20
21 #define IS_POW2(num) (((num) != 0) && (((num) & (~(num) + 1)) == (num)))
22
23
24 #define VIRTQUEUE_FLAG_INDIRECT  0x0001
25 #define VIRTQUEUE_FLAG_EVENT_IDX 0x0002
26 #define VIRTQUEUE_FLAG_FREE_CAP  0x8000
27
28 /**
29  * this data structure stores additional information to the descriptors
30  */
31 struct vring_desc_info
32 {
33     struct virtio_buffer *buf;
34     void *st;
35     uint8_t is_head;
36
37 };
38
39 /**
40  * this data structure represents a VirtIO queue. It contains additional
41  * information not stored with the vring structure
42  */
43 struct virtqueue
44 {
45     /* device information */
46     struct virtio_device *device;       ///< pointer to to the virtio device
47     uint16_t              queue_index;  ///< index of this queue in the device
48     char name[VIRTQUEUE_NAME_SIZE];     ///< name of the queue for debugging
49
50     /* vring information */
51     struct vring vring;                 ///< vring data structure
52     uint16_t vring_ndesc;               ///< number of descriptors of this vring
53     uint32_t flags;                     ///< flags
54     uint16_t free_head;                 ///< head of the free descriptor chain
55     uint16_t free_count;                ///< number of available free descriptors
56     uint16_t used_tail;                 ///< last consumed descriptor used table
57     uint16_t queued_count;              ///< number of queued used descriptors
58
59     /* vring memory information */
60     struct capref vring_cap;            ///< capability of the vring data structure
61     lvaddr_t vring_vaddr;               ///< virtual address of the vring in memory
62     lpaddr_t vring_paddr;               ///< physical address of the vring
63     size_t vring_size;                  ///< the size of the vring in memory
64     lvaddr_t vring_align;               ///< the alignment of the vring
65
66     /* interrupt handling */
67     virtq_intr_hander_t intr_handler;   ///< interrupt handler
68     void               *intr_arg;       ///< user argument for the handler
69
70     struct vring_desc_info vring_di[0]; ///< array of additional desc information
71 #if 0
72     /* indirect descriptors */
73     uint16_t max_indirect;
74     size_t   indirect_size;
75     struct vq_desc_extra {
76             void          *cookie;  << virtual address?
77             struct vring_desc *indirect;
78             vm_paddr_t     indirect_paddr;
79             uint16_t       ndescs;
80         } vq_descx[0];
81 #endif
82 };
83
84 /**
85  * \brief sets the interrupt threshold to num_desc processed descriptors
86  *
87  * \param vq        virtqueue to enable the interrupts
88  * \param num_desc  the interrupt threshold
89  *
90  * \returns 1 if the interrupts have been enabled
91  *          0 if the interrupts have not been enabled
92  */
93 static bool virtqueue_interrupt_enable(struct virtqueue *vq,
94                                        uint16_t num_desc)
95 {
96     if (vq->flags & VIRTQUEUE_FLAG_EVENT_IDX) {
97         uint16_t *used_event = vring_get_used_event(&vq->vring);
98         *used_event = vq->used_tail + num_desc;
99     } else {
100         vq->vring.avail->flags &= ~VIRTIO_RING_AVAIL_F_NO_INTERRUPT;
101     }
102
103     assert(!"NYI: memory barrier mb()");
104
105     if (virtio_virtqueue_get_num_used(vq) > num_desc) {
106         return 1;
107     }
108
109     return 0;
110 }
111
112
113 /**
114  * \brief initializes the vring structure of the virtqueue
115  *
116  * \param vq virtqueue of the vring to initialize
117  */
118 static void virtqueue_init_vring(struct virtqueue *vq)
119 {
120     struct vring *vr = &vq->vring;
121
122     assert(vq);
123     assert(vq->vring_ndesc);
124     assert(vq->vring_vaddr);
125
126     /*
127      * initialize the vring structure in memory
128      */
129     vring_init(vr, vq->vring_ndesc, vq->vring_align, (void *)vq->vring_vaddr);
130
131     /*
132      * initialize the descriptor chains
133      */
134     uint32_t i;
135     for (i = 0; i < vq->vring_ndesc; ++i) {
136         vr->desc[i].next = i+1;
137     }
138     vr->desc[i].next = VIRTQUEUE_CHAIN_END;
139
140 }
141
142 /**
143  * \brief initializes the indirect descriptors
144  *
145  * \param vq the virtqueue to initialize the indirect descriptors
146  * \param size the number of indirect descriptors
147  *
148  * \returns SYS_ERR_OK on success
149  */
150 static errval_t virtqueue_init_indirect(struct virtqueue *vq,
151                                         uint16_t size)
152 {
153     struct virtio_device *vdev = vq->device;
154
155     /*
156      * check if the device supports indirect descriptors first
157      */
158     if (virtio_device_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC)) {
159         VIRTIO_DEBUG_VQ("Device does not support indirect descriptors\n");
160         return SYS_ERR_OK;
161     }
162
163     assert(!"NYI: virtqueue_init_indirect");
164
165     return SYS_ERR_OK;
166 }
167
168
169 static bool virtqueue_should_notify_host(struct virtqueue *vq)
170 {
171     uint16_t new, prev, *event_idx;
172
173     if (vq->flags & VIRTQUEUE_FLAG_EVENT_IDX) {
174         new = vq->vring.avail->idx;
175         prev = new - vq->queued_count;
176         event_idx = vring_get_avail_event(&vq->vring);
177
178         return (vring_need_event(*event_idx, new, prev) != 0);
179     }
180
181     return ((vq->vring.used->flags & VIRTIO_RING_USED_F_NO_NOTIFY) == 0);
182 }
183
184
185 /*
186  * ============================================================================
187  * Public Interface
188  * ============================================================================
189  */
190
191
192 /*
193  * ----------------------------------------------------------------------------
194  *  Virtqueue Allocation / Deallocation
195  */
196
197 /**
198  * \brief allocates and initiates a new virtqueue structure
199  *
200  * \param setup  pointer to the setup information
201  * \param vq     pointer where to store the new virtqueue pointer
202  *
203  * \returns SYS_ERR_OK on success
204  */
205 errval_t virtio_virtqueue_alloc(struct virtqueue_setup *setup,
206                                 struct virtqueue **vq)
207 {
208     errval_t err;
209
210     assert(vq);
211
212     if (setup->vring_ndesc == 0 || !IS_POW2(setup->vring_ndesc)) {
213         VIRTIO_DEBUG_VQ("ERROR: invalid size: %u\n", setup->vring_ndesc);
214         return VIRTIO_ERR_SIZE_INVALID;
215     }
216
217     size_t size = vring_size(setup->vring_ndesc, setup->vring_align);
218     size = ROUND_UP(size, BASE_PAGE_SIZE);
219
220     struct capref vring_cap;
221     size_t framesize;
222     err = frame_alloc(&vring_cap, size, &framesize);
223     if (err_is_fail(err)) {
224         return err;
225     }
226
227     VIRTIO_DEBUG_VQ("Allocated memory for vring: [%lx & %lx]",
228                     (uint64_t)size, (uint64_t)framesize);
229
230     err = virtio_virtqueue_alloc_with_caps(setup, vring_cap, vq);
231     if (err_is_fail(err)) {
232         cap_destroy(vring_cap);
233         return err;
234     }
235
236     /* set the flag that we have allocated the cap, so that it gets free'd */
237     (*vq)->flags |= VIRTQUEUE_FLAG_FREE_CAP;
238
239     return SYS_ERR_OK;
240 }
241
242 /**
243  * \brief allocates and initiates a new virtqueue structure
244  *
245  * \param setup     pointer to the setup information
246  * \param vring_cap capability to be used for the vring
247  * \param vq        pointer where to store the new virtqueue pointer
248  *
249  * \returns SYS_ERR_OK on success
250  */
251 errval_t virtio_virtqueue_alloc_with_caps(struct virtqueue_setup *setup,
252                                           struct capref vring_cap,
253                                           struct virtqueue **ret_vq)
254 {
255     errval_t err;
256
257     assert(ret_vq);
258
259     if (setup->vring_ndesc == 0 || !IS_POW2(setup->vring_ndesc)) {
260         VIRTIO_DEBUG_VQ("ERROR: invalid size: %u\n", setup->vring_ndesc);
261         return VIRTIO_ERR_SIZE_INVALID;
262     }
263
264     if (setup->max_indirect > VIRTIO_RING_MAX_INDIRECT) {
265         VIRTIO_DEBUG_VQ("ERROR: too many indirect descriptors requested: [%u / %u]\n", setup->vring_ndesc, VIRTIO_RING_MAX_INDIRECT);
266         return VIRTIO_ERR_MAX_INDIRECT;
267     }
268
269     assert(!capref_is_null(vring_cap));
270
271     struct frame_identity id;
272     err = invoke_frame_identify(vring_cap, &id);
273     if (err_is_fail(err)) {
274         return err;
275     }
276
277     size_t vring_mem_size = vring_size(setup->vring_ndesc, setup->vring_align);
278     vring_mem_size = ROUND_UP(vring_mem_size, BASE_PAGE_SIZE);
279
280     if (vring_mem_size > (1UL << id.bits)) {
281         VIRTIO_DEBUG_VQ("ERROR: supplied cap was too small %lx, needed %lx\n",
282                         ((1UL << id.bits)), (uint64_t)vring_mem_size);
283         return VIRTIO_ERR_CAP_SIZE;
284     }
285
286     void *vring_addr;
287     err = vspace_map_one_frame(&vring_addr, vring_mem_size, vring_cap, NULL, NULL);
288     if (err_is_fail(err)) {
289         return err;
290     }
291
292     struct virtqueue *vq = calloc(1, sizeof(struct virtqueue)
293                                   + (setup->vring_ndesc * sizeof(struct vring_desc_info)));
294     if (vq == NULL) {
295         vspace_unmap(vring_addr);
296         return LIB_ERR_MALLOC_FAIL;
297     }
298
299     vq->device = setup->device;
300     strncpy(vq->name, setup->name, sizeof(vq->name));
301     vq->queue_index = setup->queue_id;
302     vq->vring_ndesc = setup->vring_ndesc;
303     vq->vring_align = setup->vring_align;
304     vq->vring_size = vring_mem_size;
305     vq->vring_cap = vring_cap;
306     vq->vring_paddr = id.base;
307     vq->vring_vaddr = (lvaddr_t)vring_addr;
308     vq->free_count = setup->vring_ndesc;
309
310
311     vq->intr_handler = setup->intr_handler;
312     vq->intr_arg = setup->intr_arg;
313
314     if (0 && setup->max_indirect > 0) {
315         /*
316          * TODO: initialize indirect descriptors
317          */
318         virtqueue_init_indirect(vq, setup->max_indirect);
319     }
320
321     if(virtio_device_has_feature(setup->device, VIRTIO_RING_F_EVENT_IDX)) {
322         vq->flags |= (1<<VIRTQUEUE_FLAG_EVENT_IDX);
323     }
324
325     virtqueue_init_vring(vq);
326     virtio_virtqueue_intr_disable(vq);
327
328     if (ret_vq) {
329         *ret_vq = vq;
330     }
331
332     return SYS_ERR_OK;
333 }
334
335
336 /**
337  * \brief frees the resources of previously allocated virtqueues
338  *
339  * \param vq pointer to the virtqueue memory to be freed
340  *
341  * \returns SYS_ERR_OK on success
342  */
343 errval_t virtio_virtqueue_free(struct virtqueue *vq)
344 {
345     assert(!"NYI: virtio_virtqueue_free");
346
347     return SYS_ERR_OK;
348 }
349
350 /*
351  * ----------------------------------------------------------------------------
352  *  Virtqueue Getter Functions
353  */
354
355 /**
356  * \brief Returns the physical address of the vring.
357  *
358  * \param vq pointer to the virtqueue structure
359  *
360  * \returns the physical address of the vring
361  */
362 lpaddr_t virtio_virtqueue_get_vring_paddr(struct virtqueue *vq)
363 {
364     return vq->vring_paddr;
365 }
366
367 /**
368  * \brief returns the alignment of the vring
369  *
370  * \param the virtqueue to get the alignment from
371  *
372  * \returns vring alignment
373  */
374 lvaddr_t virtio_virtqueue_get_vring_align(struct virtqueue *vq)
375 {
376     return vq->vring_align;
377 }
378
379 /**
380  * \brief Returns the frame capability of the vring
381  *
382  * \param vq        pointer to the virtqueue structure
383  * \param ret_cap   memory location where to store the capref
384  */
385 void virtio_virtqueue_get_vring_cap(struct virtqueue *vq,
386                                     struct capref *ret_cap)
387 {
388     if (ret_cap) {
389         *ret_cap = vq->vring_cap;
390     }
391 }
392
393 /**
394  * \brief Returns the number of elements (number of descriptors)in the vring of
395  *        this virtqueue
396  *
397  * \param vq pointer to the virtqueue structure
398  *
399  * \returns number of elements in the vring
400  */
401 uint16_t virtio_virtqueue_get_num_desc(struct virtqueue *vq)
402 {
403     return vq->vring_ndesc;
404 }
405
406 /**
407  * \brief Returns the queue index of the virtqueue of the device
408  *
409  * \param vq pointer to the virtqueue structure
410  *
411  * \returns queue index
412  */
413 uint16_t virtio_virtqueue_get_queue_index(struct virtqueue *vq)
414 {
415     return vq->queue_index;
416 }
417
418
419 /**
420  * \brief Checks if the virtqueue is empty
421  *
422  * \param vq pointer to the virtqueue structure
423  *
424  * \returns 0 the queue is not empty
425  *          1 the queue is empty
426  */
427 bool virtio_virtqueue_is_empty(struct virtqueue *vq)
428 {
429     return (vq->vring_ndesc == vq->free_count);
430 }
431
432 /**
433  * \brief Checks if the virtqueue is full
434  *
435  * \param vq pointer to the virtqueue structure
436  *
437  * \returns 0 the queue is not full
438  *          1 the queue is full
439  */
440 bool virtio_virtqueue_is_full(struct virtqueue *vq)
441 {
442     return (vq->free_count == 0);
443 }
444
445 /**
446  * \brief Calculates the number of used descriptors in this queue
447  *
448  * \param vq pointer to the virtqueue structure
449  *
450  * \returns number of used descriptors
451  */
452 uint16_t virtio_virtqueue_get_num_used(struct virtqueue *vq)
453 {
454     uint16_t num_used;
455
456     num_used = vq->vring.used->idx - vq->used_tail;
457
458     /* sanity check */
459     assert(num_used <= vq->vring_ndesc);
460
461     return num_used;
462 }
463
464 /*
465  * ----------------------------------------------------------------------------
466  *  Interrupt handling
467  */
468
469 /**
470  * \brief checks if the interrupts can be disabled
471  *
472  * \param vq virtual queue to check
473  *
474  * \returns 1 if the interrupts have been disabled
475  *          0 if the interrupts are not changed
476  *
477  */
478 bool virtio_virtqueue_intr_filter(struct virtqueue *vq)
479 {
480     if (vq->used_tail == vq->vring.used->idx) {
481         return 0;
482     }
483
484     virtio_virtqueue_intr_disable(vq);
485
486     return 1;
487 }
488
489 /**
490  * \brief calls the interrupt handler for this virtqueue
491  *
492  * \param vq virtqueue to call the intr handler for
493  */
494 void virtio_virtqueue_intr_handle(struct virtqueue *vq)
495 {
496     if (vq->intr_handler == NULL) {
497         VIRTIO_DEBUG_VQ("Notice: Interrupt handler is not set\n");
498         return;
499     }
500     vq->intr_handler(vq, vq->intr_arg);
501 }
502
503
504 /**
505  * \brief enables the interrupts on the next descriptor processed
506  *
507  * \param vq the virtqueue to enable the interrupts
508  *
509  * \returns 1 if the interrupts have been enabled
510  *          0 if the interrupts have not been enabled
511  */
512 bool virtio_virtqueue_intr_enable(struct virtqueue *vq)
513 {
514     return virtqueue_interrupt_enable(vq, 0);
515 }
516
517 /**
518  * \brief postpones the interrupt to a later point of time
519  *
520  * \param vq the virtqueue to enable the interrupts
521  * \param
522  *
523  * \returns 1 if the interrupts have been enabled
524  *          0 if the interrupts have not been enabled
525  */
526 bool virtio_virtqueue_intr_postpone(struct virtqueue *vq,
527                                     enum virtqueue_intr_postpone hint)
528 {
529     uint16_t ndesc = vq->vring.avail->idx - vq->used_tail;
530
531     switch (hint) {
532         case VIRTQUEUE_INTR_POSTPONE_SHORT:
533             ndesc = ndesc / 4;
534             break;
535         case VIRTQUEUE_INTR_POSTPONE_LONG:
536             ndesc = (ndesc * 3) / 4;
537             break;
538         case VIRTQUEUE_INTR_POSTPONE_EMPTIED:
539             break;
540     }
541
542     return virtqueue_interrupt_enable(vq, ndesc);
543 }
544
545
546 /**
547  * \brief disables the interrupts for the given virtqueue
548  *
549  * \param vq        virtqueue to disable the interrupts
550  */
551 void virtio_virtqueue_intr_disable(struct virtqueue *vq)
552 {
553     if (vq->flags & VIRTQUEUE_FLAG_EVENT_IDX) {
554         uint16_t *used_event = vring_get_used_event(&vq->vring);
555         *used_event = vq->used_tail - vq->vring_ndesc - 1;
556     } else {
557         vq->vring.avail->flags |= VIRTIO_RING_AVAIL_F_NO_INTERRUPT;
558     }
559 }
560
561 /**
562  * \brief notifies the host about the new queued descriptors
563  *
564  * \param vq virtqueue to notify the host
565  */
566 void virtio_virtqueue_notify_host(struct virtqueue *vq)
567 {
568     /* TODO: memory barrier */
569     if (virtqueue_should_notify_host(vq)) {
570         assert(!"NYI: host notify");
571     }
572     vq->queued_count = 0;
573
574 }
575
576
577 /*
578  * We layout the vring structure in memory as follows:
579  *
580  * struct vring {
581  *      // The actual descriptors (16 bytes each)
582  *      struct vring_desc desc[num];
583  *
584  *      // A ring of available descriptor heads with free-running index.
585  *      uint16_t avail_flags;
586  *      uint16_t avail_idx;
587  *      uint16_t available[num];
588  *      uint16_t used_event_idx;
589  *
590  *      // Padding to the next align boundary.
591  *      char pad[];
592  *
593  *      // A ring of used descriptor heads with free-running index.
594  *      uint16_t used_flags;
595  *      uint16_t used_idx;
596  *      struct vring_used_elem used[num];
597  *      uint16_t avail_event_idx;
598  * };
599  */
600
601 /**
602  * \brief Maps the given capability and initializes the vring on the memory
603  *        backed by the supplied capability
604  *
605  * \param vr    pointer to the vring structure to be initialized
606  * \param num   the number of elements in the ring
607  * \param align alignment constraints for the vring
608  * \param cap   frame capability used as backing memory for the structure
609  *
610  * \return SYS_ERR_OK on success
611  *         errno      on failure
612  */
613 errval_t vring_init_from_cap(struct vring *vr,
614                              uint16_t num,
615                              uintptr_t align,
616                              struct capref cap)
617 {
618     errval_t err;
619
620     /* num must be a power of two */
621     assert(((num != 0) && ((num & (~num + 1)) == num)));
622
623     size_t size = vring_size(num, align);
624
625     struct frame_identity id;
626     err = invoke_frame_identify(cap, &id);
627     if (err_is_fail(err)) {
628         return err_push(err, LIB_ERR_FRAME_IDENTIFY);
629     }
630
631     /* check if we have enough space in the given cap */
632     if ((1UL << id.bits) < size) {
633         return SYS_ERR_INVALID_SIZE_BITS;
634     }
635
636     void *addr;
637     err = vspace_map_one_frame(&addr, (1UL << id.bits), cap, NULL, NULL);
638     if (err_is_fail(err)) {
639         return err_push(err, LIB_ERR_VSPACE_MAP);
640     }
641
642     vring_init(vr, num, align, addr);
643
644     return SYS_ERR_OK;
645 }
646
647 /**
648  * \brief allocates a new vring structure
649  *
650  * \param vr        pointer to the vring structure
651  * \param num       the number of queue elements
652  * \param align     the alignment constraints for the vring
653  * \param ret_frame returned frame capability
654  *
655  * \return SYS_ERR_OK on success
656  *         errno      on failure
657  */
658 errval_t vring_alloc(struct vring *vr,
659                      uint16_t num,
660                      uintptr_t align,
661                      struct capref *ret_frame)
662 {
663     errval_t err;
664
665     /* num must be a power of two */
666     assert(((num != 0) && ((num & (~num + 1)) == num)));
667
668     size_t size = vring_size(num, align);
669
670     struct capref frame;
671     err = frame_alloc(&frame, size, &size);
672     if (err_is_fail(err)) {
673         return err;
674     }
675
676     err = vring_init_from_cap(vr, num, align, frame);
677     if (err_is_fail(err)) {
678         return err;
679     }
680
681     if (ret_frame) {
682         *ret_frame = frame;
683     }
684
685     return SYS_ERR_OK;
686 }
687
688 /**
689  * \brief frees the resources used by the vring structure
690  *
691  * \param vr the vring to be freed
692  *
693  * \return SYS_ERR_OK on success
694  *         errno      on failure
695  */
696 errval_t vring_free(struct vring *vr)
697 {
698     errval_t err;
699
700     err = vspace_unmap(vr->desc);
701     if (err_is_fail(err)) {
702         return err;
703     }
704
705     assert(!"NYI: returning the cap to the origin");
706     return SYS_ERR_OK;
707 }
708
709 /*
710  * ----------------------------------------------------------------------------
711  *  Queue Management
712  */
713
714 /**
715  * \brief updates the available ring of the virtqueue by placing the descriptor
716  *        into the availabe ring.
717  *
718  * \param vq    the virtqueue to update
719  * \param idx   index of the new descriptor chain head
720  */
721 static void virtqueue_update_available(struct virtqueue *vq,
722                                        uint16_t idx)
723 {
724     uint16_t avail_idx = vq->vring.avail->idx & (vq->vring_ndesc - 1);
725     vq->vring.avail->ring[avail_idx] = idx;
726
727     /*
728      * wmb();
729      */
730
731     vq->vring.avail->idx++;
732     vq->queued_count++;
733 }
734
735
736 static errval_t virtqueue_enqueue_bufs(struct virtqueue *vq,
737                                        struct vring_desc *desc,
738                                        uint16_t head,
739                                        struct virtio_buffer_list *bl,
740                                        uint16_t readable,
741                                        uint16_t writable,
742                                        uint16_t *ret_idx)
743 {
744     struct virtio_buffer *buf = bl->head;
745     struct vring_desc *cd;
746
747     uint16_t needed = readable + writable;
748     uint16_t idx = head;
749
750     for (uint16_t i = 0; i < needed; ++i) {
751         vq->vring_di[idx].buf = buf;
752         cd = &desc[idx];
753
754         cd->addr = buf->paddr;
755         cd->length = buf->length;
756         cd->flags = 0;
757
758         if (i < needed - 1) {
759             cd->flags |= VIRTIO_RING_DESC_F_NEXT;
760         }
761         if (i >= readable) {
762             cd->flags |= VIRTIO_RING_DESC_F_WRITE;
763         }
764         idx = cd->next;
765         buf = buf->next;
766     }
767
768     if (ret_idx) {
769         *ret_idx = idx;
770     }
771
772     return SYS_ERR_OK;
773 }
774
775
776 errval_t virtio_virtqueue_desc_enqueue(struct virtqueue *vq,
777                                        struct virtio_buffer_list *bl,
778                                        void *vaddr,
779                                        uint16_t writeable,
780                                        uint16_t readable)
781 {
782     uint16_t needed = readable + writeable;
783
784     if (needed != bl->length || needed < 0) {
785         return VIRTIO_ERR_SIZE_INVALID;
786     }
787
788     if (vq->free_count < needed) {
789         return VIRTIO_ERR_QUEUE_EMPTY;
790     }
791
792     /*
793      * TODO: check if we should use indirect descriptors or not
794      */
795
796     uint16_t free_head = vq->free_head;
797     struct vring_desc_info *info = &vq->vring_di[free_head];
798
799     info->is_head = 0x1;
800     info->st = NULL;
801
802     uint16_t idx;
803     virtqueue_enqueue_bufs(vq, vq->vring.desc, free_head,
804                            bl, readable, writeable, &idx);
805
806
807     /* update free values */
808     vq->free_head = idx;
809     vq->free_count -= needed;
810
811     virtqueue_update_available(vq, free_head);
812
813     return SYS_ERR_OK;
814 }
815
816 #if 0
817
818 /**
819  *
820  */
821 errval_t virtio_virtqueue_desc_alloc(struct virtqueue *vq,
822                                      struct virtio_buffer_list *bl,
823                                      uint16_t readable,
824                                      uint16_t writeable)
825 {
826
827 }
828
829
830
831 void *virtio_virtqueue_desc_deq(struct virtqueue *vq)
832 {
833     return NULL;
834 }
835
836
837
838 void *virtio_virtqueue_poll(struct virtqueue *vq)
839 {
840     return NULL;
841 };
842
843 #endif
844