IRQ_CONNECT_STATIC implementation for x86 platform
In order to simplify x86 interrupt stub creation, each interrupt
controller implements an interrupt stub definition macro.
Add IRQ_CONNECT_STATIC() for static interrupt registration, and
construct the interrupt stubs name from device and interrupt
handler names.
Add IRQ_CONFIG() macro for the interrupt controller configuration.
On x86 platform it programs APIC to associate an IRQ number with
the interupt vector.
Add HPET_TIMER0_INT_PRI parameter to Quark platform header to
make it build correctly.
Change-Id: I24ad25e1aa807ffa63733a27ad882877fcad72af
Signed-off-by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
diff --git a/arch/x86/driver_static_irq_stubs.S b/arch/x86/driver_static_irq_stubs.S
index b5bf2a1..246945d 100644
--- a/arch/x86/driver_static_irq_stubs.S
+++ b/arch/x86/driver_static_irq_stubs.S
@@ -46,30 +46,37 @@
#include <drivers/pic.h>
#include <drivers/system_timer.h>
- /* exports (internal APIs) */
-#if defined(CONFIG_LOAPIC_TIMER)
- GTEXT(_loapic_timer_irq_stub)
-#endif
-
-#if defined(CONFIG_HPET_TIMER)
- GTEXT(_hpetIntStub)
-#endif
-
#if defined (CONFIG_PIC)
- GTEXT(_masterStrayIntStub)
- GTEXT(_slaveStrayIntStub)
+ GTEXT(_pic_master__i8259_boi_master_stub)
+ GTEXT(_pic_slave__i8259_boi_slave_stub)
#endif
#if defined (CONFIG_PIT)
- GTEXT(_i8253_interrupt_stub)
+ pic_master_mkstub i8253 _timer_int_handler
+#endif
+
+#if defined(CONFIG_LOAPIC_TIMER)
+ loapic_mkstub loapic _timer_int_handler
+#endif
+
+#if defined(CONFIG_HPET_TIMER)
+ ioapic_mkstub hpet _timer_int_handler
#endif
#if defined(CONFIG_BLUETOOTH_UART)
- GTEXT(_bluetooth_uart_stub)
-#endif /* CONFIG_BLUETOOTH */
+#if defined(CONFIG_PIC)
+ pic_master_mkstub bluetooth bt_uart_isr
+#elif defined(CONFIG_IOAPIC)
+ ioapic_mkstub bluetooth bt_uart_isr
+#endif /* CONFIG_PIC */
+#endif /* CONFIG_BLUETOOTH_UART */
#if defined(CONFIG_CONSOLE_HANDLER)
- GTEXT(_console_uart_stub)
+#if defined(CONFIG_PIC)
+ pic_master_mkstub console uart_console_isr
+#elif defined(CONFIG_IOAPIC)
+ ioapic_mkstub console uart_console_isr
+#endif /* CONFIG_PIC */
#endif /* CONFIG_CONSOLE_HANDLER */
/* externs (internal APIs) */
@@ -77,28 +84,8 @@
GTEXT(_IntEnt)
GTEXT(_IntExit)
-#if defined(CONFIG_LOAPIC_TIMER)
-SECTION_FUNC (TEXT, _loapic_timer_irq_stub)
- call _IntEnt /* Inform kernel interrupt has begun */
- pushl $0 /* Push dummy parameter */
- call _timer_int_handler /* Call actual interrupt handler */
- call _loapic_eoi /* Inform loapic interrupt is done */
- addl $4, %esp /* Clean-up stack from push above */
- jmp _IntExit /* Inform kernel interrupt is done */
-#endif /* CONFIG_LOAPIC_TIMER */
-
-#if defined(CONFIG_HPET_TIMER)
-SECTION_FUNC(TEXT, _hpetIntStub)
- call _IntEnt /* Inform kernel interrupt has begun */
- pushl $0 /* Push dummy parameter */
- call _timer_int_handler /* Call actual interrupt handler */
- call _ioapic_eoi /* Inform ioapic interrupt is done */
- addl $4, %esp /* Clean-up stack from push above */
- jmp _IntExit /* Inform kernel interrupt is done */
-#endif /* CONFIG_HPET_TIMER */
-
#if defined(CONFIG_PIC)
-SECTION_FUNC(TEXT, _masterStrayIntStub)
+SECTION_FUNC(TEXT, _pic_master__i8259_boi_master_stub)
/*
* Handle possible spurious (stray) interrupts on IRQ 7. Since on this
* particular BSP, no device is hooked up to IRQ 7, a C level ISR is
@@ -118,7 +105,7 @@
* jmp _IntExit /+ Inform kernel interrupt is done +/
*/
-SECTION_FUNC(TEXT, _slaveStrayIntStub)
+SECTION_FUNC(TEXT, _pic_slave__i8259_boi_slave_stub)
/*
* Handle possible spurious (stray) interrupts on IRQ 15 (slave PIC
* IRQ 7). Since on this particular BSP, no device is hooked up to
@@ -140,56 +127,4 @@
*/
#endif /* CONFIG_PIC */
-#if defined(CONFIG_PIT)
-SECTION_FUNC(TEXT, _i8253_interrupt_stub)
- call _IntEnt /* Inform kernel interrupt has begun */
- pushl $0 /* Push dummy parameter */
- call _timer_int_handler /* Call actual interrupt handler */
- call _i8259_eoi_master /* Inform the PIC interrupt is done */
- addl $4, %esp /* Clean-up stack from push above */
- jmp _IntExit /* Inform kernel interrupt is done */
-#endif /* CONFIG_PIT */
-
-#if defined(CONFIG_BLUETOOTH_UART)
-#if defined(CONFIG_PIC)
-SECTION_FUNC(TEXT, _bluetooth_uart_stub)
- call _IntEnt /* Inform kernel interrupt has begun */
- pushl $0 /* Push dummy parameter */
- call bt_uart_isr /* Call actual interrupt handler */
- call _i8259_eoi_master /* Inform the PIC interrupt is done */
- addl $4, %esp /* Clean-up stack from push above */
- jmp _IntExit /* Inform kernel interrupt is done */
-#elif defined(CONFIG_IOAPIC)
-SECTION_FUNC(TEXT, _bluetooth_uart_stub)
- call _IntEnt /* Inform kernel interrupt has begun */
- pushl $0 /* Push dummy parameter */
- call bt_uart_isr /* Call actual interrupt handler */
- call _ioapic_eoi /* Inform the PIC interrupt is done */
- addl $4, %esp /* Clean-up stack from push above */
- jmp _IntExit /* Inform kernel interrupt is done */
-#endif /* CONFIG_PIC */
-#endif /* CONFIG_BLUETOOTH_UART */
-
-#if defined(CONFIG_CONSOLE_HANDLER)
-
-#if defined(CONFIG_PIC)
-SECTION_FUNC(TEXT, _console_uart_stub)
- call _IntEnt /* Inform kernel interrupt has begun */
- pushl $0 /* Push dummy parameter */
- call uart_console_isr /* Call actual interrupt handler */
- call _i8259_eoi_master /* Inform the PIC interrupt is done */
- addl $4, %esp /* Clean-up stack from push above */
- jmp _IntExit /* Inform kernel interrupt is done */
-#elif defined(CONFIG_IOAPIC)
-SECTION_FUNC(TEXT, _console_uart_stub)
- call _IntEnt /* Inform kernel interrupt has begun */
- pushl $0 /* Push dummy parameter */
- call uart_console_isr /* Call actual interrupt handler */
- call _ioapic_eoi /* Inform the PIC interrupt is done */
- addl $4, %esp /* Clean-up stack from push above */
- jmp _IntExit /* Inform kernel interrupt is done */
-#endif /* CONFIG_PIC */
-
-#endif /* CONFIG_CONSOLE_HANDLER */
-
#endif /* !CONFIG_DYNAMIC_INT_STUBS */
diff --git a/arch/x86/generic_pc/board.h b/arch/x86/generic_pc/board.h
index a98ac82..c7a9822 100644
--- a/arch/x86/generic_pc/board.h
+++ b/arch/x86/generic_pc/board.h
@@ -167,15 +167,6 @@
#ifndef _ASMLANGUAGE
/*
- * The <pri> parameter is deliberately ignored. For this BSP, the macro just has
- * to make sure that unique vector numbers are generated.
- */
-#define SYS_INT_REGISTER(s, irq, pri) \
- NANO_CPU_INT_REGISTER(s, INT_VEC_IRQ0 + (irq), 0)
-#endif
-
-#ifndef _ASMLANGUAGE
-/*
* Device drivers utilize the macros PLB_BYTE_REG_WRITE() and
* PLB_BYTE_REG_READ() to access byte-wide registers on the processor
* local bus (PLB), as opposed to a PCI bus, for example. Boards are
diff --git a/arch/x86/generic_pc/system.c b/arch/x86/generic_pc/system.c
index ff142a7..aa83df9 100644
--- a/arch/x86/generic_pc/system.c
+++ b/arch/x86/generic_pc/system.c
@@ -105,9 +105,8 @@
#endif /* DO_CONSOLE_INIT */
#if defined(CONFIG_CONSOLE_HANDLER)
-extern void *_console_uart_stub;
-SYS_INT_REGISTER(_console_uart_stub,
- CONFIG_UART_CONSOLE_IRQ, CONFIG_UART_CONSOLE_INT_PRI);
+IRQ_CONNECT_STATIC(console, CONFIG_UART_CONSOLE_IRQ,
+ CONFIG_UART_CONSOLE_INT_PRI, uart_console_isr, 0);
#endif /* CONFIG_CONSOLE_HANDLER */
#if defined(DO_CONSOLE_INIT)
@@ -143,10 +142,8 @@
#if defined(CONFIG_BLUETOOTH_UART)
#include <bluetooth/uart.h>
/* Interrupt handling */
-extern void *_bluetooth_uart_stub;
-SYS_INT_REGISTER(_bluetooth_uart_stub,
- CONFIG_BLUETOOTH_UART_IRQ,
- CONFIG_BLUETOOTH_UART_INT_PRI);
+IRQ_CONNECT_STATIC(bluetooth, CONFIG_BLUETOOTH_UART_IRQ,
+ CONFIG_BLUETOOTH_UART_INT_PRI, bt_uart_isr, 0);
#endif /* CONFIG_BLUETOOTH_UART */
static void bluetooth_init(void)
{
diff --git a/arch/x86/quark/board.h b/arch/x86/quark/board.h
index 259a5af..0034eea 100644
--- a/arch/x86/quark/board.h
+++ b/arch/x86/quark/board.h
@@ -77,6 +77,7 @@
#define HPET_TIMER0_IRQ (20)
#define HPET_TIMER0_VEC (HPET_TIMER0_IRQ + INT_VEC_IRQ0)
+#define HPET_TIMER0_INT_PRI (4)
/* HPET uses falling edge triggered interrupt */
#define HPET_IOAPIC_FLAGS (IOAPIC_EDGE | IOAPIC_LOW)
@@ -129,15 +130,6 @@
*/
#define LOAPIC_VEC_BASE(x) (x + INT_VEC_IRQ0 + IOAPIC_NUM_RTES)
-#ifndef _ASMLANGUAGE
-/*
- * The <pri> parameter is deliberately ignored. For this BSP, the macro just has
- * to make sure that unique vector numbers are generated.
- */
-#define SYS_INT_REGISTER(s, irq, pri) \
- NANO_CPU_INT_REGISTER(s, INT_VEC_IRQ0 + (irq), 0)
-#endif
-
/* PCI definitions */
#define PCI_BUS_NUMBERS 2
diff --git a/drivers/interrupt_controller/system_pic.c b/drivers/interrupt_controller/system_pic.c
index 58d3c41..534355f 100644
--- a/drivers/interrupt_controller/system_pic.c
+++ b/drivers/interrupt_controller/system_pic.c
@@ -42,10 +42,8 @@
#include <drivers/pic.h>
/* Handle possible stray or spurious interrupts on the master and slave PICs */
-extern void _masterStrayIntStub(void);
-extern void _slaveStrayIntStub(void);
-SYS_INT_REGISTER(_masterStrayIntStub, PIC_MASTER_STRAY_INT_LVL, 0);
-SYS_INT_REGISTER(_slaveStrayIntStub, PIC_SLAVE_STRAY_INT_LVL, 0);
+IRQ_CONNECT_STATIC(pic_master, PIC_MASTER_STRAY_INT_LVL, 0, _i8259_boi_master, 0);
+IRQ_CONNECT_STATIC(pic_slave, PIC_SLAVE_STRAY_INT_LVL, 0, _i8259_boi_slave, 0);
/*******************************************************************************
*
@@ -148,3 +146,26 @@
return vector;
}
+
+/*******************************************************************************
+*
+* _SysIntVecProgram - program interrupt controller
+*
+* This BSP provided routine programs the appropriate interrupt controller
+* with the given vector based on the given IRQ parameter.
+*
+* Drivers call this routine instead of irq_connect() when interrupts are
+* configured statically.
+*
+* For PIC-equipped boards this routine does nothing, as PIC does not need
+* any additional setup
+*
+*/
+
+void _SysIntVecProgram(unsigned int vector, /* vector number */
+ unsigned int irq /* virtualized IRQ */
+ )
+{
+ ARG_UNUSED(vector);
+ ARG_UNUSED(irq);
+}
diff --git a/drivers/timer/hpet.c b/drivers/timer/hpet.c
index 002fd6d..b6cfcfe 100644
--- a/drivers/timer/hpet.c
+++ b/drivers/timer/hpet.c
@@ -195,9 +195,9 @@
#ifdef CONFIG_DYNAMIC_INT_STUBS
static NANO_CPU_INT_STUB_DECL(_hpetIntStub); /* interrupt stub memory */
#else /* !CONFIG_DYNAMIC_INT_STUBS */
-extern void *_hpetIntStub(void); /* interrupt stub code */
-SYS_INT_REGISTER(_hpetIntStub, HPET_TIMER0_IRQ, HPET_TIMER0_INT_PRI);
-#endif /* CONFIG_DYNAMIC_INT_STUBS */
+IRQ_CONNECT_STATIC(hpet, HPET_TIMER0_IRQ, HPET_TIMER0_INT_PRI,
+ _timer_int_handler, 0);
+#endif
#ifdef CONFIG_INT_LATENCY_BENCHMARK
static uint32_t main_count_first_irq_value = 0;
@@ -626,7 +626,7 @@
* has to be programmed into the interrupt controller.
*/
- _SysIntVecProgram(HPET_TIMER0_VEC, HPET_TIMER0_IRQ);
+ IRQ_CONFIG(hpet, HPET_TIMER0_IRQ);
#endif
/* enable the IRQ in the interrupt controller */
diff --git a/drivers/timer/i8253.c b/drivers/timer/i8253.c
index de1e14f..f08cb0f 100644
--- a/drivers/timer/i8253.c
+++ b/drivers/timer/i8253.c
@@ -116,10 +116,7 @@
/* interrupt stub memory for irq_connect() */
#ifndef CONFIG_DYNAMIC_INT_STUBS
-extern void *_i8253_interrupt_stub;
-SYS_INT_REGISTER(_i8253_interrupt_stub, PIT_INT_LVL, PIT_INT_PRI);
-#else
-static NANO_CPU_INT_STUB_DECL(_i8253_interrupt_stub);
+IRQ_CONNECT_STATIC(i8253, PIT_INT_LVL, PIT_INT_PRI, _timer_int_handler, 0);
#endif
static uint16_t __noinit counterLoadVal; /* computed counter */
@@ -497,7 +494,9 @@
_i8253CounterPeriodic(counterLoadVal);
-#ifdef CONFIG_DYNAMIC_INT_STUBS
+#ifndef CONFIG_DYNAMIC_INT_STUBS
+ IRQ_CONFIG(i8253, PIT_INT_LVL);
+#else
/* connect specified routine/parameter to PIT interrupt vector */
(void)irq_connect(PIT_INT_LVL,
@@ -505,6 +504,7 @@
_timer_int_handler,
0,
_i8253_interrupt_stub);
+
#endif /* CONFIG_DYNAMIC_INT_STUBS */
_i8253TicklessIdleSkew();
diff --git a/drivers/timer/loapic_timer.c b/drivers/timer/loapic_timer.c
index 2f9c4be..7025137 100644
--- a/drivers/timer/loapic_timer.c
+++ b/drivers/timer/loapic_timer.c
@@ -115,9 +115,9 @@
_loapic_timer_irq_stub); /* interrupt stub memory for */
/* irq_connect() */
#else /* !CONFIG_DYNAMIC_INT_STUBS */
-extern void *_loapic_timer_irq_stub;
-SYS_INT_REGISTER(_loapic_timer_irq_stub, LOAPIC_TIMER_IRQ, LOAPIC_TIMER_INT_PRI);
-#endif /* CONFIG_DYNAMIC_INT_STUBS */
+IRQ_CONNECT_STATIC(loapic, LOAPIC_TIMER_IRQ, LOAPIC_TIMER_INT_PRI,
+ _timer_int_handler, 0);
+#endif
static uint32_t __noinit counterLoadVal; /* computed counter 0
initial count value */
@@ -580,7 +580,7 @@
* still
* has to be programmed into the interrupt controller.
*/
- _SysIntVecProgram(LOAPIC_TIMER_VEC, LOAPIC_TIMER_IRQ);
+ IRQ_CONFIG(loapic, LOAPIC_TIMER_IRQ);
#endif /* CONFIG_DYNAMIC_INT_STUBS */
_loApicTimerTicklessIdleSkew();
diff --git a/include/arch/x86/arch.h b/include/arch/x86/arch.h
index db60d88..47a7586 100644
--- a/include/arch/x86/arch.h
+++ b/include/arch/x86/arch.h
@@ -137,6 +137,41 @@
#define NANO_CPU_INT_STUB_DECL(s) \
_NODATA_SECTION(.intStubSect) NANO_INT_STUB(s)
+
+/*******************************************************************************
+ *
+ * IRQ_CONNECT_STATIC - connect a routine to interrupt number
+ *
+ * For the device <device> associates IRQ number <irq> with priority
+ * <priority> with the interrupt routine <isr>, that receives parameter
+ * <parameter>
+ *
+ * RETURNS: N/A
+ *
+ */
+#define IRQ_CONNECT_STATIC(device, irq, priority, isr, parameter) \
+ const uint32_t _##device##_int_vector = INT_VEC_IRQ0 + (irq); \
+ extern void *_##device##_##isr##_stub; \
+ NANO_CPU_INT_REGISTER(_##device##_##isr##_stub, INT_VEC_IRQ0 + (irq), priority)
+
+
+/*******************************************************************************
+ *
+ * IRQ_CONFIG - configure interrupt for the device
+ *
+ * For the given device do the neccessary configuration steps.
+ * For x86 platform configure APIC and mark interrupt vector allocated
+ *
+ * RETURNS: N/A
+ *
+ */
+#define IRQ_CONFIG(device, irq) \
+ do { \
+ _SysIntVecProgram(_##device##_int_vector, irq); \
+ _IntVecMarkAllocated(_##device##_int_vector); \
+ } while(0)
+
+
/*
* A pointer to an "exception stack frame" (ESF) is passed as an argument
* to exception handlers registered via nanoCpuExcConnect(). When an exception
diff --git a/include/drivers/ioapic.h b/include/drivers/ioapic.h
index f859fb8..3621df4 100644
--- a/include/drivers/ioapic.h
+++ b/include/drivers/ioapic.h
@@ -61,7 +61,19 @@
#define IOAPIC_EXTINT 0x00000700
#ifdef _ASMLANGUAGE
-GTEXT(ioapic_eoi)
+GTEXT(_ioapic_eoi)
+
+.macro ioapic_mkstub device isr
+GTEXT(_\()\device\()_\()\isr\()_stub)
+
+SECTION_FUNC(TEXT, _\()\device\()_\()\isr\()_stub)
+ call _IntEnt /* Inform kernel interrupt has begun */
+ pushl $0 /* Push dummy parameter */
+ call \isr /* Call actual interrupt handler */
+ call _ioapic_eoi /* Inform ioapic interrupt is done */
+ addl $4, %esp /* Clean-up stack from push above */
+ jmp _IntExit /* Inform kernel interrupt is done */
+.endm
#else /* _ASMLANGUAGE */
void _ioapic_init(void);
void _ioapic_eoi(unsigned int irq);
diff --git a/include/drivers/loapic.h b/include/drivers/loapic.h
index f644f2c..9b207e4 100644
--- a/include/drivers/loapic.h
+++ b/include/drivers/loapic.h
@@ -70,6 +70,18 @@
#ifdef _ASMLANGUAGE
GTEXT(_loapic_eoi)
+
+.macro loapic_mkstub device isr
+GTEXT(_\()\device\()_\()\isr\()_stub)
+
+SECTION_FUNC(TEXT, _\()\device\()_\()\isr\()_stub)
+ call _IntEnt /* Inform kernel interrupt has begun */
+ pushl $0 /* Push dummy parameter */
+ call \isr /* Call actual interrupt handler */
+ call _loapic_eoi /* Inform loapic interrupt is done */
+ addl $4, %esp /* Clean-up stack from push above */
+ jmp _IntExit /* Inform kernel interrupt is done */
+.endm
#else /* _ASMLANGUAGE */
extern void _loapic_init(void);
extern void _loapic_eoi(unsigned int irq);
diff --git a/include/drivers/pic.h b/include/drivers/pic.h
index 610848a..8312c33 100644
--- a/include/drivers/pic.h
+++ b/include/drivers/pic.h
@@ -71,6 +71,29 @@
GTEXT(_i8259_eoi_master)
GTEXT(_i8259_eoi_slave)
+.macro pic_master_mkstub device isr
+GTEXT(_\()\device\()_\()\isr\()_stub)
+
+SECTION_FUNC(TEXT, _\()\device\()_\()\isr\()_stub)
+ call _IntEnt /* Inform kernel interrupt has begun */
+ pushl $0 /* Push dummy parameter */
+ call \isr /* Call actual interrupt handler */
+ call _i8259_eoi_master /* Inform PIC interrupt is done */
+ addl $4, %esp /* Clean-up stack from push above */
+ jmp _IntExit /* Inform kernel interrupt is done */
+.endm
+
+.macro pic_slave_mkstub device isr
+GTEXT(_\()\device\()_\()\isr\()_stub)
+
+SECTION_FUNC(TEXT, _\()\device\()_\()\isr\()_stub)
+ call _IntEnt /* Inform kernel interrupt has begun */
+ pushl $0 /* Push dummy parameter */
+ call \isr /* Call actual interrupt handler */
+ call _i8259_eoi_slave /* Inform PIC interrupt is done */
+ addl $4, %esp /* Clean-up stack from push above */
+ jmp _IntExit /* Inform kernel interrupt is done */
+.endm
#else /* _ASMLANGUAGE */
extern void _i8259_init(void);