|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/bsp/hal/arm/gba/interrupt.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.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 <sys/ipl.h> 35 #include <kernel.h> 36 #include <hal.h> 37 #include <irq.h> 38 #include <locore.h> 39 #include <cpufunc.h> 40 #include <context.h> 41 42 /* Number of IRQ lines */ 43 #define NIRQS 14 44 45 /* Interrupt hook vector */ 46 #define IRQ_VECTOR *(uint32_t *)0x3007ffc 47 48 /* Registers for interrupt control unit - enable/flag/master */ 49 #define ICU_IE (*(volatile uint16_t *)0x4000200) 50 #define ICU_IF (*(volatile uint16_t *)0x4000202) 51 #define ICU_IME (*(volatile uint16_t *)0x4000208) 52 53 /* ICU_IE */ 54 #define IRQ_VALID 0x3fff 55 56 /* ICU_IME */ 57 #define IRQ_OFF 0 58 #define IRQ_ON 1 59 60 /* 61 * Interrupt priority level 62 * 63 * Each interrupt has its logical priority level, with 0 being 64 * the lowest priority. While some ISR is running, all lower 65 * priority interrupts are masked off. 66 */ 67 volatile int irq_level; 68 69 /* 70 * Interrupt mapping table 71 */ 72 static int ipl_table[NIRQS]; /* Vector -> level */ 73 static uint16_t mask_table[NIPLS]; /* Level -> mask */ 74 75 /* 76 * Set mask for current ipl 77 */ 78 #define update_mask() ICU_IE = mask_table[irq_level] 79 80 /* 81 * Unmask interrupt in PIC for specified irq. 82 * The interrupt mask table is also updated. 83 * Assumes CPU interrupt is disabled in caller. 84 */ 85 void 86 interrupt_unmask(int vector, int level) 87 { 88 int i; 89 uint16_t unmask = (uint16_t)1 << vector; 90 91 /* Save level mapping */ 92 ipl_table[vector] = level; 93 94 /* 95 * Unmask target interrupt for all 96 * lower interrupt levels. 97 */ 98 for (i = 0; i < level; i++) 99 mask_table[i] |= unmask; 100 update_mask(); 101 } 102 103 /* 104 * Mask interrupt in PIC for specified irq. 105 * Interrupt must be disabled when this routine is called. 106 */ 107 void 108 interrupt_mask(int vector) 109 { 110 int i, level; 111 u_int mask = (uint16_t)~(1 << vector); 112 113 level = ipl_table[vector]; 114 for (i = 0; i < level; i++) 115 mask_table[i] &= mask; 116 ipl_table[vector] = IPL_NONE; 117 update_mask(); 118 } 119 120 /* 121 * Setup interrupt mode. 122 * Select whether an interrupt trigger is edge or level. 123 */ 124 void 125 interrupt_setup(int vector, int mode) 126 { 127 /* nop */ 128 } 129 130 /* 131 * Dispatch interrupt 132 */ 133 void 134 interrupt_dispatch(int vector) 135 { 136 int old_ipl; 137 138 /* Save & update interrupt level */ 139 old_ipl = irq_level; 140 irq_level = ipl_table[vector]; 141 update_mask(); 142 143 /* Send acknowledge to ICU for this irq */ 144 ICU_IF = (uint16_t)(1 << vector); 145 146 /* Allow another interrupt that has higher priority */ 147 splon(); 148 149 /* Dispatch interrupt */ 150 irq_handler(vector); 151 152 sploff(); 153 154 /* Restore interrupt level */ 155 irq_level = old_ipl; 156 update_mask(); 157 } 158 159 /* 160 * Common interrupt handler. 161 */ 162 void 163 interrupt_handler(void) 164 { 165 uint16_t bits; 166 int vector; 167 168 bits = ICU_IF; 169 retry: 170 for (vector = 0; vector < NIRQS; vector++) { 171 if (bits & (uint16_t)(1 << vector)) 172 break; 173 } 174 if (vector == NIRQS) 175 goto out; 176 177 interrupt_dispatch(vector); 178 179 /* 180 * Multiple interrupts can be fired in case of GBA. 181 * So, we have to check the interrupt status, again. 182 */ 183 bits = ICU_IF; 184 if (bits & IRQ_VALID) 185 goto retry; 186 out: 187 return; 188 } 189 190 /* 191 * Initialize interrupt controllers. 192 * All interrupts will be masked off. 193 */ 194 void 195 interrupt_init(void) 196 { 197 int i; 198 199 irq_level = IPL_NONE; 200 201 for (i = 0; i < NIRQS; i++) 202 ipl_table[i] = IPL_NONE; 203 204 for (i = 0; i < NIPLS; i++) 205 mask_table[i] = 0; 206 207 ICU_IME = IRQ_OFF; 208 209 /* 210 * Since GBA has its own interrupt vector in ROM area, 211 * we can not modify it. Instead, the GBA BIOS will 212 * call the user's interrupt hook routine placed in 213 * the address in 0x3007ffc. 214 */ 215 IRQ_VECTOR = (uint32_t)interrupt_entry; /* Interrupt hook address */ 216 ICU_IE = 0; /* Mask all interrupts */ 217 ICU_IME = IRQ_ON; 218 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |