/* * \brief Core-specific instance of the IRQ session interface * \author Christian Helmuth * \date 2007-09-13 */ /* * Copyright (C) 2007-2013 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ #ifndef _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ #define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ #include #include #include #include #include #include /* XXX Notes * * - each H/W IRQ is an irq thread * - each irq thread has an Rpc_entrypoint * -> irq thread is special Server_activation * -> IRQ session is Rpc_object * * - session("IRQ", "irq_num=") -> Native_capability(irq_thread, cap) * - cap must be generated at CAP * - cap must be managed by irq_thread-local Rpc_entrypoint * * - irq thread states * 1. wait_for_client --[ client calls wait_for_irq ]--> 2. * 2. wait_for_irq --[ kernel signals irq ]--> 3. * 3. irq_occured --[ inform client about occurence ]--> 1. * * - irq thread roles * - Irq_server (Ipc_server) for client * - Fiasco_irq_client (Ipc_client) at kernel */ namespace Genode { class Irq_session_component : public Rpc_object, public List::Element { private: struct Irq_control { GENODE_RPC(Rpc_associate_to_irq, bool, associate_to_irq, unsigned); GENODE_RPC_INTERFACE(Rpc_associate_to_irq); }; struct Irq_control_client : Rpc_client { Irq_control_client(Capability cap) : Rpc_client(cap) { } bool associate_to_irq(unsigned irq_number) { return call(irq_number); } }; struct Irq_control_component : Rpc_object { /** * Associate to IRQ at Fiasco * * This is executed by the IRQ server activation itself. */ bool associate_to_irq(unsigned irq_number); }; unsigned _irq_number; Range_allocator *_irq_alloc; enum { STACK_SIZE = 2048 }; Rpc_entrypoint _ep; /* * On Pistachio, an IRQ is unmasked right after attaching. * Hence, the kernel may send an IRQ IPC when the IRQ hander is * not explicitly waiting for an IRQ but when it is waiting for * a client's 'wait_for_irq' RPC call. To avoid this conflict, we * lazily associate to the IRQ when calling the 'wait_for_irq' * function for the first time. We use the '_irq_attached' flag * for detecting the first call. On other kernels, this variable * may be unused. */ unsigned _irq_attached; /* true if IRQ is already attached */ /******************************************** ** IRQ control server (internal use only) ** ********************************************/ Irq_control_component _control_component; /* ctrl component */ Capability _control_cap; /* capability for ctrl server */ Irq_control_client _control_client; /* ctrl client */ Capability _irq_cap; /* capability for IRQ */ public: /** * Constructor * * \param cap_session capability session to use * \param irq_alloc platform-dependent IRQ allocator * \param args session construction arguments */ Irq_session_component(Cap_session *cap_session, Range_allocator *irq_alloc, const char *args); /** * Destructor */ ~Irq_session_component(); /** * Return capability to this session * * If an initialization error occurs, returned _cap is invalid. */ Capability cap() const { return _irq_cap; } /*************************** ** Irq session interface ** ***************************/ void wait_for_irq(); }; } #endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */