Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / seabios / src / hw / 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 "config.h" // CONFIG_DEBUG_LEVEL
19 #include "malloc.h" // free
20 #include "output.h" // dprintf
21 #include "pci.h" // pci_config_readl
22 #include "pci_regs.h" // PCI_BASE_ADDRESS_0
23 #include "string.h" // memset
24 #include "virtio-pci.h"
25 #include "virtio-ring.h"
26
27 int vp_find_vq(unsigned int ioaddr, int queue_index,
28                struct vring_virtqueue **p_vq)
29 {
30    u16 num;
31
32    ASSERT32FLAT();
33    struct vring_virtqueue *vq = *p_vq = memalign_low(PAGE_SIZE, sizeof(*vq));
34    if (!vq) {
35        warn_noalloc();
36        goto fail;
37    }
38    memset(vq, 0, sizeof(*vq));
39
40    /* select the queue */
41
42    outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
43
44    /* check if the queue is available */
45
46    num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM);
47    if (!num) {
48        dprintf(1, "ERROR: queue size is 0\n");
49        goto fail;
50    }
51
52    if (num > MAX_QUEUE_NUM) {
53        dprintf(1, "ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
54        goto fail;
55    }
56
57    /* check if the queue is already active */
58
59    if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
60        dprintf(1, "ERROR: queue already active\n");
61        goto fail;
62    }
63
64    vq->queue_index = queue_index;
65
66    /* initialize the queue */
67
68    struct vring * vr = &vq->vring;
69    vring_init(vr, num, (unsigned char*)&vq->queue);
70
71    /* activate the queue
72     *
73     * NOTE: vr->desc is initialized by vring_init()
74     */
75
76    outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT,
77         ioaddr + VIRTIO_PCI_QUEUE_PFN);
78
79    return num;
80
81 fail:
82    free(vq);
83    *p_vq = NULL;
84    return -1;
85 }
86
87 u16 vp_init_simple(u16 bdf)
88 {
89     u16 ioaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) &
90         PCI_BASE_ADDRESS_IO_MASK;
91
92     vp_reset(ioaddr);
93     pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
94     vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
95                   VIRTIO_CONFIG_S_DRIVER );
96     return ioaddr;
97 }