diff --git a/repos/os/include/legacy/x86/platform_device/platform_device.h b/repos/os/include/legacy/x86/platform_device/platform_device.h index 7fbedef03a..e628a5d689 100644 --- a/repos/os/include/legacy/x86/platform_device/platform_device.h +++ b/repos/os/include/legacy/x86/platform_device/platform_device.h @@ -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); } /** diff --git a/repos/os/src/drivers/platform/legacy/x86/README b/repos/os/src/drivers/platform/legacy/x86/README index ff2c4837af..6391dc0346 100644 --- a/repos/os/src/drivers/platform/legacy/x86/README +++ b/repos/os/src/drivers/platform/legacy/x86/README @@ -182,3 +182,26 @@ The driver provides for the PS2 and PIT device the IO_PORT and IRQ resources. ! ! ! + +Also, known ACPI device resources can be statically configured on +startup like follows. + +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! diff --git a/repos/os/src/drivers/platform/legacy/x86/acpi_devices.cc b/repos/os/src/drivers/platform/legacy/x86/acpi_devices.cc new file mode 100644 index 0000000000..ae1cf74d85 --- /dev/null +++ b/repos/os/src/drivers/platform/legacy/x86/acpi_devices.cc @@ -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::Element, + public Platform::Acpi::Device +{ + private: + + Hid _hid; /* ACPI Spec 6.1.5 Hardware ID */ + + struct Resource_element : Registry::Element + { + unsigned id; + Resource res; + + Resource_element(Registry ®istry, + unsigned id, + Resource res) + : + Registry::Element(registry, *this), + id(id), res(res) + { } + }; + + Registry _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 ®istry, + Allocator &heap, Xml_node config) + : + Registry::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; +} diff --git a/repos/os/src/drivers/platform/legacy/x86/acpi_devices.h b/repos/os/src/drivers/platform/legacy/x86/acpi_devices.h new file mode 100644 index 0000000000..89e7aa98e3 --- /dev/null +++ b/repos/os/src/drivers/platform/legacy/x86/acpi_devices.h @@ -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 +#include +#include +#include + + +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_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 +{ + bool _initialized { false }; + + void init_devices(Allocator &heap, Xml_node config); + + enum struct Lookup_failed { }; + typedef Attempt Lookup_result; + + Lookup_result lookup(Device::Hid name) const; +}; diff --git a/repos/os/src/drivers/platform/legacy/x86/irq.cc b/repos/os/src/drivers/platform/legacy/x86/irq.cc index 4de20bb2d0..609142475d 100644 --- a/repos/os/src/drivers/platform/legacy/x86/irq.cc +++ b/repos/os/src/drivers/platform/legacy/x86/irq.cc @@ -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; } diff --git a/repos/os/src/drivers/platform/legacy/x86/irq.h b/repos/os/src/drivers/platform/legacy/x86/irq.h index 1a64e3b51b..55c2402a96 100644 --- a/repos/os/src/drivers/platform/legacy/x86/irq.h +++ b/repos/os/src/drivers/platform/legacy/x86/irq.h @@ -42,18 +42,21 @@ class Platform::Irq_session_component : public Rpc_object, Platform::Irq_sigh _irq_sigh { }; Irq_session::Info _msi_info { }; - Constructible _irq_conn { }; + Constructible _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::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::Element return i->gsi(); } - trigger = Irq_session::TRIGGER_UNCHANGED; - polarity = Irq_session::POLARITY_UNCHANGED; + /* trigger and polarity not touched in this case! */ return irq; } }; diff --git a/repos/os/src/drivers/platform/legacy/x86/main.cc b/repos/os/src/drivers/platform/legacy/x86/main.cc index 5043e754d7..3c01f8c286 100644 --- a/repos/os/src/drivers/platform/legacy/x86/main.cc +++ b/repos/os/src/drivers/platform/legacy/x86/main.cc @@ -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(), 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); } }; diff --git a/repos/os/src/drivers/platform/legacy/x86/nonpci_devices.cc b/repos/os/src/drivers/platform/legacy/x86/nonpci_devices.cc index 69e8f3fd60..550883b19b 100644 --- a/repos/os/src/drivers/platform/legacy/x86/nonpci_devices.cc +++ b/repos/os/src/drivers/platform/legacy/x86/nonpci_devices.cc @@ -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 ®istry) +{ + _acpi_device_registry = ®istry; +} + + +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( + [&] (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( + [&] (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( + [&] (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( + [&] (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( + [&] (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(); } diff --git a/repos/os/src/drivers/platform/legacy/x86/pci_device.cc b/repos/os/src/drivers/platform/legacy/x86/pci_device.cc index ea4acb6a6a..30aa26399b 100644 --- a/repos/os/src/drivers/platform/legacy/x86/pci_device.cc +++ b/repos/os/src/drivers/platform/legacy/x86/pci_device.cc @@ -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(_mem_irq_component, _irq_line, ~0UL, diff --git a/repos/os/src/drivers/platform/legacy/x86/pci_device_component.h b/repos/os/src/drivers/platform/legacy/x86/pci_device_component.h index b8e68de77e..db3d92da36 100644 --- a/repos/os/src/drivers/platform/legacy/x86/pci_device_component.h +++ b/repos/os/src/drivers/platform/legacy/x86/pci_device_component.h @@ -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 > Device_bars_pool; } @@ -536,12 +539,15 @@ class Platform::Device_component : public Rpc_object, } } - 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, 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 void for_each_device(FUNC const &fn) const @@ -580,18 +586,14 @@ class Platform::Device_component : public Rpc_object, 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; diff --git a/repos/os/src/drivers/platform/legacy/x86/pci_device_config.h b/repos/os/src/drivers/platform/legacy/x86/pci_device_config.h index 8610f17321..0478bc988b 100644 --- a/repos/os/src/drivers/platform/legacy/x86/pci_device_config.h +++ b/repos/os/src/drivers/platform/legacy/x86/pci_device_config.h @@ -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 diff --git a/repos/os/src/drivers/platform/legacy/x86/pci_session_component.h b/repos/os/src/drivers/platform/legacy/x86/pci_session_component.h index c157edf06c..ddf2828faa 100644 --- a/repos/os/src/drivers/platform/legacy/x86/pci_session_component.h +++ b/repos/os/src/drivers/platform/legacy/x86/pci_session_component.h @@ -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_label const _label; List _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 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 _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 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 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 _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 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 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 private: Env &_env; + Allocator &_heap; Attached_rom_dataspace &_config; Constructible _pci_confspace { }; addr_t _pci_confspace_base = 0; Constructible _pci_reporter { }; - Heap _heap { _env.ram(), _env.rm() }; - Device_bars_pool _devices_bars { }; Constructible _buses { }; @@ -1123,11 +1123,12 @@ class Platform::Root : public Root_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(&env.ep().rpc_ep(), &md_alloc), _env(env), + _heap(heap), _config(config), _msi_platform(msi_platform) { diff --git a/repos/os/src/drivers/platform/legacy/x86/target.mk b/repos/os/src/drivers/platform/legacy/x86/target.mk index 65a0a83892..d9ab3786c1 100644 --- a/repos/os/src/drivers/platform/legacy/x86/target.mk +++ b/repos/os/src/drivers/platform/legacy/x86/target.mk @@ -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)