On Mon, Nov 15, 2010 at 04:30:43PM +0900, Isaku Yamahata wrote: > 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>
Hmm. How about we use openfirmware path like what Gleb's patch does, with a fallback to bus:dev.fn for when it's unambiguous? > --- > 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