1 | /* virtio-pci.c - pci interface for virtio interface |
---|
2 | * |
---|
3 | * (c) Copyright 2008 Bull S.A.S. |
---|
4 | * |
---|
5 | * Author: Laurent Vivier <Laurent.Vivier@bull.net> |
---|
6 | * |
---|
7 | * some parts from Linux Virtio PCI driver |
---|
8 | * |
---|
9 | * Copyright IBM Corp. 2007 |
---|
10 | * Authors: Anthony Liguori <aliguori@us.ibm.com> |
---|
11 | * |
---|
12 | */ |
---|
13 | |
---|
14 | #include "etherboot.h" |
---|
15 | #include "gpxe/io.h" |
---|
16 | #include "gpxe/virtio-ring.h" |
---|
17 | #include "gpxe/virtio-pci.h" |
---|
18 | |
---|
19 | int vp_find_vq(unsigned int ioaddr, int queue_index, |
---|
20 | struct vring_virtqueue *vq) |
---|
21 | { |
---|
22 | struct vring * vr = &vq->vring; |
---|
23 | u16 num; |
---|
24 | |
---|
25 | /* select the queue */ |
---|
26 | |
---|
27 | outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL); |
---|
28 | |
---|
29 | /* check if the queue is available */ |
---|
30 | |
---|
31 | num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM); |
---|
32 | if (!num) { |
---|
33 | printf("ERROR: queue size is 0\n"); |
---|
34 | return -1; |
---|
35 | } |
---|
36 | |
---|
37 | if (num > MAX_QUEUE_NUM) { |
---|
38 | printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); |
---|
39 | return -1; |
---|
40 | } |
---|
41 | |
---|
42 | /* check if the queue is already active */ |
---|
43 | |
---|
44 | if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) { |
---|
45 | printf("ERROR: queue already active\n"); |
---|
46 | return -1; |
---|
47 | } |
---|
48 | |
---|
49 | vq->queue_index = queue_index; |
---|
50 | |
---|
51 | /* initialize the queue */ |
---|
52 | |
---|
53 | vring_init(vr, num, (unsigned char*)&vq->queue); |
---|
54 | |
---|
55 | /* activate the queue |
---|
56 | * |
---|
57 | * NOTE: vr->desc is initialized by vring_init() |
---|
58 | */ |
---|
59 | |
---|
60 | outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT, |
---|
61 | ioaddr + VIRTIO_PCI_QUEUE_PFN); |
---|
62 | |
---|
63 | return num; |
---|
64 | } |
---|