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