iPXE
virtio-ring.h
Go to the documentation of this file.
00001 #ifndef _VIRTIO_RING_H_
00002 # define _VIRTIO_RING_H_
00003 
00004 #include <ipxe/virtio-pci.h>
00005 
00006 /* Status byte for guest to report progress, and synchronize features. */
00007 /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
00008 #define VIRTIO_CONFIG_S_ACKNOWLEDGE     1
00009 /* We have found a driver for the device. */
00010 #define VIRTIO_CONFIG_S_DRIVER          2
00011 /* Driver has used its parts of the config, and is happy */
00012 #define VIRTIO_CONFIG_S_DRIVER_OK       4
00013 /* Driver has finished configuring features */
00014 #define VIRTIO_CONFIG_S_FEATURES_OK     8
00015 /* We've given up on this device. */
00016 #define VIRTIO_CONFIG_S_FAILED          0x80
00017 
00018 /* Virtio feature flags used to negotiate device and driver features. */
00019 /* Can the device handle any descriptor layout? */
00020 #define VIRTIO_F_ANY_LAYOUT             27
00021 /* v1.0 compliant. */
00022 #define VIRTIO_F_VERSION_1              32
00023 #define VIRTIO_F_IOMMU_PLATFORM         33
00024 
00025 #define MAX_QUEUE_NUM      (256)
00026 
00027 #define VRING_DESC_F_NEXT  1
00028 #define VRING_DESC_F_WRITE 2
00029 
00030 #define VRING_AVAIL_F_NO_INTERRUPT 1
00031 
00032 #define VRING_USED_F_NO_NOTIFY     1
00033 
00034 struct vring_desc
00035 {
00036    u64 addr;
00037    u32 len;
00038    u16 flags;
00039    u16 next;
00040 };
00041 
00042 struct vring_avail
00043 {
00044    u16 flags;
00045    u16 idx;
00046    u16 ring[0];
00047 };
00048 
00049 struct vring_used_elem
00050 {
00051    u32 id;
00052    u32 len;
00053 };
00054 
00055 struct vring_used
00056 {
00057    u16 flags;
00058    u16 idx;
00059    struct vring_used_elem ring[];
00060 };
00061 
00062 struct vring {
00063    unsigned int num;
00064    struct vring_desc *desc;
00065    struct vring_avail *avail;
00066    struct vring_used *used;
00067 };
00068 
00069 #define vring_size(num) \
00070    (((((sizeof(struct vring_desc) * num) + \
00071       (sizeof(struct vring_avail) + sizeof(u16) * num)) \
00072          + PAGE_MASK) & ~PAGE_MASK) + \
00073          (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num))
00074 
00075 struct vring_virtqueue {
00076    unsigned char *queue;
00077    struct vring vring;
00078    u16 free_head;
00079    u16 last_used_idx;
00080    void **vdata;
00081    /* PCI */
00082    int queue_index;
00083    struct virtio_pci_region notification;
00084 };
00085 
00086 struct vring_list {
00087   char *addr;
00088   unsigned int length;
00089 };
00090 
00091 static inline void vring_init(struct vring *vr,
00092                          unsigned int num, unsigned char *queue)
00093 {
00094    unsigned int i;
00095    unsigned long pa;
00096 
00097    vr->num = num;
00098 
00099    /* physical address of desc must be page aligned */
00100 
00101    pa = virt_to_phys(queue);
00102    pa = (pa + PAGE_MASK) & ~PAGE_MASK;
00103    vr->desc = phys_to_virt(pa);
00104 
00105    vr->avail = (struct vring_avail *)&vr->desc[num];
00106 
00107    /* physical address of used must be page aligned */
00108 
00109    pa = virt_to_phys(&vr->avail->ring[num]);
00110    pa = (pa + PAGE_MASK) & ~PAGE_MASK;
00111    vr->used = phys_to_virt(pa);
00112 
00113    for (i = 0; i < num - 1; i++)
00114            vr->desc[i].next = i + 1;
00115    vr->desc[i].next = 0;
00116 }
00117 
00118 static inline void vring_enable_cb(struct vring_virtqueue *vq)
00119 {
00120    vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
00121 }
00122 
00123 static inline void vring_disable_cb(struct vring_virtqueue *vq)
00124 {
00125    vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
00126 }
00127 
00128 
00129 /*
00130  * vring_more_used
00131  *
00132  * is there some used buffers ?
00133  *
00134  */
00135 
00136 static inline int vring_more_used(struct vring_virtqueue *vq)
00137 {
00138    wmb();
00139    return vq->last_used_idx != vq->vring.used->idx;
00140 }
00141 
00142 void vring_detach(struct vring_virtqueue *vq, unsigned int head);
00143 void *vring_get_buf(struct vring_virtqueue *vq, unsigned int *len);
00144 void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[],
00145                    unsigned int out, unsigned int in,
00146                    void *index, int num_added);
00147 void vring_kick(struct virtio_pci_modern_device *vdev, unsigned int ioaddr,
00148                 struct vring_virtqueue *vq, int num_added);
00149 
00150 #endif /* _VIRTIO_RING_H_ */