Message ID | 3404152716bc65ee54b1c906b2435089a6200092.1289805831.git.yamahata@valinux.co.jp |
---|---|
State | New |
Headers | show |
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 <yamahata@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
On Mon, Nov 15, 2010 at 10:06:13AM +0200, Michael S. Tsirkin wrote: > 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 <yamahata@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? Okay, let me check my understanding of the format. The openfirmware path in pci case looks like /pci@<ioport>/<device name>@<slot>,<func>/.../<device name>@<slot>,<func> "pci@<ioport>" corresponds to pci domain. So <mmio address> should be also supported in addition to <ioport>. Maybe we'd like "<device name>@" to be optional. So the parser would accept something like /{<ioport>, <mmio addr>}/<slot>,<func>/.../<slot>,<func>
On Mon, Nov 15, 2010 at 05:57:40PM +0900, Isaku Yamahata wrote: > On Mon, Nov 15, 2010 at 10:06:13AM +0200, Michael S. Tsirkin wrote: > > 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 <yamahata@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? > > Okay, let me check my understanding of the format. > > The openfirmware path in pci case looks like > /pci@<ioport>/<device name>@<slot>,<func>/.../<device name>@<slot>,<func> > > "pci@<ioport>" corresponds to pci domain. So <mmio address> should be > also supported in addition to <ioport>. > Correct. > Maybe we'd like "<device name>@" to be optional. > So the parser would accept something like > /{<ioport>, <mmio addr>}/<slot>,<func>/.../<slot>,<func> My patch series has pci_dev_fw_name() function that fills in <device name> for you, so no reason to make it optional. If you still want to make it optional @ should stay, so it should be /@ioport/@slot.func/ -- Gleb.
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,
introduce a function to parse pci device path of the format, [Domain:]Slot.Function:Slot.Function....:Slot.Function. Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> --- hw/pci.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/pci.h | 1 + 2 files changed, 88 insertions(+), 0 deletions(-)