* shared/irq/openpic_i8259_irq.c: New file.
	* ChangeLog, Makefile.am, motorola_powerpc/ChangeLog,
	motorola_powerpc/Makefile.am, shared/irq/irq.c, shared/irq/irq.h,
	shared/irq/irq_asm.S, shared/irq/irq_init.c: Separated openpic/i8259
	specifica from generic irq handling into openpic_i8259_irq.c; added
	some compilation conditionals to help BSPs without ISA to omit ISA
	interrupts and calling i8259 code.
This commit is contained in:
Till Straumann
2005-11-04 01:39:45 +00:00
parent be45f8e250
commit 8c9fffdd38
8 changed files with 392 additions and 338 deletions

View File

@@ -44,7 +44,8 @@ EXTRA_DIST += shared/residual/residual.c
EXTRA_DIST += shared/openpic/openpic.c
## shared/irq
EXTRA_DIST += shared/irq/i8259.c shared/irq/irq.c shared/irq/irq_init.c shared/irq/irq_asm.S
EXTRA_DIST += shared/irq/i8259.c shared/irq/irq.c shared/irq/irq_init.c \
shared/irq/irq_asm.S shared/irq/openpic_i8259_irq.c
## shared/start
EXTRA_DIST += shared/start/start.S shared/start/rtems_crti.S

View File

@@ -1,3 +1,13 @@
2005-11-03 <strauman@slac.stanford.edu>
* shared/irq/openpic_i8259_irq.c: New file.
* ChangeLog, Makefile.am, motorola_powerpc/ChangeLog,
motorola_powerpc/Makefile.am, shared/irq/irq.c, shared/irq/irq.h,
shared/irq/irq_asm.S, shared/irq/irq_init.c: Separated openpic/i8259
specifica from generic irq handling into openpic_i8259_irq.c; added
some compilation conditionals to help BSPs without ISA to omit ISA
interrupts and calling i8259 code.
2005-11-03 <strauman@slac.stanford.edu>
* Makefile.am, include/bsp.h: Added new shared pretaskinghook.c and

View File

@@ -80,7 +80,7 @@ console_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
include_bsp_HEADERS += ../../powerpc/shared/irq/irq.h
noinst_PROGRAMS += irq.rel
irq_rel_SOURCES = ../../powerpc/shared/irq/irq_init.c \
irq_rel_SOURCES = ../../powerpc/shared/irq/irq_init.c ../../powerpc/shared/irq/openpic_i8259_irq.c \
../../powerpc/shared/irq/i8259.c ../../powerpc/shared/irq/irq.c \
../../powerpc/shared/irq/irq_asm.S ../../powerpc/shared/irq/irq.h
irq_rel_CPPFLAGS = $(AM_CPPFLAGS)

View File

