From 8c9fffdd382ff267757fcdf4cef3081fd15df6ce Mon Sep 17 00:00:00 2001 From: Till Straumann Date: Fri, 4 Nov 2005 01:39:45 +0000 Subject: 2005-11-03 * 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. --- c/src/lib/libbsp/powerpc/Makefile.am | 3 +- .../lib/libbsp/powerpc/motorola_powerpc/ChangeLog | 10 + .../libbsp/powerpc/motorola_powerpc/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/shared/irq/irq.c | 369 ++++----------------- c/src/lib/libbsp/powerpc/shared/irq/irq.h | 11 +- c/src/lib/libbsp/powerpc/shared/irq/irq_asm.S | 3 - c/src/lib/libbsp/powerpc/shared/irq/irq_init.c | 40 +-- .../libbsp/powerpc/shared/irq/openpic_i8259_irq.c | 296 +++++++++++++++++ 8 files changed, 394 insertions(+), 340 deletions(-) create mode 100644 c/src/lib/libbsp/powerpc/shared/irq/openpic_i8259_irq.c diff --git a/c/src/lib/libbsp/powerpc/Makefile.am b/c/src/lib/libbsp/powerpc/Makefile.am index b6dd8fd6a1..5f115574e8 100644 --- a/c/src/lib/libbsp/powerpc/Makefile.am +++ b/c/src/lib/libbsp/powerpc/Makefile.am @@ -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 diff --git a/c/src/lib/libbsp/powerpc/motorola_powerpc/ChangeLog b/c/src/lib/libbsp/powerpc/motorola_powerpc/ChangeLog index 74415b2434..8800bb0712 100644 --- a/c/src/lib/libbsp/powerpc/motorola_powerpc/ChangeLog +++ b/c/src/lib/libbsp/powerpc/motorola_powerpc/ChangeLog @@ -1,3 +1,13 @@ +2005-11-03 + + * 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 * Makefile.am, include/bsp.h: Added new shared pretaskinghook.c and diff --git a/c/src/lib/libbsp/powerpc/motorola_powerpc/Makefile.am b/c/src/lib/libbsp/powerpc/motorola_powerpc/Makefile.am index f2e9e548fa..63ea700075 100644 --- a/c/src/lib/libbsp/powerpc/motorola_powerpc/Makefile.am +++ b/c/src/lib/libbsp/powerpc/motorola_powerpc/Makefile.am @@ -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) diff --git a/c/src/lib/libbsp/powerpc/shared/irq/irq.c b/c/src/lib/libbsp/powerpc/shared/irq/irq.c index ecdc61dc34..40e8d848fa 100644 --- a/c/src/lib/libbsp/powerpc/shared/irq/irq.c +++ b/c/src/lib/libbsp/powerpc/shared/irq/irq.c @@ -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 #include -#include -#include #include /* for post ISR signal processing */ #include -#include #include #include #include /* 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); - - /* 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); - } - } - - } - 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); - } + + if ( !BSP_setup_the_pic(config) ) { + printk("PIC setup failed; leaving IRQs OFF\n"); + return 0; + } + + 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); + } + } + + _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"); } - /* - * 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); - } - } - - } + 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"); } - _CPU_ISR_Enable(level); 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) { /* diff --git a/c/src/lib/libbsp/powerpc/shared/irq/irq.h b/c/src/lib/libbsp/powerpc/shared/irq/irq.h index 1a983f8832..a822e409a6 100644 --- a/c/src/lib/libbsp/powerpc/shared/irq/irq.h +++ b/c/src/lib/libbsp/powerpc/shared/irq/irq.h @@ -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 diff --git a/c/src/lib/libbsp/powerpc/shared/irq/irq_asm.S b/c/src/lib/libbsp/powerpc/shared/irq/irq_asm.S index a8e5d82103..bc5194bd1f 100644 --- a/c/src/lib/libbsp/powerpc/shared/irq/irq_asm.S +++ b/c/src/lib/libbsp/powerpc/shared/irq/irq_asm.S @@ -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 diff --git a/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c b/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c index 0f93fd4b35..231edab695 100644 --- a/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c +++ b/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c @@ -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 } diff --git a/c/src/lib/libbsp/powerpc/shared/irq/openpic_i8259_irq.c b/c/src/lib/libbsp/powerpc/shared/irq/openpic_i8259_irq.c new file mode 100644 index 0000000000..e08561fc27 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/shared/irq/openpic_i8259_irq.c @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* 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); + } +} -- cgit v1.2.3