Commit 880345c484df16a1ec91febb8751d43b5fb8fc77

Authored by aliguori
1 parent ca2c72be

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
Showing 2 changed files with 80 additions and 0 deletions
hw/pci.c
... ... @@ -26,6 +26,7 @@
26 26 #include "console.h"
27 27 #include "net.h"
28 28 #include "virtio-net.h"
  29 +#include "sysemu.h"
29 30  
30 31 //#define DEBUG_PCI
31 32  
... ... @@ -158,6 +159,82 @@ static int pci_set_default_subsystem_id(PCIDevice *pci_dev)
158 159 return 0;
159 160 }
160 161  
  162 +/*
  163 + * Parse [[<domain>:]<bus>:]<slot>, return -1 on error
  164 + */
  165 +static int pci_parse_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp)
  166 +{
  167 + const char *p;
  168 + char *e;
  169 + unsigned long val;
  170 + unsigned long dom = 0, bus = 0;
  171 + unsigned slot = 0;
  172 +
  173 + p = addr;
  174 + val = strtoul(p, &e, 16);
  175 + if (e == p)
  176 + return -1;
  177 + if (*e == ':') {
  178 + bus = val;
  179 + p = e + 1;
  180 + val = strtoul(p, &e, 16);
  181 + if (e == p)
  182 + return -1;
  183 + if (*e == ':') {
  184 + dom = bus;
  185 + bus = val;
  186 + p = e + 1;
  187 + val = strtoul(p, &e, 16);
  188 + if (e == p)
  189 + return -1;
  190 + }
  191 + }
  192 +
  193 + if (dom > 0xffff || bus > 0xff || val > 0x1f)
  194 + return -1;
  195 +
  196 + slot = val;
  197 +
  198 + if (*e)
  199 + return -1;
  200 +
  201 + /* Note: QEMU doesn't implement domains other than 0 */
  202 + if (dom != 0 || pci_find_bus(bus) == NULL)
  203 + return -1;
  204 +
  205 + *domp = dom;
  206 + *busp = bus;
  207 + *slotp = slot;
  208 + return 0;
  209 +}
  210 +
  211 +int pci_read_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp)
  212 +{
  213 + char devaddr[32];
  214 +
  215 + if (!get_param_value(devaddr, sizeof(devaddr), "pci_addr", addr))
  216 + return -1;
  217 +
  218 + return pci_parse_devaddr(devaddr, domp, busp, slotp);
  219 +}
  220 +
  221 +int pci_assign_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp)
  222 +{
  223 + char devaddr[32];
  224 +
  225 + if (!get_param_value(devaddr, sizeof(devaddr), "pci_addr", addr))
  226 + return -1;
  227 +
  228 + if (!strcmp(devaddr, "auto")) {
  229 + *domp = *busp = 0;
  230 + *slotp = -1;
  231 + /* want to support dom/bus auto-assign at some point */
  232 + return 0;
  233 + }
  234 +
  235 + return pci_parse_devaddr(devaddr, domp, busp, slotp);
  236 +}
  237 +
161 238 /* -1 for devfn means auto assign */
162 239 PCIDevice *pci_register_device(PCIBus *bus, const char *name,
163 240 int instance_size, int devfn,
... ...
hw/pci.h
... ... @@ -232,6 +232,9 @@ void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
232 232 PCIBus *pci_find_bus(int bus_num);
233 233 PCIDevice *pci_find_device(int bus_num, int slot, int function);
234 234  
  235 +int pci_read_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp);
  236 +int pci_assign_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp);
  237 +
235 238 void pci_info(void);
236 239 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
237 240 pci_map_irq_fn map_irq, const char *name);
... ...