1 /* $NetBSD: sbus.c,v 1.60 2003/05/17 01:38:39 nakayama Exp $ */ 2 3 /* 4 * Copyright (c) 1999-2002 Eduardo Horvath 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 32 /* 33 * Sbus stuff. 34 */ 35 #include "opt_ddb.h" 36 37 #include <sys/param.h> 38 #include <sys/extent.h> 39 #include <sys/malloc.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 #include <sys/reboot.h> 43 44 #include <machine/bus.h> 45 #include <machine/openfirm.h> 46 47 #include <sparc64/sparc64/cache.h> 48 #include <sparc64/dev/iommureg.h> 49 #include <sparc64/dev/iommuvar.h> 50 #include <sparc64/dev/sbusreg.h> 51 #include <dev/sbus/sbusvar.h> 52 53 #include <uvm/uvm_extern.h> 54 55 #include <machine/autoconf.h> 56 #include <machine/cpu.h> 57 #include <machine/sparc64.h> 58 59 #ifdef DEBUG 60 #define SDB_DVMA 0x1 61 #define SDB_INTR 0x2 62 int sbus_debug = 0; 63 #define DPRINTF(l, s) do { if (sbus_debug & l) printf s; } while (0) 64 #else 65 #define DPRINTF(l, s) 66 #endif 67 68 void sbusreset __P((int)); 69 70 static bus_space_tag_t sbus_alloc_bustag __P((struct sbus_softc *)); 71 static bus_dma_tag_t sbus_alloc_dmatag __P((struct sbus_softc *)); 72 static int sbus_get_intr __P((struct sbus_softc *, int, 73 struct openprom_intr **, int *, int)); 74 static int sbus_overtemp __P((void *)); 75 static int _sbus_bus_map __P(( 76 bus_space_tag_t, 77 bus_addr_t, /*offset*/ 78 bus_size_t, /*size*/ 79 int, /*flags*/ 80 vaddr_t, /* XXX unused -- compat w/sparc */ 81 bus_space_handle_t *)); 82 static void *sbus_intr_establish __P(( 83 bus_space_tag_t, 84 int, /*Sbus interrupt level*/ 85 int, /*`device class' priority*/ 86 int (*) __P((void *)), /*handler*/ 87 void *, /*handler arg*/ 88 void (*) __P((void)))); /*optional fast trap*/ 89 90 91 /* autoconfiguration driver */ 92 int sbus_match __P((struct device *, struct cfdata *, void *)); 93 void sbus_attach __P((struct device *, struct device *, void *)); 94 95 96 CFATTACH_DECL(sbus, sizeof(struct sbus_softc), 97 sbus_match, sbus_attach, NULL, NULL); 98 99 extern struct cfdriver sbus_cd; 100 101 /* 102 * DVMA routines 103 */ 104 int sbus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *, 105 bus_size_t, struct proc *, int)); 106 void sbus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t)); 107 int sbus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t, 108 bus_dma_segment_t *, int, bus_size_t, int)); 109 void sbus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 110 bus_size_t, int)); 111 int sbus_dmamem_alloc __P((bus_dma_tag_t tag, bus_size_t size, 112 bus_size_t alignment, bus_size_t boundary, 113 bus_dma_segment_t *segs, int nsegs, int *rsegs, 114 int flags)); 115 void sbus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, 116 int nsegs)); 117 int sbus_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, 118 int nsegs, size_t size, caddr_t *kvap, int flags)); 119 void sbus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva, 120 size_t size)); 121 122 /* 123 * Child devices receive the Sbus interrupt level in their attach 124 * arguments. We translate these to CPU IPLs using the following 125 * tables. Note: obio bus interrupt levels are identical to the 126 * processor IPL. 127 * 128 * The second set of tables is used when the Sbus interrupt level 129 * cannot be had from the PROM as an `interrupt' property. We then 130 * fall back on the `intr' property which contains the CPU IPL. 131 */ 132 133 /* 134 * This value is or'ed into the attach args' interrupt level cookie 135 * if the interrupt level comes from an `intr' property, i.e. it is 136 * not an Sbus interrupt level. 137 */ 138 #define SBUS_INTR_COMPAT 0x80000000 139 140 141 /* 142 * Print the location of some sbus-attached device (called just 143 * before attaching that device). If `sbus' is not NULL, the 144 * device was found but not configured; print the sbus as well. 145 * Return UNCONF (config_find ignores this if the device was configured). 146 */ 147 int 148 sbus_print(args, busname) 149 void *args; 150 const char *busname; 151 { 152 struct sbus_attach_args *sa = args; 153 int i; 154 155 if (busname) 156 aprint_normal("%s at %s", sa->sa_name, busname); 157 aprint_normal(" slot %ld offset 0x%lx", (long)sa->sa_slot, 158 (u_long)sa->sa_offset); 159 for (i = 0; i < sa->sa_nintr; i++) { 160 struct openprom_intr *sbi = &sa->sa_intr[i]; 161 162 aprint_normal(" vector %lx ipl %ld", 163 (u_long)sbi->oi_vec, 164 (long)INTLEV(sbi->oi_pri)); 165 } 166 return (UNCONF); 167 } 168 169 int 170 sbus_match(parent, cf, aux) 171 struct device *parent; 172 struct cfdata *cf; 173 void *aux; 174 { 175 struct mainbus_attach_args *ma = aux; 176 177 return (strcmp(cf->cf_name, ma->ma_name) == 0); 178 } 179 180 /* 181 * Attach an Sbus. 182 */ 183 void 184 sbus_attach(parent, self, aux) 185 struct device *parent; 186 struct device *self; 187 void *aux; 188 { 189 struct sbus_softc *sc = (struct sbus_softc *)self; 190 struct mainbus_attach_args *ma = aux; 191 struct intrhand *ih; 192 int ipl; 193 char *name; 194 int node = ma->ma_node; 195 int node0, error; 196 bus_space_tag_t sbt; 197 struct sbus_attach_args sa; 198 199 sc->sc_bustag = ma->ma_bustag; 200 sc->sc_dmatag = ma->ma_dmatag; 201 sc->sc_ign = ma->ma_interrupts[0] & INTMAP_IGN; 202 203 /* XXXX Use sysio PROM mappings for interrupt vector regs. */ 204 sparc_promaddr_to_handle(sc->sc_bustag, ma->ma_address[0], &sc->sc_bh); 205 sc->sc_sysio = (struct sysioreg *)bus_space_vaddr(sc->sc_bustag, 206 sc->sc_bh); 207 208 #ifdef _LP64 209 /* 210 * 32-bit kernels use virtual addresses for bus space operations 211 * so we may as well use the prom VA. 212 * 213 * 64-bit kernels use physical addresses for bus space operations 214 * so mapping this in again will reduce TLB thrashing. 215 */ 216 if (bus_space_map(sc->sc_bustag, ma->ma_reg[0].ur_paddr, 217 ma->ma_reg[0].ur_len, 0, &sc->sc_bh) != 0) { 218 printf("%s: cannot map registers\n", self->dv_xname); 219 return; 220 } 221 #endif 222 223 /* 224 * Record clock frequency for synchronous SCSI. 225 * IS THIS THE CORRECT DEFAULT?? 226 */ 227 sc->sc_clockfreq = PROM_getpropint(node, "clock-frequency", 228 25*1000*1000); 229 printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq)); 230 231 sbt = sbus_alloc_bustag(sc); 232 sc->sc_dmatag = sbus_alloc_dmatag(sc); 233 234 /* 235 * Get the SBus burst transfer size if burst transfers are supported 236 */ 237 sc->sc_burst = PROM_getpropint(node, "burst-sizes", 0); 238 239 /* 240 * Collect address translations from the OBP. 241 */ 242 error = PROM_getprop(node, "ranges", sizeof(struct openprom_range), 243 &sc->sc_nrange, (void **)&sc->sc_range); 244 if (error) 245 panic("%s: error getting ranges property", sc->sc_dev.dv_xname); 246 247 /* initialize the IOMMU */ 248 249 /* punch in our copies */ 250 sc->sc_is.is_bustag = sc->sc_bustag; 251 bus_space_subregion(sc->sc_bustag, sc->sc_bh, 252 (vaddr_t)&((struct sysioreg *)NULL)->sys_iommu, 253 sizeof (struct iommureg), &sc->sc_is.is_iommu); 254 255 /* initialize our strbuf_ctl */ 256 sc->sc_is.is_sb[0] = &sc->sc_sb; 257 sc->sc_sb.sb_is = &sc->sc_is; 258 bus_space_subregion(sc->sc_bustag, sc->sc_bh, 259 (vaddr_t)&((struct sysioreg *)NULL)->sys_strbuf, 260 sizeof (struct iommu_strbuf), &sc->sc_sb.sb_sb); 261 /* Point sb_flush to our flush buffer. */ 262 sc->sc_sb.sb_flush = &sc->sc_flush; 263 264 /* give us a nice name.. */ 265 name = (char *)malloc(32, M_DEVBUF, M_NOWAIT); 266 if (name == 0) 267 panic("couldn't malloc iommu name"); 268 snprintf(name, 32, "%s dvma", sc->sc_dev.dv_xname); 269 270 iommu_init(name, &sc->sc_is, 0, -1); 271 272 /* Enable the over temp intr */ 273 ih = (struct intrhand *) 274 malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT); 275 ih->ih_map = &sc->sc_sysio->therm_int_map; 276 ih->ih_clr = NULL; /* &sc->sc_sysio->therm_clr_int; */ 277 ih->ih_fun = sbus_overtemp; 278 ipl = 1; 279 ih->ih_pil = (1<<ipl); 280 ih->ih_number = INTVEC(*(ih->ih_map)); 281 intr_establish(ipl, ih); 282 *(ih->ih_map) |= INTMAP_V; 283 284 /* 285 * Note: the stupid SBUS IOMMU ignores the high bits of an address, so a 286 * NULL DMA pointer will be translated by the first page of the IOTSB. 287 * To avoid bugs we'll alloc and ignore the first entry in the IOTSB. 288 */ 289 { 290 u_long dummy; 291 292 if (extent_alloc_subregion(sc->sc_is.is_dvmamap, 293 sc->sc_is.is_dvmabase, sc->sc_is.is_dvmabase + PAGE_SIZE, 294 PAGE_SIZE, PAGE_SIZE, 0, EX_NOWAIT|EX_BOUNDZERO, 295 (u_long *)&dummy) != 0) 296 panic("sbus iommu: can't toss first dvma page"); 297 } 298 299 /* 300 * Loop through ROM children, fixing any relative addresses 301 * and then configuring each device. 302 * `specials' is an array of device names that are treated 303 * specially: 304 */ 305 node0 = OF_child(node); 306 for (node = node0; node; node = OF_peer(node)) { 307 char *name = PROM_getpropstring(node, "name"); 308 309 if (sbus_setup_attach_args(sc, sbt, sc->sc_dmatag, 310 node, &sa) != 0) { 311 printf("sbus_attach: %s: incomplete\n", name); 312 continue; 313 } 314 (void) config_found(&sc->sc_dev, (void *)&sa, sbus_print); 315 sbus_destroy_attach_args(&sa); 316 } 317 } 318 319 int 320 sbus_setup_attach_args(sc, bustag, dmatag, node, sa) 321 struct sbus_softc *sc; 322 bus_space_tag_t bustag; 323 bus_dma_tag_t dmatag; 324 int node; 325 struct sbus_attach_args *sa; 326 { 327 /*struct openprom_addr sbusreg;*/ 328 /*int base;*/ 329 int error; 330 int n; 331 332 bzero(sa, sizeof(struct sbus_attach_args)); 333 error = PROM_getprop(node, "name", 1, &n, (void **)&sa->sa_name); 334 if (error != 0) 335 return (error); 336 sa->sa_name[n] = '\0'; 337 338 sa->sa_bustag = bustag; 339 sa->sa_dmatag = dmatag; 340 sa->sa_node = node; 341 sa->sa_frequency = sc->sc_clockfreq; 342 343 error = PROM_getprop(node, "reg", sizeof(struct openprom_addr), 344 &sa->sa_nreg, (void **)&sa->sa_reg); 345 if (error != 0) { 346 char buf[32]; 347 if (error != ENOENT || 348 !node_has_property(node, "device_type") || 349 strcmp(PROM_getpropstringA(node, "device_type", buf), 350 "hierarchical") != 0) 351 return (error); 352 } 353 for (n = 0; n < sa->sa_nreg; n++) { 354 /* Convert to relative addressing, if necessary */ 355 u_int32_t base = sa->sa_reg[n].oa_base; 356 if (SBUS_ABS(base)) { 357 sa->sa_reg[n].oa_space = SBUS_ABS_TO_SLOT(base); 358 sa->sa_reg[n].oa_base = SBUS_ABS_TO_OFFSET(base); 359 } 360 } 361 362 if ((error = sbus_get_intr(sc, node, &sa->sa_intr, &sa->sa_nintr, 363 sa->sa_slot)) != 0) 364 return (error); 365 366 error = PROM_getprop(node, "address", sizeof(u_int32_t), 367 &sa->sa_npromvaddrs, (void **)&sa->sa_promvaddrs); 368 if (error != 0 && error != ENOENT) 369 return (error); 370 371 return (0); 372 } 373 374 void 375 sbus_destroy_attach_args(sa) 376 struct sbus_attach_args *sa; 377 { 378 if (sa->sa_name != NULL) 379 free(sa->sa_name, M_DEVBUF); 380 381 if (sa->sa_nreg != 0) 382 free(sa->sa_reg, M_DEVBUF); 383 384 if (sa->sa_intr) 385 free(sa->sa_intr, M_DEVBUF); 386 387 if (sa->sa_promvaddrs) 388 free((void *)sa->sa_promvaddrs, M_DEVBUF); 389 390 bzero(sa, sizeof(struct sbus_attach_args)); /*DEBUG*/ 391 } 392 393 394 int 395 _sbus_bus_map(t, addr, size, flags, v, hp) 396 bus_space_tag_t t; 397 bus_addr_t addr; 398 bus_size_t size; 399 int flags; 400 vaddr_t v; 401 bus_space_handle_t *hp; 402 { 403 struct sbus_softc *sc = t->cookie; 404 int64_t slot = BUS_ADDR_IOSPACE(addr); 405 int64_t offset = BUS_ADDR_PADDR(addr); 406 int i; 407 408 for (i = 0; i < sc->sc_nrange; i++) { 409 bus_addr_t paddr; 410 411 if (sc->sc_range[i].or_child_space != slot) 412 continue; 413 414 /* We've found the connection to the parent bus */ 415 paddr = sc->sc_range[i].or_parent_base + offset; 416 paddr |= ((bus_addr_t)sc->sc_range[i].or_parent_space<<32); 417 DPRINTF(SDB_DVMA, 418 ("\n_sbus_bus_map: mapping paddr slot %lx offset %lx poffset %lx paddr %lx\n", 419 (long)slot, (long)offset, 420 (long)sc->sc_range[i].or_parent_base, 421 (long)paddr)); 422 return (bus_space_map(sc->sc_bustag, paddr, size, flags, hp)); 423 } 424 425 return (EINVAL); 426 } 427 428 429 bus_addr_t 430 sbus_bus_addr(t, btype, offset) 431 bus_space_tag_t t; 432 u_int btype; 433 u_int offset; 434 { 435 bus_addr_t baddr; 436 int slot = btype; 437 struct sbus_softc *sc = t->cookie; 438 int i; 439 440 for (i = 0; i < sc->sc_nrange; i++) { 441 if (sc->sc_range[i].or_child_space != slot) 442 continue; 443 444 baddr = sc->sc_range[i].or_parent_base + offset; 445 baddr |= ((bus_addr_t)sc->sc_range[i].or_parent_space<<32); 446 } 447 448 return (baddr); 449 } 450 451 452 /* 453 * Each attached device calls sbus_establish after it initializes 454 * its sbusdev portion. 455 */ 456 void 457 sbus_establish(sd, dev) 458 register struct sbusdev *sd; 459 register struct device *dev; 460 { 461 register struct sbus_softc *sc; 462 register struct device *curdev; 463 464 /* 465 * We have to look for the sbus by name, since it is not necessarily 466 * our immediate parent (i.e. sun4m /iommu/sbus/espdma/esp) 467 * We don't just use the device structure of the above-attached 468 * sbus, since we might (in the future) support multiple sbus's. 469 */ 470 for (curdev = dev->dv_parent; ; curdev = curdev->dv_parent) { 471 if (!curdev || !curdev->dv_xname) 472 panic("sbus_establish: can't find sbus parent for %s", 473 sd->sd_dev->dv_xname 474 ? sd->sd_dev->dv_xname 475 : "<unknown>" ); 476 477 if (strncmp(curdev->dv_xname, "sbus", 4) == 0) 478 break; 479 } 480 sc = (struct sbus_softc *) curdev; 481 482 sd->sd_dev = dev; 483 sd->sd_bchain = sc->sc_sbdev; 484 sc->sc_sbdev = sd; 485 } 486 487 /* 488 * Reset the given sbus. 489 */ 490 void 491 sbusreset(sbus) 492 int sbus; 493 { 494 register struct sbusdev *sd; 495 struct sbus_softc *sc = sbus_cd.cd_devs[sbus]; 496 struct device *dev; 497 498 printf("reset %s:", sc->sc_dev.dv_xname); 499 for (sd = sc->sc_sbdev; sd != NULL; sd = sd->sd_bchain) { 500 if (sd->sd_reset) { 501 dev = sd->sd_dev; 502 (*sd->sd_reset)(dev); 503 printf(" %s", dev->dv_xname); 504 } 505 } 506 /* Reload iommu regs */ 507 iommu_reset(&sc->sc_is); 508 } 509 510 /* 511 * Handle an overtemp situation. 512 * 513 * SPARCs have temperature sensors which generate interrupts 514 * if the machine's temperature exceeds a certain threshold. 515 * This handles the interrupt and powers off the machine. 516 * The same needs to be done to PCI controller drivers. 517 */ 518 int 519 sbus_overtemp(arg) 520 void *arg; 521 { 522 /* Should try a clean shutdown first */ 523 printf("DANGER: OVER TEMPERATURE detected\nShutting down...\n"); 524 delay(20); 525 cpu_reboot(RB_POWERDOWN|RB_HALT, NULL); 526 } 527 528 /* 529 * Get interrupt attributes for an Sbus device. 530 */ 531 int 532 sbus_get_intr(sc, node, ipp, np, slot) 533 struct sbus_softc *sc; 534 int node; 535 struct openprom_intr **ipp; 536 int *np; 537 int slot; 538 { 539 int *ipl; 540 int n, i; 541 char buf[32]; 542 543 /* 544 * The `interrupts' property contains the Sbus interrupt level. 545 */ 546 ipl = NULL; 547 if (PROM_getprop(node, "interrupts", sizeof(int), np, (void *)&ipl) == 0) { 548 struct openprom_intr *ip; 549 int pri; 550 551 /* Default to interrupt level 2 -- otherwise unused */ 552 pri = INTLEVENCODE(2); 553 554 /* Change format to an `struct sbus_intr' array */ 555 ip = malloc(*np * sizeof(struct openprom_intr), M_DEVBUF, 556 M_NOWAIT); 557 if (ip == NULL) 558 return (ENOMEM); 559 560 /* 561 * Now things get ugly. We need to take this value which is 562 * the interrupt vector number and encode the IPL into it 563 * somehow. Luckily, the interrupt vector has lots of free 564 * space and we can easily stuff the IPL in there for a while. 565 */ 566 PROM_getpropstringA(node, "device_type", buf); 567 if (!buf[0]) 568 PROM_getpropstringA(node, "name", buf); 569 570 for (i = 0; intrmap[i].in_class; i++) 571 if (strcmp(intrmap[i].in_class, buf) == 0) { 572 pri = INTLEVENCODE(intrmap[i].in_lev); 573 break; 574 } 575 576 /* 577 * Sbus card devices need the slot number encoded into 578 * the vector as this is generally not done. 579 */ 580 if ((ipl[0] & INTMAP_OBIO) == 0) 581 pri |= slot << 3; 582 583 for (n = 0; n < *np; n++) { 584 /* 585 * We encode vector and priority into sbi_pri so we 586 * can pass them as a unit. This will go away if 587 * sbus_establish ever takes an sbus_intr instead 588 * of an integer level. 589 * Stuff the real vector in sbi_vec. 590 */ 591 592 ip[n].oi_pri = pri|ipl[n]; 593 ip[n].oi_vec = ipl[n]; 594 } 595 free(ipl, M_DEVBUF); 596 *ipp = ip; 597 } 598 599 return (0); 600 } 601 602 603 /* 604 * Install an interrupt handler for an Sbus device. 605 */ 606 void * 607 sbus_intr_establish(t, pri, level, handler, arg, fastvec) 608 bus_space_tag_t t; 609 int pri; 610 int level; 611 int (*handler) __P((void *)); 612 void *arg; 613 void (*fastvec) __P((void)); /* ignored */ 614 { 615 struct sbus_softc *sc = t->cookie; 616 struct intrhand *ih; 617 int ipl; 618 long vec = pri; 619 620 ih = (struct intrhand *) 621 malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT); 622 if (ih == NULL) 623 return (NULL); 624 625 if ((vec & SBUS_INTR_COMPAT) != 0) 626 ipl = vec & ~SBUS_INTR_COMPAT; 627 else { 628 /* Decode and remove IPL */ 629 ipl = INTLEV(vec); 630 vec = INTVEC(vec); 631 DPRINTF(SDB_INTR, 632 ("\nsbus: intr[%ld]%lx: %lx\nHunting for IRQ...\n", 633 (long)ipl, (long)vec, (u_long)intrlev[vec])); 634 if ((vec & INTMAP_OBIO) == 0) { 635 /* We're in an SBUS slot */ 636 /* Register the map and clear intr registers */ 637 638 int slot = INTSLOT(pri); 639 640 ih->ih_map = &(&sc->sc_sysio->sbus_slot0_int)[slot]; 641 ih->ih_clr = &sc->sc_sysio->sbus0_clr_int[vec]; 642 #ifdef DEBUG 643 if (sbus_debug & SDB_INTR) { 644 int64_t intrmap = *ih->ih_map; 645 646 printf("SBUS %lx IRQ as %llx in slot %d\n", 647 (long)vec, (long long)intrmap, slot); 648 printf("\tmap addr %p clr addr %p\n", 649 ih->ih_map, ih->ih_clr); 650 } 651 #endif 652 /* Enable the interrupt */ 653 vec |= INTMAP_V; 654 /* Insert IGN */ 655 vec |= sc->sc_ign; 656 /* XXXX */ 657 *(ih->ih_map) = vec; 658 } else { 659 int64_t *intrptr = &sc->sc_sysio->scsi_int_map; 660 int64_t intrmap = 0; 661 int i; 662 663 /* Insert IGN */ 664 vec |= sc->sc_ign; 665 for (i = 0; &intrptr[i] <= 666 (int64_t *)&sc->sc_sysio->reserved_int_map && 667 INTVEC(intrmap = intrptr[i]) != INTVEC(vec); i++) 668 ; 669 if (INTVEC(intrmap) == INTVEC(vec)) { 670 DPRINTF(SDB_INTR, 671 ("OBIO %lx IRQ as %lx in slot %d\n", 672 vec, (long)intrmap, i)); 673 /* Register the map and clear intr registers */ 674 ih->ih_map = &intrptr[i]; 675 intrptr = (int64_t *)&sc->sc_sysio->scsi_clr_int; 676 ih->ih_clr = &intrptr[i]; 677 /* Enable the interrupt */ 678 intrmap |= INTMAP_V; 679 /* XXXX */ 680 *(ih->ih_map) = intrmap; 681 } else 682 panic("IRQ not found!"); 683 } 684 } 685 #ifdef DEBUG 686 if (sbus_debug & SDB_INTR) { long i; for (i = 0; i < 400000000; i++); } 687 #endif 688 689 ih->ih_fun = handler; 690 ih->ih_arg = arg; 691 ih->ih_number = vec; 692 ih->ih_pil = (1<<ipl); 693 intr_establish(ipl, ih); 694 return (ih); 695 } 696 697 static bus_space_tag_t 698 sbus_alloc_bustag(sc) 699 struct sbus_softc *sc; 700 { 701 bus_space_tag_t sbt; 702 703 sbt = (bus_space_tag_t) 704 malloc(sizeof(struct sparc_bus_space_tag), M_DEVBUF, M_NOWAIT); 705 if (sbt == NULL) 706 return (NULL); 707 708 bzero(sbt, sizeof *sbt); 709 sbt->cookie = sc; 710 sbt->parent = sc->sc_bustag; 711 sbt->type = SBUS_BUS_SPACE; 712 sbt->sparc_bus_map = _sbus_bus_map; 713 sbt->sparc_bus_mmap = sc->sc_bustag->sparc_bus_mmap; 714 sbt->sparc_intr_establish = sbus_intr_establish; 715 return (sbt); 716 } 717 718 719 static bus_dma_tag_t 720 sbus_alloc_dmatag(sc) 721 struct sbus_softc *sc; 722 { 723 bus_dma_tag_t sdt, psdt = sc->sc_dmatag; 724 725 sdt = (bus_dma_tag_t) 726 malloc(sizeof(struct sparc_bus_dma_tag), M_DEVBUF, M_NOWAIT); 727 if (sdt == NULL) 728 /* Panic? */ 729 return (psdt); 730 731 sdt->_cookie = sc; 732 sdt->_parent = psdt; 733 #define PCOPY(x) sdt->x = psdt->x 734 PCOPY(_dmamap_create); 735 PCOPY(_dmamap_destroy); 736 sdt->_dmamap_load = sbus_dmamap_load; 737 PCOPY(_dmamap_load_mbuf); 738 PCOPY(_dmamap_load_uio); 739 sdt->_dmamap_load_raw = sbus_dmamap_load_raw; 740 sdt->_dmamap_unload = sbus_dmamap_unload; 741 sdt->_dmamap_sync = sbus_dmamap_sync; 742 sdt->_dmamem_alloc = sbus_dmamem_alloc; 743 sdt->_dmamem_free = sbus_dmamem_free; 744 sdt->_dmamem_map = sbus_dmamem_map; 745 sdt->_dmamem_unmap = sbus_dmamem_unmap; 746 PCOPY(_dmamem_mmap); 747 #undef PCOPY 748 sc->sc_dmatag = sdt; 749 return (sdt); 750 } 751 752 int 753 sbus_dmamap_load(tag, map, buf, buflen, p, flags) 754 bus_dma_tag_t tag; 755 bus_dmamap_t map; 756 void *buf; 757 bus_size_t buflen; 758 struct proc *p; 759 int flags; 760 { 761 struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; 762 763 return (iommu_dvmamap_load(tag, &sc->sc_sb, map, buf, buflen, p, flags)); 764 } 765 766 int 767 sbus_dmamap_load_raw(tag, map, segs, nsegs, size, flags) 768 bus_dma_tag_t tag; 769 bus_dmamap_t map; 770 bus_dma_segment_t *segs; 771 int nsegs; 772 bus_size_t size; 773 int flags; 774 { 775 struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; 776 777 return (iommu_dvmamap_load_raw(tag, &sc->sc_sb, map, segs, nsegs, flags, size)); 778 } 779 780 void 781 sbus_dmamap_unload(tag, map) 782 bus_dma_tag_t tag; 783 bus_dmamap_t map; 784 { 785 struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; 786 787 iommu_dvmamap_unload(tag, &sc->sc_sb, map); 788 } 789 790 void 791 sbus_dmamap_sync(tag, map, offset, len, ops) 792 bus_dma_tag_t tag; 793 bus_dmamap_t map; 794 bus_addr_t offset; 795 bus_size_t len; 796 int ops; 797 { 798 struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; 799 800 if (ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) { 801 /* Flush the CPU then the IOMMU */ 802 bus_dmamap_sync(tag->_parent, map, offset, len, ops); 803 iommu_dvmamap_sync(tag, &sc->sc_sb, map, offset, len, ops); 804 } 805 if (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) { 806 /* Flush the IOMMU then the CPU */ 807 iommu_dvmamap_sync(tag, &sc->sc_sb, map, offset, len, ops); 808 bus_dmamap_sync(tag->_parent, map, offset, len, ops); 809 } 810 } 811 812 int 813 sbus_dmamem_alloc(tag, size, alignment, boundary, segs, nsegs, rsegs, flags) 814 bus_dma_tag_t tag; 815 bus_size_t size; 816 bus_size_t alignment; 817 bus_size_t boundary; 818 bus_dma_segment_t *segs; 819 int nsegs; 820 int *rsegs; 821 int flags; 822 { 823 struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; 824 825 return (iommu_dvmamem_alloc(tag, &sc->sc_sb, size, alignment, boundary, 826 segs, nsegs, rsegs, flags)); 827 } 828 829 void 830 sbus_dmamem_free(tag, segs, nsegs) 831 bus_dma_tag_t tag; 832 bus_dma_segment_t *segs; 833 int nsegs; 834 { 835 struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; 836 837 iommu_dvmamem_free(tag, &sc->sc_sb, segs, nsegs); 838 } 839 840 int 841 sbus_dmamem_map(tag, segs, nsegs, size, kvap, flags) 842 bus_dma_tag_t tag; 843 bus_dma_segment_t *segs; 844 int nsegs; 845 size_t size; 846 caddr_t *kvap; 847 int flags; 848 { 849 struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; 850 851 return (iommu_dvmamem_map(tag, &sc->sc_sb, segs, nsegs, size, kvap, flags)); 852 } 853 854 void 855 sbus_dmamem_unmap(tag, kva, size) 856 bus_dma_tag_t tag; 857 caddr_t kva; 858 size_t size; 859 { 860 struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; 861 862 iommu_dvmamem_unmap(tag, &sc->sc_sb, kva, size); 863 } 864