x86/bsp: move PIC (i8259) driver to drivers/interrupt_controller

Change-Id: I383424667f291ad4985781a7e6566c01c76ba5e0
Signed-off-by: Dirk Brandewie <dirk.j.brandewie@intel.com>
diff --git a/drivers/interrupt_controller/Kconfig b/drivers/interrupt_controller/Kconfig
new file mode 100644
index 0000000..6d15ce5
--- /dev/null
+++ b/drivers/interrupt_controller/Kconfig
@@ -0,0 +1,41 @@
+# Kconfig - interrupt controller configuration options
+
+#
+# Copyright (c) 2015 Intel Corporation
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1) Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2) Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3) Neither the name of Intel Corporation nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+menu "Interrupt Controllers"
+
+config PIC
+	bool "PIC (i8259)"
+	default n
+        depends on X86_32
+
+endmenu
diff --git a/drivers/interrupt_controller/Makefile b/drivers/interrupt_controller/Makefile
index 367dc84..ffb2644 100644
--- a/drivers/interrupt_controller/Makefile
+++ b/drivers/interrupt_controller/Makefile
@@ -1,5 +1,8 @@
 ccflags-y +=-I$(srctree)/include/drivers
-ccflags-y +=-I$(srctree)/arch/$(ARCH)
-ccflags-y +=-I$(srctree)/arch/$(ARCH)/$(strip $(CONFIG_BSP_DIR))
+ccflags-y +=-I$(srctree)/arch/$(ARCH)/$(subst $(DQUOTE),,$(CONFIG_BSP_DIR))
+asflags-y +=-I$(srctree)/arch/x86/$(subst $(DQUOTE),,$(CONFIG_BSP_DIR))
+
 
 obj-${CONFIG_PIC}${CONFIG_SHUTOFF_PIC} = i8259.o
