continue;
new_addr = pci_bar_address(d, i, r->type, r->size);
+ if (!d->has_power) {
+ new_addr = PCI_BAR_UNMAPPED;
+ }
/* This bar isn't changed */
if (new_addr == r->addr)
if (range_covers_byte(addr, l, PCI_COMMAND)) {
pci_update_irq_disabled(d, was_irq_disabled);
memory_region_set_enabled(&d->bus_master_enable_region,
- pci_get_word(d->config + PCI_COMMAND)
- & PCI_COMMAND_MASTER);
+ (pci_get_word(d->config + PCI_COMMAND)
+ & PCI_COMMAND_MASTER) && d->has_power);
}
msi_write_config(d, addr, val_in, l);
pci_qdev_unrealize(DEVICE(pci_dev));
return;
}
+
+ pci_set_power(pci_dev, true);
}
PCIDevice *pci_new_multifunction(int devfn, bool multifunction,
return msg;
}
+void pci_set_power(PCIDevice *d, bool state)
+{
+ if (d->has_power == state) {
+ return;
+ }
+
+ d->has_power = state;
+ pci_update_mappings(d);
+ memory_region_set_enabled(&d->bus_master_enable_region,
+ (pci_get_word(d->config + PCI_COMMAND)
+ & PCI_COMMAND_MASTER) && d->has_power);
+ if (!d->has_power) {
+ pci_device_reset(d);
+ }
+}
+
static const TypeInfo pci_device_type_info = {
.name = TYPE_PCI_DEVICE,
.parent = TYPE_DEVICE,
/* non-zero functions are only exposed when function 0 is present,
* allowing direct removal of unexposed functions.
*/
- if (pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) {
+ if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) ||
+ !pci_dev->has_power) {
return;
}
/* non-zero functions are only exposed when function 0 is present,
* allowing direct removal of unexposed functions.
*/
- if (pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) {
+ if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) ||
+ !pci_dev->has_power) {
return ~0x0;
}