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

Annotation of sys/arch/sparc/dev/fga.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: fga.c,v 1.15 2006/02/22 22:32:12 miod Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
                      5:  * All rights reserved.
                      6:  *
                      7:  * This software was developed by Jason L. Wright under contract with
                      8:  * RTMX Incorporated (http://www.rtmx.com).
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     21:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     22:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     23:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     24:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     25:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     27:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     28:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
                     33:  * Driver for the Force Gate Array 5000 (VME/SBus bridge) found
                     34:  * on FORCE CPU-5V boards.
                     35:  */
                     36:
                     37: #include <sys/param.h>
                     38: #include <sys/systm.h>
                     39: #include <sys/kernel.h>
                     40: #include <sys/errno.h>
                     41: #include <sys/ioctl.h>
                     42: #include <sys/syslog.h>
                     43: #include <sys/device.h>
                     44: #include <sys/malloc.h>
                     45: #include <uvm/uvm_extern.h>
                     46: #include <machine/pmap.h>
                     47:
                     48: #include <machine/autoconf.h>
                     49: #include <sparc/cpu.h>
                     50: #include <sparc/sparc/cpuvar.h>
                     51: #include <sparc/dev/sbusvar.h>
                     52: #include <sparc/dev/dmareg.h>  /* for SBUS_BURST_* */
                     53:
                     54: #include <sparc/dev/fgareg.h>
                     55: #include <sparc/dev/fgavar.h>
                     56: #include <machine/fgaio.h>
                     57:
                     58: int    fgamatch(struct device *, void *, void *);
                     59: void   fgaattach(struct device *, struct device *, void *);
                     60: int    fvmematch(struct device *, void *, void *);
                     61: void   fvmeattach(struct device *, struct device *, void *);
                     62: int    fgaprint(void *, const char *);
                     63: int    fvmeprint(void *, const char *);
                     64: int    fvmescan(struct device *parent, void *, void *);
                     65:
                     66: struct fga_softc {
                     67:        struct          device sc_dev;          /* base device */
                     68:        int             sc_node;                /* prom node */
                     69:        struct          fga_regs *sc_regs;      /* registers */
                     70:        struct          intrhand sc_ih1;        /* level 1 handler */
                     71:        struct          intrhand sc_ih2;        /* level 2 handler */
                     72:        struct          intrhand sc_ih3;        /* level 3 handler */
                     73:        struct          intrhand sc_ih4;        /* level 4 handler */
                     74:        struct          intrhand sc_ih5;        /* level 5 handler */
                     75:        struct          intrhand sc_ih6;        /* level 6 handler */
                     76:        struct          intrhand sc_ih7;        /* level 7 handler */
                     77:        struct          intrhand **sc_vmevec;   /* vectored handlers */
                     78: #ifdef DDB
                     79:        int             sc_abort;               /* abort switch enabled? */
                     80: #endif
                     81:        int             sc_nrange;              /* number of sbus ranges */
                     82:        struct          rom_range *sc_range;    /* sbus range data */
                     83:        u_int8_t        sc_established;         /* which hw intrs installed */
                     84: };
                     85:
                     86: int    fgaopen(dev_t, int, int, struct proc *);
                     87: int    fgaclose(dev_t, int, int, struct proc *);
                     88: int    fgaioctl(dev_t, u_long, caddr_t, int, struct proc *);
                     89:
                     90: int    fga_vmerangemap(struct fga_softc *, u_int32_t, u_int32_t,
                     91:     int, int, u_int32_t, struct confargs *);
                     92: int    fga_intr_establish(struct fga_softc *, int, int,
                     93:     struct intrhand *, const char *);
                     94: int    fga_hwintr_establish(struct fga_softc *, u_int8_t);
                     95:
                     96: int    fga_hwintr1(void *);
                     97: int    fga_hwintr2(void *);
                     98: int    fga_hwintr3(void *);
                     99: int    fga_hwintr4(void *);
                    100: int    fga_hwintr5(void *);
                    101: int    fga_hwintr6(void *);
                    102: int    fga_hwintr7(void *);
                    103: int    fga_intrvec(struct fga_softc *, int);
                    104:
                    105: struct cfattach fga_ca = {
                    106:        sizeof (struct fga_softc), fgamatch, fgaattach
                    107: };
                    108:
                    109: struct cfdriver fga_cd = {
                    110:        NULL, "fga", DV_DULL
                    111: };
                    112:
                    113: struct fvme_softc {
                    114:        struct          device sc_dv;
                    115:        u_int32_t       sc_vmeoffset;           /* vme range offset */
                    116:        u_int32_t       sc_len;                 /* length of range */
                    117:        u_int32_t       sc_sbusoffset;          /* sbus phys address */
                    118:        u_int32_t       sc_type;                /* amcode type */
                    119: };
                    120:
                    121: struct cfattach fvme_ca = {
                    122:        sizeof (struct fvme_softc), fvmematch, fvmeattach
                    123: };
                    124:
                    125: struct cfdriver fvme_cd = {
                    126:        NULL, "fvme", DV_DULL
                    127: };
                    128:
                    129: int
                    130: fgamatch(parent, vcf, aux)
                    131:        struct device *parent;
                    132:        void *vcf, *aux;
                    133: {
                    134:        struct confargs *ca = aux;
                    135:        struct romaux *ra = &ca->ca_ra;
                    136:
                    137:        if (strcmp("VME", ra->ra_name))
                    138:                return (0);
                    139:        return (1);
                    140: }
                    141:
                    142: void
                    143: fgaattach(parent, self, aux)
                    144:        struct device *parent, *self;
                    145:        void *aux;
                    146: {
                    147:        struct confargs *ca = aux, oca;
                    148:        struct fga_softc *sc = (struct fga_softc *)self;
                    149:        char *s;
                    150:        int i, rlen;
                    151:
                    152:        if (sc->sc_dev.dv_unit > 0) {
                    153:                printf(" unsupported\n");
                    154:                return;
                    155:        }
                    156:
                    157:        /* map registers */
                    158:        if (ca->ca_ra.ra_nreg != 1) {
                    159:                printf(": expected 1 register, got %d\n", ca->ca_ra.ra_nreg);
                    160:                return;
                    161:        }
                    162:        sc->sc_regs = mapiodev(&(ca->ca_ra.ra_reg[0]), 0,
                    163:            ca->ca_ra.ra_reg[0].rr_len);
                    164:
                    165:        sc->sc_node = ca->ca_ra.ra_node;
                    166:
                    167:        i = opennode("/iommu/sbus");
                    168:        if (i == 0) {
                    169:                printf(": no iommu or sbus found, unconfigured\n");
                    170:                return;
                    171:        }
                    172:        rlen = getproplen(i, "ranges");
                    173:        sc->sc_range =
                    174:            (struct rom_range *)malloc(rlen, M_DEVBUF, M_NOWAIT);
                    175:        if (sc->sc_range == NULL) {
                    176:                printf(": PROM ranges too large: %d\n", rlen);
                    177:                return;
                    178:        }
                    179:        sc->sc_nrange = rlen / sizeof(struct rom_range);
                    180:        (void)getprop(i, "ranges", sc->sc_range, rlen);
                    181:
                    182:        s = getpropstring(sc->sc_node, "model");
                    183:        printf(": model %s id %c%c%c\n", s,
                    184:            sc->sc_regs->id[0], sc->sc_regs->id[1], sc->sc_regs->id[2]);
                    185:
                    186:        /*
                    187:         * The prom leaves at least one of the ranges "on", so make sure
                    188:         * they are all off.
                    189:         */
                    190:        for (i = 0; i < 16; i++)
                    191:                sc->sc_regs->vme_range[i] |= VME_RANGE_DECEN;
                    192:
                    193:        sc->sc_regs->sbus_ssel[0] &= ~(SBUS_SSEL_Y);
                    194:        sc->sc_regs->sbus_ssel[0] |= SBUS_SSEL_Y_SLOT4;
                    195:        sc->sc_regs->sbus_ssel[1] &= ~(SBUS_SSEL_X | SBUS_SSEL_Y);
                    196:        sc->sc_regs->sbus_ssel[1] |= SBUS_SSEL_X_SLOT5 | SBUS_SSEL_Y_SLOT5;
                    197:        sc->sc_regs->sbus_ssel[2] &= ~(SBUS_SSEL_X | SBUS_SSEL_Y);
                    198:        sc->sc_regs->sbus_ssel[2] |= SBUS_SSEL_X_SLOT5 | SBUS_SSEL_Y_SLOT1;
                    199:        sc->sc_regs->sbus_ssel[3] &= ~(SBUS_SSEL_X | SBUS_SSEL_Y);
                    200:        sc->sc_regs->sbus_ssel[3] |= SBUS_SSEL_X_SLOT1 | SBUS_SSEL_Y_SLOT1;
                    201:
                    202:        /*
                    203:         * Map and attach vme<->sbus master ranges
                    204:         */
                    205:        fga_vmerangemap(sc, 0xf0000000, 0x10000000,
                    206:            VME_MASTER_CAP_D32 | VME_MASTER_CAP_A32, 1, 0, &oca);
                    207:        fga_vmerangemap(sc, 0xf0000000, 0x10000000,
                    208:            VME_MASTER_CAP_D16 | VME_MASTER_CAP_A32, 4, 0, &oca);
                    209:        fga_vmerangemap(sc, 0x00000000, 0x01000000,
                    210:            VME_MASTER_CAP_D16 | VME_MASTER_CAP_A24, 5, 0xe000000, &oca);
                    211:        fga_vmerangemap(sc, 0x00000000, 0x00010000,
                    212:            VME_MASTER_CAP_D8 | VME_MASTER_CAP_A16, 5, 0x0ffc0000, &oca);
                    213:        fga_vmerangemap(sc, 0x00000000, 0x00010000,
                    214:            VME_MASTER_CAP_D16 | VME_MASTER_CAP_A16, 5, 0x0ffd0000, &oca);
                    215:        fga_vmerangemap(sc, 0x00000000, 0x00010000,
                    216:            VME_MASTER_CAP_D32 | VME_MASTER_CAP_A16, 5, 0x0ffe0000, &oca);
                    217:
                    218: #ifdef DDB
                    219:        s = getpropstring(optionsnode, "abort-ena?");
                    220:        if (s && strcmp(s, "true") == 0) {
                    221:                sc->sc_abort = 1;
                    222:                fga_hwintr_establish(sc, IRQ_MAP_SINT7);
                    223:                sc->sc_regs->abort_irq_map &= ~IRQ_MAP_INT_MASK;
                    224:                sc->sc_regs->abort_irq_map |= IRQ_MAP_SINT7;
                    225:                sc->sc_regs->abort_irq_map &= ~IRQ_MAP_ENABLE;
                    226:        }
                    227: #endif
                    228: }
                    229:
                    230: int
                    231: fgaprint(args, name)
                    232:        void *args;
                    233:        const char *name;
                    234: {
                    235:        struct confargs *ca = args;
                    236:
                    237:        if (name)
                    238:                printf("%s at %s", ca->ca_ra.ra_name, name);
                    239:        printf(" slot %d addr 0x%x", ca->ca_slot, ca->ca_offset);
                    240:        return (UNCONF);
                    241: }
                    242:
                    243: /*
                    244:  * Map a region of VME space to a sbus slot/offset.
                    245:  */
                    246: int
                    247: fga_vmerangemap(sc, vmebase, vmelen, vmecap, sbusslot, sbusoffset, oca)
                    248:        struct fga_softc *sc;
                    249:        u_int32_t vmebase, vmelen;
                    250:        int vmecap;
                    251:        int sbusslot;
                    252:        u_int32_t sbusoffset;
                    253:        struct confargs *oca;
                    254: {
                    255:        struct fga_regs *regs = sc->sc_regs;
                    256:        u_int32_t rval;
                    257:        u_int8_t sval;
                    258:        int range, i, srange;
                    259:
                    260:        for (i = 0; i < FVME_MAX_RANGES; i++) {
                    261:                if (regs->vme_range[i] & VME_RANGE_DECEN)
                    262:                        break;
                    263:        }
                    264:        if (i == FVME_MAX_RANGES)
                    265:                return (-1);
                    266:        range = i;
                    267:
                    268:        for (srange = 0; srange < sc->sc_nrange; srange++) {
                    269:                if (sbusslot == sc->sc_range[srange].cspace)
                    270:                        break;
                    271:        }
                    272:        if (srange == sc->sc_nrange)
                    273:                return (-1);
                    274:
                    275:        bzero(oca, sizeof(*oca));
                    276:        oca->ca_bustype = BUS_FGA;
                    277:        oca->ca_slot = sbusslot;
                    278:        oca->ca_offset = sc->sc_range[srange].poffset | sbusoffset;
                    279:        oca->ca_ra.ra_name = "fvme";
                    280:        oca->ca_ra.ra_nreg = 2;
                    281:        oca->ca_ra.ra_reg[0].rr_len = vmelen;
                    282:        oca->ca_ra.ra_reg[0].rr_paddr =
                    283:            (void *)(sc->sc_range[srange].poffset | sbusoffset);
                    284:        oca->ca_ra.ra_reg[0].rr_iospace = sbusslot;
                    285:        oca->ca_ra.ra_reg[1].rr_iospace = vmecap;
                    286:        oca->ca_ra.ra_reg[1].rr_paddr = (void *)vmebase;
                    287:        oca->ca_ra.ra_reg[1].rr_len = vmelen;
                    288:
                    289:        /* 1. Setup slot select register for this range. */
                    290:        switch (sbusslot) {
                    291:        case 1:
                    292:                sval = SBUS_SSEL_Y_SLOT1;
                    293:                break;
                    294:        case 2:
                    295:                sval = SBUS_SSEL_Y_SLOT2;
                    296:                break;
                    297:        case 3:
                    298:                sval = SBUS_SSEL_Y_SLOT3;
                    299:                break;
                    300:        case 4:
                    301:                sval = SBUS_SSEL_Y_SLOT4;
                    302:                break;
                    303:        case 5:
                    304:                sval = SBUS_SSEL_Y_SLOT5;
                    305:                break;
                    306:        default:
                    307:                return (-1);
                    308:        }
                    309:
                    310:        if (range & 1) {
                    311:                regs->sbus_ssel[range >> 1] &= ~SBUS_SSEL_Y;
                    312:                regs->sbus_ssel[range >> 1] |= sval;
                    313:        } else {
                    314:                regs->sbus_ssel[range >> 1] &= ~SBUS_SSEL_X;
                    315:                regs->sbus_ssel[range >> 1] |= sval << 4;
                    316:        }
                    317:
                    318:        /* 2. Setup and enable the VME master range. */
                    319:        rval = regs->vme_range[range];
                    320:        rval &= ~(VME_RANGE_VMAE | VME_RANGE_VMAT);
                    321:        rval |= (vmebase >> 13) & (VME_RANGE_VMAE | VME_RANGE_VMAT);
                    322:        rval &= ~VME_RANGE_VMRCC;
                    323:        rval |= ((sbusoffset << 4) | (vmelen << 3)) & VME_RANGE_VMRCC;
                    324:        rval &= ~VME_RANGE_DECEN;
                    325:        regs->vme_range[range] = rval;
                    326:
                    327:        /* 3. Setup addr/data capabilities for the range. */
                    328:        regs->vme_master_cap[range] &=
                    329:            ~(VME_MASTER_CAP_DATA | VME_MASTER_CAP_ADDR);
                    330:        regs->vme_master_cap[range] |= vmecap;
                    331:
                    332:        (void)config_found(&sc->sc_dev, oca, fgaprint);
                    333:
                    334:        return (0);
                    335: }
                    336:
                    337: int
                    338: fga_hwintr1(v)
                    339:        void *v;
                    340: {
                    341:        struct fga_softc *sc = v;
                    342:        struct fga_regs *regs = sc->sc_regs;
                    343:        u_int32_t bits = 0, stat;
                    344:        int r = 0, s;
                    345:
                    346:        s = splhigh();
                    347:        stat = regs->intr_stat;
                    348:        splx(s);
                    349:
                    350:        if ((stat & INTR_STAT_VMEIRQ1) == 0) {
                    351:                bits |= INTR_STAT_VMEIRQ1;
                    352:                r |= fga_intrvec(sc, regs->viack_emu1);
                    353:        }
                    354:
                    355:        s = splhigh();
                    356:        regs->intr_stat &= ~bits;
                    357:        splx(s);
                    358:
                    359:        return (r);
                    360: }
                    361:
                    362: int
                    363: fga_hwintr2(v)
                    364:        void *v;
                    365: {
                    366:        struct fga_softc *sc = v;
                    367:        struct fga_regs *regs = sc->sc_regs;
                    368:        int r = 0;
                    369:
                    370:        if ((regs->intr_stat & INTR_STAT_VMEIRQ2) == 0)
                    371:                r |= fga_intrvec(sc, regs->viack_emu2);
                    372:
                    373:        return (r);
                    374: }
                    375:
                    376: int
                    377: fga_hwintr3(v)
                    378:        void *v;
                    379: {
                    380:        struct fga_softc *sc = v;
                    381:        struct fga_regs *regs = sc->sc_regs;
                    382:        int r = 0;
                    383:
                    384:        /* vme irq 3 */
                    385:        if ((regs->intr_stat & INTR_STAT_VMEIRQ3) == 0)
                    386:                r |= fga_intrvec(sc, regs->viack_emu3);
                    387:
                    388:        return (r);
                    389: }
                    390:
                    391: int
                    392: fga_hwintr4(v)
                    393:        void *v;
                    394: {
                    395:        struct fga_softc *sc = v;
                    396:        struct fga_regs *regs = sc->sc_regs;
                    397:        int r = 0;
                    398:
                    399:        if ((regs->intr_stat & INTR_STAT_VMEIRQ4) == 0)
                    400:                r |= fga_intrvec(sc, regs->viack_emu4);
                    401:
                    402:        return (r);
                    403: }
                    404:
                    405: int
                    406: fga_hwintr5(v)
                    407:        void *v;
                    408: {
                    409:        struct fga_softc *sc = v;
                    410:        struct fga_regs *regs = sc->sc_regs;
                    411:        int r = 0;
                    412:
                    413:        if ((regs->intr_stat & INTR_STAT_VMEIRQ5) == 0)
                    414:                r |= fga_intrvec(sc, regs->viack_emu5);
                    415:
                    416:        return (r);
                    417: }
                    418:
                    419: int
                    420: fga_hwintr6(v)
                    421:        void *v;
                    422: {
                    423:        struct fga_softc *sc = v;
                    424:        struct fga_regs *regs = sc->sc_regs;
                    425:        int r = 0;
                    426:
                    427:        if ((regs->intr_stat & INTR_STAT_VMEIRQ6) == 0)
                    428:                r |= fga_intrvec(sc, regs->viack_emu6);
                    429:
                    430:        return (r);
                    431: }
                    432:
                    433: int
                    434: fga_hwintr7(v)
                    435:        void *v;
                    436: {
                    437:        struct fga_softc *sc = v;
                    438:        struct fga_regs *regs = sc->sc_regs;
                    439:        int r = 0, s;
                    440:        u_int32_t bits = 0, stat;
                    441:
                    442:        s = splhigh();
                    443:        stat = regs->intr_stat;
                    444:        splx(s);
                    445:
                    446: #ifdef DDB
                    447:        if (sc->sc_abort && (stat & INTR_STAT_ABORT) == 0) {
                    448:                bits |= INTR_STAT_ABORT;
                    449:                r |= 1;
                    450:                Debugger();
                    451:        }
                    452: #endif
                    453:
                    454:        if ((regs->intr_stat & INTR_STAT_VMEIRQ7) == 0) {
                    455:                bits |= INTR_STAT_VMEIRQ7;
                    456:                r |= fga_intrvec(sc, regs->viack_emu7);
                    457:        }
                    458:
                    459:        s = splhigh();
                    460:        regs->intr_stat &= ~bits;
                    461:        splx(s);
                    462:
                    463:        return (r);
                    464: }
                    465:
                    466: /*
                    467:  * Handle a VME vectored interrupt.
                    468:  */
                    469: int
                    470: fga_intrvec(sc, vec)
                    471:        struct fga_softc *sc;
                    472:        u_int8_t vec;
                    473: {
                    474:        struct intrhand *ih;
                    475:        int r, s = 0;
                    476:
                    477:        if (sc->sc_vmevec == NULL)
                    478:                return (0);
                    479:
                    480:        for (ih = sc->sc_vmevec[vec]; ih; ih = ih->ih_next) {
                    481:                r = (*ih->ih_fun)(ih->ih_arg);
                    482:                if (r > 0) {
                    483:                        ih->ih_count.ec_count++;
                    484:                        return (r);
                    485:                }
                    486:                s |= r;
                    487:        }
                    488:
                    489:        return (s);
                    490: }
                    491:
                    492: /*
                    493:  * Establish a VME level/vector interrupt.
                    494:  */
                    495: int
                    496: fga_intr_establish(sc, vec, level, ih, name)
                    497:        struct fga_softc *sc;
                    498:        int vec, level;
                    499:        struct intrhand *ih;
                    500:        const char *name;
                    501: {
                    502:        struct intrhand *ihs;
                    503:        const u_int8_t level_to_sint[] = {
                    504:                IRQ_MAP_INT,
                    505:                IRQ_MAP_SINT1,
                    506:                IRQ_MAP_SINT2,
                    507:                IRQ_MAP_SINT3,
                    508:                IRQ_MAP_SINT4,
                    509:                IRQ_MAP_SINT5,
                    510:                IRQ_MAP_SINT6,
                    511:                IRQ_MAP_SINT7
                    512:        };
                    513:        const u_int8_t level_to_irqmap[] = {0xff, 6, 5, 4, 3, 2, 1, 0};
                    514:
                    515: #ifdef DIAGNOSTIC
                    516:        if (level < 1 || level > 7)
                    517:                panic("fga_level");
                    518: #endif
                    519:
                    520:        /* setup vector handler */
                    521:        if (sc->sc_vmevec == NULL) {
                    522:                sc->sc_vmevec = (struct intrhand **)malloc(256 *
                    523:                    sizeof(struct intrhand *), M_DEVBUF, M_NOWAIT);
                    524:                if (sc->sc_vmevec == NULL)
                    525:                        panic("fga_addirq");
                    526:                bzero(sc->sc_vmevec, 256 * sizeof(struct intrhand *));
                    527:        }
                    528:        if (sc->sc_vmevec[vec] == NULL)
                    529:                sc->sc_vmevec[vec] = ih;
                    530:        else {
                    531:                ihs = sc->sc_vmevec[vec];
                    532:                while (ihs->ih_next)
                    533:                        ihs = ihs->ih_next;
                    534:                ih->ih_next = ih;
                    535:        }
                    536:
                    537:        ih->ih_vec = level;
                    538:        evcount_attach(&ih->ih_count, name, &ih->ih_vec, &evcount_intr);
                    539:
                    540:        /* setup hardware handler */
                    541:        fga_hwintr_establish(sc, level_to_sint[level]);
                    542:
                    543:        /* setup/enable vme -> sbus irq mapping */
                    544:        sc->sc_regs->virq_map[level_to_irqmap[level]] &= ~IRQ_MAP_INT_MASK;
                    545:        sc->sc_regs->virq_map[level_to_irqmap[level]] |= level_to_sint[level];
                    546:        sc->sc_regs->virq_map[level_to_irqmap[level]] &= ~IRQ_MAP_ENABLE;
                    547:
                    548:        return (0);
                    549: }
                    550:
                    551: /*
                    552:  * Establish a hardware interrupt, making sure we're not there already.
                    553:  */
                    554: int
                    555: fga_hwintr_establish(sc, sint)
                    556:        struct fga_softc *sc;
                    557:        u_int8_t sint;
                    558: {
                    559:        const int sint_to_pri[] = {0, 2, 3, 5, 6, 7, 8, 9};
                    560:
                    561:        if (sc->sc_established & (1 << sint))
                    562:                return (0);
                    563:
                    564:        switch (sint) {
                    565:        case 1:
                    566:                sc->sc_ih1.ih_fun = fga_hwintr1;
                    567:                sc->sc_ih1.ih_arg = sc;
                    568:                intr_establish(sint_to_pri[sint], &sc->sc_ih1, -1, NULL);
                    569:                break;
                    570:        case 2:
                    571:                sc->sc_ih2.ih_fun = fga_hwintr2;
                    572:                sc->sc_ih2.ih_arg = sc;
                    573:                intr_establish(sint_to_pri[sint], &sc->sc_ih2, -1, NULL);
                    574:                break;
                    575:        case 3:
                    576:                sc->sc_ih3.ih_fun = fga_hwintr3;
                    577:                sc->sc_ih3.ih_arg = sc;
                    578:                intr_establish(sint_to_pri[sint], &sc->sc_ih3, -1, NULL);
                    579:                break;
                    580:        case 4:
                    581:                sc->sc_ih4.ih_fun = fga_hwintr4;
                    582:                sc->sc_ih4.ih_arg = sc;
                    583:                intr_establish(sint_to_pri[sint], &sc->sc_ih4, -1, NULL);
                    584:                break;
                    585:        case 5:
                    586:                sc->sc_ih5.ih_fun = fga_hwintr5;
                    587:                sc->sc_ih5.ih_arg = sc;
                    588:                intr_establish(sint_to_pri[sint], &sc->sc_ih5, -1, NULL);
                    589:                break;
                    590:        case 6:
                    591:                sc->sc_ih6.ih_fun = fga_hwintr6;
                    592:                sc->sc_ih6.ih_arg = sc;
                    593:                intr_establish(sint_to_pri[sint], &sc->sc_ih6, -1, NULL);
                    594:                break;
                    595:        case 7:
                    596:                sc->sc_ih7.ih_fun = fga_hwintr7;
                    597:                sc->sc_ih7.ih_arg = sc;
                    598:                intr_establish(sint_to_pri[sint], &sc->sc_ih7, -1, NULL);
                    599:                break;
                    600: #ifdef DIAGNOSTIC
                    601:        default:
                    602:                panic("fga_sint");
                    603: #endif
                    604:        }
                    605:
                    606:        sc->sc_established |= 1 << sint;
                    607:        return (0);
                    608: }
                    609:
                    610: int
                    611: fgaopen(dev, flags, mode, p)
                    612:        dev_t dev;
                    613:        int flags, mode;
                    614:        struct proc *p;
                    615: {
                    616:        struct fga_softc *sc;
                    617:
                    618:        if (fga_cd.cd_ndevs == 0)
                    619:                return (ENXIO);
                    620:        sc = fga_cd.cd_devs[0];
                    621:        if (sc == NULL)
                    622:                return (ENXIO);
                    623:        return (0);
                    624: }
                    625:
                    626: int
                    627: fgaclose(dev, flags, mode, p)
                    628:        dev_t dev;
                    629:        int flags, mode;
                    630:        struct proc *p;
                    631: {
                    632:        return (0);
                    633: }
                    634:
                    635: int
                    636: fgaioctl(dev, cmd, data, flags, p)
                    637:        dev_t dev;
                    638:        u_long cmd;
                    639:        caddr_t data;
                    640:        int flags;
                    641:        struct proc *p;
                    642: {
                    643:        struct fga_softc *sc = fga_cd.cd_devs[0];
                    644:        struct fga_sem *fsem = (struct fga_sem *)data;
                    645:        int error = 0;
                    646:
                    647:        switch (cmd) {
                    648:        case FGAIOCSEM:
                    649:                if (fsem->fgasem_num >= 48) {
                    650:                        error = ENOENT;
                    651:                        break;
                    652:                }
                    653:                sc->sc_regs->sem[fsem->fgasem_num] = 0xff;
                    654:                break;
                    655:        case FGAIOGSEM:
                    656:                if (fsem->fgasem_num >= 48) {
                    657:                        error = ENOENT;
                    658:                        break;
                    659:                }
                    660:                fsem->fgasem_val =
                    661:                    (sc->sc_regs->sem[fsem->fgasem_num] & MBOX_SEM) ? 0 : 1;
                    662:                break;
                    663:        case FGAIOCMBX:
                    664:                if (fsem->fgasem_num >= 16) {
                    665:                        error = ENOENT;
                    666:                        break;
                    667:                }
                    668:                sc->sc_regs->mbox[fsem->fgasem_num] = 0xff;
                    669:                break;
                    670:        case FGAIOGMBX:
                    671:                if (fsem->fgasem_num >= 16) {
                    672:                        error = ENOENT;
                    673:                        break;
                    674:                }
                    675:                fsem->fgasem_val =
                    676:                    sc->sc_regs->mbox[fsem->fgasem_num] ? 0 : 1;
                    677:                break;
                    678:        default:
                    679:                error = EINVAL;
                    680:        }
                    681:
                    682:        return (error);
                    683: }
                    684:
                    685: int
                    686: fvmematch(parent, vcf, aux)
                    687:        struct device *parent;
                    688:        void *vcf, *aux;
                    689: {
                    690:        struct confargs *ca = aux;
                    691:         struct romaux *ra = &ca->ca_ra;
                    692:
                    693:        if (strcmp("fvme", ra->ra_name) || ca->ca_bustype != BUS_FGA)
                    694:                return (0);
                    695:
                    696:        return (1);
                    697: }
                    698:
                    699: const struct fvme_types {
                    700:        int data_cap;
                    701:        int addr_cap;
                    702:        const char *name;
                    703:        int bustype;
                    704: } fvme_types[] = {
                    705:        {0, 0, "a16d8", BUS_FGA_A16D8},
                    706:        {0, 1, "a24d8", BUS_FGA_A24D8},
                    707:        {0, 2, "a32d8", BUS_FGA_A32D8},
                    708:        {1, 0, "a16d16", BUS_FGA_A16D16},
                    709:        {1, 1, "a24d16", BUS_FGA_A24D16},
                    710:        {1, 2, "a32d16", BUS_FGA_A32D16},
                    711:        {2, 0, "a16d32", BUS_FGA_A16D32},
                    712:        {2, 1, "a24d32", BUS_FGA_A24D32},
                    713:        {2, 2, "a32d32", BUS_FGA_A32D32},
                    714:        {3, 0, "a16blt", -1},
                    715:        {3, 1, "a24blt", -1},
                    716:        {3, 2, "a32blt", -1},
                    717:        {4, 0, "a16mblt", -1},
                    718:        {4, 1, "a24mblt", -1},
                    719:        {4, 2, "a32mblt", -1},
                    720:        {-1, -1, "", -1},
                    721: };
                    722:
                    723: void
                    724: fvmeattach(parent, self, aux)
                    725:        struct device *parent, *self;
                    726:        void *aux;
                    727: {
                    728:        struct confargs *ca = aux;
                    729:        const struct fvme_types *p;
                    730:        int dtype, atype;
                    731:
                    732:        atype = (ca->ca_ra.ra_reg[1].rr_iospace & VME_MASTER_CAP_ADDR) >> 2;
                    733:        dtype = (ca->ca_ra.ra_reg[1].rr_iospace & VME_MASTER_CAP_DATA) >> 5;
                    734:        for (p = fvme_types; p->data_cap != -1; p++) {
                    735:                if (p->data_cap == dtype && p->addr_cap == atype)
                    736:                        break;
                    737:        }
                    738:        if (p->data_cap == -1) {
                    739:                printf(" unknown addr/data capability\n");
                    740:                return;
                    741:        }
                    742:        printf(": %s", p->name);
                    743:        if (p->bustype == -1) {
                    744:                printf(" unsupported\n");
                    745:                return;
                    746:        }
                    747:        ca->ca_ra.ra_reg[1].rr_iospace = p->bustype;
                    748:
                    749:        printf(" offset 0x%x len 0x%x\n", ca->ca_ra.ra_reg[1].rr_paddr,
                    750:           ca->ca_ra.ra_reg[1].rr_len);
                    751:
                    752:        (void)config_search(fvmescan, self, aux);
                    753: }
                    754:
                    755: int
                    756: fvmescan(parent, child, aux)
                    757:        struct device *parent;
                    758:        void *child, *aux;
                    759: {
                    760:        struct cfdata *cf = child;
                    761:        struct confargs *ca = aux, oca;
                    762:        int plen, paddr;
                    763:
                    764:        if (cf->cf_loc[0] == -1)
                    765:                return (0);
                    766:
                    767:        if ((unsigned)cf->cf_loc[0] < (unsigned)ca->ca_ra.ra_reg[1].rr_paddr)
                    768:                return (0);
                    769:
                    770:        paddr = cf->cf_loc[0] - (int)ca->ca_ra.ra_reg[1].rr_paddr;
                    771:        paddr = (int)ca->ca_ra.ra_reg[0].rr_paddr + paddr;
                    772:        plen = cf->cf_loc[0] - (int)ca->ca_ra.ra_reg[1].rr_paddr;
                    773:        plen = ca->ca_ra.ra_reg[1].rr_len - plen;
                    774:
                    775:        oca.ca_bustype = ca->ca_ra.ra_reg[1].rr_iospace;
                    776:        oca.ca_offset = cf->cf_loc[0];
                    777:
                    778:        oca.ca_ra.ra_nintr = 1;
                    779:        oca.ca_ra.ra_intr[0].int_pri = cf->cf_loc[1];
                    780:        oca.ca_ra.ra_intr[0].int_vec = cf->cf_loc[2];
                    781:        oca.ca_ra.ra_name = cf->cf_driver->cd_name;
                    782:
                    783:        oca.ca_ra.ra_nreg = 1;
                    784:        oca.ca_ra.ra_reg[0].rr_paddr = (void *)paddr;
                    785:        oca.ca_ra.ra_reg[0].rr_iospace = ca->ca_ra.ra_reg[0].rr_iospace;
                    786:        oca.ca_ra.ra_reg[0].rr_len = plen;
                    787:        oca.ca_ra.ra_reg[0].rr_paddr =
                    788:            mapdev(&oca.ca_ra.ra_reg[0], TMPMAP_VA, 0, NBPG);
                    789:
                    790:        if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0) {
                    791:                bus_untmp();
                    792:                return (0);
                    793:        }
                    794:        bus_untmp();
                    795:
                    796:        oca.ca_ra.ra_reg[0].rr_paddr = (void *)paddr;
                    797:        config_attach(parent, cf, &oca, fvmeprint);
                    798:        return (1);
                    799: }
                    800:
                    801: int
                    802: fvmeprint(args, name)
                    803:        void *args;
                    804:        const char *name;
                    805: {
                    806:        struct confargs *ca = args;
                    807:
                    808:        if (name)
                    809:                printf("%s at %s", ca->ca_ra.ra_name, name);
                    810:        printf(" addr 0x%x", ca->ca_offset);
                    811:        return (UNCONF);
                    812: }
                    813:
                    814: int
                    815: fvmeintrestablish(dsc, vec, level, ih, name)
                    816:        struct device *dsc;
                    817:        int vec, level;
                    818:        struct intrhand *ih;
                    819:        const char *name;
                    820: {
                    821:        struct fga_softc *fsc = (struct fga_softc *)dsc->dv_parent;
                    822:
                    823:        return (fga_intr_establish(fsc, vec, level, ih, name));
                    824: }

CVSweb