mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-10 21:01:49 +00:00
platform_drv: add support to power PCI devices
- depending on available PCI power cap power off and on - save and restore PCI bars if required - reset PCI devices after power on if supported Fixes #3963
This commit is contained in:
parent
5f7fe7498f
commit
b185f3fac1
@ -40,10 +40,11 @@ class Nonpci::Ps2 : public Platform::Device_component
|
||||
Genode::Attached_io_mem_dataspace &pciconf,
|
||||
Platform::Session_component &session,
|
||||
Genode::Allocator &heap_for_irq,
|
||||
Platform::Pci::Config::Delayer &delayer)
|
||||
Platform::Pci::Config::Delayer &delayer,
|
||||
Platform::Device_bars_pool &devices_bars)
|
||||
:
|
||||
Platform::Device_component(env, pciconf, session, IRQ_KEYBOARD,
|
||||
heap_for_irq, delayer),
|
||||
heap_for_irq, delayer, devices_bars),
|
||||
_ep(env.ep().rpc_ep()),
|
||||
_irq_mouse(IRQ_MOUSE, ~0UL, env, heap_for_irq),
|
||||
_data(env, REG_DATA, ACCESS_WIDTH),
|
||||
@ -107,10 +108,11 @@ class Nonpci::Pit : public Platform::Device_component
|
||||
Genode::Attached_io_mem_dataspace &pciconf,
|
||||
Platform::Session_component &session,
|
||||
Genode::Allocator &heap_for_irq,
|
||||
Platform::Pci::Config::Delayer &delayer)
|
||||
Platform::Pci::Config::Delayer &delayer,
|
||||
Platform::Device_bars_pool &devices_bars)
|
||||
:
|
||||
Platform::Device_component(env, pciconf, session, IRQ_PIT,
|
||||
heap_for_irq, delayer),
|
||||
heap_for_irq, delayer, devices_bars),
|
||||
_ports(env, PIT_PORT, PORTS_WIDTH)
|
||||
{ }
|
||||
|
||||
@ -159,11 +161,13 @@ Platform::Device_capability Platform::Session_component::device(String const &na
|
||||
switch(devices_i) {
|
||||
case 0:
|
||||
dev = new (_md_alloc) Nonpci::Ps2(_env, _pciconf, *this,
|
||||
_global_heap, _delayer);
|
||||
_global_heap, _delayer,
|
||||
_devices_bars);
|
||||
break;
|
||||
case 1:
|
||||
dev = new (_md_alloc) Nonpci::Pit(_env, _pciconf, *this,
|
||||
_global_heap, _delayer);
|
||||
_global_heap, _delayer,
|
||||
_devices_bars);
|
||||
break;
|
||||
default:
|
||||
return Device_capability();
|
||||
|
@ -146,7 +146,7 @@ void Platform::Device_component::config_write(unsigned char address,
|
||||
catch (...) {
|
||||
Genode::error("assignment to device failed");
|
||||
}
|
||||
_enabled_bus_master = true;
|
||||
_device_used = true;
|
||||
}
|
||||
|
||||
_device_config.write(_config_access, address, value, size,
|
||||
|
@ -28,7 +28,12 @@
|
||||
#include "pci_device_config.h"
|
||||
#include "irq.h"
|
||||
|
||||
namespace Platform { class Device_component; class Session_component; }
|
||||
namespace Platform {
|
||||
class Device_component;
|
||||
class Session_component;
|
||||
|
||||
typedef Registry<Registered<Device_config::Device_bars> > Device_bars_pool;
|
||||
}
|
||||
|
||||
class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
private Genode::List<Device_component>::Element
|
||||
@ -45,13 +50,14 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
|
||||
Genode::Env &_env;
|
||||
Pci::Config::Delayer &_delayer;
|
||||
Device_bars_pool &_devices_bars;
|
||||
Device_config _device_config { };
|
||||
Genode::addr_t _config_space;
|
||||
Config_access _config_access;
|
||||
Platform::Session_component &_session;
|
||||
Irq_session_component *_irq_session = nullptr;
|
||||
unsigned short _irq_line;
|
||||
bool _enabled_bus_master { false };
|
||||
bool _device_used { false };
|
||||
|
||||
Genode::Allocator &_global_heap;
|
||||
|
||||
@ -89,6 +95,40 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
struct Enable : Bitfield<15, 1> { };
|
||||
};
|
||||
|
||||
struct Pci_express : Pci::Config
|
||||
{
|
||||
Pci_express(Device_component &dev, uint16_t cap)
|
||||
: Pci::Config(dev._config_access, dev._device_config.bdf(), cap) { }
|
||||
|
||||
struct Capabilities : Register<0x04, 32> {
|
||||
struct Reset : Bitfield< 28, 1> { }; };
|
||||
struct Control: Register<0x08, 16> {
|
||||
struct Reset : Bitfield< 15, 1> { }; };
|
||||
struct Status: Register<0x0a, 16> {
|
||||
struct Pending : Bitfield< 5, 1> { }; };
|
||||
struct Capabilities2 : Register<0x24, 32> {
|
||||
struct Readiness : Bitfield<31, 1> { }; };
|
||||
struct Status2 : Register<0x32, 16> {
|
||||
struct Readiness_status : Bitfield<15, 1> { }; };
|
||||
};
|
||||
|
||||
struct Pci_power: Pci::Config
|
||||
{
|
||||
Pci_power(Device_component &dev, uint16_t cap)
|
||||
: Pci::Config(dev._config_access, dev._device_config.bdf(), cap) { }
|
||||
|
||||
struct Capabilities : Register<0x02, 16>
|
||||
{
|
||||
struct Specific_init : Bitfield< 5, 1> { };
|
||||
};
|
||||
struct Control : Register<0x04, 16>
|
||||
{
|
||||
struct D0_3 : Bitfield< 0, 2> { };
|
||||
struct No_soft_reset : Bitfield< 3, 1> { };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Genode::Tslab<Genode::Io_port_connection, IO_BLOCK_SIZE> _slab_ioport;
|
||||
char _slab_ioport_block_data[IO_BLOCK_SIZE];
|
||||
|
||||
@ -105,7 +145,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
struct Status : Genode::Register<8> {
|
||||
struct Capabilities : Bitfield<4,1> { };
|
||||
|
||||
inline static access_t read(Genode::uint8_t t) { return t; };
|
||||
inline static access_t read(Genode::uint8_t t) { return t; }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -138,19 +178,32 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
/**
|
||||
* Read out msi capabilities of the device.
|
||||
*/
|
||||
Genode::uint16_t _msi_cap()
|
||||
uint16_t _msi_cap()
|
||||
{
|
||||
enum { CAP_MSI = 0x5 };
|
||||
return _lookup_cap(CAP_MSI);
|
||||
}
|
||||
|
||||
Genode::uint16_t _msix_cap()
|
||||
uint16_t _msix_cap()
|
||||
{
|
||||
enum { CAP_MSI_X = 0x11 };
|
||||
return _lookup_cap(CAP_MSI_X);
|
||||
}
|
||||
|
||||
Genode::uint16_t _lookup_cap(Genode::uint16_t const target_cap)
|
||||
uint16_t _power_cap()
|
||||
{
|
||||
enum { CAP_POWER = 0x1 };
|
||||
return _lookup_cap(CAP_POWER);
|
||||
}
|
||||
|
||||
/* PCI express cap (not PCI express extended cap!) */
|
||||
uint16_t _pcie_cap()
|
||||
{
|
||||
enum { CAP_PCIE = 0x10 };
|
||||
return _lookup_cap(CAP_PCIE);
|
||||
}
|
||||
|
||||
uint16_t _lookup_cap(uint16_t const target_cap)
|
||||
{
|
||||
enum { PCI_STATUS = 0x6, PCI_CAP_OFFSET = 0x34 };
|
||||
|
||||
@ -222,13 +275,14 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
/**
|
||||
* Disable bus master dma if already enabled.
|
||||
*/
|
||||
void _disable_bus_master_dma() {
|
||||
|
||||
void _disable_bus_master_dma()
|
||||
{
|
||||
/*
|
||||
* Disabling a bridge may make the devices behind non-functional,
|
||||
* as we have no driver which will switch it on again
|
||||
*/
|
||||
if (_device_config.pci_bridge())
|
||||
if (_device_config.pci_bridge() ||
|
||||
_device_config.bdf() == Pci::Bdf(Platform::Bridge::root_bridge_bdf))
|
||||
return;
|
||||
|
||||
_device_config.disable_bus_master_dma(_config_access);
|
||||
@ -278,7 +332,128 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
addr_t const msix_table = reinterpret_cast<addr_t>(mem_io.local_addr<void>()) + offset;
|
||||
|
||||
fn(msix_table);
|
||||
};
|
||||
}
|
||||
|
||||
void _device_reset()
|
||||
{
|
||||
uint16_t const cap = _pcie_cap();
|
||||
if (!cap)
|
||||
return;
|
||||
|
||||
Pci_express pci_cap(*this, cap);
|
||||
|
||||
if (!pci_cap.read<Pci_express::Capabilities::Reset>())
|
||||
return;
|
||||
|
||||
log(_device_config, " reset function");
|
||||
|
||||
pci_cap.write<Pci_express::Control::Reset>(1);
|
||||
|
||||
try {
|
||||
/* optional use FLR Time if available instead of heuristic */
|
||||
pci_cap.wait_for(Pci::Config::Attempts(100),
|
||||
Pci::Config::Microseconds(10000), _delayer,
|
||||
Pci_express::Status::Pending::Equal(0));
|
||||
} catch (Pci::Config::Polling_timeout) {
|
||||
warning(_device_config, " reset timeout raised");
|
||||
}
|
||||
}
|
||||
|
||||
void _power_off()
|
||||
{
|
||||
/* don't touch unused device */
|
||||
if (!_device_used)
|
||||
return;
|
||||
|
||||
uint16_t const cap = _power_cap();
|
||||
if (!cap) {
|
||||
_disable_bus_master_dma();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* PCI Power Management - 8.2.2 D3 State
|
||||
*
|
||||
* "If the device driver is not capable of fully reinitializing"
|
||||
* "a function, the operating system should not put the function"
|
||||
* "into D3"
|
||||
*
|
||||
* Actually, at this point we don't know about the capabilities of
|
||||
* the actual driver.
|
||||
*/
|
||||
log(_device_config, " power off");
|
||||
|
||||
/*
|
||||
* "When placing a function into D3, the operating system software"
|
||||
* "is required to disable I/O and memory space as well as bus"
|
||||
* "mastering via the PCI Command register.
|
||||
*/
|
||||
Device_config::Pci_header header (_config_access, _device_config.bdf());
|
||||
|
||||
auto command = header.read<Device_config::Pci_header::Command>();
|
||||
Device_config::Pci_header::Command::Dma::set(command, 0);
|
||||
Device_config::Pci_header::Command::Memory::set(command, 0);
|
||||
Device_config::Pci_header::Command::Ioport::set(command, 0);
|
||||
|
||||
header.write<Device_config::Pci_header::Command>(command);
|
||||
|
||||
/* power off */
|
||||
Pci_power pci_cap(*this, cap);
|
||||
pci_cap.write<Pci_power::Control::D0_3>(3);
|
||||
}
|
||||
|
||||
void _power_on()
|
||||
{
|
||||
uint16_t const cap = _power_cap();
|
||||
if (!cap)
|
||||
return;
|
||||
|
||||
Pci_power pci_cap(*this, cap);
|
||||
|
||||
if (pci_cap.read<Pci_power::Control::D0_3>() == 0)
|
||||
return;
|
||||
|
||||
/* since it was off before, it got used by powering it on */
|
||||
_device_used = true;
|
||||
|
||||
log(_device_config, " power on",
|
||||
pci_cap.read<Pci_power::Control::No_soft_reset>() ? ", no_soft_reset" : "",
|
||||
pci_cap.read<Pci_power::Capabilities::Specific_init>() ? ", specific_init_required" : "");
|
||||
|
||||
/* power on */
|
||||
pci_cap.write<Pci_power::Control::D0_3>(0);
|
||||
|
||||
/*
|
||||
* PCI Express 4.3 - 5.3.1.4. D3 State
|
||||
*
|
||||
* "Unless Readiness Notifications mechanisms are used ..."
|
||||
* "a minimum recovery time following a D3 hot → D0 transition of"
|
||||
* "at least 10 ms ..."
|
||||
*/
|
||||
_delayer.usleep(10'000);
|
||||
|
||||
/*
|
||||
* PCI Power Management - 3.2.4 - PMCSR Power Management Control/Status
|
||||
*
|
||||
* "no additional operating system intervention is required ..."
|
||||
* "beyond writing the PowerState"
|
||||
*/
|
||||
if (pci_cap.read<Pci_power::Control::No_soft_reset>())
|
||||
return;
|
||||
|
||||
_device_reset();
|
||||
|
||||
_devices_bars.for_each([&](auto const &bars) {
|
||||
if (!(bars.bdf == _device_config.bdf()))
|
||||
return;
|
||||
|
||||
_device_config.restore_bars(_config_access, bars);
|
||||
});
|
||||
|
||||
/* re-read the resources which set to valid ones after power on */
|
||||
_device_config = Device_config(_device_config.bdf(),
|
||||
&_config_access);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@ -291,10 +466,12 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
Platform::Session_component &session,
|
||||
Genode::Allocator &md_alloc,
|
||||
Genode::Allocator &global_heap,
|
||||
Pci::Config::Delayer &delayer)
|
||||
Pci::Config::Delayer &delayer,
|
||||
Device_bars_pool &devices_bars)
|
||||
:
|
||||
_env(env),
|
||||
_delayer(delayer),
|
||||
_devices_bars(devices_bars),
|
||||
_device_config(device_config), _config_space(addr),
|
||||
_config_access(config_access),
|
||||
_session(session),
|
||||
@ -307,6 +484,8 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
|
||||
_io_port_conn[i] = nullptr;
|
||||
}
|
||||
|
||||
_power_on();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -316,10 +495,12 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
Genode::Attached_io_mem_dataspace &pciconf,
|
||||
Platform::Session_component &session, unsigned irq,
|
||||
Genode::Allocator &global_heap,
|
||||
Pci::Config::Delayer &delayer)
|
||||
Pci::Config::Delayer &delayer,
|
||||
Device_bars_pool &devices_bars)
|
||||
:
|
||||
_env(env),
|
||||
_delayer(delayer),
|
||||
_devices_bars(devices_bars),
|
||||
_config_space(~0UL),
|
||||
_config_access(pciconf),
|
||||
_session(session),
|
||||
@ -353,8 +534,10 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
}
|
||||
}
|
||||
|
||||
if (_device_config.valid() && _enabled_bus_master)
|
||||
_disable_bus_master_dma();
|
||||
if (!_device_config.valid())
|
||||
return;
|
||||
|
||||
_power_off();
|
||||
}
|
||||
|
||||
/****************************************
|
||||
|
@ -142,6 +142,35 @@ namespace Platform {
|
||||
PCI_CMD_DMA = 0x4,
|
||||
};
|
||||
|
||||
struct Pci_header : Pci::Config
|
||||
{
|
||||
Pci_header(Config_access &access, Pci::Bdf const bdf)
|
||||
: Pci::Config(access, bdf, 0 /* from start */) { }
|
||||
|
||||
struct Command : Register<0x04, 16>
|
||||
{
|
||||
struct Ioport : Bitfield< 0, 1> { };
|
||||
struct Memory : Bitfield< 1, 1> { };
|
||||
struct Dma : Bitfield< 2, 1> { };
|
||||
};
|
||||
};
|
||||
|
||||
struct Device_bars {
|
||||
Pci::Bdf bdf;
|
||||
uint32_t bar_addr[Device::NUM_RESOURCES] { };
|
||||
|
||||
bool all_invalid() const {
|
||||
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
|
||||
if (bar_addr[i] != 0 && bar_addr[i] != ~0U)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Device_bars(Pci::Bdf bdf) : bdf(bdf) { }
|
||||
virtual ~Device_bars() { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@ -305,11 +334,41 @@ namespace Platform {
|
||||
|
||||
void disable_bus_master_dma(Config_access &pci_config)
|
||||
{
|
||||
unsigned const cmd = read(pci_config, PCI_CMD_REG,
|
||||
Platform::Device::ACCESS_16BIT);
|
||||
if (cmd & PCI_CMD_DMA)
|
||||
write(pci_config, PCI_CMD_REG, cmd ^ PCI_CMD_DMA,
|
||||
Platform::Device::ACCESS_16BIT);
|
||||
Pci_header header (pci_config, _bdf);
|
||||
|
||||
if (header.read<Pci_header::Command::Dma>())
|
||||
header.write<Pci_header::Command::Dma>(0);
|
||||
}
|
||||
|
||||
Device_bars save_bars()
|
||||
{
|
||||
Device_bars bars (_bdf);
|
||||
|
||||
for (unsigned r = 0; r < Device::NUM_RESOURCES; r++) {
|
||||
if (!_resource_id_is_valid(r))
|
||||
break;
|
||||
|
||||
bars.bar_addr[r] = _resource[r].base();
|
||||
}
|
||||
|
||||
return bars;
|
||||
};
|
||||
|
||||
void restore_bars(Config_access &config, Device_bars const &bars)
|
||||
{
|
||||
for (unsigned r = 0; r < Device::NUM_RESOURCES; r++) {
|
||||
if (!_resource_id_is_valid(r))
|
||||
break;
|
||||
|
||||
/* index of base-address register in configuration space */
|
||||
unsigned const bar_idx = 0x10 + 4 * r;
|
||||
|
||||
/* PCI protocol to write address after requesting size */
|
||||
config.write(_bdf, bar_idx, ~0U, Device::ACCESS_32BIT);
|
||||
config.read (_bdf, bar_idx, Device::ACCESS_32BIT);
|
||||
config.write(_bdf, bar_idx, bars.bar_addr[r],
|
||||
Device::ACCESS_32BIT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -136,7 +136,7 @@ class Platform::Pci_buses
|
||||
|
||||
Genode::Bit_array<Device_config::MAX_BUSES> _valid { };
|
||||
|
||||
void scan_bus(Config_access &config_access, Genode::Allocator &heap,
|
||||
void scan_bus(Config_access &, Genode::Allocator &, Device_bars_pool &,
|
||||
unsigned char bus = 0);
|
||||
|
||||
bool _bus_valid(int bus)
|
||||
@ -149,10 +149,12 @@ class Platform::Pci_buses
|
||||
|
||||
public:
|
||||
|
||||
Pci_buses(Genode::Allocator &heap, Genode::Attached_io_mem_dataspace &pciconf)
|
||||
Pci_buses(Genode::Allocator &heap,
|
||||
Genode::Attached_io_mem_dataspace &pciconf,
|
||||
Device_bars_pool &devices_bars)
|
||||
{
|
||||
Config_access c(pciconf);
|
||||
scan_bus(c, heap);
|
||||
scan_bus(c, heap, devices_bars);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,6 +219,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
Platform::Pci_buses &_pci_bus;
|
||||
Genode::Heap &_global_heap;
|
||||
Pci::Config::Delayer &_delayer;
|
||||
Device_bars_pool &_devices_bars;
|
||||
bool _iommu;
|
||||
|
||||
/**
|
||||
@ -480,6 +483,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
Platform::Pci_buses &buses,
|
||||
Genode::Heap &global_heap,
|
||||
Pci::Config::Delayer &delayer,
|
||||
Device_bars_pool &devices_bars,
|
||||
char const *args,
|
||||
bool const iommu)
|
||||
:
|
||||
@ -493,6 +497,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
_pci_bus(buses),
|
||||
_global_heap(global_heap),
|
||||
_delayer(delayer),
|
||||
_devices_bars(devices_bars),
|
||||
_iommu(iommu)
|
||||
{
|
||||
/* subtract the RPC session and session dataspace capabilities */
|
||||
@ -701,7 +706,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
*/
|
||||
Device_component * dev = new (_md_alloc)
|
||||
Device_component(_env, config, config_space, config_access,
|
||||
*this, _md_alloc, _global_heap, _delayer);
|
||||
*this, _md_alloc, _global_heap, _delayer,
|
||||
_devices_bars);
|
||||
|
||||
_device_list.insert(dev);
|
||||
|
||||
@ -827,6 +833,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
|
||||
Genode::Heap _heap { _env.ram(), _env.rm() };
|
||||
|
||||
Device_bars_pool _devices_bars { };
|
||||
Genode::Constructible<Platform::Pci_buses> _buses { };
|
||||
|
||||
bool _iommu { false };
|
||||
@ -988,7 +995,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
/* try surviving wrong ACPI ECAM/MMCONF table information */
|
||||
while (true) {
|
||||
try {
|
||||
_buses.construct(_heap, *_pci_confspace);
|
||||
_buses.construct(_heap, *_pci_confspace, _devices_bars);
|
||||
/* construction and scan succeeded */
|
||||
break;
|
||||
} catch (Platform::Config_access::Invalid_mmio_access) {
|
||||
@ -1024,7 +1031,8 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
try {
|
||||
return new (md_alloc())
|
||||
Session_component(_env, _config, *_pci_confspace, *_buses,
|
||||
_heap, _delayer, args, _iommu);
|
||||
_heap, _delayer, _devices_bars, args,
|
||||
_iommu);
|
||||
}
|
||||
catch (Genode::Session_policy::No_policy_defined) {
|
||||
Genode::error("Invalid session request, no matching policy for ",
|
||||
|
@ -39,7 +39,9 @@ unsigned short Platform::bridge_bdf(unsigned char bus)
|
||||
}
|
||||
|
||||
void Platform::Pci_buses::scan_bus(Config_access &config_access,
|
||||
Genode::Allocator &heap, unsigned char bus)
|
||||
Genode::Allocator &heap,
|
||||
Device_bars_pool &devices_bars,
|
||||
unsigned char bus)
|
||||
{
|
||||
for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
|
||||
for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
|
||||
@ -47,6 +49,13 @@ void Platform::Pci_buses::scan_bus(Config_access &config_access,
|
||||
/* read config space */
|
||||
Device_config config(Pci::Bdf(bus, dev, fun), &config_access);
|
||||
|
||||
/* remember Device BARs required after power off and/or reset */
|
||||
if (config.valid()) {
|
||||
Device_config::Device_bars bars = config.save_bars();
|
||||
if (!bars.all_invalid())
|
||||
new (heap) Registered<Device_config::Device_bars>(devices_bars, bars);
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch off PCI bus master DMA for some classes of devices,
|
||||
* which caused trouble.
|
||||
@ -112,7 +121,7 @@ void Platform::Pci_buses::scan_bus(Config_access &config_access,
|
||||
Hex(sec_bus, Hex::Prefix::OMIT_PREFIX, Hex::Pad::PAD),
|
||||
":00.0", !enabled ? " enabled" : "");
|
||||
|
||||
scan_bus(config_access, heap, sec_bus);
|
||||
scan_bus(config_access, heap, devices_bars, sec_bus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
CAP_PWRM = 0x01,
|
||||
CAP_MSI = 0x05,
|
||||
CAP_HT = 0x08,
|
||||
CAP_SECDEV = 0x0f,
|
||||
@ -189,6 +190,7 @@ static void print_device_info(Platform::Device_capability device_cap)
|
||||
case CAP_MSIX: cap_string = String<128>(cap_string, " MSI-X"); break;
|
||||
case CAP_PCI_E: cap_string = String<128>(cap_string, " PCI-E"); break;
|
||||
case CAP_SECDEV: cap_string = String<128>(cap_string, " SECURE-DEVICE"); break;
|
||||
case CAP_PWRM: cap_string = String<128>(cap_string, " PWRM"); break;
|
||||
default:
|
||||
cap_string = String<128>(cap_string, " ", Hex(type));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user