/* * \brief Core implementation of IRQ sessions * \author Christian Helmuth * \date 2007-09-13 * * FIXME ram quota missing */ /* * Copyright (C) 2007-2012 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. */ /* Genode includes */ #include #include /* core includes */ #include #include /* Fiasco includes */ namespace Fiasco { #include #include #include } using namespace Genode; bool Irq_session_component::Irq_control_component::associate_to_irq(unsigned irq_number) { using namespace Fiasco; int err; l4_threadid_t irq_tid; l4_umword_t dw0, dw1; l4_msgdope_t result; l4_make_taskid_from_irq(irq_number, &irq_tid); /* boost thread to IRQ priority */ enum { IRQ_PRIORITY = 0xC0 }; l4_sched_param_t param = {sp:{prio:IRQ_PRIORITY, small:0, state:0, time_exp:0, time_man:0}}; l4_threadid_t ext_preempter = L4_INVALID_ID; l4_threadid_t partner = L4_INVALID_ID; l4_sched_param_t old_param; l4_thread_schedule(l4_myself(), param, &ext_preempter, &partner, &old_param); err = l4_ipc_receive(irq_tid, L4_IPC_SHORT_MSG, &dw0, &dw1, L4_IPC_BOTH_TIMEOUT_0, &result); if (err != L4_IPC_RETIMEOUT) PERR("IRQ association failed"); return (err == L4_IPC_RETIMEOUT); } void Irq_session_component::wait_for_irq() { using namespace Fiasco; l4_threadid_t irq_tid; l4_umword_t dw0=0, dw1=0; l4_msgdope_t result; l4_make_taskid_from_irq(_irq_number, &irq_tid); do { l4_ipc_call(irq_tid, L4_IPC_SHORT_MSG, 0, 0, L4_IPC_SHORT_MSG, &dw0, &dw1, L4_IPC_NEVER, &result); if (L4_IPC_IS_ERROR(result)) PERR("Ipc error %lx", L4_IPC_ERROR(result)); } while (L4_IPC_IS_ERROR(result)); } Irq_session_component::Irq_session_component(Cap_session *cap_session, Range_allocator *irq_alloc, const char *args) : _irq_alloc(irq_alloc), _ep(cap_session, STACK_SIZE, "irqctrl"), _control_cap(_ep.manage(&_control_component)), _control_client(_control_cap) { bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false); if (shared) { PWRN("IRQ sharing not supported"); throw Root::Invalid_args(); } long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1); if (irq_number == -1 || !irq_alloc || irq_alloc->alloc_addr(1, irq_number) != Range_allocator::ALLOC_OK) { PERR("Unavailable IRQ %lx requested", irq_number); throw Root::Invalid_args(); } _irq_number = irq_number; if (!_control_client.associate_to_irq(irq_number)) { PWRN("IRQ association failed"); throw Root::Invalid_args(); } /* initialize capability */ _irq_cap = Irq_session_capability(_ep.manage(this)); } Irq_session_component::~Irq_session_component() { PERR("Implement me, immediately!"); }