1/*- 2 * Copyright (c) 1999, 2000 Matthew R. Green 3 * Copyright (c) 2009 by Marius Strobl <marius@FreeBSD.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 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 * from: NetBSD: ebus.c,v 1.52 2008/05/29 14:51:26 mrg Exp 30 */ 31/*- 32 * Copyright (c) 2001 Thomas Moestl <tmm@FreeBSD.org> 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. The name of the author may not be used to endorse or promote products 44 * derived from this software without specific prior written permission. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 51 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 52 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 53 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 54 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 56 * SUCH DAMAGE. 57 */ 58 59#include <sys/cdefs.h> 60__FBSDID("$FreeBSD$"); 61 62/* 63 * Driver for JBus to EBus and PCI to EBus bridges 64 */ 65 66#include <sys/param.h> 67#include <sys/systm.h> 68#include <sys/bus.h> 69#include <sys/kernel.h> 70#include <sys/malloc.h> 71#include <sys/module.h> 72 73#include <sys/rman.h> 74 75#include <dev/ofw/ofw_bus.h> 76#include <dev/ofw/ofw_bus_subr.h> 77#include <dev/ofw/openfirm.h> 78 79#include <machine/bus.h> 80#ifndef SUN4V 81#include <machine/bus_common.h> 82#endif 83#include <machine/intr_machdep.h> 84#include <machine/resource.h> 85 86#include <dev/pci/pcireg.h> 87#include <dev/pci/pcivar.h> 88 89#include <sparc64/pci/ofw_pci.h> 90 91/* 92 * The register, interrupt map and for the PCI variant also the ranges 93 * properties are identical to the ISA ones. 94 */ 95#include <sparc64/isa/ofw_isa.h> 96 97struct ebus_nexus_ranges { 98 uint32_t child_hi; 99 uint32_t child_lo; 100 uint32_t phys_hi; 101 uint32_t phys_lo; 102 uint32_t size; 103}; 104 105struct ebus_devinfo { 106 struct ofw_bus_devinfo edi_obdinfo; 107 struct resource_list edi_rl; 108}; 109 110struct ebus_rinfo { 111 int eri_rtype; 112 struct rman eri_rman; 113 struct resource *eri_res; 114}; 115 116struct ebus_softc { 117 void *sc_range; 118 struct ebus_rinfo *sc_rinfo; 119 120 u_int sc_flags; 121#define EBUS_PCI (1 << 0) 122 123 int sc_nrange; 124 125 struct ofw_bus_iinfo sc_iinfo; 126 127#ifndef SUN4V 128 uint32_t sc_ign; 129#endif 130}; 131 132static device_probe_t ebus_nexus_probe; 133static device_attach_t ebus_nexus_attach; 134static device_probe_t ebus_pci_probe; 135static device_attach_t ebus_pci_attach; 136static bus_print_child_t ebus_print_child; 137static bus_probe_nomatch_t ebus_probe_nomatch; 138static bus_alloc_resource_t ebus_alloc_resource; 139static bus_activate_resource_t ebus_activate_resource; 140static bus_adjust_resource_t ebus_adjust_resource; 141static bus_release_resource_t ebus_release_resource; 142static bus_setup_intr_t ebus_setup_intr; 143static bus_get_resource_list_t ebus_get_resource_list; 144static ofw_bus_get_devinfo_t ebus_get_devinfo; 145 146static int ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node); 147static struct ebus_devinfo *ebus_setup_dinfo(device_t dev, 148 struct ebus_softc *sc, phandle_t node); 149static void ebus_destroy_dinfo(struct ebus_devinfo *edi); 150static int ebus_print_res(struct ebus_devinfo *edi); 151 152static devclass_t ebus_devclass; 153 154static device_method_t ebus_nexus_methods[] = { 155 /* Device interface */ 156 DEVMETHOD(device_probe, ebus_nexus_probe), 157 DEVMETHOD(device_attach, ebus_nexus_attach), 158 DEVMETHOD(device_shutdown, bus_generic_shutdown), 159 DEVMETHOD(device_suspend, bus_generic_suspend), 160 DEVMETHOD(device_resume, bus_generic_resume), 161 162 /* Bus interface */ 163 DEVMETHOD(bus_print_child, ebus_print_child), 164 DEVMETHOD(bus_probe_nomatch, ebus_probe_nomatch), 165 DEVMETHOD(bus_alloc_resource, ebus_alloc_resource), 166 DEVMETHOD(bus_activate_resource, ebus_activate_resource), 167 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 168 DEVMETHOD(bus_adjust_resource, ebus_adjust_resource), 169 DEVMETHOD(bus_release_resource, ebus_release_resource), 170 DEVMETHOD(bus_setup_intr, ebus_setup_intr), 171 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 172 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 173 DEVMETHOD(bus_get_resource_list, ebus_get_resource_list), 174 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), 175 176 /* ofw_bus interface */ 177 DEVMETHOD(ofw_bus_get_devinfo, ebus_get_devinfo), 178 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 179 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 180 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 181 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 182 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 183 184 DEVMETHOD_END 185}; 186 187static driver_t ebus_nexus_driver = { 188 "ebus", 189 ebus_nexus_methods, 190 sizeof(struct ebus_softc), 191}; 192 193/* 194 * NB: we rely on the interrupt controllers of the accompanying PCI-Express 195 * bridge to be registered as the nexus variant of the EBus bridges doesn't 196 * employ its own one. 197 */ 198EARLY_DRIVER_MODULE(ebus, nexus, ebus_nexus_driver, ebus_devclass, 0, 0, 199 BUS_PASS_BUS + 1); 200MODULE_DEPEND(ebus, nexus, 1, 1, 1); 201 202static device_method_t ebus_pci_methods[] = { 203 /* Device interface */ 204 DEVMETHOD(device_probe, ebus_pci_probe), 205 DEVMETHOD(device_attach, ebus_pci_attach), 206 DEVMETHOD(device_shutdown, bus_generic_shutdown), 207 DEVMETHOD(device_suspend, bus_generic_suspend), 208 DEVMETHOD(device_resume, bus_generic_resume), 209 210 /* Bus interface */ 211 DEVMETHOD(bus_print_child, ebus_print_child), 212 DEVMETHOD(bus_probe_nomatch, ebus_probe_nomatch), 213 DEVMETHOD(bus_alloc_resource, ebus_alloc_resource), 214 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 215 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 216 DEVMETHOD(bus_release_resource, ebus_release_resource), 217 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 218 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 219 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 220 DEVMETHOD(bus_get_resource_list, ebus_get_resource_list), 221 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), 222 223 /* ofw_bus interface */ 224 DEVMETHOD(ofw_bus_get_devinfo, ebus_get_devinfo), 225 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 226 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 227 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 228 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 229 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 230 231 DEVMETHOD_END 232}; 233 234static driver_t ebus_pci_driver = { 235 "ebus", 236 ebus_pci_methods, 237 sizeof(struct ebus_softc), 238}; 239 240EARLY_DRIVER_MODULE(ebus, pci, ebus_pci_driver, ebus_devclass, 0, 0, 241 BUS_PASS_BUS); 242MODULE_DEPEND(ebus, pci, 1, 1, 1); 243MODULE_VERSION(ebus, 1); 244 245static int 246ebus_nexus_probe(device_t dev) 247{ 248 const char* compat; 249 250 compat = ofw_bus_get_compat(dev); 251 if (compat != NULL && strcmp(ofw_bus_get_name(dev), "ebus") == 0 && 252 strcmp(compat, "jbus-ebus") == 0) { 253 device_set_desc(dev, "JBus-EBus bridge"); 254 return (BUS_PROBE_GENERIC); 255 } 256 return (ENXIO); 257} 258 259static int 260ebus_pci_probe(device_t dev) 261{ 262 263 if (pci_get_class(dev) != PCIC_BRIDGE || 264 pci_get_vendor(dev) != 0x108e || 265 strcmp(ofw_bus_get_name(dev), "ebus") != 0) 266 return (ENXIO); 267 268 if (pci_get_device(dev) == 0x1000) 269 device_set_desc(dev, "PCI-EBus2 bridge"); 270 else if (pci_get_device(dev) == 0x1100) 271 device_set_desc(dev, "PCI-EBus3 bridge"); 272 else 273 return (ENXIO); 274 return (BUS_PROBE_GENERIC); 275} 276 277static int 278ebus_nexus_attach(device_t dev) 279{ 280 struct ebus_softc *sc; 281 phandle_t node; 282 283 sc = device_get_softc(dev); 284 node = ofw_bus_get_node(dev); 285 286#ifndef SUN4V 287 if (OF_getprop(node, "portid", &sc->sc_ign, 288 sizeof(sc->sc_ign)) == -1) { 289 device_printf(dev, "could not determine IGN"); 290 return (ENXIO); 291 } 292#endif 293 294 sc->sc_nrange = OF_getprop_alloc(node, "ranges", 295 sizeof(struct ebus_nexus_ranges), &sc->sc_range); 296 if (sc->sc_nrange == -1) { 297 printf("%s: could not get ranges property\n", __func__); 298 return (ENXIO); 299 } 300 return (ebus_attach(dev, sc, node)); 301} 302 303static int 304ebus_pci_attach(device_t dev) 305{ 306 struct ebus_softc *sc; 307 struct ebus_rinfo *eri; 308 struct resource *res; 309 phandle_t node; 310 int i, rnum, rid; 311 312 sc = device_get_softc(dev); 313 sc->sc_flags |= EBUS_PCI; 314 315 pci_write_config(dev, PCIR_COMMAND, 316 pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_SERRESPEN | 317 PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN, 2); 318 pci_write_config(dev, PCIR_CACHELNSZ, 16 /* 64 bytes */, 1); 319 pci_write_config(dev, PCIR_LATTIMER, 64 /* 64 PCI cycles */, 1); 320 321 node = ofw_bus_get_node(dev); 322 sc->sc_nrange = OF_getprop_alloc(node, "ranges", 323 sizeof(struct isa_ranges), &sc->sc_range); 324 if (sc->sc_nrange == -1) { 325 printf("%s: could not get ranges property\n", __func__); 326 return (ENXIO); 327 } 328 329 sc->sc_rinfo = malloc(sizeof(*sc->sc_rinfo) * sc->sc_nrange, M_DEVBUF, 330 M_WAITOK | M_ZERO); 331 332 /* For every range, there must be a matching resource. */ 333 for (rnum = 0; rnum < sc->sc_nrange; rnum++) { 334 eri = &sc->sc_rinfo[rnum]; 335 eri->eri_rtype = ofw_isa_range_restype( 336 &((struct isa_ranges *)sc->sc_range)[rnum]); 337 rid = PCIR_BAR(rnum); 338 res = bus_alloc_resource_any(dev, eri->eri_rtype, &rid, 339 RF_ACTIVE); 340 if (res == NULL) { 341 printf("%s: failed to allocate range resource!\n", 342 __func__); 343 goto fail; 344 } 345 eri->eri_res = res; 346 eri->eri_rman.rm_type = RMAN_ARRAY; 347 eri->eri_rman.rm_descr = "EBus range"; 348 if (rman_init_from_resource(&eri->eri_rman, res) != 0) { 349 printf("%s: failed to initialize rman!", __func__); 350 goto fail; 351 } 352 } 353 return (ebus_attach(dev, sc, node)); 354 355 fail: 356 for (i = rnum; i >= 0; i--) { 357 eri = &sc->sc_rinfo[i]; 358 if (i < rnum) 359 rman_fini(&eri->eri_rman); 360 if (eri->eri_res != 0) { 361 bus_release_resource(dev, eri->eri_rtype, 362 PCIR_BAR(rnum), eri->eri_res); 363 } 364 } 365 free(sc->sc_rinfo, M_DEVBUF); 366 free(sc->sc_range, M_OFWPROP); 367 return (ENXIO); 368} 369 370static int 371ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node) 372{ 373 struct ebus_devinfo *edi; 374 device_t cdev; 375 376 ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t)); 377 378 /* 379 * Now attach our children. 380 */ 381 for (node = OF_child(node); node > 0; node = OF_peer(node)) { 382 if ((edi = ebus_setup_dinfo(dev, sc, node)) == NULL) 383 continue; 384 if ((cdev = device_add_child(dev, NULL, -1)) == NULL) { 385 device_printf(dev, "<%s>: device_add_child failed\n", 386 edi->edi_obdinfo.obd_name); 387 ebus_destroy_dinfo(edi); 388 continue; 389 } 390 device_set_ivars(cdev, edi); 391 } 392 return (bus_generic_attach(dev)); 393} 394 395static int 396ebus_print_child(device_t dev, device_t child) 397{ 398 int retval; 399 400 retval = bus_print_child_header(dev, child); 401 retval += ebus_print_res(device_get_ivars(child)); 402 retval += bus_print_child_footer(dev, child); 403 return (retval); 404} 405 406static void 407ebus_probe_nomatch(device_t dev, device_t child) 408{ 409 410 device_printf(dev, "<%s>", ofw_bus_get_name(child)); 411 ebus_print_res(device_get_ivars(child)); 412 printf(" (no driver attached)\n"); 413} 414 415static struct resource * 416ebus_alloc_resource(device_t bus, device_t child, int type, int *rid, 417 u_long start, u_long end, u_long count, u_int flags) 418{ 419 struct ebus_softc *sc; 420 struct resource_list *rl; 421 struct resource_list_entry *rle = NULL; 422 struct resource *res; 423 struct ebus_rinfo *eri; 424 struct ebus_nexus_ranges *enr; 425 uint64_t cend, cstart, offset; 426 int i, isdefault, passthrough, ridx; 427 428 isdefault = (start == 0UL && end == ~0UL); 429 passthrough = (device_get_parent(child) != bus); 430 sc = device_get_softc(bus); 431 rl = BUS_GET_RESOURCE_LIST(bus, child); 432 switch (type) { 433 case SYS_RES_MEMORY: 434 KASSERT(!(isdefault && passthrough), 435 ("%s: passthrough of default allocation", __func__)); 436 if (!passthrough) { 437 rle = resource_list_find(rl, type, *rid); 438 if (rle == NULL) 439 return (NULL); 440 KASSERT(rle->res == NULL, 441 ("%s: resource entry is busy", __func__)); 442 if (isdefault) { 443 start = rle->start; 444 count = ulmax(count, rle->count); 445 end = ulmax(rle->end, start + count - 1); 446 } 447 } 448 449 res = NULL; 450 if ((sc->sc_flags & EBUS_PCI) != 0) { 451 /* 452 * Map EBus ranges to PCI ranges. This may include 453 * changing the allocation type. 454 */ 455 (void)ofw_isa_range_map(sc->sc_range, sc->sc_nrange, 456 &start, &end, &ridx); 457 eri = &sc->sc_rinfo[ridx]; 458 res = rman_reserve_resource(&eri->eri_rman, start, 459 end, count, flags & ~RF_ACTIVE, child); 460 if (res == NULL) 461 return (NULL); 462 rman_set_rid(res, *rid); 463 if ((flags & RF_ACTIVE) != 0 && bus_activate_resource( 464 child, type, *rid, res) != 0) { 465 rman_release_resource(res); 466 return (NULL); 467 } 468 } else { 469 /* Map EBus ranges to nexus ranges. */ 470 for (i = 0; i < sc->sc_nrange; i++) { 471 enr = &((struct ebus_nexus_ranges *) 472 sc->sc_range)[i]; 473 cstart = (((uint64_t)enr->child_hi) << 32) | 474 enr->child_lo; 475 cend = cstart + enr->size - 1; 476 if (start >= cstart && end <= cend) { 477 offset = 478 (((uint64_t)enr->phys_hi) << 32) | 479 enr->phys_lo; 480 start += offset - cstart; 481 end += offset - cstart; 482 res = bus_generic_alloc_resource(bus, 483 child, type, rid, start, end, 484 count, flags); 485 break; 486 } 487 } 488 } 489 if (!passthrough) 490 rle->res = res; 491 return (res); 492 case SYS_RES_IRQ: 493 return (resource_list_alloc(rl, bus, child, type, rid, start, 494 end, count, flags)); 495 } 496 return (NULL); 497} 498 499static int 500ebus_activate_resource(device_t bus, device_t child, int type, int rid, 501 struct resource *res) 502{ 503 struct ebus_softc *sc; 504 struct ebus_rinfo *eri; 505 bus_space_tag_t bt; 506 bus_space_handle_t bh; 507 int i, rv; 508 509 sc = device_get_softc(bus); 510 if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) { 511 for (i = 0; i < sc->sc_nrange; i++) { 512 eri = &sc->sc_rinfo[i]; 513 if (rman_is_region_manager(res, &eri->eri_rman) != 0) { 514 bt = rman_get_bustag(eri->eri_res); 515 rv = bus_space_subregion(bt, 516 rman_get_bushandle(eri->eri_res), 517 rman_get_start(res) - 518 rman_get_start(eri->eri_res), 519 rman_get_size(res), &bh); 520 if (rv != 0) 521 return (rv); 522 rman_set_bustag(res, bt); 523 rman_set_bushandle(res, bh); 524 return (rman_activate_resource(res)); 525 } 526 } 527 return (EINVAL); 528 } 529 return (bus_generic_activate_resource(bus, child, type, rid, res)); 530} 531 532static int 533ebus_adjust_resource(device_t bus __unused, device_t child __unused, 534 int type __unused, struct resource *res __unused, u_long start __unused, 535 u_long end __unused) 536{ 537 538 return (ENXIO); 539} 540 541static int 542ebus_release_resource(device_t bus, device_t child, int type, int rid, 543 struct resource *res) 544{ 545 struct ebus_softc *sc; 546 struct resource_list *rl; 547 struct resource_list_entry *rle; 548 int passthrough, rv; 549 550 passthrough = (device_get_parent(child) != bus); 551 rl = BUS_GET_RESOURCE_LIST(bus, child); 552 sc = device_get_softc(bus); 553 if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) { 554 if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){ 555 rv = bus_deactivate_resource(child, type, rid, res); 556 if (rv != 0) 557 return (rv); 558 } 559 rv = rman_release_resource(res); 560 if (rv != 0) 561 return (rv); 562 if (!passthrough) { 563 rle = resource_list_find(rl, type, rid); 564 KASSERT(rle != NULL, 565 ("%s: resource entry not found!", __func__)); 566 KASSERT(rle->res != NULL, 567 ("%s: resource entry is not busy", __func__)); 568 rle->res = NULL; 569 } 570 return (0); 571 } 572 return (resource_list_release(rl, bus, child, type, rid, res)); 573} 574 575static int 576ebus_setup_intr(device_t dev, device_t child, struct resource *ires, 577 int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, 578 void **cookiep) 579{ 580#ifndef SUN4V 581 struct ebus_softc *sc; 582 u_long vec; 583 584 sc = device_get_softc(dev); 585 if ((sc->sc_flags & EBUS_PCI) == 0) { 586 /* 587 * Make sure the vector is fully specified. This isn't 588 * necessarily the case with the PCI variant. 589 */ 590 vec = rman_get_start(ires); 591 if (INTIGN(vec) != sc->sc_ign) { 592 device_printf(dev, 593 "invalid interrupt vector 0x%lx\n", vec); 594 return (EINVAL); 595 } 596 597 /* 598 * As we rely on the interrupt controllers of the 599 * accompanying PCI-Express bridge ensure at least 600 * something is registered for this vector. 601 */ 602 if (intr_vectors[vec].iv_ic == NULL) { 603 device_printf(dev, 604 "invalid interrupt controller for vector 0x%lx\n", 605 vec); 606 return (EINVAL); 607 } 608 } 609#endif 610 return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, 611 arg, cookiep)); 612} 613 614static struct resource_list * 615ebus_get_resource_list(device_t dev, device_t child) 616{ 617 struct ebus_devinfo *edi; 618 619 edi = device_get_ivars(child); 620 return (&edi->edi_rl); 621} 622 623static const struct ofw_bus_devinfo * 624ebus_get_devinfo(device_t bus, device_t dev) 625{ 626 struct ebus_devinfo *edi; 627 628 edi = device_get_ivars(dev); 629 return (&edi->edi_obdinfo); 630} 631 632static struct ebus_devinfo * 633ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node) 634{ 635 struct isa_regs reg, *regs; 636 ofw_isa_intr_t intr, *intrs; 637 struct ebus_devinfo *edi; 638 uint64_t start; 639 uint32_t rintr; 640 int i, nintr, nreg, rv; 641 642 edi = malloc(sizeof(*edi), M_DEVBUF, M_ZERO | M_WAITOK); 643 if (ofw_bus_gen_setup_devinfo(&edi->edi_obdinfo, node) != 0) { 644 free(edi, M_DEVBUF); 645 return (NULL); 646 } 647 resource_list_init(&edi->edi_rl); 648 nreg = OF_getprop_alloc(node, "reg", sizeof(*regs), (void **)®s); 649 if (nreg == -1) { 650 device_printf(dev, "<%s>: incomplete\n", 651 edi->edi_obdinfo.obd_name); 652 ebus_destroy_dinfo(edi); 653 return (NULL); 654 } 655 for (i = 0; i < nreg; i++) { 656 start = ISA_REG_PHYS(regs + i); 657 (void)resource_list_add(&edi->edi_rl, SYS_RES_MEMORY, i, 658 start, start + regs[i].size - 1, regs[i].size); 659 } 660 free(regs, M_OFWPROP); 661 662 nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs), 663 (void **)&intrs); 664 if (nintr == -1) 665 return (edi); 666 for (i = 0; i < nintr; i++) { 667 rv = 0; 668 if ((sc->sc_flags & EBUS_PCI) != 0) { 669 rintr = ofw_isa_route_intr(dev, node, &sc->sc_iinfo, 670 intrs[i]); 671 } else { 672 intr = intrs[i]; 673 rv = ofw_bus_lookup_imap(node, &sc->sc_iinfo, ®, 674 sizeof(reg), &intr, sizeof(intr), &rintr, 675 sizeof(rintr), NULL); 676#ifndef SUN4V 677 if (rv != 0) 678 rintr = INTMAP_VEC(sc->sc_ign, rintr); 679#endif 680 } 681 if ((sc->sc_flags & EBUS_PCI) == 0 ? rv == 0 : 682 rintr == PCI_INVALID_IRQ) { 683 device_printf(dev, 684 "<%s>: could not map EBus interrupt %d\n", 685 edi->edi_obdinfo.obd_name, intrs[i]); 686 continue; 687 } 688 (void)resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i, rintr, 689 rintr, 1); 690 } 691 free(intrs, M_OFWPROP); 692 return (edi); 693} 694 695static void 696ebus_destroy_dinfo(struct ebus_devinfo *edi) 697{ 698 699 resource_list_free(&edi->edi_rl); 700 ofw_bus_gen_destroy_devinfo(&edi->edi_obdinfo); 701 free(edi, M_DEVBUF); 702} 703 704static int 705ebus_print_res(struct ebus_devinfo *edi) 706{ 707 int retval; 708 709 retval = 0; 710 retval += resource_list_print_type(&edi->edi_rl, "addr", SYS_RES_MEMORY, 711 "%#lx"); 712 retval += resource_list_print_type(&edi->edi_rl, "irq", SYS_RES_IRQ, 713 "%ld"); 714 return (retval); 715} 716