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

Annotation of sys/arch/hp300/hp300/intr.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: intr.c,v 1.17 2007/05/29 18:10:42 miod Exp $  */
        !             2: /*     $NetBSD: intr.c,v 1.5 1998/02/16 20:58:30 thorpej Exp $ */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Adam Glass, Gordon W. Ross, and 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:  * Link and dispatch interrupts.
        !            42:  */
        !            43:
        !            44: #include <sys/param.h>
        !            45: #include <sys/systm.h>
        !            46: #include <sys/malloc.h>
        !            47: #include <sys/vmmeter.h>
        !            48:
        !            49: #include <uvm/uvm_extern.h>
        !            50:
        !            51: #include <net/netisr.h>
        !            52: #include "ppp.h"
        !            53: #include "bridge.h"
        !            54:
        !            55: void   netintr(void);
        !            56:
        !            57: #include <machine/atomic.h>
        !            58: #include <machine/cpu.h>
        !            59: #include <machine/intr.h>
        !            60:
        !            61: /*
        !            62:  * The location and size of the autovectored interrupt portion
        !            63:  * of the vector table.
        !            64:  */
        !            65: #define ISRLOC         0x18
        !            66: #define NISR           8
        !            67:
        !            68: typedef LIST_HEAD(, isr) isr_list_t;
        !            69: isr_list_t isr_list[NISR];
        !            70:
        !            71: u_short        hp300_bioipl, hp300_netipl, hp300_ttyipl, hp300_vmipl;
        !            72:
        !            73: void   intr_computeipl(void);
        !            74:
        !            75: void
        !            76: intr_init()
        !            77: {
        !            78:        int i;
        !            79:
        !            80:        /* Initialize the ISR lists. */
        !            81:        for (i = 0; i < NISR; ++i)
        !            82:                LIST_INIT(&isr_list[i]);
        !            83:
        !            84:        /* Default interrupt priorities. */
        !            85:        hp300_bioipl = hp300_netipl = hp300_ttyipl = hp300_vmipl =
        !            86:            (PSL_S|PSL_IPL3);
        !            87: }
        !            88:
        !            89: /*
        !            90:  * Scan all of the ISRs, recomputing the interrupt levels for the spl*()
        !            91:  * calls.  This doesn't have to be fast.
        !            92:  */
        !            93: void
        !            94: intr_computeipl()
        !            95: {
        !            96:        struct isr *isr;
        !            97:        int ipl;
        !            98:
        !            99:        /* Start with low values. */
        !           100:        hp300_bioipl = hp300_netipl = hp300_ttyipl = hp300_vmipl =
        !           101:            (PSL_S|PSL_IPL3);
        !           102:
        !           103:        for (ipl = 0; ipl < NISR; ipl++) {
        !           104:                LIST_FOREACH(isr, &isr_list[ipl], isr_link) {
        !           105:                        /*
        !           106:                         * Bump up the level for a given priority,
        !           107:                         * if necessary.
        !           108:                         */
        !           109:                        switch (isr->isr_priority) {
        !           110:                        case IPL_BIO:
        !           111:                                if (ipl > PSLTOIPL(hp300_bioipl))
        !           112:                                        hp300_bioipl = IPLTOPSL(ipl);
        !           113:                                break;
        !           114:
        !           115:                        case IPL_NET:
        !           116:                                if (ipl > PSLTOIPL(hp300_netipl))
        !           117:                                        hp300_netipl = IPLTOPSL(ipl);
        !           118:                                break;
        !           119:
        !           120:                        case IPL_TTY:
        !           121:                        case IPL_TTYNOBUF:
        !           122:                                if (ipl > PSLTOIPL(hp300_ttyipl))
        !           123:                                        hp300_ttyipl = IPLTOPSL(ipl);
        !           124:                                break;
        !           125:
        !           126:                        default:
        !           127:                                printf("priority = %d\n", isr->isr_priority);
        !           128:                                panic("intr_computeipl: bad priority");
        !           129:                        }
        !           130:                }
        !           131:        }
        !           132:
        !           133:        /*
        !           134:         * Enforce `bio <= net <= tty <= vm'
        !           135:         */
        !           136:
        !           137:        if (hp300_netipl < hp300_bioipl)
        !           138:                hp300_netipl = hp300_bioipl;
        !           139:
        !           140:        if (hp300_ttyipl < hp300_netipl)
        !           141:                hp300_ttyipl = hp300_netipl;
        !           142:
        !           143:        if (hp300_vmipl < hp300_ttyipl)
        !           144:                hp300_vmipl = hp300_ttyipl;
        !           145: }
        !           146:
        !           147: void
        !           148: intr_printlevels()
        !           149: {
        !           150:
        !           151: #ifdef DEBUG
        !           152:        printf("psl: bio = 0x%x, net = 0x%x, tty = 0x%x, vm = 0x%x\n",
        !           153:            hp300_bioipl, hp300_netipl, hp300_ttyipl, hp300_vmipl);
        !           154: #endif
        !           155:
        !           156:        printf("interrupt levels: bio = %d, net = %d, tty = %d\n",
        !           157:            PSLTOIPL(hp300_bioipl), PSLTOIPL(hp300_netipl),
        !           158:            PSLTOIPL(hp300_ttyipl));
        !           159: }
        !           160:
        !           161: /*
        !           162:  * Establish an interrupt handler.
        !           163:  * Called by driver attach functions.
        !           164:  */
        !           165: void
        !           166: intr_establish(struct isr *isr, const char *name)
        !           167: {
        !           168:        struct isr *curisr;
        !           169:        isr_list_t *list;
        !           170:
        !           171: #ifdef DIAGNOSTIC
        !           172:        if (isr->isr_ipl < 0 || isr->isr_ipl >= NISR)
        !           173:                panic("intr_establish: bad ipl %d", isr->isr_ipl);
        !           174: #endif
        !           175:
        !           176:        evcount_attach(&isr->isr_count, name, &isr->isr_ipl,
        !           177:            &evcount_intr);
        !           178:
        !           179:        /*
        !           180:         * Some devices are particularly sensitive to interrupt
        !           181:         * handling latency.  The DCA, for example, can lose many
        !           182:         * characters if its interrupt isn't handled with reasonable
        !           183:         * speed.  For this reason, we sort ISRs by IPL_* priority,
        !           184:         * inserting higher priority interrupts before lower priority
        !           185:         * interrupts.
        !           186:         */
        !           187:
        !           188:        /*
        !           189:         * Get the appropriate ISR list.  If the list is empty, no
        !           190:         * additional work is necessary; we simply insert ourselves
        !           191:         * at the head of the list.
        !           192:         */
        !           193:        list = &isr_list[isr->isr_ipl];
        !           194:        if (LIST_EMPTY(list)) {
        !           195:                LIST_INSERT_HEAD(list, isr, isr_link);
        !           196:                goto compute;
        !           197:        }
        !           198:
        !           199:        /*
        !           200:         * A little extra work is required.  We traverse the list
        !           201:         * and place ourselves after any ISRs with our current (or
        !           202:         * higher) priority.
        !           203:         */
        !           204:        for (curisr = LIST_FIRST(list);
        !           205:            LIST_NEXT(curisr, isr_link) != LIST_END(list);
        !           206:            curisr = LIST_NEXT(curisr, isr_link)) {
        !           207:                if (isr->isr_priority > curisr->isr_priority) {
        !           208:                        LIST_INSERT_BEFORE(curisr, isr, isr_link);
        !           209:                        goto compute;
        !           210:                }
        !           211:        }
        !           212:
        !           213:        /*
        !           214:         * We're the least important entry, it seems.  We just go
        !           215:         * on the end.
        !           216:         */
        !           217:        LIST_INSERT_AFTER(curisr, isr, isr_link);
        !           218:
        !           219:  compute:
        !           220:        /* Compute new interrupt levels. */
        !           221:        intr_computeipl();
        !           222: }
        !           223:
        !           224: /*
        !           225:  * Disestablish an interrupt handler.
        !           226:  */
        !           227: void
        !           228: intr_disestablish(struct isr *isr)
        !           229: {
        !           230:        evcount_detach(&isr->isr_count);
        !           231:        LIST_REMOVE(isr, isr_link);
        !           232:        intr_computeipl();
        !           233: }
        !           234:
        !           235: /*
        !           236:  * This is the dispatcher called by the low-level
        !           237:  * assembly language interrupt routine.
        !           238:  */
        !           239: void
        !           240: intr_dispatch(evec)
        !           241:        int evec;               /* format | vector offset */
        !           242: {
        !           243:        struct isr *isr;
        !           244:        isr_list_t *list;
        !           245:        int handled, rc, ipl, vec;
        !           246:        static int straycount, unexpected;
        !           247:
        !           248:        vec = (evec & 0xfff) >> 2;
        !           249: #ifdef DIAGNOSTIC
        !           250:        if (vec < ISRLOC || vec >= (ISRLOC + NISR))
        !           251:                panic("isrdispatch: bad vec 0x%x", vec);
        !           252: #endif
        !           253:        ipl = vec - ISRLOC;
        !           254:
        !           255:        uvmexp.intrs++;
        !           256:
        !           257:        list = &isr_list[ipl];
        !           258:        if (LIST_EMPTY(list)) {
        !           259:                printf("intr_dispatch: ipl %d unexpected\n", ipl);
        !           260:                if (++unexpected > 10)
        !           261:                        panic("intr_dispatch: too many unexpected interrupts");
        !           262:                return;
        !           263:        }
        !           264:
        !           265:        handled = 0;
        !           266:        /* Give all the handlers a chance. */
        !           267:        LIST_FOREACH(isr, list, isr_link) {
        !           268:                rc = (*isr->isr_func)(isr->isr_arg);
        !           269:                if (rc > 0)
        !           270:                        isr->isr_count.ec_count++;
        !           271:                handled |= rc;
        !           272:        }
        !           273:
        !           274:        if (handled)
        !           275:                straycount = 0;
        !           276:        else if (++straycount > 50)
        !           277:                panic("intr_dispatch: too many stray interrupts");
        !           278:        else
        !           279:                printf("intr_dispatch: stray level %d interrupt\n", ipl);
        !           280: }
        !           281:
        !           282: int netisr;
        !           283:
        !           284: void
        !           285: netintr()
        !           286: {
        !           287:        int n;
        !           288:
        !           289:        while ((n = netisr) != 0) {
        !           290:                atomic_clearbits_int(&netisr, n);
        !           291:
        !           292: #define        DONETISR(bit, fn)                                               \
        !           293:                do {                                                    \
        !           294:                        if (n & (1 << (bit)))                           \
        !           295:                                (fn)();                                 \
        !           296:                } while (0)
        !           297:
        !           298: #include <net/netisr_dispatch.h>
        !           299:
        !           300: #undef DONETISR
        !           301:        }
        !           302: }

CVSweb