1 /* $NetBSD: schizo.c,v 1.16 2010/03/11 03:54:56 mrg Exp $ */ 2 /* $OpenBSD: schizo.c,v 1.55 2008/08/18 20:29:37 brad Exp $ */ 3 4 /* 5 * Copyright (c) 2002 Jason L. Wright (jason@thought.net) 6 * Copyright (c) 2003 Henric Jungheim 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 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/device.h> 33 #include <sys/errno.h> 34 #include <sys/extent.h> 35 #include <sys/malloc.h> 36 #include <sys/systm.h> 37 #include <sys/time.h> 38 #include <sys/reboot.h> 39 40 #define _SPARC_BUS_DMA_PRIVATE 41 #include <machine/bus.h> 42 #include <machine/autoconf.h> 43 #include <machine/psl.h> 44 45 #include <dev/pci/pcivar.h> 46 #include <dev/pci/pcireg.h> 47 48 #include <sparc64/dev/iommureg.h> 49 #include <sparc64/dev/iommuvar.h> 50 #include <sparc64/dev/schizoreg.h> 51 #include <sparc64/dev/schizovar.h> 52 #include <sparc64/sparc64/cache.h> 53 54 #ifdef DEBUG 55 #define SDB_PROM 0x01 56 #define SDB_BUSMAP 0x02 57 #define SDB_INTR 0x04 58 #define SDB_INTMAP 0x08 59 #define SDB_CONF 0x10 60 int schizo_debug = 0x0; 61 #define DPRINTF(l, s) do { if (schizo_debug & l) printf s; } while (0) 62 #else 63 #define DPRINTF(l, s) 64 #endif 65 66 extern struct sparc_pci_chipset _sparc_pci_chipset; 67 68 static int schizo_match(struct device *, struct cfdata *, void *); 69 static void schizo_attach(struct device *, struct device *, void *); 70 static int schizo_print(void *aux, const char *p); 71 72 CFATTACH_DECL(schizo, sizeof(struct schizo_softc), 73 schizo_match, schizo_attach, NULL, NULL); 74 75 void schizo_init_iommu(struct schizo_softc *, struct schizo_pbm *); 76 77 void schizo_set_intr(struct schizo_softc *, struct schizo_pbm *, int, 78 int (*handler)(void *), void *, int, const char *); 79 int schizo_ue(void *); 80 int schizo_ce(void *); 81 int schizo_safari_error(void *); 82 int schizo_pci_error(void *); 83 84 pci_chipset_tag_t schizo_alloc_chipset(struct schizo_pbm *, int, 85 pci_chipset_tag_t); 86 bus_space_tag_t schizo_alloc_mem_tag(struct schizo_pbm *); 87 bus_space_tag_t schizo_alloc_io_tag(struct schizo_pbm *); 88 bus_space_tag_t schizo_alloc_config_tag(struct schizo_pbm *); 89 bus_space_tag_t schizo_alloc_bus_tag(struct schizo_pbm *, const char *, 90 int); 91 bus_dma_tag_t schizo_alloc_dma_tag(struct schizo_pbm *); 92 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_bus_map(bus_space_tag_t t, bus_addr_t offset, bus_size_t size, 97 int flags, vaddr_t unused, bus_space_handle_t *hp); 98 static paddr_t schizo_bus_mmap(bus_space_tag_t t, bus_addr_t paddr, 99 off_t off, int prot, int flags); 100 static void *schizo_intr_establish(bus_space_tag_t, int, int, int (*)(void *), 101 void *, void(*)(void)); 102 static int schizo_pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 103 static void *schizo_pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, 104 int, int (*)(void *), void *); 105 static int schizo_pci_find_ino(struct pci_attach_args *, pci_intr_handle_t *); 106 static int schizo_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, 107 bus_size_t, int, bus_dmamap_t *); 108 109 int 110 schizo_match(struct device *parent, struct cfdata *match, void *aux) 111 { 112 struct mainbus_attach_args *ma = aux; 113 char *str; 114 115 if (strcmp(ma->ma_name, "pci") != 0) 116 return (0); 117 118 str = prom_getpropstring(ma->ma_node, "model"); 119 if (strcmp(str, "schizo") == 0) 120 return (1); 121 122 str = prom_getpropstring(ma->ma_node, "compatible"); 123 if (strcmp(str, "pci108e,8001") == 0) 124 return (1); 125 if (strcmp(str, "pci108e,8002") == 0) /* XMITS */ 126 return (1); 127 if (strcmp(str, "pci108e,a801") == 0) /* Tomatillo */ 128 return (1); 129 130 return (0); 131 } 132 133 void 134 schizo_attach(struct device *parent, struct device *self, void *aux) 135 { 136 struct schizo_softc *sc = (struct schizo_softc *)self; 137 struct mainbus_attach_args *ma = aux; 138 struct schizo_pbm *pbm; 139 struct iommu_state *is; 140 struct pcibus_attach_args pba; 141 uint64_t reg, eccctrl; 142 int *busranges = NULL, nranges; 143 char *str; 144 145 aprint_normal(": addr %" PRIx64, ma->ma_reg[0].ur_paddr); 146 str = prom_getpropstring(ma->ma_node, "compatible"); 147 if (strcmp(str, "pci108e,a801") == 0) 148 sc->sc_tomatillo = 1; 149 150 sc->sc_node = ma->ma_node; 151 sc->sc_dmat = ma->ma_dmatag; 152 sc->sc_bustag = ma->ma_bustag; 153 154 if (bus_space_map(sc->sc_bustag, ma->ma_reg[1].ur_paddr - 0x10000UL, 155 sizeof(struct schizo_regs), 0, 156 &sc->sc_ctrlh)) { 157 aprint_error(": failed to map registers\n"); 158 return; 159 } 160 161 sc->sc_ign = INTIGN(ma->ma_upaid << INTMAP_IGN_SHIFT); 162 163 /* enable schizo ecc error interrupts */ 164 eccctrl = schizo_read(sc, SCZ_ECCCTRL); 165 eccctrl |= SCZ_ECCCTRL_EE_INTEN | 166 SCZ_ECCCTRL_UE_INTEN | 167 SCZ_ECCCTRL_CE_INTEN; 168 schizo_write(sc, SCZ_ECCCTRL, eccctrl); 169 170 pbm = malloc(sizeof(*pbm), M_DEVBUF, M_NOWAIT | M_ZERO); 171 if (pbm == NULL) 172 panic("schizo: can't alloc schizo pbm"); 173 174 pbm->sp_sc = sc; 175 pbm->sp_regt = sc->sc_bustag; 176 177 if ((ma->ma_reg[0].ur_paddr & 0x00700000) == 0x00600000) 178 pbm->sp_bus_a = 1; 179 else 180 pbm->sp_bus_a = 0; 181 182 /* 183 * Map interrupt registers 184 */ 185 if (bus_space_map(sc->sc_bustag, ma->ma_reg[0].ur_paddr, 186 ma->ma_reg[0].ur_len, 187 BUS_SPACE_MAP_LINEAR, &pbm->sp_intrh)) { 188 aprint_error(": failed to interrupt map registers\n"); 189 return; 190 } 191 192 if (prom_getprop(sc->sc_node, "ranges", sizeof(struct schizo_range), 193 &pbm->sp_nrange, (void **)&pbm->sp_range)) 194 panic("schizo: can't get ranges"); 195 196 if (prom_getprop(sc->sc_node, "bus-range", sizeof(int), &nranges, 197 (void **)&busranges)) 198 panic("schizo: can't get bus-range"); 199 200 aprint_normal(": \"%s\", version %d, ign %x, bus %c %d to %d\n", 201 sc->sc_tomatillo ? "Tomatillo" : "Schizo", 202 prom_getpropint(sc->sc_node, "version#", 0), sc->sc_ign, 203 pbm->sp_bus_a ? 'A' : 'B', busranges[0], busranges[1]); 204 aprint_naive("\n"); 205 206 if (bus_space_subregion(pbm->sp_regt, sc->sc_ctrlh, 207 pbm->sp_bus_a ? offsetof(struct schizo_regs, pbm_a) : 208 offsetof(struct schizo_regs, pbm_b), 209 sizeof(struct schizo_pbm_regs), 210 &pbm->sp_regh)) { 211 panic("schizo: unable to create PBM handle"); 212 } 213 214 is = &pbm->sp_is; 215 pbm->sp_sb.sb_is = is; 216 if (prom_getproplen(sc->sc_node, "no-streaming-cache") < 0) { 217 vaddr_t va = (vaddr_t)&pbm->sp_flush[0x40]; 218 219 /* 220 * Initialize the strbuf_ctl. 221 * 222 * The flush sync buffer must be 64-byte aligned. 223 */ 224 is->is_sb[0] = &pbm->sp_sb; 225 is->is_sb[0]->sb_flush = (void *)(va & ~0x3f); 226 227 bus_space_subregion(pbm->sp_regt, pbm->sp_regh, 228 offsetof(struct schizo_pbm_regs, strbuf), 229 sizeof(struct iommu_strbuf), &is->is_sb[0]->sb_sb); 230 } else { 231 aprint_debug("%s: no streaming buffers\n", sc->sc_dv.dv_xname); 232 } 233 234 aprint_normal("%s: ", sc->sc_dv.dv_xname); 235 schizo_init_iommu(sc, pbm); 236 237 pbm->sp_memt = schizo_alloc_mem_tag(pbm); 238 pbm->sp_iot = schizo_alloc_io_tag(pbm); 239 pbm->sp_cfgt = schizo_alloc_config_tag(pbm); 240 pbm->sp_dmat = schizo_alloc_dma_tag(pbm); 241 pbm->sp_flags = (pbm->sp_memt ? PCI_FLAGS_MEM_ENABLED : 0) | 242 (pbm->sp_iot ? PCI_FLAGS_IO_ENABLED : 0); 243 244 if (bus_space_map(pbm->sp_cfgt, 0, 0x1000000, 0, &pbm->sp_cfgh)) 245 panic("schizo: could not map config space"); 246 247 pbm->sp_pc = schizo_alloc_chipset(pbm, sc->sc_node, 248 &_sparc_pci_chipset); 249 pbm->sp_pc->spc_busmax = busranges[1]; 250 pbm->sp_pc->spc_busnode = malloc(sizeof(*pbm->sp_pc->spc_busnode), 251 M_DEVBUF, M_NOWAIT | M_ZERO); 252 if (pbm->sp_pc->spc_busnode == NULL) 253 panic("schizo: malloc busnode"); 254 255 pba.pba_bus = busranges[0]; 256 pba.pba_bridgetag = NULL; 257 pba.pba_pc = pbm->sp_pc; 258 pba.pba_flags = pbm->sp_flags; 259 pba.pba_dmat = pbm->sp_dmat; 260 pba.pba_dmat64 = NULL; /* XXX */ 261 pba.pba_memt = pbm->sp_memt; 262 pba.pba_iot = pbm->sp_iot; 263 264 free(busranges, M_DEVBUF); 265 266 schizo_pbm_write(pbm, SCZ_PCI_INTR_RETRY, 5); 267 268 /* clear out the bus errors */ 269 schizo_pbm_write(pbm, SCZ_PCI_CTRL, schizo_pbm_read(pbm, SCZ_PCI_CTRL)); 270 schizo_pbm_write(pbm, SCZ_PCI_AFSR, schizo_pbm_read(pbm, SCZ_PCI_AFSR)); 271 schizo_cfg_write(pbm, PCI_COMMAND_STATUS_REG, 272 schizo_cfg_read(pbm, PCI_COMMAND_STATUS_REG)); 273 274 reg = schizo_pbm_read(pbm, SCZ_PCI_CTRL); 275 /* enable/disable error interrupts and arbiter */ 276 reg |= SCZ_PCICTRL_EEN | SCZ_PCICTRL_MMU_INT | SCZ_PCICTRL_ARB; 277 reg &= ~SCZ_PCICTRL_SBH_INT; 278 schizo_pbm_write(pbm, SCZ_PCI_CTRL, reg); 279 280 reg = schizo_pbm_read(pbm, SCZ_PCI_DIAG); 281 reg &= ~(SCZ_PCIDIAG_D_RTRYARB | SCZ_PCIDIAG_D_RETRY | 282 SCZ_PCIDIAG_D_INTSYNC); 283 schizo_pbm_write(pbm, SCZ_PCI_DIAG, reg); 284 285 if (pbm->sp_bus_a) 286 schizo_set_intr(sc, pbm, PIL_HIGH, schizo_pci_error, 287 pbm, SCZ_PCIERR_A_INO, "pci_a"); 288 else 289 schizo_set_intr(sc, pbm, PIL_HIGH, schizo_pci_error, 290 pbm, SCZ_PCIERR_B_INO, "pci_b"); 291 292 /* double mapped */ 293 schizo_set_intr(sc, pbm, PIL_HIGH, schizo_ue, sc, SCZ_UE_INO, 294 "ue"); 295 schizo_set_intr(sc, pbm, PIL_HIGH, schizo_ce, sc, SCZ_CE_INO, 296 "ce"); 297 schizo_set_intr(sc, pbm, PIL_HIGH, schizo_safari_error, sc, 298 SCZ_SERR_INO, "safari"); 299 300 config_found(&sc->sc_dv, &pba, schizo_print); 301 } 302 303 int 304 schizo_ue(void *vsc) 305 { 306 struct schizo_softc *sc = vsc; 307 308 panic("%s: uncorrectable error", sc->sc_dv.dv_xname); 309 return (1); 310 } 311 312 int 313 schizo_ce(void *vsc) 314 { 315 struct schizo_softc *sc = vsc; 316 317 panic("%s: correctable error", sc->sc_dv.dv_xname); 318 return (1); 319 } 320 321 int 322 schizo_pci_error(void *vpbm) 323 { 324 struct schizo_pbm *sp = vpbm; 325 struct schizo_softc *sc = sp->sp_sc; 326 u_int64_t afsr, afar, ctrl, tfar; 327 u_int32_t csr; 328 char bits[128]; 329 330 afsr = schizo_pbm_read(sp, SCZ_PCI_AFSR); 331 afar = schizo_pbm_read(sp, SCZ_PCI_AFAR); 332 ctrl = schizo_pbm_read(sp, SCZ_PCI_CTRL); 333 csr = schizo_cfg_read(sp, PCI_COMMAND_STATUS_REG); 334 335 printf("%s: pci bus %c error\n", sc->sc_dv.dv_xname, 336 sp->sp_bus_a ? 'A' : 'B'); 337 338 snprintb(bits, sizeof(bits), SCZ_PCIAFSR_BITS, afsr); 339 printf("PCIAFSR=%s\n", bits); 340 printf("PCIAFAR=%" PRIx64 "\n", afar); 341 snprintb(bits, sizeof(bits), SCZ_PCICTRL_BITS, ctrl); 342 printf("PCICTRL=%s\n", bits); 343 #ifdef PCI_COMMAND_STATUS_BITS 344 snprintb(bits, sizeof(bits), PCI_COMMAND_STATUS_BITS, csr); 345 printf("PCICSR=%s\n", bits); 346 #endif 347 348 if (ctrl & SCZ_PCICTRL_MMU_ERR) { 349 ctrl = schizo_pbm_read(sp, SCZ_PCI_IOMMU_CTRL); 350 printf("IOMMUCTRL=%" PRIx64 "\n", ctrl); 351 352 if ((ctrl & TOM_IOMMU_ERR) == 0) 353 goto clear_error; 354 355 if (sc->sc_tomatillo) { 356 tfar = schizo_pbm_read(sp, TOM_PCI_IOMMU_TFAR); 357 printf("IOMMUTFAR=%" PRIx64 "\n", tfar); 358 } 359 360 /* These are non-fatal if target abort was signalled. */ 361 if ((ctrl & TOM_IOMMU_ERR_MASK) == TOM_IOMMU_INV_ERR || 362 ctrl & TOM_IOMMU_ILLTSBTBW_ERR || 363 ctrl & TOM_IOMMU_BADVA_ERR) { 364 if (csr & PCI_STATUS_TARGET_TARGET_ABORT) { 365 schizo_pbm_write(sp, SCZ_PCI_IOMMU_CTRL, ctrl); 366 goto clear_error; 367 } 368 } 369 } 370 371 panic("%s: fatal", sc->sc_dv.dv_xname); 372 373 clear_error: 374 schizo_cfg_write(sp, PCI_COMMAND_STATUS_REG, csr); 375 schizo_pbm_write(sp, SCZ_PCI_CTRL, ctrl); 376 schizo_pbm_write(sp, SCZ_PCI_AFSR, afsr); 377 return (1); 378 } 379 380 int 381 schizo_safari_error(void *vsc) 382 { 383 struct schizo_softc *sc = vsc; 384 385 printf("%s: safari error\n", sc->sc_dv.dv_xname); 386 387 printf("ERRLOG=%" PRIx64 "\n", schizo_read(sc, SCZ_SAFARI_ERRLOG)); 388 printf("UE_AFSR=%" PRIx64 "\n", schizo_read(sc, SCZ_UE_AFSR)); 389 printf("UE_AFAR=%" PRIx64 "\n", schizo_read(sc, SCZ_UE_AFAR)); 390 printf("CE_AFSR=%" PRIx64 "\n", schizo_read(sc, SCZ_CE_AFSR)); 391 printf("CE_AFAR=%" PRIx64 "\n", schizo_read(sc, SCZ_CE_AFAR)); 392 393 panic("%s: fatal", sc->sc_dv.dv_xname); 394 return (1); 395 } 396 397 void 398 schizo_init_iommu(struct schizo_softc *sc, struct schizo_pbm *pbm) 399 { 400 struct iommu_state *is = &pbm->sp_is; 401 int *vdma = NULL, nitem, tsbsize = 7; 402 u_int32_t iobase = -1; 403 char *name; 404 405 /* punch in our copies */ 406 is->is_bustag = pbm->sp_regt; 407 bus_space_subregion(is->is_bustag, pbm->sp_regh, 408 offsetof(struct schizo_pbm_regs, iommu), 409 sizeof(struct schizo_iommureg), 410 &is->is_iommu); 411 412 /* 413 * Separate the men from the boys. If the `virtual-dma' 414 * property exists, use it. 415 */ 416 if (!prom_getprop(sc->sc_node, "virtual-dma", sizeof(vdma), &nitem, 417 (void **)&vdma)) { 418 /* Damn. Gotta use these values. */ 419 iobase = vdma[0]; 420 #define TSBCASE(x) case 1 << ((x) + 23): tsbsize = (x); break 421 switch (vdma[1]) { 422 TSBCASE(1); TSBCASE(2); TSBCASE(3); 423 TSBCASE(4); TSBCASE(5); TSBCASE(6); 424 default: 425 printf("bogus tsb size %x, using 7\n", vdma[1]); 426 TSBCASE(7); 427 } 428 #undef TSBCASE 429 DPRINTF(SDB_BUSMAP, ("schizo_init_iommu: iobase=0x%x\n", iobase)); 430 free(vdma, M_DEVBUF); 431 } else { 432 DPRINTF(SDB_BUSMAP, ("schizo_init_iommu: getprop failed, " 433 "using iobase=0x%x, tsbsize=%d\n", iobase, tsbsize)); 434 } 435 436 /* give us a nice name.. */ 437 name = (char *)malloc(32, M_DEVBUF, M_NOWAIT); 438 if (name == NULL) 439 panic("couldn't malloc iommu name"); 440 snprintf(name, 32, "%s dvma", sc->sc_dv.dv_xname); 441 442 iommu_init(name, is, tsbsize, iobase); 443 } 444 445 int 446 schizo_print(void *aux, const char *p) 447 { 448 449 if (p == NULL) 450 return (UNCONF); 451 return (QUIET); 452 } 453 454 pcireg_t 455 schizo_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) 456 { 457 struct schizo_pbm *sp = pc->cookie; 458 pcireg_t val = (pcireg_t)~0; 459 460 DPRINTF(SDB_CONF, ("%s: tag %lx reg %x ", __func__, (long)tag, reg)); 461 if (PCITAG_NODE(tag) != -1) 462 val = bus_space_read_4(sp->sp_cfgt, sp->sp_cfgh, 463 PCITAG_OFFSET(tag) + reg); 464 DPRINTF(SDB_CONF, (" returning %08x\n", (u_int)val)); 465 return (val); 466 } 467 468 void 469 schizo_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 470 { 471 struct schizo_pbm *sp = pc->cookie; 472 473 DPRINTF(SDB_CONF, ("%s: tag %lx; reg %x; data %x", __func__, 474 (long)tag, reg, (int)data)); 475 476 /* If we don't know it, just punt it. */ 477 if (PCITAG_NODE(tag) == -1) { 478 DPRINTF(SDB_CONF, (" .. bad addr\n")); 479 return; 480 } 481 482 bus_space_write_4(sp->sp_cfgt, sp->sp_cfgh, 483 PCITAG_OFFSET(tag) + reg, data); 484 DPRINTF(SDB_CONF, (" .. done\n")); 485 } 486 487 void 488 schizo_set_intr(struct schizo_softc *sc, struct schizo_pbm *pbm, int ipl, 489 int (*handler)(void *), void *arg, int ino, const char *what) 490 { 491 struct intrhand *ih; 492 u_int64_t mapoff, clroff; 493 uintptr_t intrregs; 494 495 DPRINTF(SDB_INTR, ("%s: ino %x ign %x fn %p arg %p", __func__, 496 ino, sc->sc_ign, handler, arg)); 497 498 mapoff = offsetof(struct schizo_pbm_regs, imap[ino]); 499 clroff = offsetof(struct schizo_pbm_regs, iclr[ino]); 500 ino |= sc->sc_ign; 501 502 DPRINTF(SDB_INTR, (" mapoff %" PRIx64 " clroff %" PRIx64 "\n", 503 mapoff, clroff)); 504 505 ih = (struct intrhand *) 506 malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT); 507 if (ih == NULL) 508 return; 509 ih->ih_arg = arg; 510 intrregs = (uintptr_t)bus_space_vaddr(pbm->sp_regt, pbm->sp_intrh); 511 ih->ih_map = (uint64_t *)(uintptr_t)(intrregs + mapoff); 512 ih->ih_clr = (uint64_t *)(uintptr_t)(intrregs + clroff); 513 ih->ih_fun = handler; 514 ih->ih_pil = (1<<ipl); 515 ih->ih_number = INTVEC(schizo_pbm_read(pbm, mapoff)); 516 intr_establish(ipl, ipl != IPL_VM, ih); 517 518 schizo_pbm_write(pbm, mapoff, 519 ih->ih_number | INTMAP_V | (CPU_UPAID << INTMAP_TID_SHIFT)); 520 } 521 522 bus_space_tag_t 523 schizo_alloc_mem_tag(struct schizo_pbm *sp) 524 { 525 return (schizo_alloc_bus_tag(sp, "mem", 526 PCI_MEMORY_BUS_SPACE)); 527 } 528 529 bus_space_tag_t 530 schizo_alloc_io_tag(struct schizo_pbm *sp) 531 { 532 return (schizo_alloc_bus_tag(sp, "io", 533 PCI_IO_BUS_SPACE)); 534 } 535 536 bus_space_tag_t 537 schizo_alloc_config_tag(struct schizo_pbm *sp) 538 { 539 return (schizo_alloc_bus_tag(sp, "cfg", 540 PCI_CONFIG_BUS_SPACE)); 541 } 542 543 bus_space_tag_t 544 schizo_alloc_bus_tag(struct schizo_pbm *pbm, const char *name, int type) 545 { 546 struct schizo_softc *sc = pbm->sp_sc; 547 bus_space_tag_t bt; 548 549 bt = (bus_space_tag_t) malloc(sizeof(struct sparc_bus_space_tag), 550 M_DEVBUF, M_NOWAIT | M_ZERO); 551 if (bt == NULL) 552 panic("schizo: could not allocate bus tag"); 553 554 bt->cookie = pbm; 555 bt->parent = sc->sc_bustag; 556 bt->type = type; 557 bt->sparc_bus_map = schizo_bus_map; 558 bt->sparc_bus_mmap = schizo_bus_mmap; 559 bt->sparc_intr_establish = schizo_intr_establish; 560 return (bt); 561 } 562 563 bus_dma_tag_t 564 schizo_alloc_dma_tag(struct schizo_pbm *pbm) 565 { 566 struct schizo_softc *sc = pbm->sp_sc; 567 bus_dma_tag_t dt, pdt = sc->sc_dmat; 568 569 dt = malloc(sizeof(*dt), M_DEVBUF, M_NOWAIT | M_ZERO); 570 if (dt == NULL) 571 panic("schizo: could not alloc dma tag"); 572 573 dt->_cookie = pbm; 574 dt->_parent = pdt; 575 #define PCOPY(x) dt->x = pdt->x 576 dt->_dmamap_create = schizo_dmamap_create; 577 PCOPY(_dmamap_destroy); 578 dt->_dmamap_load = iommu_dvmamap_load; 579 PCOPY(_dmamap_load_mbuf); 580 PCOPY(_dmamap_load_uio); 581 dt->_dmamap_load_raw = iommu_dvmamap_load_raw; 582 dt->_dmamap_unload = iommu_dvmamap_unload; 583 dt->_dmamap_sync = iommu_dvmamap_sync; 584 dt->_dmamem_alloc = iommu_dvmamem_alloc; 585 dt->_dmamem_free = iommu_dvmamem_free; 586 dt->_dmamem_map = iommu_dvmamem_map; 587 dt->_dmamem_unmap = iommu_dvmamem_unmap; 588 PCOPY(_dmamem_mmap); 589 #undef PCOPY 590 return (dt); 591 } 592 593 pci_chipset_tag_t 594 schizo_alloc_chipset(struct schizo_pbm *pbm, int node, pci_chipset_tag_t pc) 595 { 596 pci_chipset_tag_t npc; 597 598 npc = malloc(sizeof *npc, M_DEVBUF, M_NOWAIT); 599 if (npc == NULL) 600 panic("schizo: could not allocate pci_chipset_tag_t"); 601 memcpy(npc, pc, sizeof *pc); 602 npc->cookie = pbm; 603 npc->rootnode = node; 604 npc->spc_conf_read = schizo_conf_read; 605 npc->spc_conf_write = schizo_conf_write; 606 npc->spc_intr_map = schizo_pci_intr_map; 607 npc->spc_intr_establish = schizo_pci_intr_establish; 608 npc->spc_find_ino = schizo_pci_find_ino; 609 return (npc); 610 } 611 612 int 613 schizo_dmamap_create(bus_dma_tag_t t, bus_size_t size, 614 int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags, 615 bus_dmamap_t *dmamp) 616 { 617 struct schizo_pbm *pbm = t->_cookie; 618 int error; 619 620 error = bus_dmamap_create(t->_parent, size, nsegments, maxsegsz, 621 boundary, flags, dmamp); 622 if (error == 0) 623 (*dmamp)->_dm_cookie = &pbm->sp_sb; 624 return error; 625 } 626 627 static struct schizo_range * 628 get_schizorange(struct schizo_pbm *pbm, int ss) 629 { 630 int i; 631 632 for (i = 0; i < pbm->sp_nrange; i++) { 633 if (((pbm->sp_range[i].cspace >> 24) & 0x03) == ss) 634 return (&pbm->sp_range[i]); 635 } 636 /* not found */ 637 return (NULL); 638 } 639 640 int 641 schizo_bus_map(bus_space_tag_t t, bus_addr_t offset, bus_size_t size, 642 int flags, vaddr_t unused, bus_space_handle_t *hp) 643 { 644 bus_addr_t paddr; 645 struct schizo_pbm *pbm = t->cookie; 646 struct schizo_softc *sc = pbm->sp_sc; 647 struct schizo_range *sr; 648 int ss; 649 650 DPRINTF(SDB_BUSMAP, ("schizo_bus_map: type %d off %qx sz %qx flags %d", 651 t->type, 652 (unsigned long long)offset, 653 (unsigned long long)size, 654 flags)); 655 656 ss = sparc_pci_childspace(t->type); 657 DPRINTF(SDB_BUSMAP, (" cspace %d\n", ss)); 658 659 sr = get_schizorange(pbm, ss); 660 if (sr != NULL) { 661 paddr = BUS_ADDR(sr->phys_hi, sr->phys_lo + offset); 662 DPRINTF(SDB_BUSMAP, ("%s: mapping paddr " 663 "space %lx offset %lx paddr %qx\n", 664 __func__, (long)ss, (long)offset, 665 (unsigned long long)paddr)); 666 return ((*sc->sc_bustag->sparc_bus_map)(t, paddr, size, 667 flags, 0, hp)); 668 } 669 DPRINTF(SDB_BUSMAP, ("%s: FAILED\n", __func__)); 670 return (EINVAL); 671 } 672 673 static paddr_t 674 schizo_bus_mmap(bus_space_tag_t t, bus_addr_t paddr, off_t off, int prot, 675 int flags) 676 { 677 bus_addr_t offset = paddr; 678 struct schizo_pbm *pbm = t->cookie; 679 struct schizo_softc *sc = pbm->sp_sc; 680 struct schizo_range *sr; 681 int ss; 682 683 ss = sparc_pci_childspace(t->type); 684 685 DPRINTF(SDB_BUSMAP, ("schizo_bus_mmap: prot %d flags %d pa %qx\n", 686 prot, flags, (unsigned long long)paddr)); 687 688 sr = get_schizorange(pbm, ss); 689 if (sr != NULL) { 690 paddr = BUS_ADDR(sr->phys_hi, sr->phys_lo + offset); 691 DPRINTF(SDB_BUSMAP, ("%s: mapping paddr " 692 "space %lx offset %lx paddr %qx\n", 693 __func__, (long)ss, (long)offset, 694 (unsigned long long)paddr)); 695 return (bus_space_mmap(sc->sc_bustag, paddr, off, 696 prot, flags)); 697 } 698 DPRINTF(SDB_BUSMAP, ("%s: FAILED\n", __func__)); 699 return (-1); 700 } 701 702 /* 703 * Set the IGN for this schizo into the handle. 704 */ 705 int 706 schizo_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 707 { 708 struct schizo_pbm *pbm = pa->pa_pc->cookie; 709 struct schizo_softc *sc = pbm->sp_sc; 710 711 *ihp |= sc->sc_ign; 712 DPRINTF(SDB_INTMAP, ("returning IGN adjusted to %x\n", *ihp)); 713 return (0); 714 } 715 716 static void * 717 schizo_intr_establish(bus_space_tag_t t, int ihandle, int level, 718 int (*handler)(void *), void *arg, void (*fastvec)(void) /* ignored */) 719 { 720 struct schizo_pbm *pbm = t->cookie; 721 struct intrhand *ih = NULL; 722 uint64_t mapoff, clroff; 723 uintptr_t intrregs; 724 volatile uint64_t *intrmapptr = NULL, *intrclrptr = NULL; 725 int ino; 726 long vec; 727 728 vec = INTVEC(ihandle); 729 ino = INTINO(vec); 730 731 ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT); 732 if (ih == NULL) 733 return (NULL); 734 735 DPRINTF(SDB_INTR, ("\n%s: ihandle %d level %d fn %p arg %p\n", __func__, 736 ihandle, level, handler, arg)); 737 738 if (level == IPL_NONE) 739 level = INTLEV(vec); 740 if (level == IPL_NONE) { 741 printf(": no IPL, setting IPL 2.\n"); 742 level = 2; 743 } 744 745 mapoff = offsetof(struct schizo_pbm_regs, imap[ino]); 746 clroff = offsetof(struct schizo_pbm_regs, iclr[ino]); 747 748 DPRINTF(SDB_INTR, ("%s: intr %x: %p mapoff %" PRIx64 " clroff %" 749 PRIx64 "\n", __func__, ino, intrlev[ino], mapoff, clroff)); 750 751 intrregs = (uintptr_t)bus_space_vaddr(pbm->sp_regt, pbm->sp_intrh); 752 intrmapptr = (uint64_t *)(uintptr_t)(intrregs + mapoff); 753 intrclrptr = (uint64_t *)(uintptr_t)(intrregs + clroff); 754 755 if (INTIGN(vec) == 0) 756 ino |= schizo_pbm_readintr(pbm, mapoff) & INTMAP_IGN; 757 else 758 ino |= vec & INTMAP_IGN; 759 760 /* Register the map and clear intr registers */ 761 ih->ih_map = intrmapptr; 762 ih->ih_clr = intrclrptr; 763 764 ih->ih_fun = handler; 765 ih->ih_arg = arg; 766 ih->ih_pil = level; 767 ih->ih_number = ino; 768 769 DPRINTF(SDB_INTR, ( 770 "; installing handler %p arg %p with inr %x pil %u\n", 771 handler, arg, ino, (u_int)ih->ih_pil)); 772 773 intr_establish(ih->ih_pil, level != IPL_VM, ih); 774 775 /* 776 * Enable the interrupt now we have the handler installed. 777 * Read the current value as we can't change it besides the 778 * valid bit so so make sure only this bit is changed. 779 */ 780 if (intrmapptr) { 781 u_int64_t imap; 782 783 imap = schizo_pbm_readintr(pbm, mapoff); 784 DPRINTF(SDB_INTR, ("; read intrmap = %016qx", 785 (unsigned long long)imap)); 786 imap |= INTMAP_V; 787 DPRINTF(SDB_INTR, ("; addr of intrmapptr = %p", intrmapptr)); 788 DPRINTF(SDB_INTR, ("; writing intrmap = %016qx\n", 789 (unsigned long long)imap)); 790 schizo_pbm_writeintr(pbm, mapoff, imap); 791 imap = schizo_pbm_readintr(pbm, mapoff); 792 DPRINTF(SDB_INTR, ("; reread intrmap = %016qx", 793 (unsigned long long)imap)); 794 ih->ih_number |= imap & INTMAP_INR; 795 } 796 if (intrclrptr) { 797 /* set state to IDLE */ 798 schizo_pbm_writeintr(pbm, clroff, 0); 799 } 800 801 return (ih); 802 } 803 804 static void * 805 schizo_pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, 806 int (*func)(void *), void *arg) 807 { 808 void *cookie; 809 struct schizo_pbm *pbm = (struct schizo_pbm *)pc->cookie; 810 811 DPRINTF(SDB_INTR, ("%s: ih %lx; level %d", __func__, (u_long)ih, level)); 812 cookie = bus_intr_establish(pbm->sp_memt, ih, level, func, arg); 813 814 DPRINTF(SDB_INTR, ("; returning handle %p\n", cookie)); 815 return (cookie); 816 } 817 818 static int 819 schizo_pci_find_ino(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 820 { 821 #if 0 822 struct schizo_pbm *pbm = pa->pa_pc->cookie; 823 struct schizo_softc *sc = pbm->sp_sc; 824 u_int bus; 825 u_int dev; 826 u_int pin; 827 #endif 828 829 DPRINTF(SDB_INTMAP, ("pci_find_ino: pa_tag: node %x, %d:%d:%d\n", 830 PCITAG_NODE(pa->pa_tag), (int)PCITAG_BUS(pa->pa_tag), 831 (int)PCITAG_DEV(pa->pa_tag), 832 (int)PCITAG_FUN(pa->pa_tag))); 833 DPRINTF(SDB_INTMAP, 834 ("pci_find_ino: intrswiz %d, intrpin %d, intrline %d, rawintrpin %d\n", 835 pa->pa_intrswiz, pa->pa_intrpin, pa->pa_intrline, pa->pa_rawintrpin)); 836 DPRINTF(SDB_INTMAP, ("pci_find_ino: pa_intrtag: node %x, %d:%d:%d\n", 837 PCITAG_NODE(pa->pa_intrtag), 838 (int)PCITAG_BUS(pa->pa_intrtag), 839 (int)PCITAG_DEV(pa->pa_intrtag), 840 (int)PCITAG_FUN(pa->pa_intrtag))); 841 842 #if 0 843 bus = (pp->pp_id == PSYCHO_PBM_B); 844 /* 845 * If we are on a ppb, use the devno on the underlying bus when forming 846 * the ivec. 847 */ 848 if (pa->pa_intrswiz != 0 && PCITAG_NODE(pa->pa_intrtag) != 0) 849 dev = PCITAG_DEV(pa->pa_intrtag); 850 else 851 dev = pa->pa_device; 852 dev--; 853 854 if (sc->sc_mode == PSYCHO_MODE_PSYCHO && 855 pp->pp_id == PSYCHO_PBM_B) 856 dev--; 857 858 pin = pa->pa_intrpin - 1; 859 DPRINTF(SDB_INTMAP, ("pci_find_ino: mode %d, pbm %d, dev %d, pin %d\n", 860 sc->sc_mode, pp->pp_id, dev, pin)); 861 862 *ihp = sc->sc_ign | ((bus << 4) & INTMAP_PCIBUS) | 863 ((dev << 2) & INTMAP_PCISLOT) | (pin & INTMAP_PCIINT); 864 #endif 865 866 return (0); 867 } 868