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
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)
43 * IRQ objects can be created using a factory, see the \ref l4_factory_api API
44 * (use l4_factory_create_irq()).
46 * \includefile{l4/sys/irq.h}
48 * For the C++ interface refer to the L4::Irq API for an overview.
52 * Attach a thread to an interrupt source.
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.
59 * \return Syscall return tag
62 l4_irq_attach(l4_cap_idx_t irq, l4_umword_t label,
63 l4_cap_idx_t thread) L4_NOTHROW;
67 * \copybrief L4::Irq::attach
68 * \param irq IRQ object where `thread` is attached to.
69 * \copydetails L4::Irq::attach
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;
76 * Chain an IRQ to another master IRQ source.
79 * \param irq The master IRQ object.
80 * \param slave The slave that shall be attached to the master.
82 * \return Syscall return tag
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.
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
95 l4_irq_mux_chain(l4_cap_idx_t irq, l4_cap_idx_t slave) L4_NOTHROW;
99 * \copybrief L4::Irq_mux::chain
100 * \param irq The master IRQ object.
101 * \copydetails L4::Irq_mux::chain
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;
108 * Detach from an interrupt source.
109 * \ingroup l4_irq_api
111 * \param irq The IRQ object that shall be detached.
113 * \return Syscall return tag
115 L4_INLINE l4_msgtag_t
116 l4_irq_detach(l4_cap_idx_t irq) L4_NOTHROW;
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
124 L4_INLINE l4_msgtag_t
125 l4_irq_detach_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
130 * \ingroup l4_irq_api
132 * \param irq The IRQ object that shall be triggered.
134 * \return Syscall return tag.
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.
141 * Use l4_ipc_error() to check for (send) errors.
143 L4_INLINE l4_msgtag_t
144 l4_irq_trigger(l4_cap_idx_t irq) L4_NOTHROW;
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
152 L4_INLINE l4_msgtag_t
153 l4_irq_trigger_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
156 * Unmask and wait for specified IRQ.
157 * \ingroup l4_irq_api
159 * \param irq The IRQ object that shall be unmasked.
162 * \return Syscall return tag
164 L4_INLINE l4_msgtag_t
165 l4_irq_receive(l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW;
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
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;
177 * Unmask IRQ and wait for any message.
178 * \ingroup l4_irq_api
180 * \param irq The IRQ object that shall be unmasked.
181 * \param label Receive label.
184 * \return Syscall return tag
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;
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
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;
202 * \ingroup l4_irq_api
204 * \param irq The IRQ object that shall be unmasked.
206 * \return Syscall return tag
208 * \note l4_irq_wait() and l4_irq_receive() are doing the unmask themselves.
210 L4_INLINE l4_msgtag_t
211 l4_irq_unmask(l4_cap_idx_t irq) L4_NOTHROW;
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
219 L4_INLINE l4_msgtag_t
220 l4_irq_unmask_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW;
225 enum L4_irq_sender_op
227 L4_IRQ_SENDER_OP_ATTACH = 0,
228 L4_IRQ_SENDER_OP_DETACH = 1
236 L4_IRQ_MUX_OP_CHAIN = 0
244 L4_IRQ_OP_TRIGGER = 2,
248 /**************************************************************************
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
257 l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
258 m->mr[0] = L4_IRQ_SENDER_OP_ATTACH;
261 if (!l4_is_invalid_cap(thread))
264 m->mr[2] = l4_map_obj_control(0, 0);
265 m->mr[3] = l4_obj_fpage(thread, 0, L4_FPAGE_RWX).raw;
267 return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ_SENDER, 2, items, 0),
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
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),
283 L4_INLINE l4_msgtag_t
284 l4_irq_detach_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
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),
291 L4_INLINE l4_msgtag_t
292 l4_irq_trigger_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
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);
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
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);
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
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),
315 L4_INLINE l4_msgtag_t
316 l4_irq_unmask_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW
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);
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
327 return l4_irq_attach_u(irq, label, thread, l4_utcb());
330 L4_INLINE l4_msgtag_t
331 l4_irq_mux_chain(l4_cap_idx_t irq, l4_cap_idx_t slave) L4_NOTHROW
333 return l4_irq_mux_chain_u(irq, slave, l4_utcb());
336 L4_INLINE l4_msgtag_t
337 l4_irq_detach(l4_cap_idx_t irq) L4_NOTHROW
339 return l4_irq_detach_u(irq, l4_utcb());
342 L4_INLINE l4_msgtag_t
343 l4_irq_trigger(l4_cap_idx_t irq) L4_NOTHROW
345 return l4_irq_trigger_u(irq, l4_utcb());
348 L4_INLINE l4_msgtag_t
349 l4_irq_receive(l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW
351 return l4_irq_receive_u(irq, to, l4_utcb());
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
358 return l4_irq_wait_u(irq, label, to, l4_utcb());
361 L4_INLINE l4_msgtag_t
362 l4_irq_unmask(l4_cap_idx_t irq) L4_NOTHROW
364 return l4_irq_unmask_u(irq, l4_utcb());