@@ -1,6 +1,6 @@
/*
*
* This file contains the implementation of the function described in irq.h
* This file contains the PIC-independent implementation of the functions described in irq.h
*
* Copyright (C) 1998, 1999 valette@crf.canon.fr
*
@@ -15,26 +15,18 @@
#include <bsp.h>
#include <bsp/irq.h>
#include <bsp/VME.h>
#include <bsp/openpic.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 */
#define RAVEN_INTR_ACK_REG 0xfeff0030
/*
* pointer to the mask representing the additionnal irq vectors
* that must be disabled when a particular entry is activated.
* They will be dynamically computed from the priority table given
* in BSP_rtems_irq_mngt_set();
* CAUTION : this table is accessed directly by interrupt routine
* prologue.
*/
rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_NUMBER];
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 handler connected on each irq after bsp initialization
*/
@@ -47,26 +39,6 @@ static rtems_irq_connect_data default_rtems_entry;
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_number irqLine)
{
return (((int) irqLine <= BSP_ISA_IRQ_MAX_OFFSET) &
((int) irqLine >= BSP_ISA_IRQ_LOWEST_OFFSET)
);
}
/*
* Check if IRQ is an OPENPIC IRQ
*/
static inline int is_pci_irq(const rtems_irq_number irqLine)
{
return (((int) irqLine <= BSP_PCI_IRQ_MAX_OFFSET) &
((int) irqLine >= BSP_PCI_IRQ_LOWEST_OFFSET)
);
}
/*
* Check if IRQ is a Processor IRQ
*/
@@ -78,33 +50,22 @@ static inline int is_processor_irq(const rtems_irq_number irqLine)
}
/*
* ------------------------ RTEMS Irq helper functions ----------------
* 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;}
/*
* Caution : this function assumes the variable "internal_config"
* is already set and that the tables it contains are still valid
* and accessible.
* ------------------------ RTEMS Irq helper functions ----------------
*/
static void compute_i8259_masks_from_prio ()
{
int i;
int j;
/*
* Always mask at least current interrupt to prevent re-entrance
*/
for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) {
* ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);
for (j = BSP_ISA_IRQ_LOWEST_OFFSET; j < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; j++) {
/*
* Mask interrupts at i8259 level that have a lower priority
*/
if (internal_config->irqPrioTbl [i] > internal_config->irqPrioTbl [j]) {
* ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j);
}
}
}
}
/*
* This function check that the value given for the irq line
@@ -152,25 +113,13 @@ int BSP_install_rtems_shared_irq_handler (const rtems_irq_connect_data* irq)
/* link chain to new topmost handler */
rtems_hdl_tbl[irq->name].next_handler = (void *)vchain;
if (is_isa_irq(irq->name)) {
/*
* Enable interrupt at PIC level
*/
BSP_irq_enable_at_i8259s (irq->name);
}
if (is_pci_irq(irq->name)) {
/*
* Enable interrupt at OPENPIC level
*/
openpic_enable_irq ((int) irq->name - BSP_PCI_IRQ_LOWEST_OFFSET);
}
if (is_processor_irq(irq->name)) {
/*
* Enable exception at processor level
*/
}
} else {
BSP_enable_irq_at_pic(irq->name);
}
/*
* Enable interrupt on device
*/
@@ -213,25 +162,13 @@ int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
rtems_hdl_tbl[irq->name] = *irq;
rtems_hdl_tbl[irq->name].next_handler = (void *)-1;
if (is_isa_irq(irq->name)) {
/*
* Enable interrupt at PIC level
*/
BSP_irq_enable_at_i8259s (irq->name);
}
if (is_pci_irq(irq->name)) {
/*
* Enable interrupt at OPENPIC level
*/
openpic_enable_irq ((int) irq->name - BSP_PCI_IRQ_LOWEST_OFFSET);
}
if (is_processor_irq(irq->name)) {
/*
* Enable exception at processor level
*/
}
} else {
BSP_enable_irq_at_pic(irq->name);
}
/*
* Enable interrupt on device
*/
@@ -305,23 +242,13 @@ int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
}
}
if (is_isa_irq(irq->name)) {
/*
* disable interrupt at PIC level
*/
BSP_irq_disable_at_i8259s (irq->name);
}
if (is_pci_irq(irq->name)) {
/*
* disable interrupt at OPENPIC level
*/
openpic_disable_irq ((int) irq->name - BSP_PCI_IRQ_LOWEST_OFFSET);
}
if (is_processor_irq(irq->name)) {
/*
* disable exception at processor level
*/
}
} else {
BSP_disable_irq_at_pic(irq->name);
}
/*
* Disable interrupt on device
@@ -366,129 +293,55 @@ int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
{
int i;
unsigned int level;
/*
* Store various code accelerators
*/
rtems_irq_connect_data* vchain;
rtems_raw_except_connect_data vectorDesc;
/*
* Store various code accelerators
*/
internal_config = config;
default_rtems_entry = config->defaultEntry;
rtems_hdl_tbl = config->irqHdlTbl;
rtems_hdl_tbl = config->irqHdlTbl;
_CPU_ISR_Disable(level);
/*
* set up internal tables used by rtems interrupt prologue
*/
/*
* start with ISA IRQ
*/
compute_i8259_masks_from_prio ();
for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) {
if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
BSP_irq_enable_at_i8259s (i);
if ( !BSP_setup_the_pic(config) ) {
printk("PIC setup failed; leaving IRQs OFF\n");
return 0;
}
/* rtems_hdl_tbl[i].on(&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->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);
}
}
BSP_irq_disable_at_i8259s (i);
}
}
/*
* must enable slave pic anyway
*/
BSP_irq_enable_at_i8259s (2);
/*
* continue with PCI IRQ
*/
for (i=BSP_PCI_IRQ_LOWEST_OFFSET; i < BSP_PCI_IRQ_LOWEST_OFFSET + BSP_PCI_IRQ_NUMBER ; i++) {
/*
* Note that openpic_set_priority() sets the TASK priority of the PIC
*/
openpic_set_source_priority(i - BSP_PCI_IRQ_LOWEST_OFFSET,
internal_config->irqPrioTbl[i]);
if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
openpic_enable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET);
/* rtems_hdl_tbl[i].on(&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->on(vchain);
}
}
for ( i = BSP_LOWEST_OFFSET; i <= BSP_MAX_OFFSET; i++ ) {
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);
}
}
openpic_disable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET);
}
}
/*
* Must enable PCI/ISA bridge IRQ
*/
openpic_enable_irq (0);
/*
* 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_hdl_tbl[i].on(&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->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);
}
}
}
}
_CPU_ISR_Enable(level);
/*
* 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");
}
return 1;
}
@@ -498,88 +351,6 @@ int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** 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 isaIntr; /* boolean */
register unsigned oldMask = 0; /* old isa pic masks */
register unsigned newMask; /* new isa pic masks */
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 = openpic_irq(0);
if (irq == OPENPIC_VEC_SPURIOUS) {
++BSP_spuriousIntr;
return;
}
isaIntr = (irq == BSP_PCI_ISA_BRIDGE_IRQ);
if (isaIntr) {
/*
* Acknowledge and read 8259 vector
*/
irq = (unsigned int) (*(unsigned char *) RAVEN_INTR_ACK_REG);
/*
* store current PIC mask
*/
oldMask = i8259s_cache;
newMask = oldMask | irq_mask_or_tbl [irq];
i8259s_cache = newMask;
outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8));
BSP_irq_ack_at_i8259s (irq);
openpic_eoi(0);
}
_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);
if (isaIntr) {
i8259s_cache = oldMask;
outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8));
}
else {
#ifdef BSP_PCI_VME_DRIVER_DOES_EOI
/* leave it to the VME bridge driver to do EOI, so
* it can re-enable the openpic while handling
* VME interrupts (-> VME priorities in software)
*/
if (_BSP_vme_bridge_irq != irq)
#endif
openpic_eoi(0);
}
}
void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
{
/*

View File

@@ -154,6 +154,7 @@ extern volatile rtems_i8259_masks i8259s_cache;
/*
* ------------------------ Intel 8259 (or emulation) Mngt Routines -------
*/
void BSP_i8259s_init(void);
/*
* function to disable a particular irq at 8259 level. After calling
@@ -183,8 +184,16 @@ int BSP_irq_enabled_at_i8259s (const rtems_irq_number irqLine);
extern void BSP_rtems_irq_mng_init(unsigned cpuId);
extern void BSP_i8259s_init(void);
/*
* PIC-independent function to enable/disable interrupt lines at
* the pic.
*/
extern void BSP_enable_irq_at_pic (const rtems_irq_number irqLine);
extern void BSP_disable_irq_at_pic (const rtems_irq_number irqLine);
extern int BSP_setup_the_pic (rtems_irq_global_settings* config);
#ifdef __cplusplus
}
};
#endif
#endif

