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

Annotation of sys/arch/alpha/alpha/interrupt.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: interrupt.c,v 1.24 2007/06/17 10:01:25 miod Exp $ */
                      2: /* $NetBSD: interrupt.c,v 1.46 2000/06/03 20:47:36 thorpej Exp $ */
                      3:
                      4: /*-
                      5:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Jason R. Thorpe.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
                     42:  * All rights reserved.
                     43:  *
                     44:  * Authors: Keith Bostic, Chris G. Demetriou
                     45:  *
                     46:  * Permission to use, copy, modify and distribute this software and
                     47:  * its documentation is hereby granted, provided that both the copyright
                     48:  * notice and this permission notice appear in all copies of the
                     49:  * software, derivative works or modified versions, and any portions
                     50:  * thereof, and that both notices appear in supporting documentation.
                     51:  *
                     52:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     53:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
                     54:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     55:  *
                     56:  * Carnegie Mellon requests users of this software to return to
                     57:  *
                     58:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     59:  *  School of Computer Science
                     60:  *  Carnegie Mellon University
                     61:  *  Pittsburgh PA 15213-3890
                     62:  *
                     63:  * any improvements or extensions that they make and grant Carnegie the
                     64:  * rights to redistribute these changes.
                     65:  */
                     66: /*
                     67:  * Additional Copyright (c) 1997 by Matthew Jacob for NASA/Ames Research Center.
                     68:  * Redistribute and modify at will, leaving only this additional copyright
                     69:  * notice.
                     70:  */
                     71:
                     72: #include <sys/param.h>
                     73: #include <sys/systm.h>
                     74: #include <sys/proc.h>
                     75: #include <sys/vmmeter.h>
                     76: #include <sys/sched.h>
                     77: #include <sys/kernel.h>
                     78: #include <sys/systm.h>
                     79: #include <sys/device.h>
                     80: #include <sys/mbuf.h>
                     81: #include <sys/socket.h>
                     82: #include <sys/evcount.h>
                     83:
                     84: #include <uvm/uvm_extern.h>
                     85:
                     86: #include <machine/atomic.h>
                     87: #include <machine/autoconf.h>
                     88: #include <machine/cpu.h>
                     89: #include <machine/reg.h>
                     90: #include <machine/rpb.h>
                     91: #include <machine/frame.h>
                     92: #include <machine/cpuconf.h>
                     93:
                     94: #if defined(MULTIPROCESSOR)
                     95: #include <sys/device.h>
                     96: #endif
                     97:
                     98: #include <net/netisr.h>
                     99: #include <net/if.h>
                    100:
                    101: #ifdef INET
                    102: #include <netinet/in.h>
                    103: #include <netinet/if_ether.h>
                    104: #include <netinet/ip_var.h>
                    105: #endif
                    106:
                    107: #ifdef INET6
                    108: #ifndef INET
                    109: #include <netinet/in.h>
                    110: #endif
                    111: #include <netinet/ip6.h>
                    112: #include <netinet6/ip6_var.h>
                    113: #endif
                    114:
                    115: #include "ppp.h"
                    116: #include "bridge.h"
                    117:
                    118: #include "apecs.h"
                    119: #include "cia.h"
                    120: #include "lca.h"
                    121: #include "tcasic.h"
                    122:
                    123: static u_int schedclk2;
                    124:
                    125: extern struct evcount clk_count;
                    126:
                    127: struct scbvec scb_iovectab[SCB_VECTOIDX(SCB_SIZE - SCB_IOVECBASE)];
                    128:
                    129: void netintr(void);
                    130:
                    131: void   scb_stray(void *, u_long);
                    132:
                    133: void
                    134: scb_init(void)
                    135: {
                    136:        u_long i;
                    137:
                    138:        for (i = 0; i < SCB_NIOVECS; i++) {
                    139:                scb_iovectab[i].scb_func = scb_stray;
                    140:                scb_iovectab[i].scb_arg = NULL;
                    141:        }
                    142: }
                    143:
                    144: void
                    145: scb_stray(void *arg, u_long vec)
                    146: {
                    147:
                    148:        printf("WARNING: stray interrupt, vector 0x%lx\n", vec);
                    149: }
                    150:
                    151: void
                    152: scb_set(u_long vec, void (*func)(void *, u_long), void *arg)
                    153: {
                    154:        u_long idx;
                    155:        int s;
                    156:
                    157:        s = splhigh();
                    158:
                    159:        if (vec < SCB_IOVECBASE || vec >= SCB_SIZE ||
                    160:            (vec & (SCB_VECSIZE - 1)) != 0)
                    161:                panic("scb_set: bad vector 0x%lx", vec);
                    162:
                    163:        idx = SCB_VECTOIDX(vec - SCB_IOVECBASE);
                    164:
                    165:        if (scb_iovectab[idx].scb_func != scb_stray)
                    166:                panic("scb_set: vector 0x%lx already occupied", vec);
                    167:
                    168:        scb_iovectab[idx].scb_func = func;
                    169:        scb_iovectab[idx].scb_arg = arg;
                    170:
                    171:        splx(s);
                    172: }
                    173:
                    174: u_long
                    175: scb_alloc(void (*func)(void *, u_long), void *arg)
                    176: {
                    177:        u_long vec, idx;
                    178:        int s;
                    179:
                    180:        s = splhigh();
                    181:
                    182:        /*
                    183:         * Allocate "downwards", to avoid bumping into
                    184:         * interrupts which are likely to be at the lower
                    185:         * vector numbers.
                    186:         */
                    187:        for (vec = SCB_SIZE - SCB_VECSIZE;
                    188:             vec >= SCB_IOVECBASE; vec -= SCB_VECSIZE) {
                    189:                idx = SCB_VECTOIDX(vec - SCB_IOVECBASE);
                    190:                if (scb_iovectab[idx].scb_func == scb_stray) {
                    191:                        scb_iovectab[idx].scb_func = func;
                    192:                        scb_iovectab[idx].scb_arg = arg;
                    193:                        splx(s);
                    194:                        return (vec);
                    195:                }
                    196:        }
                    197:
                    198:        splx(s);
                    199:
                    200:        return (SCB_ALLOC_FAILED);
                    201: }
                    202:
                    203: void
                    204: scb_free(u_long vec)
                    205: {
                    206:        u_long idx;
                    207:        int s;
                    208:
                    209:        s = splhigh();
                    210:
                    211:        if (vec < SCB_IOVECBASE || vec >= SCB_SIZE ||
                    212:            (vec & (SCB_VECSIZE - 1)) != 0)
                    213:                panic("scb_free: bad vector 0x%lx", vec);
                    214:
                    215:        idx = SCB_VECTOIDX(vec - SCB_IOVECBASE);
                    216:
                    217:        if (scb_iovectab[idx].scb_func == scb_stray)
                    218:                panic("scb_free: vector 0x%lx is empty", vec);
                    219:
                    220:        scb_iovectab[idx].scb_func = scb_stray;
                    221:        scb_iovectab[idx].scb_arg = (void *) vec;
                    222:
                    223:        splx(s);
                    224: }
                    225:
                    226: void
                    227: interrupt(unsigned long a0, unsigned long a1, unsigned long a2,
                    228:     struct trapframe *framep)
                    229: {
                    230:        struct proc *p;
                    231:        struct cpu_info *ci = curcpu();
                    232:        extern int schedhz;
                    233:
                    234:        switch (a0) {
                    235:        case ALPHA_INTR_XPROC:  /* interprocessor interrupt */
                    236: #if defined(MULTIPROCESSOR)
                    237:            {
                    238:                u_long pending_ipis, bit;
                    239:
                    240: #if 0
                    241:                printf("CPU %lu got IPI\n", cpu_id);
                    242: #endif
                    243:
                    244: #ifdef DIAGNOSTIC
                    245:                if (ci->ci_dev == NULL) {
                    246:                        /* XXX panic? */
                    247:                        printf("WARNING: no device for ID %lu\n", ci->ci_cpuid);
                    248:                        return;
                    249:                }
                    250: #endif
                    251:
                    252:                pending_ipis = atomic_loadlatch_ulong(&ci->ci_ipis, 0);
                    253:                for (bit = 0; bit < ALPHA_NIPIS; bit++)
                    254:                        if (pending_ipis & (1UL << bit))
                    255:                                (*ipifuncs[bit])();
                    256:
                    257:                /*
                    258:                 * Handle inter-console messages if we're the primary
                    259:                 * CPU.
                    260:                 */
                    261:                if (ci->ci_cpuid == hwrpb->rpb_primary_cpu_id &&
                    262:                    hwrpb->rpb_txrdy != 0)
                    263:                        cpu_iccb_receive();
                    264:            }
                    265: #else
                    266:                printf("WARNING: received interprocessor interrupt!\n");
                    267: #endif /* MULTIPROCESSOR */
                    268:                break;
                    269:
                    270:        case ALPHA_INTR_CLOCK:  /* clock interrupt */
                    271: #if defined(MULTIPROCESSOR)
                    272:                /* XXX XXX XXX */
                    273:                if (CPU_IS_PRIMARY(ci) == 0)
                    274:                        return;
                    275: #endif
                    276:                uvmexp.intrs++;
                    277:                clk_count.ec_count++;
                    278:                if (platform.clockintr) {
                    279:                        /*
                    280:                         * Call hardclock().  This will also call
                    281:                         * statclock(). On the primary CPU, it
                    282:                         * will also deal with time-of-day stuff.
                    283:                         */
                    284:                        (*platform.clockintr)((struct clockframe *)framep);
                    285:
                    286:                        /*
                    287:                         * If it's time to call the scheduler clock,
                    288:                         * do so.
                    289:                         */
                    290:                        if ((++schedclk2 & 0x3f) == 0 &&
                    291:                            (p = ci->ci_curproc) != NULL && schedhz != 0)
                    292:                                schedclock(p);
                    293:                }
                    294:                break;
                    295:
                    296:        case ALPHA_INTR_ERROR:  /* Machine Check or Correctable Error */
                    297:                a0 = alpha_pal_rdmces();
                    298:                if (platform.mcheck_handler)
                    299:                        (*platform.mcheck_handler)(a0, framep, a1, a2);
                    300:                else
                    301:                        machine_check(a0, framep, a1, a2);
                    302:                break;
                    303:
                    304:        case ALPHA_INTR_DEVICE: /* I/O device interrupt */
                    305:            {
                    306:                struct scbvec *scb;
                    307:
                    308:                KDASSERT(a1 >= SCB_IOVECBASE && a1 < SCB_SIZE);
                    309:
                    310: #if defined(MULTIPROCESSOR)
                    311:                /* XXX XXX XXX */
                    312:                if (CPU_IS_PRIMARY(ci) == 0)
                    313:                        return;
                    314: #endif
                    315:                uvmexp.intrs++;
                    316:
                    317:                scb = &scb_iovectab[SCB_VECTOIDX(a1 - SCB_IOVECBASE)];
                    318:                (*scb->scb_func)(scb->scb_arg, a1);
                    319:                break;
                    320:            }
                    321:
                    322:        case ALPHA_INTR_PERF:   /* performance counter interrupt */
                    323:                printf("WARNING: received performance counter interrupt!\n");
                    324:                break;
                    325:
                    326:        case ALPHA_INTR_PASSIVE:
                    327: #if 0
                    328:                printf("WARNING: received passive release interrupt vec "
                    329:                    "0x%lx\n", a1);
                    330: #endif
                    331:                break;
                    332:
                    333:        default:
                    334:                printf("unexpected interrupt: type 0x%lx vec 0x%lx "
                    335:                    "a2 0x%lx"
                    336: #if defined(MULTIPROCESSOR)
                    337:                    " cpu %lu"
                    338: #endif
                    339:                    "\n", a0, a1, a2
                    340: #if defined(MULTIPROCESSOR)
                    341:                    , ci->ci_cpuid
                    342: #endif
                    343:                    );
                    344:                panic("interrupt");
                    345:                /* NOTREACHED */
                    346:        }
                    347: }
                    348:
                    349: void
                    350: machine_check(unsigned long mces, struct trapframe *framep,
                    351:     unsigned long vector, unsigned long param)
                    352: {
                    353:        const char *type;
                    354:        struct mchkinfo *mcp;
                    355:
                    356:        mcp = &curcpu()->ci_mcinfo;
                    357:        /* Make sure it's an error we know about. */
                    358:        if ((mces & (ALPHA_MCES_MIP|ALPHA_MCES_SCE|ALPHA_MCES_PCE)) == 0) {
                    359:                type = "fatal machine check or error (unknown type)";
                    360:                goto fatal;
                    361:        }
                    362:
                    363:        /* Machine checks. */
                    364:        if (mces & ALPHA_MCES_MIP) {
                    365:                /* If we weren't expecting it, then we punt. */
                    366:                if (!mcp->mc_expected) {
                    367:                        type = "unexpected machine check";
                    368:                        goto fatal;
                    369:                }
                    370:                mcp->mc_expected = 0;
                    371:                mcp->mc_received = 1;
                    372:        }
                    373:
                    374:        /* System correctable errors. */
                    375:        if (mces & ALPHA_MCES_SCE)
                    376:                printf("Warning: received system correctable error.\n");
                    377:
                    378:        /* Processor correctable errors. */
                    379:        if (mces & ALPHA_MCES_PCE)
                    380:                printf("Warning: received processor correctable error.\n");
                    381:
                    382:        /* Clear pending machine checks and correctable errors */
                    383:        alpha_pal_wrmces(mces);
                    384:        return;
                    385:
                    386: fatal:
                    387:        /* Clear pending machine checks and correctable errors */
                    388:        alpha_pal_wrmces(mces);
                    389:
                    390:        printf("\n");
                    391:        printf("%s:\n", type);
                    392:        printf("\n");
                    393:        printf("    mces    = 0x%lx\n", mces);
                    394:        printf("    vector  = 0x%lx\n", vector);
                    395:        printf("    param   = 0x%lx\n", param);
                    396:        printf("    pc      = 0x%lx\n", framep->tf_regs[FRAME_PC]);
                    397:        printf("    ra      = 0x%lx\n", framep->tf_regs[FRAME_RA]);
                    398:        printf("    curproc = %p\n", curproc);
                    399:        if (curproc != NULL)
                    400:                printf("        pid = %d, comm = %s\n", curproc->p_pid,
                    401:                    curproc->p_comm);
                    402:        printf("\n");
                    403:        panic("machine check");
                    404: }
                    405:
                    406: #if NAPECS > 0 || NCIA > 0 || NLCA > 0 || NTCASIC > 0
                    407:
                    408: int
                    409: badaddr(void *addr, size_t size)
                    410: {
                    411:        return(badaddr_read(addr, size, NULL));
                    412: }
                    413:
                    414: int
                    415: badaddr_read(void *addr, size_t size, void *rptr)
                    416: {
                    417:        struct mchkinfo *mcp = &curcpu()->ci_mcinfo;
                    418:        long rcpt;
                    419:        int rv;
                    420:
                    421:        /* Get rid of any stale machine checks that have been waiting.  */
                    422:        alpha_pal_draina();
                    423:
                    424:        /* Tell the trap code to expect a machine check. */
                    425:        mcp->mc_received = 0;
                    426:        mcp->mc_expected = 1;
                    427:
                    428:        /* Read from the test address, and make sure the read happens. */
                    429:        alpha_mb();
                    430:        switch (size) {
                    431:        case sizeof (u_int8_t):
                    432:                rcpt = *(volatile u_int8_t *)addr;
                    433:                break;
                    434:
                    435:        case sizeof (u_int16_t):
                    436:                rcpt = *(volatile u_int16_t *)addr;
                    437:                break;
                    438:
                    439:        case sizeof (u_int32_t):
                    440:                rcpt = *(volatile u_int32_t *)addr;
                    441:                break;
                    442:
                    443:        case sizeof (u_int64_t):
                    444:                rcpt = *(volatile u_int64_t *)addr;
                    445:                break;
                    446:
                    447:        default:
                    448:                panic("badaddr: invalid size (%ld)", size);
                    449:        }
                    450:        alpha_mb();
                    451:        alpha_mb();     /* MAGIC ON SOME SYSTEMS */
                    452:
                    453:        /* Make sure we took the machine check, if we caused one. */
                    454:        alpha_pal_draina();
                    455:
                    456:        /* disallow further machine checks */
                    457:        mcp->mc_expected = 0;
                    458:
                    459:        rv = mcp->mc_received;
                    460:        mcp->mc_received = 0;
                    461:
                    462:        /*
                    463:         * And copy back read results (if no fault occurred).
                    464:         */
                    465:        if (rptr && rv == 0) {
                    466:                switch (size) {
                    467:                case sizeof (u_int8_t):
                    468:                        *(volatile u_int8_t *)rptr = rcpt;
                    469:                        break;
                    470:
                    471:                case sizeof (u_int16_t):
                    472:                        *(volatile u_int16_t *)rptr = rcpt;
                    473:                        break;
                    474:
                    475:                case sizeof (u_int32_t):
                    476:                        *(volatile u_int32_t *)rptr = rcpt;
                    477:                        break;
                    478:
                    479:                case sizeof (u_int64_t):
                    480:                        *(volatile u_int64_t *)rptr = rcpt;
                    481:                        break;
                    482:                }
                    483:        }
                    484:        /* Return non-zero (i.e. true) if it's a bad address. */
                    485:        return (rv);
                    486: }
                    487:
                    488: #endif /* NAPECS > 0 || NCIA > 0 || NLCA > 0 || NTCASIC > 0 */
                    489:
                    490: int netisr;
                    491:
                    492: void
                    493: netintr()
                    494: {
                    495:        int n;
                    496:
                    497:        while ((n = netisr) != 0) {
                    498:                atomic_clearbits_int(&netisr, n);
                    499:
                    500: #define        DONETISR(bit, fn)                                               \
                    501:                do {                                                    \
                    502:                        if (n & (1 << (bit)))                           \
                    503:                                fn();                                   \
                    504:                } while (0)
                    505:
                    506: #include <net/netisr_dispatch.h>
                    507:
                    508: #undef DONETISR
                    509:        }
                    510: }
                    511:
                    512: struct alpha_soft_intr alpha_soft_intrs[SI_NSOFT];
                    513:
                    514: /* XXX For legacy software interrupts. */
                    515: struct alpha_soft_intrhand *softnet_intrhand, *softclock_intrhand;
                    516:
                    517: /*
                    518:  * softintr_init:
                    519:  *
                    520:  *     Initialize the software interrupt system.
                    521:  */
                    522: void
                    523: softintr_init()
                    524: {
                    525:        struct alpha_soft_intr *asi;
                    526:        int i;
                    527:
                    528:        for (i = 0; i < SI_NSOFT; i++) {
                    529:                asi = &alpha_soft_intrs[i];
                    530:                TAILQ_INIT(&asi->softintr_q);
                    531:                simple_lock_init(&asi->softintr_slock);
                    532:                asi->softintr_siq = i;
                    533:        }
                    534:
                    535:        /* XXX Establish legacy software interrupt handlers. */
                    536:        softnet_intrhand = softintr_establish(IPL_SOFTNET,
                    537:            (void (*)(void *))netintr, NULL);
                    538:        softclock_intrhand = softintr_establish(IPL_SOFTCLOCK,
                    539:            (void (*)(void *))softclock, NULL);
                    540: }
                    541:
                    542: /*
                    543:  * softintr_dispatch:
                    544:  *
                    545:  *     Process pending software interrupts.
                    546:  */
                    547: void
                    548: softintr_dispatch()
                    549: {
                    550:        struct alpha_soft_intr *asi;
                    551:        struct alpha_soft_intrhand *sih;
                    552:        u_int64_t n, i;
                    553:
                    554:        while ((n = atomic_loadlatch_ulong(&ssir, 0)) != 0) {
                    555:                for (i = 0; i < SI_NSOFT; i++) {
                    556:                        if ((n & (1 << i)) == 0)
                    557:                                continue;
                    558:
                    559:                        asi = &alpha_soft_intrs[i];
                    560:
                    561:                        for (;;) {
                    562:                                (void) alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH);
                    563:                                simple_lock(&asi->softintr_slock);
                    564:
                    565:                                sih = TAILQ_FIRST(&asi->softintr_q);
                    566:                                if (sih != NULL) {
                    567:                                        TAILQ_REMOVE(&asi->softintr_q, sih,
                    568:                                            sih_q);
                    569:                                        sih->sih_pending = 0;
                    570:                                }
                    571:
                    572:                                simple_unlock(&asi->softintr_slock);
                    573:                                (void) alpha_pal_swpipl(ALPHA_PSL_IPL_SOFT);
                    574:
                    575:                                if (sih == NULL)
                    576:                                        break;
                    577:
                    578:                                uvmexp.softs++;
                    579:                                (*sih->sih_fn)(sih->sih_arg);
                    580:                        }
                    581:                }
                    582:        }
                    583: }
                    584:
                    585: static int
                    586: ipl2si(int ipl)
                    587: {
                    588:        int si;
                    589:
                    590:        switch (ipl) {
                    591:        case IPL_TTY:                   /* XXX */
                    592:        case IPL_SOFTSERIAL:
                    593:                si = SI_SOFTSERIAL;
                    594:                break;
                    595:        case IPL_SOFTNET:
                    596:                si = SI_SOFTNET;
                    597:                break;
                    598:        case IPL_SOFTCLOCK:
                    599:                si = SI_SOFTCLOCK;
                    600:                break;
                    601:        case IPL_SOFT:
                    602:                si = SI_SOFT;
                    603:                break;
                    604:        default:
                    605:                panic("ipl2si: %d", ipl);
                    606:        }
                    607:        return si;
                    608: }
                    609:
                    610: /*
                    611:  * softintr_establish:         [interface]
                    612:  *
                    613:  *     Register a software interrupt handler.
                    614:  */
                    615: void *
                    616: softintr_establish(int ipl, void (*func)(void *), void *arg)
                    617: {
                    618:        struct alpha_soft_intr *asi;
                    619:        struct alpha_soft_intrhand *sih;
                    620:        int si;
                    621:
                    622:        si = ipl2si(ipl);
                    623:        asi = &alpha_soft_intrs[si];
                    624:
                    625:        sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT);
                    626:        if (__predict_true(sih != NULL)) {
                    627:                sih->sih_intrhead = asi;
                    628:                sih->sih_fn = func;
                    629:                sih->sih_arg = arg;
                    630:                sih->sih_pending = 0;
                    631:        }
                    632:        return (sih);
                    633: }
                    634:
                    635: /*
                    636:  * softintr_disestablish:      [interface]
                    637:  *
                    638:  *     Unregister a software interrupt handler.
                    639:  */
                    640: void
                    641: softintr_disestablish(void *arg)
                    642: {
                    643:        struct alpha_soft_intrhand *sih = arg;
                    644:        struct alpha_soft_intr *asi = sih->sih_intrhead;
                    645:        int s;
                    646:
                    647:        s = splhigh();
                    648:        simple_lock(&asi->softintr_slock);
                    649:        if (sih->sih_pending) {
                    650:                TAILQ_REMOVE(&asi->softintr_q, sih, sih_q);
                    651:                sih->sih_pending = 0;
                    652:        }
                    653:        simple_unlock(&asi->softintr_slock);
                    654:        splx(s);
                    655:
                    656:        free(sih, M_DEVBUF);
                    657: }
                    658:
                    659: int
                    660: _splraise(int s)
                    661: {
                    662:        int cur = alpha_pal_rdps() & ALPHA_PSL_IPL_MASK;
                    663:        return (s > cur ? alpha_pal_swpipl(s) : cur);
                    664: }
                    665:
                    666: #ifdef DIAGNOSTIC
                    667: void
                    668: splassert_check(int wantipl, const char *func)
                    669: {
                    670:        int curipl = alpha_pal_rdps() & ALPHA_PSL_IPL_MASK;
                    671:
                    672:        /*
                    673:         * Tell soft interrupts apart from regular levels.
                    674:         */
                    675:        if (wantipl < 0)
                    676:                wantipl = IPL_SOFTINT;
                    677:
                    678:        /*
                    679:         * Depending on the system, hardware interrupts may occur either
                    680:         * at level 3 or level 4. Avoid false positives in the former case.
                    681:         */
                    682:        if (curipl == ALPHA_PSL_IPL_IO - 1)
                    683:                curipl = ALPHA_PSL_IPL_IO;
                    684:
                    685:        if (curipl < wantipl) {
                    686:                splassert_fail(wantipl, curipl, func);
                    687:                /*
                    688:                 * If splassert_ctl is set to not panic, raise the ipl
                    689:                 * in a feeble attempt to reduce damage.
                    690:                 */
                    691:                alpha_pal_swpipl(wantipl);
                    692:        }
                    693: }
                    694: #endif

CVSweb