]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4sys/include/irq.h
64490b9d6ce9512d2eac042dd093cee861a297f4
[l4.git] / l4 / pkg / l4sys / include / irq.h
1 /**
2  * \file
3  * \brief Interrupt functionality
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  * \brief The IRQ and IRQ class.
35  *
36  * <c>\#include <l4/sys/irq.h></c>
37  *
38  * The IRQ class provides access to abstract interrupts
39  * provided by the micro kernel. Interrupts may be hardware interrupts
40  * provided by the platform interrupt controller, virtual device interrupts
41  * provided by the micro kernel virtual devices (virtual serial or trace
42  * buffer), or IRQs (virtual interrupts that can be triggered by user
43  * programs).
44  *
45  * IRQ objects can be created using a Factory, see \ref l4_factory_api
46  * (l4_factory_create_irq()).
47  *
48  */
49
50 /**
51  * \brief Attach to an interrupt source.
52  * \ingroup l4_irq_api
53  *
54  * \param irq    IRQ to attach to.
55  * \param label  Identifier of the IRQ.
56  * \param thread Thread to attach the interrupt to.
57  *
58  * \return Syscall return tag
59  */
60 L4_INLINE l4_msgtag_t
61 l4_irq_attach(l4_cap_idx_t irq, l4_umword_t label,
62               l4_cap_idx_t thread) L4_NOTHROW;
63
64 /**
65  * \internal
66  */
67 L4_INLINE l4_msgtag_t
68 l4_irq_attach_u(l4_cap_idx_t irq, l4_umword_t label,
69                 l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW;
70
71 /**
72  * \brief Chain an IRQ to another master IRQ source.
73  * \ingroup l4_irq_api
74  *
75  * The chaining feature of IRQ objects allows to deal with shared IRQs.
76  * For chaining IRQs there must be a master IRQ object, bound to the
77  * real IRQ source. Note, the master IRQ must not have a thread attached to it.
78  * This function allows to add a limited number of slave IRQs to this master
79  * IRQ, with the semantics that each of the slave IRQs is triggered whenever
80  * the master IRQ is triggered. The master IRQ will be masked automatically
81  * when an IRQ is delivered and shall be unmasked when all attached slave IRQs
82  * are unmasked.
83  *
84  * \param irq    The master IRQ object.
85  * \param label  Identifier of the IRQ.
86  * \param slave  The slave that shall be attached to the master.
87  *
88  * \return Syscall return tag
89  */
90 L4_INLINE l4_msgtag_t
91 l4_irq_chain(l4_cap_idx_t irq, l4_umword_t label,
92              l4_cap_idx_t slave) L4_NOTHROW;
93
94 /**
95  * \internal
96  */
97 L4_INLINE l4_msgtag_t
98 l4_irq_chain_u(l4_cap_idx_t irq, l4_umword_t label,
99                l4_cap_idx_t slave, l4_utcb_t *utcb) L4_NOTHROW;
100
101 /**
102  * \brief Detach from an interrupt source.
103  * \ingroup l4_irq_api
104  *
105  * \param irq  IRQ to detach from.
106  *
107  * \return Syscall return tag
108  */
109 L4_INLINE l4_msgtag_t
110 l4_irq_detach(l4_cap_idx_t irq) L4_NOTHROW;
111
112 /**
113  * \internal
114  */
115 L4_INLINE l4_msgtag_t
116 l4_irq_detach_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
117
118
119 /**
120  * \brief Trigger an IRQ.
121  * \ingroup l4_irq_api
122  *
123  * \param irq    IRQ to trigger.
124  * \pre \a irq must be a reference to an IRQ.
125  *
126  * \return Syscall return tag.
127  *
128  * Note that this function is a send only operation, i.e. there is no return
129  * value except for a failed send operation. Especially l4_error() will
130  * return an error value from the message tag which still contains the IRQ
131  * protocol used for the send operation.
132  *
133  * Use l4_ipc_error() to check for (send) errors.
134  */
135 L4_INLINE l4_msgtag_t
136 l4_irq_trigger(l4_cap_idx_t irq) L4_NOTHROW;
137
138 /**
139  * \internal
140  */
141 L4_INLINE l4_msgtag_t
142 l4_irq_trigger_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
143
144 /**
145  * \brief Unmask and wait for specified IRQ.
146  * \ingroup l4_irq_api
147  *
148  * \param irq   IRQ to wait for.
149  * \param to    Timeout.
150  *
151  * \return Syscall return tag
152  */
153 L4_INLINE l4_msgtag_t
154 l4_irq_receive(l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW;
155
156 /**
157  * \internal
158  */
159 L4_INLINE l4_msgtag_t
160 l4_irq_receive_u(l4_cap_idx_t irq, l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW;
161
162 /**
163  * \brief Unmask IRQ and wait for any message.
164  * \ingroup l4_irq_api
165  *
166  * \param irq   IRQ to wait for.
167  * \param label Receive label.
168  * \param to    Timeout.
169  *
170  * \return Syscall return tag
171  */
172 L4_INLINE l4_msgtag_t
173 l4_irq_wait(l4_cap_idx_t irq, l4_umword_t *label,
174             l4_timeout_t to) L4_NOTHROW;
175
176 /**
177  * \internal
178  */
179 L4_INLINE l4_msgtag_t
180 l4_irq_wait_u(l4_cap_idx_t irq, l4_umword_t *label,
181               l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW;
182
183 /**
184  * \brief Unmask IRQ.
185  * \ingroup l4_irq_api
186  *
187  * \param irq   IRQ to unmask.
188  *
189  * \return Syscall return tag
190  *
191  * \note l4_irq_wait and l4_irq_receive are doing the unmask themselves.
192  */
193 L4_INLINE l4_msgtag_t
194 l4_irq_unmask(l4_cap_idx_t irq) L4_NOTHROW;
195
196 /**
197  * \internal
198  */
199 L4_INLINE l4_msgtag_t
200 l4_irq_unmask_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
201
202 /**
203  * \internal
204  */
205 enum L4_irq_op
206 {
207   L4_IRQ_OP_ATTACH    = 1,
208   L4_IRQ_OP_TRIGGER   = 2,
209   L4_IRQ_OP_CHAIN     = 3,
210   L4_IRQ_OP_EOI       = 4,
211 };
212
213 /**************************************************************************
214  * Implementations
215  */
216
217 L4_INLINE l4_msgtag_t
218 l4_irq_attach_u(l4_cap_idx_t irq, l4_umword_t label,
219                 l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW
220 {
221   l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
222   m->mr[0] = L4_IRQ_OP_ATTACH;
223   m->mr[1] = label;
224   m->mr[2] = l4_map_obj_control(0, 0);
225   m->mr[3] = l4_obj_fpage(thread, 0, L4_FPAGE_RWX).raw;
226   return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 2, 1, 0), L4_IPC_NEVER);
227 }
228
229 L4_INLINE l4_msgtag_t
230 l4_irq_chain_u(l4_cap_idx_t irq, l4_umword_t label,
231                l4_cap_idx_t slave, l4_utcb_t *utcb) L4_NOTHROW
232 {
233   l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
234   m->mr[0] = L4_IRQ_OP_CHAIN;
235   m->mr[1] = label;
236   m->mr[2] = l4_map_obj_control(0, 0);
237   m->mr[3] = l4_obj_fpage(slave, 0, L4_FPAGE_RWX).raw;
238   return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 2, 1, 0), L4_IPC_NEVER);
239 }
240
241 L4_INLINE l4_msgtag_t
242 l4_irq_detach_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
243 {
244   l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_ATTACH;
245   return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), L4_IPC_NEVER);
246 }
247
248 L4_INLINE l4_msgtag_t
249 l4_irq_trigger_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
250 {
251   l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_TRIGGER;
252   return l4_ipc_send(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0),
253                      L4_IPC_BOTH_TIMEOUT_0);
254 }
255
256 L4_INLINE l4_msgtag_t
257 l4_irq_receive_u(l4_cap_idx_t irq, l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW
258 {
259   l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_EOI;
260   return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), to);
261 }
262
263 L4_INLINE l4_msgtag_t
264 l4_irq_wait_u(l4_cap_idx_t irq, l4_umword_t *label,
265             l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW
266 {
267   l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_EOI;
268   return l4_ipc_send_and_wait(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0),
269                               label, to);
270 }
271
272 L4_INLINE l4_msgtag_t
273 l4_irq_unmask_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
274 {
275   l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_EOI;
276   return l4_ipc_send(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), L4_IPC_NEVER);
277 }
278
279
280 L4_INLINE l4_msgtag_t
281 l4_irq_attach(l4_cap_idx_t irq, l4_umword_t label,
282               l4_cap_idx_t thread) L4_NOTHROW
283 {
284   return l4_irq_attach_u(irq, label, thread, l4_utcb());
285 }
286
287 L4_INLINE l4_msgtag_t
288 l4_irq_chain(l4_cap_idx_t irq, l4_umword_t label,
289              l4_cap_idx_t slave) L4_NOTHROW
290 {
291   return l4_irq_chain_u(irq, label, slave, l4_utcb());
292 }
293
294 L4_INLINE l4_msgtag_t
295 l4_irq_detach(l4_cap_idx_t irq) L4_NOTHROW
296 {
297   return l4_irq_detach_u(irq, l4_utcb());
298 }
299
300 L4_INLINE l4_msgtag_t
301 l4_irq_trigger(l4_cap_idx_t irq) L4_NOTHROW
302 {
303   return l4_irq_trigger_u(irq, l4_utcb());
304 }
305
306 L4_INLINE l4_msgtag_t
307 l4_irq_receive(l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW
308 {
309   return l4_irq_receive_u(irq, to, l4_utcb());
310 }
311
312 L4_INLINE l4_msgtag_t
313 l4_irq_wait(l4_cap_idx_t irq, l4_umword_t *label,
314             l4_timeout_t to) L4_NOTHROW
315 {
316   return l4_irq_wait_u(irq, label, to, l4_utcb());
317 }
318
319 L4_INLINE l4_msgtag_t
320 l4_irq_unmask(l4_cap_idx_t irq) L4_NOTHROW
321 {
322   return l4_irq_unmask_u(irq, l4_utcb());
323 }
324