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

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

CVSweb