[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

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