Commit 880345c484df16a1ec91febb8751d43b5fb8fc77
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); | ... | ... |