1 /* $OpenBSD: ebus.c,v 1.25 2019/12/05 12:46:54 mpi Exp $ */ 2 /* $NetBSD: ebus.c,v 1.24 2001/07/25 03:49:54 eeh Exp $ */ 3 4 /* 5 * Copyright (c) 1999, 2000 Matthew R. Green 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 WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * UltraSPARC 5 and beyond ebus support. 32 * 33 * note that this driver is not complete: 34 * - ebus2 dma code is completely unwritten 35 * - interrupt establish is written and appears to work 36 * - bus map code is written and appears to work 37 */ 38 39 #ifdef DEBUG 40 #define EDB_PROM 0x01 41 #define EDB_CHILD 0x02 42 #define EDB_INTRMAP 0x04 43 #define EDB_BUSMAP 0x08 44 #define EDB_BUSDMA 0x10 45 #define EDB_INTR 0x20 46 int ebus_debug = 0x0; 47 #define DPRINTF(l, s) do { if (ebus_debug & l) printf s; } while (0) 48 #else 49 #define DPRINTF(l, s) 50 #endif 51 52 #include <sys/param.h> 53 #include <sys/conf.h> 54 #include <sys/device.h> 55 #include <sys/errno.h> 56 #include <sys/extent.h> 57 #include <sys/malloc.h> 58 #include <sys/systm.h> 59 #include <sys/time.h> 60 61 #define _SPARC_BUS_DMA_PRIVATE 62 #include <machine/bus.h> 63 #include <machine/autoconf.h> 64 #include <machine/openfirm.h> 65 66 #include <dev/pci/pcivar.h> 67 #include <dev/pci/pcireg.h> 68 #include <dev/pci/pcidevs.h> 69 70 #include <sparc64/dev/iommureg.h> 71 #include <sparc64/dev/iommuvar.h> 72 #include <sparc64/dev/psychoreg.h> 73 #include <sparc64/dev/psychovar.h> 74 #include <sparc64/dev/ebusreg.h> 75 #include <sparc64/dev/ebusvar.h> 76 #include <sparc64/sparc64/cache.h> 77 78 int ebus_match(struct device *, void *, void *); 79 void ebus_attach(struct device *, struct device *, void *); 80 81 struct cfattach ebus_ca = { 82 sizeof(struct ebus_softc), ebus_match, ebus_attach 83 }; 84 85 struct cfdriver ebus_cd = { 86 NULL, "ebus", DV_DULL 87 }; 88 89 90 void ebus_find_ino(struct ebus_softc *, struct ebus_attach_args *); 91 int ebus_find_node(struct pci_attach_args *); 92 93 /* 94 * here are our bus space and bus dma routines. 95 */ 96 static paddr_t ebus_bus_mmap(bus_space_tag_t, bus_space_tag_t, bus_addr_t, 97 off_t, int, int); 98 static int _ebus_bus_map(bus_space_tag_t, bus_space_tag_t, bus_addr_t, 99 bus_size_t, int, bus_space_handle_t *); 100 bus_space_tag_t ebus_alloc_mem_tag(struct ebus_softc *, bus_space_tag_t); 101 bus_space_tag_t ebus_alloc_io_tag(struct ebus_softc *, bus_space_tag_t); 102 bus_space_tag_t _ebus_alloc_bus_tag(struct ebus_softc *sc, const char *, 103 bus_space_tag_t, int); 104 105 106 int 107 ebus_match(struct device *parent, void *match, void *aux) 108 { 109 struct pci_attach_args *pa = aux; 110 char name[10]; 111 int node; 112 113 /* Only attach if there's a PROM node. */ 114 node = PCITAG_NODE(pa->pa_tag); 115 if (node == -1) return (0); 116 117 /* Match a real ebus */ 118 OF_getprop(node, "name", &name, sizeof(name)); 119 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 120 PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN && 121 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_EBUS && 122 strcmp(name, "ebus") == 0) 123 return (1); 124 125 /* Or a real RIO ebus */ 126 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 127 PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN && 128 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_RIO_EBUS && 129 strcmp(name, "ebus") == 0) 130 return (1); 131 132 /* Or a fake ebus */ 133 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 134 PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALTERA && 135 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALTERA_EBUS && 136 strcmp(name, "ebus") == 0) 137 return (1); 138 139 /* Or a PCI-ISA bridge XXX I hope this is on-board. */ 140 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 141 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA) { 142 return (1); 143 } 144 145 return (0); 146 } 147 148 /* 149 * attach an ebus and all its children. this code is modeled 150 * after the sbus code which does similar things. 151 */ 152 void 153 ebus_attach(struct device *parent, struct device *self, void *aux) 154 { 155 struct ebus_softc *sc = (struct ebus_softc *)self; 156 struct pci_attach_args *pa = aux; 157 struct ebus_attach_args eba; 158 struct ebus_interrupt_map_mask *immp; 159 int node, nmapmask, error; 160 161 printf("\n"); 162 163 sc->sc_memtag = ebus_alloc_mem_tag(sc, pa->pa_memt); 164 sc->sc_iotag = ebus_alloc_io_tag(sc, pa->pa_iot); 165 sc->sc_dmatag = ebus_alloc_dma_tag(sc, pa->pa_dmat); 166 167 node = PCITAG_NODE(pa->pa_tag); 168 if (node == -1) 169 panic("could not find ebus node"); 170 171 sc->sc_node = node; 172 173 /* 174 * fill in our softc with information from the prom 175 */ 176 sc->sc_intmap = NULL; 177 sc->sc_range = NULL; 178 error = getprop(node, "interrupt-map", 179 sizeof(struct ebus_interrupt_map), 180 &sc->sc_nintmap, (void **)&sc->sc_intmap); 181 switch (error) { 182 case 0: 183 immp = &sc->sc_intmapmask; 184 error = getprop(node, "interrupt-map-mask", 185 sizeof(struct ebus_interrupt_map_mask), &nmapmask, 186 (void **)&immp); 187 if (error) 188 panic("could not get ebus interrupt-map-mask"); 189 if (nmapmask != 1) 190 panic("ebus interrupt-map-mask is broken"); 191 break; 192 case ENOENT: 193 break; 194 default: 195 panic("ebus interrupt-map: error %d", error); 196 break; 197 } 198 199 error = getprop(node, "ranges", sizeof(struct ebus_ranges), 200 &sc->sc_nrange, &sc->sc_range); 201 if (error) 202 panic("ebus ranges: error %d", error); 203 204 /* 205 * now attach all our children 206 */ 207 DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node)); 208 for (node = firstchild(node); node; node = nextsibling(node)) { 209 if (!checkstatus(node)) 210 continue; 211 212 if (ebus_setup_attach_args(sc, node, &eba) != 0) { 213 DPRINTF(EDB_CHILD, 214 ("ebus_attach: %s: incomplete\n", 215 getpropstring(node, "name"))); 216 continue; 217 } else { 218 DPRINTF(EDB_CHILD, ("- found child `%s', attaching\n", 219 eba.ea_name)); 220 (void)config_found(self, &eba, ebus_print); 221 } 222 ebus_destroy_attach_args(&eba); 223 } 224 } 225 226 int 227 ebus_setup_attach_args(struct ebus_softc *sc, int node, 228 struct ebus_attach_args *ea) 229 { 230 int n, rv; 231 232 bzero(ea, sizeof(struct ebus_attach_args)); 233 rv = getprop(node, "name", 1, &n, (void **)&ea->ea_name); 234 if (rv != 0) 235 return (rv); 236 ea->ea_name[n] = '\0'; 237 238 ea->ea_node = node; 239 ea->ea_memtag = sc->sc_memtag; 240 ea->ea_iotag = sc->sc_iotag; 241 ea->ea_dmatag = sc->sc_dmatag; 242 243 rv = getprop(node, "reg", sizeof(struct ebus_regs), &ea->ea_nregs, 244 (void **)&ea->ea_regs); 245 if (rv) 246 return (rv); 247 248 rv = getprop(node, "address", sizeof(u_int32_t), &ea->ea_nvaddrs, 249 (void **)&ea->ea_vaddrs); 250 if (rv != ENOENT) { 251 if (rv) 252 return (rv); 253 254 if (ea->ea_nregs != ea->ea_nvaddrs) 255 printf("ebus loses: device %s: %d regs and %d addrs\n", 256 ea->ea_name, ea->ea_nregs, ea->ea_nvaddrs); 257 } else 258 ea->ea_nvaddrs = 0; 259 260 if (getprop(node, "interrupts", sizeof(u_int32_t), &ea->ea_nintrs, 261 (void **)&ea->ea_intrs)) 262 ea->ea_nintrs = 0; 263 else 264 ebus_find_ino(sc, ea); 265 266 return (0); 267 } 268 269 void 270 ebus_destroy_attach_args(struct ebus_attach_args *ea) 271 { 272 if (ea->ea_name) 273 free((void *)ea->ea_name, M_DEVBUF, 0); 274 if (ea->ea_regs) 275 free((void *)ea->ea_regs, M_DEVBUF, 0); 276 if (ea->ea_intrs) 277 free((void *)ea->ea_intrs, M_DEVBUF, 0); 278 if (ea->ea_vaddrs) 279 free((void *)ea->ea_vaddrs, M_DEVBUF, 0); 280 } 281 282 int 283 ebus_print(void *aux, const char *p) 284 { 285 struct ebus_attach_args *ea = aux; 286 int i; 287 288 if (p) 289 printf("\"%s\" at %s", ea->ea_name, p); 290 for (i = 0; i < ea->ea_nregs; i++) 291 printf("%s %x-%x", i == 0 ? " addr" : ",", 292 ea->ea_regs[i].lo, 293 ea->ea_regs[i].lo + ea->ea_regs[i].size - 1); 294 for (i = 0; i < ea->ea_nintrs; i++) 295 printf(" ivec 0x%x", ea->ea_intrs[i]); 296 return (UNCONF); 297 } 298 299 300 /* 301 * find the INO values for each interrupt and fill them in. 302 * 303 * for each "reg" property of this device, mask its hi and lo 304 * values with the "interrupt-map-mask"'s hi/lo values, and also 305 * mask the interrupt number with the interrupt mask. search the 306 * "interrupt-map" list for matching values of hi, lo and interrupt 307 * to give the INO for this interrupt. 308 */ 309 void 310 ebus_find_ino(struct ebus_softc *sc, struct ebus_attach_args *ea) 311 { 312 u_int32_t hi, lo, intr; 313 int i, j, k; 314 315 if (sc->sc_nintmap == 0) { 316 for (i = 0; i < ea->ea_nintrs; i++) { 317 OF_mapintr(ea->ea_node, &ea->ea_intrs[i], 318 sizeof(ea->ea_intrs[0]), 319 sizeof(ea->ea_intrs[0])); 320 } 321 return; 322 } 323 324 DPRINTF(EDB_INTRMAP, 325 ("ebus_find_ino: searching %d interrupts", ea->ea_nintrs)); 326 327 for (j = 0; j < ea->ea_nintrs; j++) { 328 329 intr = ea->ea_intrs[j] & sc->sc_intmapmask.intr; 330 331 DPRINTF(EDB_INTRMAP, 332 ("; intr %x masked to %x", ea->ea_intrs[j], intr)); 333 for (i = 0; i < ea->ea_nregs; i++) { 334 hi = ea->ea_regs[i].hi & sc->sc_intmapmask.hi; 335 lo = ea->ea_regs[i].lo & sc->sc_intmapmask.lo; 336 337 DPRINTF(EDB_INTRMAP, 338 ("; reg hi.lo %08x.%08x masked to %08x.%08x", 339 ea->ea_regs[i].hi, ea->ea_regs[i].lo, hi, lo)); 340 for (k = 0; k < sc->sc_nintmap; k++) { 341 DPRINTF(EDB_INTRMAP, 342 ("; checking hi.lo %08x.%08x intr %x", 343 sc->sc_intmap[k].hi, sc->sc_intmap[k].lo, 344 sc->sc_intmap[k].intr)); 345 if (hi == sc->sc_intmap[k].hi && 346 lo == sc->sc_intmap[k].lo && 347 intr == sc->sc_intmap[k].intr) { 348 ea->ea_intrs[j] = 349 sc->sc_intmap[k].cintr; 350 DPRINTF(EDB_INTRMAP, 351 ("; FOUND IT! changing to %d\n", 352 sc->sc_intmap[k].cintr)); 353 goto next_intr; 354 } 355 } 356 } 357 next_intr:; 358 } 359 } 360 361 bus_space_tag_t 362 ebus_alloc_mem_tag(struct ebus_softc *sc, bus_space_tag_t parent) 363 { 364 return (_ebus_alloc_bus_tag(sc, "mem", parent, 365 0x02)); /* 32-bit mem space (where's the #define???) */ 366 } 367 368 bus_space_tag_t 369 ebus_alloc_io_tag(struct ebus_softc *sc, bus_space_tag_t parent) 370 { 371 return (_ebus_alloc_bus_tag(sc, "io", parent, 372 0x01)); /* IO space (where's the #define???) */ 373 } 374 375 /* 376 * bus space and bus dma below here 377 */ 378 bus_space_tag_t 379 _ebus_alloc_bus_tag(struct ebus_softc *sc, const char *name, 380 bus_space_tag_t parent, int ss) 381 { 382 struct sparc_bus_space_tag *bt; 383 384 bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT | M_ZERO); 385 if (bt == NULL) 386 panic("could not allocate ebus bus tag"); 387 388 snprintf(bt->name, sizeof(bt->name), "%s_%s", 389 sc->sc_dev.dv_xname, name); 390 bt->cookie = sc; 391 bt->parent = parent; 392 bt->default_type = ss; 393 bt->asi = parent->asi; 394 bt->sasi = parent->sasi; 395 bt->sparc_bus_map = _ebus_bus_map; 396 bt->sparc_bus_mmap = ebus_bus_mmap; 397 398 return (bt); 399 } 400 401 bus_dma_tag_t 402 ebus_alloc_dma_tag(struct ebus_softc *sc, bus_dma_tag_t pdt) 403 { 404 bus_dma_tag_t dt; 405 406 dt = malloc(sizeof(*dt), M_DEVBUF, M_NOWAIT | M_ZERO); 407 if (dt == NULL) 408 panic("could not allocate ebus dma tag"); 409 410 dt->_cookie = sc; 411 dt->_parent = pdt; 412 sc->sc_dmatag = dt; 413 return (dt); 414 } 415 416 /* 417 * bus space support. <sparc64/dev/psychoreg.h> has a discussion 418 * about PCI physical addresses, which also applies to ebus. 419 */ 420 static int 421 _ebus_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset, 422 bus_size_t size, int flags, bus_space_handle_t *hp) 423 { 424 struct ebus_softc *sc = t->cookie; 425 struct ebus_ranges *range = sc->sc_range; 426 bus_addr_t hi, lo; 427 int i; 428 429 DPRINTF(EDB_BUSMAP, 430 ("\n_ebus_bus_map: type %d off %016llx sz %x flags %d", 431 (int)t->default_type, (unsigned long long)offset, (int)size, 432 (int)flags)); 433 434 if (t->parent == 0 || t->parent->sparc_bus_map == 0) { 435 printf("\n_ebus_bus_map: invalid parent"); 436 return (EINVAL); 437 } 438 439 t = t->parent; 440 441 if (flags & BUS_SPACE_MAP_PROMADDRESS) { 442 return ((*t->sparc_bus_map) 443 (t, t0, offset, size, flags, hp)); 444 } 445 446 hi = offset >> 32UL; 447 lo = offset & 0xffffffff; 448 449 DPRINTF(EDB_BUSMAP, (" (hi %08x lo %08x)", (u_int)hi, (u_int)lo)); 450 for (i = 0; i < sc->sc_nrange; i++) { 451 bus_addr_t pciaddr; 452 453 if (hi != range[i].child_hi) 454 continue; 455 if (lo < range[i].child_lo || 456 (lo + size) > (range[i].child_lo + range[i].size)) 457 continue; 458 459 if(((range[i].phys_hi >> 24) & 3) != t->default_type) 460 continue; 461 462 pciaddr = ((bus_addr_t)range[i].phys_mid << 32UL) | 463 range[i].phys_lo; 464 pciaddr += lo; 465 DPRINTF(EDB_BUSMAP, 466 ("\n_ebus_bus_map: mapping space %x paddr offset %llx " 467 "pciaddr %llx\n", (int)t->default_type, 468 (unsigned long long)offset, (unsigned long long)pciaddr)); 469 return ((*t->sparc_bus_map)(t, t0, pciaddr, size, flags, hp)); 470 } 471 DPRINTF(EDB_BUSMAP, (": FAILED\n")); 472 return (EINVAL); 473 } 474 475 static paddr_t 476 ebus_bus_mmap(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t paddr, 477 off_t off, int prot, int flags) 478 { 479 bus_addr_t offset = paddr; 480 struct ebus_softc *sc = t->cookie; 481 struct ebus_ranges *range = sc->sc_range; 482 int i; 483 484 if (t->parent == 0 || t->parent->sparc_bus_mmap == 0) { 485 printf("\nebus_bus_mmap: invalid parent"); 486 return (-1); 487 } 488 489 t = t->parent; 490 491 for (i = 0; i < sc->sc_nrange; i++) { 492 bus_addr_t paddr = ((bus_addr_t)range[i].child_hi << 32) | 493 range[i].child_lo; 494 495 if (offset != paddr) 496 continue; 497 498 DPRINTF(EDB_BUSMAP, ("\n_ebus_bus_mmap: mapping paddr %llx\n", 499 (unsigned long long)paddr)); 500 return ((*t->sparc_bus_mmap)(t, t0, paddr, off, prot, flags)); 501 } 502 503 return (-1); 504 } 505