[BACK]Return to sa11x0_intr.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / sa11x0

Annotation of sys/arch/arm/sa11x0/sa11x0_intr.c, Revision 1.3

1.1       nbrk        1: /*     $OpenBSD: pxa2x0_intr.c,v 1.15 2007/05/19 15:47:16 miod Exp $ */
                      2: /*     $NetBSD: pxa2x0_intr.c,v 1.5 2003/07/15 00:24:55 lukem Exp $    */
                      3:
                      4: /*
                      5:  * Copyright (c) 2002  Genetec Corporation.  All rights reserved.
                      6:  * Written by Hiroyuki Bessho for Genetec Corporation.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed for the NetBSD Project by
                     19:  *     Genetec Corporation.
                     20:  * 4. The name of Genetec Corporation may not be used to endorse or
                     21:  *    promote products derived from this software without specific prior
                     22:  *    written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     26:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     27:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
                     28:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     29:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     30:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     31:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     32:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     33:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     34:  * POSSIBILITY OF SUCH DAMAGE.
                     35:  */
                     36:
                     37: /*
                     38:  * IRQ handler for the Intel StrongARM SA-11[01]0 processor.
                     39:  * It has integrated interrupt controller.
                     40:  */
                     41:
                     42: #include <sys/cdefs.h>
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/malloc.h>
                     47: #include <sys/evcount.h>
                     48: #include <sys/queue.h>
                     49: #include <uvm/uvm_extern.h>
                     50:
                     51: #include <machine/bus.h>
                     52: #include <machine/intr.h>
                     53: #include <machine/lock.h>
                     54:
                     55: #include <arm/sa11x0/sa11x0_reg.h>
                     56: #include <arm/sa11x0/sa11x0_var.h>
                     57: #include <arm/sa11x0/sa11x0_intr.h>
                     58:
                     59: /*
                     60:  * INTC autoconf glue
                     61:  */
                     62: int    saic_match(struct device *, void *, void *);
                     63: void   saic_attach(struct device *, struct device *, void *);
                     64:
                     65: struct cfattach saic_ca = {
                     66:         sizeof(struct device), saic_match, saic_attach
                     67: };
                     68:
                     69: struct cfdriver saic_cd = {
                     70:        NULL, "saic", DV_DULL
                     71: };
                     72:
                     73: static int saic_attached;
                     74: vaddr_t saic_base;
                     75:
                     76: int sa11x0_stray_interrupt(void *);
                     77: void sa11x0_init_interrupt_masks(void);
                     78: void *_sa11x0_intr_establish(int irqno, int level,
                     79:     int (*func)(void *), void *arg, char *name);
                     80: void sa11x0_intr_disestablish(void *cookie);
                     81:
                     82: /* XXX defined in arch/arm/sa11x0/sa11x0_intr.h */
                     83: #define read_icu(offset) (*(volatile uint32_t *)(saic_base+(offset)))
                     84: #define write_icu(offset,value) \
                     85:  (*(volatile uint32_t *)(saic_base+(offset))=(value))
                     86:
                     87:
                     88: /*
                     89:  * interrupt dispatch table.
                     90:  */
                     91: #if 1
                     92: #define MULTIPLE_HANDLERS_ON_ONE_IRQ
                     93: #endif
                     94: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                     95: struct intrhand {
                     96:        TAILQ_ENTRY(intrhand)   ih_list;                /* link on intrq list */
                     97:        int                     (*ih_func)(void *);     /* handler */
                     98:        void                    *ih_arg;                /* arg for handler */
                     99:        char                    *ih_name;
                    100:        struct evcount          ih_count;
                    101:        int                     ih_irq;
                    102:        int                     ih_level;
                    103: };
                    104: #endif
                    105:
                    106: static struct intrhandler{
                    107: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    108:        TAILQ_HEAD(,intrhand) list;
                    109: #else
                    110:        sa11x0_irq_handler_t func;
                    111:        char *name;
                    112:        void *arg;              /* NULL for stackframe */
                    113:        int ih_irq;
                    114:        struct evcount ih_count;
                    115: #endif
                    116: } handler[ICU_LEN];
                    117:
                    118: __volatile int softint_pending;
                    119: __volatile int current_spl_level;
                    120: /* interrupt masks for each level */
                    121: int sa11x0_imask[NIPL];
                    122: static int extirq_level[ICU_LEN];
                    123:
                    124:
                    125: int
                    126: saic_match(struct device *parent, void *cf, void *aux)
                    127: {
                    128:        struct saip_attach_args *saa = aux;
                    129:
                    130:        if (saic_attached || saa->sai_addr != SAIPIC_BASE)
                    131:                return (0);
                    132:
                    133:        return (1);
                    134: }
                    135:
                    136: void
                    137: saic_attach(struct device *parent, struct device *self, void *args)
                    138: {
                    139:        int i;
                    140:
                    141:        saic_attached = 1;
                    142:
                    143:        printf(": SA-11x0 Interrupt Controller\n");
                    144:
                    145: //#define      SAIPIC_ICCR     0x14    /* XXX what's this? typo or err in spec?? */
                    146:
                    147:        write_icu(SAIPIC_CR, 1);
                    148:        write_icu(SAIPIC_MR, 0);
                    149:
                    150:        for(i = 0; i < sizeof handler / sizeof handler[0]; ++i){
                    151: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    152:                TAILQ_INIT(&handler[i].list);
                    153:                extirq_level[i] = IPL_NONE;
                    154: #else
                    155:                handler[i].name = "stray";
                    156:                handler[i].func = sa11x0_stray_interrupt;
                    157:                handler[i].arg = (void *)(u_int32_t) i;
                    158:                extirq_level[i] = IPL_SERIAL;
                    159: #endif
                    160:
                    161:        }
                    162:
                    163:        sa11x0_init_interrupt_masks();
                    164:
                    165:        _splraise(IPL_TTY);
                    166:        enable_interrupts(I32_bit);
                    167: }
                    168:
                    169: /*
                    170:  * Invoked very early on from the board-specific initarm(), in order to
                    171:  * inform us the virtual address of the interrupt controller's registers.
                    172:  */
                    173: void
                    174: sa11x0_intr_bootstrap(vaddr_t addr)
                    175: {
                    176:
                    177:        saic_base = addr;
                    178: }
                    179:
                    180: #if 0
                    181: /*
                    182:  * PXA27x has MSL interface and SSP3 interrupts [0,1], USIM interface
                    183:  * and SSP2 interrupts [15,16]. PXA255 has bits [0..6,15] reserved and
                    184:  * bit [16] network SSP interrupt.  We don't need any of those, so we
                    185:  * map software interrupts to bits [0..1,15..16].  Sadly there are no
                    186:  * four contiguous bits safe enough to use on both processors.
                    187:  */
                    188: #define SI_TO_IRQBIT(si)  ((si) < 2 ? 1U<<(si) : 1U<<(15-2+(si)))
                    189: #else
                    190: #define SI_TO_IRQBIT(si)       (1 << (si))
                    191: #endif /* 0 */
                    192:
                    193: /*
                    194:  * Map a software interrupt queue to an interrupt priority level.
                    195:  */
                    196: static const int si_to_ipl[SI_NQUEUES] = {
                    197:        IPL_SOFT,               /* SI_SOFT */
                    198:        IPL_SOFTCLOCK,          /* SI_SOFTCLOCK */
                    199:        IPL_SOFTNET,            /* SI_SOFTNET */
                    200:        IPL_SOFTSERIAL,         /* SI_SOFTSERIAL */
                    201: };
                    202:
                    203: /*
                    204:  * called from irq_entry.
                    205:  */
                    206: void
                    207: sa11x0_irq_handler(void *arg)
                    208: {
                    209:        struct clockframe *frame = arg;
                    210:        uint32_t irqbits;
                    211:        int irqno;
                    212:        int saved_spl_level;
                    213: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    214:        struct intrhand *ih;
                    215: #endif
                    216:
                    217:        saved_spl_level = current_spl_level;
                    218:
                    219:        /* get pending IRQs */
                    220:        irqbits = read_icu(SAIPIC_IP);
                    221:
                    222:        while ((irqno = find_first_bit(irqbits)) >= 0) {
                    223:                /* XXX: Should we handle IRQs in priority order? */
                    224:
                    225:                /* raise spl to stop interrupts of lower priorities */
                    226:                if (saved_spl_level < extirq_level[irqno])
                    227:                        sa11x0_setipl(extirq_level[irqno]);
                    228:
                    229:                /* Enable interrupt */
                    230:                enable_interrupts(I32_bit);
                    231:
                    232: #ifndef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    233:                (* handler[irqno].func)(
                    234:                        handler[irqno].arg == 0
                    235:                        ? frame : handler[irqno].arg );
                    236:                handler[irqno].ih_count.ec_count++;
                    237: #else
                    238:                TAILQ_FOREACH(ih, &handler[irqno].list, ih_list) {
                    239:                        if ((ih->ih_func)( ih->ih_arg == 0
                    240:                            ? frame : ih->ih_arg))
                    241:                                ih->ih_count.ec_count++;
                    242:                }
                    243: #endif
                    244:
                    245:                /* Disable interrupt */
                    246:                disable_interrupts(I32_bit);
                    247:
                    248:                irqbits &= ~(1<<irqno);
                    249:        }
                    250:
                    251:        /* restore spl to that was when this interrupt happen */
                    252:        sa11x0_setipl(saved_spl_level);
                    253:
                    254:        if(softint_pending & sa11x0_imask[current_spl_level])
                    255:                sa11x0_do_pending();
                    256: }
                    257:
                    258: int
                    259: sa11x0_stray_interrupt(void *cookie)
                    260: {
                    261:        int irqno = (int)cookie;
                    262:        printf("stray interrupt %d\n", irqno);
                    263:
                    264:        if (1 <= irqno && irqno < ICU_LEN){
                    265:                int save = disable_interrupts(I32_bit);
                    266:                write_icu(SAIPIC_MR,
                    267:                    read_icu(SAIPIC_MR) & ~(1U<<irqno));
                    268:                restore_interrupts(save);
                    269:        }
                    270:
                    271:        return 0;
                    272: }
                    273:
                    274:
                    275:
                    276: /*
                    277:  * Interrupt Mask Handling
                    278:  */
                    279:
                    280: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    281: void sa11x0_update_intr_masks(void);
                    282:
                    283: void
                    284: sa11x0_update_intr_masks()
                    285: #else
                    286: void sa11x0_update_intr_masks(int irqno, int level);
                    287:
                    288: void
                    289: sa11x0_update_intr_masks(int irqno, int irqlevel)
                    290: #endif
                    291: {
                    292:        int psw;
                    293:
                    294: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    295:        int irq;
                    296: #ifdef DEBUG
                    297:        int level;
                    298: #endif
                    299:        struct intrhand *ih;
                    300:        psw = disable_interrupts(I32_bit);
                    301:
                    302:        /* First figure out which levels each IRQ uses. */
                    303:        for (irq = 0; irq < ICU_LEN; irq++) {
                    304:                int i;
                    305:                int max = IPL_NONE;
                    306:                int min = IPL_HIGH; /* XXX kill IPL_SERIAL */
                    307:                TAILQ_FOREACH(ih, &handler[irq].list, ih_list) {
                    308:                        if (ih->ih_level > max)
                    309:                                max = ih->ih_level;
                    310:
                    311:                        if (ih->ih_level < min)
                    312:                                min = ih->ih_level;
                    313:                }
                    314:
                    315:                extirq_level[irq] = max;
                    316:
                    317:                if (min == IPL_HIGH)
                    318:                        min = IPL_NONE;
                    319:
                    320:                /* Enable interrupt at lower level */
                    321:                for(i = 0; i < min; ++i)
                    322:                        sa11x0_imask[i] |= (1 << irq);
                    323:
                    324:                /* Disable interrupt at upper level */
                    325:                for( ; i < NIPL-1; ++i)
                    326:                        sa11x0_imask[i] &= ~(1 << irq);
                    327:        }
                    328:
                    329:        /* fixup */
                    330:        sa11x0_imask[IPL_NONE] |=
                    331:            SI_TO_IRQBIT(SI_SOFT) |
                    332:            SI_TO_IRQBIT(SI_SOFTCLOCK) |
                    333:            SI_TO_IRQBIT(SI_SOFTNET) |
                    334:            SI_TO_IRQBIT(SI_SOFTSERIAL);
                    335:        sa11x0_imask[IPL_SOFT] |=
                    336:            SI_TO_IRQBIT(SI_SOFTCLOCK) |
                    337:            SI_TO_IRQBIT(SI_SOFTNET) |
                    338:            SI_TO_IRQBIT(SI_SOFTSERIAL);
                    339:        sa11x0_imask[IPL_SOFTCLOCK] |=
                    340:            SI_TO_IRQBIT(SI_SOFTNET) |
                    341:            SI_TO_IRQBIT(SI_SOFTSERIAL);
                    342:        sa11x0_imask[IPL_SOFTNET] |=
                    343:            SI_TO_IRQBIT(SI_SOFTSERIAL);
                    344:        sa11x0_imask[IPL_SOFTSERIAL] |=
                    345:            0;
                    346: #else
                    347:        int level; /* debug */
                    348:        int mask = 1U<<irqno;
                    349:        int i;
                    350:        psw = disable_interrupts(I32_bit);
                    351:
                    352:        for(i = 0; i < irqlevel; ++i)
                    353:                sa11x0_imask[i] |= mask; /* Enable interrupt at lower level */
                    354:
                    355:        for( ; i < NIPL-1; ++i)
                    356:                sa11x0_imask[i] &= ~mask; /* Disable interrupt at upper level */
                    357: #endif
                    358:
                    359:        /*
                    360:         * Enforce a hierarchy that gives "slow" device (or devices with
                    361:         * limited input buffer space/"real-time" requirements) a better
                    362:         * chance at not dropping data.
                    363:         */
                    364:        sa11x0_imask[IPL_BIO] &= sa11x0_imask[IPL_SOFTNET];
                    365:        sa11x0_imask[IPL_NET] &= sa11x0_imask[IPL_BIO];
                    366:        sa11x0_imask[IPL_SOFTSERIAL] &= sa11x0_imask[IPL_NET];
                    367:        sa11x0_imask[IPL_TTY] &= sa11x0_imask[IPL_SOFTSERIAL];
                    368:
                    369:        /*
                    370:         * splvm() blocks all interrupts that use the kernel memory
                    371:         * allocation facilities.
                    372:         */
                    373:        sa11x0_imask[IPL_VM] &= sa11x0_imask[IPL_TTY];
                    374:
                    375:        /*
                    376:         * Audio devices are not allowed to perform memory allocation
                    377:         * in their interrupt routines, and they have fairly "real-time"
                    378:         * requirements, so give them a high interrupt priority.
                    379:         */
                    380:        sa11x0_imask[IPL_AUDIO] &= sa11x0_imask[IPL_VM];
                    381:
                    382:        /*
                    383:         * splclock() must block anything that uses the scheduler.
                    384:         */
                    385:        sa11x0_imask[IPL_CLOCK] &= sa11x0_imask[IPL_AUDIO];
                    386:
                    387:        /*
                    388:         * splhigh() must block "everything".
                    389:         */
                    390:        sa11x0_imask[IPL_HIGH] &= sa11x0_imask[IPL_STATCLOCK];
                    391:
                    392:        /*
                    393:         * XXX We need serial drivers to run at the absolute highest priority
                    394:         * in order to avoid overruns, so serial > high.
                    395:         */
                    396:        sa11x0_imask[IPL_TTY] &= sa11x0_imask[IPL_HIGH];
                    397:
                    398: #ifdef DEBUG
                    399:        for (level = IPL_NONE; level < NIPL; level++) {
                    400:                printf("imask %d, %x\n", level, sa11x0_imask[level]);
                    401:        }
                    402: #endif
                    403:
                    404: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    405:        for (irq = 0; irq < ICU_LEN; irq++) {
                    406:                int max_irq = IPL_NONE;
                    407:                TAILQ_FOREACH(ih, &handler[irq].list, ih_list) {
                    408:                        if (ih->ih_level > max_irq)
                    409:                                max_irq  = ih->ih_level;
                    410:                }
                    411:                extirq_level[irq] = max_irq;
                    412:        }
                    413: #endif
                    414:
                    415:        write_icu(SAIPIC_MR, sa11x0_imask[current_spl_level]);
                    416:
                    417:        restore_interrupts(psw);
                    418: }
                    419:
                    420:
                    421: void
                    422: sa11x0_init_interrupt_masks(void)
                    423: {
                    424:
                    425:        memset(sa11x0_imask, 0, sizeof(sa11x0_imask));
                    426:
                    427:        /*
                    428:         * IPL_NONE has soft interrupts enabled only, at least until
                    429:         * hardware handlers are installed.
                    430:         */
                    431:        sa11x0_imask[IPL_NONE] =
                    432:            SI_TO_IRQBIT(SI_SOFT) |
                    433:            SI_TO_IRQBIT(SI_SOFTCLOCK) |
                    434:            SI_TO_IRQBIT(SI_SOFTNET) |
                    435:            SI_TO_IRQBIT(SI_SOFTSERIAL);
                    436:
                    437:        /*
                    438:         * Initialize the soft interrupt masks to block themselves.
                    439:         */
                    440:        sa11x0_imask[IPL_SOFT] = ~SI_TO_IRQBIT(SI_SOFT);
                    441:        sa11x0_imask[IPL_SOFTCLOCK] = ~SI_TO_IRQBIT(SI_SOFTCLOCK);
                    442:        sa11x0_imask[IPL_SOFTNET] = ~SI_TO_IRQBIT(SI_SOFTNET);
                    443:        sa11x0_imask[IPL_SOFTSERIAL] = ~SI_TO_IRQBIT(SI_SOFTSERIAL);
                    444:
                    445:        sa11x0_imask[IPL_SOFT] &= sa11x0_imask[IPL_NONE];
                    446:
                    447:        /*
                    448:         * splsoftclock() is the only interface that users of the
                    449:         * generic software interrupt facility have to block their
                    450:         * soft intrs, so splsoftclock() must also block IPL_SOFT.
                    451:         */
                    452:        sa11x0_imask[IPL_SOFTCLOCK] &= sa11x0_imask[IPL_SOFT];
                    453:
                    454:        /*
                    455:         * splsoftnet() must also block splsoftclock(), since we don't
                    456:         * want timer-driven network events to occur while we're
                    457:         * processing incoming packets.
                    458:         */
                    459:        sa11x0_imask[IPL_SOFTNET] &= sa11x0_imask[IPL_SOFTCLOCK];
                    460: }
                    461:
                    462: void
                    463: sa11x0_do_pending(void)
                    464: {
                    465:        static __cpu_simple_lock_t processing = __SIMPLELOCK_UNLOCKED;
                    466:        int oldirqstate, spl_save;
                    467:
                    468:        if (__cpu_simple_lock_try(&processing) == 0)
                    469:                return;
                    470:
                    471:        spl_save = current_spl_level;
                    472:
                    473:        oldirqstate = disable_interrupts(I32_bit);
                    474:
                    475: #if 1
                    476: #define        DO_SOFTINT(si,ipl)                                              \
                    477:        if ((softint_pending & sa11x0_imask[current_spl_level]) &       \
                    478:            SI_TO_IRQBIT(si)) {         \
                    479:                softint_pending &= ~SI_TO_IRQBIT(si);                   \
                    480:                if (current_spl_level < ipl)                            \
                    481:                        sa11x0_setipl(ipl);                             \
                    482:                restore_interrupts(oldirqstate);                        \
                    483:                softintr_dispatch(si);                                  \
                    484:                oldirqstate = disable_interrupts(I32_bit);              \
                    485:                sa11x0_setipl(spl_save);                                \
                    486:        }
                    487:
                    488:        do {
                    489:                DO_SOFTINT(SI_SOFTSERIAL,IPL_SOFTSERIAL);
                    490:                DO_SOFTINT(SI_SOFTNET, IPL_SOFTNET);
                    491:                DO_SOFTINT(SI_SOFTCLOCK, IPL_SOFTCLOCK);
                    492:                DO_SOFTINT(SI_SOFT, IPL_SOFT);
                    493:        } while( softint_pending & sa11x0_imask[current_spl_level] );
                    494: #else
                    495:        while( (si = find_first_bit(softint_pending & sa11x0_imask[current_spl_level])) >= 0 ){
                    496:                softint_pending &= ~SI_TO_IRQBIT(si);
                    497:                if (current_spl_level < ipl)
                    498:                        sa11x0_setipl(ipl);
                    499:                restore_interrupts(oldirqstate);
                    500:                softintr_dispatch(si);
                    501:                oldirqstate = disable_interrupts(I32_bit);
                    502:                sa11x0_setipl(spl_save);
                    503:        }
                    504: #endif
                    505:
                    506:        __cpu_simple_unlock(&processing);
                    507:
                    508:        restore_interrupts(oldirqstate);
                    509: }
                    510:
                    511:
                    512: #undef splx
                    513: void
                    514: splx(int ipl)
                    515: {
                    516:
                    517:        sa11x0_splx(ipl);
                    518: }
                    519:
                    520: #undef _splraise
                    521: int
                    522: _splraise(int ipl)
                    523: {
                    524:
                    525:        return sa11x0_splraise(ipl);
                    526: }
                    527:
                    528: #undef _spllower
                    529: int
                    530: _spllower(int ipl)
                    531: {
                    532:
                    533:        return sa11x0_spllower(ipl);
                    534: }
                    535:
                    536: #undef _setsoftintr
                    537: void
                    538: _setsoftintr(int si)
                    539: {
                    540:
                    541:        return sa11x0_setsoftintr(si);
                    542: }
                    543:
                    544: void *
                    545: _sa11x0_intr_establish(int irqno, int level,
                    546:     int (*func)(void *), void *arg, char *name)
                    547: {
                    548:        int psw;
                    549: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    550:        struct intrhand *ih;
                    551: #else
                    552:        struct intrhandler *ih;
                    553: #endif
                    554:
                    555:        if (irqno < 0 || irqno >= ICU_LEN - 1)
                    556:                panic("intr_establish: bogus irq number %d", irqno);
                    557:
                    558:        psw = disable_interrupts(I32_bit);
                    559:
                    560: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    561:        /* no point in sleeping unless someone can free memory. */
                    562:        MALLOC(ih, struct intrhand *, sizeof *ih, M_DEVBUF,
                    563:            cold ? M_NOWAIT : M_WAITOK);
                    564:        if (ih == NULL)
                    565:                panic("intr_establish: can't malloc handler info");
                    566:         ih->ih_func = func;
                    567:        ih->ih_arg = arg;
                    568:        ih->ih_level = level;
                    569:        ih->ih_irq = irqno;
                    570:
                    571:        TAILQ_INSERT_TAIL(&handler[irqno].list, ih, ih_list);
                    572: #else
                    573:        ih = &handler[irqno];
                    574:        ih->arg = arg;
                    575:        ih->func = func;
                    576:        ih->name = name;
                    577:        ih->ih_irq = irqno;
                    578:        extirq_level[irqno] = level;
                    579: #endif
                    580:
                    581:        if (name != NULL)
                    582:                evcount_attach(&ih->ih_count, name, (void *)&ih->ih_irq,
                    583:                    &evcount_intr);
                    584:
                    585: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    586:        sa11x0_update_intr_masks();
                    587: #else
                    588:        sa11x0_update_intr_masks(irqno, level);
                    589: #endif
                    590:
                    591:        restore_interrupts(psw);
                    592:
                    593:        return (ih);
                    594: }
                    595:
                    596: void
                    597: sa11x0_intr_disestablish(void *cookie)
                    598: {
                    599:
                    600: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    601:        int psw;
                    602:        struct intrhand *ih = cookie;
                    603:        int irqno =  ih->ih_irq;
                    604:
                    605:        psw = disable_interrupts(I32_bit);
                    606:        TAILQ_REMOVE(&handler[irqno].list, ih, ih_list);
                    607:
                    608:        FREE(ih, M_DEVBUF);
                    609:
                    610:        sa11x0_update_intr_masks();
                    611:
                    612:        restore_interrupts(psw);
                    613: #else
                    614:        struct intrhandler *lhandler = cookie;
                    615:        int irqno;
                    616:        int psw;
                    617:        struct intrhandler *ih;
                    618:        irqno = lhandler - handler;
                    619:
1.3     ! nbrk      620:        if (irqno < 0 || irqno >= ICU_LEN)
1.1       nbrk      621:                panic("intr_disestablish: bogus irq number %d", irqno);
                    622:
                    623:        psw = disable_interrupts(I32_bit);
                    624:
                    625:        ih = &handler[irqno];
                    626:        if (ih->name != NULL)
                    627:                evcount_detach(&ih->ih_count);
                    628:
                    629:        ih->arg = (void *) irqno;
                    630:        ih->func = sa11x0_stray_interrupt;
                    631:        ih->name = "stray";
                    632:        extirq_level[irqno] = IPL_SERIAL;
                    633:        sa11x0_update_intr_masks(irqno, IPL_SERIAL);
                    634:
                    635:        restore_interrupts(psw);
                    636: #endif
                    637: }
                    638:
                    639: /*
                    640:  * Glue for drivers of sa11x0 compatible integrated logic.
                    641:  */
                    642:
                    643: void *
                    644: sa11x0_intr_establish(sa11x0_chipset_tag_t ic, int irq, int type, int level,
                    645:     int (*ih_fun)(void *), void *ih_arg, char *name)
                    646: {
                    647:        /* XXX */
                    648:        return _sa11x0_intr_establish(irq, level, ih_fun, ih_arg, name);
                    649: }
                    650:
                    651: void
                    652: sa11x0_setipl(int new)
                    653: {
                    654:        u_int32_t intr_mask;
                    655:
                    656:        intr_mask = sa11x0_imask[new];
                    657:        current_spl_level = new;
                    658:        write_icu( SAIPIC_MR, intr_mask );
                    659: }
                    660:
                    661:
                    662: void
                    663: sa11x0_splx(int new)
                    664: {
                    665:        int psw;
                    666:
                    667:        psw = disable_interrupts(I32_bit);
                    668:        sa11x0_setipl(new);
                    669:        restore_interrupts(psw);
                    670:
                    671:        /* If there are pending software interrupts, process them. */
                    672:        if (softint_pending & sa11x0_imask[current_spl_level])
                    673:                sa11x0_do_pending();
                    674: }
                    675:
                    676:
                    677: int
                    678: sa11x0_splraise(int ipl)
                    679: {
                    680:        int     old, psw;
                    681:
                    682:        old = current_spl_level;
                    683:        if( ipl > current_spl_level ){
                    684:                psw = disable_interrupts(I32_bit);
                    685:                sa11x0_setipl(ipl);
                    686:                restore_interrupts(psw);
                    687:        }
                    688:
                    689:        return (old);
                    690: }
                    691:
                    692: int
                    693: sa11x0_spllower(int ipl)
                    694: {
                    695:        int old = current_spl_level;
                    696:        int psw = disable_interrupts(I32_bit);
                    697:        sa11x0_splx(ipl);
                    698:        restore_interrupts(psw);
                    699:        return(old);
                    700: }
                    701:
                    702: void
                    703: sa11x0_setsoftintr(int si)
                    704: {
                    705: #if 0
                    706:        atomic_set_bit( (u_int *)&softint_pending, SI_TO_IRQBIT(si) );
                    707: #else
                    708:        softint_pending |=  SI_TO_IRQBIT(si);
                    709: #endif
                    710:
                    711:        /* Process unmasked pending soft interrupts. */
                    712:        if ( softint_pending & sa11x0_imask[current_spl_level] )
                    713:                sa11x0_do_pending();
                    714: }
                    715:
                    716: const char *
                    717: sa11x0_intr_string(void *cookie)
                    718: {
                    719: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    720:        struct intrhand *ih = cookie;
                    721: #else
                    722:        struct intrhandler *lhandler = cookie;
                    723: #endif
                    724:        static char irqstr[32];
                    725:
                    726:        if (ih == NULL)
                    727:                snprintf(irqstr, sizeof irqstr, "couldn't establish interrupt");
                    728:        else
                    729:                snprintf(irqstr, sizeof irqstr, "irq %ld", ih->ih_irq);
                    730:
                    731:        return irqstr;
                    732: }
                    733:
                    734: #ifdef DIAGNOSTIC
                    735: void
                    736: sa11x0_splassert_check(int wantipl, const char *func)
                    737: {
                    738:        int oldipl = current_spl_level, psw;
                    739:
                    740:        if (oldipl < wantipl) {
                    741:                splassert_fail(wantipl, oldipl, func);
                    742:                /*
                    743:                 * If the splassert_ctl is set to not panic, raise the ipl
                    744:                 * in a feeble attempt to reduce damage.
                    745:                 */
                    746:                psw = disable_interrupts(I32_bit);
                    747:                sa11x0_setipl(wantipl);
                    748:                restore_interrupts(psw);
                    749:        }
                    750: }
                    751: #endif

CVSweb