aboutsummaryrefslogtreecommitdiff
path: root/hw/pci.c
diff options
context:
space:
mode:
authoraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2009-02-11 15:21:48 +0000
committeraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2009-02-11 15:21:48 +0000
commit880345c484df16a1ec91febb8751d43b5fb8fc77 (patch)
treea2e4c18223d8ff1fcec92f3e8ed922be09ee5d1a /hw/pci.c
parentca2c72be18dd8104fa9108ecefcd562e85672360 (diff)
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> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6609 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/pci.c')
-rw-r--r--hw/pci.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/hw/pci.c b/hw/pci.c
index cd07273c83..97918a378b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -26,6 +26,7 @@
#include "console.h"
#include "net.h"
#include "virtio-net.h"
+#include "sysemu.h"
//#define DEBUG_PCI
@@ -158,6 +159,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,