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

Annotation of sys/arch/hp300/dev/frodo.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: frodo.c,v 1.11 2007/01/14 17:54:45 miod Exp $ */
        !             2: /*     $NetBSD: frodo.c,v 1.5 1999/07/31 21:15:20 thorpej Exp $        */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Jason R. Thorpe.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *     This product includes software developed by the NetBSD
        !            22:  *     Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: /*
        !            41:  * Copyright (c) 1997 Michael Smith.  All rights reserved.
        !            42:  *
        !            43:  * Redistribution and use in source and binary forms, with or without
        !            44:  * modification, are permitted provided that the following conditions
        !            45:  * are met:
        !            46:  * 1. Redistributions of source code must retain the above copyright
        !            47:  *    notice, this list of conditions and the following disclaimer.
        !            48:  * 2. Redistributions in binary form must reproduce the above copyright
        !            49:  *    notice, this list of conditions and the following disclaimer in the
        !            50:  *    documentation and/or other materials provided with the distribution.
        !            51:  *
        !            52:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            53:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            54:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            55:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            56:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            57:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            58:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            59:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            60:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            61:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            62:  * SUCH DAMAGE.
        !            63:  */
        !            64:
        !            65: /*
        !            66:  * Support for the "Frodo" (a.k.a. "Apollo Utility") chip found
        !            67:  * in HP Apollo 9000/4xx workstations, as well as HP 9000/362 and 9000/382.
        !            68:  */
        !            69:
        !            70: #include <sys/param.h>
        !            71: #include <sys/systm.h>
        !            72: #include <sys/kernel.h>
        !            73: #include <sys/syslog.h>
        !            74: #include <sys/device.h>
        !            75:
        !            76: #include <machine/bus.h>
        !            77: #include <machine/cpu.h>
        !            78: #include <machine/intr.h>
        !            79: #include <machine/hp300spu.h>
        !            80:
        !            81: #include <hp300/dev/intiovar.h>
        !            82:
        !            83: #include <hp300/dev/frodoreg.h>
        !            84: #include <hp300/dev/frodovar.h>
        !            85:
        !            86: #include "isabr.h"
        !            87:
        !            88: #if NISABR > 0
        !            89: #include <uvm/uvm_extern.h>
        !            90:
        !            91: #include <dev/isa/isareg.h>
        !            92: #include <hp300/dev/isabrreg.h>
        !            93: #endif
        !            94:
        !            95: struct frodo_softc {
        !            96:        struct device   sc_dev;         /* generic device glue */
        !            97:        volatile u_int8_t *sc_regs;     /* register base */
        !            98:        struct isr      *sc_intr[FRODO_NINTR]; /* interrupt handlers */
        !            99:        struct isr      sc_isr;         /* main interrupt handler */
        !           100:        u_int           sc_refcnt;      /* number of interrupt refs */
        !           101: };
        !           102:
        !           103: int    frodomatch(struct device *, void *, void *);
        !           104: void   frodoattach(struct device *, struct device *, void *);
        !           105:
        !           106: int    frodoprint(void *, const char *);
        !           107: int    frodosubmatch(struct device *, void *, void *);
        !           108:
        !           109: int    frodointr(void *);
        !           110: void   frodo_imask(struct frodo_softc *, u_int16_t, u_int16_t);
        !           111: int    frodo_isa_exists(void);
        !           112: void   frodo_state(struct frodo_softc *);
        !           113:
        !           114: struct cfattach frodo_ca = {
        !           115:        sizeof(struct frodo_softc), frodomatch, frodoattach
        !           116: };
        !           117:
        !           118: struct cfdriver frodo_cd = {
        !           119:        NULL, "frodo", DV_DULL
        !           120: };
        !           121:
        !           122: struct frodo_attach_args frodo_subdevs[] = {
        !           123:        { "dnkbd",      NULL,   FRODO_APCI_OFFSET(0),   FRODO_INTR_APCI0 },
        !           124:        { "apci",       NULL,   FRODO_APCI_OFFSET(1),   FRODO_INTR_APCI1 },
        !           125:        { "apci",       NULL,   FRODO_APCI_OFFSET(2),   FRODO_INTR_APCI2 },
        !           126:        { "apci",       NULL,   FRODO_APCI_OFFSET(3),   FRODO_INTR_APCI3 },
        !           127:        { NULL,         NULL,   0,                      0 },
        !           128: };
        !           129:
        !           130: #define        FRODO_IPL       5
        !           131:
        !           132: int
        !           133: frodomatch(parent, match, aux)
        !           134:        struct device *parent;
        !           135:        void *match, *aux;
        !           136: {
        !           137:        struct intio_attach_args *ia = aux;
        !           138:        caddr_t va;
        !           139:        static int frodo_matched = 0;
        !           140:
        !           141:        /* only allow one instance */
        !           142:        if (frodo_matched)
        !           143:                return (0);
        !           144:
        !           145:        /* only specific workstations can have this */
        !           146:        switch (machineid) {
        !           147:        case HP_362:
        !           148:        case HP_382:
        !           149:        case HP_400:
        !           150:        case HP_425:
        !           151:        case HP_433:
        !           152:                break;
        !           153:
        !           154:        default:
        !           155:                return (0);
        !           156:        }
        !           157:
        !           158:        /* make sure the hardware is there in any case */
        !           159:        va = (caddr_t)IIOV(FRODO_BASE);
        !           160:        if (badaddr(va))
        !           161:                return (0);
        !           162:
        !           163:        frodo_matched = 1;
        !           164:        ia->ia_addr = (caddr_t)FRODO_BASE;
        !           165:        return (1);
        !           166: }
        !           167:
        !           168: void
        !           169: frodoattach(parent, self, aux)
        !           170:        struct device *parent, *self;
        !           171:        void *aux;
        !           172: {
        !           173:        struct frodo_softc *sc = (struct frodo_softc *)self;
        !           174:        struct intio_attach_args *ia = aux;
        !           175:        int i;
        !           176:
        !           177:        sc->sc_regs = (volatile u_int8_t *)IIOV(ia->ia_addr);
        !           178:
        !           179:        printf(" ipl %d", FRODO_IPL);
        !           180:        if ((FRODO_READ(sc, FRODO_IISR) & FRODO_IISR_SERVICE) == 0)
        !           181:                printf(": service mode enabled");
        !           182:        printf("\n");
        !           183:
        !           184:        /* Clear all of the interrupt handlers. */
        !           185:        bzero(sc->sc_intr, sizeof(sc->sc_intr));
        !           186:
        !           187:        /*
        !           188:         * Disable all of the interrupt lines; we reenable them
        !           189:         * as subdevices attach.
        !           190:         */
        !           191:        frodo_imask(sc, 0, 0xffff);
        !           192:
        !           193:        /* Clear any pending interrupts. */
        !           194:        FRODO_WRITE(sc, FRODO_PIC_PU, 0xff);
        !           195:        FRODO_WRITE(sc, FRODO_PIC_PL, 0xff);
        !           196:
        !           197:        /* Set interrupt polarities... */
        !           198:        FRODO_WRITE(sc, FRODO_PIO_IPR, 0x10);
        !           199:
        !           200:        /* ...and configure 1-5 for edge triggering. */
        !           201:        FRODO_WRITE(sc, FRODO_PIO_IELR, 0xc1);
        !           202:
        !           203:        /* Initialize IVR high half to zero so we don't need to mask it later */
        !           204:        FRODO_WRITE(sc, FRODO_PIC_IVR, 0x00);
        !           205:
        !           206:        /* Mask ISA interrupts until an ISA interrupt handler is registered. */
        !           207:        FRODO_WRITE(sc, FRODO_PIO_ISA_CONTROL, 0x80);
        !           208:
        !           209:        /*
        !           210:         * We defer hooking up our interrupt handler until
        !           211:         * a subdevice hooks up theirs.
        !           212:         */
        !           213:        sc->sc_refcnt = 0;
        !           214:
        !           215:        /* ... and attach subdevices. */
        !           216:        for (i = 0; frodo_subdevs[i].fa_name != NULL; i++) {
        !           217:                /*
        !           218:                 * Skip the first serial port if we're not a 425e;
        !           219:                 * it's mapped to the DCA at select code 9 on all
        !           220:                 * other models.
        !           221:                 */
        !           222:                if (frodo_subdevs[i].fa_offset == FRODO_APCI_OFFSET(1) &&
        !           223:                    mmuid != MMUID_425_E)
        !           224:                        continue;
        !           225:                frodo_subdevs[i].fa_tag = ia->ia_tag;
        !           226:                config_found_sm(self, &frodo_subdevs[i],
        !           227:                    frodoprint, frodosubmatch);
        !           228:        }
        !           229:
        !           230: #if NISABR > 0
        !           231:        /*
        !           232:         * Only attempt to attach the isa bridge if it exists on this
        !           233:         * machine.
        !           234:         */
        !           235:        if (frodo_isa_exists()) {
        !           236:                struct frodo_attach_args fa;
        !           237:
        !           238:                fa.fa_name = "isabr";
        !           239:                fa.fa_tag = ia->ia_tag;
        !           240:                fa.fa_offset = fa.fa_line = 0;
        !           241:                config_found_sm(self, &fa, frodoprint, frodosubmatch);
        !           242:        }
        !           243: #endif
        !           244: }
        !           245:
        !           246: int
        !           247: frodosubmatch(parent, match, aux)
        !           248:        struct device *parent;
        !           249:        void *match, *aux;
        !           250: {
        !           251:        struct cfdata *cf = match;
        !           252:        struct frodo_attach_args *fa = aux;
        !           253:
        !           254:        if (cf->frodocf_offset != FRODO_UNKNOWN_OFFSET &&
        !           255:            cf->frodocf_offset != fa->fa_offset)
        !           256:                return (0);
        !           257:
        !           258:        return ((*cf->cf_attach->ca_match)(parent, cf, aux));
        !           259: }
        !           260:
        !           261: int
        !           262: frodoprint(aux, pnp)
        !           263:        void *aux;
        !           264:        const char *pnp;
        !           265: {
        !           266:        struct frodo_attach_args *fa = aux;
        !           267:
        !           268:        if (pnp)
        !           269:                printf("%s at %s", fa->fa_name, pnp);
        !           270:        printf(" offset 0x%x", fa->fa_offset);
        !           271:        return (UNCONF);
        !           272: }
        !           273:
        !           274: int
        !           275: frodo_intr_establish(struct device *frdev, int line, struct isr *isr,
        !           276:     const char *name)
        !           277: {
        !           278:        struct frodo_softc *sc = (struct frodo_softc *)frdev;
        !           279:        int priority = isr->isr_priority;
        !           280:
        !           281:        if (line <= 0 || line >= FRODO_NINTR) {
        !           282:                panic("%s: bad interrupt line %d",
        !           283:                    sc->sc_dev.dv_xname, line);
        !           284:        }
        !           285:        if (sc->sc_intr[line] != NULL) {
        !           286: #ifdef DEBUG
        !           287:                printf("%s: interrupt line %d already used\n",
        !           288:                    sc->sc_dev.dv_xname, line);
        !           289: #endif
        !           290:                return (EPERM);
        !           291:        }
        !           292:
        !           293:        /*
        !           294:         * If this is the first one, establish the frodo
        !           295:         * interrupt handler.  If not, reestablish at a
        !           296:         * higher priority if necessary.
        !           297:         */
        !           298:        if (sc->sc_isr.isr_priority < priority) {
        !           299:                if (sc->sc_refcnt != 0)
        !           300:                        intr_disestablish(&sc->sc_isr);
        !           301:                sc->sc_isr.isr_func = frodointr;
        !           302:                sc->sc_isr.isr_arg = sc;
        !           303:                sc->sc_isr.isr_ipl = FRODO_IPL;
        !           304:                sc->sc_isr.isr_priority = priority;
        !           305:                intr_establish(&sc->sc_isr, sc->sc_dev.dv_xname);
        !           306:        }
        !           307:
        !           308:        sc->sc_refcnt++;
        !           309:
        !           310:        /* Install the handler. */
        !           311:        isr->isr_ipl = sc->sc_isr.isr_ipl;
        !           312:        evcount_attach(&isr->isr_count, name, &isr->isr_ipl, &evcount_intr);
        !           313:        sc->sc_intr[line] = isr;
        !           314:
        !           315:        /* Enable the interrupt line. */
        !           316:        frodo_imask(sc, FRODO_INTR_BIT(line), 0);
        !           317:
        !           318: #if NISABR > 0
        !           319:        /* Unmask ISA interrupts if necessary. */
        !           320:        if (FRODO_INTR_ISA(line))
        !           321:                FRODO_WRITE(sc, FRODO_PIO_ISA_CONTROL, 0x00);
        !           322: #endif
        !           323:
        !           324:        return (0);
        !           325: }
        !           326:
        !           327: void
        !           328: frodo_intr_disestablish(frdev, line)
        !           329:        struct device *frdev;
        !           330:        int line;
        !           331: {
        !           332:        struct frodo_softc *sc = (struct frodo_softc *)frdev;
        !           333:        int newpri;
        !           334:
        !           335: #ifdef DIAGNOSTIC
        !           336:        if (sc->sc_intr[line] == NULL) {
        !           337:                printf("%s(%s): no handler for line %d",
        !           338:                    sc->sc_dev.dv_xname, __func__, line);
        !           339:                return;
        !           340:        }
        !           341: #endif
        !           342:
        !           343:        sc->sc_intr[line] = NULL;
        !           344:        frodo_imask(sc, 0, FRODO_INTR_BIT(line));
        !           345:
        !           346: #if NISABR > 0
        !           347:        /* Mask ISA interrupts if necessary. */
        !           348:        if (FRODO_INTR_ISA(line)) {
        !           349:                if (sc->sc_intr[FRODO_INTR_ILOW] == NULL &&
        !           350:                    sc->sc_intr[FRODO_INTR_IMID] == NULL &&
        !           351:                    sc->sc_intr[FRODO_INTR_IHI] == NULL)
        !           352:                        FRODO_WRITE(sc, FRODO_PIO_ISA_CONTROL, 0x80);
        !           353:        }
        !           354: #endif
        !           355:
        !           356:        /* If this was the last, unhook ourselves. */
        !           357:        if (sc->sc_refcnt-- == 1) {
        !           358:                intr_disestablish(&sc->sc_isr);
        !           359:                return;
        !           360:        }
        !           361:
        !           362:        /* Lower our priority, if appropriate. */
        !           363:        for (newpri = 0, line = 0; line < FRODO_NINTR; line++)
        !           364:                if (sc->sc_intr[line] != NULL &&
        !           365:                    sc->sc_intr[line]->isr_priority > newpri)
        !           366:                        newpri = sc->sc_intr[line]->isr_priority;
        !           367:
        !           368:        if (newpri != sc->sc_isr.isr_priority) {
        !           369:                intr_disestablish(&sc->sc_isr);
        !           370:                sc->sc_isr.isr_func = frodointr;
        !           371:                sc->sc_isr.isr_arg = sc;
        !           372:                sc->sc_isr.isr_ipl = FRODO_IPL;
        !           373:                sc->sc_isr.isr_priority = newpri;
        !           374:                intr_establish(&sc->sc_isr, sc->sc_dev.dv_xname);
        !           375:        }
        !           376: }
        !           377:
        !           378: int
        !           379: frodointr(arg)
        !           380:        void *arg;
        !           381: {
        !           382:        struct frodo_softc *sc = arg;
        !           383:        struct isr *fisr;
        !           384:        int pending, line, rc = 0;
        !           385:
        !           386: #ifdef DEBUG
        !           387:        frodo_state(sc);
        !           388: #endif
        !           389:
        !           390:        /* Any interrupts pending? */
        !           391:        while ((pending = FRODO_GETPEND(sc)) != 0) {
        !           392:                rc++;
        !           393:
        !           394:                /*
        !           395:                 * Get pending interrupt; this also clears it for us.
        !           396:                 */
        !           397:                line = FRODO_READ(sc, FRODO_PIC_ACK) /* & 0x0f */;
        !           398:
        !           399:                fisr = sc->sc_intr[line];
        !           400:                if (fisr == NULL) {
        !           401:                        printf("%s: unhandled interrupt on line %d\n",
        !           402:                            sc->sc_dev.dv_xname, line);
        !           403: #ifdef DEBUG
        !           404:                        /* Disable interrupt source */
        !           405:                        frodo_imask(sc, 0, FRODO_INTR_BIT(line));
        !           406: #endif
        !           407:                } else {
        !           408:                        if ((*fisr->isr_func)(fisr->isr_arg) != 0) {
        !           409:                                fisr->isr_count.ec_count++;
        !           410:                        } else {
        !           411:                                printf("%s: spurious interrupt on line %d\n",
        !           412:                                    sc->sc_dev.dv_xname, line);
        !           413:                        }
        !           414:                }
        !           415:
        !           416:                if (rc > 100)
        !           417:                        panic("frodointr: looping, pending %x line %d fisr %p",
        !           418:                            pending, line, fisr);
        !           419:
        !           420: #ifdef DEBUG
        !           421:                frodo_state(sc);
        !           422: #endif
        !           423:        }
        !           424:
        !           425:        return (rc);
        !           426: }
        !           427:
        !           428: void
        !           429: frodo_imask(sc, set, clear)
        !           430:        struct frodo_softc *sc;
        !           431:        u_int16_t set, clear;
        !           432: {
        !           433:        u_int16_t imask;
        !           434:
        !           435:        imask = FRODO_GETMASK(sc);
        !           436:
        !           437:        imask |= set;
        !           438:        imask &= ~clear;
        !           439:
        !           440:        FRODO_SETMASK(sc, imask);
        !           441: }
        !           442:
        !           443: #ifdef DEBUG
        !           444: void
        !           445: frodo_state(struct frodo_softc *sc)
        !           446: {
        !           447:        int i;
        !           448:
        !           449:        printf("%s state:", sc->sc_dev.dv_xname);
        !           450:        for (i = 0xc0; i < 0x100; i += 4) {
        !           451:                printf(" %02x", FRODO_READ(sc, i));
        !           452:                if (i == 0xcc || i == 0xdc || i == 0xec)
        !           453:                        printf(" /");
        !           454:        }
        !           455:        printf("\n");
        !           456: }
        !           457: #endif
        !           458:
        !           459: #if NISABR > 0
        !           460: int
        !           461: frodo_isa_exists()
        !           462: {
        !           463:        vaddr_t va;
        !           464:        int rv;
        !           465:
        !           466:        va = uvm_km_valloc(kernel_map, PAGE_SIZE);
        !           467:        if (va == NULL)
        !           468:                return (0);
        !           469:
        !           470:        /*
        !           471:         * Check that the iomem space answers probes
        !           472:         */
        !           473:        pmap_kenter_cache(va, ISABR_IOMEM_BASE, PG_RW | PG_CI);
        !           474:        pmap_update(pmap_kernel());
        !           475:        rv = badbaddr((caddr_t)va);
        !           476:        pmap_kremove(va, PAGE_SIZE);
        !           477:        pmap_update(pmap_kernel());
        !           478:
        !           479:        /*
        !           480:         * Check that the ioport space answers probes
        !           481:         */
        !           482:        pmap_kenter_cache(va, ISABR_IOPORT_BASE, PG_RW | PG_CI);
        !           483:        pmap_update(pmap_kernel());
        !           484:        rv |= badbaddr((caddr_t)va);
        !           485:        pmap_kremove(va, PAGE_SIZE);
        !           486:        pmap_update(pmap_kernel());
        !           487:
        !           488:        uvm_km_free(kernel_map, va, PAGE_SIZE);
        !           489:
        !           490:        return (!rv);
        !           491: }
        !           492: #endif

CVSweb