legacy_platform_drv: ACPI devices in configuration

Known ACPI device resources can be statically configured on startup like
follows.

  <config>
    <policy label_prefix="driver">
      <device name="ACPI0000"/>
    </policy>
    <device name="ACPI0000" typee="acpi">
      <irq number="99" mode="level" polarity="low"/>
      <io_mem        address="0xfc000000" size="0x100000"/>
      <io_port_range address="0x4000"     size="4"/>
    </device>
  </config>

Fixes #4545
This commit is contained in:
Christian Helmuth 2022-05-20 18:08:05 +02:00
parent c5bdc1ccbe
commit 393766a931
13 changed files with 584 additions and 65 deletions

View File

@ -1,6 +1,7 @@
/*
* \brief PCI-device interface
* \author Norman Feske
* \author Christian Helmuth
* \date 2008-01-28
*/
@ -80,10 +81,10 @@ struct Platform::Device : Platform::Abstract_device
{
/*
* Mask out the resource-description bits of the base
* address register. I/O resources use the lowest 3
* address register. I/O resources use the lowest 2
* bits, memory resources use the lowest 4 bits.
*/
return _bar & ((type() == IO) ? ~7 : ~15);
return _bar & ((type() == IO) ? ~3 : ~15);
}
/**

View File

@ -182,3 +182,26 @@ The driver provides for the PS2 and PIT device the IO_PORT and IRQ resources.
! </policy>
! </config>
!</start>
Also, known ACPI device resources can be statically configured on
startup like follows.
!<config>
! <policy label_prefix="driver">
! <device name="INT34C5"/>
! <device name="ACPI0000"/>
! </policy>
!
! <device hid="INT34C5" type="acpi">
! <irq number="14" mode="level" polarity="low"/>
! <io_mem address="0xfd690000" size="0x1000"/>
! <io_mem address="0xfd6a0000" size="0x1000"/>
! <io_mem address="0xfd6d0000" size="0x1000"/>
! <io_mem address="0xfd6e0000" size="0x1000"/>
! </device>
! <device name="ACPI0000" type="acpi">
! <irq number="99"/>
! <io_mem address="0xfc000000" size="0x100000"/>
! <io_port_range address="0x4000" size="4"/>
! </device>
!</config>

View File

@ -0,0 +1,207 @@
/*
* \brief ACPI device information from config
* \author Christian Helmuth
* \date 2022-05-16
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include "acpi_devices.h"
namespace Platform { namespace Acpi {
struct Device_impl;
typedef String<16> Str;
}}
void Platform::Acpi::Device::Resource::print(Output &o) const
{
using Genode::print;
switch (type) {
case Type::IRQ:
print(o, "IRQ [", base);
print(o, " ", irq == Irq::EDGE ? "edge" : irq == Irq::LEVEL_LOW ? "level-low" : "level-high");
print(o, "]");
break;
case Type::IOMEM:
print(o, "IOMEM ");
print(o, "[", Hex(base, Hex::Prefix::OMIT_PREFIX, Hex::PAD));
print(o, "-", Hex(base + (size - 1), Hex::Prefix::OMIT_PREFIX, Hex::PAD));
print(o, "]");
break;
case Type::IOPORT:
print(o, "IOPORT ");
print(o, "[", Hex((unsigned short)base, Hex::Prefix::OMIT_PREFIX, Hex::PAD));
print(o, "-", Hex((unsigned short)(base + (size - 1)), Hex::Prefix::OMIT_PREFIX, Hex::PAD));
print(o, "]");
break;
}
}
class Platform::Acpi::Device_impl : private Registry<Device>::Element,
public Platform::Acpi::Device
{
private:
Hid _hid; /* ACPI Spec 6.1.5 Hardware ID */
struct Resource_element : Registry<Resource_element>::Element
{
unsigned id;
Resource res;
Resource_element(Registry<Resource_element> &registry,
unsigned id,
Resource res)
:
Registry<Resource_element>::Element(registry, *this),
id(id), res(res)
{ }
};
Registry<Resource_element> _resource_registry { };
Resource_result _lookup_resource(Resource::Type type, unsigned const id) const
{
Resource const *res = nullptr;
_resource_registry.for_each([&] (Resource_element const &e) {
if (e.res.type == type && e.id == id)
res = &e.res;
});
if (res)
return *res;
else
return Invalid_resource { };
}
unsigned _max_irq_id { 0 };
unsigned _max_iomem_id { 0 };
unsigned _max_ioport_id { 0 };
public:
Device_impl(Registry<Device> &registry,
Allocator &heap, Xml_node config)
:
Registry<Device>::Element(registry, *this),
_hid(config.attribute_value("name", Hid("ACPI0000")))
{
config.for_each_sub_node("irq", [&] (Xml_node node) {
auto irq = [&] (Str const &mode, Str const &polarity) {
if (mode == "level") {
if (polarity == "high")
return Resource::Irq::LEVEL_HIGH;
else
return Resource::Irq::LEVEL_LOW;
} else {
return Resource::Irq::EDGE;
}
};
new (heap)
Resource_element {
_resource_registry,
_max_irq_id++,
Resource {
.type = Resource::Type::IRQ,
.base = node.attribute_value("number", addr_t(0)),
.irq = irq(node.attribute_value("mode", Str("unchanged")),
node.attribute_value("polarity", Str("unchanged"))) } };
});
config.for_each_sub_node("io_mem", [&] (Xml_node node) {
new (heap)
Resource_element {
_resource_registry,
_max_iomem_id++,
Resource {
.type = Resource::Type::IOMEM,
.base = node.attribute_value("address", addr_t(0)),
.size = node.attribute_value("size", size_t(0)) } };
});
config.for_each_sub_node("io_port_range", [&] (Xml_node node) {
new (heap)
Resource_element {
_resource_registry,
_max_ioport_id++,
Resource {
.type = Resource::Type::IOPORT,
.base = node.attribute_value("address", addr_t(0)),
.size = node.attribute_value("size", size_t(0)) } };
});
}
~Device_impl() { error("unexpected call of ", __func__); }
/* Platform::Acpi::Device interface */
Hid hid() const override { return _hid; }
Resource_result resource(unsigned idx) const override
{
/*
* Index of all IOMEM and IOPORT resources - no IRQ!
*
* first _max_iomem_id IOMEM, then _max_ioport_id IOPORT
*/
if (idx < _max_iomem_id)
return iomem(idx);
else if (idx < _max_iomem_id + _max_ioport_id)
return ioport(idx - _max_iomem_id);
else
return Invalid_resource { };
}
Resource_result irq(unsigned id) const override
{
return _lookup_resource(Resource::Type::IRQ, id);
}
Resource_result iomem(unsigned id) const override
{
return _lookup_resource(Resource::Type::IOMEM, id);
}
Resource_result ioport(unsigned id) const override
{
return _lookup_resource(Resource::Type::IOPORT, id);
}
};
Platform::Acpi::Device_registry::Lookup_result
Platform::Acpi::Device_registry::lookup(Platform::Acpi::Device::Hid hid) const
{
Device const *found = nullptr;
this->for_each([&] (Device const &device) {
if (device.hid() == hid)
found = &device;
});
if (found)
return found;
else
return Lookup_failed { };
}
void Platform::Acpi::Device_registry::init_devices(Allocator &heap, Xml_node config)
{
/* init only once */
if (_initialized)
return;
config.for_each_sub_node("device", [&] (Xml_node node) {
if (node.attribute_value("type", Str()) == "acpi")
new (heap) Device_impl(*this, heap, node);
});
_initialized = true;
}