+obj-$(CONFIG_PIC) += i8259_boi.o
+obj-$(CONFIG_PIC) += system_pic.o
diff --git a/drivers/interrupt_controller/i8259_boi.s b/drivers/interrupt_controller/i8259_boi.s
new file mode 100644
index 0000000..f46a4e0
--- /dev/null
+++ b/drivers/interrupt_controller/i8259_boi.s
@@ -0,0 +1,151 @@
+/* i8259Boi.s - Intel 8259A PIC BOI Handler */
+
+/*
+ * Copyright (c) 2013-2015 Wind River Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1) Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2) Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3) Neither the name of Wind River Systems nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+DESCRIPTION
+
+The PIC BOI handler determines if the IRQ in question is a spurious or real
+interrupt. The IRQ inputs must remain high until after the falling edge of the
+first INTA.  A spurious interrupt on IRQ 7 can occur if the IRQ input goes low
+before this time when the CPU acknowledges the interrupt. In this case, the
+interrupt handler should simply return without sending an EOI command.
+
+The distinction between a spurious interrupt and a real one is detected by
+looking at the in service register (ISR). The bit (bit 7) will be 1 indicating
+a real IRQ has been inserted.
+
+*/
+
+/* includes */
+#define _ASMLANGUAGE
+
+#include <arch/cpu.h>
+#include <arch/x86/asm.h>
+
+#include <drivers/pic.h>
+#include <board.h>
+
+ 	/* externs */
+
+	GTEXT(_IntExit)
+	GDATA(_i8259_spurious_interrupt_count)
+
+
+/*******************************************************************************
+*
+* _i8259_boi_master - detect whether it is spurious interrupt or not
+*
+* This routine is called before the user's interrupt handler to detect the
+* spurious interrupt on the master PIC.  If a spurious interrupt condition is
+* detected, a global variable is incremented and the execution of the interrupt
+* stub is "short circuited", i.e. a return to the interrupted context
+* occurs.
+*
+* void _i8259_boi_master (void)
+*
+* RETURNS: N/A
+*/
+
+SECTION_FUNC(TEXT, _i8259_boi_master)
+    /* disable interrupts */
+    pushfl
+    cli
+
+    /* Master PIC, get contents of in serivce register */
+    PLB_BYTE_REG_WRITE (0x0b, PIC_PORT1(PIC_MASTER_BASE_ADRS))
+    PLB_BYTE_REG_READ (PIC_PORT1(PIC_MASTER_BASE_ADRS))
+
+    /* enable interrupts */
+    popfl
+
+    /* Contents of ISR in %AL */
+    andb    $0x80, %al
+    je	    spur_isr
+
+    ret
+
+
+/*******************************************************************************
+*
+* _i8259_boi_slave - detect whether it is spurious interrupt or not
+*
+* This routine is called before the user's interrupt handler to detect the
+* spurious interrupt on the slave PIC.  If a spurious interrupt condition is
+* detected, a global variable is incremented and the execution of the interrupt
+* stub is "short circuited", i.e. a return to the interrupted context
+* occurs.
+*
+* void _i8259_boi_slave (void)
+*
+* RETURNS: N/A
+*/
+
+SECTION_FUNC(TEXT, _i8259_boi_slave)
+    /* disable interrupts */
+    pushfl
+    cli
+
+    /* Slave PIC, get contents of in serivce register */
+    PLB_BYTE_REG_WRITE (0x0b, PIC_PORT1 (PIC_SLAVE_BASE_ADRS))
+    PLB_BYTE_REG_READ (PIC_PORT1 (PIC_SLAVE_BASE_ADRS))
+
+    /* Contents of ISR in EAX */
+    testb   %al, %al
+    jne	    check_isr
+
+    /* Check the master PIC's in service register for slave PIC IRQ */
+    PLB_BYTE_REG_WRITE (0x0b, PIC_PORT1(PIC_MASTER_BASE_ADRS))
+    PLB_BYTE_REG_READ (PIC_PORT1(PIC_MASTER_BASE_ADRS))
+
+    /* Slave connected to IRQ2 on master */
+    testb   $0x4, %al
+    je	    check_isr
+
+    /* Send non-specific EOI to the master PIC IRQ2 */
+    PLB_BYTE_REG_WRITE (I8259_EOI, PIC_IACK (PIC_MASTER_BASE_ADRS));
+
+BRANCH_LABEL(check_isr)
+    /* unlock interrupts */
+    popfl
+
+    /* Contents of ISR for either PIC in %AL */
+    andb    $0x80, %al
+    je	    spur_isr
+
+    ret
+
+BRANCH_LABEL(spur_isr)
+    /* An actual spurious interrupt. Increment counter and short circuit */
+    incl    _i8259_spurious_interrupt_count
+
+    /* Pop the return address */
+    addl    $4, %esp
+    jmp	    _IntExit
diff --git a/drivers/interrupt_controller/system_pic.c b/drivers/interrupt_controller/system_pic.c
new file mode 100644
index 0000000..58d3c41
--- /dev/null
+++ b/drivers/interrupt_controller/system_pic.c
@@ -0,0 +1,150 @@
+/* systemPic.c - system module for variants with PIC */
+
+/*
+ * Copyright (c) 2013-2015, Wind River Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1) Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2) Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3) Neither the name of Wind River Systems nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+DESCRIPTION
+This module provides routines to initialize and support board-level hardware
+for the pentium4 and minuteia variants of the generic_pc BSP.
+*/
+
+#include "board.h"
+#include <nanokernel.h>
+#include <arch/cpu.h>
+#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);
+
+/*******************************************************************************
+*
+* _SysIntVecAlloc - allocate interrupt vector
+*
+* This BSP provided routine supports the irq_connect() API.  This
+* routine performs the following functions:
+*
+*  a) Allocates a vector satisfying the requested priority, where possible.
+*     When the <irq> argument is not equal to NANO_SOFT_IRQ, the vector assigned
+*     to the <irq> during interrupt controller initialization is returned,
+*     which may or may not have the desired prioritization. (Prioritization of
+*     such vectors is fixed by the 8259 interrupt controllers, and cannot be
+*     programmed on an IRQ basis; for example, IRQ0 is always the highest
+*     priority interrupt no matter which interrupt vector was assigned to IRQ0.)
+*  b) Provides End of Interrupt (EOI) and Beginning of Interrupt (BOI) related
+*     information to be used when generating the interrupt stub code.
+*
+* The pcPentium4 board virtualizes IRQs as follows:
+*
+*   - IRQ0 to IRQ7  are provided by the master i8259 PIC
+*   - IRQ8 to IRQ15 are provided by the slave i8259 PIC
+*
+* RETURNS: the allocated interrupt vector
+*
+* INTERNAL
+* For debug kernels, this routine will return -1 for invalid <priority> or
+* <irq> parameter values.
+*/
+
+int _SysIntVecAlloc(
+	unsigned int irq,		 /* virtualized IRQ */
+	unsigned int priority,		 /* get vector from <priority> group */
+	NANO_EOI_GET_FUNC * boiRtn,       /* ptr to BOI routine; NULL if none */
+	NANO_EOI_GET_FUNC * eoiRtn,       /* ptr to EOI routine; NULL if none */
+	void **boiRtnParm,		 /* BOI routine parameter, if any */
+	void **eoiRtnParm,		 /* EOI routine parameter, if any */
+	unsigned char *boiParamRequired, /* BOI routine parameter req? */
+	unsigned char *eoiParamRequired  /* BOI routine parameter req? */
+	)
+{
+	int vector;
+
+	ARG_UNUSED(boiRtnParm);
+	ARG_UNUSED(eoiRtnParm);
+
+#if defined(DEBUG)
+	if ((priority > 15) || (irq > 15) && (irq != NANO_SOFT_IRQ))
+		return -1;
+#endif
+
+	/* The PIC BOI does not require a parameter */
+
+	*boiParamRequired = 0;
+
+	/* Assume BOI is not required */
+
+	*boiRtn = (NANO_EOI_GET_FUNC)NULL;
+
+	if (irq != NANO_SOFT_IRQ) {
+		/* convert interrupt 'vector' to an interrupt controller IRQ
+		 * number */
+
+		vector = INT_VEC_IRQ0 + irq;
+
+		/* mark vector as allocated */
+
+		_IntVecMarkAllocated(vector);
+
+		/* vector not handled by PIC, thus don't specify an EOI handler
+		 */
+
+		if (irq >= N_PIC_IRQS) {
+			*eoiRtn = (NANO_EOI_GET_FUNC)NULL;
+			return vector;
+		}
+
+		if (irq == PIC_MASTER_STRAY_INT_LVL) {
+			*boiRtn = (NANO_EOI_GET_FUNC)_i8259_boi_master;
+		} else if (irq == PIC_SLAVE_STRAY_INT_LVL) {
+			*boiRtn = (NANO_EOI_GET_FUNC)_i8259_boi_slave;
+		}
+
+		if (irq <= PIC_MASTER_STRAY_INT_LVL)
+			*eoiRtn = (NANO_EOI_GET_FUNC)_i8259_eoi_master;
+		else
+			*eoiRtn = (NANO_EOI_GET_FUNC)_i8259_eoi_slave;
+
+		*eoiParamRequired = 0;
+	} else {
+		/*
+		 * Use the nanokernel utility function _IntVecAlloc() to
+		 * allocate
+		 * a vector for software generated interrupts.
+		 */
+
+		vector = _IntVecAlloc(priority);
+		*eoiRtn = (NANO_EOI_GET_FUNC)NULL;
+	}
+
+	return vector;
+}