143402ba5SAndrew Jones #ifndef _VIRTIO_H_ 243402ba5SAndrew Jones #define _VIRTIO_H_ 343402ba5SAndrew Jones /* 443402ba5SAndrew Jones * A minimal implementation of virtio. 543402ba5SAndrew Jones * Structures adapted from the Linux Kernel. 643402ba5SAndrew Jones * 743402ba5SAndrew Jones * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 843402ba5SAndrew Jones * 943402ba5SAndrew Jones * This work is licensed under the terms of the GNU LGPL, version 2. 1043402ba5SAndrew Jones */ 1143402ba5SAndrew Jones #include "libcflat.h" 1243402ba5SAndrew Jones 1343402ba5SAndrew Jones struct virtio_device_id { 1443402ba5SAndrew Jones u32 device; 1543402ba5SAndrew Jones u32 vendor; 1643402ba5SAndrew Jones }; 1743402ba5SAndrew Jones 1843402ba5SAndrew Jones struct virtio_device { 1943402ba5SAndrew Jones struct virtio_device_id id; 2043402ba5SAndrew Jones const struct virtio_config_ops *config; 2143402ba5SAndrew Jones }; 2243402ba5SAndrew Jones 23*d73e4521SAndrew Jones struct virtqueue { 24*d73e4521SAndrew Jones void (*callback)(struct virtqueue *vq); 25*d73e4521SAndrew Jones const char *name; 26*d73e4521SAndrew Jones struct virtio_device *vdev; 27*d73e4521SAndrew Jones unsigned int index; 28*d73e4521SAndrew Jones unsigned int num_free; 29*d73e4521SAndrew Jones void *priv; 30*d73e4521SAndrew Jones }; 31*d73e4521SAndrew Jones 32*d73e4521SAndrew Jones typedef void vq_callback_t(struct virtqueue *); 3343402ba5SAndrew Jones struct virtio_config_ops { 3443402ba5SAndrew Jones void (*get)(struct virtio_device *vdev, unsigned offset, 3543402ba5SAndrew Jones void *buf, unsigned len); 3643402ba5SAndrew Jones void (*set)(struct virtio_device *vdev, unsigned offset, 3743402ba5SAndrew Jones const void *buf, unsigned len); 38*d73e4521SAndrew Jones int (*find_vqs)(struct virtio_device *vdev, unsigned nvqs, 39*d73e4521SAndrew Jones struct virtqueue *vqs[], 40*d73e4521SAndrew Jones vq_callback_t *callbacks[], 41*d73e4521SAndrew Jones const char *names[]); 4243402ba5SAndrew Jones }; 4343402ba5SAndrew Jones 4443402ba5SAndrew Jones static inline u8 4543402ba5SAndrew Jones virtio_config_readb(struct virtio_device *vdev, unsigned offset) 4643402ba5SAndrew Jones { 4743402ba5SAndrew Jones u8 val; 4843402ba5SAndrew Jones vdev->config->get(vdev, offset, &val, 1); 4943402ba5SAndrew Jones return val; 5043402ba5SAndrew Jones } 5143402ba5SAndrew Jones 5243402ba5SAndrew Jones static inline u16 5343402ba5SAndrew Jones virtio_config_readw(struct virtio_device *vdev, unsigned offset) 5443402ba5SAndrew Jones { 5543402ba5SAndrew Jones u16 val; 5643402ba5SAndrew Jones vdev->config->get(vdev, offset, &val, 2); 5743402ba5SAndrew Jones return val; 5843402ba5SAndrew Jones } 5943402ba5SAndrew Jones 6043402ba5SAndrew Jones static inline u32 6143402ba5SAndrew Jones virtio_config_readl(struct virtio_device *vdev, unsigned offset) 6243402ba5SAndrew Jones { 6343402ba5SAndrew Jones u32 val; 6443402ba5SAndrew Jones vdev->config->get(vdev, offset, &val, 4); 6543402ba5SAndrew Jones return val; 6643402ba5SAndrew Jones } 6743402ba5SAndrew Jones 6843402ba5SAndrew Jones static inline void 6943402ba5SAndrew Jones virtio_config_writeb(struct virtio_device *vdev, unsigned offset, u8 val) 7043402ba5SAndrew Jones { 7143402ba5SAndrew Jones vdev->config->set(vdev, offset, &val, 1); 7243402ba5SAndrew Jones } 7343402ba5SAndrew Jones 7443402ba5SAndrew Jones static inline void 7543402ba5SAndrew Jones virtio_config_writew(struct virtio_device *vdev, unsigned offset, u16 val) 7643402ba5SAndrew Jones { 7743402ba5SAndrew Jones vdev->config->set(vdev, offset, &val, 2); 7843402ba5SAndrew Jones } 7943402ba5SAndrew Jones 8043402ba5SAndrew Jones static inline void 8143402ba5SAndrew Jones virtio_config_writel(struct virtio_device *vdev, unsigned offset, u32 val) 8243402ba5SAndrew Jones { 8343402ba5SAndrew Jones vdev->config->set(vdev, offset, &val, 4); 8443402ba5SAndrew Jones } 8543402ba5SAndrew Jones 86*d73e4521SAndrew Jones #define VRING_DESC_F_NEXT 1 87*d73e4521SAndrew Jones #define VRING_DESC_F_WRITE 2 88*d73e4521SAndrew Jones 89*d73e4521SAndrew Jones struct vring_desc { 90*d73e4521SAndrew Jones u64 addr; 91*d73e4521SAndrew Jones u32 len; 92*d73e4521SAndrew Jones u16 flags; 93*d73e4521SAndrew Jones u16 next; 94*d73e4521SAndrew Jones }; 95*d73e4521SAndrew Jones 96*d73e4521SAndrew Jones struct vring_avail { 97*d73e4521SAndrew Jones u16 flags; 98*d73e4521SAndrew Jones u16 idx; 99*d73e4521SAndrew Jones u16 ring[]; 100*d73e4521SAndrew Jones }; 101*d73e4521SAndrew Jones 102*d73e4521SAndrew Jones struct vring_used_elem { 103*d73e4521SAndrew Jones u32 id; 104*d73e4521SAndrew Jones u32 len; 105*d73e4521SAndrew Jones }; 106*d73e4521SAndrew Jones 107*d73e4521SAndrew Jones struct vring_used { 108*d73e4521SAndrew Jones u16 flags; 109*d73e4521SAndrew Jones u16 idx; 110*d73e4521SAndrew Jones struct vring_used_elem ring[]; 111*d73e4521SAndrew Jones }; 112*d73e4521SAndrew Jones 113*d73e4521SAndrew Jones struct vring { 114*d73e4521SAndrew Jones unsigned int num; 115*d73e4521SAndrew Jones struct vring_desc *desc; 116*d73e4521SAndrew Jones struct vring_avail *avail; 117*d73e4521SAndrew Jones struct vring_used *used; 118*d73e4521SAndrew Jones }; 119*d73e4521SAndrew Jones 120*d73e4521SAndrew Jones struct vring_virtqueue { 121*d73e4521SAndrew Jones struct virtqueue vq; 122*d73e4521SAndrew Jones struct vring vring; 123*d73e4521SAndrew Jones unsigned int free_head; 124*d73e4521SAndrew Jones unsigned int num_added; 125*d73e4521SAndrew Jones u16 last_used_idx; 126*d73e4521SAndrew Jones bool (*notify)(struct virtqueue *vq); 127*d73e4521SAndrew Jones void *data[]; 128*d73e4521SAndrew Jones }; 129*d73e4521SAndrew Jones 130*d73e4521SAndrew Jones #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq) 131*d73e4521SAndrew Jones 132*d73e4521SAndrew Jones extern void vring_init(struct vring *vr, unsigned int num, void *p, 133*d73e4521SAndrew Jones unsigned long align); 134*d73e4521SAndrew Jones extern void vring_init_virtqueue(struct vring_virtqueue *vq, unsigned index, 135*d73e4521SAndrew Jones unsigned num, unsigned vring_align, 136*d73e4521SAndrew Jones struct virtio_device *vdev, void *pages, 137*d73e4521SAndrew Jones bool (*notify)(struct virtqueue *), 138*d73e4521SAndrew Jones void (*callback)(struct virtqueue *), 139*d73e4521SAndrew Jones const char *name); 140*d73e4521SAndrew Jones extern int virtqueue_add_outbuf(struct virtqueue *vq, char *buf, size_t len); 141*d73e4521SAndrew Jones extern bool virtqueue_kick(struct virtqueue *vq); 142*d73e4521SAndrew Jones extern void detach_buf(struct vring_virtqueue *vq, unsigned head); 143*d73e4521SAndrew Jones extern void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len); 144*d73e4521SAndrew Jones 14543402ba5SAndrew Jones extern struct virtio_device *virtio_bind(u32 devid); 14643402ba5SAndrew Jones 14743402ba5SAndrew Jones #endif /* _VIRTIO_H_ */ 148