mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
platform: introduce I/O ports in API
* Introduces Platform::Device::Io_port client utility * Implements I/O ports as common device resources in platform driver Fix genodelabs/genode#4436
This commit is contained in:
parent
8a4cbe3cc9
commit
57aab46fc3
@ -21,6 +21,7 @@
|
||||
#include <base/exception.h>
|
||||
#include <io_mem_session/client.h>
|
||||
#include <irq_session/client.h>
|
||||
#include <io_port_session/client.h>
|
||||
#include <platform_session/connection.h>
|
||||
|
||||
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<Device_interface::Rpc_io_mem>(index, range, cache);
|
||||
}
|
||||
|
||||
Io_port_session_capability _io_port_range(unsigned index)
|
||||
{
|
||||
return _cap.call<Device_interface::Rpc_io_port_range>(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_ */
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <rom_session/capability.h>
|
||||
#include <irq_session/capability.h>
|
||||
#include <io_mem_session/capability.h>
|
||||
#include <io_port_session/capability.h>
|
||||
#include <session/session.h>
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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<Device>::Element
|
||||
Irq(unsigned number) : number(number) {}
|
||||
};
|
||||
|
||||
struct Io_port_range : List_model<Io_port_range>::Element
|
||||
{
|
||||
uint16_t addr;
|
||||
uint16_t size;
|
||||
|
||||
Io_port_range(uint16_t addr, uint16_t size)
|
||||
: addr(addr), size(size) {}
|
||||
};
|
||||
|
||||
struct Property : List_model<Property>::Element
|
||||
{
|
||||
using Name = Genode::String<64>;
|
||||
@ -149,6 +159,13 @@ class Driver::Device : private List_model<Device>::Element
|
||||
fn(idx++, iomem.range); });
|
||||
}
|
||||
|
||||
template <typename FN> 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<Device>::Element
|
||||
friend class List_model<Device>;
|
||||
friend class List<Device>;
|
||||
|
||||
Name _name;
|
||||
Type _type;
|
||||
Owner _owner {};
|
||||
List_model<Io_mem> _io_mem_list {};
|
||||
List_model<Irq> _irq_list {};
|
||||
List_model<Property> _property_list {};
|
||||
List_model<Clock> _clock_list {};
|
||||
List_model<Power_domain> _power_domain_list {};
|
||||
List_model<Reset_domain> _reset_domain_list {};
|
||||
Name _name;
|
||||
Type _type;
|
||||
Owner _owner {};
|
||||
List_model<Io_mem> _io_mem_list {};
|
||||
List_model<Irq> _irq_list {};
|
||||
List_model<Io_port_range> _io_port_range_list {};
|
||||
List_model<Property> _property_list {};
|
||||
List_model<Clock> _clock_list {};
|
||||
List_model<Power_domain> _power_domain_list {};
|
||||
List_model<Reset_domain> _reset_domain_list {};
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
@ -290,6 +308,39 @@ struct Driver::Io_mem_update_policy : Genode::List_model<Device::Io_mem>::Update
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Io_port_update_policy
|
||||
: Genode::List_model<Device::Io_port_range>::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<uint16_t>("address", 0);
|
||||
uint16_t size = node.attribute_value<uint16_t>("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<uint16_t>("address", 0);
|
||||
uint16_t size = node.attribute_value<uint16_t>("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<Device::Property>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
@ -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<Device_component> & registry,
|
||||
Driver::Session_component & session,
|
||||
Driver::Device & device)
|
||||
@ -109,7 +128,7 @@ Device_component::Device_component(Registry<Device_component> & 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<Device_component> & 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;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <base/registry.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <io_port_session/connection.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <irq_session/connection.h>
|
||||
#include <platform_session/device.h>
|
||||
@ -63,6 +64,22 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
|
||||
idx(idx), range(range) {}
|
||||
};
|
||||
|
||||
struct Io_port_range : Registry<Io_port_range>::Element
|
||||
{
|
||||
unsigned idx;
|
||||
uint16_t addr;
|
||||
uint16_t size;
|
||||
Constructible<Io_port_connection> io_port_range {};
|
||||
|
||||
Io_port_range(Registry<Io_port_range> & registry,
|
||||
unsigned idx,
|
||||
uint16_t addr,
|
||||
uint16_t size)
|
||||
:
|
||||
Registry<Io_port_range>::Element(registry, *this),
|
||||
idx(idx), addr(addr), size(size) {}
|
||||
};
|
||||
|
||||
Device_component(Registry<Device_component> & registry,
|
||||
Session_component & session,
|
||||
Driver::Device & device);
|
||||
@ -76,8 +93,9 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
|
||||
** Platform::Device RPC functions **
|
||||
************************************/
|
||||
|
||||
Irq_session_capability irq(unsigned);
|
||||
Io_mem_session_capability io_mem(unsigned, Range &, Cache);
|
||||
Irq_session_capability irq(unsigned);
|
||||
Io_mem_session_capability io_mem(unsigned, Range &, Cache);
|
||||
Io_port_session_capability io_port_range(unsigned);
|
||||
|
||||
private:
|
||||
|
||||
@ -88,6 +106,7 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
|
||||
Registry<Device_component>::Element _reg_elem;
|
||||
Registry<Irq> _irq_registry {};
|
||||
Registry<Io_mem> _io_mem_registry {};
|
||||
Registry<Io_port_range> _io_port_range_registry {};
|
||||
|
||||
void _release_resources();
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user