Support for booting from virtio disks
[seabios.git] / src / virtio-pci.c
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  *  Adopted for Seabios: Gleb Natapov <gleb@redhat.com>
13  *
14  * This work is licensed under the terms of the GNU LGPLv3
15  * See the COPYING file in the top-level directory.
16  */
17
18 #include "virtio-ring.h"
19 #include "virtio-pci.h"
20
21 int vp_find_vq(unsigned int ioaddr, int queue_index,
22                struct vring_virtqueue *vq)
23 {
24    struct vring * vr = &vq->vring;
25    u16 num;
26
27    ASSERT32FLAT();
28    /* select the queue */
29
30    outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
31
32    /* check if the queue is available */
33
34    num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM);
35    if (!num) {
36        dprintf(1, "ERROR: queue size is 0\n");
37        return -1;
38    }
39
40    if (num > MAX_QUEUE_NUM) {
41        dprintf(1, "ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
42        return -1;
43    }
44
45    /* check if the queue is already active */
46
47    if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
48        dprintf(1, "ERROR: queue already active\n");
49        return -1;
50    }
51
52    vq->queue_index = queue_index;
53
54    /* initialize the queue */
55
56    vring_init(vr, num, (unsigned char*)&vq->queue);
57
58    /* activate the queue
59     *
60     * NOTE: vr->desc is initialized by vring_init()
61     */
62
63    outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT,
64         ioaddr + VIRTIO_PCI_QUEUE_PFN);
65
66    return num;
67 }