#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 *vq)
+ struct vring_virtqueue **p_vq)
{
- struct vring * vr = &vq->vring;
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);
num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM);
if (!num) {
dprintf(1, "ERROR: queue size is 0\n");
- return -1;
+ goto fail;
}
if (num > MAX_QUEUE_NUM) {
dprintf(1, "ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
- return -1;
+ goto fail;
}
/* check if the queue is already active */
if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
dprintf(1, "ERROR: queue already active\n");
- return -1;
+ 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
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;
}