diff options
Diffstat (limited to 'c/src/lib/libcpu/mips/au1x00/vectorisrs/vectorisrs.c')
-rw-r--r-- | c/src/lib/libcpu/mips/au1x00/vectorisrs/vectorisrs.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/mips/au1x00/vectorisrs/vectorisrs.c b/c/src/lib/libcpu/mips/au1x00/vectorisrs/vectorisrs.c new file mode 100644 index 0000000000..01256e38ad --- /dev/null +++ b/c/src/lib/libcpu/mips/au1x00/vectorisrs/vectorisrs.c @@ -0,0 +1,174 @@ +/* + * Au1x00 Interrupt Vectoring + * + * Copyright (c) 2005 by Cogent Computer Systems + * Written by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <stdlib.h> +#include <libcpu/au1x00.h> + +void mips_default_isr( int vector ); +static void call_vectored_isr(CPU_Interrupt_frame *, unsigned32 , void *); + +#define CALL_ISR(_vector,_frame) \ + do { \ + if ( _ISR_Vector_table[_vector] ) \ + (_ISR_Vector_table[_vector])(_vector,_frame); \ + else \ + mips_default_isr(_vector); \ + } while (0) + +#include <rtems/bspIo.h> /* for printk */ + +void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) +{ + unsigned int sr; + unsigned int cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + cause &= (sr & SR_IMASK); + cause >>= CAUSE_IPSHIFT; + + /* count/compare interrupt */ + if ( cause & 0x80 ) { + unsigned long zero = 0; + /* + * I don't see a good way to disable the compare + * interrupt, so let's just ignore it. + */ + asm volatile ("mtc0 %0, $11\n" :: "r" (zero)); + +/* CALL_ISR( AU1X00_IRQ_CNT, frame ); */ + } + + /* Performance counter */ + if ( cause & 0x40 ) { + CALL_ISR( AU1X00_IRQ_PERF, frame ); + } + + /* Interrupt controller 0 */ + if ( cause & 0x0c ) { + call_vectored_isr(frame, cause, (void *)AU1X00_IC0_ADDR); + } + + /* Interrupt controller 1 */ + if ( cause & 0x30 ) { + call_vectored_isr(frame, cause, (void *)AU1X00_IC1_ADDR); + } + + /* SW[0] */ + if ( cause & 0x01 ) + CALL_ISR( AU1X00_IRQ_SW0, frame ); + + /* SW[1] */ + if ( cause & 0x02 ) + CALL_ISR( AU1X00_IRQ_SW1, frame ); +} + +void mips_default_isr( int vector ) +{ + unsigned int sr; + unsigned int cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", + vector, cause, sr ); + rtems_fatal_error_occurred(1); +} + +static void call_vectored_isr( + CPU_Interrupt_frame *frame, + unsigned32 cause, + void *ctrlr + ) +{ + unsigned32 src; + unsigned32 mask; + int index; + + /* get mask register */ + mask = AU1X00_IC_MASKRD(ctrlr); + + /* check request 0 */ + src = AU1X00_IC_REQ0INT(ctrlr); + src = src & mask; + index = 0; + while (src) { + /* check LSB */ + if (src & 1) { + /* clear rising/falling edge detects */ + AU1X00_IC_RISINGCLR(ctrlr) = (1 << index); + AU1X00_IC_FALLINGCLR(ctrlr) = (1 << index); + au_sync(); + CALL_ISR(AU1X00_IRQ_IC0_BASE + index, frame); + } + index ++; + + /* shift, and make sure MSB is clear */ + src = (src >> 1) & 0x7fffffff; + } + + /* check request 1 */ + src = AU1X00_IC_REQ1INT(ctrlr); + src = src & mask; + index = 0; + while (src) { + /* check LSB */ + if (src & 1) { + /* clear rising/falling edge detects */ + AU1X00_IC_RISINGCLR(ctrlr) = (1 << index); + AU1X00_IC_FALLINGCLR(ctrlr) = (1 << index); + au_sync(); + CALL_ISR(AU1X00_IRQ_IC0_BASE + index, frame); + } + index ++; + + /* shift, and make sure MSB is clear */ + src = (src >> 1) & 0x7fffffff; + } +} + +/* Generate a software interrupt */ +int assert_sw_irq(unsigned32 irqnum) +{ + unsigned32 cause; + + if (irqnum <= 1) { + mips_get_cause(cause); + cause = cause | ((irqnum + 1) << CAUSE_IPSHIFT); + mips_set_cause(cause); + + return irqnum; + } else { + return -1; + } +} + +/* Clear a software interrupt */ +int negate_sw_irq(unsigned32 irqnum) +{ + unsigned32 cause; + + if (irqnum <= 1) { + mips_get_cause(cause); + cause = cause & ~((irqnum + 1) << CAUSE_IPSHIFT); + mips_set_cause(cause); + + return irqnum; + } else { + return -1; + } +} |