From a8968330aff45e0b8cf278f49fa337d5fcb9bfd8 Mon Sep 17 00:00:00 2001 From: Alex AUVOLAT Date: Fri, 28 Mar 2014 17:09:15 +0100 Subject: Import and compile code for article 6.5 --- sos-code-article6.5/hwcore/irq.c | 100 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 sos-code-article6.5/hwcore/irq.c (limited to 'sos-code-article6.5/hwcore/irq.c') diff --git a/sos-code-article6.5/hwcore/irq.c b/sos-code-article6.5/hwcore/irq.c new file mode 100644 index 0000000..6722027 --- /dev/null +++ b/sos-code-article6.5/hwcore/irq.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2004 David Decotigny + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. +*/ +#include "idt.h" +#include "i8259.h" + +#include "irq.h" + +/** array of IRQ wrappers, defined in irq_wrappers.S */ +extern sos_vaddr_t sos_irq_wrapper_array[SOS_IRQ_NUM]; + +/** arrays of IRQ handlers, shared with irq_wrappers.S */ +sos_irq_handler_t sos_irq_handler_array[SOS_IRQ_NUM] = { NULL, }; + +/** Number of interrupt handlers that are currently executing */ +sos_ui32_t sos_irq_nested_level_counter; + +sos_ret_t sos_irq_subsystem_setup(void) +{ + sos_irq_nested_level_counter = 0; + return sos_i8259_subsystem_setup(); +} + + +sos_ret_t sos_irq_set_routine(int irq_level, + sos_irq_handler_t routine) +{ + sos_ret_t retval; + sos_ui32_t flags; + + if ((irq_level < 0) || (irq_level >= SOS_IRQ_NUM)) + return -SOS_EINVAL; + + sos_disable_IRQs(flags); + + retval = SOS_OK; + + /* Set the irq routine to be called by the IRQ wrapper */ + sos_irq_handler_array[irq_level] = routine; + + /* If the irq is to be enabled, update the IDT with the IRQ + wrapper */ + if (routine != NULL) + { + retval + = sos_idt_set_handler(SOS_IRQ_BASE + irq_level, + (sos_vaddr_t) sos_irq_wrapper_array[irq_level], + 0 /* CPL0 routine */); + /* A problem occured */ + if (retval != SOS_OK) + sos_irq_handler_array[irq_level] = NULL; + } + else /* Disable this idt entry */ + { + retval + = sos_idt_set_handler(SOS_IRQ_BASE + irq_level, + (sos_vaddr_t)NULL /* Disable IDTE */, + 0 /* Don't care */); + } + + /* Update the PIC only if an IRQ handler has been set */ + if (sos_irq_handler_array[irq_level] != NULL) + sos_i8259_enable_irq_line(irq_level); + else + sos_i8259_disable_irq_line(irq_level); + + sos_restore_IRQs(flags); + return retval; +} + + +sos_irq_handler_t sos_irq_get_routine(int irq_level) +{ + if ((irq_level < 0) || (irq_level >= SOS_IRQ_NUM)) + return NULL; + + /* Expected to be atomic */ + return sos_irq_handler_array[irq_level]; +} + + +sos_ui32_t sos_irq_get_nested_level() +{ + /* No need to disable interrupts here */ + return sos_irq_nested_level_counter; +} -- cgit v1.2.3