mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-21 22:47:50 +00:00
parent
935dcf8b18
commit
1a80f166c5
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief PCI device capability type
|
||||
* \brief Device capability type
|
||||
* \author Norman Feske
|
||||
* \date 2008-08-16
|
||||
*/
|
58
repos/os/include/spec/arm/platform_device/client.h
Normal file
58
repos/os/include/spec/arm/platform_device/client.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* \brief Client-side interface for ARM device
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__CLIENT_H_
|
||||
#define _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__CLIENT_H_
|
||||
|
||||
#include <platform_session/platform_session.h>
|
||||
#include <platform_device/platform_device.h>
|
||||
#include <base/rpc_client.h>
|
||||
#include <io_mem_session/client.h>
|
||||
|
||||
namespace Platform { struct Device_client; }
|
||||
|
||||
|
||||
struct Platform::Device_client : Genode::Rpc_client<Device>
|
||||
{
|
||||
Device_client(Device_capability device)
|
||||
: Genode::Rpc_client<Device>(device) {}
|
||||
|
||||
Genode::Irq_session_capability irq(unsigned id = 0) override
|
||||
{
|
||||
return call<Rpc_irq>(id);
|
||||
}
|
||||
|
||||
Genode::Io_mem_session_capability
|
||||
io_mem(unsigned id = 0,
|
||||
Genode::Cache_attribute caching =
|
||||
Genode::Cache_attribute::UNCACHED) override
|
||||
{
|
||||
return call<Rpc_io_mem>(id, caching);
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
** Convenience utilities **
|
||||
***************************/
|
||||
|
||||
Genode::Io_mem_dataspace_capability
|
||||
io_mem_dataspace(unsigned id = 0,
|
||||
Genode::Cache_attribute caching =
|
||||
Genode::Cache_attribute::UNCACHED)
|
||||
{
|
||||
Genode::Io_mem_session_client session(io_mem(id, caching));
|
||||
return session.dataspace();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__CLIENT_H_ */
|
56
repos/os/include/spec/arm/platform_device/platform_device.h
Normal file
56
repos/os/include/spec/arm/platform_device/platform_device.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* \brief ARM-device interface
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
|
||||
#define _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
|
||||
|
||||
#include <base/rpc.h>
|
||||
#include <base/exception.h>
|
||||
#include <io_mem_session/capability.h>
|
||||
#include <irq_session/capability.h>
|
||||
#include <util/string.h>
|
||||
|
||||
namespace Platform { struct Device; }
|
||||
|
||||
struct Platform::Device : Genode::Session
|
||||
{
|
||||
enum { DEVICE_NAME_LEN = 64 };
|
||||
|
||||
using Name = Genode::String<DEVICE_NAME_LEN>;
|
||||
|
||||
virtual ~Device() { }
|
||||
|
||||
/**
|
||||
* Get IRQ session capability
|
||||
*/
|
||||
virtual Genode::Irq_session_capability irq(unsigned id) = 0;
|
||||
|
||||
/**
|
||||
* Get IO mem session capability of specified resource id
|
||||
*/
|
||||
virtual Genode::Io_mem_session_capability
|
||||
io_mem(unsigned id, Genode::Cache_attribute attr) = 0;
|
||||
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_irq, Genode::Irq_session_capability, irq, unsigned);
|
||||
GENODE_RPC(Rpc_io_mem, Genode::Io_mem_session_capability, io_mem,
|
||||
unsigned, Genode::Cache_attribute);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_irq, Rpc_io_mem);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ */
|
52
repos/os/include/spec/arm/platform_session/client.h
Normal file
52
repos/os/include/spec/arm/platform_session/client.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* \brief Client-side Platform-session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-28
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CLIENT_H_
|
||||
#define _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CLIENT_H_
|
||||
|
||||
#include <base/rpc_client.h>
|
||||
#include <platform_device/client.h>
|
||||
#include <platform_session/capability.h>
|
||||
|
||||
namespace Platform {
|
||||
using namespace Genode;
|
||||
|
||||
struct Client;
|
||||
}
|
||||
|
||||
|
||||
struct Platform::Client : public Genode::Rpc_client<Session>
|
||||
{
|
||||
Client(Session_capability session)
|
||||
: Rpc_client<Session>(session) { }
|
||||
|
||||
Rom_session_capability devices_rom() override {
|
||||
return call<Rpc_devices_rom>(); }
|
||||
|
||||
Device_capability acquire_device(String const &device) override {
|
||||
return call<Rpc_acquire_device>(device); }
|
||||
|
||||
void release_device(Device_capability device) override {
|
||||
call<Rpc_release_device>(device); }
|
||||
|
||||
Ram_dataspace_capability alloc_dma_buffer(size_t size) override {
|
||||
return call<Rpc_alloc_dma_buffer>(size); }
|
||||
|
||||
void free_dma_buffer(Ram_dataspace_capability cap) override {
|
||||
call<Rpc_free_dma_buffer>(cap); }
|
||||
|
||||
addr_t bus_addr_dma_buffer(Ram_dataspace_capability cap) override {
|
||||
return call<Rpc_bus_addr_dma_buffer>(cap); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CLIENT_H_ */
|
132
repos/os/include/spec/arm/platform_session/connection.h
Normal file
132
repos/os/include/spec/arm/platform_session/connection.h
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* \brief Connection to Platform service
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-05-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CONNECTION_H_
|
||||
#define _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CONNECTION_H_
|
||||
|
||||
#include <base/connection.h>
|
||||
#include <base/env.h>
|
||||
#include <platform_session/client.h>
|
||||
#include <rom_session/client.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
namespace Platform { struct Connection; }
|
||||
|
||||
|
||||
class Platform::Connection : public Genode::Connection<Session>,
|
||||
public Client
|
||||
{
|
||||
private:
|
||||
|
||||
Region_map & _rm;
|
||||
Rom_session_client _rom {devices_rom()};
|
||||
Constructible<Attached_dataspace> _ds {};
|
||||
|
||||
void _try_attach()
|
||||
{
|
||||
_ds.destruct();
|
||||
try { _ds.construct(_rm, _rom.dataspace()); }
|
||||
catch (Attached_dataspace::Invalid_dataspace) {
|
||||
warning("Invalid devices rom dataspace returned!");}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Connection(Env &env)
|
||||
: Genode::Connection<Session>(env, session(env.parent(),
|
||||
"ram_quota=%u, cap_quota=%u",
|
||||
RAM_QUOTA, CAP_QUOTA)),
|
||||
Client(cap()),
|
||||
_rm(env.rm()) { _try_attach(); }
|
||||
|
||||
Device_capability acquire_device(String const &device) override
|
||||
{
|
||||
return retry_with_upgrade(Ram_quota{6*1024}, Cap_quota{6}, [&] () {
|
||||
return Client::acquire_device(device); });
|
||||
}
|
||||
|
||||
Ram_dataspace_capability alloc_dma_buffer(size_t size) override
|
||||
{
|
||||
return retry_with_upgrade(Ram_quota{size}, Cap_quota{2}, [&] () {
|
||||
return Client::alloc_dma_buffer(size); });
|
||||
}
|
||||
|
||||
template <typename FN>
|
||||
void with_xml(FN const & fn)
|
||||
{
|
||||
try {
|
||||
if (_ds.constructed() && _ds->local_addr<void const>()) {
|
||||
Xml_node xml(_ds->local_addr<char>(), _ds->size());
|
||||
fn(xml);
|
||||
}
|
||||
} catch (Xml_node::Invalid_syntax) {
|
||||
warning("Devices rom has invalid XML syntax"); }
|
||||
}
|
||||
|
||||
Device_capability device_by_index(unsigned idx)
|
||||
{
|
||||
Device_capability cap;
|
||||
|
||||
with_xml([&] (Xml_node & xml) {
|
||||
try {
|
||||
Xml_node node = xml.sub_node(idx);
|
||||
Device::Name name = node.attribute_value("name",
|
||||
Device::Name());
|
||||
cap = acquire_device(name.string());
|
||||
} catch(Xml_node::Nonexistent_sub_node) {
|
||||
error(__func__, ": invalid device index ", idx);
|
||||
error("device ROM content: ", xml);
|
||||
}
|
||||
});
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
Device_capability device_by_property(char const * property,
|
||||
char const * value)
|
||||
{
|
||||
using String = Genode::String<64>;
|
||||
|
||||
Device_capability cap;
|
||||
|
||||
with_xml([&] (Xml_node & xml) {
|
||||
xml.for_each_sub_node("device", [&] (Xml_node node) {
|
||||
/* already found a device? */
|
||||
if (cap.valid()) { return; }
|
||||
|
||||
bool found = false;
|
||||
node.for_each_sub_node("property", [&] (Xml_node node) {
|
||||
if ((node.attribute_value("name", String()) == property) &&
|
||||
(node.attribute_value("value", String()) == value)) {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (found) {
|
||||
Device::Name name = node.attribute_value("name",
|
||||
Device::Name());
|
||||
cap = acquire_device(name.string());
|
||||
}
|
||||
});
|
||||
if (!cap.valid()) {
|
||||
error(__func__, ": property=", property, " value=",
|
||||
value, " not found!");
|
||||
error("device ROM content: ", xml);
|
||||
}
|
||||
});
|
||||
|
||||
return cap;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CONNECTION_H_ */
|
108
repos/os/include/spec/arm/platform_session/platform_session.h
Normal file
108
repos/os/include/spec/arm/platform_session/platform_session.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* \brief Platform session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-28
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SPEC__ARM__PLATFORM_SESSION__PLATFORM_SESSION_H_
|
||||
#define _INCLUDE__SPEC__ARM__PLATFORM_SESSION__PLATFORM_SESSION_H_
|
||||
|
||||
#include <base/quota_guard.h>
|
||||
#include <base/rpc_args.h>
|
||||
#include <dataspace/capability.h>
|
||||
#include <platform_device/capability.h>
|
||||
#include <platform_device/platform_device.h>
|
||||
#include <rom_session/capability.h>
|
||||
#include <session/session.h>
|
||||
|
||||
namespace Platform {
|
||||
using namespace Genode;
|
||||
|
||||
struct Session;
|
||||
}
|
||||
|
||||
|
||||
struct Platform::Session : Genode::Session
|
||||
{
|
||||
/*********************
|
||||
** Exception types **
|
||||
*********************/
|
||||
|
||||
class Fatal : public Out_of_ram { };
|
||||
|
||||
/**
|
||||
* \noapi
|
||||
*/
|
||||
static const char *service_name() { return "Platform"; }
|
||||
|
||||
enum { RAM_QUOTA = 16 * 1024, CAP_QUOTA = 6 };
|
||||
|
||||
virtual ~Session() { }
|
||||
|
||||
using String = Rpc_in_buffer<Device::DEVICE_NAME_LEN>;
|
||||
|
||||
/**
|
||||
* Request ROM session containing the information about available devices.
|
||||
*
|
||||
* \return capability to ROM dataspace
|
||||
*/
|
||||
virtual Rom_session_capability devices_rom() = 0;
|
||||
|
||||
/**
|
||||
* Acquire device known by unique 'name'.
|
||||
*/
|
||||
virtual Device_capability acquire_device(String const &name) = 0;
|
||||
|
||||
/**
|
||||
* Free server-internal data structures representing the device
|
||||
*
|
||||
* Use this method to relax the resource-allocation of the Platform session.
|
||||
*/
|
||||
virtual void release_device(Device_capability device) = 0;
|
||||
|
||||
/**
|
||||
* Allocate memory suitable for DMA.
|
||||
*/
|
||||
virtual Ram_dataspace_capability alloc_dma_buffer(size_t) = 0;
|
||||
|
||||
/**
|
||||
* Free previously allocated DMA memory
|
||||
*/
|
||||
virtual void free_dma_buffer(Ram_dataspace_capability) = 0;
|
||||
|
||||
/**
|
||||
* Return the bus address of the previously allocated DMA memory
|
||||
*/
|
||||
virtual addr_t bus_addr_dma_buffer(Ram_dataspace_capability) = 0;
|
||||
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_devices_rom, Rom_session_capability, devices_rom);
|
||||
GENODE_RPC_THROW(Rpc_acquire_device, Device_capability, acquire_device,
|
||||
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps),
|
||||
String const &);
|
||||
GENODE_RPC(Rpc_release_device, void, release_device, Device_capability);
|
||||
GENODE_RPC_THROW(Rpc_alloc_dma_buffer, Ram_dataspace_capability,
|
||||
alloc_dma_buffer,
|
||||
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps, Fatal), size_t);
|
||||
GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer,
|
||||
Ram_dataspace_capability);
|
||||
GENODE_RPC(Rpc_bus_addr_dma_buffer, addr_t, bus_addr_dma_buffer,
|
||||
Ram_dataspace_capability);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_devices_rom, Rpc_acquire_device, Rpc_release_device,
|
||||
Rpc_alloc_dma_buffer, Rpc_free_dma_buffer,
|
||||
Rpc_bus_addr_dma_buffer);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SPEC__ARM__PLATFORM_SESSION__PLATFORM_SESSION_H_ */
|
35
repos/os/include/spec/imx53/platform_session/connection.h
Normal file
35
repos/os/include/spec/imx53/platform_session/connection.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* \brief Connection to platform service
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2013-04-29
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SPEC__IMX53__PLATFORM_SESSION__CONNECTION_H_
|
||||
#define _INCLUDE__SPEC__IMX53__PLATFORM_SESSION__CONNECTION_H_
|
||||
|
||||
#include <platform_session/client.h>
|
||||
#include <util/arg_string.h>
|
||||
#include <base/connection.h>
|
||||
|
||||
namespace Platform { struct Connection; }
|
||||
|
||||
|
||||
struct Platform::Connection : Genode::Connection<Session>, Client
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Connection(Genode::Env &env)
|
||||
: Genode::Connection<Session>(env, session(env.parent(),
|
||||
"ram_quota=6K, cap_quota=%u", CAP_QUOTA)),
|
||||
Client(cap()) { }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SPEC__IMX53__PLATFORM_SESSION__CONNECTION_H_ */
|
@ -11,14 +11,14 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__PLATFORM_SESSION__CONNECTION_H_
|
||||
#define _INCLUDE__PLATFORM_SESSION__CONNECTION_H_
|
||||
#ifndef _INCLUDE__SPEC__RPI__PLATFORM_SESSION__CONNECTION_H_
|
||||
#define _INCLUDE__SPEC__RPI__PLATFORM_SESSION__CONNECTION_H_
|
||||
|
||||
#include <platform_session/client.h>
|
||||
#include <util/arg_string.h>
|
||||
#include <base/connection.h>
|
||||
|
||||
namespace Platform { class Connection; }
|
||||
namespace Platform { struct Connection; }
|
||||
|
||||
|
||||
struct Platform::Connection : Genode::Connection<Session>, Client
|
||||
@ -28,8 +28,8 @@ struct Platform::Connection : Genode::Connection<Session>, Client
|
||||
*/
|
||||
Connection(Genode::Env &env)
|
||||
: Genode::Connection<Session>(env, session(env.parent(),
|
||||
"ram_quota=6K, cap_quota=%ld", CAP_QUOTA)),
|
||||
"ram_quota=6K, cap_quota=%u", CAP_QUOTA)),
|
||||
Client(cap()) { }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__PLATFORM_SESSION__CONNECTION_H_ */
|
||||
#endif /* _INCLUDE__SPEC__RPI__PLATFORM_SESSION__CONNECTION_H_ */
|
@ -38,7 +38,7 @@ struct Platform::Session : Genode::Session
|
||||
*/
|
||||
static const char *service_name() { return "Platform"; }
|
||||
|
||||
enum { CAP_QUOTA = 2 };
|
||||
enum { RAM_QUOTA = 16 * 1024, CAP_QUOTA = 2 };
|
||||
|
||||
virtual ~Session() { }
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
INCLUDE_SUB_DIRS := platform_session \
|
||||
platform_device \
|
||||
spec/arm/platform_session \
|
||||
spec/arm/platform_device \
|
||||
spec/imx53/platform_session \
|
||||
spec/rpi/platform \
|
||||
spec/rpi/platform_session \
|
||||
spec/x86/platform_session \
|
||||
platform_device \
|
||||
spec/x86/platform_device
|
||||
|
||||
INCLUDE_DIRS := $(addprefix include/,$(INCLUDE_SUB_DIRS))
|
||||
|
162
repos/os/src/drivers/platform/spec/arm/device.cc
Normal file
162
repos/os/src/drivers/platform/spec/arm/device.cc
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* \brief Platform driver - Device abstraction
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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 <device.h>
|
||||
#include <session_component.h>
|
||||
|
||||
Driver::Device::Name Driver::Device::name() const { return _name; }
|
||||
|
||||
|
||||
bool Driver::Device::acquire(Session_component & sc)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
if (_session.valid() && _session != sc.label()) { return false; }
|
||||
|
||||
/**
|
||||
* FIXME: By now, we cannot use the connection objects for IRQ and
|
||||
* IOMEM and propagate missing resources when opening the
|
||||
* sessions, because the combination of Genode::Env and
|
||||
* Genode::Connection object transparently does quota upgrades.
|
||||
* If we like to account those costs per client, we actually
|
||||
* need to explicitely forward exceptions during session
|
||||
* requests.
|
||||
* For now, we try to measure the probable costs.
|
||||
*/
|
||||
Cap_quota_guard::Reservation caps(sc.cap_quota_guard(),
|
||||
Cap_quota{_cap_quota_required()});
|
||||
Ram_quota_guard::Reservation ram(sc.ram_quota_guard(),
|
||||
Ram_quota{_ram_quota_required()});
|
||||
|
||||
_session = sc.label();
|
||||
|
||||
caps.acknowledge();
|
||||
ram.acknowledge();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Driver::Device::release(Session_component & sc)
|
||||
{
|
||||
if (_session != sc.label()) { return; }
|
||||
|
||||
sc.replenish(Genode::Cap_quota{_cap_quota_required()});
|
||||
sc.replenish(Genode::Ram_quota{_ram_quota_required()});
|
||||
|
||||
_io_mem_list.for_each([&] (Io_mem & io_mem) {
|
||||
if (io_mem.io_mem) {
|
||||
Genode::destroy(sc.heap(), io_mem.io_mem);
|
||||
}
|
||||
});
|
||||
|
||||
_irq_list.for_each([&] (Irq & irq) {
|
||||
if (irq.irq) {
|
||||
Genode::destroy(sc.heap(), irq.irq);
|
||||
}
|
||||
});
|
||||
|
||||
_session = Platform::Session::Label();;
|
||||
}
|
||||
|
||||
|
||||
Genode::Irq_session_capability Driver::Device::irq(unsigned idx,
|
||||
Session_component & sc)
|
||||
{
|
||||
Genode::Irq_session_capability cap;
|
||||
|
||||
if (_session != sc.label()) { return cap; }
|
||||
|
||||
unsigned i = 0;
|
||||
_irq_list.for_each([&] (Irq & irq)
|
||||
{
|
||||
if (i++ != idx) return;
|
||||
|
||||
if (!irq.irq) {
|
||||
irq.irq = new (sc.heap())
|
||||
Genode::Irq_connection(sc.env(), irq.number);
|
||||
}
|
||||
cap = irq.irq->cap();
|
||||
});
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
|
||||
Genode::Io_mem_session_capability
|
||||
Driver::Device::io_mem(unsigned idx, Genode::Cache_attribute attr,
|
||||
Session_component & sc)
|
||||
{
|
||||
Genode::Io_mem_session_capability cap;
|
||||
|
||||
if (_session != sc.label()) return cap;
|
||||
|
||||
unsigned i = 0;
|
||||
_io_mem_list.for_each([&] (Io_mem & io_mem)
|
||||
{
|
||||
if (i++ != idx) return;
|
||||
|
||||
if (!io_mem.io_mem) {
|
||||
io_mem.io_mem = new (sc.heap())
|
||||
Genode::Io_mem_connection(sc.env(), io_mem.base, io_mem.size,
|
||||
(attr == Genode::WRITE_COMBINED));
|
||||
}
|
||||
cap = io_mem.io_mem->cap();
|
||||
});
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
|
||||
void Driver::Device::report(Genode::Xml_generator & xml)
|
||||
{
|
||||
xml.node("device", [&] () {
|
||||
xml.attribute("name", name());
|
||||
_property_list.for_each([&] (Property & p) {
|
||||
xml.node("property", [&] () {
|
||||
xml.attribute("name", p.name);
|
||||
xml.attribute("value", p.value);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Genode::size_t Driver::Device::_cap_quota_required()
|
||||
{
|
||||
Genode::size_t total = 0;
|
||||
_io_mem_list.for_each([&] (Io_mem &) {
|
||||
total += Genode::Io_mem_session::CAP_QUOTA; });
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
Genode::size_t Driver::Device::_ram_quota_required()
|
||||
{
|
||||
Genode::size_t total = 0;
|
||||
_io_mem_list.for_each([&] (Io_mem & io_mem) {
|
||||
total += io_mem.size + 2*1024; });
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
Driver::Device::Device(Name name)
|
||||
: _name(name) { }
|
||||
|
||||
|
||||
Driver::Device::~Device()
|
||||
{
|
||||
if (_session.valid()) {
|
||||
Genode::error("Device to be destroyed, still obtained by session ",
|
||||
_session);
|
||||
}
|
||||
}
|
144
repos/os/src/drivers/platform/spec/arm/device.h
Normal file
144
repos/os/src/drivers/platform/spec/arm/device.h
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* \brief Platform driver - Device abstraction
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_
|
||||
#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_
|
||||
|
||||
#include <base/allocator.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <irq_session/connection.h>
|
||||
#include <platform_session/platform_session.h>
|
||||
#include <util/list.h>
|
||||
#include <util/list_model.h>
|
||||
#include <util/reconstructible.h>
|
||||
#include <util/xml_generator.h>
|
||||
|
||||
namespace Driver {
|
||||
class Device;
|
||||
struct Device_model;
|
||||
class Session_component;
|
||||
}
|
||||
|
||||
|
||||
class Driver::Device : public Genode::List_model<Device>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
struct Io_mem : Genode::List_model<Io_mem>::Element
|
||||
{
|
||||
Genode::addr_t base;
|
||||
Genode::size_t size;
|
||||
Genode::Io_mem_connection * io_mem { nullptr };
|
||||
|
||||
Io_mem(Genode::addr_t base, Genode::size_t size)
|
||||
: base(base), size(size) {}
|
||||
};
|
||||
|
||||
struct Irq : Genode::List_model<Irq>::Element
|
||||
{
|
||||
unsigned number;
|
||||
Genode::Irq_connection * irq { nullptr };
|
||||
|
||||
Irq(unsigned number) : number(number) {}
|
||||
};
|
||||
|
||||
struct Property : Genode::List_model<Property>::Element
|
||||
{
|
||||
using Name = Genode::String<64>;
|
||||
using Value = Genode::String<64>;
|
||||
|
||||
Name name;
|
||||
Value value;
|
||||
|
||||
Property(Name name, Value value)
|
||||
: name(name), value(value) {}
|
||||
};
|
||||
|
||||
using Name = Genode::String<64>;
|
||||
|
||||
Device(Name name);
|
||||
~Device();
|
||||
|
||||
Name name() const;
|
||||
|
||||
bool acquire(Session_component &);
|
||||
void release(Session_component &);
|
||||
|
||||
Genode::Irq_session_capability irq(unsigned idx,
|
||||
Session_component & session);
|
||||
Genode::Io_mem_session_capability io_mem(unsigned idx,
|
||||
Genode::Cache_attribute,
|
||||
Session_component & session);
|
||||
|
||||
void report(Genode::Xml_generator &);
|
||||
|
||||
private:
|
||||
|
||||
Genode::size_t _cap_quota_required();
|
||||
Genode::size_t _ram_quota_required();
|
||||
|
||||
friend class Driver::Device_model;
|
||||
|
||||
Name _name;
|
||||
Platform::Session::Label _session {};
|
||||
Genode::List_model<Io_mem> _io_mem_list {};
|
||||
Genode::List_model<Irq> _irq_list {};
|
||||
Genode::List_model<Property> _property_list {};
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Device(Device const &);
|
||||
Device &operator = (Device const &);
|
||||
};
|
||||
|
||||
|
||||
class Driver::Device_model :
|
||||
public Genode::List_model<Device>::Update_policy
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Allocator & _alloc;
|
||||
Genode::List_model<Device> _model {};
|
||||
|
||||
public:
|
||||
|
||||
void update(Genode::Xml_node const & node) {
|
||||
_model.update_from_xml(*this, node);
|
||||
}
|
||||
|
||||
Device_model(Genode::Allocator & alloc,
|
||||
Genode::Xml_node const & node)
|
||||
: _alloc(alloc) { update(node); }
|
||||
|
||||
~Device_model() {
|
||||
_model.destroy_all_elements(*this); }
|
||||
|
||||
|
||||
template <typename FN>
|
||||
void for_each(FN const & fn) { _model.for_each(fn); }
|
||||
|
||||
|
||||
/***********************
|
||||
** Update_policy API **
|
||||
***********************/
|
||||
|
||||
void destroy_element(Device & device);
|
||||
Device & create_element(Genode::Xml_node node);
|
||||
void update_element(Device & device, Genode::Xml_node node);
|
||||
static bool element_matches_xml_node(Device const &,
|
||||
Genode::Xml_node);
|
||||
static bool node_is_element(Genode::Xml_node);
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_ */
|
75
repos/os/src/drivers/platform/spec/arm/device_component.cc
Normal file
75
repos/os/src/drivers/platform/spec/arm/device_component.cc
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* \brief Platform driver for ARM device component
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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 <device.h>
|
||||
#include <device_component.h>
|
||||
#include <session_component.h>
|
||||
|
||||
using Driver::Device_component;
|
||||
|
||||
Driver::Device::Name Device_component::device() const { return _device; }
|
||||
|
||||
|
||||
Driver::Session_component & Device_component::session() { return _session; }
|
||||
|
||||
|
||||
bool Driver::Device_component::acquire()
|
||||
{
|
||||
bool acquired = false;
|
||||
_session.devices().for_each([&] (Driver::Device & device) {
|
||||
if (device.name() == _device) {
|
||||
acquired = device.acquire(_session); }});
|
||||
return acquired;
|
||||
}
|
||||
|
||||
|
||||
void Driver::Device_component::release()
|
||||
{
|
||||
_session.devices().for_each([&] (Driver::Device & device) {
|
||||
if (device.name() == _device) { device.release(_session); }});
|
||||
}
|
||||
|
||||
|
||||
Genode::Io_mem_session_capability
|
||||
Device_component::io_mem(unsigned idx, Genode::Cache_attribute attr)
|
||||
{
|
||||
Genode::Io_mem_session_capability cap;
|
||||
_session.devices().for_each([&] (Driver::Device & device) {
|
||||
if (device.name() == _device) {
|
||||
cap = device.io_mem(idx, attr, _session); }});
|
||||
return cap;
|
||||
}
|
||||
|
||||
|
||||
Genode::Irq_session_capability Device_component::irq(unsigned idx)
|
||||
{
|
||||
Genode::Irq_session_capability cap;
|
||||
_session.devices().for_each([&] (Driver::Device & device) {
|
||||
if (device.name() == _device) { cap = device.irq(idx, _session); }});
|
||||
return cap;
|
||||
}
|
||||
|
||||
|
||||
void Driver::Device_component::report(Genode::Xml_generator & xml)
|
||||
{
|
||||
_session.devices().for_each([&] (Driver::Device & device) {
|
||||
if (device.name() == _device) { device.report(xml); }});
|
||||
}
|
||||
|
||||
|
||||
Device_component::Device_component(Driver::Session_component & session,
|
||||
Driver::Device::Name const device)
|
||||
: _session(session), _device(device) { }
|
||||
|
||||
|
||||
Device_component::~Device_component() { release(); }
|
71
repos/os/src/drivers/platform/spec/arm/device_component.h
Normal file
71
repos/os/src/drivers/platform/spec/arm/device_component.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* \brief Platform driver for ARM device component
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_COMPONENT_H_
|
||||
#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_COMPONENT_H_
|
||||
|
||||
#include <base/rpc_server.h>
|
||||
#include <platform_session/platform_session.h>
|
||||
#include <platform_device/platform_device.h>
|
||||
|
||||
#include <device.h>
|
||||
|
||||
namespace Driver {
|
||||
class Device_component;
|
||||
class Session_component;
|
||||
}
|
||||
|
||||
|
||||
class Driver::Device_component : public Genode::Rpc_object<Platform::Device>
|
||||
{
|
||||
public:
|
||||
|
||||
Device_component(Session_component & session,
|
||||
Driver::Device::Name const device);
|
||||
~Device_component();
|
||||
|
||||
Driver::Device::Name device() const;
|
||||
Session_component & session();
|
||||
|
||||
bool acquire();
|
||||
void release();
|
||||
|
||||
void report(Genode::Xml_generator&);
|
||||
|
||||
|
||||
/**************************
|
||||
** Platform::Device API **
|
||||
**************************/
|
||||
|
||||
Genode::Irq_session_capability irq(unsigned) override;
|
||||
|
||||
Genode::Io_mem_session_capability
|
||||
io_mem(unsigned, Genode::Cache_attribute) override;
|
||||
|
||||
private:
|
||||
|
||||
friend class Session_component;
|
||||
|
||||
Session_component & _session;
|
||||
Driver::Device::Name const _device;
|
||||
Platform::Device_capability _cap {};
|
||||
Genode::List_element<Device_component> _list_elem { this };
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Device_component(Device_component const &);
|
||||
Device_component &operator = (Device_component const &);
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_COMPONENT_H_ */
|
169
repos/os/src/drivers/platform/spec/arm/device_model_policy.cc
Normal file
169
repos/os/src/drivers/platform/spec/arm/device_model_policy.cc
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* \brief Platform driver - Device model policy
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-05-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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 <device.h>
|
||||
|
||||
using Driver::Device_model;
|
||||
using Driver::Device;
|
||||
|
||||
struct Irq_update_policy : Genode::List_model<Device::Irq>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Irq_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & irq) {
|
||||
Genode::destroy(alloc, &irq); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
unsigned number = node.attribute_value<unsigned>("number", 0);
|
||||
return *(new (alloc) Element(number));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & irq, Genode::Xml_node node)
|
||||
{
|
||||
unsigned number = node.attribute_value<unsigned>("number", 0);
|
||||
return number == irq.number;
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
using Name = Genode::String<16>;
|
||||
return node.has_type("resource") &&
|
||||
(node.attribute_value("name", Name()) == "IRQ");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Io_mem_update_policy : Genode::List_model<Device::Io_mem>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Io_mem_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & iomem) {
|
||||
Genode::destroy(alloc, &iomem); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
Genode::addr_t base = node.attribute_value<Genode::addr_t>("address", 0);
|
||||
Genode::size_t size = node.attribute_value<Genode::size_t>("size", 0);
|
||||
return *(new (alloc) Element(base, size));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & iomem, Genode::Xml_node node)
|
||||
{
|
||||
Genode::addr_t base = node.attribute_value<Genode::addr_t>("address", 0);
|
||||
Genode::size_t size = node.attribute_value<Genode::size_t>("size", 0);
|
||||
return (base == iomem.base) && (size == iomem.size);
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
bool iomem = node.attribute_value("name", Genode::String<16>())
|
||||
== "IO_MEM";
|
||||
return node.has_type("resource") && iomem;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Property_update_policy : Genode::List_model<Device::Property>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Property_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & p) {
|
||||
Genode::destroy(alloc, &p); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
return *(new (alloc)
|
||||
Element(node.attribute_value("name", Element::Name()),
|
||||
node.attribute_value("value", Element::Value())));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & prop, Genode::Xml_node node)
|
||||
{
|
||||
Element::Name n = node.attribute_value("name", Element::Name());
|
||||
Element::Value v = node.attribute_value("value", Element::Value());
|
||||
return (n == prop.name) && (v == prop.value);
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node) {
|
||||
return node.has_type("property"); }
|
||||
};
|
||||
|
||||
|
||||
void Device_model::destroy_element(Device & device)
|
||||
{
|
||||
{
|
||||
Irq_update_policy policy(_alloc);
|
||||
device._irq_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Io_mem_update_policy policy(_alloc);
|
||||
device._io_mem_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Property_update_policy policy(_alloc);
|
||||
device._property_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
Genode::destroy(_alloc, &device);
|
||||
}
|
||||
|
||||
|
||||
Device & Device_model::create_element(Genode::Xml_node node)
|
||||
{
|
||||
Device::Name name = node.attribute_value("name", Device::Name());
|
||||
return *(new (_alloc) Device(name));
|
||||
}
|
||||
|
||||
|
||||
void Device_model::update_element(Device & device,
|
||||
Genode::Xml_node node)
|
||||
{
|
||||
{
|
||||
Irq_update_policy policy(_alloc);
|
||||
device._irq_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Io_mem_update_policy policy(_alloc);
|
||||
device._io_mem_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Property_update_policy policy(_alloc);
|
||||
device._property_list.update_from_xml(policy, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Device_model::element_matches_xml_node(Device const & dev,
|
||||
Genode::Xml_node n) {
|
||||
return dev.name() == n.attribute_value("name", Device::Name()); }
|
||||
|
||||
|
||||
bool Device_model::node_is_element(Genode::Xml_node node) {
|
||||
return node.has_type("device"); }
|
53
repos/os/src/drivers/platform/spec/arm/main.cc
Normal file
53
repos/os/src/drivers/platform/spec/arm/main.cc
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* \brief Platform driver for ARM
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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 <base/component.h>
|
||||
#include <base/env.h>
|
||||
#include <base/heap.h>
|
||||
|
||||
#include <root.h>
|
||||
|
||||
namespace Driver { struct Main; };
|
||||
|
||||
struct Driver::Main
|
||||
{
|
||||
void update_config();
|
||||
|
||||
Genode::Env & env;
|
||||
Genode::Heap heap { env.ram(), env.rm() };
|
||||
Genode::Sliced_heap sliced_heap { env.ram(), env.rm() };
|
||||
Genode::Attached_rom_dataspace config { env, "config" };
|
||||
Genode::Signal_handler<Main> config_handler { env.ep(), *this,
|
||||
&Main::update_config };
|
||||
Driver::Device_model devices { heap, config.xml() };
|
||||
Driver::Root root { env, sliced_heap,
|
||||
config, devices };
|
||||
|
||||
Main(Genode::Env &env)
|
||||
: env(env)
|
||||
{
|
||||
config.sigh(config_handler);
|
||||
env.parent().announce(env.ep().manage(root));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Driver::Main::update_config()
|
||||
{
|
||||
config.update();
|
||||
devices.update(config.xml());
|
||||
root.update_policy();
|
||||
}
|
||||
|
||||
void Component::construct(Genode::Env &env) {
|
||||
static Driver::Main main(env); }
|
0
repos/os/src/drivers/platform/spec/arm/policy.h
Normal file
0
repos/os/src/drivers/platform/spec/arm/policy.h
Normal file
89
repos/os/src/drivers/platform/spec/arm/root.cc
Normal file
89
repos/os/src/drivers/platform/spec/arm/root.cc
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* \brief Platform driver for ARM root component
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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 <root.h>
|
||||
|
||||
void Driver::Root::update_policy()
|
||||
{
|
||||
_sessions.for_each([&] (Session_component & sc) {
|
||||
|
||||
bool policy_changed = false;
|
||||
unsigned device_count = 0;
|
||||
|
||||
try {
|
||||
Genode::Session_policy const policy { sc._label, _config.xml() };
|
||||
|
||||
policy.for_each_sub_node("device", [&] (Genode::Xml_node node) {
|
||||
device_count++;
|
||||
if (!sc.has_device(node.attribute_value("name",
|
||||
Device::Name()))) {
|
||||
policy_changed = true; }
|
||||
});
|
||||
|
||||
if (device_count != sc.devices_count()) { policy_changed = true; }
|
||||
}
|
||||
catch (Genode::Session_policy::No_policy_defined) {
|
||||
policy_changed = true;
|
||||
Genode::error("No matching policy for '", sc._label.string(),
|
||||
"' anymore, will close the session!");
|
||||
}
|
||||
|
||||
if (policy_changed) { close(sc.cap()); }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Driver::Session_component * Driver::Root::_create_session(const char *args)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Session_component * sc = nullptr;
|
||||
|
||||
try {
|
||||
sc = new (md_alloc()) Session_component(_env,
|
||||
_devices,
|
||||
_sessions,
|
||||
session_label_from_args(args),
|
||||
session_resources_from_args(args),
|
||||
session_diag_from_args(args));
|
||||
|
||||
Session_policy const policy { sc->_label, _config.xml() };
|
||||
policy.for_each_sub_node("device", [&] (Xml_node node) {
|
||||
sc->add(node.attribute_value("name", Driver::Device::Name())); });
|
||||
} catch (Session_policy::No_policy_defined) {
|
||||
if (sc) { Genode::destroy(md_alloc(), sc); }
|
||||
error("Invalid session request, no matching policy for ",
|
||||
"'", Genode::label_from_args(args).string(), "'");
|
||||
throw Service_denied();
|
||||
} catch (...) {
|
||||
if (sc) { Genode::destroy(md_alloc(), sc); }
|
||||
throw;
|
||||
}
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
|
||||
void Driver::Root::_upgrade_session(Session_component * sc, const char * args)
|
||||
{
|
||||
sc->upgrade(Genode::ram_quota_from_args(args));
|
||||
sc->upgrade(Genode::cap_quota_from_args(args));
|
||||
}
|
||||
|
||||
|
||||
Driver::Root::Root(Genode::Env & env,
|
||||
Genode::Allocator & alloc,
|
||||
Genode::Attached_rom_dataspace & config,
|
||||
Driver::Device_model & devices)
|
||||
: Genode::Root_component<Session_component>(env.ep(), alloc),
|
||||
_env(env), _config(config), _devices(devices) { }
|
49
repos/os/src/drivers/platform/spec/arm/root.h
Normal file
49
repos/os/src/drivers/platform/spec/arm/root.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* \brief Platform driver for ARM root component
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__ROOT_H_
|
||||
#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__ROOT_H_
|
||||
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/registry.h>
|
||||
#include <root/component.h>
|
||||
#include <session_component.h>
|
||||
|
||||
#include <device.h>
|
||||
|
||||
namespace Driver { class Root; }
|
||||
|
||||
class Driver::Root : public Genode::Root_component<Driver::Session_component>
|
||||
{
|
||||
public:
|
||||
|
||||
Root(Genode::Env & env,
|
||||
Genode::Allocator & alloc,
|
||||
Genode::Attached_rom_dataspace & config,
|
||||
Device_model & devices);
|
||||
|
||||
void update_policy();
|
||||
|
||||
private:
|
||||
|
||||
Session_component * _create_session(const char * args) override;
|
||||
|
||||
void _upgrade_session(Session_component *, const char *) override;
|
||||
|
||||
Genode::Env & _env;
|
||||
Genode::Attached_rom_dataspace & _config;
|
||||
Driver::Device_model & _devices;
|
||||
Genode::Registry<Session_component> _sessions {};
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__ROOT_H_ */
|
198
repos/os/src/drivers/platform/spec/arm/session_component.cc
Normal file
198
repos/os/src/drivers/platform/spec/arm/session_component.cc
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* \brief Platform driver - session component
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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 <dataspace/client.h>
|
||||
|
||||
#include <device.h>
|
||||
#include <session_component.h>
|
||||
|
||||
using Driver::Session_component;
|
||||
|
||||
void Session_component::produce_xml(Genode::Xml_generator &xml)
|
||||
{
|
||||
for (Device_list_element * e = _device_list.first(); e; e = e->next()) {
|
||||
e->object()->report(xml); }
|
||||
}
|
||||
|
||||
|
||||
Genode::Heap & Session_component::heap() { return _md_alloc; }
|
||||
|
||||
|
||||
Genode::Env & Session_component::env() { return _env; }
|
||||
|
||||
|
||||
Driver::Device_model & Session_component::devices() { return _device_model; }
|
||||
|
||||
|
||||
void Session_component::add(Device::Name const & device)
|
||||
{
|
||||
if (has_device(device)) return;
|
||||
|
||||
Device_component * new_dc =
|
||||
new (_md_alloc) Device_component(*this, device);
|
||||
|
||||
Device_list_element * last = nullptr;
|
||||
for (last = _device_list.first(); last; last = last->next()) {
|
||||
if (!last->next()) break; }
|
||||
_device_list.insert(&new_dc->_list_elem, last);
|
||||
}
|
||||
|
||||
|
||||
bool Session_component::has_device(Device::Name const & device) const
|
||||
{
|
||||
for (Device_list_element const * e = _device_list.first(); e;
|
||||
e = e->next()) {
|
||||
if (e->object()->device() == device) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
unsigned Session_component::devices_count() const
|
||||
{
|
||||
unsigned counter = 0;
|
||||
for (Device_list_element const * e = _device_list.first();
|
||||
e; e = e->next()) { counter++; }
|
||||
return counter;
|
||||
}
|
||||
|
||||
|
||||
Genode::Rom_session_capability Session_component::devices_rom() {
|
||||
return _rom_session.cap(); }
|
||||
|
||||
|
||||
Platform::Device_capability
|
||||
Session_component::acquire_device(Platform::Session::String const &name)
|
||||
{
|
||||
for (Device_list_element * e = _device_list.first(); e; e = e->next()) {
|
||||
if (e->object()->device() != name.string()) { continue; }
|
||||
|
||||
if (!e->object()->acquire()) {
|
||||
Genode::error("Device ", e->object()->device(),
|
||||
" already acquired!");
|
||||
break;
|
||||
}
|
||||
|
||||
/* account one device capability needed */
|
||||
_cap_quota_guard().replenish(Genode::Cap_quota{1});
|
||||
|
||||
return _env.ep().rpc_ep().manage(e->object());
|
||||
}
|
||||
|
||||
return Platform::Device_capability();
|
||||
}
|
||||
|
||||
|
||||
void Session_component::release_device(Platform::Device_capability device_cap)
|
||||
{
|
||||
_env.ep().rpc_ep().apply(device_cap, [&] (Device_component * dc) {
|
||||
_env.ep().rpc_ep().dissolve(dc);
|
||||
_cap_quota_guard().replenish(Genode::Cap_quota{1});
|
||||
dc->release();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Genode::Ram_dataspace_capability
|
||||
Session_component::alloc_dma_buffer(Genode::size_t const size)
|
||||
{
|
||||
Genode::Ram_dataspace_capability ram_cap =
|
||||
_env_ram.alloc(size, Genode::UNCACHED);
|
||||
|
||||
if (!ram_cap.valid()) return ram_cap;
|
||||
|
||||
try {
|
||||
_buffer_list.insert(new (_md_alloc) Dma_buffer(ram_cap));
|
||||
} catch (Genode::Out_of_ram) {
|
||||
_env_ram.free(ram_cap);
|
||||
throw;
|
||||
} catch (Genode::Out_of_caps) {
|
||||
_env_ram.free(ram_cap);
|
||||
throw;
|
||||
}
|
||||
|
||||
return ram_cap;
|
||||
}
|
||||
|
||||
|
||||
void Session_component::free_dma_buffer(Genode::Ram_dataspace_capability ram_cap)
|
||||
{
|
||||
if (!ram_cap.valid()) { return; }
|
||||
|
||||
for (Dma_buffer * buf = _buffer_list.first(); buf; buf = buf->next()) {
|
||||
|
||||
if (buf->cap.local_name() != ram_cap.local_name()) continue;
|
||||
|
||||
_buffer_list.remove(buf);
|
||||
destroy(_md_alloc, buf);
|
||||
_env_ram.free(ram_cap);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Genode::addr_t Session_component::bus_addr_dma_buffer(Ram_dataspace_capability ram_cap)
|
||||
{
|
||||
if (!ram_cap.valid()) { return 0; }
|
||||
|
||||
for (Dma_buffer * buf = _buffer_list.first(); buf; buf = buf->next()) {
|
||||
|
||||
if (buf->cap.local_name() != ram_cap.local_name()) continue;
|
||||
|
||||
Genode::Dataspace_client dsc(buf->cap);
|
||||
return dsc.phys_addr();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Session_component::Session_component(Genode::Env & env,
|
||||
Device_model & devices,
|
||||
Registry & registry,
|
||||
Label const & label,
|
||||
Resources const & resources,
|
||||
Diag const & diag)
|
||||
: Genode::Session_object<Platform::Session>(env.ep(), resources,
|
||||
label, diag),
|
||||
Registry::Element(registry, *this),
|
||||
Genode::Dynamic_rom_session::Xml_producer("devices"),
|
||||
_env(env),
|
||||
_device_model(devices)
|
||||
{
|
||||
/*
|
||||
* FIXME: As the ROM session does not propagate Out_of_*
|
||||
* exceptions resp. does not account costs for the ROM
|
||||
* dataspace to the client for the moment, we cannot do
|
||||
* so in the dynamic rom session, and cannot use the
|
||||
* constrained ram allocator within it. Therefore,
|
||||
* we account the costs here until the ROM session interface
|
||||
* changes.
|
||||
*/
|
||||
_cap_quota_guard().withdraw(Genode::Cap_quota{1});
|
||||
_ram_quota_guard().withdraw(Genode::Ram_quota{5*1024});
|
||||
}
|
||||
|
||||
|
||||
Session_component::~Session_component()
|
||||
{
|
||||
while (_device_list.first()) {
|
||||
Device_list_element * e = _device_list.first();
|
||||
_device_list.remove(e);
|
||||
destroy(_md_alloc, e->object());
|
||||
}
|
||||
|
||||
/* replenish quota for rom sessions, see constructor for explanation */
|
||||
_cap_quota_guard().replenish(Genode::Cap_quota{1});
|
||||
_ram_quota_guard().replenish(Genode::Ram_quota{5*1024});
|
||||
}
|
123
repos/os/src/drivers/platform/spec/arm/session_component.h
Normal file
123
repos/os/src/drivers/platform/spec/arm/session_component.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* \brief Platform driver - session component
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_
|
||||
#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/quota_guard.h>
|
||||
#include <base/registry.h>
|
||||
#include <base/session_object.h>
|
||||
#include <os/dynamic_rom_session.h>
|
||||
#include <os/session_policy.h>
|
||||
#include <platform_session/platform_session.h>
|
||||
|
||||
#include <device_component.h>
|
||||
|
||||
namespace Driver {
|
||||
class Session_component;
|
||||
class Root;
|
||||
}
|
||||
|
||||
|
||||
class Driver::Session_component :
|
||||
public Genode::Session_object<Platform::Session>,
|
||||
private Genode::Registry<Driver::Session_component>::Element,
|
||||
private Genode::Dynamic_rom_session::Xml_producer
|
||||
{
|
||||
public:
|
||||
|
||||
using Registry = Genode::Registry<Session_component>;
|
||||
|
||||
Session_component(Genode::Env & env,
|
||||
Device_model & devices,
|
||||
Registry & registry,
|
||||
Label const & label,
|
||||
Resources const & resources,
|
||||
Diag const & diag);
|
||||
~Session_component();
|
||||
|
||||
Genode::Heap & heap();
|
||||
Genode::Env & env();
|
||||
Device_model & devices();
|
||||
|
||||
void add(Device::Name const &);
|
||||
bool has_device(Device::Name const &) const;
|
||||
unsigned devices_count() const;
|
||||
|
||||
Genode::Ram_quota_guard &ram_quota_guard() {
|
||||
return _ram_quota_guard(); }
|
||||
|
||||
Genode::Cap_quota_guard &cap_quota_guard() {
|
||||
return _cap_quota_guard(); }
|
||||
|
||||
|
||||
/**************************
|
||||
** Platform Session API **
|
||||
**************************/
|
||||
|
||||
using Rom_session_capability = Genode::Rom_session_capability;
|
||||
using Device_capability = Platform::Device_capability;
|
||||
using Ram_dataspace_capability = Genode::Ram_dataspace_capability;
|
||||
using String = Platform::Session::String;
|
||||
using size_t = Genode::size_t;
|
||||
|
||||
Rom_session_capability devices_rom() override;
|
||||
Device_capability acquire_device(String const &) override;
|
||||
void release_device(Device_capability) override;
|
||||
Ram_dataspace_capability alloc_dma_buffer(size_t const) override;
|
||||
void free_dma_buffer(Ram_dataspace_capability ram_cap) override;
|
||||
Genode::addr_t bus_addr_dma_buffer(Ram_dataspace_capability) override;
|
||||
|
||||
private:
|
||||
|
||||
friend class Root;
|
||||
|
||||
struct Dma_buffer : Genode::List<Dma_buffer>::Element
|
||||
{
|
||||
Genode::Ram_dataspace_capability const cap;
|
||||
|
||||
Dma_buffer(Genode::Ram_dataspace_capability const cap)
|
||||
: cap(cap) {}
|
||||
};
|
||||
|
||||
using Device_list_element = Genode::List_element<Device_component>;
|
||||
using Device_list = Genode::List<Device_list_element>;
|
||||
|
||||
Genode::Env & _env;
|
||||
Genode::Constrained_ram_allocator _env_ram { _env.pd(),
|
||||
_ram_quota_guard(),
|
||||
_cap_quota_guard() };
|
||||
Genode::Heap _md_alloc { _env_ram, _env.rm() };
|
||||
Device_list _device_list { };
|
||||
Genode::List<Dma_buffer> _buffer_list { };
|
||||
Genode::Dynamic_rom_session _rom_session { _env.ep(), _env.ram(),
|
||||
_env.rm(), *this };
|
||||
Device_model & _device_model;
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Session_component(Session_component const &);
|
||||
Session_component &operator = (Session_component const &);
|
||||
|
||||
|
||||
/*******************************************
|
||||
** Dynamic_rom_session::Xml_producer API **
|
||||
*******************************************/
|
||||
|
||||
void produce_xml(Genode::Xml_generator &xml) override;
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_ */
|
5
repos/os/src/drivers/platform/spec/arm/target.mk
Normal file
5
repos/os/src/drivers/platform/spec/arm/target.mk
Normal file
@ -0,0 +1,5 @@
|
||||
TARGET = platform_drv
|
||||
REQUIRES = arm
|
||||
SRC_CC = device.cc device_component.cc device_model_policy.cc main.cc session_component.cc root.cc
|
||||
INC_DIR = $(PRG_DIR)
|
||||
LIBS = base
|
Loading…
Reference in New Issue
Block a user