1 /* $OpenBSD: schizo.c,v 1.67 2016/08/23 03:28:01 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Jason L. Wright (jason@thought.net) 5 * Copyright (c) 2003 Henric Jungheim 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/device.h> 32 #include <sys/errno.h> 33 #include <sys/extent.h> 34 #include <sys/malloc.h> 35 #include <sys/systm.h> 36 #include <sys/time.h> 37 #include <sys/reboot.h> 38 39 #define _SPARC_BUS_DMA_PRIVATE 40 #include <machine/bus.h> 41 #include <machine/autoconf.h> 42 #include <machine/psl.h> 43 44 #ifdef DDB 45 #include <machine/db_machdep.h> 46 #endif 47 48 #include <dev/pci/pcivar.h> 49 #include <dev/pci/pcireg.h> 50 51 #include <sparc64/dev/iommureg.h> 52 #include <sparc64/dev/iommuvar.h> 53 #include <sparc64/dev/schizoreg.h> 54 #include <sparc64/dev/schizovar.h> 55 #include <sparc64/sparc64/cache.h> 56 57 #ifdef DEBUG 58 #define SDB_PROM 0x01 59 #define SDB_BUSMAP 0x02 60 #define SDB_INTR 0x04 61 #define SDB_CONF 0x08 62 int schizo_debug = ~0; 63 #define DPRINTF(l, s) do { if (schizo_debug & l) printf s; } while (0) 64 #else 65 #define DPRINTF(l, s) 66 #endif 67 68 extern struct sparc_pci_chipset _sparc_pci_chipset; 69 70 int schizo_match(struct device *, void *, void *); 71 void schizo_attach(struct device *, struct device *, void *); 72 void schizo_init(struct schizo_softc *, int); 73 void schizo_init_iommu(struct schizo_softc *, struct schizo_pbm *); 74 int schizo_print(void *, const char *); 75 76 void schizo_set_intr(struct schizo_softc *, struct schizo_pbm *, int, 77 int (*handler)(void *), void *, int, char *); 78 int schizo_ue(void *); 79 int schizo_ce(void *); 80 int schizo_safari_error(void *); 81 int schizo_pci_error(void *); 82 83 pci_chipset_tag_t schizo_alloc_chipset(struct schizo_pbm *, int, 84 pci_chipset_tag_t); 85 bus_space_tag_t schizo_alloc_mem_tag(struct schizo_pbm *); 86 bus_space_tag_t schizo_alloc_io_tag(struct schizo_pbm *); 87 bus_space_tag_t schizo_alloc_config_tag(struct schizo_pbm *); 88 bus_space_tag_t schizo_alloc_bus_tag(struct schizo_pbm *, const char *, 89 int, int, int); 90 bus_dma_tag_t schizo_alloc_dma_tag(struct schizo_pbm *); 91 92 int schizo_conf_size(pci_chipset_tag_t, pcitag_t); 93 pcireg_t schizo_conf_read(pci_chipset_tag_t, pcitag_t, int); 94 void schizo_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t); 95 96 int schizo_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 97 int schizo_bus_map(bus_space_tag_t, bus_space_tag_t, bus_addr_t, 98 bus_size_t, int, bus_space_handle_t *); 99 paddr_t schizo_bus_mmap(bus_space_tag_t, bus_space_tag_t, bus_addr_t, off_t, 100 int, int); 101 bus_addr_t schizo_bus_addr(bus_space_tag_t, bus_space_tag_t, 102 bus_space_handle_t); 103 void *schizo_intr_establish(bus_space_tag_t, bus_space_tag_t, int, int, int, 104 int (*)(void *), void *, const char *); 105 106 int schizo_dmamap_create(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, int, 107 bus_size_t, bus_size_t, int, bus_dmamap_t *); 108 109 #ifdef DDB 110 void schizo_xir(void *, int); 111 #endif 112 113 int 114 schizo_match(struct device *parent, void *match, void *aux) 115 { 116 struct mainbus_attach_args *ma = aux; 117 char *str; 118 119 if (strcmp(ma->ma_name, "pci") != 0) 120 return (0); 121 122 str = getpropstring(ma->ma_node, "model"); 123 if (strcmp(str, "schizo") == 0) 124 return (1); 125 126 str = getpropstring(ma->ma_node, "compatible"); 127 if (strcmp(str, "pci108e,8001") == 0) 128 return (1); 129 if (strcmp(str, "pci108e,8002") == 0) /* XMITS */ 130 return (1); 131 if (strcmp(str, "pci108e,a801") == 0) /* Tomatillo */ 132 return (1); 133 134 return (0); 135 } 136 137 void 138 schizo_attach(struct device *parent, struct device *self, void *aux) 139 { 140 struct schizo_softc *sc = (struct schizo_softc *)self; 141 struct mainbus_attach_args *ma = aux; 142 int busa; 143 char *str; 144 145 str = getpropstring(ma->ma_node, "compatible"); 146 if (strcmp(str, "pci108e,a801") == 0) 147 sc->sc_tomatillo = 1; 148 149 sc->sc_node = ma->ma_node; 150 sc->sc_dmat = ma->ma_dmatag; 151 sc->sc_bust = ma->ma_bustag; 152 sc->sc_ctrl = ma->ma_reg[1].ur_paddr - 0x10000UL; 153 sc->sc_ign = INTIGN(ma->ma_upaid << INTMAP_IGN_SHIFT); 154 155 if ((ma->ma_reg[0].ur_paddr & 0x00700000) == 0x00600000) 156 busa = 1; 157 else 158 busa = 0; 159 160 if (bus_space_map(sc->sc_bust, sc->sc_ctrl, 161 sizeof(struct schizo_regs), 0, &sc->sc_ctrlh)) { 162 printf(": failed to map registers\n"); 163 return; 164 } 165 166 /* enable schizo ecc error interrupts */ 167 schizo_write(sc, SCZ_ECCCTRL, schizo_read(sc, SCZ_ECCCTRL) | 168 SCZ_ECCCTRL_EE_INTEN | SCZ_ECCCTRL_UE_INTEN | 169 SCZ_ECCCTRL_CE_INTEN); 170 171 schizo_init(sc, busa); 172 } 173 174 void 175 schizo_init(struct schizo_softc *sc, int busa) 176 { 177 struct schizo_pbm *pbm; 178 struct pcibus_attach_args pba; 179 int *busranges = NULL, nranges; 180 u_int64_t match, reg; 181 182 pbm = malloc(sizeof(*pbm), M_DEVBUF, M_NOWAIT | M_ZERO); 183 if (pbm == NULL) 184 panic("schizo: can't alloc schizo pbm"); 185 186 pbm->sp_sc = sc; 187 pbm->sp_bus_a = busa; 188 pbm->sp_regt = sc->sc_bust; 189 190 if (getprop(sc->sc_node, "ranges", sizeof(struct schizo_range), 191 &pbm->sp_nrange, (void **)&pbm->sp_range)) 192 panic("schizo: can't get ranges"); 193 194 if (getprop(sc->sc_node, "bus-range", sizeof(int), &nranges, 195 (void **)&busranges)) 196 panic("schizo: can't get bus-range"); 197 198 printf(": \"%s\", version %d, ign %x, bus %c %d to %d\n", 199 sc->sc_tomatillo ? "Tomatillo" : "Schizo", 200 getpropint(sc->sc_node, "version#", 0), sc->sc_ign, 201 busa ? 'A' : 'B', busranges[0], busranges[1]); 202 203 if (bus_space_subregion(pbm->sp_regt, sc->sc_ctrlh, 204 busa ? offsetof(struct schizo_regs, pbm_a) : 205 offsetof(struct schizo_regs, pbm_b), 206 sizeof(struct schizo_pbm_regs), 207 &pbm->sp_regh)) { 208 panic("schizo: unable to create PBM handle"); 209 } 210 211 printf("%s: ", sc->sc_dv.dv_xname); 212 schizo_init_iommu(sc, pbm); 213 214 match = schizo_read(sc, busa ? SCZ_PCIA_IO_MATCH : SCZ_PCIB_IO_MATCH); 215 pbm->sp_confpaddr = match & ~0x8000000000000000UL; 216 217 pbm->sp_memt = schizo_alloc_mem_tag(pbm); 218 pbm->sp_iot = schizo_alloc_io_tag(pbm); 219 pbm->sp_cfgt = schizo_alloc_config_tag(pbm); 220 pbm->sp_dmat = schizo_alloc_dma_tag(pbm); 221 222 if (bus_space_map(pbm->sp_cfgt, 0, 0x1000000, 0, &pbm->sp_cfgh)) 223 panic("schizo: can't map config space"); 224 225 pbm->sp_pc = schizo_alloc_chipset(pbm, sc->sc_node, 226 &_sparc_pci_chipset); 227 228 pbm->sp_pc->bustag = pbm->sp_cfgt; 229 pbm->sp_pc->bushandle = pbm->sp_cfgh; 230 231 bzero(&pba, sizeof(pba)); 232 pba.pba_busname = "pci"; 233 pba.pba_domain = pci_ndomains++; 234 pba.pba_bus = busranges[0]; 235 pba.pba_pc = pbm->sp_pc; 236 #if 0 237 pba.pba_flags = pbm->sp_flags; 238 #endif 239 pba.pba_dmat = pbm->sp_dmat; 240 pba.pba_memt = pbm->sp_memt; 241 pba.pba_iot = pbm->sp_iot; 242 pba.pba_pc->conf_size = schizo_conf_size; 243 pba.pba_pc->conf_read = schizo_conf_read; 244 pba.pba_pc->conf_write = schizo_conf_write; 245 pba.pba_pc->intr_map = schizo_intr_map; 246 247 free(busranges, M_DEVBUF, 0); 248 249 schizo_pbm_write(pbm, SCZ_PCI_INTR_RETRY, 5); 250 251 /* clear out the bus errors */ 252 schizo_pbm_write(pbm, SCZ_PCI_CTRL, schizo_pbm_read(pbm, SCZ_PCI_CTRL)); 253 schizo_pbm_write(pbm, SCZ_PCI_AFSR, schizo_pbm_read(pbm, SCZ_PCI_AFSR)); 254 schizo_cfg_write(pbm, PCI_COMMAND_STATUS_REG, 255 schizo_cfg_read(pbm, PCI_COMMAND_STATUS_REG)); 256 257 reg = schizo_pbm_read(pbm, SCZ_PCI_CTRL); 258 /* enable/disable error interrupts and arbiter */ 259 reg |= SCZ_PCICTRL_EEN | SCZ_PCICTRL_MMU_INT | SCZ_PCICTRL_ARB; 260 reg &= ~SCZ_PCICTRL_SBH_INT; 261 schizo_pbm_write(pbm, SCZ_PCI_CTRL, reg); 262 263 reg = schizo_pbm_read(pbm, SCZ_PCI_DIAG); 264 reg &= ~(SCZ_PCIDIAG_D_RTRYARB | SCZ_PCIDIAG_D_RETRY | 265 SCZ_PCIDIAG_D_INTSYNC); 266 schizo_pbm_write(pbm, SCZ_PCI_DIAG, reg); 267 268 if (busa) 269 schizo_set_intr(sc, pbm, PIL_HIGH, schizo_pci_error, 270 pbm, SCZ_PCIERR_A_INO, "pci_a"); 271 else 272 schizo_set_intr(sc, pbm, PIL_HIGH, schizo_pci_error, 273 pbm, SCZ_PCIERR_B_INO, "pci_b"); 274 275 /* double mapped */ 276 schizo_set_intr(sc, pbm, PIL_HIGH, schizo_ue, sc, SCZ_UE_INO, 277 "ue"); 278 schizo_set_intr(sc, pbm, PIL_HIGH, schizo_ce, sc, SCZ_CE_INO, 279 "ce"); 280 schizo_set_intr(sc, pbm, PIL_HIGH, schizo_safari_error, sc, 281 SCZ_SERR_INO, "safari"); 282 283 #ifdef DDB 284 /* 285 * Only a master Tomatillo (the one with JPID[0:2] = 6) 286 * can/should generate XIR. 287 */ 288 if (sc->sc_tomatillo && 289 ((schizo_read(sc, SCZ_CONTROL_STATUS) >> 20) & 0x7) == 6) 290 db_register_xir(schizo_xir, sc); 291 #endif 292 293 config_found(&sc->sc_dv, &pba, schizo_print); 294 } 295 296 int 297 schizo_ue(void *vsc) 298 { 299 struct schizo_softc *sc = vsc; 300 301 panic("%s: uncorrectable error", sc->sc_dv.dv_xname); 302 return (1); 303 } 304 305 int 306 schizo_ce(void *vsc) 307 { 308 struct schizo_softc *sc = vsc; 309 310 panic("%s: correctable error", sc->sc_dv.dv_xname); 311 return (1); 312 } 313 314 int 315 schizo_pci_error(void *vpbm) 316 { 317 struct schizo_pbm *sp = vpbm; 318 struct schizo_softc *sc = sp->sp_sc; 319 u_int64_t afsr, afar, ctrl; 320 u_int32_t csr; 321 322 afsr = schizo_pbm_read(sp, SCZ_PCI_AFSR); 323 afar = schizo_pbm_read(sp, SCZ_PCI_AFAR); 324 ctrl = schizo_pbm_read(sp, SCZ_PCI_CTRL); 325 csr = schizo_cfg_read(sp, PCI_COMMAND_STATUS_REG); 326 327 printf("%s: pci bus %c error\n", sc->sc_dv.dv_xname, 328 sp->sp_bus_a ? 'A' : 'B'); 329 330 printf("PCIAFSR=%llb\n", afsr, SCZ_PCIAFSR_BITS); 331 printf("PCIAFAR=%llx\n", afar); 332 printf("PCICTRL=%llb\n", ctrl, SCZ_PCICTRL_BITS); 333 printf("PCICSR=%b\n", csr, PCI_COMMAND_STATUS_BITS); 334 335 if (ctrl & SCZ_PCICTRL_MMU_ERR) { 336 u_int64_t ctrl, tfar; 337 338 ctrl = schizo_pbm_read(sp, SCZ_PCI_IOMMU_CTRL); 339 printf("IOMMUCTRL=%llx\n", ctrl); 340 341 if ((ctrl & TOM_IOMMU_ERR) == 0) 342 goto clear_error; 343 344 if (sc->sc_tomatillo) { 345 tfar = schizo_pbm_read(sp, TOM_PCI_IOMMU_TFAR); 346 printf("IOMMUTFAR=%llx\n", tfar); 347 } 348 349 /* These are non-fatal if target abort was signalled. */ 350 if ((ctrl & TOM_IOMMU_ERR_MASK) == TOM_IOMMU_INV_ERR || 351 ctrl & TOM_IOMMU_ILLTSBTBW_ERR || 352 ctrl & TOM_IOMMU_BADVA_ERR) { 353 if (csr & PCI_STATUS_TARGET_TARGET_ABORT) { 354 schizo_pbm_write(sp, SCZ_PCI_IOMMU_CTRL, ctrl); 355 goto clear_error; 356 } 357 } 358 } 359 360 panic("%s: fatal", sc->sc_dv.dv_xname); 361 362 clear_error: 363 schizo_cfg_write(sp, PCI_COMMAND_STATUS_REG, csr); 364 schizo_pbm_write(sp, SCZ_PCI_CTRL, ctrl); 365 schizo_pbm_write(sp, SCZ_PCI_AFSR, afsr); 366 return (1); 367 } 368 369 int 370 schizo_safari_error(void *vsc) 371 { 372 struct schizo_softc *sc = vsc; 373 374 printf("%s: safari error\n", sc->sc_dv.dv_xname); 375 376 printf("ERRLOG=%llx\n", schizo_read(sc, SCZ_SAFARI_ERRLOG)); 377 printf("UE_AFSR=%llx\n", schizo_read(sc, SCZ_UE_AFSR)); 378 printf("UE_AFAR=%llx\n", schizo_read(sc, SCZ_UE_AFAR)); 379 printf("CE_AFSR=%llx\n", schizo_read(sc, SCZ_CE_AFSR)); 380 printf("CE_AFAR=%llx\n", schizo_read(sc, SCZ_CE_AFAR)); 381 382 panic("%s: fatal", sc->sc_dv.dv_xname); 383 return (1); 384 } 385 386 void 387 schizo_init_iommu(struct schizo_softc *sc, struct schizo_pbm *pbm) 388 { 389 struct iommu_state *is = &pbm->sp_is; 390 int *vdma = NULL, nitem, tsbsize = 7; 391 u_int32_t iobase = -1; 392 vaddr_t va; 393 char *name; 394 395 va = (vaddr_t)pbm->sp_flush[0x40]; 396 397 is->is_bustag = pbm->sp_regt; 398 399 if (bus_space_subregion(is->is_bustag, pbm->sp_regh, 400 offsetof(struct schizo_pbm_regs, iommu), 401 sizeof(struct iommureg), &is->is_iommu)) { 402 panic("schizo: unable to create iommu handle"); 403 } 404 405 is->is_sb[0] = &pbm->sp_sb; 406 is->is_sb[0]->sb_bustag = is->is_bustag; 407 is->is_sb[0]->sb_flush = (void *)(va & ~0x3f); 408 409 if (bus_space_subregion(is->is_bustag, pbm->sp_regh, 410 offsetof(struct schizo_pbm_regs, strbuf), 411 sizeof(struct iommu_strbuf), &is->is_sb[0]->sb_sb)) { 412 panic("schizo: unable to create streaming buffer handle"); 413 is->is_sb[0]->sb_flush = NULL; 414 } 415 416 #if 1 417 /* XXX disable the streaming buffers for now */ 418 bus_space_write_8(is->is_bustag, is->is_sb[0]->sb_sb, 419 STRBUFREG(strbuf_ctl), 420 bus_space_read_8(is->is_bustag, is->is_sb[0]->sb_sb, 421 STRBUFREG(strbuf_ctl)) & ~STRBUF_EN); 422 is->is_sb[0]->sb_flush = NULL; 423 #endif 424 425 name = (char *)malloc(32, M_DEVBUF, M_NOWAIT); 426 if (name == NULL) 427 panic("couldn't malloc iommu name"); 428 snprintf(name, 32, "%s dvma", sc->sc_dv.dv_xname); 429 430 /* 431 * Separate the men from the boys. If the `virtual-dma' 432 * property exists, use it. 433 */ 434 if (!getprop(sc->sc_node, "virtual-dma", sizeof(vdma), &nitem, 435 (void **)&vdma)) { 436 /* Damn. Gotta use these values. */ 437 iobase = vdma[0]; 438 #define TSBCASE(x) case 1 << ((x) + 23): tsbsize = (x); break 439 switch (vdma[1]) { 440 TSBCASE(1); TSBCASE(2); TSBCASE(3); 441 TSBCASE(4); TSBCASE(5); TSBCASE(6); 442 default: 443 printf("bogus tsb size %x, using 7\n", vdma[1]); 444 TSBCASE(7); 445 } 446 #undef TSBCASE 447 DPRINTF(SDB_BUSMAP, ("schizo_iommu_init: iobase=0x%x\n", iobase)); 448 free(vdma, M_DEVBUF, 0); 449 } else { 450 DPRINTF(SDB_BUSMAP, ("schizo_iommu_init: getprop failed, " 451 "using iobase=0x%x, tsbsize=%d\n", iobase, tsbsize)); 452 } 453 454 iommu_init(name, is, tsbsize, iobase); 455 } 456 457 int 458 schizo_print(void *aux, const char *p) 459 { 460 if (p == NULL) 461 return (UNCONF); 462 return (QUIET); 463 } 464 465 int 466 schizo_conf_size(pci_chipset_tag_t pc, pcitag_t tag) 467 { 468 return PCI_CONFIG_SPACE_SIZE; 469 } 470 471 pcireg_t 472 schizo_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) 473 { 474 struct cpu_info *ci = curcpu(); 475 pcireg_t val; 476 int s; 477 478 s = splhigh(); 479 membar(Sync); 480 ci->ci_pci_probe = 1; 481 val = bus_space_read_4(pc->bustag, pc->bushandle, 482 PCITAG_OFFSET(tag) + reg); 483 membar(Sync); 484 if (ci->ci_pci_fault) 485 val = 0xffffffff; 486 ci->ci_pci_probe = ci->ci_pci_fault = 0; 487 splx(s); 488 489 return (val); 490 } 491 492 void 493 schizo_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 494 { 495 bus_space_write_4(pc->bustag, pc->bushandle, 496 PCITAG_OFFSET(tag) + reg, data); 497 } 498 499 /* 500 * Bus-specific interrupt mapping 501 */ 502 int 503 schizo_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 504 { 505 struct schizo_pbm *sp = pa->pa_pc->cookie; 506 struct schizo_softc *sc = sp->sp_sc; 507 u_int dev; 508 509 if (*ihp != (pci_intr_handle_t)-1) { 510 *ihp |= sc->sc_ign; 511 return (0); 512 } 513 514 /* 515 * We didn't find a PROM mapping for this interrupt. Try to 516 * construct one ourselves based on the swizzled interrupt pin 517 * and the interrupt mapping for PCI slots documented in the 518 * UltraSPARC-IIi User's Manual. 519 */ 520 521 if (pa->pa_intrpin == 0) 522 return (-1); 523 524 /* 525 * This deserves some documentation. Should anyone 526 * have anything official looking, please speak up. 527 */ 528 dev = pa->pa_device - 1; 529 530 *ihp = (pa->pa_intrpin - 1) & INTMAP_PCIINT; 531 *ihp |= (dev << 2) & INTMAP_PCISLOT; 532 *ihp |= sc->sc_ign; 533 534 return (0); 535 } 536 537 void 538 schizo_set_intr(struct schizo_softc *sc, struct schizo_pbm *pbm, int ipl, 539 int (*handler)(void *), void *arg, int ino, char *what) 540 { 541 struct intrhand *ih; 542 volatile u_int64_t *map, *clr; 543 struct schizo_pbm_regs *pbmreg; 544 char *name; 545 int nlen; 546 547 pbmreg = bus_space_vaddr(pbm->sp_regt, pbm->sp_regh); 548 map = &pbmreg->imap[ino]; 549 clr = &pbmreg->iclr[ino]; 550 ino |= sc->sc_ign; 551 552 nlen = strlen(sc->sc_dv.dv_xname) + 1 + strlen(what) + 1; 553 name = malloc(nlen, M_DEVBUF, M_WAITOK); 554 snprintf(name, nlen, "%s:%s", sc->sc_dv.dv_xname, what); 555 556 ih = bus_intr_allocate(pbm->sp_regt, handler, arg, ino, ipl, 557 map, clr, name); 558 if (ih == NULL) { 559 printf("set_intr failed...\n"); 560 free(name, M_DEVBUF, 0); 561 return; 562 } 563 564 intr_establish(ih->ih_pil, ih); 565 } 566 567 bus_space_tag_t 568 schizo_alloc_mem_tag(struct schizo_pbm *sp) 569 { 570 return (schizo_alloc_bus_tag(sp, "mem", 571 0x02, /* 32-bit mem space (where's the #define???) */ 572 ASI_PRIMARY, ASI_PRIMARY_LITTLE)); 573 } 574 575 bus_space_tag_t 576 schizo_alloc_io_tag(struct schizo_pbm *sp) 577 { 578 return (schizo_alloc_bus_tag(sp, "io", 579 0x01, /* IO space (where's the #define???) */ 580 ASI_PHYS_NON_CACHED_LITTLE, ASI_PHYS_NON_CACHED)); 581 } 582 583 bus_space_tag_t 584 schizo_alloc_config_tag(struct schizo_pbm *sp) 585 { 586 return (schizo_alloc_bus_tag(sp, "cfg", 587 0x00, /* Config space (where's the #define???) */ 588 ASI_PHYS_NON_CACHED_LITTLE, ASI_PHYS_NON_CACHED)); 589 } 590 591 bus_space_tag_t 592 schizo_alloc_bus_tag(struct schizo_pbm *pbm, const char *name, int ss, 593 int asi, int sasi) 594 { 595 struct schizo_softc *sc = pbm->sp_sc; 596 struct sparc_bus_space_tag *bt; 597 598 bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT | M_ZERO); 599 if (bt == NULL) 600 panic("schizo: could not allocate bus tag"); 601 602 snprintf(bt->name, sizeof(bt->name), "%s-pbm_%s(%d/%2.2x)", 603 sc->sc_dv.dv_xname, name, ss, asi); 604 605 bt->cookie = pbm; 606 bt->parent = sc->sc_bust; 607 bt->default_type = ss; 608 bt->asi = asi; 609 bt->sasi = sasi; 610 bt->sparc_bus_map = schizo_bus_map; 611 bt->sparc_bus_mmap = schizo_bus_mmap; 612 bt->sparc_bus_addr = schizo_bus_addr; 613 bt->sparc_intr_establish = schizo_intr_establish; 614 return (bt); 615 } 616 617 bus_dma_tag_t 618 schizo_alloc_dma_tag(struct schizo_pbm *pbm) 619 { 620 struct schizo_softc *sc = pbm->sp_sc; 621 bus_dma_tag_t dt, pdt = sc->sc_dmat; 622 623 dt = malloc(sizeof(*dt), M_DEVBUF, M_NOWAIT | M_ZERO); 624 if (dt == NULL) 625 panic("schizo: could not alloc dma tag"); 626 627 dt->_cookie = pbm; 628 dt->_parent = pdt; 629 dt->_dmamap_create = schizo_dmamap_create; 630 dt->_dmamap_destroy = iommu_dvmamap_destroy; 631 dt->_dmamap_load = iommu_dvmamap_load; 632 dt->_dmamap_load_raw = iommu_dvmamap_load_raw; 633 dt->_dmamap_unload = iommu_dvmamap_unload; 634 dt->_dmamap_sync = iommu_dvmamap_sync; 635 dt->_dmamem_alloc = iommu_dvmamem_alloc; 636 dt->_dmamem_free = iommu_dvmamem_free; 637 return (dt); 638 } 639 640 pci_chipset_tag_t 641 schizo_alloc_chipset(struct schizo_pbm *pbm, int node, pci_chipset_tag_t pc) 642 { 643 pci_chipset_tag_t npc; 644 645 npc = malloc(sizeof *npc, M_DEVBUF, M_NOWAIT); 646 if (npc == NULL) 647 panic("schizo: could not allocate pci_chipset_tag_t"); 648 memcpy(npc, pc, sizeof *pc); 649 npc->cookie = pbm; 650 npc->rootnode = node; 651 return (npc); 652 } 653 654 int 655 schizo_dmamap_create(bus_dma_tag_t t, bus_dma_tag_t t0, bus_size_t size, 656 int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags, 657 bus_dmamap_t *dmamp) 658 { 659 struct schizo_pbm *sp = t->_cookie; 660 661 return (iommu_dvmamap_create(t, t0, &sp->sp_sb, size, nsegments, 662 maxsegsz, boundary, flags, dmamp)); 663 } 664 665 int 666 schizo_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset, 667 bus_size_t size, int flags, bus_space_handle_t *hp) 668 { 669 struct schizo_pbm *pbm = t->cookie; 670 int i, ss; 671 672 DPRINTF(SDB_BUSMAP,("schizo_bus_map: type %d off %llx sz %llx flags %d", 673 t->default_type, 674 (unsigned long long)offset, 675 (unsigned long long)size, 676 flags)); 677 678 ss = t->default_type; 679 DPRINTF(SDB_BUSMAP, (" cspace %d", ss)); 680 681 if (t->parent == 0 || t->parent->sparc_bus_map == 0) { 682 printf("\nschizo_bus_map: invalid parent"); 683 return (EINVAL); 684 } 685 686 if (flags & BUS_SPACE_MAP_PROMADDRESS) { 687 return ((*t->parent->sparc_bus_map) 688 (t, t0, offset, size, flags, hp)); 689 } 690 691 for (i = 0; i < pbm->sp_nrange; i++) { 692 bus_addr_t paddr; 693 694 if (((pbm->sp_range[i].cspace >> 24) & 0x03) != ss) 695 continue; 696 697 paddr = pbm->sp_range[i].phys_lo + offset; 698 paddr |= ((bus_addr_t)pbm->sp_range[i].phys_hi) << 32; 699 return ((*t->parent->sparc_bus_map) 700 (t, t0, paddr, size, flags, hp)); 701 } 702 703 return (EINVAL); 704 } 705 706 paddr_t 707 schizo_bus_mmap(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t paddr, 708 off_t off, int prot, int flags) 709 { 710 bus_addr_t offset = paddr; 711 struct schizo_pbm *pbm = t->cookie; 712 int i, ss; 713 714 ss = t->default_type; 715 716 DPRINTF(SDB_BUSMAP, ("schizo_bus_mmap: prot %d flags %d pa %llx\n", 717 prot, flags, (unsigned long long)paddr)); 718 719 if (t->parent == 0 || t->parent->sparc_bus_mmap == 0) { 720 printf("\nschizo_bus_mmap: invalid parent"); 721 return (-1); 722 } 723 724 for (i = 0; i < pbm->sp_nrange; i++) { 725 bus_addr_t paddr; 726 727 if (((pbm->sp_range[i].cspace >> 24) & 0x03) != ss) 728 continue; 729 730 paddr = pbm->sp_range[i].phys_lo + offset; 731 paddr |= ((bus_addr_t)pbm->sp_range[i].phys_hi) << 32; 732 return ((*t->parent->sparc_bus_mmap) 733 (t, t0, paddr, off, prot, flags)); 734 } 735 736 return (-1); 737 } 738 739 bus_addr_t 740 schizo_bus_addr(bus_space_tag_t t, bus_space_tag_t t0, bus_space_handle_t h) 741 { 742 struct schizo_pbm *pbm = t->cookie; 743 bus_addr_t addr; 744 int i, ss; 745 746 ss = t->default_type; 747 748 if (t->parent == 0 || t->parent->sparc_bus_addr == 0) { 749 printf("\nschizo_bus_addr: invalid parent"); 750 return (-1); 751 } 752 753 t = t->parent; 754 755 addr = ((*t->sparc_bus_addr)(t, t0, h)); 756 if (addr == -1) 757 return (-1); 758 759 for (i = 0; i < pbm->sp_nrange; i++) { 760 if (((pbm->sp_range[i].cspace >> 24) & 0x03) != ss) 761 continue; 762 763 return (BUS_ADDR_PADDR(addr) - pbm->sp_range[i].phys_lo); 764 } 765 766 return (-1); 767 } 768 769 void * 770 schizo_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, 771 int level, int flags, int (*handler)(void *), void *arg, const char *what) 772 { 773 struct schizo_pbm *pbm = t->cookie; 774 struct intrhand *ih = NULL; 775 volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL; 776 int ino; 777 long vec = INTVEC(ihandle); 778 779 vec = INTVEC(ihandle); 780 ino = INTINO(vec); 781 782 if (level == IPL_NONE) 783 level = INTLEV(vec); 784 if (level == IPL_NONE) { 785 printf(": no IPL, setting IPL 2.\n"); 786 level = 2; 787 } 788 789 if ((flags & BUS_INTR_ESTABLISH_SOFTINTR) == 0) { 790 struct schizo_pbm_regs *pbmreg; 791 792 pbmreg = bus_space_vaddr(pbm->sp_regt, pbm->sp_regh); 793 intrmapptr = &pbmreg->imap[ino]; 794 intrclrptr = &pbmreg->iclr[ino]; 795 if (INTIGN(vec) == 0) 796 ino |= (*intrmapptr) & INTMAP_IGN; 797 else 798 ino |= vec & INTMAP_IGN; 799 } 800 801 ih = bus_intr_allocate(t0, handler, arg, ino, level, intrmapptr, 802 intrclrptr, what); 803 if (ih == NULL) 804 return (NULL); 805 806 if (flags & BUS_INTR_ESTABLISH_MPSAFE) 807 ih->ih_mpsafe = 1; 808 809 intr_establish(ih->ih_pil, ih); 810 811 if (intrmapptr != NULL) { 812 u_int64_t intrmap; 813 814 intrmap = *intrmapptr; 815 intrmap |= INTMAP_V; 816 *intrmapptr = intrmap; 817 intrmap = *intrmapptr; 818 ih->ih_number |= intrmap & INTMAP_INR; 819 } 820 821 return (ih); 822 } 823 824 #ifdef DDB 825 void 826 schizo_xir(void *arg, int cpu) 827 { 828 struct schizo_softc *sc = arg; 829 830 schizo_write(sc, TOM_RESET_GEN, TOM_RESET_GEN_XIR); 831 } 832 #endif 833 834 const struct cfattach schizo_ca = { 835 sizeof(struct schizo_softc), schizo_match, schizo_attach 836 }; 837 838 struct cfdriver schizo_cd = { 839 NULL, "schizo", DV_DULL 840 }; 841