introduce a function to parse pci device path of the format, [Domain:]Slot.Function:Slot.Function....:Slot.Function.
Signed-off-by: Isaku Yamahata <yamah...@valinux.co.jp> --- hw/pci.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/pci.h | 1 + 2 files changed, 88 insertions(+), 0 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index fba765b..6a9a5ef 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -433,6 +433,93 @@ static void pci_set_default_subsystem_id(PCIDevice *pci_dev) } /* + * Parse format [Domain:]Slot.Function:Slot.Function....:Slot.Function + * and get PCIDevice + * return 0 on success + * -1 on error: format is invalid or device isn't found. + */ +int pci_parse_dev_path(const char *addr, PCIDevice **pdev) +{ + unsigned long domain; + unsigned long slot; + unsigned long func; + const char *p; + char *e; + unsigned long val; + PCIBus *bus; + PCIBus *child_bus; + PCIDevice *d; + + p = addr; + val = strtoul(p, &e, 0); + if (e == p) { + return -1; + } + if (*e == ':') { + domain = val; + p = e + 1; + val = strtoul(p, &e, 0); + if (e == p) { + return -1; + } + } else if (*e == '.'){ + domain = 0; + } else { + return -1; + } + if (domain > 0xffff) { + return -1; + } + + bus = pci_find_root_bus(domain); + if (!bus) { + return -1; + } + + for (;;) { + slot = val; + if (*e != '.') { + return -1; + } + p = e + 1; + val = strtoul(p, &e, 0); + if (e == p) { + return -1; + } + func = val; + if (slot > 0x1f || func >= PCI_FUNC_MAX) { + return -1; + } + d = bus->devices[PCI_DEVFN(slot, func)]; + if (!d) { + return -1; + } + if (*e == '\0') { + break; + } + + if (*e != ':') { + return -1; + } + p = e + 1; + val = strtoul(p, &e, 0); + if (e == p) { + return -1; + } + QLIST_FOREACH(child_bus, &bus->child, sibling) { + if (child_bus->parent_dev == d) { + bus = child_bus; + continue; + } + } + return -1; + } + + *pdev = d; + return 0; +} + +/* * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL * [[<domain>:]<bus>:]<slot>.<func>, return -1 on error */ diff --git a/hw/pci.h b/hw/pci.h index 7100804..8c16f91 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -239,6 +239,7 @@ PCIBus *pci_find_bus(PCIBus *bus, int bus_num); PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function); PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr); +int pci_parse_dev_path(const char *addr, PCIDevice **pdev); int pci_parse_devaddr(const char *addr, int *domp, int *busp, unsigned int *slotp, unsigned int *funcp); int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp, -- 1.7.1.1