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

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

1.1     ! nbrk        1: /*     $OpenBSD: openpic.c,v 1.40 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.h>
        !            47: #include <ddb/db_var.h>
        !            48:
        !            49: #include <machine/atomic.h>
        !            50: #include <machine/autoconf.h>
        !            51: #include <machine/intr.h>
        !            52: #include <machine/psl.h>
        !            53: #include <machine/pio.h>
        !            54: #include <machine/powerpc.h>
        !            55: #include <macppc/dev/openpicreg.h>
        !            56: #include <dev/ofw/openfirm.h>
        !            57:
        !            58: #define ICU_LEN 128
        !            59: #define LEGAL_IRQ(x) ((x >= 0) && (x < ICU_LEN))
        !            60:
        !            61: int o_intrtype[ICU_LEN], o_intrmask[ICU_LEN], o_intrlevel[ICU_LEN];
        !            62: struct intrhand *o_intrhand[ICU_LEN] = { 0 };
        !            63: int o_hwirq[ICU_LEN], o_virq[ICU_LEN];
        !            64: unsigned int imen_o = 0xffffffff;
        !            65: int o_virq_max;
        !            66:
        !            67: static int fakeintr(void *);
        !            68: static char *intr_typename(int type);
        !            69: static void intr_calculatemasks(void);
        !            70: static __inline int cntlzw(int x);
        !            71: static int mapirq(int irq);
        !            72: int openpic_prog_button(void *arg);
        !            73: void openpic_enable_irq_mask(int irq_mask);
        !            74:
        !            75: #define HWIRQ_MAX 27
        !            76: #define HWIRQ_MASK 0x0fffffff
        !            77:
        !            78: static __inline u_int openpic_read(int);
        !            79: static __inline void openpic_write(int, u_int);
        !            80: void openpic_set_enable_irq(int, int);
        !            81: void openpic_enable_irq(int);
        !            82: void openpic_disable_irq(int);
        !            83: void openpic_init(void);
        !            84: void openpic_set_priority(int, int);
        !            85: static __inline int openpic_read_irq(int);
        !            86: static __inline void openpic_eoi(int);
        !            87:
        !            88: struct openpic_softc {
        !            89:        struct device sc_dev;
        !            90: };
        !            91:
        !            92: int    openpic_match(struct device *parent, void *cf, void *aux);
        !            93: void   openpic_attach(struct device *, struct device *, void *);
        !            94: void   openpic_do_pending_int(void);
        !            95: void   openpic_collect_preconf_intr(void);
        !            96: void   ext_intr_openpic(void);
        !            97:
        !            98: struct cfattach openpic_ca = {
        !            99:        sizeof(struct openpic_softc),
        !           100:        openpic_match,
        !           101:        openpic_attach
        !           102: };
        !           103:
        !           104: struct cfdriver openpic_cd = {
        !           105:        NULL, "openpic", DV_DULL
        !           106: };
        !           107:
        !           108: int
        !           109: openpic_match(struct device *parent, void *cf, void *aux)
        !           110: {
        !           111:        char type[40];
        !           112:        int pirq;
        !           113:        struct confargs *ca = aux;
        !           114:
        !           115:        bzero (type, sizeof(type));
        !           116:
        !           117:        if (OF_getprop(ca->ca_node, "interrupt-parent", &pirq, sizeof(pirq))
        !           118:            == sizeof(pirq))
        !           119:                return 0; /* XXX */
        !           120:
        !           121:        if (strcmp(ca->ca_name, "interrupt-controller") != 0 &&
        !           122:            strcmp(ca->ca_name, "mpic") != 0)
        !           123:                return 0;
        !           124:
        !           125:        OF_getprop(ca->ca_node, "device_type", type, sizeof(type));
        !           126:        if (strcmp(type, "open-pic") != 0)
        !           127:                return 0;
        !           128:
        !           129:        if (ca->ca_nreg < 8)
        !           130:                return 0;
        !           131:
        !           132:        return 1;
        !           133: }
        !           134:
        !           135: typedef void  (void_f) (void);
        !           136: extern void_f *pending_int_f;
        !           137:
        !           138: vaddr_t openpic_base;
        !           139: void * openpic_intr_establish( void * lcv, int irq, int type, int level,
        !           140:        int (*ih_fun)(void *), void *ih_arg, char *name);
        !           141: void openpic_intr_disestablish( void *lcp, void *arg);
        !           142: void openpic_collect_preconf_intr(void);
        !           143: int openpic_big_endian;
        !           144:
        !           145: void
        !           146: openpic_attach(struct device *parent, struct device  *self, void *aux)
        !           147: {
        !           148:        struct confargs *ca = aux;
        !           149:        extern intr_establish_t *intr_establish_func;
        !           150:        extern intr_disestablish_t *intr_disestablish_func;
        !           151:        extern intr_establish_t *mac_intr_establish_func;
        !           152:        extern intr_disestablish_t *mac_intr_disestablish_func;
        !           153:        u_int32_t reg;
        !           154:
        !           155:        reg = 0;
        !           156:        if (OF_getprop(ca->ca_node, "big-endian", &reg, sizeof reg) == 0)
        !           157:                openpic_big_endian = 1;
        !           158:
        !           159:        openpic_base = (vaddr_t) mapiodev (ca->ca_baseaddr +
        !           160:                        ca->ca_reg[0], 0x40000);
        !           161:
        !           162:        printf(": version 0x%x %s endian", openpic_read(OPENPIC_VENDOR_ID),
        !           163:                openpic_big_endian ? "big" : "little" );
        !           164:
        !           165:        openpic_init();
        !           166:
        !           167:        pending_int_f = openpic_do_pending_int;
        !           168:        intr_establish_func  = openpic_intr_establish;
        !           169:        intr_disestablish_func  = openpic_intr_disestablish;
        !           170:        mac_intr_establish_func  = openpic_intr_establish;
        !           171:        mac_intr_disestablish_func  = openpic_intr_disestablish;
        !           172:        install_extint(ext_intr_openpic);
        !           173:
        !           174: #if 1
        !           175:        openpic_collect_preconf_intr();
        !           176: #endif
        !           177:
        !           178: #if 1
        !           179:        mac_intr_establish(parent, 0x37, IST_LEVEL,
        !           180:                IPL_HIGH, openpic_prog_button, (void *)0x37, "progbutton");
        !           181: #endif
        !           182:        ppc_intr_enable(1);
        !           183:
        !           184:        printf("\n");
        !           185: }
        !           186:
        !           187: void
        !           188: openpic_collect_preconf_intr()
        !           189: {
        !           190:        int i;
        !           191:        for (i = 0; i < ppc_configed_intr_cnt; i++) {
        !           192: #ifdef DEBUG
        !           193:                printf("\n\t%s irq %d level %d fun %x arg %x",
        !           194:                    ppc_configed_intr[i].ih_what, ppc_configed_intr[i].ih_irq,
        !           195:                    ppc_configed_intr[i].ih_level, ppc_configed_intr[i].ih_fun,
        !           196:                    ppc_configed_intr[i].ih_arg);
        !           197: #endif
        !           198:                openpic_intr_establish(NULL, ppc_configed_intr[i].ih_irq,
        !           199:                    IST_LEVEL, ppc_configed_intr[i].ih_level,
        !           200:                    ppc_configed_intr[i].ih_fun, ppc_configed_intr[i].ih_arg,
        !           201:                    ppc_configed_intr[i].ih_what);
        !           202:        }
        !           203: }
        !           204:
        !           205: static int
        !           206: fakeintr(void *arg)
        !           207: {
        !           208:
        !           209:        return 0;
        !           210: }
        !           211:
        !           212: /*
        !           213:  * Register an interrupt handler.
        !           214:  */
        !           215: void *
        !           216: openpic_intr_establish(void *lcv, int irq, int type, int level,
        !           217:     int (*ih_fun)(void *), void *ih_arg, char *name)
        !           218: {
        !           219:        struct intrhand **p, *q, *ih;
        !           220:        static struct intrhand fakehand;
        !           221:
        !           222:        fakehand.ih_next = NULL;
        !           223:        fakehand.ih_fun  = fakeintr;
        !           224:
        !           225: #if 0
        !           226: printf("mac_intr_establish, hI %d L %d ", irq, type);
        !           227: #endif
        !           228:
        !           229:        irq = mapirq(irq);
        !           230: #if 0
        !           231: printf("vI %d ", irq);
        !           232: #endif
        !           233:
        !           234:        /* no point in sleeping unless someone can free memory. */
        !           235:        ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
        !           236:        if (ih == NULL)
        !           237:                panic("intr_establish: can't malloc handler info");
        !           238:
        !           239:        if (!LEGAL_IRQ(irq) || type == IST_NONE)
        !           240:                panic("intr_establish: bogus irq or type");
        !           241:
        !           242:        switch (o_intrtype[irq]) {
        !           243:        case IST_NONE:
        !           244:                o_intrtype[irq] = type;
        !           245:                break;
        !           246:        case IST_EDGE:
        !           247:        case IST_LEVEL:
        !           248:                if (type == o_intrtype[irq])
        !           249:                        break;
        !           250:        case IST_PULSE:
        !           251:                if (type != IST_NONE)
        !           252:                        panic("intr_establish: can't share %s with %s",
        !           253:                            intr_typename(o_intrtype[irq]),
        !           254:                            intr_typename(type));
        !           255:                break;
        !           256:        }
        !           257:
        !           258:        /*
        !           259:         * Figure out where to put the handler.
        !           260:         * This is O(N^2), but we want to preserve the order, and N is
        !           261:         * generally small.
        !           262:         */
        !           263:        for (p = &o_intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
        !           264:                ;
        !           265:
        !           266:        /*
        !           267:         * Actually install a fake handler momentarily, since we might be doing
        !           268:         * this with interrupts enabled and DON'T WANt the real routine called
        !           269:         * until masking is set up.
        !           270:         */
        !           271:        fakehand.ih_level = level;
        !           272:        *p = &fakehand;
        !           273:
        !           274:        intr_calculatemasks();
        !           275:
        !           276:        /*
        !           277:         * Poke the real handler in now.
        !           278:         */
        !           279:        ih->ih_fun = ih_fun;
        !           280:        ih->ih_arg = ih_arg;
        !           281:        ih->ih_next = NULL;
        !           282:        ih->ih_level = level;
        !           283:        ih->ih_irq = irq;
        !           284:        evcount_attach(&ih->ih_count, name, (void *)&o_hwirq[irq],
        !           285:            &evcount_intr);
        !           286:        *p = ih;
        !           287:
        !           288:        return (ih);
        !           289: }
        !           290:
        !           291: /*
        !           292:  * Deregister an interrupt handler.
        !           293:  */
        !           294: void
        !           295: openpic_intr_disestablish(void *lcp, void *arg)
        !           296: {
        !           297:        struct intrhand *ih = arg;
        !           298:        int irq = ih->ih_irq;
        !           299:        struct intrhand **p, *q;
        !           300:
        !           301:        if (!LEGAL_IRQ(irq))
        !           302:                panic("intr_disestablish: bogus irq");
        !           303:
        !           304:        /*
        !           305:         * Remove the handler from the chain.
        !           306:         * This is O(n^2), too.
        !           307:         */
        !           308:        for (p = &o_intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next)
        !           309:                ;
        !           310:        if (q)
        !           311:                *p = q->ih_next;
        !           312:        else
        !           313:                panic("intr_disestablish: handler not registered");
        !           314:
        !           315:        evcount_detach(&ih->ih_count);
        !           316:        free((void *)ih, M_DEVBUF);
        !           317:
        !           318:        intr_calculatemasks();
        !           319:
        !           320:        if (o_intrhand[irq] == NULL)
        !           321:                o_intrtype[irq] = IST_NONE;
        !           322: }
        !           323:
        !           324:
        !           325: static char *
        !           326: intr_typename(int type)
        !           327: {
        !           328:
        !           329:        switch (type) {
        !           330:        case IST_NONE:
        !           331:                return ("none");
        !           332:        case IST_PULSE:
        !           333:                return ("pulsed");
        !           334:        case IST_EDGE:
        !           335:                return ("edge-triggered");
        !           336:        case IST_LEVEL:
        !           337:                return ("level-triggered");
        !           338:        default:
        !           339:                panic("intr_typename: invalid type %d", type);
        !           340: #if 1 /* XXX */
        !           341:                return ("unknown");
        !           342: #endif
        !           343:        }
        !           344: }
        !           345:
        !           346: /*
        !           347:  * Recalculate the interrupt masks from scratch.
        !           348:  * We could code special registry and deregistry versions of this function that
        !           349:  * would be faster, but the code would be nastier, and we don't expect this to
        !           350:  * happen very much anyway.
        !           351:  */
        !           352: static void
        !           353: intr_calculatemasks()
        !           354: {
        !           355:        int irq, level;
        !           356:        struct intrhand *q;
        !           357:
        !           358:        /* First, figure out which levels each IRQ uses. */
        !           359:        for (irq = 0; irq < ICU_LEN; irq++) {
        !           360:                register int levels = 0;
        !           361:                for (q = o_intrhand[irq]; q; q = q->ih_next)
        !           362:                        levels |= 1 << q->ih_level;
        !           363:                o_intrlevel[irq] = levels;
        !           364:        }
        !           365:
        !           366:        /* Then figure out which IRQs use each level. */
        !           367:        for (level = IPL_NONE; level < IPL_NUM; level++) {
        !           368:                register int irqs = 0;
        !           369:                for (irq = 0; irq < ICU_LEN; irq++)
        !           370:                        if (o_intrlevel[irq] & (1 << level))
        !           371:                                irqs |= 1 << irq;
        !           372:                imask[level] = irqs | SINT_MASK;
        !           373:        }
        !           374:
        !           375:        /*
        !           376:         * There are tty, network and disk drivers that use free() at interrupt
        !           377:         * time, so vm > (tty | net | bio).
        !           378:         *
        !           379:         * Enforce a hierarchy that gives slow devices a better chance at not
        !           380:         * dropping data.
        !           381:         */
        !           382:        imask[IPL_NET] |= imask[IPL_BIO];
        !           383:        imask[IPL_TTY] |= imask[IPL_NET];
        !           384:        imask[IPL_VM] |= imask[IPL_TTY];
        !           385:        imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCK;
        !           386:
        !           387:        /*
        !           388:         * These are pseudo-levels.
        !           389:         */
        !           390:        imask[IPL_NONE] = 0x00000000;
        !           391:        imask[IPL_HIGH] = 0xffffffff;
        !           392:
        !           393:        /* And eventually calculate the complete masks. */
        !           394:        for (irq = 0; irq < ICU_LEN; irq++) {
        !           395:                register int irqs = 1 << irq;
        !           396:                for (q = o_intrhand[irq]; q; q = q->ih_next)
        !           397:                        irqs |= imask[q->ih_level];
        !           398:                o_intrmask[irq] = irqs | SINT_MASK;
        !           399:        }
        !           400:
        !           401:        /* Lastly, determine which IRQs are actually in use. */
        !           402:        {
        !           403:                register int irqs = 0;
        !           404:                for (irq = 0; irq < ICU_LEN; irq++) {
        !           405:                        if (o_intrhand[irq]) {
        !           406:                                irqs |= 1 << irq;
        !           407:                                openpic_enable_irq(o_hwirq[irq]);
        !           408:                        } else {
        !           409:                                openpic_disable_irq(o_hwirq[irq]);
        !           410:                        }
        !           411:                }
        !           412:                imen_o = ~irqs;
        !           413:        }
        !           414: }
        !           415:
        !           416: /*
        !           417:  * Map 64 irqs into 32 (bits).
        !           418:  */
        !           419: static int
        !           420: mapirq(int irq)
        !           421: {
        !           422:        int v;
        !           423:
        !           424:        /* irq in table already? */
        !           425:        if (o_virq[irq] != 0)
        !           426:                return o_virq[irq];
        !           427:
        !           428:        if (irq < 0 || irq >= ICU_LEN)
        !           429:                panic("invalid irq %d", irq);
        !           430:
        !           431:        o_virq_max++;
        !           432:        v = o_virq_max;
        !           433:        if (v > HWIRQ_MAX)
        !           434:                panic("virq overflow");
        !           435:
        !           436:        o_hwirq[v] = irq;
        !           437:        o_virq[irq] = v;
        !           438: #if 0
        !           439: printf("\nmapirq %x to %x\n", irq, v);
        !           440: #endif
        !           441:
        !           442:        return v;
        !           443: }
        !           444:
        !           445: /*
        !           446:  * Count leading zeros.
        !           447:  */
        !           448: static __inline int
        !           449: cntlzw(int x)
        !           450: {
        !           451:        int a;
        !           452:
        !           453:        __asm __volatile ("cntlzw %0,%1" : "=r"(a) : "r"(x));
        !           454:
        !           455:        return a;
        !           456: }
        !           457:
        !           458:
        !           459: void
        !           460: openpic_do_pending_int()
        !           461: {
        !           462:        struct cpu_info *ci = curcpu();
        !           463:        struct intrhand *ih;
        !           464:        int irq;
        !           465:        int pcpl;
        !           466:        int hwpend;
        !           467:        int s;
        !           468:
        !           469:        if (ci->ci_iactive)
        !           470:                return;
        !           471:
        !           472:        ci->ci_iactive = 1;
        !           473:        pcpl = splhigh();               /* Turn off all */
        !           474:        s = ppc_intr_disable();
        !           475:
        !           476:        hwpend = ci->ci_ipending & ~pcpl;       /* Do now unmasked pendings */
        !           477:        imen_o &= ~hwpend;
        !           478:        openpic_enable_irq_mask(~imen_o);
        !           479:        hwpend &= HWIRQ_MASK;
        !           480:        while (hwpend) {
        !           481:                irq = 31 - cntlzw(hwpend);
        !           482:                hwpend &= ~(1L << irq);
        !           483:                ih = o_intrhand[irq];
        !           484:                while(ih) {
        !           485:                        ppc_intr_enable(1);
        !           486:
        !           487:                        if ((*ih->ih_fun)(ih->ih_arg))
        !           488:                                ih->ih_count.ec_count++;
        !           489:
        !           490:                        (void)ppc_intr_disable();
        !           491:
        !           492:                        ih = ih->ih_next;
        !           493:                }
        !           494:        }
        !           495:
        !           496:        /*out32rb(INT_ENABLE_REG, ~imen_o);*/
        !           497:
        !           498:        do {
        !           499:                if((ci->ci_ipending & SINT_CLOCK) & ~pcpl) {
        !           500:                        ci->ci_ipending &= ~SINT_CLOCK;
        !           501:                        softclock();
        !           502:                }
        !           503:                if((ci->ci_ipending & SINT_NET) & ~pcpl) {
        !           504:                        extern int netisr;
        !           505:                        int pisr;
        !           506:
        !           507:                        ci->ci_ipending &= ~SINT_NET;
        !           508:                        while ((pisr = netisr) != 0) {
        !           509:                                atomic_clearbits_int(&netisr, pisr);
        !           510:                                softnet(pisr);
        !           511:                        }
        !           512:                }
        !           513:                if((ci->ci_ipending & SINT_TTY) & ~pcpl) {
        !           514:                        ci->ci_ipending &= ~SINT_TTY;
        !           515:                        softtty();
        !           516:                }
        !           517:        } while ((ci->ci_ipending & SINT_MASK) & ~pcpl);
        !           518:        ci->ci_ipending &= pcpl;
        !           519:        ci->ci_cpl = pcpl;      /* Don't use splx... we are here already! */
        !           520:        ppc_intr_enable(s);
        !           521:        ci->ci_iactive = 0;
        !           522: }
        !           523:
        !           524: u_int
        !           525: openpic_read(int reg)
        !           526: {
        !           527:        char *addr = (void *)(openpic_base + reg);
        !           528:
        !           529:        if (openpic_big_endian)
        !           530:                return in32(addr);
        !           531:        else
        !           532:                return in32rb(addr);
        !           533: }
        !           534:
        !           535: void
        !           536: openpic_write(int reg, u_int val)
        !           537: {
        !           538:        char *addr = (void *)(openpic_base + reg);
        !           539:
        !           540:        if (openpic_big_endian)
        !           541:                out32(addr, val);
        !           542:        else
        !           543:                out32rb(addr, val);
        !           544: }
        !           545:
        !           546: void
        !           547: openpic_enable_irq_mask(int irq_mask)
        !           548: {
        !           549:        int irq;
        !           550:        for ( irq = 0; irq <= o_virq_max; irq++) {
        !           551:                if (irq_mask & (1 << irq))
        !           552:                        openpic_enable_irq(o_hwirq[irq]);
        !           553:                else
        !           554:                        openpic_disable_irq(o_hwirq[irq]);
        !           555:        }
        !           556: }
        !           557:
        !           558: void
        !           559: openpic_set_enable_irq(int irq, int type)
        !           560: {
        !           561:        u_int x;
        !           562:
        !           563:        x = openpic_read(OPENPIC_SRC_VECTOR(irq));
        !           564:        x &= ~(OPENPIC_IMASK|OPENPIC_SENSE_LEVEL|OPENPIC_SENSE_EDGE);
        !           565:        if (type == IST_LEVEL)
        !           566:                x |= OPENPIC_SENSE_LEVEL;
        !           567:        else
        !           568:                x |= OPENPIC_SENSE_EDGE;
        !           569:        openpic_write(OPENPIC_SRC_VECTOR(irq), x);
        !           570: }
        !           571: void
        !           572: openpic_enable_irq(int irq)
        !           573: {
        !           574:        u_int x;
        !           575:
        !           576:        x = openpic_read(OPENPIC_SRC_VECTOR(irq));
        !           577:        x &= ~(OPENPIC_IMASK|OPENPIC_SENSE_LEVEL|OPENPIC_SENSE_EDGE);
        !           578:        if (o_intrtype[o_virq[irq]] == IST_LEVEL)
        !           579:                x |= OPENPIC_SENSE_LEVEL;
        !           580:        else
        !           581:                x |= OPENPIC_SENSE_EDGE;
        !           582:        openpic_write(OPENPIC_SRC_VECTOR(irq), x);
        !           583: }
        !           584:
        !           585: void
        !           586: openpic_disable_irq(int irq)
        !           587: {
        !           588:        u_int x;
        !           589:
        !           590:        x = openpic_read(OPENPIC_SRC_VECTOR(irq));
        !           591:        x |= OPENPIC_IMASK;
        !           592:        openpic_write(OPENPIC_SRC_VECTOR(irq), x);
        !           593: }
        !           594:
        !           595: void
        !           596: openpic_set_priority(int cpu, int pri)
        !           597: {
        !           598:        u_int x;
        !           599:
        !           600:        x = openpic_read(OPENPIC_CPU_PRIORITY(cpu));
        !           601:        x &= ~OPENPIC_CPU_PRIORITY_MASK;
        !           602:        x |= pri;
        !           603:        openpic_write(OPENPIC_CPU_PRIORITY(cpu), x);
        !           604: }
        !           605:
        !           606: int
        !           607: openpic_read_irq(int cpu)
        !           608: {
        !           609:        return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
        !           610: }
        !           611:
        !           612: void
        !           613: openpic_eoi(int cpu)
        !           614: {
        !           615:        openpic_write(OPENPIC_EOI(cpu), 0);
        !           616:        openpic_read(OPENPIC_EOI(cpu));
        !           617: }
        !           618:
        !           619: void
        !           620: ext_intr_openpic()
        !           621: {
        !           622:        struct cpu_info *ci = curcpu();
        !           623:        int irq, realirq;
        !           624:        int r_imen;
        !           625:        int pcpl, ocpl;
        !           626:        struct intrhand *ih;
        !           627:
        !           628:        pcpl = ci->ci_cpl;
        !           629:
        !           630:        realirq = openpic_read_irq(0);
        !           631:
        !           632:        while (realirq != 255) {
        !           633:                irq = o_virq[realirq];
        !           634:
        !           635:                /* XXX check range */
        !           636:
        !           637:                r_imen = 1 << irq;
        !           638:
        !           639:                if ((pcpl & r_imen) != 0) {
        !           640:                        /* Masked! Mark this as pending. */
        !           641:                        ci->ci_ipending |= r_imen;
        !           642:                        openpic_disable_irq(realirq);
        !           643:                        openpic_eoi(0);
        !           644:                } else {
        !           645:                        openpic_disable_irq(realirq);
        !           646:                        openpic_eoi(0);
        !           647:                        ocpl = splraise(o_intrmask[irq]);
        !           648:
        !           649:                        ih = o_intrhand[irq];
        !           650:                        while (ih) {
        !           651:                                ppc_intr_enable(1);
        !           652:
        !           653:                                if ((*ih->ih_fun)(ih->ih_arg))
        !           654:                                        ih->ih_count.ec_count++;
        !           655:
        !           656:                                (void)ppc_intr_disable();
        !           657:                                ih = ih->ih_next;
        !           658:                        }
        !           659:
        !           660:                        uvmexp.intrs++;
        !           661:                        __asm__ volatile("":::"memory"); /* don't reorder.... */
        !           662:                        ci->ci_cpl = ocpl;
        !           663:                        __asm__ volatile("":::"memory"); /* don't reorder.... */
        !           664:                        openpic_enable_irq(realirq);
        !           665:                }
        !           666:
        !           667:                realirq = openpic_read_irq(0);
        !           668:        }
        !           669:        ppc_intr_enable(1);
        !           670:
        !           671:        splx(pcpl);     /* Process pendings. */
        !           672: }
        !           673:
        !           674: void
        !           675: openpic_init()
        !           676: {
        !           677:        int irq;
        !           678:        u_int x;
        !           679:
        !           680:        /* disable all interrupts */
        !           681:        for (irq = 0; irq < 255; irq++)
        !           682:                openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
        !           683:        openpic_set_priority(0, 15);
        !           684:
        !           685:        /* we don't need 8259 pass through mode */
        !           686:        x = openpic_read(OPENPIC_CONFIG);
        !           687:        x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
        !           688:        openpic_write(OPENPIC_CONFIG, x);
        !           689:
        !           690:        /* send all interrupts to cpu 0 */
        !           691:        for (irq = 0; irq < ICU_LEN; irq++)
        !           692:                openpic_write(OPENPIC_IDEST(irq), 1 << 0);
        !           693:        for (irq = 0; irq < ICU_LEN; irq++) {
        !           694:                x = irq;
        !           695:                x |= OPENPIC_IMASK;
        !           696:                x |= OPENPIC_POLARITY_POSITIVE;
        !           697:                x |= OPENPIC_SENSE_LEVEL;
        !           698:                x |= 8 << OPENPIC_PRIORITY_SHIFT;
        !           699:                openpic_write(OPENPIC_SRC_VECTOR(irq), x);
        !           700:        }
        !           701:
        !           702:        /* XXX set spurious intr vector */
        !           703:
        !           704:        openpic_set_priority(0, 0);
        !           705:
        !           706:        /* clear all pending interrunts */
        !           707:        for (irq = 0; irq < ICU_LEN; irq++) {
        !           708:                openpic_read_irq(0);
        !           709:                openpic_eoi(0);
        !           710:        }
        !           711:
        !           712:        for (irq = 0; irq < ICU_LEN; irq++)
        !           713:                openpic_disable_irq(irq);
        !           714:
        !           715:        install_extint(ext_intr_openpic);
        !           716: }
        !           717:
        !           718: /*
        !           719:  * programmer_button function to fix args to Debugger.
        !           720:  * deal with any enables/disables, if necessary.
        !           721:  */
        !           722: int
        !           723: openpic_prog_button (void *arg)
        !           724: {
        !           725: #ifdef DDB
        !           726:        if (db_console)
        !           727:                Debugger();
        !           728: #else
        !           729:        printf("programmer button pressed, debugger not available\n");
        !           730: #endif
        !           731:        return 1;
        !           732: }

CVSweb