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