blob: 014defc34917c3b3888e38e22a05d872343f8d04 [file] [log] [blame]
Gleb Natapov89acfa32010-05-10 11:36:37 +03001#ifndef _VIRTIO_RING_H
2#define _VIRTIO_RING_H
3
Kevin O'Connor7d09d0e2010-05-10 21:51:38 -04004#include "types.h" // u64
5#include "memmap.h" // PAGE_SIZE
6
Gleb Natapov89acfa32010-05-10 11:36:37 +03007#define PAGE_SHIFT 12
8#define PAGE_MASK (PAGE_SIZE-1)
9
10#define virt_to_phys(v) (unsigned long)(v)
11#define phys_to_virt(p) (void*)(p)
12#define wmb() barrier()
13#define mb() barrier()
14
15/* Status byte for guest to report progress, and synchronize features. */
16/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
17#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
18/* We have found a driver for the device. */
19#define VIRTIO_CONFIG_S_DRIVER 2
20/* Driver has used its parts of the config, and is happy */
21#define VIRTIO_CONFIG_S_DRIVER_OK 4
22/* We've given up on this device. */
23#define VIRTIO_CONFIG_S_FAILED 0x80
24
25#define MAX_QUEUE_NUM (128)
26
27#define VRING_DESC_F_NEXT 1
28#define VRING_DESC_F_WRITE 2
29
30#define VRING_AVAIL_F_NO_INTERRUPT 1
31
32#define VRING_USED_F_NO_NOTIFY 1
33
34struct vring_desc
35{
36 u64 addr;
37 u32 len;
38 u16 flags;
39 u16 next;
40};
41
42struct vring_avail
43{
44 u16 flags;
45 u16 idx;
46 u16 ring[0];
47};
48
49struct vring_used_elem
50{
51 u32 id;
52 u32 len;
53};
54
55struct vring_used
56{
57 u16 flags;
58 u16 idx;
59 struct vring_used_elem ring[];
60};
61
62struct vring {
63 unsigned int num;
64 struct vring_desc *desc;
65 struct vring_avail *avail;
66 struct vring_used *used;
67};
68
69#define vring_size(num) \
70 (((((sizeof(struct vring_desc) * num) + \
71 (sizeof(struct vring_avail) + sizeof(u16) * num)) \
72 + PAGE_MASK) & ~PAGE_MASK) + \
73 (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num))
74
Kevin O'Connorea8ac632010-05-16 11:34:38 -040075typedef unsigned char virtio_queue_t[vring_size(MAX_QUEUE_NUM)];
Gleb Natapov89acfa32010-05-10 11:36:37 +030076
77struct vring_virtqueue {
78 virtio_queue_t queue;
79 struct vring vring;
80 u16 free_head;
81 u16 last_used_idx;
82 u16 vdata[MAX_QUEUE_NUM];
83 /* PCI */
84 int queue_index;
85};
86
87struct vring_list {
88 char *addr;
89 unsigned int length;
90};
91
92static inline void vring_init(struct vring *vr,
93 unsigned int num, unsigned char *queue)
94{
95 unsigned int i;
96 unsigned long pa;
97
98 ASSERT32FLAT();
99 vr->num = num;
100
101 /* physical address of desc must be page aligned */
102
103 pa = virt_to_phys(queue);
104 pa = (pa + PAGE_MASK) & ~PAGE_MASK;
105 vr->desc = phys_to_virt(pa);
106
107 vr->avail = (struct vring_avail *)&vr->desc[num];
Gleb Natapov4030db02010-05-17 16:27:27 +0300108 /* disable interrupts */
109 vr->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
Gleb Natapov89acfa32010-05-10 11:36:37 +0300110
111 /* physical address of used must be page aligned */
112
113 pa = virt_to_phys(&vr->avail->ring[num]);
114 pa = (pa + PAGE_MASK) & ~PAGE_MASK;
115 vr->used = phys_to_virt(pa);
116
117 for (i = 0; i < num - 1; i++)
118 vr->desc[i].next = i + 1;
119 vr->desc[i].next = 0;
120}
121
122int vring_more_used(struct vring_virtqueue *vq);
123void vring_detach(struct vring_virtqueue *vq, unsigned int head);
124int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len);
125void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[],
126 unsigned int out, unsigned int in,
127 int index, int num_added);
128void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added);
129
130#endif /* _VIRTIO_RING_H_ */