From ca1d23790a16d7f5c4c4644a3c70ad9706e6faf4 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti <mtosatti@redhat.com> Date: Thu, 19 Feb 2009 21:28:09 -0300 Subject: [PATCH 1/3] Parse full PCI device addresses (Markus Armbruster) This code parses full PCI device addresses. It then rejects domains other than zero, because these are not supported in QEMU. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Bugzilla: 489992 Acked-by: Eduardo Habkost <ehabkost@redhat.com> Acked-by: Markus Armbruster <armbru@redhat.com> --- qemu/hw/pci.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu/hw/pci.h | 3 ++ 2 files changed, 80 insertions(+), 0 deletions(-) diff --git a/qemu/hw/pci.c b/qemu/hw/pci.c index 5910c8a..27bdb7c 100644 --- a/qemu/hw/pci.c +++ b/qemu/hw/pci.c @@ -28,6 +28,7 @@ #include "virtio-net.h" #include "pc.h" #include "qemu-kvm.h" +#include "sysemu.h" //#define DEBUG_PCI @@ -161,6 +162,82 @@ static int pci_set_default_subsystem_id(PCIDevice *pci_dev) return 0; } +/* + * Parse [[<domain>:]<bus>:]<slot>, return -1 on error + */ +static int pci_parse_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp) +{ + const char *p; + char *e; + unsigned long val; + unsigned long dom = 0, bus = 0; + unsigned slot = 0; + + p = addr; + val = strtoul(p, &e, 16); + if (e == p) + return -1; + if (*e == ':') { + bus = val; + p = e + 1; + val = strtoul(p, &e, 16); + if (e == p) + return -1; + if (*e == ':') { + dom = bus; + bus = val; + p = e + 1; + val = strtoul(p, &e, 16); + if (e == p) + return -1; + } + } + + if (dom > 0xffff || bus > 0xff || val > 0x1f) + return -1; + + slot = val; + + if (*e) + return -1; + + /* Note: QEMU doesn't implement domains other than 0 */ + if (dom != 0 || pci_find_bus(bus) == NULL) + return -1; + + *domp = dom; + *busp = bus; + *slotp = slot; + return 0; +} + +int pci_read_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp) +{ + char devaddr[32]; + + if (!get_param_value(devaddr, sizeof(devaddr), "pci_addr", addr)) + return -1; + + return pci_parse_devaddr(devaddr, domp, busp, slotp); +} + +int pci_assign_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp) +{ + char devaddr[32]; + + if (!get_param_value(devaddr, sizeof(devaddr), "pci_addr", addr)) + return -1; + + if (!strcmp(devaddr, "auto")) { + *domp = *busp = 0; + *slotp = -1; + /* want to support dom/bus auto-assign at some point */ + return 0; + } + + return pci_parse_devaddr(devaddr, domp, busp, slotp); +} + /* -1 for devfn means auto assign */ PCIDevice *pci_register_device(PCIBus *bus, const char *name, int instance_size, int devfn, diff --git a/qemu/hw/pci.h b/qemu/hw/pci.h index 060183a..5667f36 100644 --- a/qemu/hw/pci.h +++ b/qemu/hw/pci.h @@ -135,6 +135,9 @@ void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d)); PCIBus *pci_find_bus(int bus_num); PCIDevice *pci_find_device(int bus_num, int slot); +int pci_read_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp); +int pci_assign_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp); + void pci_info(void); PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id, pci_map_irq_fn map_irq, const char *name); -- 1.6.1