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
This commit is contained in:
parent
51bf9e7e18
commit
5851e08cb8
47
hw/pci.c
47
hw/pci.c
@ -196,6 +196,48 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
|
|||||||
return pci_dev;
|
return pci_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
|
||||||
|
{
|
||||||
|
return addr + pci_mem_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pci_unregister_io_regions(PCIDevice *pci_dev)
|
||||||
|
{
|
||||||
|
PCIIORegion *r;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < PCI_NUM_REGIONS; i++) {
|
||||||
|
r = &pci_dev->io_regions[i];
|
||||||
|
if (!r->size || r->addr == -1)
|
||||||
|
continue;
|
||||||
|
if (r->type == PCI_ADDRESS_SPACE_IO) {
|
||||||
|
isa_unassign_ioport(r->addr, r->size);
|
||||||
|
} else {
|
||||||
|
cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
|
||||||
|
r->size,
|
||||||
|
IO_MEM_UNASSIGNED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int pci_unregister_device(PCIDevice *pci_dev)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (pci_dev->unregister)
|
||||||
|
ret = pci_dev->unregister(pci_dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
pci_unregister_io_regions(pci_dev);
|
||||||
|
|
||||||
|
qemu_free_irqs(pci_dev->irq);
|
||||||
|
pci_irq_index--;
|
||||||
|
pci_dev->bus->devices[pci_dev->devfn] = NULL;
|
||||||
|
qemu_free(pci_dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void pci_register_io_region(PCIDevice *pci_dev, int region_num,
|
void pci_register_io_region(PCIDevice *pci_dev, int region_num,
|
||||||
uint32_t size, int type,
|
uint32_t size, int type,
|
||||||
PCIMapIORegionFunc *map_func)
|
PCIMapIORegionFunc *map_func)
|
||||||
@ -218,11 +260,6 @@ void pci_register_io_region(PCIDevice *pci_dev, int region_num,
|
|||||||
*(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
|
*(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
|
|
||||||
{
|
|
||||||
return addr + pci_mem_base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pci_update_mappings(PCIDevice *d)
|
static void pci_update_mappings(PCIDevice *d)
|
||||||
{
|
{
|
||||||
PCIIORegion *r;
|
PCIIORegion *r;
|
||||||
|
3
hw/pci.h
3
hw/pci.h
@ -125,6 +125,7 @@ typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
|
|||||||
uint32_t address, int len);
|
uint32_t address, int len);
|
||||||
typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
|
typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
|
||||||
uint32_t addr, uint32_t size, int type);
|
uint32_t addr, uint32_t size, int type);
|
||||||
|
typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
|
||||||
|
|
||||||
#define PCI_ADDRESS_SPACE_MEM 0x00
|
#define PCI_ADDRESS_SPACE_MEM 0x00
|
||||||
#define PCI_ADDRESS_SPACE_IO 0x01
|
#define PCI_ADDRESS_SPACE_IO 0x01
|
||||||
@ -189,6 +190,7 @@ struct PCIDevice {
|
|||||||
/* do not access the following fields */
|
/* do not access the following fields */
|
||||||
PCIConfigReadFunc *config_read;
|
PCIConfigReadFunc *config_read;
|
||||||
PCIConfigWriteFunc *config_write;
|
PCIConfigWriteFunc *config_write;
|
||||||
|
PCIUnregisterFunc *unregister;
|
||||||
/* ??? This is a PC-specific hack, and should be removed. */
|
/* ??? This is a PC-specific hack, and should be removed. */
|
||||||
int irq_index;
|
int irq_index;
|
||||||
|
|
||||||
@ -203,6 +205,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
|
|||||||
int instance_size, int devfn,
|
int instance_size, int devfn,
|
||||||
PCIConfigReadFunc *config_read,
|
PCIConfigReadFunc *config_read,
|
||||||
PCIConfigWriteFunc *config_write);
|
PCIConfigWriteFunc *config_write);
|
||||||
|
int pci_unregister_device(PCIDevice *pci_dev);
|
||||||
|
|
||||||
void pci_register_io_region(PCIDevice *pci_dev, int region_num,
|
void pci_register_io_region(PCIDevice *pci_dev, int region_num,
|
||||||
uint32_t size, int type,
|
uint32_t size, int type,
|
||||||
|
Loading…
Reference in New Issue
Block a user