Commit 5851e08cb8df5c9d0c69fb5259ee6174ee651fae

Authored by aliguori
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 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 241 void pci_register_io_region(PCIDevice *pci_dev, int region_num,
200 242 uint32_t size, int type,
201 243 PCIMapIORegionFunc *map_func)
... ... @@ -218,11 +260,6 @@ void pci_register_io_region(PCIDevice *pci_dev, int region_num,
218 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 263 static void pci_update_mappings(PCIDevice *d)
227 264 {
228 265 PCIIORegion *r;
... ...
hw/pci.h
... ... @@ -125,6 +125,7 @@ typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
125 125 uint32_t address, int len);
126 126 typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
127 127 uint32_t addr, uint32_t size, int type);
  128 +typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
128 129  
129 130 #define PCI_ADDRESS_SPACE_MEM 0x00
130 131 #define PCI_ADDRESS_SPACE_IO 0x01
... ... @@ -189,6 +190,7 @@ struct PCIDevice {
189 190 /* do not access the following fields */
190 191 PCIConfigReadFunc *config_read;
191 192 PCIConfigWriteFunc *config_write;
  193 + PCIUnregisterFunc *unregister;
192 194 /* ??? This is a PC-specific hack, and should be removed. */
193 195 int irq_index;
194 196  
... ... @@ -203,6 +205,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
203 205 int instance_size, int devfn,
204 206 PCIConfigReadFunc *config_read,
205 207 PCIConfigWriteFunc *config_write);
  208 +int pci_unregister_device(PCIDevice *pci_dev);
206 209  
207 210 void pci_register_io_region(PCIDevice *pci_dev, int region_num,
208 211 uint32_t size, int type,
... ...