diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2013-09-02 20:48:46 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2013-09-02 20:48:46 -0400 |
commit | 5d369d8d9eb5326db111cc2e518c74739dbe3f84 (patch) | |
tree | 1fe04c2372e2041c5feb7e6c177a25f692cf4e76 /src/hw/virtio-pci.c | |
parent | 3cb0f504a782c1a9c790b939631854473c039397 (diff) | |
download | seabios-5d369d8d9eb5326db111cc2e518c74739dbe3f84.tar.gz |
Move code centered around specific hardware devices to src/hw/
Move many C files from the src/ directory to the new src/hw/ directory.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/hw/virtio-pci.c')
-rw-r--r-- | src/hw/virtio-pci.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c new file mode 100644 index 00000000..4b9ad0ac --- /dev/null +++ b/src/hw/virtio-pci.c @@ -0,0 +1,94 @@ +/* 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> + * + * Adopted for Seabios: Gleb Natapov <gleb@redhat.com> + * + * This work is licensed under the terms of the GNU LGPLv3 + * See the COPYING file in the top-level directory. + */ + +#include "virtio-ring.h" +#include "virtio-pci.h" +#include "config.h" // CONFIG_DEBUG_LEVEL +#include "util.h" // dprintf +#include "pci.h" // pci_config_readl +#include "pci_regs.h" // PCI_BASE_ADDRESS_0 + +int vp_find_vq(unsigned int ioaddr, int queue_index, + struct vring_virtqueue **p_vq) +{ + u16 num; + + ASSERT32FLAT(); + struct vring_virtqueue *vq = *p_vq = memalign_low(PAGE_SIZE, sizeof(*vq)); + if (!vq) { + warn_noalloc(); + goto fail; + } + memset(vq, 0, sizeof(*vq)); + + /* 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) { + dprintf(1, "ERROR: queue size is 0\n"); + goto fail; + } + + if (num > MAX_QUEUE_NUM) { + dprintf(1, "ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); + goto fail; + } + + /* check if the queue is already active */ + + if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) { + dprintf(1, "ERROR: queue already active\n"); + goto fail; + } + + vq->queue_index = queue_index; + + /* initialize the queue */ + + struct vring * vr = &vq->vring; + 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; + +fail: + free(vq); + *p_vq = NULL; + return -1; +} + +u16 vp_init_simple(u16 bdf) +{ + u16 ioaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) & + PCI_BASE_ADDRESS_IO_MASK; + + vp_reset(ioaddr); + vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE | + VIRTIO_CONFIG_S_DRIVER ); + return ioaddr; +} |