Ejemplo n.º 1
0
Archivo: sbus.c Proyecto: MarginC/kame
static struct sbus_devinfo *
sbus_setup_dinfo(struct sbus_softc *sc, phandle_t node, char *name)
{
	struct sbus_devinfo *sdi;
	struct sbus_regs *reg;
	u_int32_t base, iv, *intr;
	int i, nreg, nintr, slot, rslot;

	sdi = malloc(sizeof(*sdi), M_DEVBUF, M_ZERO | M_WAITOK);
	if (sdi == NULL)
		return (NULL);
	resource_list_init(&sdi->sdi_rl);
	sdi->sdi_name = name;
	sdi->sdi_node = node;
	OF_getprop_alloc(node, "compat", 1, (void **)&sdi->sdi_compat);
	OF_getprop_alloc(node, "device_type", 1, (void **)&sdi->sdi_type);
	slot = -1;
	nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
	if (nreg == -1) {
		if (sdi->sdi_type == NULL ||
		    strcmp(sdi->sdi_type, "hierarchical") != 0) {
			sbus_destroy_dinfo(sdi);
			return (NULL);
		}
	} else {
		for (i = 0; i < nreg; i++) {
			base = reg[i].sbr_offset;
			if (SBUS_ABS(base)) {
				rslot = SBUS_ABS_TO_SLOT(base);
				base = SBUS_ABS_TO_OFFSET(base);
			} else
				rslot = reg[i].sbr_slot;
			if (slot != -1 && slot != rslot)
				panic("sbus_setup_dinfo: multiple slots");
			slot = rslot;

			resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY, i,
			    base, base + reg[i].sbr_size, reg[i].sbr_size);
		}
		free(reg, M_OFWPROP);
	}
	sdi->sdi_slot = slot;

	/*
	 * The `interrupts' property contains the Sbus interrupt level.
	 */
	nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr), (void **)&intr);
	if (nintr != -1) {
		for (i = 0; i < nintr; i++) {
			iv = intr[i];
			/*
			 * Sbus card devices need the slot number encoded into
			 * the vector as this is generally not done.
			 */
			if ((iv & INTMAP_OBIO_MASK) == 0)
				iv |= slot << 3;
			/* Set the ign as appropriate. */
			iv |= sc->sc_ign;
			resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ, i,
			    iv, iv, 1);
		}
		free(intr, M_OFWPROP);
	}
	if (OF_getprop(node, "burst-sizes", &sdi->sdi_burstsz,
	    sizeof(sdi->sdi_burstsz)) == -1)
		sdi->sdi_burstsz = sc->sc_burst;
	else
		sdi->sdi_burstsz &= sc->sc_burst;

	return (sdi);
}
Ejemplo n.º 2
0
static struct dma_devinfo *
dma_setup_dinfo(device_t dev, struct dma_softc *dsc, phandle_t node)
{
	struct dma_devinfo *ddi;
	struct sbus_regs *reg;
	uint32_t base, iv, *intr;
	int i, nreg, nintr, slot, rslot;

	ddi = malloc(sizeof(*ddi), M_DEVBUF, M_WAITOK | M_ZERO);
	if (ofw_bus_gen_setup_devinfo(&ddi->ddi_obdinfo, node) != 0) {
		free(ddi, M_DEVBUF);
		return (NULL);
	}
	resource_list_init(&ddi->ddi_rl);
	slot = -1;
	nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
	if (nreg == -1) {
		device_printf(dev, "<%s>: incomplete\n",
		    ddi->ddi_obdinfo.obd_name);
		goto fail;
	}
	for (i = 0; i < nreg; i++) {
		base = reg[i].sbr_offset;
		if (SBUS_ABS(base)) {
			rslot = SBUS_ABS_TO_SLOT(base);
			base = SBUS_ABS_TO_OFFSET(base);
		} else
			rslot = reg[i].sbr_slot;
		if (slot != -1 && slot != rslot) {
			device_printf(dev, "<%s>: multiple slots\n",
			    ddi->ddi_obdinfo.obd_name);
			free(reg, M_OFWPROP);
			goto fail;
		}
		slot = rslot;

		resource_list_add(&ddi->ddi_rl, SYS_RES_MEMORY, i, base,
		    base + reg[i].sbr_size, reg[i].sbr_size);
	}
	free(reg, M_OFWPROP);
	if (slot != dsc->sc_slot) {
		device_printf(dev, "<%s>: parent and child slot do not match\n",
		    ddi->ddi_obdinfo.obd_name);
		goto fail;
	}

	/*
	 * The `interrupts' property contains the SBus interrupt level.
	 */
	nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr),
	    (void **)&intr);
	if (nintr != -1) {
		for (i = 0; i < nintr; i++) {
			iv = intr[i];
			/*
			 * SBus card devices need the slot number encoded into
			 * the vector as this is generally not done.
			 */
			if ((iv & INTMAP_OBIO_MASK) == 0)
				iv |= slot << 3;
			/* Set the IGN as appropriate. */
			iv |= dsc->sc_ign << INTMAP_IGN_SHIFT;
			resource_list_add(&ddi->ddi_rl, SYS_RES_IRQ, i,
			    iv, iv, 1);
		}
		free(intr, M_OFWPROP);
	}
	return (ddi);

 fail:
	dma_destroy_dinfo(ddi);
	return (NULL);
}
Ejemplo n.º 3
0
static struct sbus_devinfo *
sbus_setup_dinfo(device_t dev, struct sbus_softc *sc, phandle_t node)
{
    struct sbus_devinfo *sdi;
    struct sbus_regs *reg;
    u_int32_t base, iv, *intr;
    int i, nreg, nintr, slot, rslot;

    sdi = malloc(sizeof(*sdi), M_DEVBUF, M_ZERO | M_WAITOK);
    if (ofw_bus_gen_setup_devinfo(&sdi->sdi_obdinfo, node) != 0) {
        free(sdi, M_DEVBUF);
        return (NULL);
    }
    resource_list_init(&sdi->sdi_rl);
    slot = -1;
    nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
    if (nreg == -1) {
        if (sdi->sdi_obdinfo.obd_type == NULL ||
                strcmp(sdi->sdi_obdinfo.obd_type, "hierarchical") != 0) {
            device_printf(dev, "<%s>: incomplete\n",
                          sdi->sdi_obdinfo.obd_name);
            goto fail;
        }
    } else {
        for (i = 0; i < nreg; i++) {
            base = reg[i].sbr_offset;
            if (SBUS_ABS(base)) {
                rslot = SBUS_ABS_TO_SLOT(base);
                base = SBUS_ABS_TO_OFFSET(base);
            } else
                rslot = reg[i].sbr_slot;
            if (slot != -1 && slot != rslot) {
                device_printf(dev, "<%s>: multiple slots\n",
                              sdi->sdi_obdinfo.obd_name);
                free(reg, M_OFWPROP);
                goto fail;
            }
            slot = rslot;

            resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY, i,
                              base, base + reg[i].sbr_size, reg[i].sbr_size);
        }
        free(reg, M_OFWPROP);
    }
    sdi->sdi_slot = slot;

    /*
     * The `interrupts' property contains the SBus interrupt level.
     */
    nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr),
                             (void **)&intr);
    if (nintr != -1) {
        for (i = 0; i < nintr; i++) {
            iv = intr[i];
            /*
             * SBus card devices need the slot number encoded into
             * the vector as this is generally not done.
             */
            if ((iv & INTMAP_OBIO_MASK) == 0)
                iv |= slot << 3;
            iv = INTMAP_VEC(sc->sc_ign, iv);
            resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ, i,
                              iv, iv, 1);
        }
        free(intr, M_OFWPROP);
    }
    if (OF_getprop(node, "burst-sizes", &sdi->sdi_burstsz,
                   sizeof(sdi->sdi_burstsz)) == -1)
        sdi->sdi_burstsz = sc->sc_burst;
    else
        sdi->sdi_burstsz &= sc->sc_burst;
    if (OF_getprop(node, "clock-frequency", &sdi->sdi_clockfreq,
                   sizeof(sdi->sdi_clockfreq)) == -1)
        sdi->sdi_clockfreq = sc->sc_clockfreq;

    return (sdi);

fail:
    sbus_destroy_dinfo(sdi);
    return (NULL);
}