genode/base-nova/src/core/irq_session_component.cc

75 lines
1.9 KiB
C++
Raw Normal View History

2011-12-22 16:19:25 +01:00
/*
* \brief Implementation of IRQ session component
* \author Norman Feske
* \author Sebastian Sumpf
* \date 2009-10-02
*/
/*
* Copyright (C) 2009-2011 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 <base/printf.h>
/* core includes */
#include <irq_root.h>
#include <platform.h>
/* NOVA includes */
#include <nova/syscalls.h>
#include <nova_util.h>
using namespace Genode;
void Irq_session_component::wait_for_irq()
{
Nova::sm_ctrl(_irq_number, Nova::SEMAPHORE_DOWN);
}
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, "irq")
{
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();
}
/* alloc slector where IRQ will be mapped */
_irq_number = cap_selector_allocator()->alloc();
/* since we run in APIC mode translate IRQ 0 (PIT) to 2 */
if (!irq_number)
irq_number = 2;
/* map IRQ number to selector */
int ret = map_local((Nova::Utcb *)Thread_base::myself()->utcb(),
Nova::Obj_crd(platform_specific()->gsi_base_sel() + irq_number, 0),
Nova::Obj_crd(_irq_number, 0),
true);
if (ret) {
PERR("Could not map IRQ %d", _irq_number);
throw Root::Unavailable();
}
/* assign IRQ to CPU */
enum { CPU = 0 };
Nova::assign_gsi(_irq_number, 0, CPU);
/* initialize capability */
_irq_cap = _ep.manage(this);
}
Irq_session_component::~Irq_session_component() { }