|
|
1.1 root 1: /* virtio-pci.c - virtio ring management
2: *
3: * (c) Copyright 2008 Bull S.A.S.
4: *
5: * Author: Laurent Vivier <[email protected]>
6: *
7: * some parts from Linux Virtio Ring
8: *
9: * Copyright Rusty Russell IBM Corporation 2007
10: *
11: * This work is licensed under the terms of the GNU GPL, version 2 or later.
12: * See the COPYING file in the top-level directory.
13: *
14: *
15: */
16:
17: FILE_LICENCE ( GPL2_OR_LATER );
18:
19: #include "etherboot.h"
20: #include "ipxe/io.h"
21: #include "ipxe/virtio-ring.h"
22: #include "ipxe/virtio-pci.h"
23:
24: #define BUG() do { \
25: printf("BUG: failure at %s:%d/%s()!\n", \
26: __FILE__, __LINE__, __FUNCTION__); \
27: while(1); \
28: } while (0)
29: #define BUG_ON(condition) do { if (condition) BUG(); } while (0)
30:
31: /*
32: * vring_free
33: *
34: * put at the begin of the free list the current desc[head]
35: */
36:
37: void vring_detach(struct vring_virtqueue *vq, unsigned int head)
38: {
39: struct vring *vr = &vq->vring;
40: unsigned int i;
41:
42: /* find end of given descriptor */
43:
44: i = head;
45: while (vr->desc[i].flags & VRING_DESC_F_NEXT)
46: i = vr->desc[i].next;
47:
48: /* link it with free list and point to it */
49:
50: vr->desc[i].next = vq->free_head;
51: wmb();
52: vq->free_head = head;
53: }
54:
55: /*
56: * vring_get_buf
57: *
58: * get a buffer from the used list
59: *
60: */
61:
62: void *vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
63: {
64: struct vring *vr = &vq->vring;
65: struct vring_used_elem *elem;
66: u32 id;
67: void *opaque;
68:
69: BUG_ON(!vring_more_used(vq));
70:
71: elem = &vr->used->ring[vq->last_used_idx % vr->num];
72: wmb();
73: id = elem->id;
74: if (len != NULL)
75: *len = elem->len;
76:
77: opaque = vq->vdata[id];
78:
79: vring_detach(vq, id);
80:
81: vq->last_used_idx++;
82:
83: return opaque;
84: }
85:
86: void vring_add_buf(struct vring_virtqueue *vq,
87: struct vring_list list[],
88: unsigned int out, unsigned int in,
89: void *opaque, int num_added)
90: {
91: struct vring *vr = &vq->vring;
92: int i, avail, head, prev;
93:
94: BUG_ON(out + in == 0);
95:
96: prev = 0;
97: head = vq->free_head;
98: for (i = head; out; i = vr->desc[i].next, out--) {
99:
100: vr->desc[i].flags = VRING_DESC_F_NEXT;
101: vr->desc[i].addr = (u64)virt_to_phys(list->addr);
102: vr->desc[i].len = list->length;
103: prev = i;
104: list++;
105: }
106: for ( ; in; i = vr->desc[i].next, in--) {
107:
108: vr->desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
109: vr->desc[i].addr = (u64)virt_to_phys(list->addr);
110: vr->desc[i].len = list->length;
111: prev = i;
112: list++;
113: }
114: vr->desc[prev].flags &= ~VRING_DESC_F_NEXT;
115:
116: vq->free_head = i;
117:
118: vq->vdata[head] = opaque;
119:
120: avail = (vr->avail->idx + num_added) % vr->num;
121: vr->avail->ring[avail] = head;
122: wmb();
123: }
124:
125: void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
126: {
127: struct vring *vr = &vq->vring;
128:
129: wmb();
130: vr->avail->idx += num_added;
131:
132: mb();
133: if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY))
134: vp_notify(ioaddr, vq->queue_index);
135: }
136:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.