[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     ! 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