static struct ebus_devinfo * ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node) { struct ebus_devinfo *edi; struct isa_regs *reg; ofw_isa_intr_t *intrs; ofw_pci_intr_t rintr; u_int64_t start; int nreg, nintr, i; edi = malloc(sizeof(*edi), M_DEVBUF, M_ZERO | M_WAITOK); if (ofw_bus_gen_setup_devinfo(&edi->edi_obdinfo, node) != 0) { free(edi, M_DEVBUF); return (NULL); } resource_list_init(&edi->edi_rl); nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®); if (nreg == -1) { device_printf(dev, "<%s>: incomplete\n", edi->edi_obdinfo.obd_name); goto fail; } for (i = 0; i < nreg; i++) { start = ISA_REG_PHYS(reg + i); resource_list_add(&edi->edi_rl, SYS_RES_MEMORY, i, start, start + reg[i].size - 1, reg[i].size); } free(reg, M_OFWPROP); nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs), (void **)&intrs); for (i = 0; i < nintr; i++) { rintr = ofw_isa_route_intr(dev, node, &sc->sc_iinfo, intrs[i]); if (rintr == PCI_INVALID_IRQ) { device_printf(dev, "<%s>: could not map EBus interrupt %d\n", edi->edi_obdinfo.obd_name, intrs[i]); free(intrs, M_OFWPROP); goto fail; } resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i, rintr, rintr, 1); } free(intrs, M_OFWPROP); return (edi); fail: ebus_destroy_dinfo(edi); return (NULL); }
static int ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node) { struct ebus_devinfo *edi; device_t cdev; ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t)); /* * Now attach our children. */ for (node = OF_child(node); node > 0; node = OF_peer(node)) { if ((edi = ebus_setup_dinfo(dev, sc, node)) == NULL) continue; if ((cdev = device_add_child(dev, NULL, -1)) == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", edi->edi_obdinfo.obd_name); ebus_destroy_dinfo(edi); continue; } device_set_ivars(cdev, edi); } return (bus_generic_attach(dev)); }
static int ebus_attach(device_t dev) { struct ebus_softc *sc; struct ebus_devinfo *edi; struct ebus_rinfo *eri; struct resource *res; device_t cdev; phandle_t node; int i, rnum, rid; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(*sc->sc_range), (void **)&sc->sc_range); if (sc->sc_nrange == -1) { printf("ebus_attach: could not get ranges property\n"); return (ENXIO); } sc->sc_rinfo = malloc(sizeof(*sc->sc_rinfo) * sc->sc_nrange, M_DEVBUF, M_WAITOK | M_ZERO); /* For every range, there must be a matching resource. */ for (rnum = 0; rnum < sc->sc_nrange; rnum++) { eri = &sc->sc_rinfo[rnum]; eri->eri_rtype = ofw_isa_range_restype(&sc->sc_range[rnum]); rid = PCIR_BAR(rnum); res = bus_alloc_resource_any(dev, eri->eri_rtype, &rid, RF_ACTIVE); if (res == NULL) { printf("ebus_attach: failed to allocate range " "resource!\n"); goto fail; } eri->eri_res = res; eri->eri_rman.rm_type = RMAN_ARRAY; eri->eri_rman.rm_descr = "EBus range"; if (rman_init(&eri->eri_rman) != 0) { printf("ebus_attach: failed to initialize rman!"); goto fail; } if (rman_manage_region(&eri->eri_rman, rman_get_start(res), rman_get_end(res)) != 0) { printf("ebus_attach: failed to register region!"); rman_fini(&eri->eri_rman); goto fail; } } ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t)); /* * Now attach our children. */ for (node = OF_child(node); node > 0; node = OF_peer(node)) { if ((edi = ebus_setup_dinfo(dev, sc, node)) == NULL) continue; if ((cdev = device_add_child(dev, NULL, -1)) == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", edi->edi_obdinfo.obd_name); ebus_destroy_dinfo(edi); continue; } device_set_ivars(cdev, edi); } return (bus_generic_attach(dev)); fail: for (i = rnum; i >= 0; i--) { eri = &sc->sc_rinfo[i]; if (i < rnum) rman_fini(&eri->eri_rman); if (eri->eri_res != 0) { bus_release_resource(dev, eri->eri_rtype, PCIR_BAR(rnum), eri->eri_res); } } free(sc->sc_rinfo, M_DEVBUF); free(sc->sc_range, M_OFWPROP); return (ENXIO); }