diff --git a/headers/os/drivers/PCI.h b/headers/os/drivers/PCI.h index 569e43cec5..a692dd8c47 100644 --- a/headers/os/drivers/PCI.h +++ b/headers/os/drivers/PCI.h @@ -182,6 +182,9 @@ struct pci_module_info { uint16 cap_id, uint16 *offset ); + + status_t (*get_powerstate)(uint8 bus, uint8 device, uint8 function, uint8* state); + status_t (*set_powerstate)(uint8 bus, uint8 device, uint8 function, uint8 newState); }; #define B_PCI_MODULE_NAME "bus_managers/pci/v1" diff --git a/src/add-ons/kernel/bus_managers/pci/pci.cpp b/src/add-ons/kernel/bus_managers/pci/pci.cpp index 5f5a49cb60..4789674c2b 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci.cpp @@ -300,6 +300,30 @@ pci_update_interrupt_line(uchar virtualBus, uchar device, uchar function, } +status_t +pci_get_powerstate(uchar virtualBus, uint8 device, uint8 function, uint8* state) +{ + uint8 bus; + uint8 domain; + if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) + return B_ERROR; + + return gPCI->GetPowerstate(domain, bus, device, function, state); +} + + +status_t +pci_set_powerstate(uchar virtualBus, uint8 device, uint8 function, uint8 newState) +{ + uint8 bus; + uint8 domain; + if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) + return B_ERROR; + + return gPCI->SetPowerstate(domain, bus, device, function, newState); +} + + // used by pci_info.cpp print_info_basic() void __pci_resolve_virtual_bus(uint8 virtualBus, uint8 *domain, uint8 *bus) @@ -1838,3 +1862,29 @@ PCI::SetPowerstate(PCIDev *device, uint8 newState) } } + +status_t +PCI::GetPowerstate(uint8 domain, uint8 bus, uint8 _device, uint8 function, + uint8* state) +{ + PCIDev *device = FindDevice(domain, bus, _device, function); + if (device == NULL) + return B_ERROR; + + *state = GetPowerstate(device); + return B_OK; +} + + +status_t +PCI::SetPowerstate(uint8 domain, uint8 bus, uint8 _device, uint8 function, + uint8 newState) +{ + PCIDev *device = FindDevice(domain, bus, _device, function); + if (device == NULL) + return B_ERROR; + + SetPowerstate(device, newState); + return B_OK; +} + diff --git a/src/add-ons/kernel/bus_managers/pci/pci.h b/src/add-ons/kernel/bus_managers/pci/pci.h index f3a7f9370c..f099fc1ec3 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.h +++ b/src/add-ons/kernel/bus_managers/pci/pci.h @@ -115,7 +115,11 @@ public: void ClearDeviceStatus(PCIBus *bus, bool dumpStatus); uint8 GetPowerstate(PCIDev *device); + status_t GetPowerstate(uint8 domain, uint8 bus, uint8 device, + uint8 function, uint8* state); void SetPowerstate(PCIDev *device, uint8 state); + status_t SetPowerstate(uint8 domain, uint8 bus, uint8 device, + uint8 function, uint8 newState); void RefreshDeviceInfo(); diff --git a/src/add-ons/kernel/bus_managers/pci/pci_module.cpp b/src/add-ons/kernel/bus_managers/pci/pci_module.cpp index afdb4f2e80..585aace2f6 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_module.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci_module.cpp @@ -68,7 +68,9 @@ static struct pci_module_info sOldPCIModule = { &pci_reserve_device, &pci_unreserve_device, &pci_update_interrupt_line, - &pci_find_extended_capability + &pci_find_extended_capability, + &pci_get_powerstate, + &pci_set_powerstate }; module_dependency module_dependencies[] = { diff --git a/src/add-ons/kernel/bus_managers/pci/pci_private.h b/src/add-ons/kernel/bus_managers/pci/pci_private.h index 0787b40c6d..3538227990 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_private.h +++ b/src/add-ons/kernel/bus_managers/pci/pci_private.h @@ -60,6 +60,10 @@ status_t pci_unreserve_device(uchar virtualBus, uchar device, uchar function, status_t pci_update_interrupt_line(uchar virtualBus, uchar device, uchar function, uchar newInterruptLineValue); +status_t pci_get_powerstate(uchar virtualBus, uint8 device, + uint8 function, uint8* state); +status_t pci_set_powerstate(uchar virtualBus, uint8 device, + uint8 function, uint8 newState); status_t pci_io_init(void); uint8 pci_read_io_8(int mapped_io_addr);