View File

@ -0,0 +1,71 @@
/*
* \brief ACPI device information from config
* \author Christian Helmuth
* \date 2022-05-16
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/allocator.h>
#include <base/registry.h>
#include <util/xml_node.h>
#include <util/attempt.h>
namespace Platform { namespace Acpi {
using namespace Genode;
class Device;
class Device_registry;
} }
struct Platform::Acpi::Device : Interface
{
typedef String<10> Hid; /* ACPI Spec 6.1.5 Hardware ID */
struct Resource
{
enum class Type { IRQ, IOMEM, IOPORT };
enum class Irq { EDGE, LEVEL_LOW, LEVEL_HIGH };
Type type;
addr_t base;
union {
size_t size;
Irq irq;
};
void print(Output &o) const;
};
enum struct Invalid_resource { };
typedef Attempt<Resource, Invalid_resource> Resource_result;
virtual Hid hid() const = 0;
virtual Resource_result resource(unsigned idx) const = 0;
virtual Resource_result irq(unsigned id) const = 0;
virtual Resource_result iomem(unsigned id) const = 0;
virtual Resource_result ioport(unsigned id) const = 0;
};
struct Platform::Acpi::Device_registry : Genode::Registry<Device>
{
bool _initialized { false };
void init_devices(Allocator &heap, Xml_node config);
enum struct Lookup_failed { };
typedef Attempt<Device const *, Lookup_failed> Lookup_result;
Lookup_result lookup(Device::Hid name) const;
};

