diff --git a/repos/os/include/platform_session/connection.h b/repos/os/include/platform_session/connection.h index 05809cf5fa..350c8c7a1d 100644 --- a/repos/os/include/platform_session/connection.h +++ b/repos/os/include/platform_session/connection.h @@ -17,6 +17,7 @@ #include <base/attached_dataspace.h> #include <base/connection.h> #include <base/env.h> +#include <base/signal.h> #include <platform_session/client.h> #include <rom_session/client.h> #include <util/xml_node.h> @@ -34,31 +35,58 @@ class Platform::Connection : public Genode::Connection<Session>, { private: - /* 'Device' and 'Dma_buffer' access the '_rm' member */ + /* 'Device' and 'Dma_buffer' access the '_env' member */ friend class Device; friend class Dma_buffer; - Region_map &_rm; - Rom_session_client _rom {devices_rom()}; - Constructible<Attached_dataspace> _ds {}; + Env &_env; + Rom_session_client _rom {devices_rom()}; + Constructible<Attached_dataspace> _ds {}; + Constructible<Io_signal_handler<Connection>> _handler {}; void _try_attach() { _ds.destruct(); - try { _ds.construct(_rm, _rom.dataspace()); } + try { _ds.construct(_env.rm(), _rom.dataspace()); } catch (Attached_dataspace::Invalid_dataspace) { warning("Invalid devices rom dataspace returned!");} } + void _handle_io() {} + + template <typename FN> + Capability<Device_interface> _wait_for_device(FN const & fn) + { + for (;;) { + /* repeatedly check for availability of device */ + Capability<Device_interface> cap = fn(); + if (cap.valid()) { + if (_handler.constructed()) { + sigh(Signal_context_capability()); + _handler.destruct(); + } + return cap; + } + + if (!_handler.constructed()) { + _handler.construct(_env.ep(), *this, + &Connection::_handle_io); + sigh(*_handler); + } + + _env.ep().wait_and_dispatch_one_io_signal(); + } + } + public: Connection(Env &env) : Genode::Connection<Session>(env, session(env.parent(), - "ram_quota=%u, cap_quota=%u", - RAM_QUOTA, CAP_QUOTA)), + "ram_quota=%u, cap_quota=%u", + RAM_QUOTA, CAP_QUOTA)), Client(cap()), - _rm(env.rm()) + _env(env) { _try_attach(); } @@ -75,14 +103,18 @@ class Platform::Connection : public Genode::Connection<Session>, Capability<Device_interface> acquire_device(Device_name const &name) override { - return retry_with_upgrade(Ram_quota{6*1024}, Cap_quota{6}, [&] () { - return Client::acquire_device(name); }); + return _wait_for_device([&] () { + return retry_with_upgrade(Ram_quota{6*1024}, Cap_quota{6}, [&] () { + return Client::acquire_device(name); }); + }); } Capability<Device_interface> acquire_device() { - return retry_with_upgrade(Ram_quota{6*1024}, Cap_quota{6}, [&] () { - return Client::acquire_single_device(); }); + return _wait_for_device([&] () { + return retry_with_upgrade(Ram_quota{6*1024}, Cap_quota{6}, [&] () { + return Client::acquire_single_device(); }); + }); } Ram_dataspace_capability alloc_dma_buffer(size_t size, Cache cache) override @@ -105,30 +137,29 @@ class Platform::Connection : public Genode::Connection<Session>, Capability<Device_interface> device_by_type(char const * type) { - using String = Genode::String<64>; + return _wait_for_device([&] () { - Capability<Device_interface> cap; + using String = Genode::String<64>; - with_xml([&] (Xml_node & xml) { - xml.for_each_sub_node("device", [&] (Xml_node node) { + Capability<Device_interface> cap; - /* already found a device? */ - if (cap.valid()) - return; + with_xml([&] (Xml_node & xml) { + xml.for_each_sub_node("device", [&] (Xml_node node) { - if (node.attribute_value("type", String()) != type) - return; + /* already found a device? */ + if (cap.valid()) + return; - Device_name name = node.attribute_value("name", Device_name()); - cap = acquire_device(name); + if (node.attribute_value("type", String()) != type) + return; + + Device_name name = node.attribute_value("name", Device_name()); + cap = acquire_device(name); + }); }); - if (!cap.valid()) { - error(__func__, ": type=", type, " not found!"); - error("device ROM content: ", xml); - } - }); - return cap; + return cap; + }); } }; diff --git a/repos/os/include/platform_session/device.h b/repos/os/include/platform_session/device.h index 1d8950b9ee..736fc5ceeb 100644 --- a/repos/os/include/platform_session/device.h +++ b/repos/os/include/platform_session/device.h @@ -59,7 +59,7 @@ class Platform::Device : Interface, Noncopyable return _cap.call<Device_interface::Rpc_io_port_range>(index); } - Region_map &_rm() { return _platform._rm; } + Region_map &_rm() { return _platform._env.rm(); } public: diff --git a/repos/os/include/platform_session/dma_buffer.h b/repos/os/include/platform_session/dma_buffer.h index 9d8100aa30..b80f42d2cd 100644 --- a/repos/os/include/platform_session/dma_buffer.h +++ b/repos/os/include/platform_session/dma_buffer.h @@ -46,7 +46,7 @@ class Platform::Dma_buffer : Noncopyable } _allocation; - Attached_dataspace _ds { _allocation.platform._rm, _allocation.cap }; + Attached_dataspace _ds { _allocation.platform._env.rm(), _allocation.cap }; public: diff --git a/repos/os/run/platform_drv.run b/repos/os/run/platform_drv.run index d4e08442d4..3fdfaf45f2 100644 --- a/repos/os/run/platform_drv.run +++ b/repos/os/run/platform_drv.run @@ -88,7 +88,7 @@ install_config { <config verbose="no"/> </start> - <start name="platform_drv"> + <start name="platform_drv" managing_system="yes"> <resource name="RAM" quantum="1M"/> <provides> <service name="Platform"/> </provides> <route> @@ -168,25 +168,6 @@ set good_string { [init -> test-platform_drv] <irq number="32"/> [init -> test-platform_drv] </device> [init -> test-platform_drv] </devices> -[init -> test-platform_drv] Error: Device 0 not valid! -[init -> test-platform_drv] <devices version="7"> -[init -> test-platform_drv] <device name="0" type="dummy-device" used="true"> -[init -> test-platform_drv] <io_mem phys_addr="0x40000100" size="0x1000"/> -[init -> test-platform_drv] <irq number="32"/> -[init -> test-platform_drv] </device> -[init -> test-platform_drv] <device name="1" type="dummy-device" used="false"> -[init -> test-platform_drv] <io_mem phys_addr="0x40001100" size="0x1000"/> -[init -> test-platform_drv] <irq number="33"/> -[init -> test-platform_drv] </device> -[init -> test-platform_drv] <device name="2" type="dummy-device" used="false"> -[init -> test-platform_drv] <io_mem phys_addr="0x40002100" size="0x1000"/> -[init -> test-platform_drv] <irq number="34"/> -[init -> test-platform_drv] </device> -[init -> test-platform_drv] <device name="3" type="dummy-device" used="false"> -[init -> test-platform_drv] <io_mem phys_addr="0x40003100" size="0x1000"/> -[init -> test-platform_drv] <irq number="35"/> -[init -> test-platform_drv] </device> -[init -> test-platform_drv] </devices> [init -> test-platform_drv] Found next valid device of dummy type [init -> test-platform_drv] Test has ended! } diff --git a/repos/os/src/drivers/platform/README b/repos/os/src/drivers/platform/README index e059d4efbb..777fac775b 100644 --- a/repos/os/src/drivers/platform/README +++ b/repos/os/src/drivers/platform/README @@ -42,9 +42,10 @@ physical to virtual identical mappings of DMA memory for the device_pd On some systems, e.g., base-hw kernel on certain ARM platforms, it allows the platform driver to call system management firmware via kernel syscalls. -The 'info' attribute in a policy node describe, whether the client gets -permission to access a devices ROM containing detailed information about -the devices of its virtual bus. +The 'info' attribute in a policy node describe, whether the client's devices +ROM will contain detailed information about physical resources of the devices +of its virtual bus. This is only useful when using ported legacy drivers, which +operate with global names of physical resources. Report facilities ----------------- diff --git a/repos/os/src/drivers/platform/device.cc b/repos/os/src/drivers/platform/device.cc index 80446a6cfd..3f530e3e0b 100644 --- a/repos/os/src/drivers/platform/device.cc +++ b/repos/os/src/drivers/platform/device.cc @@ -112,7 +112,8 @@ void Driver::Device::release(Session_component & sc) } -void Driver::Device::report(Xml_generator & xml, Device_model & devices) +void Driver::Device::report(Xml_generator & xml, Device_model & devices, + bool info) { xml.node("device", [&] () { xml.attribute("name", name()); @@ -120,17 +121,23 @@ void Driver::Device::report(Xml_generator & xml, Device_model & devices) xml.attribute("used", _owner.valid()); _io_mem_list.for_each([&] (Io_mem & io_mem) { xml.node("io_mem", [&] () { + if (!info) + return; xml.attribute("phys_addr", String<16>(Hex(io_mem.range.start))); xml.attribute("size", String<16>(Hex(io_mem.range.size))); }); }); _irq_list.for_each([&] (Irq & irq) { xml.node("irq", [&] () { + if (!info) + return; xml.attribute("number", irq.number); }); }); _io_port_range_list.for_each([&] (Io_port_range & io_port_range) { xml.node("io_port_range", [&] () { + if (!info) + return; xml.attribute("phys_addr", String<16>(Hex(io_port_range.addr))); xml.attribute("size", String<16>(Hex(io_port_range.size))); }); @@ -171,7 +178,7 @@ void Driver::Device_model::update_report() if (_reporter.enabled()) { Reporter::Xml_generator xml(_reporter, [&] () { for_each([&] (Device & device) { - device.report(xml, *this); }); + device.report(xml, *this, true); }); }); } } diff --git a/repos/os/src/drivers/platform/device.h b/repos/os/src/drivers/platform/device.h index 728ed3c329..3aa5bdc990 100644 --- a/repos/os/src/drivers/platform/device.h +++ b/repos/os/src/drivers/platform/device.h @@ -167,7 +167,7 @@ class Driver::Device : private List_model<Device>::Element fn(idx++, ipr.addr, ipr.size); }); } - void report(Xml_generator &, Device_model &); + void report(Xml_generator &, Device_model &, bool); protected: diff --git a/repos/os/src/drivers/platform/session_component.cc b/repos/os/src/drivers/platform/session_component.cc index 6af99fa901..447832c277 100644 --- a/repos/os/src/drivers/platform/session_component.cc +++ b/repos/os/src/drivers/platform/session_component.cc @@ -97,14 +97,11 @@ void Session_component::update_policy(bool info, Policy_version version) void Session_component::produce_xml(Xml_generator &xml) { - if (!_info) - return; - if (_version.valid()) xml.attribute("version", _version); _devices.for_each([&] (Device & dev) { - if (matches(dev)) dev.report(xml, _devices); }); + if (matches(dev)) dev.report(xml, _devices, _info); }); } diff --git a/repos/os/src/test/platform_drv/main.cc b/repos/os/src/test/platform_drv/main.cc index 522ea5421a..f4ce9192fc 100644 --- a/repos/os/src/test/platform_drv/main.cc +++ b/repos/os/src/test/platform_drv/main.cc @@ -60,7 +60,6 @@ struct Main Reporter device_reporter { env, "devices" }; Reconstructible<Platform::Connection> platform { env }; - Constructible<Platform::Connection> platform_2 { }; Signal_handler<Main> device_rom_handler { env.ep(), *this, &Main::handle_device_update }; @@ -193,14 +192,6 @@ struct Main next_step(1, 1, 0x40000100, 32); return; case 6: - start_driver(0); - platform_2.construct(env); - devices[1].construct(*platform_2, Platform::Device::Name(0)); - stop_driver(1); - platform_2.destruct(); - next_step(4, 4, 0x40000100, 32); - return; - case 7: { Platform::Device dev (*platform, Platform::Device::Type({"dummy-device"})); if (dev._cap.valid()) log("Found next valid device of dummy type");