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 13*b412ad0dSAndrew Jones #define VIRTIO_ID_CONSOLE 3 14*b412ad0dSAndrew Jones 1543402ba5SAndrew Jones struct virtio_device_id { 1643402ba5SAndrew Jones u32 device; 1743402ba5SAndrew Jones u32 vendor; 1843402ba5SAndrew Jones }; 1943402ba5SAndrew Jones 2043402ba5SAndrew Jones struct virtio_device { 2143402ba5SAndrew Jones struct virtio_device_id id; 2243402ba5SAndrew Jones const struct virtio_config_ops *config; 2343402ba5SAndrew Jones }; 2443402ba5SAndrew Jones 25d73e4521SAndrew Jones struct virtqueue { 26d73e4521SAndrew Jones void (*callback)(struct virtqueue *vq); 27d73e4521SAndrew Jones const char *name; 28d73e4521SAndrew Jones struct virtio_device *vdev; 29d73e4521SAndrew Jones unsigned int index; 30d73e4521SAndrew Jones unsigned int num_free; 31d73e4521SAndrew Jones void *priv; 32d73e4521SAndrew Jones }; 33d73e4521SAndrew Jones 34d73e4521SAndrew Jones typedef void vq_callback_t(struct virtqueue *); 3543402ba5SAndrew Jones struct virtio_config_ops { 3643402ba5SAndrew Jones void (*get)(struct virtio_device *vdev, unsigned offset, 3743402ba5SAndrew Jones void *buf, unsigned len); 3843402ba5SAndrew Jones void (*set)(struct virtio_device *vdev, unsigned offset, 3943402ba5SAndrew Jones const void *buf, unsigned len); 40d73e4521SAndrew Jones int (*find_vqs)(struct virtio_device *vdev, unsigned nvqs, 41d73e4521SAndrew Jones struct virtqueue *vqs[], 42d73e4521SAndrew Jones vq_callback_t *callbacks[], 43d73e4521SAndrew Jones const char *names[]); 4443402ba5SAndrew Jones }; 4543402ba5SAndrew Jones 4643402ba5SAndrew Jones static inline u8 4743402ba5SAndrew Jones virtio_config_readb(struct virtio_device *vdev, unsigned offset) 4843402ba5SAndrew Jones { 4943402ba5SAndrew Jones u8 val; 5043402ba5SAndrew Jones vdev->config->get(vdev, offset, &val, 1); 5143402ba5SAndrew Jones return val; 5243402ba5SAndrew Jones } 5343402ba5SAndrew Jones 5443402ba5SAndrew Jones static inline u16 5543402ba5SAndrew Jones virtio_config_readw(struct virtio_device *vdev, unsigned offset) 5643402ba5SAndrew Jones { 5743402ba5SAndrew Jones u16 val; 5843402ba5SAndrew Jones vdev->config->get(vdev, offset, &val, 2); 5943402ba5SAndrew Jones return val; 6043402ba5SAndrew Jones } 6143402ba5SAndrew Jones 6243402ba5SAndrew Jones static inline u32 6343402ba5SAndrew Jones virtio_config_readl(struct virtio_device *vdev, unsigned offset) 6443402ba5SAndrew Jones { 6543402ba5SAndrew Jones u32 val; 6643402ba5SAndrew Jones vdev->config->get(vdev, offset, &val, 4); 6743402ba5SAndrew Jones return val; 6843402ba5SAndrew Jones } 6943402ba5SAndrew Jones 7043402ba5SAndrew Jones static inline void 7143402ba5SAndrew Jones virtio_config_writeb(struct virtio_device *vdev, unsigned offset, u8 val) 7243402ba5SAndrew Jones { 7343402ba5SAndrew Jones vdev->config->set(vdev, offset, &val, 1); 7443402ba5SAndrew Jones } 7543402ba5SAndrew Jones 7643402ba5SAndrew Jones static inline void 7743402ba5SAndrew Jones virtio_config_writew(struct virtio_device *vdev, unsigned offset, u16 val) 7843402ba5SAndrew Jones { 7943402ba5SAndrew Jones vdev->config->set(vdev, offset, &val, 2); 8043402ba5SAndrew Jones } 8143402ba5SAndrew Jones 8243402ba5SAndrew Jones static inline void 8343402ba5SAndrew Jones virtio_config_writel(struct virtio_device *vdev, unsigned offset, u32 val) 8443402ba5SAndrew Jones { 8543402ba5SAndrew Jones vdev->config->set(vdev, offset, &val, 4); 8643402ba5SAndrew Jones } 8743402ba5SAndrew Jones 88d73e4521SAndrew Jones #define VRING_DESC_F_NEXT 1 89d73e4521SAndrew Jones #define VRING_DESC_F_WRITE 2 90d73e4521SAndrew Jones 91d73e4521SAndrew Jones struct vring_desc { 92d73e4521SAndrew Jones u64 addr; 93d73e4521SAndrew Jones u32 len; 94d73e4521SAndrew Jones u16 flags; 95d73e4521SAndrew Jones u16 next; 96d73e4521SAndrew Jones }; 97d73e4521SAndrew Jones 98d73e4521SAndrew Jones struct vring_avail { 99d73e4521SAndrew Jones u16 flags; 100d73e4521SAndrew Jones u16 idx; 101d73e4521SAndrew Jones u16 ring[]; 102d73e4521SAndrew Jones }; 103d73e4521SAndrew Jones 104d73e4521SAndrew Jones struct vring_used_elem { 105d73e4521SAndrew Jones u32 id; 106d73e4521SAndrew Jones u32 len; 107d73e4521SAndrew Jones }; 108d73e4521SAndrew Jones 109d73e4521SAndrew Jones struct vring_used { 110d73e4521SAndrew Jones u16 flags; 111d73e4521SAndrew Jones u16 idx; 112d73e4521SAndrew Jones struct vring_used_elem ring[]; 113d73e4521SAndrew Jones }; 114d73e4521SAndrew Jones 115d73e4521SAndrew Jones struct vring { 116d73e4521SAndrew Jones unsigned int num; 117d73e4521SAndrew Jones struct vring_desc *desc; 118d73e4521SAndrew Jones struct vring_avail *avail; 119d73e4521SAndrew Jones struct vring_used *used; 120d73e4521SAndrew Jones }; 121d73e4521SAndrew Jones 122d73e4521SAndrew Jones struct vring_virtqueue { 123d73e4521SAndrew Jones struct virtqueue vq; 124d73e4521SAndrew Jones struct vring vring; 125d73e4521SAndrew Jones unsigned int free_head; 126d73e4521SAndrew Jones unsigned int num_added; 127d73e4521SAndrew Jones u16 last_used_idx; 128d73e4521SAndrew Jones bool (*notify)(struct virtqueue *vq); 129d73e4521SAndrew Jones void *data[]; 130d73e4521SAndrew Jones }; 131d73e4521SAndrew Jones 132d73e4521SAndrew Jones #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq) 133d73e4521SAndrew Jones 134d73e4521SAndrew Jones extern void vring_init(struct vring *vr, unsigned int num, void *p, 135d73e4521SAndrew Jones unsigned long align); 136d73e4521SAndrew Jones extern void vring_init_virtqueue(struct vring_virtqueue *vq, unsigned index, 137d73e4521SAndrew Jones unsigned num, unsigned vring_align, 138d73e4521SAndrew Jones struct virtio_device *vdev, void *pages, 139d73e4521SAndrew Jones bool (*notify)(struct virtqueue *), 140d73e4521SAndrew Jones void (*callback)(struct virtqueue *), 141d73e4521SAndrew Jones const char *name); 142d73e4521SAndrew Jones extern int virtqueue_add_outbuf(struct virtqueue *vq, char *buf, size_t len); 143d73e4521SAndrew Jones extern bool virtqueue_kick(struct virtqueue *vq); 144d73e4521SAndrew Jones extern void detach_buf(struct vring_virtqueue *vq, unsigned head); 145d73e4521SAndrew Jones extern void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len); 146d73e4521SAndrew Jones 14743402ba5SAndrew Jones extern struct virtio_device *virtio_bind(u32 devid); 14843402ba5SAndrew Jones 14943402ba5SAndrew Jones #endif /* _VIRTIO_H_ */ 150