Annotation of sys/arch/sparc/dev/obio.c, Revision 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