summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1998-07-23 22:02:34 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1998-07-23 22:02:34 +0000
commit67a2288991ce3662a588ee83c0bea9c9efae5f1e (patch)
treea8d68b22bfd313619f2a0d0b2e3b4755b8278b9d /c/src/lib/libbsp
parentPatch from Ralf Corsepius <corsepiu@faw.uni-ulm.de>: (diff)
downloadrtems-67a2288991ce3662a588ee83c0bea9c9efae5f1e.tar.bz2
Patch from Eric VALETTE <valette@crf.canon.fr>:
Here is a enhanced version of my previous patch. This patch enables to potentially share the new interrupt management code for all Intel targets (pc386, go32 and force386) bsp. Note : this patch is complete only for pc386. It still needs to be completed for go32 and force386. I carrefully checked that anything needed is in for force386 (only some function name changes for IDT manipulation and GDT segment manipulation). But anyway I will not be able to test any of theses targets...
Diffstat (limited to 'c/src/lib/libbsp')
-rw-r--r--c/src/lib/libbsp/i386/Makefile.in2
-rw-r--r--c/src/lib/libbsp/i386/pc386/clock/ckinit.c66
-rw-r--r--c/src/lib/libbsp/i386/pc386/console/console.c46
-rw-r--r--c/src/lib/libbsp/i386/pc386/console/inch.c31
-rw-r--r--c/src/lib/libbsp/i386/pc386/include/Makefile.in4
-rw-r--r--c/src/lib/libbsp/i386/pc386/include/bsp.h10
-rw-r--r--c/src/lib/libbsp/i386/pc386/start/start.s3
-rw-r--r--c/src/lib/libbsp/i386/pc386/startup/Makefile.in10
-rw-r--r--c/src/lib/libbsp/i386/pc386/startup/bspstart.c8
-rw-r--r--c/src/lib/libbsp/i386/pc386/startup/ldsegs.s30
-rw-r--r--c/src/lib/libbsp/i386/pc386/timer/timer.c72
-rw-r--r--c/src/lib/libbsp/i386/shared/Makefile.in16
-rw-r--r--c/src/lib/libbsp/i386/shared/irq/Makefile.in33
-rw-r--r--c/src/lib/libbsp/i386/shared/irq/idt.c265
-rw-r--r--c/src/lib/libbsp/i386/shared/irq/irq.c358
-rw-r--r--c/src/lib/libbsp/i386/shared/irq/irq.h260
-rw-r--r--c/src/lib/libbsp/i386/shared/irq/irq_asm.h30
-rw-r--r--c/src/lib/libbsp/i386/shared/irq/irq_asm.s261
-rw-r--r--c/src/lib/libbsp/i386/shared/irq/irq_init.c200
19 files changed, 1591 insertions, 114 deletions
diff --git a/c/src/lib/libbsp/i386/Makefile.in b/c/src/lib/libbsp/i386/Makefile.in
index f049e9b2e8..98bc04bc5d 100644
--- a/c/src/lib/libbsp/i386/Makefile.in
+++ b/c/src/lib/libbsp/i386/Makefile.in
@@ -12,4 +12,4 @@ include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
include $(RTEMS_ROOT)/make/directory.cfg
# Descend into the $(RTEMS_BSP_FAMILY) directory
-SUB_DIRS=$(RTEMS_BSP_FAMILY)
+SUB_DIRS=shared $(RTEMS_BSP_FAMILY)
diff --git a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
index 956d453747..f3687d1e66 100644
--- a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
+++ b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
@@ -39,11 +39,6 @@
#include <rtems/libio.h>
/*-------------------------------------------------------------------------+
-| Constants
-+--------------------------------------------------------------------------*/
-#define CLOCK_IRQ 0x00 /* Clock IRQ. */
-
-/*-------------------------------------------------------------------------+
| Macros
+--------------------------------------------------------------------------*/
#if 0
@@ -67,13 +62,12 @@ rtems_device_minor_number rtems_clock_minor;
/*-------------------------------------------------------------------------+
| Function: clockIsr
-| Description: Interrupt Service Routine for clock (08h) interruption.
+| Description: Interrupt Service Routine for clock (0h) interruption.
| Global Variables: Clock_driver_ticks, Clock_isrs.
| Arguments: vector - standard RTEMS argument - see documentation.
| Returns: standard return value - see documentation.
+--------------------------------------------------------------------------*/
-static rtems_isr
-clockIsr(rtems_vector_number vector)
+static void clockIsr()
{
/*-------------------------------------------------------------------------+
| PLEASE NOTE: The following is directly transcribed from the go32 BSP for
@@ -98,10 +92,8 @@ clockIsr(rtems_vector_number vector)
else
Clock_isrs--;
- PC386_ackIrq(vector - PC386_IRQ_VECTOR_BASE);
} /* clockIsr */
-
/*-------------------------------------------------------------------------+
| Function: Clock_exit
| Description: Clock cleanup routine at RTEMS exit. NOTE: This routine is
@@ -110,7 +102,7 @@ clockIsr(rtems_vector_number vector)
| Arguments: None.
| Returns: Nothing.
+--------------------------------------------------------------------------*/
-void Clock_exit(void)
+void clockOff(const rtems_irq_connect_data* unused)
{
if (BSP_Configuration.ticks_per_timeslice)
{
@@ -129,13 +121,10 @@ void Clock_exit(void)
| Arguments: None.
| Returns: Nothing.
+--------------------------------------------------------------------------*/
-void
-Install_clock(rtems_isr_entry isr)
+static void clockOn(const rtems_irq_connect_data* unused)
{
rtems_unsigned32 microseconds_per_isr;
- rtems_status_code status;
-
#if 0
/* Initialize clock from on-board real time clock. This breaks the */
/* test code which assumes which assumes the application will do it. */
@@ -175,22 +164,25 @@ Install_clock(rtems_isr_entry isr)
/* 105/88 approximates TIMER_TICK * 1e-6 */
rtems_unsigned32 count = US_TO_TICK(microseconds_per_isr);
- status = PC386_installRtemsIrqHandler(CLOCK_IRQ, isr);
-
- if (status != RTEMS_SUCCESSFUL)
- {
- printk("Error installing clock interrupt handler!\n");
- rtems_fatal_error_occurred(status);
- }
-
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
outport_byte(TIMER_CNTR0, count >> 0 & 0xff);
outport_byte(TIMER_CNTR0, count >> 8 & 0xff);
}
- atexit(Clock_exit);
-} /* Install_clock */
+}
+int clockIsOn(const rtems_irq_connect_data* unused)
+{
+ return ((i8259s_cache & 0x1) == 0);
+}
+
+static rtems_irq_connect_data clockIrqData = {PC_386_PERIODIC_TIMER,
+ clockIsr,
+ clockOn,
+ clockOff,
+ clockIsOn};
+
+
/*-------------------------------------------------------------------------+
| Clock device driver INITIALIZE entry point.
@@ -202,8 +194,11 @@ Clock_initialize(rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp)
{
- Install_clock(clockIsr); /* Install the interrupt handler */
-
+
+ if (!pc386_install_rtems_irq_handler (&clockIrqData)) {
+ printk("Unable to initialize system clock\n");
+ rtems_fatal_error_occurred(1);
+ }
/* make major/minor avail to others such as shared memory driver */
rtems_clock_major = major;
@@ -212,7 +207,7 @@ Clock_initialize(rtems_device_major_number major,
return RTEMS_SUCCESSFUL;
} /* Clock_initialize */
-
+
/*-------------------------------------------------------------------------+
| Console device driver CONTROL entry point
+--------------------------------------------------------------------------*/
@@ -231,17 +226,12 @@ Clock_control(rtems_device_major_number major,
+-------------------------------------------------------------------------*/
if (args->command == rtems_build_name('I', 'S', 'R', ' '))
- clockIsr(PC386_IRQ_VECTOR_BASE + CLOCK_IRQ);
+ clockIsr();
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
- rtems_status_code status;
-
- status = PC386_installRtemsIrqHandler(CLOCK_IRQ, clockIsr);
-
- if (status != RTEMS_SUCCESSFUL)
- {
+ if (!pc386_install_rtems_irq_handler (&clockIrqData)) {
printk("Error installing clock interrupt handler!\n");
- rtems_fatal_error_occurred(status);
+ rtems_fatal_error_occurred(1);
}
}
}
@@ -249,6 +239,10 @@ Clock_control(rtems_device_major_number major,
return RTEMS_SUCCESSFUL;
} /* Clock_control */
+void Clock_exit()
+{
+ pc386_remove_rtems_irq_handler (&clockIrqData);
+}
/*-------------------------------------------------------------------------+
| PLEASE NOTE: The following is directly transcribed from the go32 BSP for
diff --git a/c/src/lib/libbsp/i386/pc386/console/console.c b/c/src/lib/libbsp/i386/pc386/console/console.c
index 29ec37ec56..c8d9a2c4f4 100644
--- a/c/src/lib/libbsp/i386/pc386/console/console.c
+++ b/c/src/lib/libbsp/i386/pc386/console/console.c
@@ -46,16 +46,19 @@ int PC386ConsolePort = PC386_CONSOLE_PORT_CONSOLE;
static int conSetAttr(int minor, const struct termios *);
/*-------------------------------------------------------------------------+
-| Constants
-+--------------------------------------------------------------------------*/
-#define KEYBOARD_IRQ 0x01 /* Keyboard IRQ. */
-
-
-/*-------------------------------------------------------------------------+
| External Prototypes
+--------------------------------------------------------------------------*/
-extern rtems_isr _IBMPC_keyboard_isr(rtems_vector_number);
- /* keyboard (IRQ 0x01) Interrupt Service Routine (defined in 'inch.c') */
+extern void _IBMPC_keyboard_isr(void);
+extern void _IBMPC_keyboard_isr_on(const rtems_irq_connect_data*);
+extern void _IBMPC_keyboard_isr_off(const rtems_irq_connect_data*);
+extern int _IBMPC_keyboard_isr_is_on(const rtems_irq_connect_data*);
+
+static rtems_irq_connect_data console_isr_data = {PC_386_KEYBOARD,
+ _IBMPC_keyboard_isr,
+ _IBMPC_keyboard_isr_on,
+ _IBMPC_keyboard_isr_off,
+ _IBMPC_keyboard_isr_is_on};
+
extern rtems_boolean _IBMPC_scankey(char *); /* defined in 'inch.c' */
@@ -164,9 +167,9 @@ console_initialize(rtems_device_major_number major,
{
/* Install keyboard interrupt handler */
- status = PC386_installRtemsIrqHandler(KEYBOARD_IRQ, _IBMPC_keyboard_isr);
-
- if (status != RTEMS_SUCCESSFUL)
+ status = pc386_install_rtems_irq_handler(&console_isr_data);
+
+ if (!status)
{
printk("Error installing keyboard interrupt handler!\n");
rtems_fatal_error_occurred(status);
@@ -198,16 +201,18 @@ console_initialize(rtems_device_major_number major,
/* Set interrupt handler */
if(PC386ConsolePort == PC386_UART_COM1)
{
- status = PC386_installRtemsIrqHandler(PC386_UART_COM1_IRQ,
- PC386_uart_termios_isr_com1);
+ console_isr_data.name = PC386_UART_COM1_IRQ;
+ console_isr_data.hdl = PC386_uart_termios_isr_com1;
+
}
else
{
assert(PC386ConsolePort == PC386_UART_COM2);
-
- status = PC386_installRtemsIrqHandler(PC386_UART_COM2_IRQ,
- PC386_uart_termios_isr_com2);
+ console_isr_data.name = PC386_UART_COM2_IRQ;
+ console_isr_data.hdl = PC386_uart_termios_isr_com2;
}
+
+ status =pc386_install_rtems_irq_handler(&console_isr_data);
/*
* Register the device
*/
@@ -291,12 +296,15 @@ console_close(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
+ rtems_device_driver res = RTEMS_SUCCESSFUL;
+
if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
{
- return rtems_termios_close (arg);
+ res = rtems_termios_close (arg);
}
-
- return RTEMS_SUCCESSFUL;
+ pc386_remove_rtems_irq_handler (&console_isr_data);
+
+ return res;
} /* console_close */
diff --git a/c/src/lib/libbsp/i386/pc386/console/inch.c b/c/src/lib/libbsp/i386/pc386/console/inch.c
index 9159e62ab4..39c29f93e0 100644
--- a/c/src/lib/libbsp/i386/pc386/console/inch.c
+++ b/c/src/lib/libbsp/i386/pc386/console/inch.c
@@ -210,6 +210,17 @@ _IBMPC_scankey(char *outChar)
return TRUE;
} /* _IBMPC_scankey */
+void _IBMPC_keyboard_isr_on(const rtems_irq_connect_data* unused)
+{}
+void _IBMPC_keyboard_isr_off(const rtems_irq_connect_data* unused)
+{}
+
+int _IBMPC_keyboard_isr_is_on(const rtems_irq_connect_data* irq)
+{
+ return pc386_irq_enabled_at_i8259s (irq->name);
+}
+
+
/*-------------------------------------------------------------------------+
| Function: _IBMPC_keyboard_isr
@@ -218,8 +229,7 @@ _IBMPC_scankey(char *outChar)
| Arguments: vector - standard RTEMS argument - see documentation.
| Returns: standard return value - see documentation.
+--------------------------------------------------------------------------*/
-rtems_isr
-_IBMPC_keyboard_isr(rtems_vector_number vector)
+void _IBMPC_keyboard_isr()
{
if (_IBMPC_scankey(&kbd_buffer[kbd_last]))
{
@@ -231,8 +241,6 @@ _IBMPC_keyboard_isr(rtems_vector_number vector)
kbd_last = next;
}
}
-
- PC386_ackIrq(vector - PC386_IRQ_VECTOR_BASE); /* Mark interrupt as handled. */
} /* _IBMPC_keyboard_isr */
@@ -281,6 +289,21 @@ _IBMPC_inch(void)
return c;
} /* _IBMPC_inch */
+
+ /*
+ * Routine that can be used before interrupt management is initialized.
+ */
+
+char
+debugPollingGetChar(void)
+{
+ char c;
+ while (!_IBMPC_scankey(&c))
+ continue;
+
+ return c;
+}
+
/*-------------------------------------------------------------------------+
| Function: _IBMPC_inch_sleep
| Description: If charcter is ready return it, otherwise sleep until
diff --git a/c/src/lib/libbsp/i386/pc386/include/Makefile.in b/c/src/lib/libbsp/i386/pc386/include/Makefile.in
index 49e4168eca..10cf41f1a3 100644
--- a/c/src/lib/libbsp/i386/pc386/include/Makefile.in
+++ b/c/src/lib/libbsp/i386/pc386/include/Makefile.in
@@ -8,8 +8,8 @@ VPATH = @srcdir@
RTEMS_ROOT = @top_srcdir@
PROJECT_ROOT = @PROJECT_ROOT@
-H_FILES = $(srcdir)/bsp.h $(srcdir)/coverhd.h $(srcdir)/irq.h \
- $(srcdir)/crt.h $(srcdir)/pc386uart.h $(srcdir)/pcibios.h
+H_FILES = $(srcdir)/bsp.h $(srcdir)/coverhd.h $(srcdir)/crt.h \
+ $(srcdir)/pc386uart.h $(srcdir)/pcibios.h
#
# Equate files are for including from assembly preprocessed by
diff --git a/c/src/lib/libbsp/i386/pc386/include/bsp.h b/c/src/lib/libbsp/i386/pc386/include/bsp.h
index c7920f385b..1e7a4a6506 100644
--- a/c/src/lib/libbsp/i386/pc386/include/bsp.h
+++ b/c/src/lib/libbsp/i386/pc386/include/bsp.h
@@ -51,7 +51,8 @@ extern "C" {
#include <iosupp.h>
#include <console.h>
#include <clockdrv.h>
-
+#include <libcpu/cpu.h>
+
/*-------------------------------------------------------------------------+
| Constants
+--------------------------------------------------------------------------*/
@@ -133,8 +134,11 @@ extern "C" {
/*-------------------------------------------------------------------------+
| External Variables.
+--------------------------------------------------------------------------*/
-extern i386_IDT_slot Interrupt_descriptor_table[];
-extern i386_GDT_slot Global_descriptor_table [];
+#define IDT_SIZE 256
+#define GDT_SIZE 3
+
+extern interrupt_gate_descriptor Interrupt_descriptor_table[IDT_SIZE];
+extern segment_descriptors Global_descriptor_table [GDT_SIZE];
extern rtems_configuration_table BSP_Configuration;
/* User provided BSP configuration table. */
diff --git a/c/src/lib/libbsp/i386/pc386/start/start.s b/c/src/lib/libbsp/i386/pc386/start/start.s
index fae56137e5..36fad8153c 100644
--- a/c/src/lib/libbsp/i386/pc386/start/start.s
+++ b/c/src/lib/libbsp/i386/pc386/start/start.s
@@ -104,7 +104,8 @@ speakl: jmp speakl # and SPIN!!!
call printk
addl $4, esp
- /*call debugPollingGetChar */
+ call debugPollingGetChar
+
#endif
/*----------------------------------------------------------------------------+
diff --git a/c/src/lib/libbsp/i386/pc386/startup/Makefile.in b/c/src/lib/libbsp/i386/pc386/startup/Makefile.in
index 1c8f298249..a4fe0e4cb2 100644
--- a/c/src/lib/libbsp/i386/pc386/startup/Makefile.in
+++ b/c/src/lib/libbsp/i386/pc386/startup/Makefile.in
@@ -11,14 +11,14 @@ PROJECT_ROOT = @PROJECT_ROOT@
PGM=${ARCH}/startup.rel
# C source names, if any, go here -- minus the .c
-C_PIECES=bspclean bsplibc bsppost bspstart exit irq main sbrk
+C_PIECES=bspclean bsplibc bsppost bspstart exit irq irq_init main sbrk
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
H_FILES=
# Assembly source names, if any, go here -- minus the .s
-S_PIECES=ldsegs
+S_PIECES=ldsegs irq_asm
S_FILES=$(S_PIECES:%=%.s)
S_O_FILES=$(S_FILES:%.s=${ARCH}/%.o)
@@ -50,6 +50,12 @@ LDFLAGS +=
CLEAN_ADDITIONS +=
CLOBBER_ADDITIONS +=
+IMPORT_SRC=$(srcdir)/../../shared/irq/irq.c \
+ $(srcdir)/../../shared/irq/irq_init.c $(srcdir)/../../shared/irq/irq_asm.s
+
+preinstall:
+ ${CP} ${IMPORT_SRC} .
+
${PGM}: ${SRCS} ${OBJS}
$(make-rel)
all: ${ARCH} $(SRCS) $(PGM)
diff --git a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c
index 607e816d6d..744808b3be 100644
--- a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c
+++ b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c
@@ -65,7 +65,8 @@ char *rtems_progname; /* Program name - from main(). */
extern void _exit(int); /* define in exit.c */
void bsp_libc_init( void *, unsigned32, int );
void bsp_postdriver_hook(void);
-
+extern void rtems_irq_mngt_init();
+
/*-------------------------------------------------------------------------+
| Function: bsp_pretasking_hook
| Description: BSP pretasking hook. Called just before drivers are
@@ -129,6 +130,11 @@ void bsp_start( void )
console_reserve_resources(&BSP_Configuration);
/*
+ * Init trems_interrupt_management
+ */
+ rtems_irq_mngt_init();
+
+ /*
* The following information is very useful when debugging.
*/
diff --git a/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s b/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s
index f2171575ce..8805128e69 100644
--- a/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s
+++ b/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s
@@ -45,12 +45,13 @@
/*----------------------------------------------------------------------------+
| CODE section
+----------------------------------------------------------------------------*/
-
+EXTERN (rtems_i8259_masks)
+
BEGIN_CODE
EXTERN (_establish_stack)
EXTERN (Timer_exit)
- EXTERN (Clock_exit)
+ EXTERN (clockOff)
.p2align 4
/*----------------------------------------------------------------------------+
@@ -95,25 +96,6 @@ next_step:
movw ax, fs
movw ax, gs
- /* Set default interrupt handler */
- movl $0, ecx
- movl $Interrupt_descriptor_table, eax
- movl $_default_int_handler, ebx
- movl ebx, edx
- sarl $16, edx
-loop:
- movw bx, (eax)
- movw $0x8, 2(eax)
- movw $0x8e00, 4(eax)
- movw dx, 8(eax)
- addl $8, eax
- addl $1, ecx
- cmpl $255, ecx
- jle loop
-
-
-
-
/*---------------------------------------------------------------------+
| Now we have to reprogram the interrupts :-(. We put them right after
| the intel-reserved hardware interrupts, at int 0x20-0x2F. There they
@@ -157,6 +139,8 @@ loop:
outb al, $0x21 /* is cascaded */
call SYM(delay)
+ movw $0xFFFB, SYM(i8259s_cache) /* set up same values in cache */
+
jmp SYM (_establish_stack) # return to the bsp entry code
/*-------------------------------------------------------------------------+
@@ -185,10 +169,6 @@ SYM (_return_to_monitor):
+--------------------------------------------------------------------------*/
.p2align 4
- PUBLIC (_default_int_handler)
-SYM (_default_int_handler):
- iret
-
/*---------------------------------------------------------------------------+
| GDT itself
+--------------------------------------------------------------------------*/
diff --git a/c/src/lib/libbsp/i386/pc386/timer/timer.c b/c/src/lib/libbsp/i386/pc386/timer/timer.c
index ea7b5c5219..650c6a5a5e 100644
--- a/c/src/lib/libbsp/i386/pc386/timer/timer.c
+++ b/c/src/lib/libbsp/i386/pc386/timer/timer.c
@@ -43,7 +43,6 @@
/*-------------------------------------------------------------------------+
| Constants
+--------------------------------------------------------------------------*/
-#define TIMER_IRQ 0x00 /* Timer IRQ. */
#define AVG_OVERHEAD 0 /* 0.1 microseconds to start/stop timer. */
#define LEAST_VALID 1 /* Don't trust a value lower than this. */
@@ -54,6 +53,13 @@ volatile rtems_unsigned32 Ttimer_val;
rtems_boolean Timer_driver_Find_average_overhead = TRUE;
/*-------------------------------------------------------------------------+
+| External Prototypes
++--------------------------------------------------------------------------*/
+extern void timerisr();
+ /* timer (int 08h) Interrupt Service Routine (defined in 'timerisr.s') */
+extern int clockIsOn(const rtems_irq_connect_data*);
+
+/*-------------------------------------------------------------------------+
| Pentium optimized timer handling.
+--------------------------------------------------------------------------*/
#if defined(pentium)
@@ -86,7 +92,6 @@ rdtsc(void)
void
Timer_exit(void)
{
- PC386_disableIrq(TIMER_IRQ);
} /* Timer_exit */
@@ -107,8 +112,6 @@ Timer_initialize(void)
First = FALSE;
atexit(Timer_exit); /* Try not to hose the system at exit. */
- PC386_enableIrq(TIMER_IRQ);
- /* Disable the programmable timer so ticks don't interfere. */
}
Ttimer_val = rdtsc(); /* read starting time */
} /* Timer_initialize */
@@ -143,11 +146,48 @@ Read_timer(void)
+--------------------------------------------------------------------------*/
#define US_PER_ISR 250 /* Number of micro-seconds per timer interruption */
+
/*-------------------------------------------------------------------------+
-| External Prototypes
+| Function: Timer_exit
+| Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
+| not really necessary, since there will be a reset at exit.
+| Global Variables: None.
+| Arguments: None.
+| Returns: Nothing.
+--------------------------------------------------------------------------*/
-extern rtems_isr timerisr(rtems_vector_number);
- /* timer (int 08h) Interrupt Service Routine (defined in 'timerisr.s') */
+void
+timerOff(const rtems_raw_irq_connect_data* used)
+{
+ /*
+ * disable interrrupt at i8259 level
+ */
+ pc386_irq_disable_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE);
+ /* reset timer mode to standard (DOS) value */
+ outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
+ outport_byte(TIMER_CNTR0, 0);
+ outport_byte(TIMER_CNTR0, 0);
+} /* Timer_exit */
+
+
+void timerOn(const rtems_raw_irq_connect_data* used)
+{
+ /* load timer for US_PER_ISR microsecond period */
+ outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
+ outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff);
+ outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff);
+ /*
+ * disable interrrupt at i8259 level
+ */
+ pc386_irq_enable_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE);
+}
+
+static rtems_raw_irq_connect_data timer_raw_irq_data = {
+ PC_386_PERIODIC_TIMER + PC386_IRQ_VECTOR_BASE,
+ timerisr,
+ timerOn,
+ timerOff,
+ clockIsOn
+};
/*-------------------------------------------------------------------------+
| Function: Timer_exit
@@ -160,13 +200,9 @@ extern rtems_isr timerisr(rtems_vector_number);
void
Timer_exit(void)
{
- /* reset timer mode to standard (DOS) value */
- outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
- outport_byte(TIMER_CNTR0, 0);
- outport_byte(TIMER_CNTR0, 0);
+ i386_delete_idt_entry (&timer_raw_irq_data);
} /* Timer_exit */
-
/*-------------------------------------------------------------------------+
| Function: Timer_initialize
| Description: Timer initialization routine.
@@ -184,14 +220,10 @@ Timer_initialize(void)
First = FALSE;
atexit(Timer_exit); /* Try not to hose the system at exit. */
-
- /* install a raw interrupt handler for timer */
- PC386_installRawIrqHandler(TIMER_IRQ, timerisr);
-
- /* load timer for US_PER_ISR microsecond period */
- outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
- outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff);
- outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff);
+ if (!i386_set_idt_entry (&timer_raw_irq_data)) {
+ printk("raw handler connexion failed\n");
+ rtems_fatal_error_occurred(1);
+ }
}
/* wait for ISR to be called at least once */
Ttimer_val = 0;
diff --git a/c/src/lib/libbsp/i386/shared/Makefile.in b/c/src/lib/libbsp/i386/shared/Makefile.in
new file mode 100644
index 0000000000..feab84d468
--- /dev/null
+++ b/c/src/lib/libbsp/i386/shared/Makefile.in
@@ -0,0 +1,16 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/directory.cfg
+
+# Descend into the $(RTEMS_BSP_FAMILY) directory
+SUB_DIRS=irq
+
diff --git a/c/src/lib/libbsp/i386/shared/irq/Makefile.in b/c/src/lib/libbsp/i386/shared/irq/Makefile.in
new file mode 100644
index 0000000000..098852cfa0
--- /dev/null
+++ b/c/src/lib/libbsp/i386/shared/irq/Makefile.in
@@ -0,0 +1,33 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+H_FILES = $(srcdir)/irq.h $(srcdir)/irq_asm.h
+
+#
+# Equate files are for including from assembly preprocessed by
+# gm4 or gasp. No examples are provided except for those for
+# other CPUs. The best way to generate them would be to
+# provide a program which generates the constants used based
+# on the C equivalents.
+#
+
+EQ_FILES =
+
+SRCS=$(H_FILES) $(EQ_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+preinstall all: $(SRCS)
+ $(INSTALL) -m 444 $(H_FILES) $(PROJECT_INCLUDE)
+ $(INSTALL) -m 444 $(EQ_FILES) $(PROJECT_INCLUDE)
diff --git a/c/src/lib/libbsp/i386/shared/irq/idt.c b/c/src/lib/libbsp/i386/shared/irq/idt.c
new file mode 100644
index 0000000000..8873de3811
--- /dev/null
+++ b/c/src/lib/libbsp/i386/shared/irq/idt.c
@@ -0,0 +1,265 @@
+/*
+ * cpu.c - This file contains implementation of C function to
+ * Instanciate IDT entries. More detailled information can be found
+ * on Intel site and more precisely in the following book :
+ *
+ * Pentium Processor familly
+ * Developper's Manual
+ *
+ * Volume 3 : Architecture and Programming Manual
+ *
+ * Copyright (C) 1998 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <libcpu/cpu.h>
+#include <irq.h>
+
+static rtems_raw_irq_connect_data* raw_irq_table;
+static rtems_raw_irq_connect_data default_raw_irq_entry;
+static interrupt_gate_descriptor default_idt_entry;
+static rtems_raw_irq_global_settings* local_settings;
+
+void create_interrupt_gate_descriptor (interrupt_gate_descriptor* idtEntry,
+ rtems_raw_irq_hdl hdl)
+{
+ idtEntry->low_offsets_bits = (((unsigned) hdl) & 0xffff);
+ idtEntry->segment_selector = i386_get_cs();
+ idtEntry->fixed_value_bits = 0;
+ idtEntry->gate_type = 0xe;
+ idtEntry->privilege = 0;
+ idtEntry->present = 1;
+ idtEntry->high_offsets_bits = ((((unsigned) hdl) >> 16) & 0xffff);
+}
+
+rtems_raw_irq_hdl get_hdl_from_vector(rtems_vector_offset index)
+{
+ rtems_raw_irq_hdl hdl;
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ * ((unsigned int*) &hdl) = (idt_entry_tbl[index].low_offsets_bits |
+ (idt_entry_tbl[index].high_offsets_bits << 16));
+ return hdl;
+}
+
+int i386_set_idt_entry (const rtems_raw_irq_connect_data* irq)
+{
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+ unsigned int level;
+
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ if (irq->idtIndex > limit) {
+ return 0;
+ }
+ /*
+ * Check if default handler is actually connected. If not issue an error.
+ * You must first get the current handler via i386_get_current_idt_entry
+ * and then disconnect it using i386_delete_idt_entry.
+ * RATIONALE : to always have the same transition by forcing the user
+ * to get the previous handler before accepting to disconnect.
+ */
+ if (get_hdl_from_vector(irq->idtIndex) != default_raw_irq_entry.hdl) {
+ return 0;
+ }
+ _CPU_ISR_Disable(level);
+
+ raw_irq_table [irq->idtIndex] = *irq;
+ create_interrupt_gate_descriptor (&idt_entry_tbl[irq->idtIndex], irq->hdl);
+ irq->on(irq);
+
+ _CPU_ISR_Enable(level);
+ return 1;
+}
+
+void _CPU_ISR_install_vector (unsigned vector,
+ void* hdl,
+ void** oldHdl)
+{
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+ interrupt_gate_descriptor new;
+ unsigned int level;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ if (vector > limit) {
+ return;
+ }
+ _CPU_ISR_Disable(level)
+ * ((unsigned int *) oldHdl) = idt_entry_tbl[vector].low_offsets_bits |
+ (idt_entry_tbl[vector].high_offsets_bits << 16);
+
+ create_interrupt_gate_descriptor(&new, hdl);
+ idt_entry_tbl[vector] = new;
+
+ _CPU_ISR_Enable(level);
+}
+
+int i386_get_current_idt_entry (rtems_raw_irq_connect_data* irq)
+{
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ if (irq->idtIndex > limit) {
+ return 1;
+ }
+ raw_irq_table [irq->idtIndex].hdl = get_hdl_from_vector(irq->idtIndex);
+
+ *irq = raw_irq_table [irq->idtIndex];
+
+ return 0;
+}
+
+int i386_delete_idt_entry (const rtems_raw_irq_connect_data* irq)
+{
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+ unsigned int level;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ if (irq->idtIndex > limit) {
+ return 1;
+ }
+ /*
+ * Check if handler passed is actually connected. If not issue an error.
+ * You must first get the current handler via i386_get_current_idt_entry
+ * and then disconnect it using i386_delete_idt_entry.
+ * RATIONALE : to always have the same transition by forcing the user
+ * to get the previous handler before accepting to disconnect.
+ */
+ if (get_hdl_from_vector(irq->idtIndex) != irq->hdl){
+ return 1;
+ }
+ _CPU_ISR_Disable(level);
+
+ idt_entry_tbl[irq->idtIndex] = default_idt_entry;
+
+ irq->off(irq);
+
+ raw_irq_table[irq->idtIndex] = default_raw_irq_entry;
+
+ _CPU_ISR_Enable(level);
+
+ return 0;
+}
+
+/*
+ * Caution this function assumes the IDTR has been already set.
+ */
+int i386_init_idt (rtems_raw_irq_global_settings* config)
+{
+ unsigned limit;
+ unsigned i;
+ unsigned level;
+ interrupt_gate_descriptor* idt_entry_tbl;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+
+ if (config->idtSize != limit) {
+ return 1;
+ }
+ /*
+ * store various accelarators
+ */
+ raw_irq_table = config->rawIrqHdlTbl;
+ local_settings = config;
+ default_raw_irq_entry = config->defaultRawEntry;
+
+ _CPU_ISR_Disable(level);
+
+ create_interrupt_gate_descriptor (&default_idt_entry, default_raw_irq_entry.hdl);
+
+ for (i=0; i < limit; i++) {
+ interrupt_gate_descriptor new;
+ create_interrupt_gate_descriptor (&new, raw_irq_table[i].hdl);
+ idt_entry_tbl[i] = new;
+ if (raw_irq_table[i].hdl != default_raw_irq_entry.hdl) {
+ raw_irq_table[i].on(&raw_irq_table[i]);
+ }
+ else {
+ raw_irq_table[i].off(&raw_irq_table[i]);
+ }
+ }
+ _CPU_ISR_Enable(level);
+
+ return 0;
+}
+
+int i386_get_idt_config (rtems_raw_irq_global_settings** config)
+{
+ *config = local_settings;
+ return 0;
+}
+
+/*
+ * Caution this function assumes the GDTR has been already set.
+ */
+int i386_set_gdt_entry (unsigned short segment_selector, unsigned base,
+ unsigned limit)
+{
+ unsigned gdt_limit;
+ unsigned short tmp_segment = 0;
+ unsigned int limit_adjusted;
+ segment_descriptors* gdt_entry_tbl;
+
+
+ i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit);
+
+ if (segment_selector > limit) {
+ return 1;
+ }
+ /*
+ * set up limit first
+ */
+ limit_adjusted = limit;
+ if ( limit > 4095 ) {
+ gdt_entry_tbl[segment_selector].granularity = 1;
+ limit_adjusted /= 4096;
+ }
+ gdt_entry_tbl[segment_selector].limit_15_0 = limit_adjusted & 0xffff;
+ gdt_entry_tbl[segment_selector].limit_19_16 = (limit_adjusted >> 16) & 0xf;
+ /*
+ * set up base
+ */
+ gdt_entry_tbl[segment_selector].base_address_15_0 = base & 0xffff;
+ gdt_entry_tbl[segment_selector].base_address_23_16 = (base >> 16) & 0xff;
+ gdt_entry_tbl[segment_selector].base_address_31_24 = (base >> 24) & 0xff;
+ /*
+ * set up descriptor type (this may well becomes a parameter if needed)
+ */
+ gdt_entry_tbl[segment_selector].type = 2; /* Data R/W */
+ gdt_entry_tbl[segment_selector].descriptor_type = 1; /* Code or Data */
+ gdt_entry_tbl[segment_selector].privilege = 0; /* ring 0 */
+ gdt_entry_tbl[segment_selector].present = 1; /* not present */
+
+ /*
+ * Now, reload all segment registers so the limit takes effect.
+ */
+
+ asm volatile( "movw %%ds,%0 ; movw %0,%%ds
+ movw %%es,%0 ; movw %0,%%es
+ movw %%fs,%0 ; movw %0,%%fs
+ movw %%gs,%0 ; movw %0,%%gs
+ movw %%ss,%0 ; movw %0,%%ss"
+ : "=r" (tmp_segment)
+ : "0" (tmp_segment)
+ );
+
+ return 0;
+}
diff --git a/c/src/lib/libbsp/i386/shared/irq/irq.c b/c/src/lib/libbsp/i386/shared/irq/irq.c
new file mode 100644
index 0000000000..026f4953d7
--- /dev/null
+++ b/c/src/lib/libbsp/i386/shared/irq/irq.c
@@ -0,0 +1,358 @@
+/* irq.c
+ *
+ * This file contains the implementation of the function described in irq.h
+ *
+ * CopyRight (C) 1998 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+
+#include <bsp.h>
+#include <irq.h>
+
+/*
+ * pointer to the mask representing the additionnal irq vectors
+ * that must be disabled when a particular entry is activated.
+ * They will be dynamically computed from teh prioruty table given
+ * in pc386_rtems_irq_mngt_set();
+ * CAUTION : this table is accessed directly by interrupt routine
+ * prologue.
+ */
+rtems_i8259_masks irq_mask_or_tbl[PC_386_IRQ_LINES_NUMBER];
+
+/*
+ * Copy of data given via initial pc386_rtems_irq_mngt_set() for
+ * the sake of efficiency.
+ * CAUTION : this table is accessed directly by interrupt routine
+ * prologue.
+ */
+rtems_irq_hdl current_irq[PC_386_IRQ_LINES_NUMBER];
+/*
+ * default handler connected on each irq after bsp initialization
+ */
+static rtems_irq_connect_data default_rtems_entry;
+
+/*
+ * location used to store initial tables used for interrupt
+ * management.
+ */
+static rtems_irq_global_settings* internal_config;
+static rtems_irq_connect_data* rtems_hdl_tbl;
+/*-------------------------------------------------------------------------+
+| Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register.
++--------------------------------------------------------------------------*/
+/*
+ * lower byte is interrupt mask on the master PIC.
+ * while upper bits are interrupt on the slave PIC.
+ * This cache is initialized in ldseg.s
+ */
+rtems_i8259_masks i8259s_cache;
+
+/*-------------------------------------------------------------------------+
+| Function: PC386_irq_disable_at_i8259s
+| Description: Mask IRQ line in appropriate PIC chip.
+| Global Variables: i8259s_cache
+| Arguments: vector_offset - number of IRQ line to mask.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+int pc386_irq_disable_at_i8259s (const rtems_irq_symbolic_name irqLine)
+{
+ unsigned short mask;
+ unsigned int level;
+
+ if ( ((int)irqLine < PC_386_LOWEST_OFFSET) ||
+ ((int)irqLine > PC_386_MAX_OFFSET )
+ )
+ return 1;
+
+ _CPU_ISR_Disable(level);
+
+ mask = 1 << irqLine;
+ i8259s_cache |= mask;
+
+ if (irqLine < 8)
+ {
+ outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
+ }
+ else
+ {
+ outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) > 8));
+ }
+ _CPU_ISR_Enable (level);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------+
+| Function: pc386_irq_enable_at_i8259s
+| Description: Unmask IRQ line in appropriate PIC chip.
+| Global Variables: i8259s_cache
+| Arguments: irqLine - number of IRQ line to mask.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+int pc386_irq_enable_at_i8259s (const rtems_irq_symbolic_name irqLine)
+{
+ unsigned short mask;
+ unsigned int level;
+
+ if ( ((int)irqLine < PC_386_LOWEST_OFFSET) ||
+ ((int)irqLine > PC_386_MAX_OFFSET )
+ )
+ return 1;
+
+ _CPU_ISR_Disable(level);
+
+ mask = ~(1 << irqLine);
+ i8259s_cache &= mask;
+
+ if (irqLine < 8)
+ {
+ outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
+ }
+ else
+ {
+ outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) > 8));
+ }
+ _CPU_ISR_Enable (level);
+
+ return 0;
+} /* mask_irq */
+
+int pc386_irq_enabled_at_i8259s (const rtems_irq_symbolic_name irqLine)
+{
+ unsigned short mask;
+
+ if ( ((int)irqLine < PC_386_LOWEST_OFFSET) ||
+ ((int)irqLine > PC_386_MAX_OFFSET )
+ )
+ return 1;
+
+ mask = (1 << irqLine);
+ return (~(i8259s_cache & mask));
+}
+
+
+/*-------------------------------------------------------------------------+
+| Function: pc386_irq_ack_at_i8259s
+| Description: Signal generic End Of Interrupt (EOI) to appropriate PIC.
+| Global Variables: None.
+| Arguments: irqLine - number of IRQ line to acknowledge.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+int pc386_irq_ack_at_i8259s (const rtems_irq_symbolic_name irqLine)
+{
+ if ( ((int)irqLine < PC_386_LOWEST_OFFSET) ||
+ ((int)irqLine > PC_386_MAX_OFFSET )
+ )
+ return 1;
+
+ if (irqLine >= 8) {
+ outport_byte(PIC_SLAVE_COMMAND_IO_PORT, PIC_EOI);
+ }
+ outport_byte(PIC_MASTER_COMMAND_IO_PORT, PIC_EOI);
+
+ return 0;
+
+} /* ackIRQ */
+
+/*
+ * ------------------------ RTEMS Irq helper functions ----------------
+ */
+
+/*
+ * Caution : this function assumes the variable "internal_config"
+ * is already set and that the tables it contains are still valid
+ * and accessible.
+ */
+static void compute_i8259_masks_from_prio ()
+{
+ unsigned int i;
+ unsigned int j;
+ /*
+ * Always mask at least current interrupt to prevent re-entrance
+ */
+ for (i=0; i < internal_config->irqNb; i++) {
+ * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);
+ for (j = 0; j < internal_config->irqNb; j++) {
+ /*
+ * Mask interrupts at i8259 level that have a lower priority
+ */
+ if (internal_config->irqPrioTbl [i] > internal_config->irqPrioTbl [j]) {
+ * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j);
+ }
+ }
+ }
+}
+
+/*
+ * Caution : this function assumes the variable "internal_config"
+ * is already set and that the tables it contains are still valid
+ * and accessible.
+ */
+static void make_copy_of_handlers ()
+{
+ int i;
+ for (i=0; i < internal_config->irqNb; i++) {
+ current_irq [i] = internal_config->irqHdlTbl[i].hdl;
+ }
+}
+
+
+/*
+ * This function check that the value given for the irq line
+ * is valid.
+ */
+
+static int isValidInterrupt(int irq)
+{
+ if ( (irq < PC_386_LOWEST_OFFSET) || (irq > PC_386_MAX_OFFSET))
+ return 0;
+ return 1;
+}
+
+/*
+ * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
+ */
+
+int pc386_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
+{
+ unsigned int level;
+
+ if (!isValidInterrupt(irq->name)) {
+ return 0;
+ }
+ /*
+ * Check if default handler is actually connected. If not issue an error.
+ * You must first get the current handler via i386_get_current_idt_entry
+ * and then disconnect it using i386_delete_idt_entry.
+ * RATIONALE : to always have the same transition by forcing the user
+ * to get the previous handler before accepting to disconnect.
+ */
+ if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
+ return 0;
+ }
+ _CPU_ISR_Disable(level);
+
+ /*
+ * store the data provided by user
+ */
+ rtems_hdl_tbl[irq->name] = *irq;
+ /*
+ * update table used directly by rtems interrupt prologue
+ */
+ current_irq [irq->name] = irq->hdl;
+ /*
+ * Enable interrupt at PIC level
+ */
+ pc386_irq_enable_at_i8259s (irq->name);
+ /*
+ * Enable interrupt on device
+ */
+ irq->on(irq);
+
+ _CPU_ISR_Enable(level);
+
+ return 1;
+}
+
+
+int pc386_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
+{
+ if (!isValidInterrupt(irq->name)) {
+ return 0;
+ }
+ *irq = rtems_hdl_tbl[irq->name];
+ return 1;
+}
+
+int pc386_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
+{
+ unsigned int level;
+
+ if (!isValidInterrupt(irq->name)) {
+ return 0;
+ }
+ /*
+ * Check if default handler is actually connected. If not issue an error.
+ * You must first get the current handler via i386_get_current_idt_entry
+ * and then disconnect it using i386_delete_idt_entry.
+ * RATIONALE : to always have the same transition by forcing the user
+ * to get the previous handler before accepting to disconnect.
+ */
+ if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
+ return 0;
+ }
+ _CPU_ISR_Disable(level);
+
+ /*
+ * disable interrupt at PIC level
+ */
+ pc386_irq_disable_at_i8259s (irq->name);
+
+ /*
+ * Disable interrupt on device
+ */
+ irq->off(irq);
+
+ /*
+ * restore the default irq value
+ */
+ rtems_hdl_tbl[irq->name] = default_rtems_entry;
+
+ current_irq[irq->name] = default_rtems_entry.hdl;
+
+ _CPU_ISR_Enable(level);
+
+ return 1;
+}
+
+/*
+ * ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
+ */
+
+int pc386_rtems_irq_mngt_set(rtems_irq_global_settings* config)
+{
+ int i;
+ unsigned int level;
+ /*
+ * Store various code accelerators
+ */
+ internal_config = config;
+ default_rtems_entry = config->defaultEntry;
+ rtems_hdl_tbl = config->irqHdlTbl;
+
+ _CPU_ISR_Disable(level);
+ /*
+ * set up internal tables used by rtems interrupt prologue
+ */
+ compute_i8259_masks_from_prio ();
+ make_copy_of_handlers ();
+
+ for (i=0; i < internal_config->irqNb; i++) {
+ if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
+ pc386_irq_enable_at_i8259s (i);
+ rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
+ }
+ else {
+ rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
+ pc386_irq_disable_at_i8259s (i);
+ }
+ }
+ /*
+ * must disable slave pic anyway
+ */
+ pc386_irq_enable_at_i8259s (2);
+ _CPU_ISR_Enable(level);
+ return 1;
+}
+
+int pc386_rtems_irq_mngt_get(rtems_irq_global_settings** config)
+{
+ *config = internal_config;
+ return 0;
+}
diff --git a/c/src/lib/libbsp/i386/shared/irq/irq.h b/c/src/lib/libbsp/i386/shared/irq/irq.h
new file mode 100644
index 0000000000..3fba2db09e
--- /dev/null
+++ b/c/src/lib/libbsp/i386/shared/irq/irq.h
@@ -0,0 +1,260 @@
+/* irq.h
+ *
+ * This include file describe the data structure and the functions implemented
+ * by rtems to write interrupt handlers.
+ *
+ * CopyRight (C) 1998 valette@crf.canon.fr
+ *
+ * This code is heavilly inspired by the public specification of STREAM V2
+ * that can be found at :
+ *
+ * <http://www.chorus.com/Documentation/index.html> by following
+ * the STREAM API Specification Document link.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef _IRQ_H_
+#define _IRQ_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Include some preprocessor value also used by assember code
+ */
+
+#include <irq_asm.h>
+#include <rtems.h>
+/*-------------------------------------------------------------------------+
+| Constants
++--------------------------------------------------------------------------*/
+
+typedef enum {
+ /* Base vector for our IRQ handlers. */
+ PC386_IRQ_VECTOR_BASE = PC386_ASM_IRQ_VECTOR_BASE,
+ PC_386_IRQ_LINES_NUMBER = 16,
+ PC_386_LOWEST_OFFSET = 0,
+ PC_386_MAX_OFFSET = PC_386_IRQ_LINES_NUMBER - 1,
+ /*
+ * Interrupt offset in comparison to PC386_ASM_IRQ_VECTOR_BASE
+ * NB : 1) Interrupt vector number in IDT = offset + PC386_ASM_IRQ_VECTOR_BASE
+ * 2) The same name should be defined on all architecture
+ * so that handler connexion can be unchanged.
+ */
+ PC_386_PERIODIC_TIMER = 0,
+
+ PC_386_KEYBOARD = 1,
+
+ PC386_UART_COM2_IRQ = 3,
+
+ PC386_UART_COM1_IRQ = 4,
+
+ PC_386_RT_TIMER1 = 8
+
+}rtems_irq_symbolic_name;
+
+
+
+
+/*
+ * Type definition for RTEMS managed interrupts
+ */
+typedef unsigned char rtems_irq_prio;
+typedef unsigned short rtems_i8259_masks;
+
+extern rtems_i8259_masks i8259s_cache;
+
+struct __rtems_irq_connect_data__; /* forward declaratiuon */
+
+typedef void (*rtems_irq_hdl) (void);
+typedef void (*rtems_irq_enable) (const struct __rtems_irq_connect_data__*);
+typedef void (*rtems_irq_disable) (const struct __rtems_irq_connect_data__*);
+typedef int (*rtems_irq_is_enabled) (const struct __rtems_irq_connect_data__*);
+
+typedef struct __rtems_irq_connect_data__ {
+ /*
+ * IRQ line
+ */
+ rtems_irq_symbolic_name name;
+ /*
+ * handler. See comment on handler properties below in function prototype.
+ */
+ rtems_irq_hdl hdl;
+ /*
+ * function for enabling interrupts at device level (ONLY!).
+ * The BSP code will automatically enable it at i8259s level.
+ * RATIONALE : anyway such code has to exist in current driver code.
+ * It is usually called immediately AFTER connecting the interrupt handler.
+ * RTEMS may well need such a function when restoring normal interrupt
+ * processing after a debug session.
+ *
+ */
+ rtems_irq_enable on;
+ /*
+ * function for disabling interrupts at device level (ONLY!).
+ * The code will disable it at i8259s level. RATIONALE : anyway
+ * such code has to exist for clean shutdown. It is usually called
+ * BEFORE disconnecting the interrupt. RTEMS may well need such
+ * a function when disabling normal interrupt processing for
+ * a debug session. May well be a NOP function.
+ */
+ rtems_irq_disable off;
+ /*
+ * function enabling to know what interrupt may currently occur
+ * if someone manipulates the i8259s interrupt mask without care...
+ */
+ rtems_irq_is_enabled isOn;
+}rtems_irq_connect_data;
+
+typedef struct {
+ /*
+ * size of all the table fields (*Tbl) described below.
+ */
+ unsigned int irqNb;
+ /*
+ * Default handler used when disconnecting interrupts.
+ */
+ rtems_irq_connect_data defaultEntry;
+ /*
+ * Table containing initials/current value.
+ */
+ rtems_irq_connect_data* irqHdlTbl;
+ /*
+ * actual value of PC386_IRQ_VECTOR_BASE...
+ */
+ rtems_irq_symbolic_name irqBase;
+ /*
+ * software priorities associated with interrupts.
+ * if irqPrio [i] > intrPrio [j] it means that
+ * interrupt handler hdl connected for interrupt name i
+ * will not be interrupted by the handler connected for interrupt j
+ * The interrupt source will be physically masked at i8259 level.
+ */
+ rtems_irq_prio* irqPrioTbl;
+}rtems_irq_global_settings;
+
+
+
+
+/*-------------------------------------------------------------------------+
+| Function Prototypes.
++--------------------------------------------------------------------------*/
+/*
+ * ------------------------ Intel 8259 (or emulation) Mngt Routines -------
+ */
+
+/*
+ * function to disable a particular irq at 8259 level. After calling
+ * this function, even if the device asserts the interrupt line it will
+ * not be propagated further to the processor
+ */
+int pc386_irq_disable_at_i8259s (const rtems_irq_symbolic_name irqLine);
+/*
+ * function to enable a particular irq at 8259 level. After calling
+ * this function, if the device asserts the interrupt line it will
+ * be propagated further to the processor
+ */
+int pc386_irq_enable_at_i8259s (const rtems_irq_symbolic_name irqLine);
+/*
+ * function to acknoledge a particular irq at 8259 level. After calling
+ * this function, if a device asserts an enabled interrupt line it will
+ * be propagated further to the processor. Mainly usefull for people
+ * writting raw handlers as this is automagically done for rtems managed
+ * handlers.
+ */
+int pc386_irq_ack_at_i8259s (const rtems_irq_symbolic_name irqLine);
+/*
+ * function to check if a particular irq is enabled at 8259 level. After calling
+ */
+int pc386_irq_enabled_at_i8259s (const rtems_irq_symbolic_name irqLine);
+/*
+ * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
+ */
+/*
+ * function to connect a particular irq handler. This hanlder will NOT be called
+ * directly as the result of the corresponding interrupt. Instead, a RTEMS
+ * irq prologue will be called that will :
+ *
+ * 1) save the C scratch registers,
+ * 2) switch to a interrupt stack if the interrupt is not nested,
+ * 3) store the current i8259s' interrupt masks
+ * 4) modify them to disable the current interrupt at 8259 level (and may
+ * be others depending on software priorities)
+ * 5) aknowledge the i8259s',
+ * 6) demask the processor,
+ * 7) call the application handler
+ *
+ * As a result the hdl function provided
+ *
+ * a) can perfectly be written is C,
+ * b) may also well directly call the part of the RTEMS API that can be used
+ * from interrupt level,
+ * c) It only responsible for handling the jobs that need to be done at
+ * the device level including (aknowledging/re-enabling the interrupt at device,
+ * level, getting the data,...)
+ *
+ * When returning from the function, the following will be performed by
+ * the RTEMS irq epilogue :
+ *
+ * 1) masks the interrupts again,
+ * 2) restore the original i8259s' interrupt masks
+ * 3) switch back on the orinal stack if needed,
+ * 4) perform rescheduling when necessary,
+ * 5) restore the C scratch registers...
+ * 6) restore initial execution flow
+ *
+ */
+int pc386_install_rtems_irq_handler (const rtems_irq_connect_data*);
+/*
+ * function to get the current RTEMS irq handler for ptr->name. It enables to
+ * define hanlder chain...
+ */
+int pc386_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr);
+/*
+ * function to get disconnect the RTEMS irq handler for ptr->name.
+ * This function checks that the value given is the current one for safety reason.
+ * The user can use the previous function to get it.
+ */
+int pc386_remove_rtems_irq_handler (const rtems_irq_connect_data*);
+
+/*
+ * ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
+ */
+/*
+ * (Re) Initialize the RTEMS interrupt management.
+ *
+ * The result of calling this function will be the same as if each individual
+ * handler (config->irqHdlTbl[i].hdl) different from "config->defaultEntry.hdl"
+ * has been individualy connected via
+ * pc386_install_rtems_irq_handler(&config->irqHdlTbl[i])
+ * And each handler currently equal to config->defaultEntry.hdl
+ * has been previously disconnected via
+ * pc386_remove_rtems_irq_handler (&config->irqHdlTbl[i])
+ *
+ * This is to say that all information given will be used and not just
+ * only the space.
+ *
+ * CAUTION : the various table address contained in config will be used
+ * directly by the interrupt mangement code in order to save
+ * data size so they must stay valid after the call => they should
+ * not be modified or declared on a stack.
+ */
+
+int pc386_rtems_irq_mngt_set(rtems_irq_global_settings* config);
+/*
+ * (Re) get info on current RTEMS interrupt management.
+ */
+int pc386_rtems_irq_mngt_get(rtems_irq_global_settings**);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _IRQ_H_ */
+/* end of include file */
diff --git a/c/src/lib/libbsp/i386/shared/irq/irq_asm.h b/c/src/lib/libbsp/i386/shared/irq/irq_asm.h
new file mode 100644
index 0000000000..bf6bb17e8e
--- /dev/null
+++ b/c/src/lib/libbsp/i386/shared/irq/irq_asm.h
@@ -0,0 +1,30 @@
+/* irq_asm.h
+ *
+ * This include file has defines to represent some contant used
+ * to program and manage the Intel 8259 interrupt controller
+ *
+ *
+ * COPYRIGHT (c) 1998 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+#ifndef __IRQ_ASM_H__
+#define __IRQ_ASM_H__
+
+#define PC386_ASM_IRQ_VECTOR_BASE 0x20
+ /* PIC's command and mask registers */
+#define PIC_MASTER_COMMAND_IO_PORT 0x20 /* Master PIC command register */
+#define PIC_SLAVE_COMMAND_IO_PORT 0xa0 /* Slave PIC command register */
+#define PIC_MASTER_IMR_IO_PORT 0x21 /* Master PIC Interrupt Mask Register */
+#define PIC_SLAVE_IMR_IO_PORT 0xa1 /* Slave PIC Interrupt Mask Register */
+
+ /* Command for specific EOI (End Of Interrupt): Interrupt acknowledge */
+#define PIC_EOSI 0x60 /* End of Specific Interrupt (EOSI) */
+#define PIC_EOI 0x20 /* Generic End of Interrupt (EOI) */
+
+
+#endif
diff --git a/c/src/lib/libbsp/i386/shared/irq/irq_asm.s b/c/src/lib/libbsp/i386/shared/irq/irq_asm.s
new file mode 100644
index 0000000000..7765a9dd22
--- /dev/null
+++ b/c/src/lib/libbsp/i386/shared/irq/irq_asm.s
@@ -0,0 +1,261 @@
+/* irq.c
+ *
+ * This file contains the implementation of the function described in irq.h
+ *
+ * CopyRight (C) 1998 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "asm.h"
+#include <irq_asm.h>
+
+.set SAVED_REGS , 32 # space consumed by saved regs
+.set EIP_OFFSET , SAVED_REGS # offset of tasks eip
+.set CS_OFFSET , EIP_OFFSET+4 # offset of tasks code segment
+.set EFLAGS_OFFSET , CS_OFFSET+4 # offset of tasks eflags
+
+
+/*PAGE
+ * void _new_ISR_Displatch()
+ *
+ * Entry point from the outermost interrupt service routine exit.
+ * The current stack is the supervisor mode stack.
+ */
+
+ PUBLIC (_new_ISR_Displatch)
+SYM (_New_ISR_Displatch):
+
+ call SYM (_Thread_Dispatch) # invoke Dispatcher
+
+ /*
+ * BEGINNING OF DE-ESTABLISH SEGMENTS
+ *
+ * NOTE: Make sure there is code here if code is added to
+ * load the segment registers.
+ *
+ */
+
+ /***** DE-ESTABLISH SEGMENTS CODE GOES HERE ****/
+
+ /*
+ * END OF DE-ESTABLISH SEGMENTS
+ */
+
+ popa # restore general registers
+ iret # return to interrupted thread
+
+
+SYM (_New_ISR_Handler):
+ /*
+ * Before this was point is reached the vectors unique
+ * entry point did the following:
+ *
+ * 1. saved sctach registers registers eax edx ecx"
+ * 2. put the vector number in ecx.
+ *
+ * BEGINNING OF ESTABLISH SEGMENTS
+ *
+ * WARNING: If an interrupt can occur when the segments are
+ * not correct, then this is where we should establish
+ * the segments. In addition to establishing the
+ * segments, it may be necessary to establish a stack
+ * in the current data area on the outermost interrupt.
+ *
+ * NOTE: If the previous values of the segment registers are
+ * pushed, do not forget to adjust SAVED_REGS.
+ *
+ * NOTE: Make sure the exit code which restores these
+ * when this type of code is needed.
+ */
+
+ /***** ESTABLISH SEGMENTS CODE GOES HERE ******/
+
+ /*
+ * END OF ESTABLISH SEGMENTS
+ */
+
+ /*
+ * Now switch stacks if necessary
+ */
+
+ movw SYM (i8259s_cache), ax # move current i8259 interrupt mask in ax
+ pushl eax # push it on the stack
+ /*
+ * compute the new PIC mask:
+ *
+ * <new mask> = <old mask> | irq_mask_or_tbl[<intr number aka ecx>]
+ */
+ movw SYM (irq_mask_or_tbl) (,ecx,2), dx
+ orw dx, ax
+ /*
+ * Install new computed value on the i8259 and update cache
+ * accordingly
+ */
+ movw ax, SYM (i8259s_cache)
+ outb $PIC_MASTER_IMR_IO_PORT
+ movb ah, al
+ outb $PIC_SLAVE_IMR_IO_PORT
+
+ /*
+ * acknowledge the interrupt
+ *
+ */
+ movb $PIC_EOI, al
+ cmpl $7, ecx
+ jbe .master
+ outb $PIC_SLAVE_COMMAND_IO_PORT
+.master:
+ outb $PIC_MASTER_COMMAND_IO_PORT
+
+.check_stack_switch:
+ pushl ebp
+ movl esp, ebp # ebp = previous stack pointer
+ cmpl $0, SYM (_ISR_Nest_level) # is this the outermost interrupt?
+ jne nested # No, then continue
+ movl SYM (_CPU_Interrupt_stack_high), esp
+
+ /*
+ * We want to insure that the old stack pointer is on the
+ * stack we will be on at the end of the ISR when we restore it.
+ * By saving it on every interrupt, all we have to do is pop it
+ * near the end of every interrupt.
+ */
+
+nested:
+ incl SYM (_ISR_Nest_level) # one nest level deeper
+ incl SYM (_Thread_Dispatch_disable_level) # disable multitasking
+ /*
+ * re-enable interrupts at processor level as the current
+ * interrupt source is now masked via i8259
+ */
+ sti
+
+ /*
+ * ECX is preloaded with the vector number but it is a scratch register
+ * so we must save it again.
+ */
+
+ pushl ecx # push vector number
+ mov SYM (current_irq) (,ecx,4),eax
+ # eax = Users handler
+ call *eax # invoke user ISR
+ /*
+ * disable interrupts_again
+ */
+ cli
+ popl ecx # ecx = vector number
+ /*
+ * restore stack
+ */
+ movl ebp, esp
+ popl ebp
+
+ /*
+ * restore the original i8259 masks
+ */
+ popl eax
+ movw ax, SYM (i8259s_cache)
+ outb $PIC_MASTER_IMR_IO_PORT
+ movb ah, al
+ outb $PIC_SLAVE_IMR_IO_PORT
+
+
+ decl SYM (_ISR_Nest_level) # one less ISR nest level
+ # If interrupts are nested,
+ # then dispatching is disabled
+
+ decl SYM (_Thread_Dispatch_disable_level)
+ # unnest multitasking
+ # Is dispatch disabled
+ jne .exit # Yes, then exit
+
+ cmpl $0, SYM (_Context_Switch_necessary)
+ # Is task switch necessary?
+ jne bframe # Yes, then build stack
+
+ cmpl $0, SYM (_ISR_Signals_to_thread_executing)
+ # signals sent to Run_thread
+ # while in interrupt handler?
+ je .exit # No, exit
+
+bframe:
+ movl $0, SYM (_ISR_Signals_to_thread_executing)
+ /*
+ * complete code as if a pusha had been executed on entry
+ */
+ pushl ebx
+ pushl esp
+ pushl ebp
+ pushl esi
+ pushl edi
+ # push the isf for Isr_dispatch
+ pushl EFLAGS_OFFSET(esp) # push tasks eflags
+ push cs # cs of Isr_dispatch
+ pushl $ SYM (_New_ISR_Displatch)# entry point
+ iret
+
+.exit:
+ /*
+ * BEGINNING OF DE-ESTABLISH SEGMENTS
+ *
+ * NOTE: Make sure there is code here if code is added to
+ * load the segment registers.
+ *
+ */
+
+ /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/
+
+ /*
+ * END OF DE-ESTABLISH SEGMENTS
+ */
+ popl edx
+ popl ecx
+ popl eax
+ iret
+
+#define DISTINCT_INTERRUPT_ENTRY(_vector) \
+ .p2align 4 ; \
+ PUBLIC (rtems_irq_prologue_ ## _vector ) ; \
+SYM (rtems_irq_prologue_ ## _vector ): \
+ pushl eax ; \
+ pushl ecx ; \
+ pushl edx ; \
+ movl $ _vector, ecx ; \
+ jmp SYM (_New_ISR_Handler) ;
+
+DISTINCT_INTERRUPT_ENTRY(0)
+DISTINCT_INTERRUPT_ENTRY(1)
+DISTINCT_INTERRUPT_ENTRY(2)
+DISTINCT_INTERRUPT_ENTRY(3)
+DISTINCT_INTERRUPT_ENTRY(4)
+DISTINCT_INTERRUPT_ENTRY(5)
+DISTINCT_INTERRUPT_ENTRY(6)
+DISTINCT_INTERRUPT_ENTRY(7)
+DISTINCT_INTERRUPT_ENTRY(8)
+DISTINCT_INTERRUPT_ENTRY(9)
+DISTINCT_INTERRUPT_ENTRY(10)
+DISTINCT_INTERRUPT_ENTRY(11)
+DISTINCT_INTERRUPT_ENTRY(12)
+DISTINCT_INTERRUPT_ENTRY(13)
+DISTINCT_INTERRUPT_ENTRY(14)
+DISTINCT_INTERRUPT_ENTRY(15)
+
+ /*
+ * routine used to initialize the IDT by default
+ */
+
+PUBLIC (default_raw_idt_handler)
+PUBLIC (raw_idt_notify)
+
+SYM (default_raw_idt_handler):
+ pusha
+ cld
+ call raw_idt_notify
+ popa
+ iret
+
diff --git a/c/src/lib/libbsp/i386/shared/irq/irq_init.c b/c/src/lib/libbsp/i386/shared/irq/irq_init.c
new file mode 100644
index 0000000000..0910bdef56
--- /dev/null
+++ b/c/src/lib/libbsp/i386/shared/irq/irq_init.c
@@ -0,0 +1,200 @@
+/* irq_init.c
+ *
+ * This file contains the implementation of rtems initialization
+ * related to interrupt handling.
+ *
+ * CopyRight (C) 1998 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <libcpu/cpu.h>
+#include <irq.h>
+#include <bsp.h>
+
+/*
+ * rtems prologue generated in irq_asm.S
+ */
+extern void rtems_irq_prologue_0();
+extern void rtems_irq_prologue_1();
+extern void rtems_irq_prologue_2();
+extern void rtems_irq_prologue_3();
+extern void rtems_irq_prologue_4();
+extern void rtems_irq_prologue_5();
+extern void rtems_irq_prologue_6();
+extern void rtems_irq_prologue_7();
+extern void rtems_irq_prologue_8();
+extern void rtems_irq_prologue_9();
+extern void rtems_irq_prologue_10();
+extern void rtems_irq_prologue_11();
+extern void rtems_irq_prologue_12();
+extern void rtems_irq_prologue_13();
+extern void rtems_irq_prologue_14();
+extern void rtems_irq_prologue_15();
+/*
+ * default idt vector
+ */
+extern void default_raw_idt_handler();
+/*
+ * default on/off function
+ */
+static void nop_func(){}
+/*
+ * default isOn function
+ */
+static int not_connected() {return 0;}
+
+
+static rtems_raw_irq_connect_data idtHdl[IDT_SIZE];
+
+/*
+ * Table used to store rtems managed interrupt handlers.
+ * Borrow the table to store raw handler entries at the beginning.
+ * The table will be reinitialized before the call to pc386_rtems_irq_mngt_set().
+ */
+static rtems_irq_connect_data rtemsIrq[PC_386_IRQ_LINES_NUMBER] = {
+ {0,(rtems_irq_hdl)rtems_irq_prologue_0},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_1},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_2},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_3},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_4},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_5},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_6},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_7},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_8},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_9},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_10},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_11},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_12},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_13},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_14},
+ {0,(rtems_irq_hdl)rtems_irq_prologue_15}
+};
+
+static rtems_raw_irq_connect_data defaultRawIrq = {
+ /* vectorIdex, hdl , on , off , isOn */
+ 0, default_raw_idt_handler ,nop_func , nop_func, not_connected
+};
+
+static rtems_irq_connect_data defaultIrq = {
+ /* vectorIdex, hdl , on , off , isOn */
+ 0, nop_func , nop_func , nop_func , not_connected
+};
+
+static rtems_irq_prio irqPrioTable[PC_386_IRQ_LINES_NUMBER]={
+ /*
+ * actual rpiorities for interrupt :
+ * 0 means that only current interrupt is masked
+ * 255 means all other interrupts are masked
+ * The second entry has a priority of 255 because
+ * it is the slave pic entry and is should always remain
+ * unamsked.
+ */
+ 0,0,
+ 255,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+
+
+static interrupt_gate_descriptor idtEntry;
+
+static rtems_irq_global_settings initial_config;
+static rtems_raw_irq_global_settings raw_initial_config;
+
+void raw_idt_notify()
+{
+ printk("raw_idt_notify has been called \n");
+}
+
+void rtems_irq_mngt_init()
+{
+ int i;
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+ unsigned int level;
+
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ _CPU_ISR_Disable(level);
+
+ /*
+ * Init the complete IDT vector table with defaultRawIrq value
+ */
+ for (i = 0; i < IDT_SIZE; i++) {
+ idtHdl[i] = defaultRawIrq;
+ }
+ raw_initial_config.idtSize = IDT_SIZE;
+ raw_initial_config.defaultRawEntry = defaultRawIrq;
+ raw_initial_config.rawIrqHdlTbl = idtHdl;
+
+ if (!i386_init_idt (&raw_initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ _IBMPC_initVideo();
+ printk("Unable to initialize IDT!!! System locked\n");
+ while (1);
+ }
+ /*
+ * Patch the entry that will be used by RTEMS for interrupt management
+ * with RTEMS prologue.
+ */
+ for (i = 0; i < PC_386_IRQ_LINES_NUMBER; i++) {
+ create_interrupt_gate_descriptor(&idtEntry,(rtems_raw_irq_hdl) rtemsIrq[i].hdl);
+ idt_entry_tbl[i + PC386_ASM_IRQ_VECTOR_BASE] = idtEntry;
+ }
+ /*
+ * At this point we have completed the initialization of IDT
+ * with raw handlers. We must now initialize the higher level
+ * interrupt management.
+ */
+ /*
+ * re-init the rtemsIrq table
+ */
+ for (i = 0; i < PC_386_IRQ_LINES_NUMBER; i++) {
+ rtemsIrq[i] = defaultIrq;
+ }
+ /*
+ * Init initial Interrupt management config
+ */
+ initial_config.irqNb = PC_386_IRQ_LINES_NUMBER;
+ initial_config.defaultEntry = defaultIrq;
+ initial_config.irqHdlTbl = rtemsIrq;
+ initial_config.irqBase = PC386_ASM_IRQ_VECTOR_BASE;
+ initial_config.irqPrioTbl = irqPrioTable;
+ if (!pc386_rtems_irq_mngt_set(&initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ _IBMPC_initVideo();
+ printk("Unable to initialize RTEMS interrupt Management!!! System locked\n");
+ while (1);
+ }
+
+#define DEBUG
+#ifdef DEBUG
+ {
+ /*
+ * following adresses should be the same
+ */
+ unsigned tmp;
+
+ _IBMPC_initVideo();
+
+ printk("idt_entry_tbl = %x Interrupt_descriptor_table addr = %x\n",
+ idt_entry_tbl, &Interrupt_descriptor_table);
+ tmp = (unsigned) get_hdl_from_vector (PC386_ASM_IRQ_VECTOR_BASE + PC_386_PERIODIC_TIMER);
+ printk("clock isr address from idt = %x should be %x\n",
+ tmp, (unsigned) rtems_irq_prologue_0);
+ }
+ printk("i8259s_cache = %x\n", * (unsigned short*) &i8259s_cache);
+ debugPollingGetChar();
+#endif
+ asm volatile ("sti");
+}