[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.1.1.1

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

CVSweb