ebus.c revision 292785
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: stable/10/sys/sparc64/ebus/ebus.c 292785 2015-12-27 17:51:10Z marius $"); 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#include <sys/rman.h> 73 74#include <dev/ofw/ofw_bus.h> 75#include <dev/ofw/ofw_bus_subr.h> 76#include <dev/ofw/openfirm.h> 77 78#include <machine/bus.h> 79#ifndef SUN4V 80#include <machine/bus_common.h> 81#endif 82#include <machine/intr_machdep.h> 83#include <machine/resource.h> 84 85#include <dev/pci/pcireg.h> 86#include <dev/pci/pcivar.h> 87 88#include <sparc64/pci/ofw_pci.h> 89 90/* 91 * The register, interrupt map and for the PCI variant also the ranges 92 * properties are identical to the ISA ones. 93 */ 94#include <sparc64/isa/ofw_isa.h> 95 96struct ebus_nexus_ranges { 97 uint32_t child_hi; 98 uint32_t child_lo; 99 uint32_t phys_hi; 100 uint32_t phys_lo; 101 uint32_t size; 102}; 103 104struct ebus_devinfo { 105 struct ofw_bus_devinfo edi_obdinfo; 106 struct resource_list edi_rl; 107}; 108 109struct ebus_rinfo { 110 int eri_rtype; 111 struct rman eri_rman; 112 struct resource *eri_res; 113}; 114 115struct ebus_softc { 116 void *sc_range; 117 struct ebus_rinfo *sc_rinfo; 118 119 u_int sc_flags; 120#define EBUS_PCI (1 << 0) 121 122 int sc_nrange; 123 124 struct ofw_bus_iinfo sc_iinfo; 125 126#ifndef SUN4V 127 uint32_t sc_ign; 128#endif 129}; 130 131static device_probe_t ebus_nexus_probe; 132static device_attach_t ebus_nexus_attach; 133static device_probe_t ebus_pci_probe; 134static device_attach_t ebus_pci_attach; 135static bus_print_child_t ebus_print_child; 136static bus_probe_nomatch_t ebus_probe_nomatch; 137static bus_alloc_resource_t ebus_alloc_resource; 138static bus_activate_resource_t ebus_activate_resource; 139static bus_adjust_resource_t ebus_adjust_resource; 140static bus_release_resource_t ebus_release_resource; 141static bus_setup_intr_t ebus_setup_intr; 142static bus_get_resource_list_t ebus_get_resource_list; 143static ofw_bus_get_devinfo_t ebus_get_devinfo; 144 145static int ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node); 146static struct ebus_devinfo *ebus_setup_dinfo(device_t dev, 147 struct ebus_softc *sc, phandle_t node); 148static void ebus_destroy_dinfo(struct ebus_devinfo *edi); 149static int ebus_print_res(struct ebus_devinfo *edi); 150 151static devclass_t ebus_devclass; 152 153static device_method_t ebus_nexus_methods[] = { 154 /* Device interface */ 155 DEVMETHOD(device_probe, ebus_nexus_probe), 156 DEVMETHOD(device_attach, ebus_nexus_attach), 157 DEVMETHOD(device_shutdown, bus_generic_shutdown), 158 DEVMETHOD(device_suspend, bus_generic_suspend), 159 DEVMETHOD(device_resume, bus_generic_resume), 160 161 /* Bus interface */ 162 DEVMETHOD(bus_print_child, ebus_print_child), 163 DEVMETHOD(bus_probe_nomatch, ebus_probe_nomatch), 164 DEVMETHOD(bus_alloc_resource, ebus_alloc_resource), 165 DEVMETHOD(bus_activate_resource, ebus_activate_resource), 166 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 167 DEVMETHOD(bus_adjust_resource, ebus_adjust_resource), 168 DEVMETHOD(bus_release_resource, ebus_release_resource), 169 DEVMETHOD(bus_setup_intr, ebus_setup_intr), 170 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 171 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 172 DEVMETHOD(bus_get_resource_list, ebus_get_resource_list), 173 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), 174 175 /* ofw_bus interface */ 176 DEVMETHOD(ofw_bus_get_devinfo, ebus_get_devinfo), 177 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 178 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 179 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 180 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 181 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 182 183 DEVMETHOD_END 184}; 185 186static driver_t ebus_nexus_driver = { 187 "ebus", 188 ebus_nexus_methods, 189 sizeof(struct ebus_softc), 190}; 191 192/* 193 * NB: we rely on the interrupt controllers of the accompanying PCI-Express 194 * bridge to be registered as the nexus variant of the EBus bridges doesn't 195 * employ its own one. 196 */ 197EARLY_DRIVER_MODULE(ebus, nexus, ebus_nexus_driver, ebus_devclass, 0, 0, 198 BUS_PASS_BUS + 1); 199MODULE_DEPEND(ebus, nexus, 1, 1, 1); 200 201static device_method_t ebus_pci_methods[] = { 202 /* Device interface */ 203 DEVMETHOD(device_probe, ebus_pci_probe), 204 DEVMETHOD(device_attach, ebus_pci_attach), 205 DEVMETHOD(device_shutdown, bus_generic_shutdown), 206 DEVMETHOD(device_suspend, bus_generic_suspend), 207 DEVMETHOD(device_resume, bus_generic_resume), 208 209 /* Bus interface */ 210 DEVMETHOD(bus_print_child, ebus_print_child), 211 DEVMETHOD(bus_probe_nomatch, ebus_probe_nomatch), 212 DEVMETHOD(bus_alloc_resource, ebus_alloc_resource), 213 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 214 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 215 DEVMETHOD(bus_release_resource, ebus_release_resource), 216 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 217 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 218 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 219 DEVMETHOD(bus_get_resource_list, ebus_get_resource_list), 220 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), 221 222 /* ofw_bus interface */ 223 DEVMETHOD(ofw_bus_get_devinfo, ebus_get_devinfo), 224 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 225 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 226 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 227 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 228 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 229 230 DEVMETHOD_END 231}; 232 233static driver_t ebus_pci_driver = { 234 "ebus", 235 ebus_pci_methods, 236 sizeof(struct ebus_softc), 237}; 238 239EARLY_DRIVER_MODULE(ebus, pci, ebus_pci_driver, ebus_devclass, 0, 0, 240 BUS_PASS_BUS); 241MODULE_DEPEND(ebus, pci, 1, 1, 1); 242MODULE_VERSION(ebus, 1); 243 244static int 245ebus_nexus_probe(device_t dev) 246{ 247 const char* compat; 248 249 compat = ofw_bus_get_compat(dev); 250 if (compat != NULL && strcmp(ofw_bus_get_name(dev), "ebus") == 0 && 251 strcmp(compat, "jbus-ebus") == 0) { 252 device_set_desc(dev, "JBus-EBus bridge"); 253 return (BUS_PROBE_GENERIC); 254 } 255 return (ENXIO); 256} 257 258static int 259ebus_pci_probe(device_t dev) 260{ 261 262 if (pci_get_class(dev) != PCIC_BRIDGE || 263 pci_get_vendor(dev) != 0x108e || 264 strcmp(ofw_bus_get_name(dev), "ebus") != 0) 265 return (ENXIO); 266 267 if (pci_get_device(dev) == 0x1000) 268 device_set_desc(dev, "PCI-EBus2 bridge"); 269 else if (pci_get_device(dev) == 0x1100) 270 device_set_desc(dev, "PCI-EBus3 bridge"); 271 else 272 return (ENXIO); 273 return (BUS_PROBE_GENERIC); 274} 275 276static int 277ebus_nexus_attach(device_t dev) 278{ 279 struct ebus_softc *sc; 280 phandle_t node; 281 282 sc = device_get_softc(dev); 283 node = ofw_bus_get_node(dev); 284 285#ifndef SUN4V 286 if (OF_getprop(node, "portid", &sc->sc_ign, 287 sizeof(sc->sc_ign)) == -1) { 288 device_printf(dev, "could not determine IGN"); 289 return (ENXIO); 290 } 291#endif 292 293 sc->sc_nrange = OF_getprop_alloc(node, "ranges", 294 sizeof(struct ebus_nexus_ranges), &sc->sc_range); 295 if (sc->sc_nrange == -1) { 296 device_printf(dev, "could not get ranges property\n"); 297 return (ENXIO); 298 } 299 return (ebus_attach(dev, sc, node)); 300} 301 302static int 303ebus_pci_attach(device_t dev) 304{ 305 struct ebus_softc *sc; 306 struct ebus_rinfo *eri; 307 struct resource *res; 308 struct isa_ranges *range; 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 device_printf(dev, "could not get ranges property\n"); 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 range = &((struct isa_ranges *)sc->sc_range)[rnum]; 336 eri->eri_rtype = ofw_isa_range_restype(range); 337 rid = PCIR_BAR(rnum); 338 res = bus_alloc_resource_any(dev, eri->eri_rtype, &rid, 339 RF_ACTIVE); 340 if (res == NULL) { 341 device_printf(dev, 342 "could not allocate range resource %d\n", rnum); 343 goto fail; 344 } 345 if (rman_get_start(res) != ISA_RANGE_PHYS(range)) { 346 device_printf(dev, 347 "mismatch in start of range %d (0x%lx/0x%lx)\n", 348 rnum, rman_get_start(res), ISA_RANGE_PHYS(range)); 349 goto fail; 350 } 351 if (rman_get_size(res) != range->size) { 352 device_printf(dev, 353 "mismatch in size of range %d (0x%lx/0x%x)\n", 354 rnum, rman_get_size(res), range->size); 355 goto fail; 356 } 357 eri->eri_res = res; 358 eri->eri_rman.rm_type = RMAN_ARRAY; 359 eri->eri_rman.rm_descr = "EBus range"; 360 if (rman_init_from_resource(&eri->eri_rman, res) != 0) { 361 device_printf(dev, 362 "could not initialize rman for range %d", rnum); 363 goto fail; 364 } 365 } 366 return (ebus_attach(dev, sc, node)); 367 368 fail: 369 for (i = rnum; i >= 0; i--) { 370 eri = &sc->sc_rinfo[i]; 371 if (i < rnum) 372 rman_fini(&eri->eri_rman); 373 if (eri->eri_res != 0) { 374 bus_release_resource(dev, eri->eri_rtype, 375 PCIR_BAR(rnum), eri->eri_res); 376 } 377 } 378 free(sc->sc_rinfo, M_DEVBUF); 379 free(sc->sc_range, M_OFWPROP); 380 return (ENXIO); 381} 382 383static int 384ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node) 385{ 386 struct ebus_devinfo *edi; 387 device_t cdev; 388 389 ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t)); 390 391 /* 392 * Now attach our children. 393 */ 394 for (node = OF_child(node); node > 0; node = OF_peer(node)) { 395 if ((edi = ebus_setup_dinfo(dev, sc, node)) == NULL) 396 continue; 397 if ((cdev = device_add_child(dev, NULL, -1)) == NULL) { 398 device_printf(dev, "<%s>: device_add_child failed\n", 399 edi->edi_obdinfo.obd_name); 400 ebus_destroy_dinfo(edi); 401 continue; 402 } 403 device_set_ivars(cdev, edi); 404 } 405 return (bus_generic_attach(dev)); 406} 407 408static int 409ebus_print_child(device_t dev, device_t child) 410{ 411 int retval; 412 413 retval = bus_print_child_header(dev, child); 414 retval += ebus_print_res(device_get_ivars(child)); 415 retval += bus_print_child_footer(dev, child); 416 return (retval); 417} 418 419static void 420ebus_probe_nomatch(device_t dev, device_t child) 421{ 422 423 device_printf(dev, "<%s>", ofw_bus_get_name(child)); 424 ebus_print_res(device_get_ivars(child)); 425 printf(" (no driver attached)\n"); 426} 427 428static struct resource * 429ebus_alloc_resource(device_t bus, device_t child, int type, int *rid, 430 u_long start, u_long end, u_long count, u_int flags) 431{ 432 struct ebus_softc *sc; 433 struct resource_list *rl; 434 struct resource_list_entry *rle = NULL; 435 struct resource *res; 436 struct ebus_rinfo *eri; 437 struct ebus_nexus_ranges *enr; 438 uint64_t cend, cstart, offset; 439 int i, isdefault, passthrough, ridx; 440 441 isdefault = (start == 0UL && end == ~0UL); 442 passthrough = (device_get_parent(child) != bus); 443 sc = device_get_softc(bus); 444 rl = BUS_GET_RESOURCE_LIST(bus, child); 445 switch (type) { 446 case SYS_RES_MEMORY: 447 KASSERT(!(isdefault && passthrough), 448 ("%s: passthrough of default allocation", __func__)); 449 if (!passthrough) { 450 rle = resource_list_find(rl, type, *rid); 451 if (rle == NULL) 452 return (NULL); 453 KASSERT(rle->res == NULL, 454 ("%s: resource entry is busy", __func__)); 455 if (isdefault) { 456 start = rle->start; 457 count = ulmax(count, rle->count); 458 end = ulmax(rle->end, start + count - 1); 459 } 460 } 461 462 res = NULL; 463 if ((sc->sc_flags & EBUS_PCI) != 0) { 464 /* 465 * Map EBus ranges to PCI ranges. This may include 466 * changing the allocation type. 467 */ 468 type = ofw_isa_range_map(sc->sc_range, sc->sc_nrange, 469 &start, &end, &ridx); 470 eri = &sc->sc_rinfo[ridx]; 471 res = rman_reserve_resource(&eri->eri_rman, start, 472 end, count, flags & ~RF_ACTIVE, child); 473 if (res == NULL) 474 return (NULL); 475 rman_set_rid(res, *rid); 476 if ((flags & RF_ACTIVE) != 0 && bus_activate_resource( 477 child, type, *rid, res) != 0) { 478 rman_release_resource(res); 479 return (NULL); 480 } 481 } else { 482 /* Map EBus ranges to nexus ranges. */ 483 for (i = 0; i < sc->sc_nrange; i++) { 484 enr = &((struct ebus_nexus_ranges *) 485 sc->sc_range)[i]; 486 cstart = (((uint64_t)enr->child_hi) << 32) | 487 enr->child_lo; 488 cend = cstart + enr->size - 1; 489 if (start >= cstart && end <= cend) { 490 offset = 491 (((uint64_t)enr->phys_hi) << 32) | 492 enr->phys_lo; 493 start += offset - cstart; 494 end += offset - cstart; 495 res = bus_generic_alloc_resource(bus, 496 child, type, rid, start, end, 497 count, flags); 498 break; 499 } 500 } 501 } 502 if (!passthrough) 503 rle->res = res; 504 return (res); 505 case SYS_RES_IRQ: 506 return (resource_list_alloc(rl, bus, child, type, rid, start, 507 end, count, flags)); 508 } 509 return (NULL); 510} 511 512static int 513ebus_activate_resource(device_t bus, device_t child, int type, int rid, 514 struct resource *res) 515{ 516 struct ebus_softc *sc; 517 struct ebus_rinfo *eri; 518 bus_space_tag_t bt; 519 bus_space_handle_t bh; 520 int i, rv; 521 522 sc = device_get_softc(bus); 523 if ((sc->sc_flags & EBUS_PCI) != 0 && type != SYS_RES_IRQ) { 524 for (i = 0; i < sc->sc_nrange; i++) { 525 eri = &sc->sc_rinfo[i]; 526 if (rman_is_region_manager(res, &eri->eri_rman) != 0) { 527 bt = rman_get_bustag(eri->eri_res); 528 rv = bus_space_subregion(bt, 529 rman_get_bushandle(eri->eri_res), 530 rman_get_start(res) - 531 rman_get_start(eri->eri_res), 532 rman_get_size(res), &bh); 533 if (rv != 0) 534 return (rv); 535 rman_set_bustag(res, bt); 536 rman_set_bushandle(res, bh); 537 return (rman_activate_resource(res)); 538 } 539 } 540 return (EINVAL); 541 } 542 return (bus_generic_activate_resource(bus, child, type, rid, res)); 543} 544 545static int 546ebus_adjust_resource(device_t bus __unused, device_t child __unused, 547 int type __unused, struct resource *res __unused, u_long start __unused, 548 u_long end __unused) 549{ 550 551 return (ENXIO); 552} 553 554static int 555ebus_release_resource(device_t bus, device_t child, int type, int rid, 556 struct resource *res) 557{ 558 struct ebus_softc *sc; 559 struct resource_list *rl; 560 struct resource_list_entry *rle; 561 int passthrough, rv; 562 563 passthrough = (device_get_parent(child) != bus); 564 rl = BUS_GET_RESOURCE_LIST(bus, child); 565 sc = device_get_softc(bus); 566 if ((sc->sc_flags & EBUS_PCI) != 0 && type != SYS_RES_IRQ) { 567 if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){ 568 rv = bus_deactivate_resource(child, type, rid, res); 569 if (rv != 0) 570 return (rv); 571 } 572 rv = rman_release_resource(res); 573 if (rv != 0) 574 return (rv); 575 if (!passthrough) { 576 rle = resource_list_find(rl, type, rid); 577 KASSERT(rle != NULL, 578 ("%s: resource entry not found!", __func__)); 579 KASSERT(rle->res != NULL, 580 ("%s: resource entry is not busy", __func__)); 581 rle->res = NULL; 582 } 583 return (0); 584 } 585 return (resource_list_release(rl, bus, child, type, rid, res)); 586} 587 588static int 589ebus_setup_intr(device_t dev, device_t child, struct resource *ires, 590 int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, 591 void **cookiep) 592{ 593#ifndef SUN4V 594 struct ebus_softc *sc; 595 u_long vec; 596 597 sc = device_get_softc(dev); 598 if ((sc->sc_flags & EBUS_PCI) == 0) { 599 /* 600 * Make sure the vector is fully specified. This isn't 601 * necessarily the case with the PCI variant. 602 */ 603 vec = rman_get_start(ires); 604 if (INTIGN(vec) != sc->sc_ign) { 605 device_printf(dev, 606 "invalid interrupt vector 0x%lx\n", vec); 607 return (EINVAL); 608 } 609 610 /* 611 * As we rely on the interrupt controllers of the 612 * accompanying PCI-Express bridge ensure at least 613 * something is registered for this vector. 614 */ 615 if (intr_vectors[vec].iv_ic == NULL) { 616 device_printf(dev, 617 "invalid interrupt controller for vector 0x%lx\n", 618 vec); 619 return (EINVAL); 620 } 621 } 622#endif 623 return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, 624 arg, cookiep)); 625} 626 627static struct resource_list * 628ebus_get_resource_list(device_t dev, device_t child) 629{ 630 struct ebus_devinfo *edi; 631 632 edi = device_get_ivars(child); 633 return (&edi->edi_rl); 634} 635 636static const struct ofw_bus_devinfo * 637ebus_get_devinfo(device_t bus, device_t dev) 638{ 639 struct ebus_devinfo *edi; 640 641 edi = device_get_ivars(dev); 642 return (&edi->edi_obdinfo); 643} 644 645static struct ebus_devinfo * 646ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node) 647{ 648 struct isa_regs reg, *regs; 649 ofw_isa_intr_t intr, *intrs; 650 struct ebus_devinfo *edi; 651 uint64_t start; 652 uint32_t rintr; 653 int i, nintr, nreg, rv; 654 655 edi = malloc(sizeof(*edi), M_DEVBUF, M_ZERO | M_WAITOK); 656 if (ofw_bus_gen_setup_devinfo(&edi->edi_obdinfo, node) != 0) { 657 free(edi, M_DEVBUF); 658 return (NULL); 659 } 660 resource_list_init(&edi->edi_rl); 661 nreg = OF_getprop_alloc(node, "reg", sizeof(*regs), (void **)®s); 662 if (nreg == -1) { 663 device_printf(dev, "<%s>: incomplete\n", 664 edi->edi_obdinfo.obd_name); 665 ebus_destroy_dinfo(edi); 666 return (NULL); 667 } 668 for (i = 0; i < nreg; i++) { 669 start = ISA_REG_PHYS(regs + i); 670 (void)resource_list_add(&edi->edi_rl, SYS_RES_MEMORY, i, 671 start, start + regs[i].size - 1, regs[i].size); 672 } 673 free(regs, M_OFWPROP); 674 675 nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs), 676 (void **)&intrs); 677 if (nintr == -1) 678 return (edi); 679 for (i = 0; i < nintr; i++) { 680 rv = 0; 681 if ((sc->sc_flags & EBUS_PCI) != 0) { 682 rintr = ofw_isa_route_intr(dev, node, &sc->sc_iinfo, 683 intrs[i]); 684 } else { 685 intr = intrs[i]; 686 rv = ofw_bus_lookup_imap(node, &sc->sc_iinfo, ®, 687 sizeof(reg), &intr, sizeof(intr), &rintr, 688 sizeof(rintr), NULL); 689#ifndef SUN4V 690 if (rv != 0) 691 rintr = INTMAP_VEC(sc->sc_ign, rintr); 692#endif 693 } 694 if ((sc->sc_flags & EBUS_PCI) == 0 ? rv == 0 : 695 rintr == PCI_INVALID_IRQ) { 696 device_printf(dev, 697 "<%s>: could not map EBus interrupt %d\n", 698 edi->edi_obdinfo.obd_name, intrs[i]); 699 continue; 700 } 701 (void)resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i, rintr, 702 rintr, 1); 703 } 704 free(intrs, M_OFWPROP); 705 return (edi); 706} 707 708static void 709ebus_destroy_dinfo(struct ebus_devinfo *edi) 710{ 711 712 resource_list_free(&edi->edi_rl); 713 ofw_bus_gen_destroy_devinfo(&edi->edi_obdinfo); 714 free(edi, M_DEVBUF); 715} 716 717static int 718ebus_print_res(struct ebus_devinfo *edi) 719{ 720 int retval; 721 722 retval = 0; 723 retval += resource_list_print_type(&edi->edi_rl, "addr", SYS_RES_MEMORY, 724 "%#lx"); 725 retval += resource_list_print_type(&edi->edi_rl, "irq", SYS_RES_IRQ, 726 "%ld"); 727 return (retval); 728} 729