virtio-ring.h
Go to the documentation of this file.00001 #ifndef _VIRTIO_RING_H_
00002 # define _VIRTIO_RING_H_
00003 #define PAGE_SHIFT (12)
00004 #define PAGE_SIZE (1<<PAGE_SHIFT)
00005 #define PAGE_MASK (PAGE_SIZE-1)
00006
00007
00008
00009 #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
00010
00011 #define VIRTIO_CONFIG_S_DRIVER 2
00012
00013 #define VIRTIO_CONFIG_S_DRIVER_OK 4
00014
00015 #define VIRTIO_CONFIG_S_FAILED 0x80
00016
00017 #define MAX_QUEUE_NUM (512)
00018
00019 #define VRING_DESC_F_NEXT 1
00020 #define VRING_DESC_F_WRITE 2
00021
00022 #define VRING_AVAIL_F_NO_INTERRUPT 1
00023
00024 #define VRING_USED_F_NO_NOTIFY 1
00025
00026 struct vring_desc
00027 {
00028 u64 addr;
00029 u32 len;
00030 u16 flags;
00031 u16 next;
00032 };
00033
00034 struct vring_avail
00035 {
00036 u16 flags;
00037 u16 idx;
00038 u16 ring[0];
00039 };
00040
00041 struct vring_used_elem
00042 {
00043 u32 id;
00044 u32 len;
00045 };
00046
00047 struct vring_used
00048 {
00049 u16 flags;
00050 u16 idx;
00051 struct vring_used_elem ring[];
00052 };
00053
00054 struct vring {
00055 unsigned int num;
00056 struct vring_desc *desc;
00057 struct vring_avail *avail;
00058 struct vring_used *used;
00059 };
00060
00061 #define vring_size(num) \
00062 (((((sizeof(struct vring_desc) * num) + \
00063 (sizeof(struct vring_avail) + sizeof(u16) * num)) \
00064 + PAGE_MASK) & ~PAGE_MASK) + \
00065 (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num))
00066
00067 typedef unsigned char virtio_queue_t[PAGE_MASK + vring_size(MAX_QUEUE_NUM)];
00068
00069 struct vring_virtqueue {
00070 virtio_queue_t queue;
00071 struct vring vring;
00072 u16 free_head;
00073 u16 last_used_idx;
00074 u16 vdata[MAX_QUEUE_NUM];
00075
00076 int queue_index;
00077 };
00078
00079 struct vring_list {
00080 char *addr;
00081 unsigned int length;
00082 };
00083
00084 static inline void vring_init(struct vring *vr,
00085 unsigned int num, unsigned char *queue)
00086 {
00087 unsigned int i;
00088 unsigned long pa;
00089
00090 vr->num = num;
00091
00092
00093
00094 pa = virt_to_phys(queue);
00095 pa = (pa + PAGE_MASK) & ~PAGE_MASK;
00096 vr->desc = phys_to_virt(pa);
00097
00098 vr->avail = (struct vring_avail *)&vr->desc[num];
00099
00100
00101
00102 pa = virt_to_phys(&vr->avail->ring[num]);
00103 pa = (pa + PAGE_MASK) & ~PAGE_MASK;
00104 vr->used = phys_to_virt(pa);
00105
00106 for (i = 0; i < num - 1; i++)
00107 vr->desc[i].next = i + 1;
00108 vr->desc[i].next = 0;
00109 }
00110
00111 static inline void vring_enable_cb(struct vring_virtqueue *vq)
00112 {
00113 vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
00114 }
00115
00116 static inline void vring_disable_cb(struct vring_virtqueue *vq)
00117 {
00118 vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 static inline int vring_more_used(struct vring_virtqueue *vq)
00130 {
00131 wmb();
00132 return vq->last_used_idx != vq->vring.used->idx;
00133 }
00134
00135 void vring_detach(struct vring_virtqueue *vq, unsigned int head);
00136 int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len);
00137 void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[],
00138 unsigned int out, unsigned int in,
00139 int index, int num_added);
00140 void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added);
00141
00142 #endif