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

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

1.1       nbrk        1: /*     $OpenBSD: obio.c,v 1.18 2007/07/01 19:07:45 miod Exp $  */
                      2: /*     $NetBSD: obio.c,v 1.37 1997/07/29 09:58:11 fair Exp $   */
                      3:
                      4: /*
                      5:  * Copyright (c) 1993, 1994 Theo de Raadt
                      6:  * Copyright (c) 1995, 1997 Paul Kranenburg
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     21:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     22:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     23:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     24:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     25:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     26:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     27:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     28:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     29:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/param.h>
                     33: #include <sys/systm.h>
                     34: #include <sys/device.h>
                     35: #include <sys/malloc.h>
                     36:
                     37: #ifdef DEBUG
                     38: #include <sys/proc.h>
                     39: #include <sys/syslog.h>
                     40: #endif
                     41:
                     42: #include <uvm/uvm_extern.h>
                     43:
                     44: #include <machine/autoconf.h>
                     45: #include <machine/pmap.h>
                     46: #include <machine/oldmon.h>
                     47: #include <machine/cpu.h>
                     48: #include <machine/ctlreg.h>
                     49: #include <sparc/sparc/asm.h>
                     50: #include <sparc/sparc/vaddrs.h>
                     51: #include <sparc/sparc/cpuvar.h>
                     52: #include <sparc/dev/sbusvar.h>
                     53: #include <sparc/dev/vmereg.h>
                     54:
                     55: struct vmebus_softc {
                     56:        struct device    sc_dev;        /* base device */
                     57:        struct vmebusreg *sc_reg;       /* VME control registers */
                     58:        struct vmebusvec *sc_vec;       /* VME interrupt vector */
                     59:        struct rom_range *sc_range;     /* ROM range property */
                     60:        int              sc_nrange;
                     61: };
                     62: struct  vmebus_softc *vmebus_sc;/*XXX*/
                     63:
                     64: struct bus_softc {
                     65:        union {
                     66:                struct  device scu_dev;         /* base device */
                     67:                struct  sbus_softc scu_sbus;    /* obio is another sbus slot */
                     68:                struct  vmebus_softc scu_vme;
                     69:        } bu;
                     70: };
                     71:
                     72:
                     73: /* autoconfiguration driver */
                     74: static int     busmatch(struct device *, void *, void *);
                     75: static void    obioattach(struct device *, struct device *, void *);
                     76: static void    vmesattach(struct device *, struct device *, void *);
                     77: static void    vmelattach(struct device *, struct device *, void *);
                     78: static void    vmeattach(struct device *, struct device *, void *);
                     79:
                     80: int            busprint(void *, const char *);
                     81: int            vmeprint(void *, const char *);
                     82: static int     busattach(struct device *, void *, void *, int);
                     83: int            obio_scan(struct device *, void *, void *);
                     84: int            vmes_scan(struct device *, void *, void *);
                     85: int            vmel_scan(struct device *, void *, void *);
                     86: void           vmebus_translate(struct device *, struct confargs *, int);
                     87: int            vmeintr(void *);
                     88:
                     89: struct cfattach obio_ca = {
                     90:        sizeof(struct bus_softc), busmatch, obioattach
                     91: };
                     92:
                     93: struct cfdriver obio_cd = {
                     94:        NULL, "obio", DV_DULL
                     95: };
                     96:
                     97: struct cfattach vmel_ca = {
                     98:        sizeof(struct bus_softc), busmatch, vmelattach
                     99: };
                    100:
                    101: struct cfdriver vmel_cd = {
                    102:        NULL, "vmel", DV_DULL
                    103: };
                    104:
                    105: struct cfattach vmes_ca = {
                    106:        sizeof(struct bus_softc), busmatch, vmesattach
                    107: };
                    108:
                    109: struct cfdriver vmes_cd = {
                    110:        NULL, "vmes", DV_DULL
                    111: };
                    112:
                    113: struct cfattach vme_ca = {
                    114:        sizeof(struct bus_softc), busmatch, vmeattach
                    115: };
                    116:
                    117: struct cfdriver vme_cd = {
                    118:        NULL, "vme", DV_DULL
                    119: };
                    120:
                    121: struct intrhand **vmeints;
                    122:
                    123:
                    124: int
                    125: busmatch(parent, vcf, aux)
                    126:        struct device *parent;
                    127:        void *vcf, *aux;
                    128: {
                    129:        register struct cfdata *cf = vcf;
                    130:        register struct confargs *ca = aux;
                    131:        register struct romaux *ra = &ca->ca_ra;
                    132:
                    133:        if (CPU_ISSUN4M)
                    134:                return (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0);
                    135:
                    136:        if (!CPU_ISSUN4)
                    137:                return (0);
                    138:
                    139:        return (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0);
                    140: }
                    141:
                    142: int
                    143: busprint(args, obio)
                    144:        void *args;
                    145:        const char *obio;
                    146: {
                    147:        register struct confargs *ca = args;
                    148:
                    149:        if (ca->ca_ra.ra_name == NULL)
                    150:                ca->ca_ra.ra_name = "<unknown>";
                    151:
                    152:        if (obio)
                    153:                printf("%s at %s", ca->ca_ra.ra_name, obio);
                    154:
                    155:        printf(" addr %p", ca->ca_ra.ra_paddr);
                    156:
                    157:        if (CPU_ISSUN4 && ca->ca_ra.ra_intr[0].int_vec != -1)
                    158:                printf(" vec 0x%x", ca->ca_ra.ra_intr[0].int_vec);
                    159:
                    160:        return (UNCONF);
                    161: }
                    162:
                    163: int
                    164: vmeprint(args, name)
                    165:        void *args;
                    166:        const char *name;
                    167: {
                    168:        register struct confargs *ca = args;
                    169:
                    170:        if (name)
                    171:                printf("%s at %s", ca->ca_ra.ra_name, name);
                    172:        return (UNCONF);
                    173: }
                    174:
                    175: void
                    176: obioattach(parent, self, args)
                    177:        struct device *parent, *self;
                    178:        void *args;
                    179: {
                    180: #if defined(SUN4M)
                    181:        register struct bus_softc *sc = (struct bus_softc *)self;
                    182:        struct confargs oca, *ca = args;
                    183:        register struct romaux *ra = &ca->ca_ra;
                    184:        register int node0, node;
                    185:        register char *name;
                    186:        register const char *sp;
                    187:        const char *const *ssp;
                    188:        int rlen;
                    189:        extern int autoconf_nzs;
                    190:
                    191:        static const char *const special4m[] = {
                    192:                /* find these first */
                    193:                "eeprom",
                    194:                "counter",
                    195: #if 0 /* Not all sun4m's have an `auxio' */
                    196:                "auxio",
                    197: #endif
                    198:                "",
                    199:                /* place device to ignore here */
                    200:                "interrupt",
                    201:                NULL
                    202:        };
                    203: #endif
                    204:
                    205:        if (CPU_ISSUN4) {
                    206:                if (self->dv_unit > 0) {
                    207:                        printf(" unsupported\n");
                    208:                        return;
                    209:                }
                    210:                printf("\n");
                    211:
                    212:                (void)config_search(obio_scan, self, args);
                    213:                bus_untmp();
                    214:        }
                    215:
                    216: #if defined(SUN4M)
                    217:        if (!CPU_ISSUN4M)
                    218:                return;
                    219:
                    220:        /*
                    221:         * There is only one obio bus (it is in fact one of the SBus slots)
                    222:         * How about VME?
                    223:         */
                    224:        if (self->dv_unit > 0) {
                    225:                printf(" unsupported\n");
                    226:                return;
                    227:        }
                    228:
                    229:        printf("\n");
                    230:
                    231:        if (ra->ra_bp != NULL && strcmp(ra->ra_bp->name, "obio") == 0)
                    232:                oca.ca_ra.ra_bp = ra->ra_bp + 1;
                    233:        else
                    234:                oca.ca_ra.ra_bp = NULL;
                    235:
                    236:        node = ra->ra_node;
                    237:        rlen = getproplen(node, "ranges");
                    238:        if (rlen > 0) {
                    239:                sc->bu.scu_sbus.sc_nrange = rlen / sizeof(struct rom_range);
                    240:                sc->bu.scu_sbus.sc_range =
                    241:                        (struct rom_range *)malloc(rlen, M_DEVBUF, M_NOWAIT);
                    242:                if (sc->bu.scu_sbus.sc_range == 0)
                    243:                        panic("obio: PROM ranges too large: %d", rlen);
                    244:                (void)getprop(node, "ranges", sc->bu.scu_sbus.sc_range, rlen);
                    245:        }
                    246:
                    247:        /*
                    248:         * Loop through ROM children, fixing any relative addresses
                    249:         * and then configuring each device.
                    250:         * We first do the crucial ones, such as eeprom, etc.
                    251:         */
                    252:        node0 = firstchild(ra->ra_node);
                    253:        for (ssp = special4m ; *(sp = *ssp) != 0; ssp++) {
                    254:                if ((node = findnode(node0, sp)) == 0) {
                    255:                        printf("could not find %s amongst obio devices\n", sp);
                    256:                        panic(sp);
                    257:                }
                    258:                if (!romprop(&oca.ca_ra, sp, node))
                    259:                        continue;
                    260:
                    261:                sbus_translate(self, &oca);
                    262:                oca.ca_bustype = BUS_OBIO;
                    263:                (void) config_found(self, (void *)&oca, busprint);
                    264:        }
                    265:
                    266:        for (node = node0; node; node = nextsibling(node)) {
                    267:                name = getpropstring(node, "name");
                    268:                for (ssp = special4m ; (sp = *ssp) != NULL; ssp++)
                    269:                        if (strcmp(name, sp) == 0)
                    270:                                break;
                    271:
                    272:                if (sp != NULL || !romprop(&oca.ca_ra, name, node))
                    273:                        continue;
                    274:
                    275:                if (strcmp(name, "zs") == 0)
                    276:                        /* XXX - see autoconf.c for this hack */
                    277:                        autoconf_nzs++;
                    278:
                    279:                /* Translate into parent address spaces */
                    280:                sbus_translate(self, &oca);
                    281:                oca.ca_bustype = BUS_OBIO;
                    282:                (void) config_found(self, (void *)&oca, busprint);
                    283:        }
                    284: #endif
                    285: }
                    286:
                    287: void
                    288: vmesattach(parent, self, args)
                    289:        struct device *parent, *self;
                    290:        void *args;
                    291: {
                    292:        if (self->dv_unit > 0 ||
                    293:            (CPU_ISSUN4M && strncmp(parent->dv_xname, "vme", 3) != 0)) {
                    294:                printf(" unsupported\n");
                    295:                return;
                    296:        }
                    297:        printf("\n");
                    298:
                    299:        if (vmeints == NULL) {
                    300:                vmeints = (struct intrhand **)malloc(256 *
                    301:                    sizeof(struct intrhand *), M_TEMP, M_NOWAIT);
                    302:                if (vmeints == NULL)
                    303:                        panic("vmesattach: can't allocate intrhand");
                    304:                bzero(vmeints, 256 * sizeof(struct intrhand *));
                    305:        }
                    306:        (void)config_search(vmes_scan, self, args);
                    307:        bus_untmp();
                    308: }
                    309:
                    310: void
                    311: vmelattach(parent, self, args)
                    312:        struct device *parent, *self;
                    313:        void *args;
                    314: {
                    315:        if (self->dv_unit > 0 ||
                    316:            (CPU_ISSUN4M && strncmp(parent->dv_xname, "vme", 3) != 0)) {
                    317:                printf(" unsupported\n");
                    318:                return;
                    319:        }
                    320:        printf("\n");
                    321:
                    322:        if (vmeints == NULL) {
                    323:                vmeints = (struct intrhand **)malloc(256 *
                    324:                    sizeof(struct intrhand *), M_TEMP, M_NOWAIT);
                    325:                if (vmeints == NULL)
                    326:                        panic("vmelattach: can't allocate intrhand");
                    327:                bzero(vmeints, 256 * sizeof(struct intrhand *));
                    328:        }
                    329:        (void)config_search(vmel_scan, self, args);
                    330:        bus_untmp();
                    331: }
                    332:
                    333: void
                    334: vmeattach(parent, self, aux)
                    335:        struct device *parent, *self;
                    336:        void *aux;
                    337: {
                    338:        struct vmebus_softc *sc = (struct vmebus_softc *)self;
                    339:        struct confargs *ca = aux;
                    340:        register struct romaux *ra = &ca->ca_ra;
                    341:        int node, rlen;
                    342:        struct confargs oca;
                    343:
                    344:        if (!CPU_ISSUN4M || self->dv_unit > 0) {
                    345:                printf(" unsupported\n");
                    346:                return;
                    347:        }
                    348:
                    349:        node = ra->ra_node;
                    350:
                    351:        sc->sc_reg = (struct vmebusreg *)
                    352:                mapiodev(&ra->ra_reg[0], 0, ra->ra_reg[0].rr_len);
                    353:        sc->sc_vec = (struct vmebusvec *)
                    354:                mapiodev(&ra->ra_reg[1], 0, ra->ra_reg[1].rr_len);
                    355:
                    356:        /*
                    357:         * Get "range" property, though we don't do anything with it yet.
                    358:         */
                    359:        rlen = getproplen(node, "ranges");
                    360:        if (rlen > 0) {
                    361:                sc->sc_nrange = rlen / sizeof(struct rom_range);
                    362:                sc->sc_range =
                    363:                        (struct rom_range *)malloc(rlen, M_DEVBUF, M_NOWAIT);
                    364:                if (sc->sc_range == 0)
                    365:                        panic("vme: PROM ranges too large: %d", rlen);
                    366:                (void)getprop(node, "ranges", sc->sc_range, rlen);
                    367:        }
                    368:
                    369:        vmebus_sc = sc;
                    370:        printf(": version 0x%x\n",
                    371:               sc->sc_reg->vmebus_cr & VMEBUS_CR_IMPL);
                    372:
                    373:        if (ra->ra_bp != NULL && strcmp(ra->ra_bp->name, "vme") == 0)
                    374:                oca.ca_ra.ra_bp = ra->ra_bp + 1;
                    375:        else
                    376:                oca.ca_ra.ra_bp = NULL;
                    377:
                    378:        oca.ca_ra.ra_name = "vmes";
                    379:        oca.ca_bustype = BUS_MAIN;
                    380:        (void)config_found(self, (void *)&oca, vmeprint);
                    381:
                    382:        oca.ca_ra.ra_name = "vmel";
                    383:        oca.ca_bustype = BUS_MAIN;
                    384:        (void)config_found(self, (void *)&oca, vmeprint);
                    385: }
                    386:
                    387: void
                    388: vmebus_translate(dev, ca, bustype)
                    389:        struct device *dev;
                    390:        struct confargs *ca;
                    391:        int bustype;
                    392: {
                    393:        struct vmebus_softc *sc = (struct vmebus_softc *)dev;
                    394:        register int j;
                    395:        int cspace;
                    396:
                    397:        if (sc->sc_nrange == 0)
                    398:                panic("vmebus: no ranges");
                    399:
                    400:        /*
                    401:         * Find VMEbus modifier based on address space.
                    402:         * XXX - should not be encoded in `ra_paddr'
                    403:         */
                    404:        if (((u_long)ca->ca_ra.ra_paddr & 0xffff0000) == 0xffff0000)
                    405:                cspace = VMEMOD_A16_D_S;
                    406:        else if (((u_long)ca->ca_ra.ra_paddr & 0xff000000) == 0xff000000)
                    407:                cspace = VMEMOD_A24_D_S;
                    408:        else
                    409:                cspace = VMEMOD_A32_D_S;
                    410:
                    411:        cspace |= (bustype == BUS_VME32) ? VMEMOD_D32 : 0;
                    412:
                    413:        /* Translate into parent address spaces */
                    414:        for (j = 0; j < sc->sc_nrange; j++) {
                    415:                if (sc->sc_range[j].cspace == cspace) {
                    416: #if notyet
                    417:                        (int)ca->ca_ra.ra_paddr +=
                    418:                                sc->sc_range[j].poffset;
                    419: #endif
                    420:                        (int)ca->ca_ra.ra_iospace =
                    421:                                sc->sc_range[j].pspace;
                    422:                        break;
                    423:                }
                    424:        }
                    425: }
                    426:
                    427: int bt2pmt[] = {
                    428:        PMAP_OBIO,
                    429:        PMAP_OBIO,
                    430:        PMAP_VME16,
                    431:        PMAP_VME32,
                    432:        PMAP_OBIO
                    433: };
                    434:
                    435: int
                    436: busattach(parent, vcf, args, bustype)
                    437:        struct device *parent;
                    438:        void *vcf, *args;
                    439:        int bustype;
                    440: {
                    441: #if defined(SUN4) || defined(SUN4M)
                    442:        register struct cfdata *cf = vcf;
                    443:        register struct confargs *ca = args;
                    444:        struct confargs oca;
                    445:        caddr_t tmp;
                    446:
                    447:        if (bustype == BUS_OBIO && CPU_ISSUN4) {
                    448:
                    449:                /*
                    450:                 * avoid sun4m entries which don't have valid PA's.
                    451:                 * no point in even probing them.
                    452:                 */
                    453:                if (cf->cf_loc[0] == -1) return 0;
                    454:
                    455:                /*
                    456:                 * On the 4/100 obio addresses must be mapped at
                    457:                 * 0x0YYYYYYY, but alias higher up (we avoid the
                    458:                 * alias condition because it causes pmap difficulties)
                    459:                 * XXX: We also assume that 4/[23]00 obio addresses
                    460:                 * must be 0xZYYYYYYY, where (Z != 0)
                    461:                 */
                    462:                if (cpuinfo.cpu_type == CPUTYP_4_100 &&
                    463:                    (cf->cf_loc[0] & 0xf0000000))
                    464:                        return 0;
                    465:                if (cpuinfo.cpu_type != CPUTYP_4_100 &&
                    466:                    !(cf->cf_loc[0] & 0xf0000000))
                    467:                        return 0;
                    468:        }
                    469:
                    470:        oca.ca_ra.ra_paddr = (void *)cf->cf_loc[0];
                    471:        oca.ca_ra.ra_len = 0;
                    472:        oca.ca_ra.ra_nreg = 1;
                    473:        if (CPU_ISSUN4M)
                    474:                vmebus_translate(parent->dv_parent, &oca, bustype);
                    475:        else
                    476:                oca.ca_ra.ra_iospace = bt2pmt[bustype];
                    477:
                    478:        if (oca.ca_ra.ra_paddr)
                    479:                tmp = (caddr_t)mapdev(oca.ca_ra.ra_reg, TMPMAP_VA, 0, NBPG);
                    480:        else
                    481:                tmp = NULL;
                    482:        oca.ca_ra.ra_vaddr = tmp;
                    483:        oca.ca_ra.ra_intr[0].int_pri = cf->cf_loc[1];
                    484:        if (bustype == BUS_VME16 || bustype == BUS_VME32)
                    485:                oca.ca_ra.ra_intr[0].int_vec = cf->cf_loc[2];
                    486:        else
                    487:                oca.ca_ra.ra_intr[0].int_vec = -1;
                    488:        oca.ca_ra.ra_nintr = 1;
                    489:        oca.ca_ra.ra_name = cf->cf_driver->cd_name;
                    490:        if (ca->ca_ra.ra_bp != NULL &&
                    491:          ((bustype == BUS_VME16 && strcmp(ca->ca_ra.ra_bp->name,"vmes") ==0) ||
                    492:           (bustype == BUS_VME32 && strcmp(ca->ca_ra.ra_bp->name,"vmel") ==0) ||
                    493:           (bustype == BUS_OBIO && strcmp(ca->ca_ra.ra_bp->name,"obio") == 0)))
                    494:                oca.ca_ra.ra_bp = ca->ca_ra.ra_bp + 1;
                    495:        else
                    496:                oca.ca_ra.ra_bp = NULL;
                    497:        oca.ca_bustype = bustype;
                    498:
                    499:        if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0)
                    500:                return 0;
                    501:
                    502:        /*
                    503:         * check if XXmatch routine replaced the temporary mapping with
                    504:         * a real mapping.   If not, then make sure we don't pass the
                    505:         * tmp mapping to the attach routine.
                    506:         */
                    507:        if (oca.ca_ra.ra_vaddr == tmp)
                    508:                oca.ca_ra.ra_vaddr = NULL; /* wipe out tmp address */
                    509:        /*
                    510:         * the match routine will set "ra_len" if it wants us to
                    511:         * establish a mapping for it.
                    512:         * (which won't be seen on future XXmatch calls,
                    513:         * so not as useful as it seems.)
                    514:         */
                    515:        if (oca.ca_ra.ra_len)
                    516:                oca.ca_ra.ra_vaddr =
                    517:                    bus_map(oca.ca_ra.ra_reg, oca.ca_ra.ra_len);
                    518:
                    519:        config_attach(parent, cf, &oca, busprint);
                    520:        return 1;
                    521: #else
                    522:        return 0;
                    523: #endif
                    524: }
                    525:
                    526: int
                    527: obio_scan(parent, child, args)
                    528:        struct device *parent;
                    529:        void *child, *args;
                    530: {
                    531:        return busattach(parent, child, args, BUS_OBIO);
                    532: }
                    533:
                    534: int
                    535: vmes_scan(parent, child, args)
                    536:        struct device *parent;
                    537:        void *child, *args;
                    538: {
                    539:        return busattach(parent, child, args, BUS_VME16);
                    540: }
                    541:
                    542: int
                    543: vmel_scan(parent, child, args)
                    544:        struct device *parent;
                    545:        void *child, *args;
                    546: {
                    547:        return busattach(parent, child, args, BUS_VME32);
                    548: }
                    549:
                    550: int pil_to_vme[] = {
                    551:        -1,     /* pil 0 */
                    552:        -1,     /* pil 1 */
                    553:        1,      /* pil 2 */
                    554:        2,      /* pil 3 */
                    555:        -1,     /* pil 4 */
                    556:        3,      /* pil 5 */
                    557:        -1,     /* pil 6 */
                    558:        4,      /* pil 7 */
                    559:        -1,     /* pil 8 */
                    560:        5,      /* pil 9 */
                    561:        -1,     /* pil 10 */
                    562:        6,      /* pil 11 */
                    563:        -1,     /* pil 12 */
                    564:        7,      /* pil 13 */
                    565:        -1,     /* pil 14 */
                    566:        -1,     /* pil 15 */
                    567: };
                    568:
                    569: int
                    570: vmeintr(arg)
                    571:        void *arg;
                    572: {
                    573:        int pil = (int)arg, level, vec;
                    574:        struct intrhand *ih;
                    575:        int r, i = 0;
                    576:
                    577:        level = (pil_to_vme[pil] << 1) | 1;
                    578:
                    579:        if (CPU_ISSUN4) {
                    580:                vec = ldcontrolb((caddr_t)(AC_VMEINTVEC | level));
                    581:        } else if (CPU_ISSUN4M) {
                    582:                vec = vmebus_sc->sc_vec->vmebusvec[level];
                    583:        } else
                    584:                panic("vme: spurious interrupt");
                    585:
                    586:        if (vec == -1) {
                    587:                printf("vme: spurious interrupt\n");
                    588:                return 0;
                    589:        }
                    590:
                    591:        for (ih = vmeints[vec]; ih; ih = ih->ih_next)
                    592:                if (ih->ih_fun) {
                    593:                        r = (ih->ih_fun)(ih->ih_arg);
                    594:                        if (r > 0) {
                    595:                                ih->ih_count.ec_count++;
                    596:                                return (r);
                    597:                        }
                    598:                        i |= r;
                    599:                }
                    600:        return (i);
                    601: }
                    602:
                    603: void
                    604: vmeintr_establish(vec, level, ih, ipl_block, name)
                    605:        int vec, level;
                    606:        struct intrhand *ih;
                    607:        int ipl_block;
                    608:        const char *name;
                    609: {
                    610:        struct intrhand *ihs;
                    611:
                    612:        if (vmeints == NULL)
                    613:                panic("vmeintr_establish: interrupt vector not allocated");
                    614:
                    615:        if (vec == -1)
                    616:                panic("vmeintr_establish: uninitialized vec");
                    617:
                    618:        if (vmeints[vec] == NULL)
                    619:                vmeints[vec] = ih;
                    620:        else {
                    621:                for (ihs = vmeints[vec]; ihs->ih_next; ihs = ihs->ih_next)
                    622:                        ;
                    623:                ihs->ih_next = ih;
                    624:        }
                    625:
                    626:        /* ensure the interrupt subsystem will call us at this level */
                    627:        for (ihs = intrhand[level]; ihs; ihs = ihs->ih_next)
                    628:                if (ihs->ih_fun == vmeintr)
                    629:                        return;
                    630:
                    631:        ihs = (struct intrhand *)malloc(sizeof(struct intrhand),
                    632:            M_TEMP, M_NOWAIT);
                    633:        if (ihs == NULL)
                    634:                panic("vme_addirq");
                    635:        bzero(ihs, sizeof *ihs);
                    636:        ihs->ih_fun = vmeintr;
                    637:        ihs->ih_arg = (void *)level;
                    638:        intr_establish(level, ihs, ipl_block, NULL);
                    639: }
                    640:
                    641: #define        getpte(va)              lda(va, ASI_PTE)
                    642:
                    643: /*
                    644:  * If we can find a mapping that was established by the rom, use it.
                    645:  * Else, create a new mapping.
                    646:  */
                    647: void *
                    648: bus_map(pa, len)
                    649:        struct rom_reg *pa;
                    650:        int len;
                    651: {
                    652:
                    653:        if (CPU_ISSUN4 && len <= NBPG) {
                    654:                u_long  pf = (u_long)(pa->rr_paddr) >> PGSHIFT;
                    655:                int pgtype = PMAP_T2PTE_4(pa->rr_iospace);
                    656:                u_long  va, pte;
                    657:
                    658:                for (va = OLDMON_STARTVADDR; va < OLDMON_ENDVADDR; va += NBPG) {
                    659:                        pte = getpte(va);
                    660:                        if ((pte & PG_V) != 0 && (pte & PG_TYPE) == pgtype &&
                    661:                            (pte & PG_PFNUM) == pf)
                    662:                                return ((void *)
                    663:                                    (va | ((u_long)pa->rr_paddr & PGOFSET)) );
                    664:                                        /* note: preserve page offset */
                    665:                }
                    666:        }
                    667:
                    668:        return mapiodev(pa, 0, len);
                    669: }
                    670:
                    671: void
                    672: bus_untmp()
                    673: {
                    674:        pmap_remove(pmap_kernel(), TMPMAP_VA, TMPMAP_VA+NBPG);
                    675:        pmap_update(pmap_kernel());
                    676: }

CVSweb