From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 1/9] PCI device registration helpers
Date: Thu, 22 Jan 2009 20:30:57 +0100 [thread overview]
Message-ID: <1232652665-1710-1-git-send-email-armbru@redhat.com> (raw)
In-Reply-To: <87ocxzrvqb.fsf@pike.pond.sub.org>
From: Markus Armbruster <armbru@pond.sub.org>
Registering a device with a PCI device address given as pci=... in the
common name=value,... option argument involves several steps: extract
the device address, parse it, find the PICBus, call
pci_register_device(). Put code for that in one place, namelt the new
helper function pci_register_device_2(). Yes, the name is stupid, and
is subject to change.
This code parses full PCI device addresses. It then rejects domains
other than zero, because these are not supported in QEMU.
FIXME it lets you specify .func, which is most probably inappropriate.
---
hw/pci.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/pci.h | 6 ++++
2 files changed, 108 insertions(+), 0 deletions(-)
diff --git a/hw/pci.c b/hw/pci.c
index bba50d0..a0e8562 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,97 @@ static int pci_set_default_subsystem_id(PCIDevice *pci_dev)
return 0;
}
+/*
+ * Parse [[<domain>:]<bus>:]<dev>[.<func>], return -1 on error
+ */
+int pci_parse_devaddr(const char *addr, int *domp, int *busp, int *devfnp)
+{
+ const char *p;
+ char *e;
+ unsigned long val;
+ unsigned long dom = 0, bus = 0;
+ unsigned slot;
+ unsigned func = 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 == '.') {
+ p = e + 1;
+ val = strtoul(p, &e, 16);
+ if (e == p || val > 7 || *e != '\0')
+ return -1;
+ func = val;
+ }
+
+ if (*e)
+ return -1;
+
+ *domp = dom;
+ *busp = bus;
+ *devfnp = (slot << 3) | func;
+ return 0;
+}
+
+PCIDevice *pci_register_device_2(const char *name, const char *opts,
+ int instance_size,
+ PCIConfigReadFunc *config_read,
+ PCIConfigWriteFunc *config_write)
+{
+ char devaddr[32];
+ int dom, bus_num, devfn;
+ PCIBus *bus;
+ PCIDevice *dev;
+
+ if (get_param_value(devaddr, sizeof(devaddr), "pci", opts)) {
+ if (pci_parse_devaddr(devaddr, &dom, &bus_num, &devfn) < 0) {
+ fprintf(stderr, "Bad PCI device address %s for %s",
+ devaddr, name);
+ return NULL;
+ }
+ } else {
+ dom = bus_num = 0;
+ devfn = -1;
+ }
+
+ /* Note: QEMU doesn't implement domains other than 0 */
+ if (dom != 0 || (bus = pci_find_bus(bus_num)) == NULL) {
+ fprintf(stderr, "PCI device address %s not supported for %s",
+ devaddr, name);
+ return NULL;
+ }
+
+ dev = pci_register_device(bus, name, instance_size, devfn,
+ config_read, config_write);
+ if (!dev) {
+ fprintf(stderr, "Could not set up PCI device %s", name);
+ return NULL;
+ }
+
+ return dev;
+}
+
/* -1 for devfn means auto assign */
PCIDevice *pci_register_device(PCIBus *bus, const char *name,
int instance_size, int devfn,
@@ -713,6 +805,16 @@ static void pci_bridge_write_config(PCIDevice *d,
pci_default_write_config(d, address, val, len);
}
+PCIBus *pci_find_bus(int bus_num)
+{
+ PCIBus *bus = first_bus;
+
+ while (bus && bus->bus_num != bus_num)
+ bus = bus->next;
+
+ return bus;
+}
+
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
pci_map_irq_fn map_irq, const char *name)
{
diff --git a/hw/pci.h b/hw/pci.h
index 867e6fe..1528fc2 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -101,6 +101,10 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
int instance_size, int devfn,
PCIConfigReadFunc *config_read,
PCIConfigWriteFunc *config_write);
+PCIDevice *pci_register_device_2(const char *name, const char *opts,
+ int instance_size,
+ PCIConfigReadFunc *config_read,
+ PCIConfigWriteFunc *config_write);
void pci_register_io_region(PCIDevice *pci_dev, int region_num,
uint32_t size, int type,
@@ -112,6 +116,7 @@ void pci_default_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len);
void pci_device_save(PCIDevice *s, QEMUFile *f);
int pci_device_load(PCIDevice *s, QEMUFile *f);
+int pci_parse_devaddr(const char *addr, int *domain, int *bus, int *devfn);
typedef void (*pci_set_irq_fn)(qemu_irq *pic, int irq_num, int level);
typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
@@ -124,6 +129,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
int pci_bus_num(PCIBus *s);
void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
+PCIBus *pci_find_bus(int bus_num);
void pci_info(void);
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
--
1.6.0.6
next prev parent reply other threads:[~2009-01-22 19:31 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-22 19:23 [Qemu-devel] [RFC PATCH 0/9] Configurable PCI device addresses Markus Armbruster
2009-01-22 19:30 ` Markus Armbruster [this message]
2009-01-22 19:30 ` [Qemu-devel] [PATCH 2/9] Clean up handling of name=value, ... part of -vga option argument Markus Armbruster
2009-01-22 19:30 ` [Qemu-devel] [PATCH 3/9] Support pci=... in option argument of -vga Markus Armbruster
2009-01-22 19:31 ` [Qemu-devel] [PATCH 4/9] Convert virtio_init_pci() to pci_register_device_2() Markus Armbruster
2009-01-22 19:31 ` [Qemu-devel] [PATCH 5/9] Support pci=... in option argument of -net nic Markus Armbruster
2009-01-22 19:31 ` [Qemu-devel] [PATCH 6/9] Make drives_opt[] accessible from device initialization Markus Armbruster
2009-01-22 19:31 ` [Qemu-devel] [PATCH 7/9] Support pci=... in option argument of -drive if=virtio Markus Armbruster
2009-01-22 19:31 ` [Qemu-devel] [PATCH 8/9] New option -audio as a more flexible alternative to -soundhw Markus Armbruster
2009-01-22 22:03 ` malc
2009-01-23 8:32 ` Markus Armbruster
2009-01-23 9:29 ` Kevin Wolf
2009-01-23 10:04 ` Markus Armbruster
2009-01-23 10:24 ` Kevin Wolf
2009-01-23 11:51 ` Markus Armbruster
2009-01-22 19:31 ` [Qemu-devel] [PATCH 9/9] Support pci=... in option argument of -audio Markus Armbruster
2009-01-22 20:06 ` [Qemu-devel] [RFC PATCH 0/9] Configurable PCI device addresses Anthony Liguori
2009-01-23 9:04 ` Markus Armbruster
2009-01-23 10:23 ` Daniel P. Berrange
2009-01-23 19:06 ` Paul Brook
2009-01-23 19:28 ` Anthony Liguori
2009-01-26 8:55 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1232652665-1710-1-git-send-email-armbru@redhat.com \
--to=armbru@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).