[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

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