Mercurial > hg > Members > menikon > CbC_xv6
diff src/device/picirq.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/device/picirq.c Fri May 26 23:11:05 2017 +0900 @@ -0,0 +1,96 @@ +// Support of ARM PrimeCell Vectored Interrrupt Controller (PL190) +#include "types.h" +#include "defs.h" +#include "param.h" +#include "arm.h" +#include "memlayout.h" +#include "mmu.h" + +// PL190 supports the vectored interrupts and non-vectored interrupts. +// In this code, we use non-vected interrupts (aka. simple interrupt). +// The flow to handle simple interrupts is as the following: +// 1. an interrupt (IRQ) occurs, trap.c branches to our IRQ handler +// 2. read the VICIRQStatus register, for each source generating +// the interrrupt: +// 2.1 locate the correct ISR +// 2.2 execute the ISR +// 2.3 clear the interrupt +// 3 return to trap.c, which will resume interrupted routines +// Note: must not read VICVectorAddr + + +// define the register offsets (in the unit of 4 bytes). The base address +// of the VIC depends on the board +static volatile uint* vic_base; + +#define VIC_IRQSTATUS 0 // status of interrupts after masking by ENABLE and SEL +#define VIC_FIQSTATUS 1 // status of interrupts after masking +#define VIC_RAWINTR 2 // status of interrupts before masking +#define VIC_INTSEL 3 // interrupt select (IRQ or FIQ), by default IRQ +#define VIC_INTENABLE 4 // enable interrupts (1 - enabled, 0 - disabled) +#define VIC_INTCLEAR 5 // clear bits in ENABLE register (1 - clear it) +#define VIC_PROTECTIOIN 8 // who can access: user or privileged + +#define NUM_INTSRC 32 // numbers of interrupt source supported + +static ISR isrs[NUM_INTSRC]; + +static void default_isr (struct trapframe *tf, int n) +{ + cprintf ("unhandled interrupt: %d\n", n); +} + +// initialize the PL190 VIC +void pic_init (void * base) +{ + int i; + + // set the base for the controller and disable all interrupts + vic_base = base; + vic_base[VIC_INTCLEAR] = 0xFFFFFFFF; + + for (i = 0; i < NUM_INTSRC; i++) { + isrs[i] = default_isr; + } +} + +// enable an interrupt (with the ISR) +void pic_enable (int n, ISR isr) +{ + if ((n<0) || (n >= NUM_INTSRC)) { + panic ("invalid interrupt source"); + } + + // write 1 bit enable the interrupt, 0 bit has no effect + isrs[n] = isr; + vic_base[VIC_INTENABLE] = (1 << n); +} + +// disable an interrupt +void pic_disable (int n) +{ + if ((n<0) || (n >= NUM_INTSRC)) { + panic ("invalid interrupt source"); + } + + vic_base[VIC_INTCLEAR] = (1 << n); + isrs[n] = default_isr; +} + +// dispatch the interrupt +void pic_dispatch (struct trapframe *tp) +{ + uint intstatus; + int i; + + intstatus = vic_base[VIC_IRQSTATUS]; + + for (i = 0; i < NUM_INTSRC; i++) { + if (intstatus & (1<<i)) { + isrs[i](tp, i); + } + } + + intstatus = vic_base[VIC_IRQSTATUS]; +} +