summaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
authorJennifer Averett <Jennifer.Averett@OARcorp.com>2005-04-28 17:47:10 +0000
committerJennifer Averett <Jennifer.Averett@OARcorp.com>2005-04-28 17:47:10 +0000
commit2608c9a9f698fe6575c84676c982427fa0ea84e7 (patch)
tree5267c7ac4c78cb14d3bf9ee45c7908cfe444d53d /c
parent2005-04-28 Joel Sherrill <joel@OARcorp.com> (diff)
downloadrtems-2608c9a9f698fe6575c84676c982427fa0ea84e7.tar.bz2
2005-04-28 Jennifer Averett <jennifer.averett@oarcorp.com>
* Add/move files for the Update to new exception model. NOTE: These modifications have not been tested on hardware. * irq/FPGA.c, irq/irq.c, irq/irq.h, irq/irq_init.c: New files. * startup/FPGA.c: Removed.
Diffstat (limited to 'c')
-rw-r--r--c/src/lib/libbsp/powerpc/score603e/ChangeLog7
-rw-r--r--c/src/lib/libbsp/powerpc/score603e/irq/FPGA.c (renamed from c/src/lib/libbsp/powerpc/score603e/startup/FPGA.c)0
-rw-r--r--c/src/lib/libbsp/powerpc/score603e/irq/irq.c451
-rw-r--r--c/src/lib/libbsp/powerpc/score603e/irq/irq.h350
-rw-r--r--c/src/lib/libbsp/powerpc/score603e/irq/irq_init.c364
5 files changed, 1172 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/score603e/ChangeLog b/c/src/lib/libbsp/powerpc/score603e/ChangeLog
index 34a4c70d0e..23ffc116e8 100644
--- a/c/src/lib/libbsp/powerpc/score603e/ChangeLog
+++ b/c/src/lib/libbsp/powerpc/score603e/ChangeLog
@@ -1,3 +1,10 @@
+2005-04-28 Jennifer Averett <jennifer.averett@oarcorp.com>
+
+ * Add/move files for the Update to new exception model.
+ NOTE: These modifications have not been tested on hardware.
+ * irq/FPGA.c, irq/irq.c, irq/irq.h, irq/irq_init.c: New files.
+ * startup/FPGA.c: Removed.
+
2005-04-15 Jennifer Averett <jennifer.averett@oarcorp.com>
* clock/clock.c: Fix multiple defined warning
diff --git a/c/src/lib/libbsp/powerpc/score603e/startup/FPGA.c b/c/src/lib/libbsp/powerpc/score603e/irq/FPGA.c
index 46c012f2ae..46c012f2ae 100644
--- a/c/src/lib/libbsp/powerpc/score603e/startup/FPGA.c
+++ b/c/src/lib/libbsp/powerpc/score603e/irq/FPGA.c
diff --git a/c/src/lib/libbsp/powerpc/score603e/irq/irq.c b/c/src/lib/libbsp/powerpc/score603e/irq/irq.c
new file mode 100644
index 0000000000..d743bcc962
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/score603e/irq/irq.c
@@ -0,0 +1,451 @@
+/*
+ *
+ * This file contains the implementation of the function described in irq.h
+ *
+ * Copyright (C) 1998, 1999 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.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/VME.h>
+#include <rtems/score/apiext.h> /* for post ISR signal processing */
+#include <libcpu/raw_exception.h>
+#include <libcpu/io.h>
+#include <bsp/vectors.h>
+#include <stdlib.h>
+#include <rtems/bspIo.h> /* for printk */
+
+/*
+ * 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;
+
+/*
+ * Check if IRQ is an ISA IRQ
+ */
+static inline int is_isa_irq(const rtems_irq_symbolic_name irqLine)
+{
+ return (((int) irqLine <= BSP_ISA_IRQ_MAX_OFFSET) &
+ ((int) irqLine >= BSP_ISA_IRQ_LOWEST_OFFSET)
+ );
+}
+
+/*
+ * Check if IRQ is an pci IRQ
+ */
+static inline int is_pci_irq(const rtems_irq_symbolic_name irqLine)
+{
+ return (((int) irqLine <= BSP_PCI_IRQ_MAX_OFFSET) &
+ ((int) irqLine >= BSP_PCI_IRQ_LOWEST_OFFSET)
+ );
+}
+
+/*
+ * Check if IRQ is a Processor IRQ
+ */
+static inline int is_processor_irq(const rtems_irq_symbolic_name irqLine)
+{
+ return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
+ ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
+ );
+}
+
+/*
+ * ------------------------ RTEMS Irq helper functions ----------------
+ */
+
+/*
+ * This function check that the value given for the irq line
+ * is valid.
+ */
+
+static int isValidInterrupt(int irq)
+{
+ if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET))
+ return 0;
+ return 1;
+}
+
+/*
+ * ------------------------ RTEMS Shared Irq Handler Mngt Routines ----------------
+ */
+int BSP_install_rtems_shared_irq_handler (const rtems_irq_connect_data* irq)
+{
+ unsigned int level;
+ rtems_irq_connect_data* vchain;
+
+ if (!isValidInterrupt(irq->name)) {
+ printk("Invalid interrupt vector %d\n",irq->name);
+ return 0;
+ }
+
+ _CPU_ISR_Disable(level);
+
+ if ( (int)rtems_hdl_tbl[irq->name].next_handler == -1 ) {
+ _CPU_ISR_Enable(level);
+ printk("IRQ vector %d already connected to an unshared handler\n",irq->name);
+ return 0;
+ }
+
+ vchain = (rtems_irq_connect_data*)malloc(sizeof(rtems_irq_connect_data));
+
+ /* save off topmost handler */
+ vchain[0]= rtems_hdl_tbl[irq->name];
+
+ /*
+ * store the data provided by user
+ */
+ rtems_hdl_tbl[irq->name] = *irq;
+
+ /* link chain to new topmost handler */
+ rtems_hdl_tbl[irq->name].next_handler = (void *)vchain;
+
+ /*
+ * XXX FIX ME
+ */
+ if (is_pci_irq(irq->name)) {
+ }
+
+ if (is_processor_irq(irq->name)) {
+ /*
+ * Enable exception at processor level
+ */
+ }
+ /*
+ * Enable interrupt on device
+ */
+ irq->on(irq);
+
+ _CPU_ISR_Enable(level);
+
+ return 1;
+}
+
+/*
+ * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
+ */
+
+int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
+{
+ unsigned int level;
+
+ if (!isValidInterrupt(irq->name)) {
+ printk("Invalid interrupt vector %d\n",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.
+ */
+ _CPU_ISR_Disable(level);
+ if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
+ _CPU_ISR_Enable(level);
+ printk("IRQ vector %d already connected\n",irq->name);
+ return 0;
+ }
+
+ /*
+ * store the data provided by user
+ */
+ rtems_hdl_tbl[irq->name] = *irq;
+ rtems_hdl_tbl[irq->name].next_handler = (void *)-1;
+
+ /* XXX -FIX ME !! */
+ if (is_pci_irq(irq->name)) {
+ /*
+ * Enable interrupt
+ */
+ }
+
+ if (is_processor_irq(irq->name)) {
+ /*
+ * Enable exception at processor level
+ */
+ }
+ /*
+ * Enable interrupt on device
+ */
+ irq->on(irq);
+
+ _CPU_ISR_Enable(level);
+
+ return 1;
+}
+
+int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
+{
+ unsigned int level;
+
+ if (!isValidInterrupt(irq->name)) {
+ return 0;
+ }
+ _CPU_ISR_Disable(level);
+ *irq = rtems_hdl_tbl[irq->name];
+ _CPU_ISR_Enable(level);
+ return 1;
+}
+
+int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
+{
+ rtems_irq_connect_data *pchain= NULL, *vchain = NULL;
+ 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.
+ */
+ _CPU_ISR_Disable(level);
+ if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
+ _CPU_ISR_Enable(level);
+ return 0;
+ }
+
+ if( (int)rtems_hdl_tbl[irq->name].next_handler != -1 )
+ {
+ int found = 0;
+
+ for( (pchain= NULL, vchain = &rtems_hdl_tbl[irq->name]);
+ (vchain->hdl != default_rtems_entry.hdl);
+ (pchain= vchain, vchain = (rtems_irq_connect_data*)vchain->next_handler) )
+ {
+ if( vchain->hdl == irq->hdl )
+ {
+ found= -1; break;
+ }
+ }
+
+ if( !found )
+ {
+ _CPU_ISR_Enable(level);
+ return 0;
+ }
+ }
+ else
+ {
+ if (rtems_hdl_tbl[irq->name].hdl != irq->hdl)
+ {
+ _CPU_ISR_Enable(level);
+ return 0;
+ }
+ }
+
+ /* XXX - FIX ME !! */
+ if (is_pci_irq(irq->name)) {
+ /*
+ * disable interrupt
+ */
+ }
+ if (is_processor_irq(irq->name)) {
+ /*
+ * disable exception at processor level
+ */
+ }
+
+ /*
+ * Disable interrupt on device
+ */
+ irq->off(irq);
+
+ /*
+ * restore the default irq value
+ */
+ if( !vchain )
+ {
+ /* single handler vector... */
+ rtems_hdl_tbl[irq->name] = default_rtems_entry;
+ }
+ else
+ {
+ if( pchain )
+ {
+ /* non-first handler being removed */
+ pchain->next_handler = vchain->next_handler;
+ }
+ else
+ {
+ /* first handler isn't malloc'ed, so just overwrite it. Since
+ the contents of vchain are being struct copied, vchain itself
+ goes away */
+ rtems_hdl_tbl[irq->name]= *vchain;
+ }
+ free(vchain);
+ }
+
+ _CPU_ISR_Enable(level);
+
+ return 1;
+}
+
+/*
+ * RTEMS Global Interrupt Handler Management Routines
+ */
+
+int BSP_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
+ */
+
+ /*
+ * XXX - FIX ME !!!
+ */
+ for (i=BSP_PCI_IRQ_LOWEST_OFFSET; i < BSP_PCI_IRQ_LOWEST_OFFSET + BSP_PCI_IRQ_NUMBER ; i++) {
+ if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
+ {
+ rtems_irq_connect_data* vchain;
+ for( vchain = &rtems_hdl_tbl[i];
+ ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
+ vchain = (rtems_irq_connect_data*)vchain->next_handler )
+ {
+ vchain->on(vchain);
+ }
+ }
+
+ }
+ else {
+ /* rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); */
+ {
+ rtems_irq_connect_data* vchain;
+ for( vchain = &rtems_hdl_tbl[i];
+ ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
+ vchain = (rtems_irq_connect_data*)vchain->next_handler )
+ {
+ vchain->off(vchain);
+ }
+ }
+ }
+ }
+ /*
+ * finish with Processor exceptions handled like IRQ
+ */
+ for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET+BSP_PROCESSOR_IRQ_NUMBER; i++){
+ if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
+ {
+ rtems_irq_connect_data* vchain;
+ for( vchain = &rtems_hdl_tbl[i];
+ ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
+ vchain = (rtems_irq_connect_data*)vchain->next_handler )
+ {
+ vchain->on(vchain);
+ }
+ }
+
+ }
+ else {
+ {
+ rtems_irq_connect_data* vchain;
+ for( vchain = &rtems_hdl_tbl[i];
+ ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
+ vchain = (rtems_irq_connect_data*)vchain->next_handler )
+ {
+ vchain->off(vchain);
+ }
+ }
+
+ }
+ }
+ _CPU_ISR_Enable(level);
+ return 1;
+}
+
+int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
+{
+ *config = internal_config;
+ return 0;
+}
+
+int _BSP_vme_bridge_irq = -1;
+
+unsigned BSP_spuriousIntr = 0;
+/*
+ * High level IRQ handler called from shared_raw_irq_code_entry
+ */
+void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
+{
+ register unsigned int irq;
+ register unsigned msr;
+ register unsigned new_msr;
+
+ if (excNum == ASM_DEC_VECTOR) {
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ rtems_hdl_tbl[BSP_DECREMENTER].hdl(rtems_hdl_tbl[BSP_DECREMENTER].handle);
+
+ _CPU_MSR_SET(msr);
+ return;
+
+ }
+ irq = read_and_clear_irq();
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ /* rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle); */
+ {
+ rtems_irq_connect_data* vchain;
+ for( vchain = &rtems_hdl_tbl[irq];
+ ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
+ vchain = (rtems_irq_connect_data*)vchain->next_handler )
+ {
+ vchain->hdl(vchain->handle);
+ }
+ }
+
+ _CPU_MSR_SET(msr);
+
+}
+
+void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
+{
+ /*
+ * Process pending signals that have not already been
+ * processed by _Thread_Displatch. This happens quite
+ * unfrequently : the ISR must have posted an action
+ * to the current running thread.
+ */
+ if ( _Thread_Do_post_task_switch_extension ||
+ _Thread_Executing->do_post_task_switch_extension ) {
+ _Thread_Executing->do_post_task_switch_extension = FALSE;
+ _API_extensions_Run_postswitch();
+ }
+ /*
+ * I plan to process other thread related events here.
+ * This will include DEBUG session requested from keyboard...
+ */
+}
diff --git a/c/src/lib/libbsp/powerpc/score603e/irq/irq.h b/c/src/lib/libbsp/powerpc/score603e/irq/irq.h
new file mode 100644
index 0000000000..93dcf9d3c4
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/score603e/irq/irq.h
@@ -0,0 +1,350 @@
+/* irq.h
+ *
+ * This include file describe the data structure and the functions implemented
+ * by RTEMS to write interrupt handlers.
+ *
+ * Copyright (C) 1999 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.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef LIBBSP_POWERPC_MCP750_IRQ_IRQ_H
+#define LIBBSP_POWERPC_MCP750_IRQ_IRQ_H
+
+/*
+ * 8259 edge/level control definitions at VIA
+ */
+#define ISA8259_M_ELCR 0x4d0
+#define ISA8259_S_ELCR 0x4d1
+
+#define ELCRS_INT15_LVL 0x80
+#define ELCRS_INT14_LVL 0x40
+#define ELCRS_INT13_LVL 0x20
+#define ELCRS_INT12_LVL 0x10
+#define ELCRS_INT11_LVL 0x08
+#define ELCRS_INT10_LVL 0x04
+#define ELCRS_INT9_LVL 0x02
+#define ELCRS_INT8_LVL 0x01
+#define ELCRM_INT7_LVL 0x80
+#define ELCRM_INT6_LVL 0x40
+#define ELCRM_INT5_LVL 0x20
+#define ELCRM_INT4_LVL 0x10
+#define ELCRM_INT3_LVL 0x8
+#define ELCRM_INT2_LVL 0x4
+#define ELCRM_INT1_LVL 0x2
+#define ELCRM_INT0_LVL 0x1
+
+#define BSP_ASM_IRQ_VECTOR_BASE 0x0
+ /* 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 SLAVE_PIC_EOSI 0x62 /* End of Specific Interrupt (EOSI) for cascade */
+#define PIC_EOI 0x20 /* Generic End of Interrupt (EOI) */
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Symbolic IRQ names and related definitions
+ */
+
+typedef enum {
+ /* Base vector for our ISA IRQ handlers. */
+ BSP_ISA_IRQ_VECTOR_BASE = BSP_ASM_IRQ_VECTOR_BASE,
+ /*
+ * ISA IRQ handler related definitions
+ */
+ BSP_ISA_IRQ_NUMBER = 16,
+ BSP_ISA_IRQ_LOWEST_OFFSET = 0,
+ BSP_ISA_IRQ_MAX_OFFSET = BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER - 1,
+ /*
+ * PCI IRQ handlers related definitions
+ * CAUTION : BSP_PCI_IRQ_LOWEST_OFFSET should be equal to OPENPIC_VEC_SOURCE
+ */
+ BSP_PCI_IRQ_NUMBER = 16,
+ BSP_PCI_IRQ_LOWEST_OFFSET = BSP_ISA_IRQ_NUMBER,
+ BSP_PCI_IRQ_MAX_OFFSET = BSP_PCI_IRQ_LOWEST_OFFSET + BSP_PCI_IRQ_NUMBER - 1,
+ /*
+ * PowerPC exceptions handled as interrupt where an RTEMS managed interrupt
+ * handler might be connected
+ */
+ BSP_PROCESSOR_IRQ_NUMBER = 1,
+ BSP_PROCESSOR_IRQ_LOWEST_OFFSET = BSP_PCI_IRQ_MAX_OFFSET + 1,
+ BSP_PROCESSOR_IRQ_MAX_OFFSET = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER - 1,
+ /* Misc vectors for OPENPIC irqs (IPI, timers)
+ */
+ BSP_MISC_IRQ_NUMBER = 8,
+ BSP_MISC_IRQ_LOWEST_OFFSET = BSP_PROCESSOR_IRQ_MAX_OFFSET + 1,
+ BSP_MISC_IRQ_MAX_OFFSET = BSP_MISC_IRQ_LOWEST_OFFSET + BSP_MISC_IRQ_NUMBER - 1,
+ /*
+ * Summary
+ */
+ BSP_IRQ_NUMBER = BSP_MISC_IRQ_MAX_OFFSET + 1,
+ BSP_LOWEST_OFFSET = BSP_ISA_IRQ_LOWEST_OFFSET,
+ BSP_MAX_OFFSET = BSP_MISC_IRQ_MAX_OFFSET,
+ /*
+ * Some ISA IRQ symbolic name definition
+ */
+ BSP_ISA_PERIODIC_TIMER = 0,
+ BSP_ISA_KEYBOARD = 1,
+ BSP_ISA_UART_COM2_IRQ = 3,
+ BSP_ISA_UART_COM1_IRQ = 4,
+ BSP_ISA_RT_TIMER1 = 8,
+ BSP_ISA_RT_TIMER3 = 10,
+ /*
+ * Some PCI IRQ symbolic name definition
+ */
+ BSP_PCI_IRQ0 = BSP_PCI_IRQ_LOWEST_OFFSET,
+ BSP_PCI_ISA_BRIDGE_IRQ = BSP_PCI_IRQ0,
+
+#if defined(mvme2100)
+ BSP_DEC21143_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 1,
+ BSP_PMC_PCMIP_TYPE1_SLOT0_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 2,
+ BSP_PCMIP_TYPE1_SLOT1_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 3,
+ BSP_PCMIP_TYPE2_SLOT0_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 4,
+ BSP_PCMIP_TYPE2_SLOT1_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 5,
+ BSP_PCI_INTA_UNIVERSE_LINT0_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 7,
+ BSP_PCI_INTB_UNIVERSE_LINT1_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 8,
+ BSP_PCI_INTC_UNIVERSE_LINT2_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 9,
+ BSP_PCI_INTD_UNIVERSE_LINT3_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 10,
+ BSP_UART_COM1_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 13,
+ BSP_FRONT_PANEL_ABORT_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 14,
+ BSP_RTC_IRQ = BSP_PCI_IRQ_LOWEST_OFFSET + 15,
+#endif
+
+ /*
+ * Some Processor execption handled as RTEMS IRQ symbolic name definition
+ */
+ BSP_DECREMENTER = BSP_PROCESSOR_IRQ_LOWEST_OFFSET
+
+} rtems_irq_symbolic_name;
+
+/*
+ * Type definition for RTEMS managed interrupts
+ */
+typedef unsigned char rtems_irq_prio;
+typedef unsigned short rtems_i8259_masks;
+
+extern volatile rtems_i8259_masks i8259s_cache;
+
+struct __rtems_irq_connect_data__; /* forward declaratiuon */
+
+typedef void *rtems_irq_hdl_param;
+typedef void (*rtems_irq_hdl) (rtems_irq_hdl_param);
+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;
+ /*
+ * Handler handle to store private data
+ */
+ rtems_irq_hdl_param handle;
+ /*
+ * function for enabling interrupts at device level (ONLY!).
+ * The BSP code will automatically enable it at i8259s level and openpic 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;
+ /*
+ * Set to -1 for vectors forced to have only 1 handler
+ */
+ void *next_handler;
+
+}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 BSP_ISA_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 BSP_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 BSP_irq_enable_at_i8259s (const rtems_irq_symbolic_name irqLine);
+/*
+ * function to acknowledge 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
+ * writing raw handlers as this is automagically done for RTEMS managed
+ * handlers.
+ */
+int BSP_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 BSP_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) acknowledge 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 BSP_install_rtems_irq_handler (const rtems_irq_connect_data*);
+int BSP_install_rtems_shared_irq_handler (const rtems_irq_connect_data*);
+
+#define BSP_SHARED_HANDLER_SUPPORT 1
+
+/*
+ * function to get the current RTEMS irq handler for ptr->name. It enables to
+ * define hanlder chain...
+ */
+int BSP_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
+ * reasons.
+ * The user can use the previous function to get it.
+ */
+int BSP_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
+ * BSP_install_rtems_irq_handler(&config->irqHdlTbl[i])
+ * And each handler currently equal to config->defaultEntry.hdl
+ * has been previously disconnected via
+ * BSP_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 BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config);
+/*
+ * (Re) get info on current RTEMS interrupt management.
+ */
+int BSP_rtems_irq_mngt_get(rtems_irq_global_settings**);
+
+extern void BSP_rtems_irq_mng_init(unsigned cpuId);
+extern void BSP_i8259s_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif
diff --git a/c/src/lib/libbsp/powerpc/score603e/irq/irq_init.c b/c/src/lib/libbsp/powerpc/score603e/irq/irq_init.c
new file mode 100644
index 0000000000..492e902da2
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/score603e/irq/irq_init.c
@@ -0,0 +1,364 @@
+/* irq_init.c
+ *
+ * This file contains the implementation of rtems initialization
+ * related to interrupt handling.
+ *
+ * CopyRight (C) 1999 valette@crf.canon.fr
+ *
+ * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
+ * to make it valid for MVME2300 Motorola boards.
+ *
+ * Till Straumann <strauman@slac.stanford.edu>, 12/20/2001:
+ * Use the new interface to openpic_init
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <libcpu/io.h>
+#include <libcpu/spr.h>
+#include <bsp/pci.h>
+#include <bsp/residual.h>
+#include <bsp/openpic.h>
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <libcpu/raw_exception.h>
+#include <bsp/motorola.h>
+#include <rtems/bspIo.h>
+
+typedef struct {
+ unsigned char bus; /* few chance the PCI/ISA bridge is not on first bus but ... */
+ unsigned char device;
+ unsigned char function;
+} pci_isa_bridge_device;
+
+pci_isa_bridge_device* via_82c586 = 0;
+static pci_isa_bridge_device bridge;
+
+extern unsigned int external_exception_vector_prolog_code_size[];
+extern void external_exception_vector_prolog_code();
+extern unsigned int decrementer_exception_vector_prolog_code_size[];
+extern void decrementer_exception_vector_prolog_code();
+
+/*
+ * default on/off function
+ */
+static void nop_func(){}
+/*
+ * default isOn function
+ */
+static int not_connected() {return 0;}
+/*
+ * default possible isOn function
+ */
+static int connected() {return 1;}
+
+static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
+static rtems_irq_global_settings initial_config;
+static rtems_irq_connect_data defaultIrq = {
+ /* vectorIdex, hdl , handle , on , off , isOn */
+ 0, nop_func , NULL , nop_func , nop_func , not_connected
+};
+static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
+ /*
+ * actual priorities for interrupt :
+ * 0 means that only current interrupt is masked
+ * 255 means all other interrupts are masked
+ */
+ /*
+ * ISA interrupts.
+ * The second entry has a priority of 255 because
+ * it is the slave pic entry and should always remain
+ * unmasked.
+ */
+ 0,0,
+ 255,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /*
+ * PCI Interrupts
+ */
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */
+ /*
+ * Processor exceptions handled as interrupts
+ */
+ 0
+};
+
+#if defined(mvme2100)
+static unsigned char mvme2100_openpic_initpolarities[16] = {
+ 0, /* Not used - should be disabled */
+ 0, /* DEC21143 Controller */
+ 0, /* PMC/PC-MIP Type I Slot 0 */
+ 0, /* PC-MIP Type I Slot 1 */
+ 0, /* PC-MIP Type II Slot 0 */
+ 0, /* PC-MIP Type II Slot 1 */
+ 0, /* Not used - should be disabled */
+ 0, /* PCI Expansion Interrupt A/Universe II (LINT0) */
+ 0, /* PCI Expansion Interrupt B/Universe II (LINT1) */
+ 0, /* PCI Expansion Interrupt C/Universe II (LINT2) */
+ 0, /* PCI Expansion Interrupt D/Universe II (LINT3) */
+ 0, /* Not used - should be disabled */
+ 0, /* Not used - should be disabled */
+ 1, /* 16550 UART */
+ 0, /* Front panel Abort Switch */
+ 0, /* RTC IRQ */
+};
+
+static unsigned char mvme2100_openpic_initsenses[] = {
+ 0, /* Not used - should be disabled */
+ 1, /* DEC21143 Controller */
+ 1, /* PMC/PC-MIP Type I Slot 0 */
+ 1, /* PC-MIP Type I Slot 1 */
+ 1, /* PC-MIP Type II Slot 0 */
+ 1, /* PC-MIP Type II Slot 1 */
+ 0, /* Not used - should be disabled */
+ 1, /* PCI Expansion Interrupt A/Universe II (LINT0) */
+ 1, /* PCI Expansion Interrupt B/Universe II (LINT1) */
+ 1, /* PCI Expansion Interrupt C/Universe II (LINT2) */
+ 1, /* PCI Expansion Interrupt D/Universe II (LINT3) */
+ 0, /* Not used - should be disabled */
+ 0, /* Not used - should be disabled */
+ 1, /* 16550 UART */
+ 0, /* Front panel Abort Switch */
+ 1, /* RTC IRQ */
+};
+#else
+static unsigned char mcp750_openpic_initpolarities[16] = {
+ 1, /* 8259 cascade */
+ 0, /* all the rest of them */
+};
+
+static unsigned char mcp750_openpic_initsenses[] = {
+ 1, /* MCP750_INT_PCB(8259) */
+ 0, /* MCP750_INT_FALCON_ECC_ERR */
+ 1, /* MCP750_INT_PCI_ETHERNET */
+ 1, /* MCP750_INT_PCI_PMC */
+ 1, /* MCP750_INT_PCI_WATCHDOG_TIMER1 */
+ 1, /* MCP750_INT_PCI_PRST_SIGNAL */
+ 1, /* MCP750_INT_PCI_FALL_SIGNAL */
+ 1, /* MCP750_INT_PCI_DEG_SIGNAL */
+ 1, /* MCP750_INT_PCI_BUS1_INTA */
+ 1, /* MCP750_INT_PCI_BUS1_INTB */
+ 1, /* MCP750_INT_PCI_BUS1_INTC */
+ 1, /* MCP750_INT_PCI_BUS1_INTD */
+ 1, /* MCP750_INT_PCI_BUS2_INTA */
+ 1, /* MCP750_INT_PCI_BUS2_INTB */
+ 1, /* MCP750_INT_PCI_BUS2_INTC */
+ 1, /* MCP750_INT_PCI_BUS2_INTD */
+};
+#endif
+
+void VIA_isa_bridge_interrupts_setup(void)
+{
+ pci_isa_bridge_device pci_dev;
+ unsigned int temp;
+ unsigned char tmp;
+ unsigned char maxBus;
+ unsigned found = 0;
+
+ maxBus = BusCountPCI();
+ pci_dev.function = 0; /* Assumes the bidge is the first function */
+
+ for (pci_dev.bus = 0; pci_dev.bus < maxBus; pci_dev.bus++) {
+#ifdef SCAN_PCI_PRINT
+ printk("isa_bridge_interrupts_setup: Scanning bus %d\n", pci_dev.bus);
+#endif
+ for (pci_dev.device = 0; pci_dev.device < PCI_MAX_DEVICES; pci_dev.device++) {
+#ifdef SCAN_PCI_PRINT
+ printk("isa_bridge_interrupts_setup: Scanning device %d\n", pci_dev.device);
+#endif
+ pci_read_config_dword(pci_dev.bus, pci_dev.device, pci_dev.function,
+ PCI_VENDOR_ID, &temp);
+#ifdef SCAN_PCI_PRINT
+ printk("Vendor/device = %x\n", temp);
+#endif
+ if ((temp == (((unsigned short) PCI_VENDOR_ID_VIA) | (PCI_DEVICE_ID_VIA_82C586_0 << 16)))
+ ) {
+ bridge = pci_dev;
+ via_82c586 = &bridge;
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ /*
+ * Should print : bus = 0, device = 11, function = 0 on a MCP750.
+ */
+ printk("Via PCI/ISA bridge found at bus = %d, device = %d, function = %d\n",
+ via_82c586->bus,
+ via_82c586->device,
+ via_82c586->function);
+#endif
+ found = 1;
+ goto loop_exit;
+
+ }
+ }
+ }
+loop_exit:
+ if (!found) BSP_panic("VIA_82C586 PCI/ISA bridge not found!n");
+
+ tmp = inb(0x810);
+ if ( !(tmp & 0x2)) {
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk("This is a second generation MCP750 board\n");
+ printk("We must reprogram the PCI/ISA bridge...\n");
+#endif
+ pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x47, &tmp);
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
+#endif
+ /*
+ * Enable 4D0/4D1 ISA interrupt level/edge config registers
+ */
+ tmp |= 0x20;
+ pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x47, tmp);
+ /*
+ * Now program the ISA interrupt edge/level
+ */
+ tmp = ELCRS_INT9_LVL | ELCRS_INT10_LVL | ELCRS_INT11_LVL;
+ outb(tmp, ISA8259_S_ELCR);
+ tmp = ELCRM_INT5_LVL;
+ outb(tmp, ISA8259_M_ELCR);;
+ /*
+ * Set the Interrupt inputs to non-inverting level interrupt
+ */
+ pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x54, &tmp);
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
+#endif
+ tmp = 0;
+ pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x54, tmp);
+ }
+ else {
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk("This is a first generation MCP750 board\n");
+ printk("We just show the actual value used by PCI/ISA bridge\n");
+#endif
+ pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x47, &tmp);
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
+#endif
+ /*
+ * Show the Interrupt inputs inverting/non-inverting level status
+ */
+ pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x54, &tmp);
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
+#endif
+ }
+}
+
+ /*
+ * This code assumes the exceptions management setup has already
+ * been done. We just need to replace the exceptions that will
+ * be handled like interrupt. On mcp750/mpc750 and many PPC processors
+ * this means the decrementer exception and the external exception.
+ */
+void BSP_rtems_irq_mng_init(unsigned cpuId)
+{
+#if !defined(mvme2100)
+ int known_cpi_isa_bridge = 0;
+#endif
+ rtems_raw_except_connect_data vectorDesc;
+ int i;
+
+ /*
+ * First initialize the Interrupt management hardware
+ */
+#if defined(mvme2100)
+#ifdef TRACE_IRQ_INIT
+ printk("Going to initialize EPIC interrupt controller (openpic compliant)\n");
+#endif
+ openpic_init(1, mvme2100_openpic_initpolarities, mvme2100_openpic_initsenses);
+#else
+#ifdef TRACE_IRQ_INIT
+ printk("Going to initialize raven interrupt controller (openpic compliant)\n");
+#endif
+ openpic_init(1, mcp750_openpic_initpolarities, mcp750_openpic_initsenses);
+#endif
+
+#if !defined(mvme2100)
+#ifdef TRACE_IRQ_INIT
+ printk("Going to initialize the PCI/ISA bridge IRQ related setting (VIA 82C586)\n");
+#endif
+ if ( currentBoard == MESQUITE ) {
+ VIA_isa_bridge_interrupts_setup();
+ known_cpi_isa_bridge = 1;
+ }
+ if ( currentBoard == MVME_2300 ) {
+ /* nothing to do for W83C553 bridge */
+ known_cpi_isa_bridge = 1;
+ }
+ if ( currentBoard == MTX_WO_PP || currentBoard == MTX_W_PP ) {
+ /* W83C554, don't to anything at the moment. gregm 11/6/2002 */
+ known_cpi_isa_bridge = 1;
+ }
+
+ if (!known_cpi_isa_bridge) {
+ printk("Please add code for PCI/ISA bridge init to libbsp/powerpc/shared/irq/irq_init.c\n");
+ printk("If your card works correctly please add a test and set known_cpi_isa_bridge to true\n");
+ printk("currentBoard = %i\n", currentBoard);
+ }
+#ifdef TRACE_IRQ_INIT
+ printk("Going to initialize the ISA PC legacy IRQ management hardware\n");
+#endif
+ BSP_i8259s_init();
+#endif
+
+ /*
+ * Initialize RTEMS management interrupt table
+ */
+ /*
+ * re-init the rtemsIrq table
+ */
+ for (i = 0; i < BSP_IRQ_NUMBER; i++) {
+ rtemsIrq[i] = defaultIrq;
+ rtemsIrq[i].name = i;
+ }
+ /*
+ * Init initial Interrupt management config
+ */
+ initial_config.irqNb = BSP_IRQ_NUMBER;
+ initial_config.defaultEntry = defaultIrq;
+ initial_config.irqHdlTbl = rtemsIrq;
+ initial_config.irqBase = BSP_ASM_IRQ_VECTOR_BASE;
+ initial_config.irqPrioTbl = irqPrioTable;
+
+ if (!BSP_rtems_irq_mngt_set(&initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
+ }
+
+ /*
+ * We must connect the raw irq handler for the two
+ * expected interrupt sources : decrementer and external interrupts.
+ */
+ vectorDesc.exceptIndex = ASM_DEC_VECTOR;
+ vectorDesc.hdl.vector = ASM_DEC_VECTOR;
+ vectorDesc.hdl.raw_hdl = decrementer_exception_vector_prolog_code;
+ vectorDesc.hdl.raw_hdl_size = (unsigned) decrementer_exception_vector_prolog_code_size;
+ vectorDesc.on = nop_func;
+ vectorDesc.off = nop_func;
+ vectorDesc.isOn = connected;
+ if (!mpc60x_set_exception (&vectorDesc)) {
+ BSP_panic("Unable to initialize RTEMS decrementer raw exception\n");
+ }
+ vectorDesc.exceptIndex = ASM_EXT_VECTOR;
+ vectorDesc.hdl.vector = ASM_EXT_VECTOR;
+ vectorDesc.hdl.raw_hdl = external_exception_vector_prolog_code;
+ vectorDesc.hdl.raw_hdl_size = (unsigned) external_exception_vector_prolog_code_size;
+ if (!mpc60x_set_exception (&vectorDesc)) {
+ BSP_panic("Unable to initialize RTEMS external raw exception\n");
+ }
+#ifdef TRACE_IRQ_INIT
+ printk("RTEMS IRQ management is now operational\n");
+#endif
+}