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

Annotation of sys/arch/mvmeppc/dev/openpic.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: openpic.c,v 1.22 2007/05/29 18:10:43 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_extern.h>
                     47:
                     48: #include <ddb/db_var.h>
                     49:
                     50: #include <machine/atomic.h>
                     51: #include <machine/autoconf.h>
                     52: #include <machine/intr.h>
                     53: #include <machine/psl.h>
                     54: #include <machine/pio.h>
                     55:
                     56: #include <mvmeppc/dev/openpicreg.h>
                     57: #include <mvmeppc/dev/ravenvar.h>
                     58: #include <mvmeppc/dev/ravenreg.h>
                     59:
                     60: #define ICU_LEN                32
                     61: #define LEGAL_IRQ(x)   ((x >= 0) && (x < ICU_LEN))
                     62: #define IO_ICU1                (isaspace_va + 0x20)
                     63: #define IO_ICU2                (isaspace_va + 0xa0)
                     64: #define IO_ELCR1       (isaspace_va + 0x4d0)
                     65: #define IO_ELCR2       (isaspace_va + 0x4d1)
                     66: #define IRQ_SLAVE      2
                     67: #define ICU_OFFSET     0
                     68: #define PIC_OFFSET     16
                     69:
                     70: #define        PIC_SPURIOUS    0xff
                     71:
                     72: unsigned char icu1_val = 0xff;
                     73: unsigned char icu2_val = 0xff;
                     74: unsigned char elcr1_val = 0x00;
                     75: unsigned char elcr2_val = 0x00;
                     76:
                     77: int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
                     78: struct intrhand *intrhand[ICU_LEN];
                     79: int hwirq[ICU_LEN], virq[ICU_LEN];
                     80: unsigned int imen = 0xffffffff;
                     81: int virq_max;
                     82:
                     83: int fakeintr(void *);
                     84: const char *intr_typename(int type);
                     85: void intr_calculatemasks(void);
                     86: static __inline int cntlzw(int x);
                     87: int mapirq(int irq);
                     88: void openpic_enable_irq_mask(int irq_mask);
                     89:
                     90: #define HWIRQ_MAX 27
                     91: #define HWIRQ_MASK 0x0fffffff
                     92:
                     93: static __inline u_int openpic_read(int);
                     94: static __inline void openpic_write(int, u_int);
                     95: void openpic_enable_irq(int, int);
                     96: void openpic_disable_irq(int);
                     97: void openpic_init(void);
                     98: void openpic_set_priority(int, int);
                     99: static __inline int openpic_iack(int);
                    100: static __inline void openpic_eoi(int);
                    101: void openpic_initirq(int, int, int);
                    102:
                    103: void i8259_init(void);
                    104: int i8259_intr(void);
                    105: void i8259_enable_irq(int, int);
                    106: void i8259_disable_irq(int);
                    107: void i8259_eoi(int);
                    108: void *i8259_intr_establish(void *, int, int, int, int (*)(void *), void *,
                    109:     char *);
                    110: void i8259_set_irq_mask(void);
                    111:
                    112: struct openpic_softc {
                    113:        struct device sc_dev;
                    114: };
                    115:
                    116: int openpic_match(struct device *parent, void *cf, void *aux);
                    117: void openpic_attach(struct device *, struct device *, void *);
                    118: void openpic_do_pending_int(void);
                    119: void ext_intr_openpic(void);
                    120:
                    121: struct cfattach openpic_ca = {
                    122:        sizeof(struct openpic_softc), openpic_match, openpic_attach
                    123: };
                    124:
                    125: struct cfdriver openpic_cd = {
                    126:        NULL, "openpic", DV_DULL
                    127: };
                    128:
                    129: /*
                    130:  * ISA IRQ for PCI IRQ to MPIC IRQ routing.
                    131:  * From MVME2600APG tables 5.2 and 5.3
                    132:  */
                    133: const struct pci_route {
                    134:        int pci;
                    135:        int openpic;
                    136: } pci_routes[] = {
                    137:        { 10, 2 },
                    138:        { 11, 5 },
                    139:        { 14, 3 },
                    140:        { 15, 4 },
                    141:        { 0, 0 }
                    142: };
                    143:
                    144: int
                    145: openpic_match(parent, cf, aux)
                    146:        struct device *parent;
                    147:        void *cf;
                    148:        void *aux;
                    149: {
                    150:        /* We must be a child of the raven device */
                    151:        if (strcmp(parent->dv_cfdata->cf_driver->cd_name, "raven") != 0)
                    152:                return (0);
                    153:        /* If there is a raven, then there is a mpic! */
                    154:        return 1;
                    155: }
                    156:
                    157: u_int8_t *interrupt_reg;
                    158: typedef void (void_f) (void);
                    159: extern void_f *pending_int_f;
                    160: int abort_switch (void *arg);
                    161: int i8259_dummy(void *arg);
                    162:
                    163: typedef int mac_intr_handle_t;
                    164:
                    165: typedef void *(intr_establish_t)(void *, int, int, int, int (*)(void *),
                    166:     void *, char *);
                    167: typedef void (intr_disestablish_t)(void *, void *);
                    168:
                    169: vaddr_t openpic_base;
                    170: extern vaddr_t isaspace_va;
                    171:
                    172: void * openpic_intr_establish(void *, int, int, int, int (*)(void *), void *,
                    173:     char *);
                    174: void openpic_intr_disestablish(void *, void *);
                    175: void openpic_collect_preconf_intr(void);
                    176:
                    177: void
                    178: openpic_attach(parent, self, aux)
                    179:        struct device *parent, *self;
                    180:        void *aux;
                    181: {
                    182:        extern intr_establish_t *intr_establish_func;
                    183:        extern intr_disestablish_t *intr_disestablish_func;
                    184:
                    185:        if ((openpic_base = (vaddr_t)mapiodev(MPCIC_BASE, MPCIC_SIZE)) == NULL) {
                    186:                printf(": can't map MPCIC!\n");
                    187:                return;
                    188:        }
                    189:
                    190:        /* the ICU area in isa space already mapped */
                    191:
                    192:        printf(": version 0x%x", openpic_read(OPENPIC_FEATURE) & 0xFF);
                    193:
                    194:        i8259_init();
                    195:        openpic_init();
                    196:
                    197:        pending_int_f = openpic_do_pending_int;
                    198:        intr_establish_func = i8259_intr_establish;
                    199:        intr_disestablish_func = openpic_intr_disestablish;
                    200:
                    201:        openpic_collect_preconf_intr();
                    202:
                    203:        /*
                    204:         * i8259 interrupts are chained to openpic interrupt #0
                    205:         */
                    206:        openpic_intr_establish(parent, 0x00, IST_LEVEL, IPL_HIGH,
                    207:            i8259_dummy, NULL, "8259 Interrupt");
                    208:
                    209:        i8259_intr_establish(parent, 0x08, IST_EDGE, IPL_HIGH,
                    210:            abort_switch, NULL, "abort button");
                    211:
                    212:        printf("\n");
                    213: }
                    214:
                    215: void
                    216: openpic_collect_preconf_intr()
                    217: {
                    218:        int i;
                    219:
                    220:        for (i = 0; i < ppc_configed_intr_cnt; i++) {
                    221: #ifdef DEBUG
                    222:                printf("\n\t%s irq %d level %d fun %x arg %x",
                    223:                    ppc_configed_intr[i].ih_what, ppc_configed_intr[i].ih_irq,
                    224:                    ppc_configed_intr[i].ih_level, ppc_configed_intr[i].ih_fun,
                    225:                    ppc_configed_intr[i].ih_arg);
                    226: #endif
                    227:                openpic_intr_establish(NULL, ppc_configed_intr[i].ih_irq,
                    228:                    IST_LEVEL, ppc_configed_intr[i].ih_level,
                    229:                    ppc_configed_intr[i].ih_fun, ppc_configed_intr[i].ih_arg,
                    230:                    ppc_configed_intr[i].ih_what);
                    231:        }
                    232: }
                    233:
                    234: int
                    235: abort_switch(void *arg)
                    236: {
                    237: #ifdef DDB
                    238:        if (db_console)
                    239:                Debugger();
                    240: #else
                    241:        printf("Abort button pressed, debugger not available.\n");
                    242: #endif
                    243:        return 1;
                    244: }
                    245:
                    246: int
                    247: i8259_dummy(void *arg)
                    248: {
                    249:        /* All the 8259 handling happens in ext_intr_openpic(), actually. */
                    250:        return 1;
                    251: }
                    252:
                    253: int
                    254: fakeintr(arg)
                    255:        void *arg;
                    256: {
                    257:        return 0;
                    258: }
                    259:
                    260: /*
                    261:  * Register an ISA interrupt handler.
                    262:  */
                    263: void *
                    264: i8259_intr_establish(lcv, irq, type, level, ih_fun, ih_arg, what)
                    265:        void * lcv;
                    266:        int irq;
                    267:        int type;
                    268:        int level;
                    269:        int (*ih_fun)(void *);
                    270:        void *ih_arg;
                    271:        char *what;
                    272: {
                    273:        struct intrhand **p, *q, *ih;
                    274:        static struct intrhand fakehand;
                    275:
                    276:        fakehand.ih_next = NULL;
                    277:        fakehand.ih_fun = fakeintr;
                    278:
                    279: #if 0
                    280:        printf("i8259_intr_establish, %d, %s", irq, (type == IST_EDGE) ? "EDGE":"LEVEL"));
                    281: #endif
                    282:        irq = mapirq(irq + ICU_OFFSET);
                    283:
                    284:        /* no point in sleeping unless someone can free memory. */
                    285:        ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
                    286:        if (ih == NULL)
                    287:                panic("i8259_intr_establish: can't malloc handler info");
                    288:
                    289:        if (!LEGAL_IRQ(irq) || type == IST_NONE)
                    290:                panic("i8259_intr_establish: bogus irq or type");
                    291:
                    292:        switch (intrtype[irq]) {
                    293:        case IST_EDGE:
                    294:        case IST_LEVEL:
                    295:                if (type == intrtype[irq])
                    296:                        break;
                    297:        case IST_PULSE:
                    298:                if (type != IST_NONE)
                    299:                        panic("intr_establish: can't share %s with %s",
                    300:                            intr_typename(intrtype[irq]),
                    301:                            intr_typename(type));
                    302:                break;
                    303:        }
                    304:
                    305:        /*
                    306:         * Figure out where to put the handler.
                    307:         * This is O(N^2), but we want to preserve the order, and N is
                    308:         * generally small.
                    309:         */
                    310:        for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
                    311:                ;
                    312:
                    313:        /*
                    314:         * Actually install a fake handler momentarily, since we might be doing
                    315:         * this with interrupts enabled and don't want the real routine called
                    316:         * until masking is set up.
                    317:         */
                    318:        fakehand.ih_level = level;
                    319:        *p = &fakehand;
                    320:
                    321:        intr_calculatemasks();
                    322:
                    323:        /*
                    324:         * Poke the real handler in now.
                    325:         */
                    326:        ih->ih_fun = ih_fun;
                    327:        ih->ih_arg = ih_arg;
                    328:        ih->ih_next = NULL;
                    329:        ih->ih_level = level;
                    330:        ih->ih_irq = irq;
                    331:        ih->ih_what = what;
                    332:        evcount_attach(&ih->ih_count, what, (void *)&ih->ih_irq, &evcount_intr);
                    333:        *p = ih;
                    334:
                    335:        return (ih);
                    336: }
                    337:
                    338:
                    339: /*
                    340:  * Register a PCI interrupt handler.
                    341:  */
                    342: void *
                    343: openpic_intr_establish(lcv, irq, type, level, ih_fun, ih_arg, what)
                    344:        void * lcv;
                    345:        int irq;
                    346:        int type;
                    347:        int level;
                    348:        int (*ih_fun)(void *);
                    349:        void *ih_arg;
                    350:        char *what;
                    351: {
                    352:        struct intrhand **p, *q, *ih;
                    353:        static struct intrhand fakehand;
                    354:        const struct pci_route *pr;
                    355:
                    356:        fakehand.ih_next = NULL;
                    357:        fakehand.ih_fun = fakeintr;
                    358:
                    359:        for (pr = pci_routes; pr->pci != 0; pr++)
                    360:                if (pr->pci == irq) {
                    361:                        irq = pr->openpic;
                    362:                        break;
                    363:                }
                    364:
                    365:        irq = mapirq(irq + PIC_OFFSET);
                    366:
                    367:        /* no point in sleeping unless someone can free memory. */
                    368:        ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
                    369:        if (ih == NULL)
                    370:                panic("intr_establish: can't malloc handler info");
                    371:
                    372:        if (!LEGAL_IRQ(irq) || type == IST_NONE)
                    373:                panic("intr_establish: bogus irq or type");
                    374:
                    375:        switch (intrtype[irq]) {
                    376:        case IST_EDGE:
                    377:        case IST_LEVEL:
                    378:                if (type == intrtype[irq])
                    379:                        break;
                    380:        case IST_PULSE:
                    381:                if (type != IST_NONE)
                    382:                        panic("intr_establish: can't share %s with %s",
                    383:                            intr_typename(intrtype[irq]),
                    384:                            intr_typename(type));
                    385:                break;
                    386:        }
                    387:
                    388:        /*
                    389:         * Figure out where to put the handler.
                    390:         * This is O(N^2), but we want to preserve the order, and N is
                    391:         * generally small.
                    392:         */
                    393:        for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
                    394:                ;
                    395:
                    396:        /*
                    397:         * Actually install a fake handler momentarily, since we might be doing
                    398:         * this with interrupts enabled and don't want the real routine called
                    399:         * until masking is set up.
                    400:         */
                    401:        fakehand.ih_level = level;
                    402:        *p = &fakehand;
                    403:
                    404:        intr_calculatemasks();
                    405:
                    406:        /*
                    407:         * Poke the real handler in now.
                    408:         */
                    409:        ih->ih_fun = ih_fun;
                    410:        ih->ih_arg = ih_arg;
                    411:        ih->ih_next = NULL;
                    412:        ih->ih_level = level;
                    413:        ih->ih_irq = irq;
                    414:        ih->ih_what = what;
                    415:        evcount_attach(&ih->ih_count, what, (void *)&ih->ih_irq, &evcount_intr);
                    416:        *p = ih;
                    417:
                    418:        return (ih);
                    419: }
                    420:
                    421: /*
                    422:  * Deregister an interrupt handler.
                    423:  */
                    424: void
                    425: openpic_intr_disestablish(lcp, arg)
                    426:        void *lcp;
                    427:        void *arg;
                    428: {
                    429:        struct intrhand *ih = arg;
                    430:        int irq = ih->ih_irq;
                    431:        struct intrhand **p, *q;
                    432:
                    433:        if (!LEGAL_IRQ(irq))
                    434:                panic("intr_disestablish: bogus irq");
                    435:
                    436:        /*
                    437:         * Remove the handler from the chain.
                    438:         * This is O(n^2), too.
                    439:         */
                    440:        for (p = &intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next)
                    441:                ;
                    442:        if (q)
                    443:                *p = q->ih_next;
                    444:        else
                    445:                panic("intr_disestablish: handler not registered");
                    446:
                    447:        evcount_detach(&ih->ih_count);
                    448:        free((void *)ih, M_DEVBUF);
                    449:
                    450:        intr_calculatemasks();
                    451:
                    452:        if (intrhand[irq] == NULL)
                    453:                intrtype[irq] = IST_NONE;
                    454: }
                    455:
                    456: const char *
                    457: intr_typename(type)
                    458:        int type;
                    459: {
                    460:
                    461:        switch (type) {
                    462:        case IST_NONE :
                    463:                return ("none");
                    464:        case IST_PULSE:
                    465:                return ("pulsed");
                    466:        case IST_EDGE:
                    467:                return ("edge-triggered");
                    468:        case IST_LEVEL:
                    469:                return ("level-triggered");
                    470: #ifdef DIAGNOSTIC
                    471:        default:
                    472:                panic("intr_typename: invalid type %d", type);
                    473: #endif
                    474:        }
                    475: }
                    476:
                    477: /*
                    478:  * Recalculate the interrupt masks from scratch.
                    479:  * We could code special registry and deregistry versions of this function that
                    480:  * would be faster, but the code would be nastier, and we don't expect this to
                    481:  * happen very much anyway.
                    482:  */
                    483: void
                    484: intr_calculatemasks()
                    485: {
                    486:        int irq, hirq, level, levels;
                    487:        struct intrhand *q;
                    488:        int irqs;
                    489:
                    490:        /* First, figure out which levels each IRQ uses. */
                    491:        for (irq = 0; irq < ICU_LEN; irq++) {
                    492:                levels = 0;
                    493:                for (q = intrhand[irq]; q; q = q->ih_next)
                    494:                        levels |= 1 << q->ih_level;
                    495:                intrlevel[irq] = levels;
                    496:        }
                    497:
                    498:        /* Then figure out which IRQs use each level. */
                    499:        for (level = IPL_NONE; level < IPL_NUM; level++) {
                    500:                irqs = 0;
                    501:                for (irq = 0; irq < ICU_LEN; irq++)
                    502:                        if (intrlevel[irq] & (1 << level))
                    503:                                irqs |= 1 << irq;
                    504:                imask[level] = irqs | SINT_MASK;
                    505:        }
                    506:
                    507:        /*
                    508:         * There are tty, network and disk drivers that use free() at interrupt
                    509:         * time, so vm > (tty | net | bio).
                    510:         *
                    511:         * Enforce a hierarchy that gives slow devices a better chance at not
                    512:         * dropping data.
                    513:         */
                    514:        imask[IPL_NET] |= imask[IPL_BIO];
                    515:        imask[IPL_TTY] |= imask[IPL_NET];
                    516:        imask[IPL_VM] |= imask[IPL_TTY];
                    517:        imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCK;
                    518:
                    519:        /*
                    520:         * These are pseudo-levels.
                    521:         */
                    522:        imask[IPL_NONE] = 0x00000000;
                    523:        imask[IPL_HIGH] = 0xffffffff;
                    524:
                    525:        /* And eventually calculate the complete masks. */
                    526:        for (irq = 0; irq < ICU_LEN; irq++) {
                    527:                irqs = 1 << irq;
                    528:                for (q = intrhand[irq]; q; q = q->ih_next)
                    529:                        irqs |= imask[q->ih_level];
                    530:                intrmask[irq] = irqs | SINT_MASK;
                    531:        }
                    532:
                    533:        /* Lastly, determine which IRQs are actually in use. */
                    534:        irqs = 0;
                    535:        for (irq = 0; irq < ICU_LEN; irq++) {
                    536:                hirq = hwirq[irq];
                    537:                if (hirq < 0)
                    538:                        continue;
                    539:
                    540:                if (intrhand[irq]) {
                    541:                        irqs |= 1 << irq;
                    542:
                    543:                        if (hirq >= PIC_OFFSET)
                    544:                                openpic_enable_irq(hirq, intrtype[irq]);
                    545:                        else
                    546:                                i8259_enable_irq(hirq, intrtype[irq]);
                    547:                } else {
                    548:                        if (hirq >= PIC_OFFSET)
                    549:                                openpic_disable_irq(hirq);
                    550:                        else
                    551:                                i8259_disable_irq(hirq);
                    552:                }
                    553:        }
                    554:
                    555:        /* always enable the chained 8259 interrupt */
                    556:        i8259_enable_irq(IRQ_SLAVE, IST_EDGE);
                    557:
                    558:        imen = ~irqs;
                    559:        i8259_set_irq_mask();
                    560: }
                    561:
                    562: /*
                    563:  * Map 64 irqs into 32 (bits).
                    564:  */
                    565: int
                    566: mapirq(irq)
                    567:        int irq;
                    568: {
                    569:        int v;
                    570:
                    571: #ifdef DIAGNOSTIC
                    572:        if (irq < 0 || irq >= ICU_LEN)
                    573:                panic("invalid irq");
                    574: #endif
                    575:
                    576:        virq_max++;
                    577:        v = virq_max;
                    578:        if (v > HWIRQ_MAX)
                    579:                panic("virq overflow");
                    580:
                    581:        hwirq[v] = irq;
                    582:        virq[irq] = v;
                    583: #ifdef DEBUG
                    584:        printf("mapirq %x to %x\n", irq, v);
                    585: #endif
                    586:
                    587:        return v;
                    588: }
                    589:
                    590: /*
                    591:  * Count leading zeros.
                    592:  */
                    593: static __inline int
                    594: cntlzw(x)
                    595:        int x;
                    596: {
                    597:        int a;
                    598:
                    599:        __asm __volatile ("cntlzw %0,%1" : "=r"(a) : "r"(x));
                    600:        return a;
                    601: }
                    602:
                    603: void
                    604: openpic_do_pending_int()
                    605: {
                    606:        struct intrhand *ih;
                    607:        int irq;
                    608:        int pcpl;
                    609:        int hwpend;
                    610:        int s;
                    611:        static int processing;
                    612:
                    613:        if (processing)
                    614:                return;
                    615:
                    616:        processing = 1;
                    617:        pcpl = splhigh();               /* Turn off all */
                    618:        s = ppc_intr_disable();
                    619:
                    620:        hwpend = ipending & ~pcpl;      /* Do now unmasked pendings */
                    621:        imen &= ~hwpend;
                    622:        openpic_enable_irq_mask(~imen);
                    623:
                    624:        hwpend &= HWIRQ_MASK;
                    625:        while (hwpend) {
                    626:                irq = 31 - cntlzw(hwpend);
                    627:                hwpend &= ~(1L << irq);
                    628:                ih = intrhand[irq];
                    629:                while (ih) {
                    630:                        if ((*ih->ih_fun)(ih->ih_arg))
                    631:                                ih->ih_count.ec_count++;
                    632:                        ih = ih->ih_next;
                    633:                }
                    634:        }
                    635:
                    636:        do {
                    637:                if ((ipending & SINT_CLOCK) & ~pcpl) {
                    638:                        ipending &= ~SINT_CLOCK;
                    639:                        softclock();
                    640:                }
                    641:                if ((ipending & SINT_NET) & ~pcpl) {
                    642:                        extern int netisr;
                    643:                        int pisr;
                    644:
                    645:                        ipending &= ~SINT_NET;
                    646:                        while ((pisr = netisr) != 0) {
                    647:                                atomic_clearbits_int(&netisr, pisr);
                    648:                                softnet(pisr);
                    649:                        }
                    650:                }
                    651: #if 0
                    652:                if ((ipending & SINT_TTY) & ~pcpl) {
                    653:                        ipending &= ~SINT_TTY;
                    654:                        softtty();
                    655:                }
                    656: #endif
                    657:        } while (ipending & (SINT_NET|SINT_CLOCK/*|SINT_TTY*/) & ~cpl);
                    658:        ipending &= pcpl;
                    659:        cpl = pcpl;     /* Don't use splx... we are here already! */
                    660:
                    661: #if 0
                    662:        i8259_set_irq_mask();
                    663: #endif
                    664:
                    665:        ppc_intr_enable(s);
                    666:        processing = 0;
                    667: }
                    668:
                    669: u_int
                    670: openpic_read(reg)
                    671:        int reg;
                    672: {
                    673:        char *addr = (void *)(openpic_base + reg);
                    674:
                    675:        return in32rb(addr);
                    676: }
                    677:
                    678: void
                    679: openpic_write(reg, val)
                    680:        int reg;
                    681:        u_int val;
                    682: {
                    683:        char *addr = (void *)(openpic_base + reg);
                    684:
                    685:        out32rb(addr, val);
                    686: }
                    687:
                    688: void
                    689: openpic_enable_irq_mask(irq_mask)
                    690:        int irq_mask;
                    691: {
                    692:        int irq, hirq;
                    693:
                    694:        for (irq = 0; irq <= virq_max; irq++) {
                    695:                hirq = hwirq[irq];
                    696:                if (hirq < 0)
                    697:                        continue;
                    698:
                    699:                if (irq_mask & (1 << irq)) {
                    700:                        if (hirq >= PIC_OFFSET)
                    701:                                openpic_enable_irq(hirq, intrtype[irq]);
                    702:                        else
                    703:                                i8259_enable_irq(hirq, intrtype[irq]);
                    704:                } else {
                    705:                        if (hirq >= PIC_OFFSET)
                    706:                                openpic_disable_irq(hirq);
                    707:                        else
                    708:                                i8259_disable_irq(hirq);
                    709:                }
                    710:        }
                    711:
                    712:        i8259_set_irq_mask();
                    713: }
                    714:
                    715: void
                    716: openpic_enable_irq(irq, type)
                    717:        int irq;
                    718:        int type;
                    719: {
                    720:        u_int x, isrc;
                    721:
                    722: #ifdef DIAGNOSTIC
                    723:        /* skip invalid irqs */
                    724:        if (irq < PIC_OFFSET)
                    725:                panic("openpic_enable_irq: invalid irq %x", irq);
                    726: #endif
                    727:        irq -= PIC_OFFSET;
                    728:
                    729:        x = openpic_read(OPENPIC_SRC_VECTOR(irq));
                    730:
                    731:        isrc = x & ~(OPENPIC_IMASK | OPENPIC_SENSE_LEVEL |
                    732:            OPENPIC_POLARITY_POSITIVE | OPENPIC_ACTIVITY);
                    733:        if (irq == 0)
                    734:                isrc |= OPENPIC_POLARITY_POSITIVE;
                    735:        if (type == IST_LEVEL)
                    736:                isrc |= OPENPIC_SENSE_LEVEL;
                    737:        else
                    738:                isrc |= OPENPIC_SENSE_EDGE;
                    739:
                    740:        /* Ack all pending interrupts if this one is pending. */
                    741:        while (x & OPENPIC_ACTIVITY) {
                    742:                (void)openpic_iack(0);
                    743:                openpic_eoi(0);
                    744:                x = openpic_read(OPENPIC_SRC_VECTOR(irq));
                    745:        }
                    746:
                    747:        if (x != isrc)
                    748:                openpic_write(OPENPIC_SRC_VECTOR(irq), isrc);
                    749: }
                    750:
                    751: void
                    752: openpic_disable_irq(irq)
                    753:        int irq;
                    754: {
                    755:        u_int x;
                    756:
                    757:        /* skip invalid irqs */
                    758:        if (irq >= PIC_OFFSET)
                    759:                irq -= PIC_OFFSET;
                    760:
                    761:        x = openpic_read(OPENPIC_SRC_VECTOR(irq));
                    762:        x |= OPENPIC_IMASK;
                    763:        openpic_write(OPENPIC_SRC_VECTOR(irq), x);
                    764: }
                    765:
                    766: void
                    767: i8259_set_irq_mask(void)
                    768: {
                    769:        if (icu2_val != 0xff) {
                    770:                /* Turn on the second IC */
                    771:                icu1_val &= ~(1 << IRQ_SLAVE);
                    772:        } else {
                    773:                icu1_val |= (1 << IRQ_SLAVE);
                    774:        }
                    775:
                    776:        outb(IO_ICU1 + 1, icu1_val);
                    777:        outb(IO_ICU2 + 1, icu2_val);
                    778:        outb(IO_ELCR1, elcr1_val);
                    779:        outb(IO_ELCR2, elcr2_val);
                    780: }
                    781:
                    782: void
                    783: i8259_disable_irq(irq)
                    784:        int irq;
                    785: {
                    786: #ifdef DIAGNOSTIC
                    787:        /* skip invalid irqs */
                    788:        if (irq < 0 || irq >= PIC_OFFSET)
                    789:                panic("i8259_disable_irq: invalid irq %x", irq);
                    790: #endif
                    791:
                    792:        if (irq < 8) {
                    793:                icu1_val |= 1 << irq;
                    794:                elcr1_val &= ~(1 << irq);
                    795:        } else {
                    796:                irq -= 8;
                    797:                icu2_val |= 1 << irq;
                    798:                elcr2_val &= ~(1 << irq);
                    799:        }
                    800: }
                    801:
                    802: void
                    803: i8259_enable_irq(irq, type)
                    804:        int irq, type;
                    805: {
                    806: #ifdef DIAGNOSTIC
                    807:        /* skip invalid irqs */
                    808:        if (irq < 0 || irq >= PIC_OFFSET)
                    809:                panic("i8259_enable_irq: invalid irq %x", irq);
                    810: #endif
                    811:
                    812:        if (irq < 8) {
                    813:                icu1_val &= ~(1 << irq);
                    814:                if (type == IST_LEVEL)
                    815:                        elcr1_val |= (1 << irq);
                    816:                else
                    817:                        elcr1_val &= ~(1 << irq);
                    818:        } else {
                    819:                irq -= 8;
                    820:                icu2_val &= ~(1 << irq);
                    821:                if (type == IST_LEVEL)
                    822:                        elcr2_val |= (1 << irq);
                    823:                else
                    824:                        elcr2_val &= ~(1 << irq);
                    825:        }
                    826: }
                    827:
                    828: void
                    829: i8259_eoi(int irq)
                    830: {
                    831: #ifdef DIAGNOSTIC
                    832:        /* skip invalid irqs */
                    833:        if (irq < 0 || irq >= PIC_OFFSET)
                    834:                panic("i8259_eoi: invalid irq %x", irq);
                    835: #endif
                    836:
                    837:        if (irq < 8)
                    838:                outb(IO_ICU1, 0x60 | irq);
                    839:        else {
                    840:                outb(IO_ICU2, 0x60 | (irq - 8));
                    841:                /*
                    842:                 * Do not ack on the master unless there are no
                    843:                 * other interrupts pending on the slave
                    844:                 * controller!
                    845:                 */
                    846:                outb(IO_ICU2, 0x0b);
                    847:                if (inb(IO_ICU2) == 0)
                    848:                        outb(IO_ICU1, 0x60 | IRQ_SLAVE);
                    849:        }
                    850: }
                    851:
                    852: void
                    853: openpic_set_priority(cpu, pri)
                    854:        int cpu, pri;
                    855: {
                    856:        u_int x;
                    857:
                    858:        x = openpic_read(OPENPIC_CPU_PRIORITY(cpu));
                    859:        x &= ~OPENPIC_CPU_PRIORITY_MASK;
                    860:        x |= pri;
                    861:        openpic_write(OPENPIC_CPU_PRIORITY(cpu), x);
                    862: }
                    863:
                    864: int
                    865: openpic_iack(cpu)
                    866:        int cpu;
                    867: {
                    868:        return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
                    869: }
                    870:
                    871: void
                    872: openpic_eoi(cpu)
                    873:        int cpu;
                    874: {
                    875:        openpic_write(OPENPIC_EOI(cpu), 0);
                    876:        openpic_read(OPENPIC_EOI(cpu));
                    877: }
                    878:
                    879: void
                    880: i8259_init(void)
                    881: {
                    882:        /* initialize 8259's */
                    883:        outb(IO_ICU1, 0x11);            /* reset; program device, four bytes */
                    884:        outb(IO_ICU1+1, ICU_OFFSET);    /* starting at this vector index */
                    885:        outb(IO_ICU1+1, 1 << IRQ_SLAVE);        /* slave on line 2 */
                    886:        outb(IO_ICU1+1, 1);             /* 8086 mode */
                    887:        outb(IO_ICU1+1, 0xff);          /* leave interrupts masked */
                    888:        /* init interrupt controller 2 */
                    889:        outb(IO_ICU2, 0x11);            /* reset; program device, four bytes */
                    890:        outb(IO_ICU2+1, ICU_OFFSET+8);  /* staring at this vector index */
                    891:        outb(IO_ICU2+1, IRQ_SLAVE);
                    892:        outb(IO_ICU2+1, 1);             /* 8086 mode */
                    893:        outb(IO_ICU2+1, 0xff);          /* leave interrupts masked */
                    894: }
                    895:
                    896: int
                    897: i8259_intr(void)
                    898: {
                    899:        int irq;
                    900:
                    901:        /*
                    902:         * Perform an interrupt acknowledge cycle on controller 1
                    903:         */
                    904:        outb(IO_ICU1, 0x0c);
                    905:        irq = inb(IO_ICU1) & 7;
                    906:
                    907:        if (irq == IRQ_SLAVE) {
                    908:                /*
                    909:                 * Interrupt is cascaded so perform interrupt
                    910:                 * acknowledge on controller 2
                    911:                 */
                    912:                outb(IO_ICU2, 0x0c);
                    913:                irq = (inb(IO_ICU2) & 7) + 8;
                    914:                if (irq == 15) {
                    915:                        outb(IO_ICU2, 0x0b);
                    916:                        if ((inb(IO_ICU2) & 0x80) == 0) {
                    917: #ifdef DIAGNOSTIC
                    918:                                printf("spurious interrupt on ICU2\n");
                    919: #endif
                    920:                                return PIC_SPURIOUS;
                    921:                        }
                    922:                }
                    923:        } else if (irq == 7) {
                    924:                /*
                    925:                 * This may be a spurious interrupt
                    926:                 *
                    927:                 * Read the interrupt status register. If the most
                    928:                 * significant bit is not set then there is no valid
                    929:                 * interrupt
                    930:                 */
                    931:                outb(IO_ICU1, 0x0b);
                    932:                if ((inb(IO_ICU1) & 0x80) == 0) {
                    933: #ifdef DIAGNOSTIC
                    934:                        printf("spurious interrupt on ICU1\n");
                    935: #endif
                    936:                        return PIC_SPURIOUS;
                    937:                }
                    938:        }
                    939:
                    940:        return (ICU_OFFSET + irq);
                    941: }
                    942:
                    943: void
                    944: ext_intr_openpic()
                    945: {
                    946:        int irq, realirq;
                    947:        int r_imen;
                    948:        int pcpl, ocpl;
                    949:        struct intrhand *ih;
                    950:
                    951:        pcpl = cpl;
                    952:
                    953:        realirq = openpic_iack(0);
                    954:
                    955:        while (realirq != PIC_SPURIOUS) {
                    956:                if (realirq == 0x00) {
                    957:                        /*
                    958:                         * Interrupt from the PCI/ISA bridge. PCI interrupts
                    959:                         * are shadowed on the ISA PIC for compatibility with
                    960:                         * MVME1600, so simply handle the ISA PIC.
                    961:                         */
                    962:                        realirq = i8259_intr();
                    963:                        openpic_eoi(0);
                    964:                        if (realirq == PIC_SPURIOUS)
                    965:                                break;
                    966:                } else {
                    967:                        realirq += PIC_OFFSET;
                    968:                }
                    969:
                    970:                irq = virq[realirq];
                    971:
                    972:                /* XXX check range */
                    973:
                    974:                r_imen = 1 << irq;
                    975:
                    976:                if ((pcpl & r_imen) != 0) {
                    977:                        ipending |= r_imen;             /* Masked! Mark this as pending */
                    978:                        if (realirq >= PIC_OFFSET) {
                    979:                                openpic_disable_irq(realirq);
                    980:                                openpic_eoi(0);
                    981:                        } else {
                    982:                                i8259_disable_irq(realirq);
                    983:                                i8259_set_irq_mask();
                    984:                                i8259_eoi(realirq);
                    985:                        }
                    986:                } else {
                    987:                        if (realirq >= PIC_OFFSET) {
                    988:                                openpic_disable_irq(realirq);
                    989:                        } else {
                    990:                                i8259_disable_irq(realirq);
                    991:                                i8259_set_irq_mask();
                    992:                        }
                    993:
                    994:                        ocpl = splraise(intrmask[irq]);
                    995:
                    996:                        ih = intrhand[irq];
                    997:                        while (ih) {
                    998:                                if ((*ih->ih_fun)(ih->ih_arg))
                    999:                                        ih->ih_count.ec_count++;
                   1000:                                ih = ih->ih_next;
                   1001:                        }
                   1002:
                   1003:                        uvmexp.intrs++;
                   1004:                        __asm__ volatile("":::"memory");
                   1005:                        cpl = ocpl;
                   1006:                        __asm__ volatile("":::"memory");
                   1007:
                   1008:                        if (realirq >= PIC_OFFSET) {
                   1009:                                openpic_eoi(0);
                   1010:                                openpic_enable_irq(realirq, intrtype[irq]);
                   1011:                        } else {
                   1012:                                i8259_eoi(realirq);
                   1013:                                i8259_enable_irq(realirq, intrtype[irq]);
                   1014:                                i8259_set_irq_mask();
                   1015:                        }
                   1016:                }
                   1017:
                   1018:                realirq = openpic_iack(0);
                   1019:        }
                   1020:        ppc_intr_enable(1);
                   1021:
                   1022:        splx(pcpl);      /* Process pendings. */
                   1023: }
                   1024:
                   1025: void
                   1026: openpic_initirq(int irq, int pol, int sense)
                   1027: {
                   1028:        u_int x;
                   1029:
                   1030:        x = (irq & OPENPIC_VECTOR_MASK);
                   1031:        x |= OPENPIC_IMASK;
                   1032:        x |= (pol ? OPENPIC_POLARITY_POSITIVE : OPENPIC_POLARITY_NEGATIVE);
                   1033:        x |= (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE);
                   1034:        x |= 8 << OPENPIC_PRIORITY_SHIFT;
                   1035:        openpic_write(OPENPIC_SRC_VECTOR(irq), x);
                   1036: }
                   1037:
                   1038: void
                   1039: openpic_init()
                   1040: {
                   1041:        int irq;
                   1042:        u_int x;
                   1043:
                   1044:        /* disable all interrupts and init hwirq[] */
                   1045:        for (irq = 0; irq < ICU_LEN; irq++) {
                   1046:                hwirq[irq] = -1;
                   1047:                intrtype[irq] = IST_NONE;
                   1048:                intrmask[irq] = 0;
                   1049:                intrlevel[irq] = 0;
                   1050:                intrhand[irq] = NULL;
                   1051:                openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
                   1052:        }
                   1053:        openpic_set_priority(0, 15);
                   1054:
                   1055:        /* we don't need 8259 pass through mode */
                   1056:        x = openpic_read(OPENPIC_CONFIG);
                   1057:        x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
                   1058:        openpic_write(OPENPIC_CONFIG, x);
                   1059:
                   1060:        /* send all interrupts to cpu 0 */
                   1061:        for (irq = 0; irq < ICU_LEN; irq++)
                   1062:                openpic_write(OPENPIC_SRC_DEST(irq), CPU(0));
                   1063:
                   1064:        /* special case for intr src 0 */
                   1065:        openpic_initirq(0, 1, 0);
                   1066:        for (irq = 1; irq < ICU_LEN; irq++) {
                   1067:                openpic_initirq(irq, 0, 1);
                   1068:        }
                   1069:
                   1070:        /* XXX set spurious intr vector */
                   1071: #if 0
                   1072:        openpic_write(OPENPIC_SPURIOUS_VECTOR, 0xFF);
                   1073: #endif
                   1074:
                   1075:        /* unmask interrupts for cpu 0 */
                   1076:        openpic_set_priority(0, 0);
                   1077:
                   1078:        /* clear all pending interrunts */      /* < ICU_LEN ? */
                   1079:        for (irq = 0; irq < PIC_OFFSET; irq++) {
                   1080:                openpic_iack(0);
                   1081:                openpic_eoi(0);
                   1082:        }
                   1083:
                   1084:        for (irq = 0; irq < PIC_OFFSET; irq++) {        /* < ICU_LEN ? */
                   1085:                i8259_disable_irq(irq);
                   1086:                openpic_disable_irq(irq);
                   1087:        }
                   1088:
                   1089:        i8259_set_irq_mask();
                   1090:
                   1091:        install_extint(ext_intr_openpic);
                   1092: }

CVSweb