}
}
+static void pcie_set_power_device(PCIBus *bus, PCIDevice *dev, void *opaque)
+{
+ bool *power = opaque;
+
+ pci_set_power(dev, *power);
+}
+
+static void pcie_cap_update_power(PCIDevice *hotplug_dev)
+{
+ uint8_t *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
+ PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(hotplug_dev));
+ uint32_t sltcap = pci_get_long(exp_cap + PCI_EXP_SLTCAP);
+ uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
+ bool power = true;
+
+ if (sltcap & PCI_EXP_SLTCAP_PCP) {
+ power = (sltctl & PCI_EXP_SLTCTL_PCC) == PCI_EXP_SLTCTL_PWR_ON;
+ }
+
+ pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+ pcie_set_power_device, &power);
+}
+
/*
* A PCI Express Hot-Plug Event has occurred, so update slot status register
* and notify OS of the event if necessary.
pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA,
PCI_EXP_LNKSTA_DLLLA);
}
+ pcie_cap_update_power(hotplug_pdev);
return;
}
}
pcie_cap_slot_event(hotplug_pdev,
PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP);
+ pcie_cap_update_power(hotplug_pdev);
}
}
PCI_EXP_SLTSTA_PDC |
PCI_EXP_SLTSTA_ABP);
+ pcie_cap_update_power(dev);
hotplug_event_update_event_status(dev);
}
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_PDC);
}
+ pcie_cap_update_power(dev);
hotplug_event_notify(dev);
{
PCIDevice *dev = opaque;
hotplug_event_update_event_status(dev);
+ pcie_cap_update_power(dev);
return 0;
}