Loading...
Searching...
No Matches
icu_svr
// vi:set ft=cpp: -*- Mode: C++ -*-
/*
* (c) 2009-2014 Alexander Warg <alexander.warg@kernkonzept.com>
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#include <l4/sys/types.h>
#include <l4/sys/icu>
#include <l4/sys/task>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <l4/sys/cxx/ipc_legacy>
namespace L4Re { namespace Util {
template< typename ICU >
class Icu_svr
{
private:
ICU const *this_icu() const { return static_cast<ICU const *>(this); }
ICU *this_icu() { return static_cast<ICU*>(this); }
public:
L4_RPC_LEGACY_DISPATCH(L4::Icu);
int op_bind(L4::Icu::Rights, l4_umword_t irqnum,
L4::Ipc::Snd_fpage irq_fp);
int op_unbind(L4::Icu::Rights, l4_umword_t irqnum,
L4::Ipc::Snd_fpage irq_fp);
int op_info(L4::Icu::Rights, L4::Icu::_Info &info);
int op_msi_info(L4::Icu::Rights, l4_umword_t irqnum,
l4_uint64_t source, l4_icu_msi_info_t &info);
int op_mask(L4::Icu::Rights, l4_umword_t irqnum);
int op_unmask(L4::Icu::Rights, l4_umword_t irqnum);
int op_set_mode(L4::Icu::Rights, l4_umword_t, l4_umword_t)
{ return 0; }
};
template<typename ICU> inline
int
Icu_svr<ICU>::op_bind(L4::Icu::Rights, l4_umword_t irqnum,
L4::Ipc::Snd_fpage irq_fp)
{
typename ICU::Irq *irq = this_icu()->icu_get_irq(irqnum);
if (!irq)
return -L4_EINVAL;
return irq->bind(this_icu(), irq_fp);
}
template<typename ICU> inline
int
Icu_svr<ICU>::op_unbind(L4::Icu::Rights, l4_umword_t irqnum,
L4::Ipc::Snd_fpage irq_fp)
{
typename ICU::Irq *irq = this_icu()->icu_get_irq(irqnum);
if (!irq)
return -L4_EINVAL;
return irq->unbind(this_icu(), irq_fp);
}
template<typename ICU> inline
int
Icu_svr<ICU>::op_info(L4::Icu::Rights, L4::Icu::_Info &info)
{
l4_icu_info_t i;
this_icu()->icu_get_info(&i);
info.features = i.features;
info.nr_irqs = i.nr_irqs;
info.nr_msis = i.nr_msis;
return 0;
}
template<typename ICU> inline
int
Icu_svr<ICU>::op_msi_info(L4::Icu::Rights, l4_umword_t irqnum,
l4_uint64_t source, l4_icu_msi_info_t &info)
{
typename ICU::Irq *irq = this_icu()->icu_get_irq(irqnum);
if (!irq)
return -L4_EINVAL;
return irq->msi_info(source, &info);
}
template<typename ICU> inline
int
Icu_svr<ICU>::op_mask(L4::Icu::Rights, l4_umword_t irqnum)
{
typename ICU::Irq *irq = this_icu()->icu_get_irq(irqnum);
if (irq)
irq->mask(true);
return -L4_ENOREPLY;
}
template<typename ICU> inline
int
Icu_svr<ICU>::op_unmask(L4::Icu::Rights, l4_umword_t irqnum)
{
typename ICU::Irq *irq = this_icu()->icu_get_irq(irqnum);
if (irq)
irq->mask(false);
return -L4_ENOREPLY;
}
template< typename ICU >
class Icu_cap_array_svr : public Icu_svr<ICU>
{
protected:
static void free_irq_cap(L4::Cap<L4::Irq> &cap)
{
if (cap)
{
L4Re::Util::cap_alloc.free(cap);
cap.invalidate();
}
}
public:
class Irq
{
public:
Irq() {}
~Irq() { ICU::free_irq_cap(_cap); }
void trigger() const
{
if (_cap)
_cap->trigger();
}
int bind(ICU *, L4::Ipc::Snd_fpage const &irq_fp);
int unbind(ICU *, L4::Ipc::Snd_fpage const &irq_fp);
void mask(bool /*mask*/) const
{ }
int msi_info(l4_uint64_t, l4_icu_msi_info_t *) const
{ return -L4_EINVAL; }
L4::Cap<L4::Irq> cap() const { return _cap; }
private:
L4::Cap<L4::Irq> _cap;
};
private:
Irq *_irqs;
unsigned _nr_irqs;
public:
Icu_cap_array_svr(unsigned nr_irqs, Irq *irqs)
: _irqs(irqs), _nr_irqs(nr_irqs)
{}
Irq *icu_get_irq(l4_umword_t irqnum)
{
if (irqnum >= _nr_irqs)
return 0;
return _irqs + irqnum;
}
void icu_get_info(l4_icu_info_t *inf)
{
inf->features = 0;
inf->nr_irqs = _nr_irqs;
inf->nr_msis = 0;
}
};
template< typename ICU >
int
Icu_cap_array_svr<ICU>::Irq::bind(ICU *cfb, L4::Ipc::Snd_fpage const &irq_fp)
{
if (!irq_fp.cap_received())
return -L4_EINVAL;
L4::Cap<L4::Irq> irq = cfb->server_iface()->template rcv_cap<L4::Irq>(0);
if (!irq)
return -L4_EINVAL;
int r = cfb->server_iface()->realloc_rcv_cap(0);
if (r < 0)
return r;
ICU::free_irq_cap(_cap);
_cap = irq;
return 0;
}
template< typename ICU >
int
Icu_cap_array_svr<ICU>::Irq::unbind(ICU *, L4::Ipc::Snd_fpage const &/*irq_fp*/)
{
ICU::free_irq_cap(_cap);
_cap = L4::Cap<L4::Irq>::Invalid;
return 0;
}
}}
L4Re::Util::_Cap_alloc::free
void free(L4::Cap< void > cap, l4_cap_idx_t task=L4_INVALID_CAP, unsigned unmap_flags=L4_FP_ALL_SPACES) noexcept override
Free a capability.
Definition cap_alloc_impl.h:85
L4::Cap_base::invalidate
void invalidate() noexcept
Set this capability to invalid (L4_INVALID_CAP).
Definition capability.h:142
L4::Cap_base::Invalid
@ Invalid
Invalid capability selector.
Definition capability.h:42
L4::Ipc::Snd_fpage::cap_received
bool cap_received() const noexcept
(Defined for return items only.) Check if at least one object capability has been mapped for this ite...
Definition ipc_types:496
env
Environment interface.
l4_umword_t
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
l4_uint64_t
unsigned long long l4_uint64_t
Unsigned 64bit value.
Definition l4int.h:31
L4_EINVAL
@ L4_EINVAL
Invalid argument.
Definition err.h:46
L4_ENOREPLY
@ L4_ENOREPLY
No reply.
Definition err.h:55
l4_icu_info_t
struct l4_icu_info_t l4_icu_info_t
Info structure for an ICU.
L4Re::Util::cap_alloc
_Cap_alloc & cap_alloc
Capability allocator.
l4_icu_msi_info_t
struct l4_icu_msi_info_t l4_icu_msi_info_t
Info to use for a specific MSI.
icu
Interrupt controller.
types.h
Common L4 ABI Data Types.
L4Re::Util
Documentation of the L4 Runtime Environment utility functionality in C++.
Definition l4re.dox:21
L4Re
L4Re C++ Interfaces.
Definition cmd_control:14
l4_icu_info_t::nr_msis
unsigned nr_msis
The number of MSI vectors supported by the ICU,.
Definition icu.h:180
l4_icu_info_t::nr_irqs
unsigned nr_irqs
The number of IRQ lines supported by the ICU,.
Definition icu.h:175
l4_icu_info_t::features
unsigned features
Feature flags.
Definition icu.h:170
task
Common task related definitions.
cap_alloc
Capability allocator.