/* * \brief Interface for irq controllers * \author Martin stein * \date 2010-06-21 */ /* * Copyright (C) 2010-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 _KERNEL__INCLUDE__GENERIC__IRQ_CONTROLLER_H_ #define _KERNEL__INCLUDE__GENERIC__IRQ_CONTROLLER_H_ #include #include #include #include namespace Kernel { enum { IRQ_CONTROLLER__VERBOSE = 0, BYTE_WIDTH=8, }; template class Irq_controller_tpl : public DEVICE_T { protected: /************************* * Kernel_exit interface * *************************/ inline void _on_kernel_exit(); public: /** * Returns occured IRQ ID with highest priority and masks it */ inline Irq_id get_irq(); /** * Release IRQ and unmask it */ inline void ack_irq(Irq_id const & i); Irq_controller_tpl(typename DEVICE_T::Constr_arg const & dca); }; typedef Irq_controller_tpl Irq_controller; class Irq_allocator : public Id_allocator { typedef Id_allocator Allocator; Irq_controller * const _controller; public: /** * Error-codes that are returned by members */ enum Error { NO_ERROR = 0, HOLDER_DOESNT_OWN_IRQ = -1, IRQ_IS_PENDING_YET = -2, ALLOCATOR_ERROR = -3 }; /** * Constructor */ Irq_allocator(Irq_controller * const ic) : _controller(ic) { } /** * Free IRQ if the TID-according thread owns it */ inline Error free(Thread * const t, Irq_id irq); /** * Free IRQ if the TID-according thread owns it */ inline Error allocate(Thread * const t, Irq_id irq); }; /** * Pointer to kernels static IRQ allocator */ Irq_allocator * const irq_allocator(); /** * Pointer to kernels static IRQ controller */ Irq_controller * const irq_controller(); } template Kernel::Irq_controller_tpl::Irq_controller_tpl(typename DEVICE_T::Constr_arg const & dca) : DEVICE_T(dca) { } template Kernel::Irq_id Kernel::Irq_controller_tpl::get_irq() { Irq_id const i = DEVICE_T::next_irq(); DEVICE_T::mask(i); return i; } template void Kernel::Irq_controller_tpl::ack_irq(Irq_id const & i) { DEVICE_T::release(i); DEVICE_T::unmask(i); } Kernel::Irq_allocator::Error Kernel::Irq_allocator::allocate(Thread * const t, Irq_id irq) { if (_controller->pending(irq)) { return IRQ_IS_PENDING_YET; } if (!Allocator::allocate(t, irq)) { return ALLOCATOR_ERROR; } _controller->unmask(irq); return NO_ERROR; }; Kernel::Irq_allocator::Error Kernel::Irq_allocator::free(Thread * const t, Irq_id irq) { if (_controller->pending(irq)) { return IRQ_IS_PENDING_YET; } Allocator::free(irq); _controller->mask(irq); return NO_ERROR; }; #endif /* _KERNEL__INCLUDE__GENERIC__IRQ_CONTROLLER_H_ */