Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[virtio] Split virtio-net.c into several files.
Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
- Loading branch information
Laurent Vivier
authored and
Michael Brown
committed
Nov 19, 2008
1 parent
14a739b
commit b48f37e
Showing
5 changed files
with
252 additions
and
207 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* virtio-pci.c - pci interface for virtio interface | ||
* | ||
* (c) Copyright 2008 Bull S.A.S. | ||
* | ||
* Author: Laurent Vivier <Laurent.Vivier@bull.net> | ||
* | ||
* some parts from Linux Virtio PCI driver | ||
* | ||
* Copyright IBM Corp. 2007 | ||
* Authors: Anthony Liguori <aliguori@us.ibm.com> | ||
* | ||
*/ | ||
|
||
#include "etherboot.h" | ||
#include "gpxe/io.h" | ||
#include "gpxe/virtio-ring.h" | ||
#include "gpxe/virtio-pci.h" | ||
|
||
int vp_find_vq(unsigned int ioaddr, int queue_index, | ||
struct vring_virtqueue *vq) | ||
{ | ||
struct vring * vr = &vq->vring; | ||
u16 num; | ||
|
||
/* select the queue */ | ||
|
||
outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL); | ||
|
||
/* check if the queue is available */ | ||
|
||
num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM); | ||
if (!num) { | ||
printf("ERROR: queue size is 0\n"); | ||
return -1; | ||
} | ||
|
||
if (num > MAX_QUEUE_NUM) { | ||
printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); | ||
return -1; | ||
} | ||
|
||
/* check if the queue is already active */ | ||
|
||
if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) { | ||
printf("ERROR: queue already active\n"); | ||
return -1; | ||
} | ||
|
||
vq->queue_index = queue_index; | ||
|
||
/* initialize the queue */ | ||
|
||
vring_init(vr, num, (unsigned char*)&vq->queue); | ||
|
||
/* activate the queue | ||
* | ||
* NOTE: vr->desc is initialized by vring_init() | ||
*/ | ||
|
||
outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT, | ||
ioaddr + VIRTIO_PCI_QUEUE_PFN); | ||
|
||
return num; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
/* virtio-pci.c - virtio ring management | ||
* | ||
* (c) Copyright 2008 Bull S.A.S. | ||
* | ||
* Author: Laurent Vivier <Laurent.Vivier@bull.net> | ||
* | ||
* some parts from Linux Virtio Ring | ||
* | ||
* Copyright Rusty Russell IBM Corporation 2007 | ||
* | ||
* This work is licensed under the terms of the GNU GPL, version 2 or later. | ||
* See the COPYING file in the top-level directory. | ||
* | ||
* | ||
*/ | ||
|
||
#include "etherboot.h" | ||
#include "gpxe/io.h" | ||
#include "gpxe/virtio-ring.h" | ||
#include "gpxe/virtio-pci.h" | ||
|
||
#define BUG() do { \ | ||
printf("BUG: failure at %s:%d/%s()!\n", \ | ||
__FILE__, __LINE__, __FUNCTION__); \ | ||
while(1); \ | ||
} while (0) | ||
#define BUG_ON(condition) do { if (condition) BUG(); } while (0) | ||
|
||
/* | ||
* vring_free | ||
* | ||
* put at the begin of the free list the current desc[head] | ||
*/ | ||
|
||
void vring_detach(struct vring_virtqueue *vq, unsigned int head) | ||
{ | ||
struct vring *vr = &vq->vring; | ||
unsigned int i; | ||
|
||
/* find end of given descriptor */ | ||
|
||
i = head; | ||
while (vr->desc[i].flags & VRING_DESC_F_NEXT) | ||
i = vr->desc[i].next; | ||
|
||
/* link it with free list and point to it */ | ||
|
||
vr->desc[i].next = vq->free_head; | ||
wmb(); | ||
vq->free_head = head; | ||
} | ||
|
||
/* | ||
* vring_get_buf | ||
* | ||
* get a buffer from the used list | ||
* | ||
*/ | ||
|
||
int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len) | ||
{ | ||
struct vring *vr = &vq->vring; | ||
struct vring_used_elem *elem; | ||
u32 id; | ||
int ret; | ||
|
||
BUG_ON(!vring_more_used(vq)); | ||
|
||
elem = &vr->used->ring[vq->last_used_idx % vr->num]; | ||
wmb(); | ||
id = elem->id; | ||
if (len != NULL) | ||
*len = elem->len; | ||
|
||
ret = vq->vdata[id]; | ||
|
||
vring_detach(vq, id); | ||
|
||
vq->last_used_idx++; | ||
|
||
return ret; | ||
} | ||
|
||
void vring_add_buf(struct vring_virtqueue *vq, | ||
struct vring_list list[], | ||
unsigned int out, unsigned int in, | ||
int index, int num_added) | ||
{ | ||
struct vring *vr = &vq->vring; | ||
int i, avail, head, prev; | ||
|
||
BUG_ON(out + in == 0); | ||
|
||
prev = 0; | ||
head = vq->free_head; | ||
for (i = head; out; i = vr->desc[i].next, out--) { | ||
|
||
vr->desc[i].flags = VRING_DESC_F_NEXT; | ||
vr->desc[i].addr = (u64)virt_to_phys(list->addr); | ||
vr->desc[i].len = list->length; | ||
prev = i; | ||
list++; | ||
} | ||
for ( ; in; i = vr->desc[i].next, in--) { | ||
|
||
vr->desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE; | ||
vr->desc[i].addr = (u64)virt_to_phys(list->addr); | ||
vr->desc[i].len = list->length; | ||
prev = i; | ||
list++; | ||
} | ||
vr->desc[prev].flags &= ~VRING_DESC_F_NEXT; | ||
|
||
vq->free_head = i; | ||
|
||
vq->vdata[head] = index; | ||
|
||
avail = (vr->avail->idx + num_added) % vr->num; | ||
vr->avail->ring[avail] = head; | ||
wmb(); | ||
} | ||
|
||
void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added) | ||
{ | ||
struct vring *vr = &vq->vring; | ||
|
||
wmb(); | ||
vr->avail->idx += num_added; | ||
|
||
mb(); | ||
if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY)) | ||
vp_notify(ioaddr, vq->queue_index); | ||
} | ||
|
Oops, something went wrong.