Use the pci_enable_x() functions.
This patch also converts cap->addr from a 'u32' to a union storing a 'u32' or a 'void*'. This makes it more clear when the address is a virtual memory address.
The virtio controller code will now explicitly set PCI_COMMAND_MEMORY and/or PCI_COMMAND_IO instead of assuming it has already been enabled.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/virtio-pci.c | 36 ++++++++++++++++++++---------------- src/hw/virtio-pci.h | 32 ++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 30 deletions(-)
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c index 6df5194..f1e30a2 100644 --- a/src/hw/virtio-pci.c +++ b/src/hw/virtio-pci.c @@ -100,16 +100,14 @@ void vp_reset(struct vp_device *vp) void vp_notify(struct vp_device *vp, struct vring_virtqueue *vq) { if (vp->use_modern) { - u32 addr = vp->notify.addr + - vq->queue_notify_off * - vp->notify_off_multiplier; + u32 offset = vq->queue_notify_off * vp->notify_off_multiplier; if (vp->notify.is_io) { - outw(vq->queue_index, addr); + outw(vq->queue_index, vp->notify.ioaddr + offset); } else { - writew((void*)addr, vq->queue_index); + writew(vp->notify.memaddr + offset, vq->queue_index); } dprintf(9, "vp notify %x (%d) -- 0x%x\n", - addr, 2, vq->queue_index); + vp->notify.ioaddr, 2, vq->queue_index); } else { vp_write(&vp->legacy, virtio_pci_legacy, queue_notify, vq->queue_index); } @@ -208,7 +206,7 @@ void vp_init_simple(struct vp_device *vp, struct pci_device *pci) { u8 cap = pci_find_capability(pci, PCI_CAP_ID_VNDR, 0); struct vp_cap *vp_cap; - u32 addr, offset, mul; + u32 offset, mul; u8 type;
memset(vp, 0, sizeof(*vp)); @@ -240,19 +238,24 @@ void vp_init_simple(struct vp_device *vp, struct pci_device *pci) offsetof(struct virtio_pci_cap, bar)); offset = pci_config_readl(pci->bdf, cap + offsetof(struct virtio_pci_cap, offset)); - addr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0 + 4 * vp_cap->bar); - if (addr & PCI_BASE_ADDRESS_SPACE_IO) { + u32 bar = PCI_BASE_ADDRESS_0 + 4 * vp_cap->bar; + if (pci_config_readl(pci->bdf, bar) & PCI_BASE_ADDRESS_SPACE_IO) { vp_cap->is_io = 1; - addr &= PCI_BASE_ADDRESS_IO_MASK; + u32 addr = pci_enable_iobar(pci, bar); + if (!addr) + return; + vp_cap->ioaddr = addr + offset; } else { vp_cap->is_io = 0; - addr &= PCI_BASE_ADDRESS_MEM_MASK; + void *addr = pci_enable_membar(pci, bar); + if (!addr) + return; + vp_cap->memaddr = addr + offset; } - vp_cap->addr = addr + offset; dprintf(3, "pci dev %x:%x virtio cap at 0x%x type %d " "bar %d at 0x%08x off +0x%04x [%s]\n", pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), - vp_cap->cap, type, vp_cap->bar, addr, offset, + vp_cap->cap, type, vp_cap->bar, vp_cap->ioaddr, offset, vp_cap->is_io ? "io" : "mmio"); }
@@ -267,13 +270,14 @@ void vp_init_simple(struct vp_device *vp, struct pci_device *pci) dprintf(1, "pci dev %x:%x using legacy (0.9.5) virtio mode\n", pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf)); vp->legacy.bar = 0; - vp->legacy.addr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) & - PCI_BASE_ADDRESS_IO_MASK; + vp->legacy.ioaddr = pci_enable_iobar(pci, PCI_BASE_ADDRESS_0); + if (!vp->legacy.ioaddr) + return; vp->legacy.is_io = 1; }
vp_reset(vp); - pci_config_maskw(pci->bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); + pci_enable_busmaster(pci); vp_set_status(vp, VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER ); } diff --git a/src/hw/virtio-pci.h b/src/hw/virtio-pci.h index b11c355..ff8454e 100644 --- a/src/hw/virtio-pci.h +++ b/src/hw/virtio-pci.h @@ -86,7 +86,10 @@ typedef struct virtio_pci_isr { /* --- driver structs ----------------------------------------------- */
struct vp_cap { - u32 addr; + union { + void *memaddr; + u32 ioaddr; + }; u8 cap; u8 bar; u8 is_io; @@ -100,10 +103,10 @@ struct vp_device {
static inline u64 _vp_read(struct vp_cap *cap, u32 offset, u8 size) { - u32 addr = cap->addr + offset; u64 var;
if (cap->is_io) { + u32 addr = cap->ioaddr + offset; switch (size) { case 8: var = inl(addr); @@ -122,34 +125,34 @@ static inline u64 _vp_read(struct vp_cap *cap, u32 offset, u8 size) var = 0; } } else { + void *addr = cap->memaddr + offset; switch (size) { case 8: - var = readl((void*)addr); - var |= (u64)readl((void*)(addr+4)) << 32; + var = readl(addr); + var |= (u64)readl(addr+4) << 32; break; case 4: - var = readl((void*)addr); + var = readl(addr); break; case 2: - var = readw((void*)addr); + var = readw(addr); break; case 1: - var = readb((void*)addr); + var = readb(addr); break; default: var = 0; } } - dprintf(9, "vp read %x (%d) -> 0x%llx\n", addr, size, var); + dprintf(9, "vp read %x (%d) -> 0x%llx\n", cap->ioaddr + offset, size, var); return var; }
static inline void _vp_write(struct vp_cap *cap, u32 offset, u8 size, u64 var) { - u32 addr = cap->addr + offset; - - dprintf(9, "vp write %x (%d) <- 0x%llx\n", addr, size, var); + dprintf(9, "vp write %x (%d) <- 0x%llx\n", cap->ioaddr + offset, size, var); if (cap->is_io) { + u32 addr = cap->ioaddr + offset; switch (size) { case 4: outl(var, addr); @@ -162,15 +165,16 @@ static inline void _vp_write(struct vp_cap *cap, u32 offset, u8 size, u64 var) break; } } else { + void *addr = cap->memaddr + offset; switch (size) { case 4: - writel((void*)addr, var); + writel(addr, var); break; case 2: - writew((void*)addr, var); + writew(addr, var); break; case 1: - writeb((void*)addr, var); + writeb(addr, var); break; } }