Exemple #1
0
static int
nexus_probe(device_t dev)
{
    phandle_t root;
    phandle_t child;
    device_t cdev;
    struct nexus_devinfo *dinfo;
    struct nexus_softc *sc;
    char *name, *type;

    if ((root = OF_peer(0)) == -1)
        panic("nexus_probe: OF_peer failed.");

    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 = "UPA 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, UPA_MEMSTART, UPA_MEMEND) != 0)
        panic("nexus_probe: failed to set up rmans");
    for (child = OF_child(root); child != 0; child = OF_peer(child)) {
        if (child == -1)
            panic("nexus_probe(): OF_child failed.");
        if (OF_getprop_alloc(child, "name", 1, (void **)&name) == -1)
            continue;
        OF_getprop_alloc(child, "device_type", 1, (void **)&type);
        if (NEXUS_EXCLUDED(name, type)) {
            free(name, M_OFWPROP);
            if (type != NULL)
                free(type, M_OFWPROP);
            continue;
        }
        cdev = device_add_child(dev, NULL, -1);
        if (cdev != NULL) {
            dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK);
            dinfo->ndi_node = child;
            dinfo->ndi_name = name;
            dinfo->ndi_device_type = type;
            OF_getprop_alloc(child, "model", 1,
                             (void **)&dinfo->ndi_model);
            dinfo->ndi_nreg = OF_getprop_alloc(child, "reg",
                                               sizeof(*dinfo->ndi_reg), (void **)&dinfo->ndi_reg);
            dinfo->ndi_ninterrupts = OF_getprop_alloc(child,
                                     "interrupts", sizeof(*dinfo->ndi_interrupts),
                                     (void **)&dinfo->ndi_interrupts);
            dinfo->ndi_bustag = &nexus_bustag;
            dinfo->ndi_dmatag = &nexus_dmatag;
            device_set_ivars(cdev, dinfo);
        } else
            free(name, M_OFWPROP);

    }
    device_set_desc(dev, "OpenFirmware Nexus device");
    return (0);
}
Exemple #2
0
static struct nexus_devinfo *
nexus_setup_dinfo(device_t dev, phandle_t node)
{
	struct nexus_softc *sc;
	struct nexus_devinfo *ndi;
	uint32_t *reg, *intr, icells;
	uint64_t phys, size;
	phandle_t iparent;
	int i, j;
	int nintr;
	int nreg;

	sc = device_get_softc(dev);

	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)
		nreg = 0;

	for (i = 0; i < nreg; i += sc->acells + sc->scells) {
		phys = size = 0;
		for (j = 0; j < sc->acells; j++) {
			phys <<= 32;
			phys |= reg[i + j];
		}
		for (j = 0; j < sc->scells; j++) {
			size <<= 32;
			size |= reg[i + sc->acells + j];
		}
		/* 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) {
		iparent = 0;
		OF_searchprop(node, "interrupt-parent", &iparent,
		    sizeof(iparent));
		OF_searchprop(iparent, "#interrupt-cells", &icells,
		    sizeof(icells));
		for (i = 0; i < nintr; i+= icells) {
			intr[i] = MAP_IRQ(iparent, intr[i]);
			resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
			    intr[i], 1);
			if (icells > 1) {
				powerpc_config_intr(intr[i], (intr[i+1] & 1) ?
				    INTR_TRIGGER_LEVEL : INTR_TRIGGER_EDGE,
				    INTR_POLARITY_LOW);
			}
		}
		free(intr, M_OFWPROP);
	}

	return (ndi);
}
Exemple #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);
}