Commit 5851e08cb8df5c9d0c69fb5259ee6174ee651fae
1 parent
51bf9e7e
qemu: add pci_unregister_device (Marcelo Tosatti)
Unregister the pci device, unassign its IO and memory regions, and free associated data. Add a callback so drivers can free device state. 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@6603 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
45 additions
and
5 deletions
hw/pci.c
| @@ -196,6 +196,48 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name, | @@ -196,6 +196,48 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name, | ||
| 196 | return pci_dev; | 196 | return pci_dev; |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | +static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr) | ||
| 200 | +{ | ||
| 201 | + return addr + pci_mem_base; | ||
| 202 | +} | ||
| 203 | + | ||
| 204 | +static void pci_unregister_io_regions(PCIDevice *pci_dev) | ||
| 205 | +{ | ||
| 206 | + PCIIORegion *r; | ||
| 207 | + int i; | ||
| 208 | + | ||
| 209 | + for(i = 0; i < PCI_NUM_REGIONS; i++) { | ||
| 210 | + r = &pci_dev->io_regions[i]; | ||
| 211 | + if (!r->size || r->addr == -1) | ||
| 212 | + continue; | ||
| 213 | + if (r->type == PCI_ADDRESS_SPACE_IO) { | ||
| 214 | + isa_unassign_ioport(r->addr, r->size); | ||
| 215 | + } else { | ||
| 216 | + cpu_register_physical_memory(pci_to_cpu_addr(r->addr), | ||
| 217 | + r->size, | ||
| 218 | + IO_MEM_UNASSIGNED); | ||
| 219 | + } | ||
| 220 | + } | ||
| 221 | +} | ||
| 222 | + | ||
| 223 | +int pci_unregister_device(PCIDevice *pci_dev) | ||
| 224 | +{ | ||
| 225 | + int ret = 0; | ||
| 226 | + | ||
| 227 | + if (pci_dev->unregister) | ||
| 228 | + ret = pci_dev->unregister(pci_dev); | ||
| 229 | + if (ret) | ||
| 230 | + return ret; | ||
| 231 | + | ||
| 232 | + pci_unregister_io_regions(pci_dev); | ||
| 233 | + | ||
| 234 | + qemu_free_irqs(pci_dev->irq); | ||
| 235 | + pci_irq_index--; | ||
| 236 | + pci_dev->bus->devices[pci_dev->devfn] = NULL; | ||
| 237 | + qemu_free(pci_dev); | ||
| 238 | + return 0; | ||
| 239 | +} | ||
| 240 | + | ||
| 199 | void pci_register_io_region(PCIDevice *pci_dev, int region_num, | 241 | void pci_register_io_region(PCIDevice *pci_dev, int region_num, |
| 200 | uint32_t size, int type, | 242 | uint32_t size, int type, |
| 201 | PCIMapIORegionFunc *map_func) | 243 | PCIMapIORegionFunc *map_func) |
| @@ -218,11 +260,6 @@ void pci_register_io_region(PCIDevice *pci_dev, int region_num, | @@ -218,11 +260,6 @@ void pci_register_io_region(PCIDevice *pci_dev, int region_num, | ||
| 218 | *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type); | 260 | *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type); |
| 219 | } | 261 | } |
| 220 | 262 | ||
| 221 | -static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr) | ||
| 222 | -{ | ||
| 223 | - return addr + pci_mem_base; | ||
| 224 | -} | ||
| 225 | - | ||
| 226 | static void pci_update_mappings(PCIDevice *d) | 263 | static void pci_update_mappings(PCIDevice *d) |
| 227 | { | 264 | { |
| 228 | PCIIORegion *r; | 265 | PCIIORegion *r; |
hw/pci.h
| @@ -125,6 +125,7 @@ typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, | @@ -125,6 +125,7 @@ typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, | ||
| 125 | uint32_t address, int len); | 125 | uint32_t address, int len); |
| 126 | typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, | 126 | typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, |
| 127 | uint32_t addr, uint32_t size, int type); | 127 | uint32_t addr, uint32_t size, int type); |
| 128 | +typedef int PCIUnregisterFunc(PCIDevice *pci_dev); | ||
| 128 | 129 | ||
| 129 | #define PCI_ADDRESS_SPACE_MEM 0x00 | 130 | #define PCI_ADDRESS_SPACE_MEM 0x00 |
| 130 | #define PCI_ADDRESS_SPACE_IO 0x01 | 131 | #define PCI_ADDRESS_SPACE_IO 0x01 |
| @@ -189,6 +190,7 @@ struct PCIDevice { | @@ -189,6 +190,7 @@ struct PCIDevice { | ||
| 189 | /* do not access the following fields */ | 190 | /* do not access the following fields */ |
| 190 | PCIConfigReadFunc *config_read; | 191 | PCIConfigReadFunc *config_read; |
| 191 | PCIConfigWriteFunc *config_write; | 192 | PCIConfigWriteFunc *config_write; |
| 193 | + PCIUnregisterFunc *unregister; | ||
| 192 | /* ??? This is a PC-specific hack, and should be removed. */ | 194 | /* ??? This is a PC-specific hack, and should be removed. */ |
| 193 | int irq_index; | 195 | int irq_index; |
| 194 | 196 | ||
| @@ -203,6 +205,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name, | @@ -203,6 +205,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name, | ||
| 203 | int instance_size, int devfn, | 205 | int instance_size, int devfn, |
| 204 | PCIConfigReadFunc *config_read, | 206 | PCIConfigReadFunc *config_read, |
| 205 | PCIConfigWriteFunc *config_write); | 207 | PCIConfigWriteFunc *config_write); |
| 208 | +int pci_unregister_device(PCIDevice *pci_dev); | ||
| 206 | 209 | ||
| 207 | void pci_register_io_region(PCIDevice *pci_dev, int region_num, | 210 | void pci_register_io_region(PCIDevice *pci_dev, int region_num, |
| 208 | uint32_t size, int type, | 211 | uint32_t size, int type, |