mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +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 <base/exception.h>
|
||||||
#include <io_mem_session/client.h>
|
#include <io_mem_session/client.h>
|
||||||
#include <irq_session/client.h>
|
#include <irq_session/client.h>
|
||||||
|
#include <io_port_session/client.h>
|
||||||
#include <platform_session/connection.h>
|
#include <platform_session/connection.h>
|
||||||
|
|
||||||
class Platform::Device : Interface, Noncopyable
|
class Platform::Device : Interface, Noncopyable
|
||||||
@ -29,6 +30,7 @@ class Platform::Device : Interface, Noncopyable
|
|||||||
|
|
||||||
struct Mmio;
|
struct Mmio;
|
||||||
struct Irq;
|
struct Irq;
|
||||||
|
struct Io_port_range;
|
||||||
|
|
||||||
typedef Platform::Session::Device_name Name;
|
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);
|
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; }
|
Region_map &_rm() { return _platform._rm; }
|
||||||
|
|
||||||
public:
|
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_ */
|
#endif /* _INCLUDE__PLATFORM_SESSION__DEVICE_H_ */
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <rom_session/capability.h>
|
#include <rom_session/capability.h>
|
||||||
#include <irq_session/capability.h>
|
#include <irq_session/capability.h>
|
||||||
#include <io_mem_session/capability.h>
|
#include <io_mem_session/capability.h>
|
||||||
|
#include <io_port_session/capability.h>
|
||||||
#include <session/session.h>
|
#include <session/session.h>
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
@ -42,8 +43,10 @@ struct Platform::Device_interface : Interface
|
|||||||
GENODE_RPC(Rpc_irq, Irq_session_capability, irq, unsigned);
|
GENODE_RPC(Rpc_irq, Irq_session_capability, irq, unsigned);
|
||||||
GENODE_RPC(Rpc_io_mem, Io_mem_session_capability, io_mem,
|
GENODE_RPC(Rpc_io_mem, Io_mem_session_capability, io_mem,
|
||||||
unsigned, Range &, Cache);
|
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);
|
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) {
|
_property_list.for_each([&] (Property & p) {
|
||||||
xml.node("property", [&] () {
|
xml.node("property", [&] () {
|
||||||
xml.attribute("name", p.name);
|
xml.attribute("name", p.name);
|
||||||
|
@ -35,6 +35,7 @@ namespace Driver {
|
|||||||
class Session_component;
|
class Session_component;
|
||||||
struct Irq_update_policy;
|
struct Irq_update_policy;
|
||||||
struct Io_mem_update_policy;
|
struct Io_mem_update_policy;
|
||||||
|
struct Io_port_update_policy;
|
||||||
struct Property_update_policy;
|
struct Property_update_policy;
|
||||||
struct Clock_update_policy;
|
struct Clock_update_policy;
|
||||||
struct Reset_domain_update_policy;
|
struct Reset_domain_update_policy;
|
||||||
@ -78,6 +79,15 @@ class Driver::Device : private List_model<Device>::Element
|
|||||||
Irq(unsigned number) : number(number) {}
|
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
|
struct Property : List_model<Property>::Element
|
||||||
{
|
{
|
||||||
using Name = Genode::String<64>;
|
using Name = Genode::String<64>;
|
||||||
@ -149,6 +159,13 @@ class Driver::Device : private List_model<Device>::Element
|
|||||||
fn(idx++, iomem.range); });
|
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 &);
|
void report(Xml_generator &, Session_component &);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -165,6 +182,7 @@ class Driver::Device : private List_model<Device>::Element
|
|||||||
Owner _owner {};
|
Owner _owner {};
|
||||||
List_model<Io_mem> _io_mem_list {};
|
List_model<Io_mem> _io_mem_list {};
|
||||||
List_model<Irq> _irq_list {};
|
List_model<Irq> _irq_list {};
|
||||||
|
List_model<Io_port_range> _io_port_range_list {};
|
||||||
List_model<Property> _property_list {};
|
List_model<Property> _property_list {};
|
||||||
List_model<Clock> _clock_list {};
|
List_model<Clock> _clock_list {};
|
||||||
List_model<Power_domain> _power_domain_list {};
|
List_model<Power_domain> _power_domain_list {};
|
||||||
@ -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
|
struct Driver::Property_update_policy : Genode::List_model<Device::Property>::Update_policy
|
||||||
{
|
{
|
||||||
Genode::Allocator & alloc;
|
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,
|
Device_component::Device_component(Registry<Device_component> & registry,
|
||||||
Driver::Session_component & session,
|
Driver::Session_component & session,
|
||||||
Driver::Device & device)
|
Driver::Device & device)
|
||||||
@ -118,6 +137,17 @@ Device_component::Device_component(Registry<Device_component> & registry,
|
|||||||
_cap_quota += Io_mem_session::CAP_QUOTA;
|
_cap_quota += Io_mem_session::CAP_QUOTA;
|
||||||
new (session.heap()) Io_mem(_io_mem_registry, idx, range);
|
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(...) {
|
} catch(...) {
|
||||||
_release_resources();
|
_release_resources();
|
||||||
throw;
|
throw;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include <base/registry.h>
|
#include <base/registry.h>
|
||||||
#include <base/rpc_server.h>
|
#include <base/rpc_server.h>
|
||||||
|
#include <io_port_session/connection.h>
|
||||||
#include <io_mem_session/connection.h>
|
#include <io_mem_session/connection.h>
|
||||||
#include <irq_session/connection.h>
|
#include <irq_session/connection.h>
|
||||||
#include <platform_session/device.h>
|
#include <platform_session/device.h>
|
||||||
@ -63,6 +64,22 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
|
|||||||
idx(idx), range(range) {}
|
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,
|
Device_component(Registry<Device_component> & registry,
|
||||||
Session_component & session,
|
Session_component & session,
|
||||||
Driver::Device & device);
|
Driver::Device & device);
|
||||||
@ -78,6 +95,7 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
|
|||||||
|
|
||||||
Irq_session_capability irq(unsigned);
|
Irq_session_capability irq(unsigned);
|
||||||
Io_mem_session_capability io_mem(unsigned, Range &, Cache);
|
Io_mem_session_capability io_mem(unsigned, Range &, Cache);
|
||||||
|
Io_port_session_capability io_port_range(unsigned);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -88,6 +106,7 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
|
|||||||
Registry<Device_component>::Element _reg_elem;
|
Registry<Device_component>::Element _reg_elem;
|
||||||
Registry<Irq> _irq_registry {};
|
Registry<Irq> _irq_registry {};
|
||||||
Registry<Io_mem> _io_mem_registry {};
|
Registry<Io_mem> _io_mem_registry {};
|
||||||
|
Registry<Io_port_range> _io_port_range_registry {};
|
||||||
|
|
||||||
void _release_resources();
|
void _release_resources();
|
||||||
|
|
||||||
|
@ -28,6 +28,11 @@ void Device_model::destroy_element(Device & device)
|
|||||||
device._io_mem_list.destroy_all_elements(policy);
|
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);
|
Property_update_policy policy(_heap);
|
||||||
device._property_list.destroy_all_elements(policy);
|
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);
|
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);
|
Property_update_policy policy(_heap);
|
||||||
device._property_list.update_from_xml(policy, node);
|
device._property_list.update_from_xml(policy, node);
|
||||||
|
Loading…
Reference in New Issue
Block a user