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