static device_t newbus_device_create(device_t dev_par, phandle_t node, char *name, char *type, char *compat) { device_t child; struct fdtbus_devinfo *di; child = device_add_child(dev_par, NULL, -1); if (child == NULL) { free(name, M_OFWPROP); free(type, M_OFWPROP); free(compat, M_OFWPROP); return (NULL); } di = malloc(sizeof(*di), M_FDTBUS, M_WAITOK); di->di_node = node; di->di_name = name; di->di_type = type; di->di_compat = compat; resource_list_init(&di->di_res); if (fdt_reg_to_rl(node, &di->di_res)) { device_printf(child, "could not process 'reg' property\n"); newbus_device_destroy(child); child = NULL; goto out; } if (fdt_intr_to_rl(node, &di->di_res, di->di_intr_sl)) { device_printf(child, "could not process 'interrupts' " "property\n"); newbus_device_destroy(child); child = NULL; goto out; } device_set_ivars(child, di); debugf("added child name='%s', node=%p\n", name, (void *)node); out: return (child); }
static int simplebus_attach(device_t dev) { device_t dev_child; struct simplebus_devinfo *di; struct simplebus_softc *sc; phandle_t dt_node, dt_child; sc = device_get_softc(dev); /* * Walk simple-bus and add direct subordinates as our children. */ dt_node = ofw_bus_get_node(dev); for (dt_child = OF_child(dt_node); dt_child != 0; dt_child = OF_peer(dt_child)) { /* Check and process 'status' property. */ if (!(fdt_is_enabled(dt_child))) continue; if (!(fdt_pm_is_enabled(dt_child))) continue; di = malloc(sizeof(*di), M_SIMPLEBUS, M_WAITOK | M_ZERO); if (ofw_bus_gen_setup_devinfo(&di->di_ofw, dt_child) != 0) { free(di, M_SIMPLEBUS); device_printf(dev, "could not set up devinfo\n"); continue; } resource_list_init(&di->di_res); if (fdt_reg_to_rl(dt_child, &di->di_res)) { device_printf(dev, "%s: could not process 'reg' " "property\n", di->di_ofw.obd_name); /* XXX should unmap */ ofw_bus_gen_destroy_devinfo(&di->di_ofw); free(di, M_SIMPLEBUS); continue; } if (fdt_intr_to_rl(dt_child, &di->di_res, di->di_intr_sl)) { device_printf(dev, "%s: could not process " "'interrupts' property\n", di->di_ofw.obd_name); resource_list_free(&di->di_res); /* XXX should unmap */ ofw_bus_gen_destroy_devinfo(&di->di_ofw); free(di, M_SIMPLEBUS); continue; } /* Add newbus device for this FDT node */ dev_child = device_add_child(dev, NULL, -1); if (dev_child == NULL) { device_printf(dev, "could not add child: %s\n", di->di_ofw.obd_name); resource_list_free(&di->di_res); /* XXX should unmap */ ofw_bus_gen_destroy_devinfo(&di->di_ofw); free(di, M_SIMPLEBUS); continue; } #ifdef DEBUG device_printf(dev, "added child: %s\n\n", di->di_ofw.obd_name); #endif device_set_ivars(dev_child, di); } return (bus_generic_attach(dev)); }
static device_t newbus_pci_create(device_t dev_par, phandle_t dt_node, u_long par_base, u_long par_size) { pcell_t reg[3 + 2]; device_t dev_child; u_long start, end, count; struct fdtbus_devinfo *di; char *name, *type, *compat; int len; OF_getprop_alloc(dt_node, "device_type", 1, (void **)&type); if (!(type != NULL && strcmp(type, "pci") == 0)) { /* Only process 'pci' subnodes. */ free(type, M_OFWPROP); return (NULL); } OF_getprop_alloc(dt_node, "name", 1, (void **)&name); OF_getprop_alloc(OF_parent(dt_node), "compatible", 1, (void **)&compat); dev_child = device_add_child(dev_par, NULL, -1); if (dev_child == NULL) { free(name, M_OFWPROP); free(type, M_OFWPROP); free(compat, M_OFWPROP); return (NULL); } di = malloc(sizeof(*di), M_FDTBUS, M_WAITOK); di->di_node = dt_node; di->di_name = name; di->di_type = type; di->di_compat = compat; resource_list_init(&di->di_res); /* * Produce and set SYS_RES_MEMORY resources. */ start = 0; count = 0; len = OF_getprop(dt_node, "reg", ®, sizeof(reg)); if (len > 0) { if (fdt_data_verify((void *)®[1], 2) != 0) { device_printf(dev_child, "'reg' address value out of " "range\n"); newbus_device_destroy(dev_child); dev_child = NULL; goto out; } start = fdt_data_get((void *)®[1], 2); if (fdt_data_verify((void *)®[3], 2) != 0) { device_printf(dev_child, "'reg' size value out of " "range\n"); newbus_device_destroy(dev_child); dev_child = NULL; goto out; } count = fdt_data_get((void *)®[3], 2); } /* Calculate address range relative to base. */ par_base &= 0x000ffffful; start &= 0x000ffffful; start += par_base + fdt_immr_va; if (count == 0) count = par_size; end = start + count - 1; debugf("start = 0x%08lx, end = 0x%08lx, count = 0x%08lx\n", start, end, count); if (count > par_size) { device_printf(dev_child, "'reg' size value out of range\n"); newbus_device_destroy(dev_child); dev_child = NULL; goto out; } resource_list_add(&di->di_res, SYS_RES_MEMORY, 0, start, end, count); /* * Set SYS_RES_IRQ resources. */ if (fdt_intr_to_rl(OF_parent(dt_node), &di->di_res, di->di_intr_sl)) { device_printf(dev_child, "could not process 'interrupts' " "property\n"); newbus_device_destroy(dev_child); dev_child = NULL; goto out; } device_set_ivars(dev_child, di); debugf("added child name='%s', node=%p\n", name, (void *)dt_node); out: return (dev_child); }