1 /* virtio-pci.c - virtio ring management
3 * (c) Copyright 2008 Bull S.A.S.
5 * Author: Laurent Vivier <Laurent.Vivier@bull.net>
7 * some parts from Linux Virtio Ring
9 * Copyright Rusty Russell IBM Corporation 2007
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.
17 FILE_LICENCE ( GPL2_OR_LATER
);
19 #include "etherboot.h"
21 #include "ipxe/virtio-ring.h"
22 #include "ipxe/virtio-pci.h"
25 printf("BUG: failure at %s:%d/%s()!\n", \
26 __FILE__, __LINE__, __FUNCTION__); \
29 #define BUG_ON(condition) do { if (condition) BUG(); } while (0)
34 * put at the begin of the free list the current desc[head]
37 void vring_detach(struct vring_virtqueue
*vq
, unsigned int head
)
39 struct vring
*vr
= &vq
->vring
;
42 /* find end of given descriptor */
45 while (vr
->desc
[i
].flags
& VRING_DESC_F_NEXT
)
48 /* link it with free list and point to it */
50 vr
->desc
[i
].next
= vq
->free_head
;
58 * get a buffer from the used list
62 void *vring_get_buf(struct vring_virtqueue
*vq
, unsigned int *len
)
64 struct vring
*vr
= &vq
->vring
;
65 struct vring_used_elem
*elem
;
69 BUG_ON(!vring_more_used(vq
));
71 elem
= &vr
->used
->ring
[vq
->last_used_idx
% vr
->num
];
77 opaque
= vq
->vdata
[id
];
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
)
91 struct vring
*vr
= &vq
->vring
;
92 int i
, avail
, head
, prev
;
94 BUG_ON(out
+ in
== 0);
98 for (i
= head
; out
; i
= vr
->desc
[i
].next
, out
--) {
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
;
106 for ( ; in
; i
= vr
->desc
[i
].next
, in
--) {
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
;
114 vr
->desc
[prev
].flags
&= ~VRING_DESC_F_NEXT
;
118 vq
->vdata
[head
] = opaque
;
120 avail
= (vr
->avail
->idx
+ num_added
) % vr
->num
;
121 vr
->avail
->ring
[avail
] = head
;
125 void vring_kick(unsigned int ioaddr
, struct vring_virtqueue
*vq
, int num_added
)
127 struct vring
*vr
= &vq
->vring
;
130 vr
->avail
->idx
+= num_added
;
133 if (!(vr
->used
->flags
& VRING_USED_F_NO_NOTIFY
))
134 vp_notify(ioaddr
, vq
->queue_index
);