L4Re – L4 Runtime Environment
icu_svr
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2009-2014 Alexander Warg <alexander.warg@kernkonzept.com>
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  *
9  * As a special exception, you may use this file as part of a free software
10  * library without restriction. Specifically, if other files instantiate
11  * templates or use macros or inline functions from this file, or you compile
12  * this file and link it with other files to produce an executable, this
13  * file does not by itself cause the resulting executable to be covered by
14  * the GNU General Public License. This exception does not however
15  * invalidate any other reasons why the executable file might be covered by
16  * the GNU General Public License.
17  */
18 
19 #pragma once
20 
21 
22 #include <l4/sys/types.h>
23 
24 #include <l4/sys/icu>
25 #include <l4/sys/task>
26 #include <l4/re/env>
27 #include <l4/re/util/cap_alloc>
28 #include <l4/sys/cxx/ipc_legacy>
29 
30 namespace L4Re { namespace Util {
31 
32 template< typename ICU >
33 class Icu_svr
34 {
35 private:
36  ICU const *this_icu() const { return static_cast<ICU const *>(this); }
37  ICU *this_icu() { return static_cast<ICU*>(this); }
38 
39 public:
40  L4_RPC_LEGACY_DISPATCH(L4::Icu);
41 
42  int op_bind(L4::Icu::Rights, l4_umword_t irqnum,
43  L4::Ipc::Snd_fpage irq_fp);
44  int op_unbind(L4::Icu::Rights, l4_umword_t irqnum,
45  L4::Ipc::Snd_fpage irq_fp);
46  int op_info(L4::Icu::Rights, L4::Icu::_Info &info);
47  int op_msi_info(L4::Icu::Rights, l4_umword_t irqnum,
48  l4_uint64_t source, l4_icu_msi_info_t &info);
49  int op_mask(L4::Icu::Rights, l4_umword_t irqnum);
50  int op_unmask(L4::Icu::Rights, l4_umword_t irqnum);
51  int op_set_mode(L4::Icu::Rights, l4_umword_t, l4_umword_t)
52  { return 0; }
53 };
54 
55 template<typename ICU> inline
56 int
57 Icu_svr<ICU>::op_bind(L4::Icu::Rights, l4_umword_t irqnum,
58  L4::Ipc::Snd_fpage irq_fp)
59 {
60  typename ICU::Irq *irq = this_icu()->icu_get_irq(irqnum);
61  if (!irq)
62  return -L4_EINVAL;
63 
64  return irq->bind(this_icu(), irq_fp);
65 }
66 
67 template<typename ICU> inline
68 int
69 Icu_svr<ICU>::op_unbind(L4::Icu::Rights, l4_umword_t irqnum,
70  L4::Ipc::Snd_fpage irq_fp)
71 {
72  typename ICU::Irq *irq = this_icu()->icu_get_irq(irqnum);
73  if (!irq)
74  return -L4_EINVAL;
75 
76  return irq->unbind(this_icu(), irq_fp);
77 }
78 
79 template<typename ICU> inline
80 int
81 Icu_svr<ICU>::op_info(L4::Icu::Rights, L4::Icu::_Info &info)
82 {
83  l4_icu_info_t i;
84  this_icu()->icu_get_info(&i);
85  info.features = i.features;
86  info.nr_irqs = i.nr_irqs;
87  info.nr_msis = i.nr_msis;
88  return 0;
89 }
90 
91 template<typename ICU> inline
92 int
93 Icu_svr<ICU>::op_msi_info(L4::Icu::Rights, l4_umword_t irqnum,
94  l4_uint64_t source, l4_icu_msi_info_t &info)
95 {
96  typename ICU::Irq *irq = this_icu()->icu_get_irq(irqnum);
97  if (!irq)
98  return -L4_EINVAL;
99  return irq->msi_info(source, &info);
100 }
101 
102 template<typename ICU> inline
103 int
104 Icu_svr<ICU>::op_mask(L4::Icu::Rights, l4_umword_t irqnum)
105 {
106  typename ICU::Irq *irq = this_icu()->icu_get_irq(irqnum);
107  if (irq)
108  irq->mask(true);
109  return -L4_ENOREPLY;
110 }
111 
112 template<typename ICU> inline
113 int
114 Icu_svr<ICU>::op_unmask(L4::Icu::Rights, l4_umword_t irqnum)
115 {
116  typename ICU::Irq *irq = this_icu()->icu_get_irq(irqnum);
117  if (irq)
118  irq->mask(false);
119  return -L4_ENOREPLY;
120 }
121 
122 
123 template< typename ICU >
124 class Icu_cap_array_svr : public Icu_svr<ICU>
125 {
126 protected:
127  static void free_irq_cap(L4::Cap<L4::Irq> &cap)
128  {
129  if (cap)
130  {
132  cap.invalidate();
133  }
134  }
135 
136 public:
137  class Irq
138  {
139  public:
140  Irq() {}
141  ~Irq() { ICU::free_irq_cap(_cap); }
142 
143  void trigger() const
144  { if (_cap) _cap->trigger(); }
145 
146  int bind(ICU *, L4::Ipc::Snd_fpage const &irq_fp);
147  int unbind(ICU *, L4::Ipc::Snd_fpage const &irq_fp);
148  void mask(bool mask) const
149  { (void)mask; }
150 
151  int msi_info(l4_uint64_t, l4_icu_msi_info_t *) const
152  { return -L4_EINVAL; }
153 
154  L4::Cap<L4::Irq> cap() const { return _cap; }
155 
156  private:
157  L4::Cap<L4::Irq> _cap;
158  };
159 
160 private:
161  Irq *_irqs;
162  unsigned _nr_irqs;
163 
164 public:
165 
166  Icu_cap_array_svr(unsigned nr_irqs, Irq *irqs)
167  : _irqs(irqs), _nr_irqs(nr_irqs)
168  {}
169 
170  Irq *icu_get_irq(l4_umword_t irqnum)
171  {
172  if (irqnum >= _nr_irqs)
173  return 0;
174 
175  return _irqs + irqnum;
176  }
177 
178  void icu_get_info(l4_icu_info_t *inf)
179  {
180  inf->features = 0;
181  inf->nr_irqs = _nr_irqs;
182  inf->nr_msis = 0;
183  }
184 };
185 
186 template< typename ICU >
187 int
188 Icu_cap_array_svr<ICU>::Irq::bind(ICU *cfb, L4::Ipc::Snd_fpage const &irq_fp)
189 {
190  if (!irq_fp.cap_received())
191  return -L4_EINVAL;
192 
193  L4::Cap<L4::Irq> irq = cfb->server_iface()->template rcv_cap<L4::Irq>(0);
194  if (!irq)
195  return -L4_EINVAL;
196 
197  int r = cfb->server_iface()->realloc_rcv_cap(0);
198  if (r < 0)
199  return r;
200 
201  ICU::free_irq_cap(_cap);
202  _cap = irq;
203  return 0;
204 }
205 
206 template< typename ICU >
207 int
208 Icu_cap_array_svr<ICU>::Irq::unbind(ICU *, L4::Ipc::Snd_fpage const &/*irq_fp*/)
209 {
210  ICU::free_irq_cap(_cap);
212  return 0;
213 }
214 
215 
216 }}
bool free(L4::Cap< void > cap, l4_cap_idx_t task=L4_INVALID_CAP, unsigned unmap_flags=L4_FP_ALL_SPACES) noexcept
Free the capability.
void invalidate() noexcept
Set this capability to invalid (L4_INVALID_CAP).
Definition: capability.h:137
C++ Icu interface.
Definition: irq:239
Generic RPC wrapper for L4 flex-pages.
Definition: ipc_types:322
bool cap_received() const noexcept
Check if the capability has been mapped.
Definition: ipc_types:438
Environment interface.
unsigned long l4_umword_t
Unsigned machine word.
Definition: l4int.h:51
unsigned long long l4_uint64_t
Unsigned 64bit value.
Definition: l4int.h:42
@ L4_EINVAL
Invalid argument.
Definition: err.h:56
@ L4_ENOREPLY
No reply.
Definition: err.h:65
Interrupt controller.
Common L4 ABI Data Types.
_Cap_alloc & cap_alloc
Capability allocator.
L4Re C++ Interfaces.
Definition: cmd_control:15
Info structure for an ICU.
Definition: icu.h:160
unsigned nr_msis
The number of MSI vectors supported by the ICU,.
Definition: icu.h:176
unsigned nr_irqs
The number of IRQ lines supported by the ICU,.
Definition: icu.h:171
unsigned features
Feature flags.
Definition: icu.h:166
Info to use for a specific MSI.
Definition: icu.h:181
Common task related definitions.
Capability allocator.