[BACK]Return to macintr.c CVS log [TXT][DIR] Up to [local] / sys / arch / macppc / dev

Annotation of sys/arch/macppc/dev/macintr.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: macintr.c,v 1.33 2007/05/29 18:10:42 miod Exp $       */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 1995 Per Fogelstrom
        !             5:  * Copyright (c) 1993, 1994 Charles M. Hannum.
        !             6:  * Copyright (c) 1990 The Regents of the University of California.
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * This code is derived from software contributed to Berkeley by
        !            10:  * William Jolitz and Don Ahn.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  *     @(#)isa.c       7.2 (Berkeley) 5/12/91
        !            37:  */
        !            38:
        !            39: #include <sys/param.h>
        !            40: #include <sys/device.h>
        !            41: #include <sys/ioctl.h>
        !            42: #include <sys/mbuf.h>
        !            43: #include <sys/socket.h>
        !            44: #include <sys/systm.h>
        !            45:
        !            46: #include <uvm/uvm.h>
        !            47: #include <ddb/db_var.h>
        !            48:
        !            49: #include <machine/atomic.h>
        !            50: #include <machine/autoconf.h>
        !            51: #include <machine/intr.h>
        !            52: #include <machine/psl.h>
        !            53: #include <machine/pio.h>
        !            54: #include <machine/powerpc.h>
        !            55:
        !            56: #include <dev/ofw/openfirm.h>
        !            57:
        !            58: #define ICU_LEN 64
        !            59: #define LEGAL_IRQ(x) ((x >= 0) && (x < ICU_LEN))
        !            60:
        !            61: int m_intrtype[ICU_LEN], m_intrmask[ICU_LEN], m_intrlevel[ICU_LEN];
        !            62: struct intrhand *m_intrhand[ICU_LEN];
        !            63: int m_hwirq[ICU_LEN], m_virq[64];
        !            64: unsigned int imen_m = 0xffffffff;
        !            65: int m_virq_max = 0;
        !            66:
        !            67: static int fakeintr(void *);
        !            68: static char *intr_typename(int type);
        !            69: static void intr_calculatemasks(void);
        !            70: static void enable_irq(int x);
        !            71: static __inline int cntlzw(int x);
        !            72: static int mapirq(int irq);
        !            73: static int read_irq(void);
        !            74: static void mac_intr_do_pending_int(void);
        !            75:
        !            76: extern u_int32_t *heathrow_FCR;
        !            77:
        !            78: #define HWIRQ_MAX 27
        !            79: #define HWIRQ_MASK 0x0fffffff
        !            80:
        !            81: #define INT_STATE_REG0  (interrupt_reg + 0x20)
        !            82: #define INT_ENABLE_REG0 (interrupt_reg + 0x24)
        !            83: #define INT_CLEAR_REG0  (interrupt_reg + 0x28)
        !            84: #define INT_LEVEL_REG0  (interrupt_reg + 0x2c)
        !            85: #define INT_STATE_REG1  (INT_STATE_REG0  - 0x10)
        !            86: #define INT_ENABLE_REG1 (INT_ENABLE_REG0 - 0x10)
        !            87: #define INT_CLEAR_REG1  (INT_CLEAR_REG0  - 0x10)
        !            88: #define INT_LEVEL_REG1  (INT_LEVEL_REG0  - 0x10)
        !            89:
        !            90: struct macintr_softc {
        !            91:        struct device sc_dev;
        !            92: };
        !            93:
        !            94: int    macintr_match(struct device *parent, void *cf, void *aux);
        !            95: void   macintr_attach(struct device *, struct device *, void *);
        !            96: void   mac_do_pending_int(void);
        !            97: void   mac_ext_intr(void);
        !            98:
        !            99: struct cfattach macintr_ca = {
        !           100:        sizeof(struct macintr_softc),
        !           101:        macintr_match,
        !           102:        macintr_attach
        !           103: };
        !           104:
        !           105: struct cfdriver macintr_cd = {
        !           106:        NULL, "macintr", DV_DULL
        !           107: };
        !           108:
        !           109: int
        !           110: macintr_match(struct device *parent, void *cf, void *aux)
        !           111: {
        !           112:        struct confargs *ca = aux;
        !           113:        char type[40];
        !           114:
        !           115:        /*
        !           116:         * Match entry according to "present" openfirmware entry.
        !           117:         */
        !           118:        if (strcmp(ca->ca_name, "interrupt-controller") == 0 ) {
        !           119:                OF_getprop(ca->ca_node, "device_type", type, sizeof(type));
        !           120:                if (strcmp(type,  "interrupt-controller") == 0)
        !           121:                        return 1;
        !           122:        }
        !           123:
        !           124:        /*
        !           125:         * Check name for legacy interrupt controller, this is
        !           126:         * faked to allow old firmware which does not have an entry
        !           127:         * to attach to this device.
        !           128:         */
        !           129:        if (strcmp(ca->ca_name, "legacy-interrupt-controller") == 0 )
        !           130:                return 1;
        !           131:        return 0;
        !           132: }
        !           133:
        !           134: u_int8_t *interrupt_reg;
        !           135: typedef void  (void_f) (void);
        !           136: extern void_f *pending_int_f;
        !           137: int macintr_prog_button (void *arg);
        !           138:
        !           139: intr_establish_t macintr_establish;
        !           140: intr_disestablish_t macintr_disestablish;
        !           141: extern intr_establish_t *mac_intr_establish_func;
        !           142: extern intr_disestablish_t *mac_intr_disestablish_func;
        !           143: void macintr_collect_preconf_intr(void);
        !           144:
        !           145: void
        !           146: macintr_attach(struct device *parent, struct device *self, void *aux)
        !           147: {
        !           148:        struct confargs *ca = aux;
        !           149:        extern intr_establish_t *intr_establish_func;
        !           150:        extern intr_disestablish_t *intr_disestablish_func;
        !           151:
        !           152:        interrupt_reg = (void *)mapiodev(ca->ca_baseaddr,0x100); /* XXX */
        !           153:
        !           154:        install_extint(mac_ext_intr);
        !           155:        pending_int_f = mac_intr_do_pending_int;
        !           156:        intr_establish_func  = macintr_establish;
        !           157:        intr_disestablish_func  = macintr_disestablish;
        !           158:        mac_intr_establish_func  = macintr_establish;
        !           159:        mac_intr_disestablish_func  = macintr_disestablish;
        !           160:
        !           161:        macintr_collect_preconf_intr();
        !           162:
        !           163:        mac_intr_establish(parent, 0x14, IST_LEVEL, IPL_HIGH,
        !           164:            macintr_prog_button, (void *)0x14, "progbutton");
        !           165:
        !           166:        ppc_intr_enable(1);
        !           167:
        !           168:        printf("\n");
        !           169: }
        !           170:
        !           171: void
        !           172: macintr_collect_preconf_intr()
        !           173: {
        !           174:        int i;
        !           175:        for (i = 0; i < ppc_configed_intr_cnt; i++) {
        !           176: #ifdef DEBUG
        !           177:                printf("\n\t%s irq %d level %d fun %p arg %p",
        !           178:                        ppc_configed_intr[i].ih_what,
        !           179:                        ppc_configed_intr[i].ih_irq,
        !           180:                        ppc_configed_intr[i].ih_level,
        !           181:                        ppc_configed_intr[i].ih_fun,
        !           182:                        ppc_configed_intr[i].ih_arg
        !           183:                        );
        !           184: #endif
        !           185:                macintr_establish(NULL,
        !           186:                        ppc_configed_intr[i].ih_irq,
        !           187:                        IST_LEVEL,
        !           188:                        ppc_configed_intr[i].ih_level,
        !           189:                        ppc_configed_intr[i].ih_fun,
        !           190:                        ppc_configed_intr[i].ih_arg,
        !           191:                        ppc_configed_intr[i].ih_what);
        !           192:        }
        !           193: }
        !           194:
        !           195:
        !           196: /*
        !           197:  * programmer_button function to fix args to Debugger.
        !           198:  * deal with any enables/disables, if necessary.
        !           199:  */
        !           200: int
        !           201: macintr_prog_button (void *arg)
        !           202: {
        !           203: #ifdef DDB
        !           204:        if (db_console)
        !           205:                Debugger();
        !           206: #else
        !           207:        printf("programmer button pressed, debugger not available\n");
        !           208: #endif
        !           209:        return 1;
        !           210: }
        !           211:
        !           212: static int
        !           213: fakeintr(void *arg)
        !           214: {
        !           215:
        !           216:        return 0;
        !           217: }
        !           218:
        !           219: /*
        !           220:  * Register an interrupt handler.
        !           221:  */
        !           222: void *
        !           223: macintr_establish(void * lcv, int irq, int type, int level,
        !           224:     int (*ih_fun)(void *), void *ih_arg, char *name)
        !           225: {
        !           226:        struct intrhand **p, *q, *ih;
        !           227:        static struct intrhand fakehand;
        !           228:
        !           229:        fakehand.ih_next = NULL;
        !           230:        fakehand.ih_fun  = fakeintr;
        !           231:
        !           232: #if 0
        !           233: printf("macintr_establish, hI %d L %d ", irq, type);
        !           234: printf("addr reg0 %x\n", INT_STATE_REG0);
        !           235: #endif
        !           236:        irq = mapirq(irq);
        !           237: #if 0
        !           238: printf("vI %d ", irq);
        !           239: #endif
        !           240:
        !           241:        /* no point in sleeping unless someone can free memory. */
        !           242:        ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
        !           243:        if (ih == NULL)
        !           244:                panic("intr_establish: can't malloc handler info");
        !           245:
        !           246:        if (!LEGAL_IRQ(irq) || type == IST_NONE)
        !           247:                panic("intr_establish: bogus irq or type");
        !           248:
        !           249:        switch (m_intrtype[irq]) {
        !           250:        case IST_NONE:
        !           251:                m_intrtype[irq] = type;
        !           252:                break;
        !           253:        case IST_EDGE:
        !           254:        case IST_LEVEL:
        !           255:                if (type == m_intrtype[irq])
        !           256:                        break;
        !           257:        case IST_PULSE:
        !           258:                if (type != IST_NONE)
        !           259:                        panic("intr_establish: can't share %s with %s",
        !           260:                            intr_typename(m_intrtype[irq]),
        !           261:                            intr_typename(type));
        !           262:                break;
        !           263:        }
        !           264:
        !           265:        /*
        !           266:         * Figure out where to put the handler.
        !           267:         * This is O(N^2), but we want to preserve the order, and N is
        !           268:         * generally small.
        !           269:         */
        !           270:        for (p = &m_intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
        !           271:                ;
        !           272:
        !           273:        /*
        !           274:         * Actually install a fake handler momentarily, since we might be doing
        !           275:         * this with interrupts enabled and DON'T WANt the real routine called
        !           276:         * until masking is set up.
        !           277:         */
        !           278:        fakehand.ih_level = level;
        !           279:        *p = &fakehand;
        !           280:
        !           281:        intr_calculatemasks();
        !           282:
        !           283:        /*
        !           284:         * Poke the real handler in now.
        !           285:         */
        !           286:        ih->ih_fun = ih_fun;
        !           287:        ih->ih_arg = ih_arg;
        !           288:        ih->ih_next = NULL;
        !           289:        ih->ih_level = level;
        !           290:        ih->ih_irq = irq;
        !           291:        evcount_attach(&ih->ih_count, name, (void *)&m_hwirq[irq],
        !           292:            &evcount_intr);
        !           293:        *p = ih;
        !           294:
        !           295:        return (ih);
        !           296: }
        !           297:
        !           298: /*
        !           299:  * Deregister an interrupt handler.
        !           300:  */
        !           301: void
        !           302: macintr_disestablish(void *lcp, void *arg)
        !           303: {
        !           304:        struct intrhand *ih = arg;
        !           305:        int irq = ih->ih_irq;
        !           306:        struct intrhand **p, *q;
        !           307:
        !           308:        if (!LEGAL_IRQ(irq))
        !           309:                panic("intr_disestablish: bogus irq");
        !           310:
        !           311:        /*
        !           312:         * Remove the handler from the chain.
        !           313:         * This is O(n^2), too.
        !           314:         */
        !           315:        for (p = &m_intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next)
        !           316:                ;
        !           317:        if (q)
        !           318:                *p = q->ih_next;
        !           319:        else
        !           320:                panic("intr_disestablish: handler not registered");
        !           321:
        !           322:        evcount_detach(&ih->ih_count);
        !           323:        free((void *)ih, M_DEVBUF);
        !           324:
        !           325:        intr_calculatemasks();
        !           326:
        !           327:        if (m_intrhand[irq] == NULL)
        !           328:                m_intrtype[irq] = IST_NONE;
        !           329: }
        !           330:
        !           331:
        !           332: static char *
        !           333: intr_typename(int type)
        !           334: {
        !           335:        switch (type) {
        !           336:         case IST_NONE :
        !           337:                return ("none");
        !           338:         case IST_PULSE:
        !           339:                return ("pulsed");
        !           340:         case IST_EDGE:
        !           341:                return ("edge-triggered");
        !           342:         case IST_LEVEL:
        !           343:                return ("level-triggered");
        !           344:        default:
        !           345:                panic("intr_typename: invalid type %d", type);
        !           346: #if 1 /* XXX */
        !           347:                return ("unknown");
        !           348: #endif
        !           349:        }
        !           350: }
        !           351: /*
        !           352:  * Recalculate the interrupt masks from scratch.
        !           353:  * We could code special registry and deregistry versions of this function that
        !           354:  * would be faster, but the code would be nastier, and we don't expect this to
        !           355:  * happen very much anyway.
        !           356:  */
        !           357: static void
        !           358: intr_calculatemasks()
        !           359: {
        !           360:        int irq, level;
        !           361:        struct intrhand *q;
        !           362:
        !           363:        /* First, figure out which levels each IRQ uses. */
        !           364:        for (irq = 0; irq < ICU_LEN; irq++) {
        !           365:                register int levels = 0;
        !           366:                for (q = m_intrhand[irq]; q; q = q->ih_next)
        !           367:                        levels |= 1 << q->ih_level;
        !           368:                m_intrlevel[irq] = levels;
        !           369:        }
        !           370:
        !           371:        /* Then figure out which IRQs use each level. */
        !           372:        for (level = IPL_NONE; level < IPL_NUM; level++) {
        !           373:                register int irqs = 0;
        !           374:                for (irq = 0; irq < ICU_LEN; irq++)
        !           375:                        if (m_intrlevel[irq] & (1 << level))
        !           376:                                irqs |= 1 << irq;
        !           377:                imask[level] = irqs | SINT_MASK;
        !           378:        }
        !           379:
        !           380:        /*
        !           381:         * There are tty, network and disk drivers that use free() at interrupt
        !           382:         * time, so vm > (tty | net | bio).
        !           383:         *
        !           384:         * Enforce a hierarchy that gives slow devices a better chance at not
        !           385:         * dropping data.
        !           386:         */
        !           387:        imask[IPL_NET] |= imask[IPL_BIO];
        !           388:        imask[IPL_TTY] |= imask[IPL_NET];
        !           389:        imask[IPL_VM] |= imask[IPL_TTY];
        !           390:        imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCK;
        !           391:
        !           392:        /*
        !           393:         * These are pseudo-levels.
        !           394:         */
        !           395:        imask[IPL_NONE] = 0x00000000;
        !           396:        imask[IPL_HIGH] = 0xffffffff;
        !           397:
        !           398:        /* And eventually calculate the complete masks. */
        !           399:        for (irq = 0; irq < ICU_LEN; irq++) {
        !           400:                register int irqs = 1 << irq;
        !           401:                for (q = m_intrhand[irq]; q; q = q->ih_next)
        !           402:                        irqs |= imask[q->ih_level];
        !           403:                m_intrmask[irq] = irqs | SINT_MASK;
        !           404:        }
        !           405:
        !           406:        /* Lastly, determine which IRQs are actually in use. */
        !           407:        {
        !           408:                register int irqs = 0;
        !           409:                for (irq = 0; irq < ICU_LEN; irq++) {
        !           410:                        if (m_intrhand[irq])
        !           411:                                irqs |= 1 << irq;
        !           412:                }
        !           413:                imen_m = ~irqs;
        !           414:                enable_irq(~imen_m);
        !           415:        }
        !           416: }
        !           417: static void
        !           418: enable_irq(int x)
        !           419: {
        !           420:        int state0, state1, v;
        !           421:        int irq;
        !           422:
        !           423:        x &= HWIRQ_MASK;        /* XXX Higher bits are software interrupts. */
        !           424:
        !           425:        state0 = state1 = 0;
        !           426:        while (x) {
        !           427:                v = 31 - cntlzw(x);
        !           428:                irq = m_hwirq[v];
        !           429:                if (irq < 32)
        !           430:                        state0 |= 1 << irq;
        !           431:                else
        !           432:                        state1 |= 1 << (irq - 32);
        !           433:
        !           434:                x &= ~(1 << v);
        !           435:        }
        !           436:
        !           437:        if (heathrow_FCR)
        !           438:                out32rb(INT_ENABLE_REG1, state1);
        !           439:
        !           440:        out32rb(INT_ENABLE_REG0, state0);
        !           441: }
        !           442:
        !           443: int m_virq_inited = 0;
        !           444:
        !           445: /*
        !           446:  * Map 64 irqs into 32 (bits).
        !           447:  */
        !           448: static int
        !           449: mapirq(int irq)
        !           450: {
        !           451:        int v;
        !           452:        int i;
        !           453:
        !           454:        if (m_virq_inited == 0) {
        !           455:                m_virq_max = 0;
        !           456:                for (i = 0; i < ICU_LEN; i++) {
        !           457:                        m_virq[i] = 0;
        !           458:                }
        !           459:                m_virq_inited = 1;
        !           460:        }
        !           461:
        !           462:        /* irq in table already? */
        !           463:        if (m_virq[irq] != 0)
        !           464:                return m_virq[irq];
        !           465:
        !           466:        if (irq < 0 || irq >= 64)
        !           467:                panic("invalid irq %d", irq);
        !           468:        m_virq_max++;
        !           469:        v = m_virq_max;
        !           470:        if (v > HWIRQ_MAX)
        !           471:                panic("virq overflow");
        !           472:
        !           473:        m_hwirq[v] = irq;
        !           474:        m_virq[irq] = v;
        !           475: #if 0
        !           476: printf("\nmapirq %x to %x\n", irq, v);
        !           477: #endif
        !           478:
        !           479:        return v;
        !           480: }
        !           481:
        !           482: /*
        !           483:  * Count leading zeros.
        !           484:  */
        !           485: static __inline int
        !           486: cntlzw(int x)
        !           487: {
        !           488:        int a;
        !           489:
        !           490:        __asm __volatile ("cntlzw %0,%1" : "=r"(a) : "r"(x));
        !           491:
        !           492:        return a;
        !           493: }
        !           494:
        !           495: /*
        !           496:  * external interrupt handler
        !           497:  */
        !           498: void
        !           499: mac_ext_intr()
        !           500: {
        !           501:        int irq = 0;
        !           502:        int o_imen, r_imen;
        !           503:        int pcpl;
        !           504:        struct cpu_info *ci = curcpu();
        !           505:        struct intrhand *ih;
        !           506:        volatile unsigned long int_state;
        !           507:
        !           508:        pcpl = ci->ci_cpl;      /* Turn off all */
        !           509:
        !           510:        int_state = read_irq();
        !           511:        if (int_state == 0)
        !           512:                goto out;
        !           513:
        !           514: start:
        !           515:        irq = 31 - cntlzw(int_state);
        !           516:
        !           517:        o_imen = imen_m;
        !           518:        r_imen = 1 << irq;
        !           519:
        !           520:        if ((ci->ci_cpl & r_imen) != 0) {
        !           521:                /* Masked! Mark this as pending. */
        !           522:                ci->ci_ipending |= r_imen;
        !           523:                imen_m |= r_imen;
        !           524:                enable_irq(~imen_m);
        !           525:        } else {
        !           526:                splraise(m_intrmask[irq]);
        !           527:
        !           528:                ih = m_intrhand[irq];
        !           529:                while (ih) {
        !           530:                        if ((*ih->ih_fun)(ih->ih_arg))
        !           531:                                ih->ih_count.ec_count++;
        !           532:                        ih = ih->ih_next;
        !           533:                }
        !           534:
        !           535:                uvmexp.intrs++;
        !           536:        }
        !           537:        int_state &= ~r_imen;
        !           538:        if (int_state)
        !           539:                goto start;
        !           540:
        !           541: out:
        !           542:        splx(pcpl);     /* Process pendings. */
        !           543: }
        !           544:
        !           545: void
        !           546: mac_intr_do_pending_int()
        !           547: {
        !           548:        struct cpu_info *ci = curcpu();
        !           549:        struct intrhand *ih;
        !           550:        int irq;
        !           551:        int pcpl;
        !           552:        int hwpend;
        !           553:        int s;
        !           554:
        !           555:        if (ci->ci_iactive)
        !           556:                return;
        !           557:
        !           558:        ci->ci_iactive = 1;
        !           559:        pcpl = splhigh();               /* Turn off all */
        !           560:        s = ppc_intr_disable();
        !           561:
        !           562:        hwpend = ci->ci_ipending & ~pcpl;       /* Do now unmasked pendings */
        !           563:        imen_m &= ~hwpend;
        !           564:        enable_irq(~imen_m);
        !           565:        hwpend &= HWIRQ_MASK;
        !           566:        while (hwpend) {
        !           567:                irq = 31 - cntlzw(hwpend);
        !           568:                hwpend &= ~(1L << irq);
        !           569:                ih = m_intrhand[irq];
        !           570:                while(ih) {
        !           571:                        if ((*ih->ih_fun)(ih->ih_arg))
        !           572:                                ih->ih_count.ec_count++;
        !           573:                        ih = ih->ih_next;
        !           574:                }
        !           575:        }
        !           576:
        !           577:        /*out32rb(INT_ENABLE_REG, ~imen_m);*/
        !           578:
        !           579:        do {
        !           580:                if((ci->ci_ipending & SINT_CLOCK) & ~pcpl) {
        !           581:                        ci->ci_ipending &= ~SINT_CLOCK;
        !           582:                        softclock();
        !           583:                }
        !           584:                if((ci->ci_ipending & SINT_NET) & ~pcpl) {
        !           585:                        extern int netisr;
        !           586:                        int pisr;
        !           587:
        !           588:                        ci->ci_ipending &= ~SINT_NET;
        !           589:                        while ((pisr = netisr) != 0) {
        !           590:                                atomic_clearbits_int(&netisr, pisr);
        !           591:                                softnet(pisr);
        !           592:                        }
        !           593:                }
        !           594:                if((ci->ci_ipending & SINT_TTY) & ~pcpl) {
        !           595:                        ci->ci_ipending &= ~SINT_TTY;
        !           596:                        softtty();
        !           597:                }
        !           598:        } while ((ci->ci_ipending & SINT_MASK) & ~pcpl);
        !           599:        ci->ci_ipending &= pcpl;
        !           600:        ci->ci_cpl = pcpl;      /* Don't use splx... we are here already! */
        !           601:        ppc_intr_enable(s);
        !           602:        ci->ci_iactive = 0;
        !           603: }
        !           604:
        !           605: static int
        !           606: read_irq()
        !           607: {
        !           608:        int rv = 0;
        !           609:        int state0, state1, p;
        !           610:        int state0save, state1save;
        !           611:
        !           612:        state0 = in32rb(INT_STATE_REG0);
        !           613:        if (state0)
        !           614:                out32rb(INT_CLEAR_REG0, state0);
        !           615:        state0save = state0;
        !           616:        while (state0) {
        !           617:                p = 31 - cntlzw(state0);
        !           618:                rv |= 1 << m_virq[p];
        !           619:                state0 &= ~(1 << p);
        !           620:        }
        !           621:
        !           622:        if (heathrow_FCR)                       /* has heathrow? */
        !           623:                state1 = in32rb(INT_STATE_REG1);
        !           624:        else
        !           625:                state1 = 0;
        !           626:
        !           627:        if (state1)
        !           628:                out32rb(INT_CLEAR_REG1, state1);
        !           629:        state1save = state1;
        !           630:        while (state1) {
        !           631:                p = 31 - cntlzw(state1);
        !           632:                rv |= 1 << m_virq[p + 32];
        !           633:                state1 &= ~(1 << p);
        !           634:        }
        !           635: #if 0
        !           636: printf("mac_intr int_stat 0:%x 1:%x\n", state0save, state1save);
        !           637: #endif
        !           638:
        !           639:        /* 1 << 0 is invalid. */
        !           640:        return rv & ~1;
        !           641: }

CVSweb