View File

@@ -93,9 +93,6 @@ SYM (shared_raw_irq_code_entry):
mfmsr r3
/*
* Enable data and instruction address translation, exception recovery
*
* also, on CPUs with FP, enable FP so that FP context can be
* saved and restored (using FP instructions)
*/
ori r3, r3, MSR_RI | MSR_IR | MSR_DR
mtmsr r3

View File

@@ -38,11 +38,6 @@ typedef struct {
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
*/
@@ -53,8 +48,8 @@ static void nop_func(){}
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;
@@ -265,25 +260,21 @@ 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
#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
#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
@@ -336,29 +327,8 @@ void BSP_rtems_irq_mng_init(unsigned cpuId)
*/
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
#ifdef TRACE_IRQ_INIT
printk("RTEMS IRQ management is now operational\n");
#endif
}

View File

@@ -0,0 +1,296 @@
/*
*
* This file contains the i8259/openpic-specific 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/VMEConfig.h>
#include <bsp/openpic.h>
#include <libcpu/raw_exception.h>
#include <libcpu/io.h>
#include <bsp/vectors.h>
#include <stdlib.h>
#include <rtems/bspIo.h> /* for printk */
#define RAVEN_INTR_ACK_REG 0xfeff0030
/*
* pointer to the mask representing the additionnal irq vectors
* that must be disabled when a particular entry is activated.
* They will be dynamically computed from the priority table given
* in BSP_rtems_irq_mngt_set();
* CAUTION : this table is accessed directly by interrupt routine
* prologue.
*/
rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_NUMBER];
/*
* default handler connected on each irq after bsp initialization
*/
static rtems_irq_connect_data default_rtems_entry;
static rtems_irq_connect_data* rtems_hdl_tbl;
#ifdef BSP_PCI_ISA_BRIDGE_IRQ
/*
* Check if IRQ is an ISA IRQ
*/
static inline int is_isa_irq(const rtems_irq_number irqLine)
{
return (((int) irqLine <= BSP_ISA_IRQ_MAX_OFFSET) &
((int) irqLine >= BSP_ISA_IRQ_LOWEST_OFFSET)
);
}
#endif
/*
* Check if IRQ is an OPENPIC IRQ
*/
static inline int is_pci_irq(const rtems_irq_number irqLine)
{
return (((int) irqLine <= BSP_PCI_IRQ_MAX_OFFSET) &
((int) irqLine >= BSP_PCI_IRQ_LOWEST_OFFSET)
);
}
/*
* ------------------------ RTEMS Irq helper functions ----------------
*/
#ifdef BSP_PCI_ISA_BRIDGE_IRQ
/*
* Caution : this function assumes the variable "*config"
* is already set and that the tables it contains are still valid
* and accessible.
*/
static void compute_i8259_masks_from_prio (rtems_irq_global_settings* config)
{
int i;
int j;
/*
* Always mask at least current interrupt to prevent re-entrance
*/
for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) {
* ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);
for (j = BSP_ISA_IRQ_LOWEST_OFFSET; j < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; j++) {
/*
* Mask interrupts at i8259 level that have a lower priority
*/
if (config->irqPrioTbl [i] > config->irqPrioTbl [j]) {
* ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j);
}
}
}
}
#endif
void
BSP_enable_irq_at_pic(const rtems_irq_number name)
{
#ifdef BSP_PCI_ISA_BRIDGE_IRQ
if (is_isa_irq(name)) {
/*
* Enable interrupt at PIC level
*/
BSP_irq_enable_at_i8259s ((int) name - BSP_ISA_IRQ_LOWEST_OFFSET);
}
#endif
if (is_pci_irq(name)) {
/*
* Enable interrupt at OPENPIC level
*/
openpic_enable_irq ((int) name - BSP_PCI_IRQ_LOWEST_OFFSET);
}
}
void
BSP_disable_irq_at_pic(const rtems_irq_number name)
{
#ifdef BSP_PCI_ISA_BRIDGE_IRQ
if (is_isa_irq(name)) {
/*
* disable interrupt at PIC level
*/
BSP_irq_disable_at_i8259s ((int) name - BSP_ISA_IRQ_LOWEST_OFFSET);
}
#endif
if (is_pci_irq(name)) {
/*
* disable interrupt at OPENPIC level
*/
openpic_disable_irq ((int) name - BSP_PCI_IRQ_LOWEST_OFFSET);
}
}
/*
* RTEMS Global Interrupt Handler Management Routines
*/
int BSP_setup_the_pic(rtems_irq_global_settings* config)
{
int i;
/*
* Store various code accelerators
*/
default_rtems_entry = config->defaultEntry;
rtems_hdl_tbl = config->irqHdlTbl;
/*
* set up internal tables used by rtems interrupt prologue
*/
#ifdef BSP_PCI_ISA_BRIDGE_IRQ
/*
* start with ISA IRQ
*/
compute_i8259_masks_from_prio (config);
for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) {
if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
BSP_irq_enable_at_i8259s (i);
}
else {
BSP_irq_disable_at_i8259s (i);
}
}
if ( BSP_ISA_IRQ_NUMBER > 0 ) {
/*
* must enable slave pic anyway
*/
BSP_irq_enable_at_i8259s (2);
}
#endif
/*
* continue with PCI IRQ
*/
for (i=BSP_PCI_IRQ_LOWEST_OFFSET; i < BSP_PCI_IRQ_LOWEST_OFFSET + BSP_PCI_IRQ_NUMBER ; i++) {
/*
* Note that openpic_set_priority() sets the TASK priority of the PIC
*/
openpic_set_source_priority(i - BSP_PCI_IRQ_LOWEST_OFFSET,
config->irqPrioTbl[i]);
if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
openpic_enable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET);
}
else {
openpic_disable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET);
}
}
#ifdef BSP_PCI_ISA_BRIDGE_IRQ
if ( BSP_ISA_IRQ_NUMBER > 0 ) {
/*
* Must enable PCI/ISA bridge IRQ
*/
openpic_enable_irq (0);
}
#endif
return 1;
}
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;
#ifdef BSP_PCI_ISA_BRIDGE_IRQ
register unsigned isaIntr; /* boolean */
register unsigned oldMask = 0; /* old isa pic masks */
register unsigned newMask; /* new isa pic masks */
#endif
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 = openpic_irq(0);
if (irq == OPENPIC_VEC_SPURIOUS) {
++BSP_spuriousIntr;
return;
}
/* some BSPs might want to use a different numbering... */
irq = irq - OPENPIC_VEC_SOURCE + BSP_PCI_IRQ_LOWEST_OFFSET;
#ifdef BSP_PCI_ISA_BRIDGE_IRQ
isaIntr = (irq == BSP_PCI_ISA_BRIDGE_IRQ);
if (isaIntr) {
/*
* Acknowledge and read 8259 vector
*/
irq = (unsigned int) (*(unsigned char *) RAVEN_INTR_ACK_REG);
/*
* store current PIC mask
*/
oldMask = i8259s_cache;
newMask = oldMask | irq_mask_or_tbl [irq];
i8259s_cache = newMask;
outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8));
BSP_irq_ack_at_i8259s (irq);
openpic_eoi(0);
}
#endif
_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);
#ifdef BSP_PCI_ISA_BRIDGE_IRQ
if (isaIntr) {
i8259s_cache = oldMask;
outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8));
}
else
#endif
{
#ifdef BSP_PCI_VME_DRIVER_DOES_EOI
/* leave it to the VME bridge driver to do EOI, so
* it can re-enable the openpic while handling
* VME interrupts (-> VME priorities in software)
*/
if (_BSP_vme_bridge_irq != irq)
#endif
openpic_eoi(0);
}
}