PCI: add set_powerstate and get_powerstate hooks

Change-Id: I8e32b5fccba3461cdb1b0c6e81b15705b2be1c57
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2447
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
Jérôme Duval 2020-03-21 20:11:29 +01:00
parent f62c154804
commit c4f5ebc3df
4 changed files with 53 additions and 1 deletions

View File

@ -36,6 +36,8 @@ typedef struct pci_device_module_info {
void (*get_pci_info)(pci_device *device, struct pci_info *info);
status_t (*find_pci_extended_capability)(pci_device *device, uint16 capID,
uint16 *offset);
uint8 (*get_powerstate)(pci_device *device);
void (*set_powerstate)(pci_device *device, uint8 state);
} pci_device_module_info;

View File

@ -1801,3 +1801,34 @@ PCI::UpdateInterruptLine(uint8 domain, uint8 bus, uint8 _device, uint8 function,
return WriteConfig(device, PCI_interrupt_line, 1, newInterruptLineValue);
}
uint8
PCI::GetPowerstate(PCIDev *device)
{
uint8 capabilityOffset;
status_t res = FindCapability(device, PCI_cap_id_pm, &capabilityOffset);
if (res == B_OK) {
uint32 state = ReadConfig(device, capabilityOffset + PCI_pm_status, 2);
return (state & PCI_pm_mask);
}
return PCI_pm_state_d0;
}
void
PCI::SetPowerstate(PCIDev *device, uint8 newState)
{
uint8 capabilityOffset;
status_t res = FindCapability(device, PCI_cap_id_pm, &capabilityOffset);
if (res == B_OK) {
uint32 state = ReadConfig(device, capabilityOffset + PCI_pm_status, 2);
if ((state & PCI_pm_mask) != newState) {
WriteConfig(device, capabilityOffset + PCI_pm_status, 2,
(state & ~PCI_pm_mask) | newState);
if ((state & PCI_pm_mask) == PCI_pm_state_d3)
snooze(10);
}
}
}

View File

@ -114,6 +114,9 @@ public:
void ClearDeviceStatus(PCIBus *bus, bool dumpStatus);
uint8 GetPowerstate(PCIDev *device);
void SetPowerstate(PCIDev *device, uint8 state);
void RefreshDeviceInfo();
status_t UpdateInterruptLine(uint8 domain, uint8 bus,

View File

@ -102,6 +102,20 @@ pci_device_find_extended_capability(pci_device* device, uint16 capID,
}
static uint8
pci_device_get_powerstate(pci_device *device)
{
return gPCI->GetPowerstate(device->device);
}
static void
pci_device_set_powerstate(pci_device *device, uint8 state)
{
return gPCI->SetPowerstate(device->device, state);
}
static void
pci_device_get_pci_info(pci_device* device, struct pci_info* info)
{
@ -196,5 +210,7 @@ pci_device_module_info gPCIDeviceModule = {
pci_device_write_pci_config,
pci_device_find_capability,
pci_device_get_pci_info,
pci_device_find_extended_capability
pci_device_find_extended_capability,
pci_device_get_powerstate,
pci_device_set_powerstate
};