1 /* $NetBSD: ebus.c,v 1.31 2002/03/16 14:00:00 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 <dev/ebus/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_addr_t, bus_size_t, int, 119 vaddr_t, bus_space_handle_t *)); 120 static void *ebus_intr_establish __P((bus_space_tag_t, int, int, int, 121 int (*) __P((void *)), void *)); 122 123 int 124 ebus_match(parent, match, aux) 125 struct device *parent; 126 struct cfdata *match; 127 void *aux; 128 { 129 struct pci_attach_args *pa = aux; 130 char name[10]; 131 int node; 132 133 /* Only attach if there's a PROM node. */ 134 node = PCITAG_NODE(pa->pa_tag); 135 if (node == -1) return (0); 136 137 /* Match a real ebus */ 138 OF_getprop(node, "name", &name, sizeof(name)); 139 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 140 PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN && 141 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_EBUS && 142 strcmp(name, "ebus") == 0) 143 return (1); 144 145 /* Or a real ebus III */ 146 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 147 PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN && 148 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_EBUSIII && 149 strcmp(name, "ebus") == 0) 150 return (1); 151 152 /* Or a PCI-ISA bridge XXX I hope this is on-board. */ 153 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 154 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA) { 155 return (1); 156 } 157 158 return (0); 159 } 160 161 /* 162 * attach an ebus and all it's children. this code is modeled 163 * after the sbus code which does similar things. 164 */ 165 void 166 ebus_attach(parent, self, aux) 167 struct device *parent, *self; 168 void *aux; 169 { 170 struct ebus_softc *sc = (struct ebus_softc *)self; 171 struct pci_attach_args *pa = aux; 172 struct ebus_attach_args eba; 173 struct ebus_interrupt_map_mask *immp; 174 int node, nmapmask, error; 175 char devinfo[256]; 176 177 printf("\n"); 178 179 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 180 printf("%s: %s, revision 0x%02x\n", self->dv_xname, devinfo, 181 PCI_REVISION(pa->pa_class)); 182 183 sc->sc_memtag = pa->pa_memt; 184 sc->sc_iotag = pa->pa_iot; 185 sc->sc_childbustag = ebus_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE); 186 sc->sc_dmatag = pa->pa_dmat; 187 188 node = PCITAG_NODE(pa->pa_tag); 189 if (node == -1) 190 panic("could not find ebus node"); 191 192 sc->sc_node = node; 193 194 /* 195 * fill in our softc with information from the prom 196 */ 197 sc->sc_intmap = NULL; 198 sc->sc_range = NULL; 199 error = PROM_getprop(node, "interrupt-map", 200 sizeof(struct ebus_interrupt_map), 201 &sc->sc_nintmap, (void **)&sc->sc_intmap); 202 switch (error) { 203 case 0: 204 immp = &sc->sc_intmapmask; 205 error = PROM_getprop(node, "interrupt-map-mask", 206 sizeof(struct ebus_interrupt_map_mask), &nmapmask, 207 (void **)&immp); 208 if (error) 209 panic("could not get ebus interrupt-map-mask"); 210 if (nmapmask != 1) 211 panic("ebus interrupt-map-mask is broken"); 212 break; 213 case ENOENT: 214 break; 215 default: 216 panic("ebus interrupt-map: error %d", error); 217 break; 218 } 219 220 error = PROM_getprop(node, "ranges", sizeof(struct ebus_ranges), 221 &sc->sc_nrange, (void **)&sc->sc_range); 222 if (error) 223 panic("ebus ranges: error %d", error); 224 225 /* 226 * now attach all our children 227 */ 228 DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node)); 229 for (node = firstchild(node); node; node = nextsibling(node)) { 230 char *name = PROM_getpropstring(node, "name"); 231 232 if (ebus_setup_attach_args(sc, node, &eba) != 0) { 233 printf("ebus_attach: %s: incomplete\n", name); 234 continue; 235 } else { 236 DPRINTF(EDB_CHILD, ("- found child `%s', attaching\n", 237 eba.ea_name)); 238 (void)config_found(self, &eba, ebus_print); 239 } 240 ebus_destroy_attach_args(&eba); 241 } 242 } 243 244 int 245 ebus_setup_attach_args(sc, node, ea) 246 struct ebus_softc *sc; 247 int node; 248 struct ebus_attach_args *ea; 249 { 250 int n, rv; 251 252 bzero(ea, sizeof(struct ebus_attach_args)); 253 rv = PROM_getprop(node, "name", 1, &n, (void **)&ea->ea_name); 254 if (rv != 0) 255 return (rv); 256 ea->ea_name[n] = '\0'; 257 258 ea->ea_node = node; 259 ea->ea_bustag = sc->sc_childbustag; 260 ea->ea_dmatag = sc->sc_dmatag; 261 262 rv = PROM_getprop(node, "reg", sizeof(struct ebus_regs), &ea->ea_nreg, 263 (void **)&ea->ea_reg); 264 if (rv) 265 return (rv); 266 267 rv = PROM_getprop(node, "address", sizeof(u_int32_t), &ea->ea_nvaddr, 268 (void **)&ea->ea_vaddr); 269 if (rv != ENOENT) { 270 if (rv) 271 return (rv); 272 273 if (ea->ea_nreg != ea->ea_nvaddr) 274 printf("ebus loses: device %s: %d regs and %d addrs\n", 275 ea->ea_name, ea->ea_nreg, ea->ea_nvaddr); 276 } else 277 ea->ea_nvaddr = 0; 278 279 if (PROM_getprop(node, "interrupts", sizeof(u_int32_t), &ea->ea_nintr, 280 (void **)&ea->ea_intr)) 281 ea->ea_nintr = 0; 282 else 283 ebus_find_ino(sc, ea); 284 285 return (0); 286 } 287 288 void 289 ebus_destroy_attach_args(ea) 290 struct ebus_attach_args *ea; 291 { 292 293 if (ea->ea_name) 294 free((void *)ea->ea_name, M_DEVBUF); 295 if (ea->ea_reg) 296 free((void *)ea->ea_reg, M_DEVBUF); 297 if (ea->ea_intr) 298 free((void *)ea->ea_intr, M_DEVBUF); 299 if (ea->ea_vaddr) 300 free((void *)ea->ea_vaddr, M_DEVBUF); 301 } 302 303 int 304 ebus_print(aux, p) 305 void *aux; 306 const char *p; 307 { 308 struct ebus_attach_args *ea = aux; 309 int i; 310 311 if (p) 312 printf("%s at %s", ea->ea_name, p); 313 for (i = 0; i < ea->ea_nreg; i++) 314 printf("%s %x-%x", i == 0 ? " addr" : ",", 315 ea->ea_reg[i].lo, 316 ea->ea_reg[i].lo + ea->ea_reg[i].size - 1); 317 for (i = 0; i < ea->ea_nintr; i++) 318 printf(" ipl %d", ea->ea_intr[i]); 319 return (UNCONF); 320 } 321 322 323 /* 324 * find the INO values for each interrupt and fill them in. 325 * 326 * for each "reg" property of this device, mask it's hi and lo 327 * values with the "interrupt-map-mask"'s hi/lo values, and also 328 * mask the interrupt number with the interrupt mask. search the 329 * "interrupt-map" list for matching values of hi, lo and interrupt 330 * to give the INO for this interrupt. 331 */ 332 void 333 ebus_find_ino(sc, ea) 334 struct ebus_softc *sc; 335 struct ebus_attach_args *ea; 336 { 337 u_int32_t hi, lo, intr; 338 int i, j, k; 339 340 if (sc->sc_nintmap == 0) { 341 for (i = 0; i < ea->ea_nintr; i++) { 342 OF_mapintr(ea->ea_node, &ea->ea_intr[i], 343 sizeof(ea->ea_intr[0]), 344 sizeof(ea->ea_intr[0])); 345 } 346 return; 347 } 348 349 DPRINTF(EDB_INTRMAP, 350 ("ebus_find_ino: searching %d interrupts", ea->ea_nintr)); 351 352 for (j = 0; j < ea->ea_nintr; j++) { 353 354 intr = ea->ea_intr[j] & sc->sc_intmapmask.intr; 355 356 DPRINTF(EDB_INTRMAP, 357 ("; intr %x masked to %x", ea->ea_intr[j], intr)); 358 for (i = 0; i < ea->ea_nreg; i++) { 359 hi = ea->ea_reg[i].hi & sc->sc_intmapmask.hi; 360 lo = ea->ea_reg[i].lo & sc->sc_intmapmask.lo; 361 362 DPRINTF(EDB_INTRMAP, 363 ("; reg hi.lo %08x.%08x masked to %08x.%08x", 364 ea->ea_reg[i].hi, ea->ea_reg[i].lo, hi, lo)); 365 for (k = 0; k < sc->sc_nintmap; k++) { 366 DPRINTF(EDB_INTRMAP, 367 ("; checking hi.lo %08x.%08x intr %x", 368 sc->sc_intmap[k].hi, sc->sc_intmap[k].lo, 369 sc->sc_intmap[k].intr)); 370 if (hi == sc->sc_intmap[k].hi && 371 lo == sc->sc_intmap[k].lo && 372 intr == sc->sc_intmap[k].intr) { 373 ea->ea_intr[j] = 374 sc->sc_intmap[k].cintr; 375 DPRINTF(EDB_INTRMAP, 376 ("; FOUND IT! changing to %d\n", 377 sc->sc_intmap[k].cintr)); 378 goto next_intr; 379 } 380 } 381 } 382 next_intr:; 383 } 384 } 385 386 /* 387 * bus space support. <sparc64/dev/psychoreg.h> has a discussion 388 * about PCI physical addresses, which also applies to ebus. 389 */ 390 bus_space_tag_t 391 ebus_alloc_bus_tag(sc, type) 392 struct ebus_softc *sc; 393 int type; 394 { 395 bus_space_tag_t bt; 396 397 bt = (bus_space_tag_t) 398 malloc(sizeof(struct sparc_bus_space_tag), M_DEVBUF, M_NOWAIT); 399 if (bt == NULL) 400 panic("could not allocate ebus bus tag"); 401 402 bzero(bt, sizeof *bt); 403 bt->cookie = sc; 404 bt->parent = sc->sc_memtag; 405 bt->type = type; 406 bt->sparc_bus_map = _ebus_bus_map; 407 bt->sparc_bus_mmap = ebus_bus_mmap; 408 bt->sparc_intr_establish = ebus_intr_establish; 409 return (bt); 410 } 411 412 static int 413 _ebus_bus_map(t, ba, size, flags, va, hp) 414 bus_space_tag_t t; 415 bus_addr_t ba; 416 bus_size_t size; 417 int flags; 418 vaddr_t va; 419 bus_space_handle_t *hp; 420 { 421 struct ebus_softc *sc = t->cookie; 422 paddr_t offset; 423 u_int bar; 424 int i, ss; 425 426 bar = BUS_ADDR_IOSPACE(ba); 427 offset = BUS_ADDR_PADDR(ba); 428 429 DPRINTF(EDB_BUSMAP, 430 ("\n_ebus_bus_map: bar %d offset %08x sz %x flags %x va %p\n", 431 (int)bar, (u_int32_t)offset, (u_int32_t)size, 432 flags, (void *)va)); 433 434 for (i = 0; i < sc->sc_nrange; i++) { 435 bus_addr_t pciaddr; 436 437 if (bar != sc->sc_range[i].child_hi) 438 continue; 439 if (offset < sc->sc_range[i].child_lo || 440 (offset + size) > 441 (sc->sc_range[i].child_lo + sc->sc_range[i].size)) 442 continue; 443 444 /* Isolate address space and find the right tag */ 445 ss = (sc->sc_range[i].phys_hi>>24)&3; 446 switch (ss) { 447 case 1: /* I/O space */ 448 t = sc->sc_iotag; 449 break; 450 case 2: /* Memory space */ 451 t = sc->sc_memtag; 452 break; 453 case 0: /* Config space */ 454 case 3: /* 64-bit Memory space */ 455 default: /* WTF? */ 456 /* We don't handle these */ 457 panic("_ebus_bus_map: illegal space %x", ss); 458 break; 459 } 460 pciaddr = ((bus_addr_t)sc->sc_range[i].phys_mid << 32UL) | 461 sc->sc_range[i].phys_lo; 462 pciaddr += offset; 463 464 DPRINTF(EDB_BUSMAP, 465 ("_ebus_bus_map: mapping to PCI addr %x\n", 466 (u_int32_t)pciaddr)); 467 468 /* pass it onto the psycho */ 469 return (bus_space_map(t, pciaddr, size, flags, 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