]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/l4sys/include/irq.h
Update
[l4.git] / l4 / pkg / l4re-core / l4sys / include / irq.h
1 /**
2  * \file
3  * C Irq interface
4  * \ingroup l4_api
5  */
6 /*
7  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8  *               Alexander Warg <warg@os.inf.tu-dresden.de>,
9  *               Björn Döbel <doebel@os.inf.tu-dresden.de>
10  *     economic rights: Technische Universität Dresden (Germany)
11  *
12  * This file is part of TUD:OS and distributed under the terms of the
13  * GNU General Public License 2.
14  * Please see the COPYING-GPL-2 file for details.
15  *
16  * As a special exception, you may use this file as part of a free software
17  * library without restriction.  Specifically, if other files instantiate
18  * templates or use macros or inline functions from this file, or you compile
19  * this file and link it with other files to produce an executable, this
20  * file does not by itself cause the resulting executable to be covered by
21  * the GNU General Public License.  This exception does not however
22  * invalidate any other reasons why the executable file might be covered by
23  * the GNU General Public License.
24  */
25 #pragma once
26
27 #include <l4/sys/kernel_object.h>
28 #include <l4/sys/ipc.h>
29
30 /**
31  * \defgroup l4_irq_api IRQs
32  * \ingroup  l4_kernel_object_api
33  *
34  * C IRQ interface.
35  *
36  * The IRQ interface provides access to abstract interrupts provided by the
37  * microkernel. Interrupts may be
38  * - hardware interrupts provided by the platform interrupt controller,
39  * - virtual device interrupts provided by the microkernel's virtual devices
40  *   (virtual serial or trace buffer) or
41  * - virtual interrupts that can be triggered by user programs (IRQs)
42  *
43  * IRQ objects can be created using a factory, see the \ref l4_factory_api API
44  * (use l4_factory_create_irq()).
45  *
46  * \includefile{l4/sys/irq.h}
47  *
48  * For the C++ interface refer to the L4::Irq API for an overview.
49  */
50
51 /**
52  * Attach a thread to an interrupt source.
53  * \ingroup l4_irq_api
54  *
55  * \param irq     IRQ object where `thread` is attached to.
56  * \param label   Identifier of the IRQ.
57  * \param thread  The thread object to attach `irq` to.
58  *
59  * \return Syscall return tag
60  */
61 L4_INLINE l4_msgtag_t
62 l4_irq_attach(l4_cap_idx_t irq, l4_umword_t label,
63               l4_cap_idx_t thread) L4_NOTHROW;
64
65 /**
66  * \ingroup l4_irq_api
67  * \copybrief L4::Irq::attach
68  * \param irq  IRQ object where `thread` is attached to.
69  * \copydetails L4::Irq::attach
70  */
71 L4_INLINE l4_msgtag_t
72 l4_irq_attach_u(l4_cap_idx_t irq, l4_umword_t label,
73                 l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW;
74
75 /**
76  * Chain an IRQ to another master IRQ source.
77  * \ingroup l4_irq_api
78  *
79  * \param irq    The master IRQ object.
80  * \param slave  The slave that shall be attached to the master.
81  *
82  * \return Syscall return tag
83  *
84  * The chaining feature of IRQ objects allows to deal with shared IRQs. For
85  * chaining IRQs there must be a master IRQ object, bound to the real IRQ
86  * source. Note, the master IRQ must not have a thread attached to it.
87  *
88  * This function allows to add a limited number of slave IRQs to this master
89  * IRQ, with the semantics that each of the slave IRQs is triggered whenever
90  * the master IRQ is triggered. The master IRQ will be masked automatically
91  * when an IRQ is delivered and shall be unmasked when all attached slave IRQs
92  * are unmasked.
93  */
94 L4_INLINE l4_msgtag_t
95 l4_irq_mux_chain(l4_cap_idx_t irq, l4_cap_idx_t slave) L4_NOTHROW;
96
97 /**
98  * \ingroup l4_irq_api
99  * \copybrief L4::Irq_mux::chain
100  * \param irq  The master IRQ object.
101  * \copydetails L4::Irq_mux::chain
102  */
103 L4_INLINE l4_msgtag_t
104 l4_irq_mux_chain_u(l4_cap_idx_t irq, l4_cap_idx_t slave,
105                    l4_utcb_t *utcb) L4_NOTHROW;
106
107 /**
108  * Detach from an interrupt source.
109  * \ingroup l4_irq_api
110  *
111  * \param irq  The IRQ object that shall be detached.
112  *
113  * \return Syscall return tag
114  */
115 L4_INLINE l4_msgtag_t
116 l4_irq_detach(l4_cap_idx_t irq) L4_NOTHROW;
117
118 /**
119  * \ingroup l4_irq_api
120  * \copybrief L4::Irq::detach
121  * \param irq  The IRQ object that shall be detached.
122  * \copydetails L4::Irq::detach
123  */
124 L4_INLINE l4_msgtag_t
125 l4_irq_detach_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
126
127
128 /**
129  * Trigger an IRQ.
130  * \ingroup l4_irq_api
131  *
132  * \param irq  The IRQ object that shall be triggered.
133  *
134  * \return Syscall return tag.
135  *
136  * Note that this function is a send only operation, i.e. there is no return
137  * value except for a failed send operation. Especially l4_error() will
138  * return an error value from the message tag which still contains the IRQ
139  * protocol used for the send operation.
140  *
141  * Use l4_ipc_error() to check for (send) errors.
142  */
143 L4_INLINE l4_msgtag_t
144 l4_irq_trigger(l4_cap_idx_t irq) L4_NOTHROW;
145
146 /**
147  * \ingroup l4_irq_api
148  * \copybrief L4::Irq::trigger
149  * \param irq  The IRQ object that shall be triggered.
150  * \copydetails L4::Irq::trigger
151  */
152 L4_INLINE l4_msgtag_t
153 l4_irq_trigger_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
154
155 /**
156  * Unmask and wait for specified IRQ.
157  * \ingroup l4_irq_api
158  *
159  * \param irq  The IRQ object that shall be unmasked.
160  * \param to   Timeout.
161  *
162  * \return Syscall return tag
163  */
164 L4_INLINE l4_msgtag_t
165 l4_irq_receive(l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW;
166
167 /**
168  * \ingroup l4_irq_api
169  * \copybrief L4::Irq::receive
170  * \param irq  The IRQ object that shall be unmasked.
171  * \copydetails L4::Irq::receive
172  */
173 L4_INLINE l4_msgtag_t
174 l4_irq_receive_u(l4_cap_idx_t irq, l4_timeout_t timeout, l4_utcb_t *utcb) L4_NOTHROW;
175
176 /**
177  * Unmask IRQ and wait for any message.
178  * \ingroup l4_irq_api
179  *
180  * \param irq    The IRQ object that shall be unmasked.
181  * \param label  Receive label.
182  * \param to     Timeout.
183  *
184  * \return Syscall return tag
185  */
186 L4_INLINE l4_msgtag_t
187 l4_irq_wait(l4_cap_idx_t irq, l4_umword_t *label,
188             l4_timeout_t to) L4_NOTHROW;
189
190 /**
191  * \ingroup l4_irq_api
192  * \copybrief L4::Irq::wait
193  * \param irq  The IRQ object that shall be unmasked.
194  * \copydetails L4::Irq::wait
195  */
196 L4_INLINE l4_msgtag_t
197 l4_irq_wait_u(l4_cap_idx_t irq, l4_umword_t *label,
198               l4_timeout_t timeout, l4_utcb_t *utcb) L4_NOTHROW;
199
200 /**
201  * Unmask IRQ.
202  * \ingroup l4_irq_api
203  *
204  * \param irq  The IRQ object that shall be unmasked.
205  *
206  * \return Syscall return tag
207  *
208  * \note l4_irq_wait() and l4_irq_receive() are doing the unmask themselves.
209  */
210 L4_INLINE l4_msgtag_t
211 l4_irq_unmask(l4_cap_idx_t irq) L4_NOTHROW;
212
213 /**
214  * \ingroup l4_irq_api
215  * \copybrief L4::Irq::unmask
216  * \param irq  The IRQ object that shall be unmasked.
217  * \copydetails L4::Irq::unmask
218  */
219 L4_INLINE l4_msgtag_t
220 l4_irq_unmask_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
221
222 /**
223  * \internal
224  */
225 enum L4_irq_sender_op
226 {
227   L4_IRQ_SENDER_OP_ATTACH    = 0,
228   L4_IRQ_SENDER_OP_DETACH    = 1
229 };
230
231 /**
232  * \internal
233  */
234 enum L4_irq_mux_op
235 {
236   L4_IRQ_MUX_OP_CHAIN = 0
237 };
238
239 /**
240  * \internal
241  */
242 enum L4_irq_op
243 {
244   L4_IRQ_OP_TRIGGER   = 2,
245   L4_IRQ_OP_EOI       = 4
246 };
247
248 /**************************************************************************
249  * Implementations
250  */
251
252 L4_INLINE l4_msgtag_t
253 l4_irq_attach_u(l4_cap_idx_t irq, l4_umword_t label,
254                 l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW
255 {
256   int items = 0;
257   l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
258   m->mr[0] = L4_IRQ_SENDER_OP_ATTACH;
259   m->mr[1] = label;
260
261   if (!l4_is_invalid_cap(thread))
262     {
263       items = 1;
264       m->mr[2] = l4_map_obj_control(0, 0);
265       m->mr[3] = l4_obj_fpage(thread, 0, L4_FPAGE_RWX).raw;
266     }
267   return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ_SENDER, 2, items, 0),
268                      L4_IPC_NEVER);
269 }
270
271 L4_INLINE l4_msgtag_t
272 l4_irq_mux_chain_u(l4_cap_idx_t irq, l4_cap_idx_t slave,
273                    l4_utcb_t *utcb) L4_NOTHROW
274 {
275   l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
276   m->mr[0] = L4_IRQ_MUX_OP_CHAIN;
277   m->mr[1] = l4_map_obj_control(0, 0);
278   m->mr[2] = l4_obj_fpage(slave, 0, L4_FPAGE_RWX).raw;
279   return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ_MUX, 1, 1, 0),
280                      L4_IPC_NEVER);
281 }
282
283 L4_INLINE l4_msgtag_t
284 l4_irq_detach_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
285 {
286   l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_SENDER_OP_DETACH;
287   return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ_SENDER, 1, 0, 0),
288                      L4_IPC_NEVER);
289 }
290
291 L4_INLINE l4_msgtag_t
292 l4_irq_trigger_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
293 {
294   l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_TRIGGER;
295   return l4_ipc_send(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0),
296                      L4_IPC_BOTH_TIMEOUT_0);
297 }
298
299 L4_INLINE l4_msgtag_t
300 l4_irq_receive_u(l4_cap_idx_t irq, l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW
301 {
302   l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_EOI;
303   return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), to);
304 }
305
306 L4_INLINE l4_msgtag_t
307 l4_irq_wait_u(l4_cap_idx_t irq, l4_umword_t *label,
308             l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW
309 {
310   l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_EOI;
311   return l4_ipc_send_and_wait(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0),
312                               label, to);
313 }
314
315 L4_INLINE l4_msgtag_t
316 l4_irq_unmask_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
317 {
318   l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_EOI;
319   return l4_ipc_send(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), L4_IPC_NEVER);
320 }
321
322
323 L4_INLINE l4_msgtag_t
324 l4_irq_attach(l4_cap_idx_t irq, l4_umword_t label,
325               l4_cap_idx_t thread) L4_NOTHROW
326 {
327   return l4_irq_attach_u(irq, label, thread, l4_utcb());
328 }
329
330 L4_INLINE l4_msgtag_t
331 l4_irq_mux_chain(l4_cap_idx_t irq, l4_cap_idx_t slave) L4_NOTHROW
332 {
333   return l4_irq_mux_chain_u(irq, slave, l4_utcb());
334 }
335
336 L4_INLINE l4_msgtag_t
337 l4_irq_detach(l4_cap_idx_t irq) L4_NOTHROW
338 {
339   return l4_irq_detach_u(irq, l4_utcb());
340 }
341
342 L4_INLINE l4_msgtag_t
343 l4_irq_trigger(l4_cap_idx_t irq) L4_NOTHROW
344 {
345   return l4_irq_trigger_u(irq, l4_utcb());
346 }
347
348 L4_INLINE l4_msgtag_t
349 l4_irq_receive(l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW
350 {
351   return l4_irq_receive_u(irq, to, l4_utcb());
352 }
353
354 L4_INLINE l4_msgtag_t
355 l4_irq_wait(l4_cap_idx_t irq, l4_umword_t *label,
356             l4_timeout_t to) L4_NOTHROW
357 {
358   return l4_irq_wait_u(irq, label, to, l4_utcb());
359 }
360
361 L4_INLINE l4_msgtag_t
362 l4_irq_unmask(l4_cap_idx_t irq) L4_NOTHROW
363 {
364   return l4_irq_unmask_u(irq, l4_utcb());
365 }
366