diff --git a/repos/os/src/driver/platform/pci.cc b/repos/os/src/driver/platform/pci.cc index 7db4216b18..0c6627e875 100644 --- a/repos/os/src/driver/platform/pci.cc +++ b/repos/os/src/driver/platform/pci.cc @@ -91,6 +91,14 @@ struct Config_helper Config::Command::Io_space_enable::set(cmd, 1); }); + /* enable i/o space for bridges when I/O base/limit are defined */ + if (_config.bridge() && (_cfg.io_base_limit || _cfg.io_base_limit_upper)) + Config::Command::Io_space_enable::set(cmd, 1); + + /* enable memory space for bridges when I/O mem limit is defined */ + if (_config.bridge() && _cfg.memory_limit) + Config::Command::Memory_space_enable::set(cmd, 1); + _config.write(cmd); } @@ -296,3 +304,39 @@ void Driver::pci_device_specific_info(Device const & dev, Driver::pci_virtio_info(dev, cfg, env, xml); }); } + + +void Driver::pci_resume_bridges(Env & env, Device_model & devices) +{ + devices.for_each([&](Device & device) { + device.for_pci_config([&](Device::Pci_config const & pc) { + + if (!pc.bridge) + return; + + try { + Config_helper config(env, device, pc); + Config_type1 bridge(config._config.range()); + + using C1 = Config_type1; + + bridge.write(pc.io_base_limit); + bridge.write (pc.memory_base); + bridge.write (pc.memory_limit); + + bridge.write (pc.prefetch_memory_base); + bridge.write (pc.prefetch_memory_base_upper); + bridge.write(pc.prefetch_memory_limit_upper); + bridge.write (pc.io_base_limit_upper); + bridge.write (pc.expansion_rom_base); + bridge.write (pc.bridge_control); + + config.enable(); + + } catch (Genode::Service_denied) { + Bdf bdf(pc.bus_num, pc.dev_num, pc.func_num); + error("resuming bridge ", bdf, " failed"); + } + }); + }); +} diff --git a/repos/os/src/driver/platform/pci.h b/repos/os/src/driver/platform/pci.h index b4395a8856..ccfff604df 100644 --- a/repos/os/src/driver/platform/pci.h +++ b/repos/os/src/driver/platform/pci.h @@ -41,6 +41,7 @@ namespace Driver { Env & env, Device_model & model, Xml_generator & xml); + void pci_resume_bridges(Env &, Device_model &); } #endif /* _SRC__DRIVERS__PLATFORM__PCI_H_ */ diff --git a/repos/pc/src/driver/platform/pc/spec/x86_64/main.cc b/repos/pc/src/driver/platform/pc/spec/x86_64/main.cc index 0b347bd660..7ca7e1afe1 100644 --- a/repos/pc/src/driver/platform/pc/spec/x86_64/main.cc +++ b/repos/pc/src/driver/platform/pc/spec/x86_64/main.cc @@ -14,6 +14,7 @@ #include #include +#include #include namespace Driver { struct Main; }; @@ -111,6 +112,9 @@ void Driver::Main::_system_update() _common.io_mmu_devices().for_each([&] (Driver::Io_mmu & io_mmu) { io_mmu.resume(); }); + + Driver::pci_resume_bridges(_env, _common.devices()); + /* report independent of result */ _common.report_resume(); }