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,6 +26,7 @@
26 #include "console.h" 26 #include "console.h"
27 #include "net.h" 27 #include "net.h"
28 #include "virtio-net.h" 28 #include "virtio-net.h"
  29 +#include "sysemu.h"
29 30
30 //#define DEBUG_PCI 31 //#define DEBUG_PCI
31 32
@@ -158,6 +159,82 @@ static int pci_set_default_subsystem_id(PCIDevice *pci_dev) @@ -158,6 +159,82 @@ static int pci_set_default_subsystem_id(PCIDevice *pci_dev)
158 return 0; 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 /* -1 for devfn means auto assign */ 238 /* -1 for devfn means auto assign */
162 PCIDevice *pci_register_device(PCIBus *bus, const char *name, 239 PCIDevice *pci_register_device(PCIBus *bus, const char *name,
163 int instance_size, int devfn, 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,6 +232,9 @@ void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
232 PCIBus *pci_find_bus(int bus_num); 232 PCIBus *pci_find_bus(int bus_num);
233 PCIDevice *pci_find_device(int bus_num, int slot, int function); 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 void pci_info(void); 238 void pci_info(void);
236 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did, 239 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
237 pci_map_irq_fn map_irq, const char *name); 240 pci_map_irq_fn map_irq, const char *name);