diff --git a/repos/os/include/platform_session/device.h b/repos/os/include/platform_session/device.h
index 47f24d684e..1d8950b9ee 100644
--- a/repos/os/include/platform_session/device.h
+++ b/repos/os/include/platform_session/device.h
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
class Platform::Device : Interface, Noncopyable
@@ -29,6 +30,7 @@ class Platform::Device : Interface, Noncopyable
struct Mmio;
struct Irq;
+ struct Io_port_range;
typedef Platform::Session::Device_name Name;
@@ -52,6 +54,11 @@ class Platform::Device : Interface, Noncopyable
return _cap.call(index, range, cache);
}
+ Io_port_session_capability _io_port_range(unsigned index)
+ {
+ return _cap.call(index);
+ }
+
Region_map &_rm() { return _platform._rm; }
public:
@@ -167,4 +174,33 @@ class Platform::Device::Irq : Noncopyable
}
};
+
+class Platform::Device::Io_port_range : Noncopyable
+{
+ private:
+
+ Io_port_session_client _io_port_range;
+
+ public:
+
+ struct Index { unsigned value; };
+
+ Io_port_range(Device &device, Index index)
+ : _io_port_range(device._io_port_range(index.value)) { }
+
+ explicit Io_port_range(Device &device)
+ : Io_port_range(device, Index { 0 }) { }
+
+ uint8_t inb(uint16_t addr) { return _io_port_range.inb(addr); };
+ uint16_t inw(uint16_t addr) { return _io_port_range.inw(addr); };
+ uint32_t inl(uint16_t addr) { return _io_port_range.inl(addr); };
+
+ void outb(uint16_t addr, uint8_t value) {
+ _io_port_range.outb(addr, value); };
+ void outw(uint16_t addr, uint16_t value) {
+ _io_port_range.outw(addr, value); };
+ void outl(uint16_t addr, uint32_t value) {
+ _io_port_range.outl(addr, value); };
+};
+
#endif /* _INCLUDE__PLATFORM_SESSION__DEVICE_H_ */
diff --git a/repos/os/include/platform_session/platform_session.h b/repos/os/include/platform_session/platform_session.h
index a826aafd1b..6818276188 100644
--- a/repos/os/include/platform_session/platform_session.h
+++ b/repos/os/include/platform_session/platform_session.h
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
namespace Platform {
@@ -42,8 +43,10 @@ struct Platform::Device_interface : Interface
GENODE_RPC(Rpc_irq, Irq_session_capability, irq, unsigned);
GENODE_RPC(Rpc_io_mem, Io_mem_session_capability, io_mem,
unsigned, Range &, Cache);
+ GENODE_RPC(Rpc_io_port_range, Io_port_session_capability, io_port_range,
+ unsigned);
- GENODE_RPC_INTERFACE(Rpc_irq, Rpc_io_mem);
+ GENODE_RPC_INTERFACE(Rpc_irq, Rpc_io_mem, Rpc_io_port_range);
};
diff --git a/repos/os/src/drivers/platform/device.cc b/repos/os/src/drivers/platform/device.cc
index 83d47a40e6..c0adf9a25d 100644
--- a/repos/os/src/drivers/platform/device.cc
+++ b/repos/os/src/drivers/platform/device.cc
@@ -122,6 +122,12 @@ void Driver::Device::report(Xml_generator & xml, Session_component & sc)
xml.attribute("number", irq.number);
});
});
+ _io_port_range_list.for_each([&] (Io_port_range & io_port_range) {
+ xml.node("io_port_range", [&] () {
+ xml.attribute("phys_addr", String<16>(Hex(io_port_range.addr)));
+ xml.attribute("size", String<16>(Hex(io_port_range.size)));
+ });
+ });
_property_list.for_each([&] (Property & p) {
xml.node("property", [&] () {
xml.attribute("name", p.name);
diff --git a/repos/os/src/drivers/platform/device.h b/repos/os/src/drivers/platform/device.h
index 17772775e0..ff0a3fa249 100644
--- a/repos/os/src/drivers/platform/device.h
+++ b/repos/os/src/drivers/platform/device.h
@@ -35,6 +35,7 @@ namespace Driver {
class Session_component;
struct Irq_update_policy;
struct Io_mem_update_policy;
+ struct Io_port_update_policy;
struct Property_update_policy;
struct Clock_update_policy;
struct Reset_domain_update_policy;
@@ -78,6 +79,15 @@ class Driver::Device : private List_model::Element
Irq(unsigned number) : number(number) {}
};
+ struct Io_port_range : List_model::Element
+ {
+ uint16_t addr;
+ uint16_t size;
+
+ Io_port_range(uint16_t addr, uint16_t size)
+ : addr(addr), size(size) {}
+ };
+
struct Property : List_model::Element
{
using Name = Genode::String<64>;
@@ -149,6 +159,13 @@ class Driver::Device : private List_model::Element
fn(idx++, iomem.range); });
}
+ template void for_each_io_port_range(FN const & fn)
+ {
+ unsigned idx = 0;
+ _io_port_range_list.for_each([&] (Io_port_range const & ipr) {
+ fn(idx++, ipr.addr, ipr.size); });
+ }
+
void report(Xml_generator &, Session_component &);
protected:
@@ -160,15 +177,16 @@ class Driver::Device : private List_model::Element
friend class List_model;
friend class List;
- Name _name;
- Type _type;
- Owner _owner {};
- List_model _io_mem_list {};
- List_model _irq_list {};
- List_model _property_list {};
- List_model _clock_list {};
- List_model _power_domain_list {};
- List_model _reset_domain_list {};
+ Name _name;
+ Type _type;
+ Owner _owner {};
+ List_model _io_mem_list {};
+ List_model _irq_list {};
+ List_model _io_port_range_list {};
+ List_model _property_list {};
+ List_model _clock_list {};
+ List_model _power_domain_list {};
+ List_model _reset_domain_list {};
/*
* Noncopyable
@@ -290,6 +308,39 @@ struct Driver::Io_mem_update_policy : Genode::List_model::Update
};
+struct Driver::Io_port_update_policy
+: Genode::List_model::Update_policy
+{
+ Genode::Allocator & alloc;
+
+ Io_port_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
+
+ void destroy_element(Element & ipr) {
+ Genode::destroy(alloc, &ipr); }
+
+ Element & create_element(Genode::Xml_node node)
+ {
+ uint16_t addr = node.attribute_value("address", 0);
+ uint16_t size = node.attribute_value("size", 0);
+ return *(new (alloc) Element(addr, size));
+ }
+
+ void update_element(Element &, Genode::Xml_node) {}
+
+ static bool element_matches_xml_node(Element const & ipr, Genode::Xml_node node)
+ {
+ uint16_t addr = node.attribute_value("address", 0);
+ uint16_t size = node.attribute_value("size", 0);
+ return addr == ipr.addr && size == ipr.size;
+ }
+
+ static bool node_is_element(Genode::Xml_node node)
+ {
+ return node.has_type("io_port_range");
+ }
+};
+
+
struct Driver::Property_update_policy : Genode::List_model::Update_policy
{
Genode::Allocator & alloc;
diff --git a/repos/os/src/drivers/platform/device_component.cc b/repos/os/src/drivers/platform/device_component.cc
index c8e3cb5fa1..5ec400f0de 100644
--- a/repos/os/src/drivers/platform/device_component.cc
+++ b/repos/os/src/drivers/platform/device_component.cc
@@ -81,6 +81,25 @@ Genode::Irq_session_capability Device_component::irq(unsigned idx)
}
+Genode::Io_port_session_capability Device_component::io_port_range(unsigned idx)
+{
+ Io_port_session_capability cap;
+
+ _io_port_range_registry.for_each([&] (Io_port_range & ipr)
+ {
+ if (ipr.idx != idx)
+ return;
+
+ if (!ipr.io_port_range.constructed())
+ ipr.io_port_range.construct(_session.env(), ipr.addr, ipr.size);
+
+ cap = ipr.io_port_range->cap();
+ });
+
+ return cap;
+}
+
+
Device_component::Device_component(Registry & registry,
Driver::Session_component & session,
Driver::Device & device)
@@ -109,7 +128,7 @@ Device_component::Device_component(Registry & registry,
_cap_quota += Irq_session::CAP_QUOTA;
new (session.heap()) Irq(_irq_registry, idx, nr);
});
-
+
device.for_each_io_mem([&] (unsigned idx, Range range)
{
session.ram_quota_guard().withdraw(Ram_quota{Io_mem_session::RAM_QUOTA});
@@ -118,6 +137,17 @@ Device_component::Device_component(Registry & registry,
_cap_quota += Io_mem_session::CAP_QUOTA;
new (session.heap()) Io_mem(_io_mem_registry, idx, range);
});
+
+ device.for_each_io_port_range([&] (unsigned idx, uint16_t addr,
+ uint16_t size)
+ {
+ session.ram_quota_guard().withdraw(Ram_quota{Io_port_session::RAM_QUOTA});
+ _ram_quota += Io_port_session::RAM_QUOTA;
+ session.cap_quota_guard().withdraw(Cap_quota{Io_port_session::CAP_QUOTA});
+ _cap_quota += Io_port_session::CAP_QUOTA;
+ new (session.heap()) Io_port_range(_io_port_range_registry,
+ idx, addr, size);
+ });
} catch(...) {
_release_resources();
throw;
diff --git a/repos/os/src/drivers/platform/device_component.h b/repos/os/src/drivers/platform/device_component.h
index 6998cd8ed8..babefbef91 100644
--- a/repos/os/src/drivers/platform/device_component.h
+++ b/repos/os/src/drivers/platform/device_component.h
@@ -16,6 +16,7 @@
#include
#include
+#include
#include
#include
#include
@@ -63,6 +64,22 @@ class Driver::Device_component : public Rpc_object::Element
+ {
+ unsigned idx;
+ uint16_t addr;
+ uint16_t size;
+ Constructible io_port_range {};
+
+ Io_port_range(Registry & registry,
+ unsigned idx,
+ uint16_t addr,
+ uint16_t size)
+ :
+ Registry::Element(registry, *this),
+ idx(idx), addr(addr), size(size) {}
+ };
+
Device_component(Registry & registry,
Session_component & session,
Driver::Device & device);
@@ -76,8 +93,9 @@ class Driver::Device_component : public Rpc_object::Element _reg_elem;
Registry _irq_registry {};
Registry _io_mem_registry {};
+ Registry _io_port_range_registry {};
void _release_resources();
diff --git a/repos/os/src/drivers/platform/device_model_policy.cc b/repos/os/src/drivers/platform/device_model_policy.cc
index bb72ab98b2..a3e7dfac3c 100644
--- a/repos/os/src/drivers/platform/device_model_policy.cc
+++ b/repos/os/src/drivers/platform/device_model_policy.cc
@@ -28,6 +28,11 @@ void Device_model::destroy_element(Device & device)
device._io_mem_list.destroy_all_elements(policy);
}
+ {
+ Io_port_update_policy policy(_heap);
+ device._io_port_range_list.destroy_all_elements(policy);
+ }
+
{
Property_update_policy policy(_heap);
device._property_list.destroy_all_elements(policy);
@@ -73,6 +78,11 @@ void Device_model::update_element(Device & device,
device._io_mem_list.update_from_xml(policy, node);
}
+ {
+ Io_port_update_policy policy(_heap);
+ device._io_port_range_list.update_from_xml(policy, node);
+ }
+
{
Property_update_policy policy(_heap);
device._property_list.update_from_xml(policy, node);