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);