To communicate in both directions with a VIRTIO device we need to add the incoming communication to the VIRTIO level. Signed-off-by: Pierre Morel <pmorel@xxxxxxxxxxxxx> --- lib/virtio.c | 32 ++++++++++++++++++++++++++++++++ lib/virtio.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/lib/virtio.c b/lib/virtio.c index e10153b9..b84bc680 100644 --- a/lib/virtio.c +++ b/lib/virtio.c @@ -47,6 +47,38 @@ void vring_init_virtqueue(struct vring_virtqueue *vq, unsigned index, vq->data[i] = NULL; } +int virtqueue_add_inbuf(struct virtqueue *_vq, char *buf, unsigned int len) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + unsigned int avail; + int head; + + assert(buf); + assert(len); + + if (!vq->vq.num_free) + return -1; + + --vq->vq.num_free; + + head = vq->free_head; + + vq->vring.desc[head].flags = 0; + vq->vring.desc[head].addr = virt_to_phys(buf); + vq->vring.desc[head].len = len; + + vq->free_head = vq->vring.desc[head].next; + + vq->data[head] = buf; + + avail = (vq->vring.avail->idx & (vq->vring.num - 1)); + vq->vring.avail->ring[avail] = head; + wmb(); /* be sure to update the ring before updating the idx */ + vq->vring.avail->idx++; + vq->num_added++; + + return 0; +} int virtqueue_add_outbuf(struct virtqueue *_vq, char *buf, unsigned int len) { struct vring_virtqueue *vq = to_vvq(_vq); diff --git a/lib/virtio.h b/lib/virtio.h index 2c31fdc7..44b727f8 100644 --- a/lib/virtio.h +++ b/lib/virtio.h @@ -141,6 +141,8 @@ extern void vring_init_virtqueue(struct vring_virtqueue *vq, unsigned index, const char *name); extern int virtqueue_add_outbuf(struct virtqueue *vq, char *buf, unsigned int len); +extern int virtqueue_add_inbuf(struct virtqueue *vq, char *buf, + unsigned int len); extern bool virtqueue_kick(struct virtqueue *vq); extern void detach_buf(struct vring_virtqueue *vq, unsigned head); extern void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len); -- 2.25.1