3 * \brief Interrupt functionality
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)
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.
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.
27 #include <l4/sys/kernel_object.h>
28 #include <l4/sys/ipc.h>
31 * \defgroup l4_irq_api IRQs
32 * \ingroup l4_kernel_object_api
34 * \brief The IRQ and IRQ class.
36 * <c>\#include <l4/sys/irq.h></c>
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
45 * IRQ objects can be created using a Factory, see \ref l4_factory_api
46 * (l4_factory_create_irq()).
54 L4_IRQ_OP_TRIGGER = 2,
60 * \brief Attach to an interrupt source.
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.
68 * \return Syscall return tag
71 l4_irq_attach(l4_cap_idx_t irq, l4_umword_t label,
72 l4_cap_idx_t thread) L4_NOTHROW;
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;
82 * \brief Chain an IRQ to another master IRQ source.
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
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.
99 * \return Syscall return tag
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;
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;
113 * \brief Detach from an interrupt source.
114 * \ingroup l4_irq_api
116 * \param irq IRQ to detach from.
118 * \return Syscall return tag
120 L4_INLINE l4_msgtag_t
121 l4_irq_detach(l4_cap_idx_t irq) L4_NOTHROW;
126 L4_INLINE l4_msgtag_t
127 l4_irq_detach_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
131 * \brief Trigger an IRQ.
132 * \ingroup l4_irq_api
134 * \param irq IRQ to trigger.
135 * \pre \a irq must be a reference to an IRQ.
137 * \return Syscall return tag, note this is a send only operation, i.e. there
138 * is no return value except for failed sending.
140 L4_INLINE l4_msgtag_t
141 l4_irq_trigger(l4_cap_idx_t irq) L4_NOTHROW;
146 L4_INLINE l4_msgtag_t
147 l4_irq_trigger_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
150 * \brief Unmask and wait for specified IRQ.
151 * \ingroup l4_irq_api
153 * \param irq IRQ to wait for.
156 * \return Syscall return tag
158 L4_INLINE l4_msgtag_t
159 l4_irq_receive(l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW;
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;
168 * \brief Unmask IRQ and wait for any message.
169 * \ingroup l4_irq_api
171 * \param irq IRQ to wait for.
172 * \param label Receive label.
175 * \return Syscall return tag
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;
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;
190 * \ingroup l4_irq_api
192 * \param irq IRQ to unmask.
194 * \return Syscall return tag
196 * \note l4_irq_wait and l4_irq_receive are doing the unmask themselves.
198 L4_INLINE l4_msgtag_t
199 l4_irq_unmask(l4_cap_idx_t irq) L4_NOTHROW;
204 L4_INLINE l4_msgtag_t
205 l4_irq_unmask_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
207 /**************************************************************************
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
215 l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
216 m->mr[0] = L4_IRQ_OP_ATTACH;
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);
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
227 l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
228 m->mr[0] = L4_IRQ_OP_CHAIN;
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);
235 L4_INLINE l4_msgtag_t
236 l4_irq_detach_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
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);
242 L4_INLINE l4_msgtag_t
243 l4_irq_trigger_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
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);
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
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);
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
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),
266 L4_INLINE l4_msgtag_t
267 l4_irq_unmask_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
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);
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
278 return l4_irq_attach_u(irq, label, thread, l4_utcb());
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
285 return l4_irq_chain_u(irq, label, slave, l4_utcb());
288 L4_INLINE l4_msgtag_t
289 l4_irq_detach(l4_cap_idx_t irq) L4_NOTHROW
291 return l4_irq_detach_u(irq, l4_utcb());
294 L4_INLINE l4_msgtag_t
295 l4_irq_trigger(l4_cap_idx_t irq) L4_NOTHROW
297 return l4_irq_trigger_u(irq, l4_utcb());
300 L4_INLINE l4_msgtag_t
301 l4_irq_receive(l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW
303 return l4_irq_receive_u(irq, to, l4_utcb());
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
310 return l4_irq_wait_u(irq, label, to, l4_utcb());
313 L4_INLINE l4_msgtag_t
314 l4_irq_unmask(l4_cap_idx_t irq) L4_NOTHROW
316 return l4_irq_unmask_u(irq, l4_utcb());