[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     ! 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