Пример #1
0
static int
nexus_attach(device_t dev)
{
    struct nexus_devinfo *ndi;
    struct nexus_softc *sc;
    device_t cdev;
    phandle_t node;

    if (strcmp(device_get_name(device_get_parent(dev)), "root") == 0) {
        node = OF_peer(0);
        if (node == -1)
            panic("%s: OF_peer failed.", __func__);

        sc = device_get_softc(dev);
        sc->sc_intr_rman.rm_type = RMAN_ARRAY;
        sc->sc_intr_rman.rm_descr = "Interrupts";
        sc->sc_mem_rman.rm_type = RMAN_ARRAY;
        sc->sc_mem_rman.rm_descr = "Device Memory";
        if (rman_init(&sc->sc_intr_rman) != 0 ||
                rman_init(&sc->sc_mem_rman) != 0 ||
                rman_manage_region(&sc->sc_intr_rman, 0,
                                   IV_MAX - 1) != 0 ||
                rman_manage_region(&sc->sc_mem_rman, 0ULL, ~0ULL) != 0)
            panic("%s: failed to set up rmans.", __func__);
    } else
        node = ofw_bus_get_node(dev);

    /*
     * Allow devices to identify.
     */
    bus_generic_probe(dev);

    /*
     * Now walk the OFW tree and attach top-level devices.
     */
    for (node = OF_child(node); node > 0; node = OF_peer(node)) {
        if ((ndi = nexus_setup_dinfo(dev, node)) == NULL)
            continue;
        cdev = device_add_child(dev, NULL, -1);
        if (cdev == NULL) {
            device_printf(dev, "<%s>: device_add_child failed\n",
                          ndi->ndi_obdinfo.obd_name);
            nexus_destroy_dinfo(ndi);
            continue;
        }
        device_set_ivars(cdev, ndi);
    }
    return (bus_generic_attach(dev));
}
Пример #2
0
static int
nexus_attach(device_t dev)
{
	struct nexus_devinfo *ndi;
	struct nexus_softc *sc;
	device_t cdev;
	phandle_t node;

	sc = device_get_softc(dev);

	if (strcmp(device_get_name(device_get_parent(dev)), "root") == 0) {
		node = OF_peer(0);

		sc->sc_intr_rman.rm_type = RMAN_ARRAY;
		sc->sc_intr_rman.rm_descr = "Interrupts";
		sc->sc_mem_rman.rm_type = RMAN_ARRAY;
		sc->sc_mem_rman.rm_descr = "Device Memory";
		if (rman_init(&sc->sc_intr_rman) != 0 ||
		    rman_init(&sc->sc_mem_rman) != 0 ||
		    rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0 ||
		    rman_manage_region(&sc->sc_mem_rman, 0, BUS_SPACE_MAXADDR)
		     != 0)
			panic("%s: failed to set up rmans.", __func__);
	} else
		node = ofw_bus_get_node(dev);

	/*
	 * Allow devices to identify.
	 */
	bus_generic_probe(dev);

	/*
	 * If no Open Firmware, bail early
	 */
	if (node == -1)
		return (bus_generic_attach(dev));

	/*
	 * Some important numbers
	 */
	sc->acells = 2;
	OF_getprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
	sc->scells = 1;
	OF_getprop(node, "#size-cells", &sc->scells, sizeof(sc->scells));

	/*
	 * Now walk the OFW tree and attach top-level devices.
	 */
	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
		if ((ndi = nexus_setup_dinfo(dev, node)) == NULL)
			continue;
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    ndi->ndi_obdinfo.obd_name);
			nexus_destroy_dinfo(ndi);
			continue;
		}
		device_set_ivars(cdev, ndi);
	}
	return (bus_generic_attach(dev));
}
Пример #3
0
static struct nexus_devinfo *
nexus_setup_dinfo(device_t dev, phandle_t node)
{
    struct nexus_devinfo *ndi;
    struct nexus_regs *reg;
    bus_addr_t phys;
    bus_size_t size;
    uint32_t ign;
    uint32_t *intr;
    int i;
    int nintr;
    int nreg;

    ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
    if (ofw_bus_gen_setup_devinfo(&ndi->ndi_obdinfo, node) != 0) {
        free(ndi, M_DEVBUF);
        return (NULL);
    }
    if (NEXUS_EXCLUDED(ndi->ndi_obdinfo.obd_name,
                       ndi->ndi_obdinfo.obd_type)) {
        ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
        free(ndi, M_DEVBUF);
        return (NULL);
    }
    resource_list_init(&ndi->ndi_rl);
    nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
    if (nreg == -1) {
        device_printf(dev, "<%s>: incomplete\n",
                      ndi->ndi_obdinfo.obd_name);
        goto fail;
    }
    for (i = 0; i < nreg; i++) {
        phys = NEXUS_REG_PHYS(&reg[i]);
        size = NEXUS_REG_SIZE(&reg[i]);
        /* Skip the dummy reg property of glue devices like ssm(4). */
        if (size != 0)
            resource_list_add(&ndi->ndi_rl, SYS_RES_MEMORY, i,
                              phys, phys + size - 1, size);
    }
    free(reg, M_OFWPROP);

    nintr = OF_getprop_alloc(node, "interrupts",  sizeof(*intr),
                             (void **)&intr);
    if (nintr > 0) {
        if (OF_getprop(node, PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII ?
                       "upa-portid" : "portid", &ign, sizeof(ign)) <= 0) {
            device_printf(dev, "<%s>: could not determine portid\n",
                          ndi->ndi_obdinfo.obd_name);
            free(intr, M_OFWPROP);
            goto fail;
        }

        /* XXX 7-bit MID on Starfire */
        ign = (ign << INTMAP_IGN_SHIFT) & INTMAP_IGN_MASK;
        for (i = 0; i < nintr; i++) {
            intr[i] |= ign;
            resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
                              intr[i], 1);
        }
        free(intr, M_OFWPROP);
    }

    return (ndi);

fail:
    nexus_destroy_dinfo(ndi);
    return (NULL);
}