[BACK]Return to interrupt.c CVS log [TXT][DIR] Up to [local] / prex-old / sys / arch / arm / gba

Annotation of prex-old/sys/arch/arm/gba/interrupt.c, Revision 1.1.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