View File

@ -167,7 +167,7 @@ class Platform::Irq_component : public Platform::Irq_proxy
void Platform::Irq_session_component::ack_irq()
{
if (msi()) {
_irq_conn->ack_irq();
_msi_conn->ack_irq();
return;
}
@ -186,7 +186,9 @@ void Platform::Irq_session_component::ack_irq()
Platform::Irq_session_component::Irq_session_component(unsigned irq,
addr_t pci_config_space,
Env &env,
Allocator &heap)
Allocator &heap,
Irq_session::Trigger trigger,
Irq_session::Polarity polarity)
:
_gsi(irq)
{
@ -197,11 +199,11 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq,
try {
using namespace Genode;
_irq_conn.construct(env, msi, Irq_session::TRIGGER_UNCHANGED,
_msi_conn.construct(env, msi, Irq_session::TRIGGER_UNCHANGED,
Irq_session::POLARITY_UNCHANGED,
pci_config_space);
_msi_info = _irq_conn->info();
_msi_info = _msi_conn->info();
if (_msi_info.type == Irq_session::Info::Type::MSI) {
_gsi = msi;
return;
@ -216,9 +218,6 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq,
if (_gsi >= INVALID_IRQ)
return;
Irq_session::Trigger trigger;
Irq_session::Polarity polarity;
_gsi = Platform::Irq_override::irq_override(_gsi, trigger, polarity);
if (_gsi != irq || trigger != Irq_session::TRIGGER_UNCHANGED ||
polarity != POLARITY_UNCHANGED) {
@ -241,7 +240,7 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq,
Platform::Irq_session_component::~Irq_session_component()
{
if (msi()) {
_irq_conn->sigh(Signal_context_capability());
_msi_conn->sigh(Signal_context_capability());
irq_alloc.free_msi(_gsi);
return;
@ -258,9 +257,9 @@ Platform::Irq_session_component::~Irq_session_component()
void Platform::Irq_session_component::sigh(Signal_context_capability sigh)
{
if (_irq_conn.constructed()) {
if (_msi_conn.constructed()) {
/* register signal handler for msi directly at parent */
_irq_conn->sigh(sigh);
_msi_conn->sigh(sigh);
return;
}

View File

@ -42,18 +42,21 @@ class Platform::Irq_session_component : public Rpc_object<Irq_session>,
Platform::Irq_sigh _irq_sigh { };
Irq_session::Info _msi_info { };
Constructible<Irq_connection> _irq_conn { };
Constructible<Irq_connection> _msi_conn { };
public:
enum { INVALID_IRQ = 0xffU };
Irq_session_component(unsigned, addr_t, Env &, Allocator &heap);
Irq_session_component(unsigned, addr_t, Env &, Allocator &heap,
Trigger trigger = TRIGGER_UNCHANGED,
Polarity polarity = POLARITY_UNCHANGED);
~Irq_session_component();
bool msi()
{
return _irq_conn.constructed() &&
return _msi_conn.constructed() &&
_msi_info.type == Irq_session::Info::Type::MSI;
}
@ -136,9 +139,9 @@ class Platform::Irq_override : public List<Platform::Irq_override>::Element
Irq_session::Trigger trigger() const { return _trigger; }
Irq_session::Polarity polarity() const { return _polarity; }
static unsigned irq_override (unsigned irq,
Irq_session::Trigger &trigger,
Irq_session::Polarity &polarity)
static unsigned irq_override(unsigned irq,
Irq_session::Trigger &trigger,
Irq_session::Polarity &polarity)
{
for (Irq_override *i = list()->first(); i; i = i->next())
if (i->irq() == irq) {
@ -147,8 +150,7 @@ class Platform::Irq_override : public List<Platform::Irq_override>::Element
return i->gsi();
}
trigger = Irq_session::TRIGGER_UNCHANGED;
polarity = Irq_session::POLARITY_UNCHANGED;
/* trigger and polarity not touched in this case! */
return irq;
}
};

View File

@ -1,6 +1,7 @@
/*
* \brief Platform driver for x86
* \author Norman Feske
* \author Christian Helmuth
* \date 2008-01-28
*/
@ -20,17 +21,26 @@
#include "pci_session_component.h"
#include "pci_device_config.h"
#include "device_pd.h"
#include "acpi_devices.h"
namespace Platform { struct Main; };
namespace Platform {
struct Main;
namespace Nonpci { void acpi_device_registry(Acpi::Device_registry &); }
};
struct Platform::Main
{
Env &_env;
Heap _heap { _env.ram(), _env.rm() };
Acpi::Device_registry _acpi_device_registry { };
/*
* Use sliced heap to allocate each session component at a separate
* dataspace.
*/
Env &_env;
Sliced_heap sliced_heap { _env.ram(), _env.rm() };
Attached_rom_dataspace _config { _env, "config" };
@ -73,7 +83,7 @@ struct Platform::Main
});
} catch (...) { }
root.construct(_env, sliced_heap, _config,
root.construct(_env, _heap, sliced_heap, _config,
acpi_rom->local_addr<const char>(), acpi_platform,
msi_platform);
}
@ -143,6 +153,8 @@ struct Platform::Main
root->generate_pci_report();
root->config_update();
}
_acpi_device_registry.init_devices(_heap, _config.xml());
}
Main(Env &env) : _env(env)
@ -165,6 +177,8 @@ struct Platform::Main
config_update();
acpi_update();
system_update();
Nonpci::acpi_device_registry(_acpi_device_registry);
}
};

View File

@ -1,6 +1,7 @@
/*
* \brief Non PCI devices, e.g. PS2
* \author Alexander Boettcher
* \author Christian Helmuth
* \date 2015-04-17
*/
@ -13,6 +14,7 @@
#include "pci_session_component.h"
#include "irq.h"
#include "acpi_devices.h"
namespace Platform { namespace Nonpci { class Ps2; class Pit; } }
@ -85,7 +87,7 @@ class Platform::Nonpci::Ps2 : public Device_component
return Io_mem_session_capability();
}
String<5> name() const override { return "PS2"; }
Device_name_string name() const override { return "PS2"; }
};
@ -124,7 +126,166 @@ class Platform::Nonpci::Pit : public Device_component
return Io_port_session_capability();
}
String<5> name() const override { return "PIT"; }
Device_name_string name() const override { return "PIT"; }
};
namespace Platform { namespace Nonpci {
class Acpi;
void acpi_device_registry(Platform::Acpi::Device_registry &);
} }
static Platform::Acpi::Device_registry *_acpi_device_registry;
void Platform::Nonpci::acpi_device_registry(Platform::Acpi::Device_registry &registry)
{
_acpi_device_registry = &registry;
}
class Platform::Nonpci::Acpi : public Device_component
{
private:
Env &_env;
Allocator &_session_heap;
Platform::Acpi::Device const &_acpi_device;
Irq_session_component *_irq0 = nullptr;
/*
* Noncopyable
*/
Acpi(Acpi const &) = delete;
Acpi &operator = (Acpi const &) = delete;
public:
Acpi(Platform::Acpi::Device const &acpi_device,
Env &env,
Attached_io_mem_dataspace &pciconf,
Session_component &session,
Allocator &session_heap,
Allocator &global_heap,
Pci::Config::Delayer &delayer,
Device_bars_pool &devices_bars)
:
Device_component(env, pciconf, session, 0,
global_heap, delayer, devices_bars),
_env(env), _session_heap(session_heap), _acpi_device(acpi_device)
{ }
Device_name_string name() const override { return _acpi_device.hid(); }
/* Platform::Device interface */
void bus_address(unsigned char *bus, unsigned char *dev,
unsigned char *fn) override
{
*bus = 0; *dev = 0; *fn = 0;
}
unsigned short vendor_id() override { return ~0; }
unsigned short device_id() override { return ~0; }
unsigned class_code() override { return ~0; }
Resource resource(int resource_id) override
{
using Acpi_device = Platform::Acpi::Device;
return _acpi_device.resource(resource_id).convert<Resource>(
[&] (Acpi_device::Resource r) {
/* craft artificial BAR values from resource info */
switch (r.type) {
case Acpi_device::Resource::Type::IOMEM:
return Resource((r.base & 0xfffffff0) | 0b0000, r.size);
case Acpi_device::Resource::Type::IOPORT:
return Resource((r.base & 0xfffffffc) | 0b01, r.size);
case Acpi_device::Resource::Type::IRQ:
return Resource();
}
return Resource();
},
[&] (Acpi_device::Invalid_resource) { return Resource(); });
}
unsigned config_read(unsigned char, Access_size) override
{
warning("ignore config_read from ACPI device ", _acpi_device.hid());
return 0;
}
void config_write(unsigned char, unsigned, Access_size) override
{
warning("ignore config_write to ACPI device ", _acpi_device.hid());
}
Irq_session_capability irq(uint8_t v_id) override
{
using Acpi_device = Platform::Acpi::Device;
/* TODO more than one IRQ */
if (v_id != 0) {
warning("ACPI device with more than one IRQ not supported (requested id ", v_id, ")");
return Irq_session_capability();
}
if (_irq0) return _irq0->cap();
/* TODO needs try see pci_device.cc ::iomem() */
return _acpi_device.irq(v_id).convert<Irq_session_capability>(
[&] (Acpi_device::Resource r) {
Platform::Irq_session_component &irq =
*new(_session_heap)
Platform::Irq_session_component(r.base, ~0UL, _env, _session_heap,
Irq_session::TRIGGER_LEVEL,
Irq_session::POLARITY_LOW);
_env.ep().manage(irq);
_irq0 = &irq;
return irq.cap();
},
[&] (Acpi_device::Invalid_resource) { return Irq_session_capability(); });
}
Io_port_session_capability io_port(uint8_t v_id) override
{
using Acpi_device = Platform::Acpi::Device;
/* TODO needs try see pci_device.cc ::iomem() */
return _acpi_device.ioport(v_id).convert<Io_port_session_capability>(
[&] (Acpi_device::Resource r) {
Io_port_connection &ioport =
*new (_session_heap) Io_port_connection(_env, r.base, r.size);
return ioport.cap();
},
[&] (Acpi_device::Invalid_resource) { return Io_port_session_capability(); });
}
Io_mem_session_capability io_mem(uint8_t v_id,
Cache /* ignored */,
addr_t /* ignored */,
size_t /* ignored */) override
{
using Acpi_device = Platform::Acpi::Device;
/* TODO needs try see pci_device.cc ::iomem() */
return _acpi_device.iomem(v_id).convert<Io_mem_session_capability>(
[&] (Acpi_device::Resource r) {
Io_mem_connection &iomem =
*new (_session_heap) Io_mem_connection(_env, r.base, r.size);
return iomem.cap();
},
[&] (Acpi_device::Invalid_resource) { return Io_mem_session_capability(); });
}
};
@ -136,20 +297,34 @@ Platform::Device_capability Platform::Session_component::device(Device_name cons
if (!name.valid_string())
return Device_capability();
char const * device_name = name.string();
const char * devices [] = { "PS2", "PIT" };
unsigned devices_i = 0;
Device_name_string const device_name { name.string() };
for (; devices_i < sizeof(devices) / sizeof(devices[0]); devices_i++)
if (!strcmp(device_name, devices[devices_i]))
break;
enum class Type { UNKNOWN, PS2, PIT, ACPI } device_type { Type::UNKNOWN };
if (devices_i >= sizeof(devices) / sizeof(devices[0])) {
error("unknown '", device_name, " device name");
Platform::Acpi::Device const *acpi_device = nullptr;
if (device_name == "PS2")
device_type = Type::PS2;
else if (device_name == "PIT")
device_type = Type::PIT;
else if (_acpi_device_registry)
device_type = _acpi_device_registry->lookup(device_name).convert<Type>(
[&] (Acpi::Device const *device) {
acpi_device = device;
return Type::ACPI;
},
[&] (Acpi::Device_registry::Lookup_failed) { return Type::UNKNOWN; });
bool const found = device_type != Type::UNKNOWN;
if (!found) {
error("unknown device name '", device_name, "'");
return Device_capability();
}
if (!permit_device(devices[devices_i])) {
if (!permit_device(device_name.string())) {
error("denied access to device '", device_name, "' for "
"session '", _label, "'");
return Device_capability();
@ -158,17 +333,24 @@ Platform::Device_capability Platform::Session_component::device(Device_name cons
try {
Device_component * dev = nullptr;
switch(devices_i) {
case 0:
switch (device_type) {
case Type::PS2:
dev = new (_md_alloc) Nonpci::Ps2(_env, _pciconf, *this,
_global_heap, _delayer,
_devices_bars);
break;
case 1:
case Type::PIT:
dev = new (_md_alloc) Nonpci::Pit(_env, _pciconf, *this,
_global_heap, _delayer,
_devices_bars);
break;
case Type::ACPI:
dev = new (_md_alloc) Nonpci::Acpi(*acpi_device,
_env, _pciconf, *this,
_md_alloc,
_global_heap, _delayer,
_devices_bars);
break;
default:
return Device_capability();
}

View File

@ -1,6 +1,8 @@
/*
* \brief PCI device component implementation
* \author Alexander Boettcher
* \author Christian Helmuth
* \date 2022-06-24
*/
/*
@ -102,10 +104,24 @@ Genode::Io_mem_session_capability Platform::Device_component::io_mem(uint8_t con
return Io_mem_session_capability();
}
unsigned Platform::Device_component::config_read(unsigned char address, Access_size size)
{
if (pci_device())
return _device_config.read(_config_access, address, size,
_device_config.DONT_TRACK_ACCESS);
return ~0;
}
void Platform::Device_component::config_write(unsigned char address,
unsigned value,
Access_size size)
{
if (!pci_device())
return;
/* white list of ports which we permit to write */
switch (address) {
case 0x40 ... 0xff:
@ -164,7 +180,7 @@ Genode::Irq_session_capability Platform::Device_component::irq(uint8_t id)
if (_irq_session)
return _irq_session->cap();
if (!_device_config.valid()) {
if (!pci_device()) {
/* Non PCI devices */
_irq_session = construct_at<Irq_session_component>(_mem_irq_component,
_irq_line, ~0UL,

View File

@ -1,6 +1,7 @@
/*
* \brief platform device component
* \author Norman Feske
* \author Christian Helmuth
* \date 2008-01-28
*/
@ -33,6 +34,8 @@ namespace Platform {
class Device_component;
class Session_component;
typedef String<10> Device_name_string;
typedef Registry<Registered<Device_config::Device_bars> > Device_bars_pool;
}
@ -536,12 +539,15 @@ class Platform::Device_component : public Rpc_object<Platform::Device>,
}
}
if (!_device_config.valid())
if (!pci_device())
return;
_power_off();
}
/* distinct non-PCI and PCI devices */
bool pci_device() const { return _device_config.valid(); }
/****************************************
** Methods used solely by pci session **
****************************************/
@ -549,7 +555,7 @@ class Platform::Device_component : public Rpc_object<Platform::Device>,
Device_config device_config() const { return _device_config; }
addr_t config_space() const { return _config_space; }
virtual String<5> name() const { return "PCI"; }
virtual Device_name_string name() const { return "PCI"; }
template <typename FUNC>
void for_each_device(FUNC const &fn) const
@ -580,18 +586,14 @@ class Platform::Device_component : public Rpc_object<Platform::Device>,
Resource resource(int resource_id) override
{
if (pci_device())
return _device_config.resource(resource_id).api_resource();
/* return invalid resource if device is invalid */
if (!_device_config.valid())
return Resource(0, 0);
return _device_config.resource(resource_id).api_resource();
return Resource(0, 0);
}
unsigned config_read(unsigned char address, Access_size size) override
{
return _device_config.read(_config_access, address, size,
_device_config.DONT_TRACK_ACCESS);
}
unsigned config_read(unsigned char address, Access_size size) override;
void config_write(unsigned char address, unsigned value,
Access_size size) override;

View File

@ -1,6 +1,7 @@
/*
* \brief PCI device configuration
* \author Norman Feske
* \author Christian Helmuth
* \date 2008-01-29
*/
@ -292,12 +293,12 @@ namespace Platform {
/**
* Return true if device is a PCI bridge
*/
bool pci_bridge() { return _header_type == HEADER_PCI_TO_PCI; }
bool pci_bridge() const { return _header_type == HEADER_PCI_TO_PCI; }
/**
* Return true if device is valid
*/
bool valid() { return _vendor_id != INVALID_VENDOR; }
bool valid() const { return _vendor_id != INVALID_VENDOR; }
/**
* Return resource description by resource ID

View File

@ -1,6 +1,7 @@
/*
* \brief Platform session component
* \author Norman Feske
* \author Christian Helmuth
* \date 2008-01-28
*/
@ -218,7 +219,7 @@ class Platform::Session_component : public Rpc_object<Session>
Session_label const _label;
List<Device_component> _device_list { };
Platform::Pci_buses &_pci_bus;
Heap &_global_heap;
Allocator &_global_heap;
Pci::Config::Delayer &_delayer;
Device_bars_pool &_devices_bars;
bool const _iommu;
@ -349,8 +350,8 @@ class Platform::Session_component : public Rpc_object<Session>
try {
policy.for_each_sub_node("device", [&] (Xml_node dev) {
/* enforce restriction based on name name */
if (dev.attribute_value("name", String<10>()) == name)
/* enforce restriction based on name */
if (dev.attribute_value("name", Device_name_string()) == name)
/* found identical match - permit access */
throw true;
});
@ -424,8 +425,7 @@ class Platform::Session_component : public Rpc_object<Session>
_config.xml().for_each_sub_node("policy", [&] (Xml_node policy) {
policy.for_each_sub_node("device", [&] (Xml_node device) {
typedef String<10> Name;
if (device.attribute_value("name", Name()) == dev_name) {
if (device.attribute_value("name", Device_name_string()) == dev_name) {
if (once)
throw true;
@ -474,7 +474,7 @@ class Platform::Session_component : public Rpc_object<Session>
Attached_io_mem_dataspace &pciconf,
addr_t pciconf_base,
Platform::Pci_buses &buses,
Heap &global_heap,
Allocator &global_heap,
Pci::Config::Delayer &delayer,
Device_bars_pool &devices_bars,
char const *args,
@ -521,8 +521,8 @@ class Platform::Session_component : public Rpc_object<Session>
throw Service_denied();
}
typedef String<16> Name;
Name const name = device_node.attribute_value("name", Name());
Device_name_string const name =
device_node.attribute_value("name", Device_name_string());
enum { DOUBLET = false };
if (find_dev_in_policy(name.string(), DOUBLET)) {
@ -610,7 +610,7 @@ class Platform::Session_component : public Rpc_object<Session>
_device_list.first()->for_each_device([&](auto const &dev) {
/* Non PCI devices */
if (!dev.device_config().valid()) {
if (!dev.pci_device()) {
if (!permit_device(dev.name().string()))
result = false;
@ -777,7 +777,7 @@ class Platform::Session_component : public Rpc_object<Session>
if (!device)
return;
if (device->device_config().valid()) {
if (device->pci_device()) {
if (bdf_in_use.get(device->device_config().bdf().value(), 1))
bdf_in_use.clear(device->device_config().bdf().value(), 1);
}
@ -877,6 +877,7 @@ class Platform::Session_component : public Rpc_object<Session>
return _env.pd().dma_addr(ram_cap);
}
/* non-PCI devices */
Device_capability device(Device_name const &name) override;
};
@ -886,14 +887,13 @@ class Platform::Root : public Root_component<Session_component>
private:
Env &_env;
Allocator &_heap;
Attached_rom_dataspace &_config;
Constructible<Attached_io_mem_dataspace> _pci_confspace { };
addr_t _pci_confspace_base = 0;
Constructible<Expanding_reporter> _pci_reporter { };
Heap _heap { _env.ram(), _env.rm() };
Device_bars_pool _devices_bars { };
Constructible<Platform::Pci_buses> _buses { };
@ -1123,11 +1123,12 @@ class Platform::Root : public Root_component<Session_component>
* \param md_alloc meta-data allocator for allocating PCI-session
* components and PCI-device components
*/
Root(Env &env, Allocator &md_alloc, Attached_rom_dataspace &config,
Root(Env &env, Allocator &heap, Allocator &md_alloc, Attached_rom_dataspace &config,
char const *acpi_rom, bool acpi_platform, bool msi_platform)
:
Root_component<Session_component>(&env.ep().rpc_ep(), &md_alloc),
_env(env),
_heap(heap),
_config(config),
_msi_platform(msi_platform)
{

View File

@ -1,7 +1,7 @@
TARGET = legacy_pc_platform_drv
REQUIRES = x86
SRC_CC = main.cc irq.cc pci_device.cc nonpci_devices.cc session.cc
SRC_CC += device_pd.cc
SRC_CC += device_pd.cc acpi_devices.cc
LIBS = base
INC_DIR = $(PRG_DIR)