Annotation of prex-old/sys/arch/arm/gba/interrupt.c, Revision 1.1
1.1 ! nbrk 1: /*-
! 2: * Copyright (c) 2005-2007, Kohsuke Ohtani
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: * 3. Neither the name of the author nor the names of any co-contributors
! 14: * may be used to endorse or promote products derived from this software
! 15: * without specific prior written permission.
! 16: *
! 17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 27: * SUCH DAMAGE.
! 28: */
! 29:
! 30: /*
! 31: * interrupt.c - interrupt handling routines for GBA
! 32: */
! 33:
! 34: #include <kernel.h>
! 35: #include <irq.h>
! 36: #include <locore.h>
! 37:
! 38: /* Interrupt hook vector */
! 39: #define IRQ_VECTOR *(uint32_t *)0x3007ffc
! 40:
! 41: /* Registers for interrupt control unit - enable/flag/master */
! 42: #define ICU_IE (*(volatile uint16_t *)0x4000200)
! 43: #define ICU_IF (*(volatile uint16_t *)0x4000202)
! 44: #define ICU_IME (*(volatile uint16_t *)0x4000208)
! 45:
! 46: /* ICU_IE */
! 47: #define IRQ_VALID 0x3fff
! 48:
! 49: /* ICU_IME */
! 50: #define IRQ_OFF 0
! 51: #define IRQ_ON 1
! 52:
! 53: /*
! 54: * Interrupt priority level
! 55: *
! 56: * Each interrupt has its logical priority level, with 0 being the highest
! 57: * priority. While some ISR is running, all lower priority interrupts
! 58: * are masked off.
! 59: */
! 60: volatile int irq_level;
! 61:
! 62: /*
! 63: * Interrupt mapping table
! 64: */
! 65: static int ipl_table[NIRQS]; /* Vector -> level */
! 66: static uint16_t mask_table[NIPLS]; /* Level -> mask */
! 67:
! 68: /*
! 69: * Set mask for current ipl
! 70: */
! 71: #define update_mask() ICU_IE = mask_table[irq_level]
! 72:
! 73: /*
! 74: * Unmask interrupt in PIC for specified irq.
! 75: * The interrupt mask table is also updated.
! 76: * Assumed CPU interrupt is disabled in caller.
! 77: */
! 78: void
! 79: interrupt_unmask(int vector, int level)
! 80: {
! 81: int i;
! 82: uint16_t unmask = (uint16_t)1 << vector;
! 83:
! 84: ipl_table[vector] = level;
! 85: /*
! 86: * Unmask target interrupt for all
! 87: * lower interrupt levels.
! 88: */
! 89: for (i = 0; i < level; i++)
! 90: mask_table[i] |= unmask;
! 91: update_mask();
! 92: }
! 93:
! 94: /*
! 95: * Mask interrupt in PIC for specified irq.
! 96: * Interrupt must be disabled when this routine is called.
! 97: */
! 98: void
! 99: interrupt_mask(int vector)
! 100: {
! 101: int i, level;
! 102: u_int mask = (uint16_t)~(1 << vector);
! 103:
! 104: level = ipl_table[vector];
! 105: for (i = 0; i < level; i++)
! 106: mask_table[i] &= mask;
! 107: ipl_table[vector] = IPL_NONE;
! 108: update_mask();
! 109: }
! 110:
! 111: /*
! 112: * Setup interrupt mode.
! 113: * Select whether an interrupt trigger is edge or level.
! 114: */
! 115: void
! 116: interrupt_setup(int vector, int mode)
! 117: {
! 118: /* nop */
! 119: }
! 120:
! 121: /*
! 122: * Dispatch interrupt
! 123: *
! 124: */
! 125: void
! 126: interrupt_dispatch(int vector)
! 127: {
! 128: int old_ipl;
! 129:
! 130: /* Save & update interrupt level */
! 131: old_ipl = irq_level;
! 132: irq_level = ipl_table[vector];
! 133: update_mask();
! 134:
! 135: /* Send acknowledge to ICU for this irq */
! 136: ICU_IF = (uint16_t)(1 << vector);
! 137:
! 138: /* Allow another interrupt that has higher priority */
! 139: interrupt_enable();
! 140:
! 141: /* Dispatch interrupt */
! 142: irq_handler(vector);
! 143:
! 144: interrupt_disable();
! 145:
! 146: /* Restore interrupt level */
! 147: irq_level = old_ipl;
! 148: update_mask();
! 149: }
! 150:
! 151: /*
! 152: * Common interrupt handler.
! 153: */
! 154: void
! 155: interrupt_handler(void)
! 156: {
! 157: uint16_t bits;
! 158: int vector;
! 159:
! 160: bits = ICU_IF;
! 161: retry:
! 162: for (vector = 0; vector < NIRQS; vector++) {
! 163: if (bits & (uint16_t)(1 << vector))
! 164: break;
! 165: }
! 166: if (vector == NIRQS)
! 167: goto out;
! 168:
! 169: interrupt_dispatch(vector);
! 170:
! 171: /*
! 172: * Multiple interrupts can be fired in case of GBA.
! 173: * So, we have to check the interrupt status, again.
! 174: */
! 175: bits = ICU_IF;
! 176: if (bits & IRQ_VALID)
! 177: goto retry;
! 178: out:
! 179: return;
! 180: }
! 181:
! 182: /*
! 183: * Initialize interrupt controllers.
! 184: * All interrupts will be masked off.
! 185: */
! 186: void
! 187: interrupt_init(void)
! 188: {
! 189: int i;
! 190:
! 191: irq_level = IPL_NONE;
! 192:
! 193: for (i = 0; i < NIRQS; i++)
! 194: ipl_table[i] = IPL_NONE;
! 195:
! 196: for (i = 0; i < NIPLS; i++)
! 197: mask_table[i] = 0;
! 198:
! 199: ICU_IME = IRQ_OFF;
! 200: IRQ_VECTOR = (uint32_t)interrupt_entry; /* Interrupt hook address */
! 201: ICU_IE = 0; /* Mask all interrupts */
! 202: ICU_IME = IRQ_ON;
! 203: }
CVSweb