summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/score603e/startup/genpvec.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--c/src/lib/libbsp/powerpc/score603e/startup/genpvec.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/score603e/startup/genpvec.c b/c/src/lib/libbsp/powerpc/score603e/startup/genpvec.c
new file mode 100644
index 0000000000..548772ff86
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/score603e/startup/genpvec.c
@@ -0,0 +1,202 @@
+/* genpvec.c
+ *
+ * These routines handle the external exception. Multiple ISRs occur off
+ * of this one interrupt.
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id:
+ */
+
+#include <bsp.h>
+#include "chain.h"
+#include <assert.h>
+
+
+/*
+ * Proto types for this file
+ */
+
+rtems_isr external_exception_ISR (
+ rtems_vector_number vector /* IN */
+);
+
+#define NUM_LIRQ_HANDLERS 20
+#define NUM_LIRQ ( MAX_BOARD_IRQS - PPC_IRQ_LAST )
+
+/*
+ * Structure to for one of possible multiple interrupt handlers for
+ * a given interrupt.
+ */
+typedef struct
+{
+ Chain_Node Node;
+ rtems_isr_entry handler; /* isr routine */
+ rtems_vector_number vector; /* vector number */
+} EE_ISR_Type;
+
+
+/* Note: The following will not work if we add a method to remove
+ * handlers at a later time.
+ */
+ EE_ISR_Type ISR_Nodes [NUM_LIRQ_HANDLERS];
+ rtems_unsigned16 Nodes_Used;
+ Chain_Control ISR_Array [NUM_LIRQ];
+
+/* XXX */
+void init_irq_data_register();
+
+void initialize_external_exception_vector ()
+{
+ int i;
+ rtems_isr_entry previous_isr;
+ rtems_status_code status;
+
+ Nodes_Used = 0;
+
+ /*
+ * Mask out all interupts until they have a handler installed.
+ */
+
+ for (i=0; i <NUM_LIRQ; i++)
+ Chain_Initialize_empty( &ISR_Array[i] );
+
+ init_irq_data_register();
+
+ /*
+ * Install external_exception_ISR () as the handler for
+ * the General Purpose Interrupt.
+ */
+ status = rtems_interrupt_catch( external_exception_ISR,
+ PPC_IRQ_EXTERNAL, (rtems_isr_entry *) &previous_isr );
+}
+
+void Init_EE_mask_init() {
+;
+}
+
+/*
+ * This routine installs one of multiple ISRs for the general purpose
+ * inerrupt.
+ */
+rtems_isr_entry set_EE_vector(
+ rtems_isr_entry handler, /* isr routine */
+ rtems_vector_number vector /* vector number */
+)
+{
+ rtems_unsigned16 vec_idx = vector - Score_IRQ_First;
+ rtems_unsigned32 index;
+
+ assert (Nodes_Used < NUM_LIRQ_HANDLERS);
+
+ /*
+ * If we have already installed this handler for this vector, then
+ * just reset it.
+ */
+
+ for ( index=0 ; index <= Nodes_Used ; index++ ) {
+ if ( ISR_Nodes[index].vector == vector &&
+ ISR_Nodes[index].handler == handler )
+ return NULL;
+ }
+
+ /*
+ * Doing things in this order makes them more atomic
+ */
+
+ Nodes_Used++;
+
+ index = Nodes_Used - 1;
+
+ ISR_Nodes[index].handler = handler;
+ ISR_Nodes[index].vector = vector;
+
+ /* printf( "Vector Index: %04x, Vector: %d (%x)\n",
+ vec_idx, vector, vector); */
+
+ Chain_Append( &ISR_Array[vec_idx], &ISR_Nodes[index].Node );
+
+ /*
+ * Unmask the interrupt.
+ */
+ unmask_irq( vec_idx );
+
+ return NULL;
+}
+
+/*
+ * This interrupt service routine is called for an External Exception.
+ */
+rtems_isr external_exception_ISR (
+ rtems_vector_number vector /* IN */
+)
+{
+ rtems_unsigned16 index;
+ EE_ISR_Type *node;
+ rtems_unsigned16 value;
+ char err_msg[100];
+ rtems_unsigned16 PMC_irq;
+ rtems_unsigned16 check_irq;
+ rtems_unsigned16 status_word;
+
+ index = read_and_clear_irq();
+ if ( index >= NUM_LIRQ ) {
+ sprintf(err_msg,"ERROR:: Invalid interrupt number (%02x)\n", index);
+ DEBUG_puts( err_msg);
+ return;
+ }
+
+#if (HAS_PMC_PSC8)
+ PMC_irq = SCORE603E_PCI_IRQ_0 - SCORE603E_IRQ00;
+
+ if (index == PMC_irq) {
+ status_word = read_and_clear_PMC_irq( index );
+
+ for (check_irq=SCORE603E_IRQ16; check_irq<=SCORE603E_IRQ19; check_irq++) {
+ if ( Is_PMC_IRQ( check_irq, status_word )) {
+ index = check_irq - SCORE603E_IRQ00;
+ node = (EE_ISR_Type *)(ISR_Array[ index ].first);
+
+ if ( _Chain_Is_tail( &ISR_Array[ index ], (void *)node ) ) {
+ sprintf(err_msg,"ERROR:: check %d interrupt %02d has no isr\n",
+ check_irq, index);
+ DEBUG_puts( err_msg);
+ value = get_irq_mask();
+ sprintf(err_msg," Mask = %02x\n", value);
+ DEBUG_puts( err_msg);
+ }
+ while ( !_Chain_Is_tail( &ISR_Array[ index ], (void *)node ) ) {
+ (*node->handler)( node->vector );
+ node = (EE_ISR_Type *) node->Node.next;
+ }
+ }
+ }
+ }
+ else
+#endif
+ {
+ node = (EE_ISR_Type *)(ISR_Array[ index ].first);
+ if ( _Chain_Is_tail( &ISR_Array[ index ], (void *)node ) ) {
+ sprintf(err_msg,"ERROR:: interrupt %02x has no isr\n", index);
+ DEBUG_puts( err_msg);
+ value = get_irq_mask();
+ sprintf(err_msg," Mask = %02x\n", value);
+ DEBUG_puts( err_msg);
+ return;
+ }
+ while ( !_Chain_Is_tail( &ISR_Array[ index ], (void *)node ) ) {
+ (*node->handler)( node->vector );
+ node = (EE_ISR_Type *) node->Node.next;
+ }
+ }
+
+}
+
+
+