static int
ebus_release_resource(device_t bus, device_t child, int type, int rid,
    struct resource *res)
{
	struct resource_list *rl;
	struct resource_list_entry *rle;
	int passthrough = (device_get_parent(child) != bus);
	int rv;

	rl = BUS_GET_RESOURCE_LIST(bus, child);
	switch (type) {
	case SYS_RES_MEMORY:
		if ((rv = rman_release_resource(res)) != 0)
			return (rv);
		if (!passthrough) {
			rle = resource_list_find(rl, type, rid);
			KASSERT(rle != NULL, ("ebus_release_resource: "
			    "resource entry not found!"));
			KASSERT(rle->res != NULL, ("ebus_alloc_resource: "
			    "resource entry is not busy"));
			rle->res = NULL;
		}
		break;
	case SYS_RES_IRQ:
		return (resource_list_release(rl, bus, child, type, rid, res));
	default:
		panic("ebus_release_resource: unsupported resource type %d",
		    type);
	}
	return (0);
}
Exemple #2
0
static struct resource *
ofwbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
	struct ofwbus_softc *sc;
	struct rman *rm;
	struct resource *rv;
	struct resource_list_entry *rle;
	int isdefault, passthrough;

	isdefault = RMAN_IS_DEFAULT_RANGE(start, end);
	passthrough = (device_get_parent(child) != bus);
	sc = device_get_softc(bus);
	rle = NULL;
	if (!passthrough && isdefault) {
		rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child),
		    type, *rid);
		if (rle == NULL) {
			if (bootverbose)
				device_printf(bus, "no default resources for "
				    "rid = %d, type = %d\n", *rid, type);
			return (NULL);
		}
		start = rle->start;
		count = ulmax(count, rle->count);
		end = ulmax(rle->end, start + count - 1);
	}

	switch (type) {
	case SYS_RES_IRQ:
		rm = &sc->sc_intr_rman;
		break;
	case SYS_RES_MEMORY:
		rm = &sc->sc_mem_rman;
		break;
	default:
		return (NULL);
	}

	rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
	    child);
	if (rv == NULL)
		return (NULL);
	rman_set_rid(rv, *rid);

	if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
	    *rid, rv) != 0) {
		rman_release_resource(rv);
		return (NULL);
	}

	if (!passthrough && rle != NULL) {
		rle->res = rv;
		rle->start = rman_get_start(rv);
		rle->end = rman_get_end(rv);
		rle->count = rle->end - rle->start + 1;
	}

	return (rv);
}
Exemple #3
0
static int
sbus_release_resource(device_t bus, device_t child, int type, int rid,
                      struct resource *r)
{
    struct resource_list *rl;
    struct resource_list_entry *rle;
    int error, passthrough;

    passthrough = (device_get_parent(child) != bus);
    rl = BUS_GET_RESOURCE_LIST(bus, child);
    if (type == SYS_RES_MEMORY) {
        if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
            error = bus_deactivate_resource(child, type, rid, r);
            if (error)
                return (error);
        }
        error = rman_release_resource(r);
        if (error != 0)
            return (error);
        if (!passthrough) {
            rle = resource_list_find(rl, type, rid);
            KASSERT(rle != NULL,
                    ("%s: resource entry not found!", __func__));
            KASSERT(rle->res != NULL,
                    ("%s: resource entry is not busy", __func__));
            rle->res = NULL;
        }
        return (0);
    }
    return (resource_list_release(rl, bus, child, type, rid, r));
}
Exemple #4
0
static int
sbus_release_resource(device_t bus, device_t child, int type, int rid,
    struct resource *r)
{
	struct resource_list *rl;
	struct resource_list_entry *rle;
	int error, passthrough;

	passthrough = (device_get_parent(child) != bus);
	rl = BUS_GET_RESOURCE_LIST(bus, child);
	if (type == SYS_RES_IRQ)
		return (resource_list_release(rl, bus, child, type, rid, r));
	if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
		error = bus_deactivate_resource(child, type, rid, r);
		if (error != 0)
			return (error);
	}
	error = rman_release_resource(r);
	if (error != 0 || passthrough)
		return (error);
	rle = resource_list_find(rl, type, rid);
	if (rle == NULL)
		panic("%s: cannot find resource", __func__);
	if (rle->res == NULL)
		panic("%s: resource entry is not busy", __func__);
	rle->res = NULL;
	return (0);
}
Exemple #5
0
static struct resource *
ofwbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
	struct ofwbus_softc *sc;
	struct rman *rm;
	struct resource *rv;
	struct resource_list_entry *rle;
	int isdefault, passthrough;

	isdefault = (start == 0UL && end == ~0UL);
	passthrough = (device_get_parent(child) != bus);
	sc = device_get_softc(bus);
	rle = NULL;

	if (!passthrough && isdefault) {
		rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child),
		    type, *rid);
		if (rle == NULL)
			return (NULL);
		if (rle->res != NULL)
			panic("%s: resource entry is busy", __func__);
		start = rle->start;
		count = ulmax(count, rle->count);
		end = ulmax(rle->end, start + count - 1);
	}

	switch (type) {
	case SYS_RES_IRQ:
		rm = &sc->sc_intr_rman;
		break;
	case SYS_RES_MEMORY:
		rm = &sc->sc_mem_rman;
		break;
	default:
		return (NULL);
	}

	rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
	    child);
	if (rv == NULL)
		return (NULL);
	rman_set_rid(rv, *rid);

	if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
	    *rid, rv) != 0) {
		rman_release_resource(rv);
		return (NULL);
	}

	if (!passthrough && rle != NULL) {
		rle->res = rv;
		rle->start = rman_get_start(rv);
		rle->end = rman_get_end(rv);
		rle->count = rle->end - rle->start + 1;
	}

	return (rv);
}
Exemple #6
0
static struct resource_list *
ndis_get_resource_list(device_t dev, device_t child)
{
	struct ndis_softc *sc;

	sc = device_get_softc(dev);
	return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev));
}
Exemple #7
0
static struct resource *
central_alloc_resource(device_t bus, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
	struct resource_list *rl;
	struct resource_list_entry *rle;
	struct central_softc *sc;
	struct resource *res;
	bus_addr_t coffset;
	bus_addr_t cend;
	bus_addr_t phys;
	int isdefault;
	int passthrough;
	int i;

	isdefault = (start == 0UL && end == ~0UL);
	passthrough = (device_get_parent(child) != bus);
	res = NULL;
	rle = NULL;
	rl = BUS_GET_RESOURCE_LIST(bus, child);
	sc = device_get_softc(bus);
	switch (type) {
	case SYS_RES_IRQ:
		return (resource_list_alloc(rl, bus, child, type, rid, start,
		    end, count, flags));
	case SYS_RES_MEMORY:
		if (!passthrough) {
			rle = resource_list_find(rl, type, *rid);
			if (rle == NULL)
				return (NULL);
			if (rle->res != NULL)
				panic("%s: resource entry is busy", __func__);
			if (isdefault) {
				start = rle->start;
				count = ulmax(count, rle->count);
				end = ulmax(rle->end, start + count - 1);
			}
		}
		for (i = 0; i < sc->sc_nrange; i++) {
			coffset = sc->sc_ranges[i].coffset;
			cend = coffset + sc->sc_ranges[i].size - 1;
			if (start >= coffset && end <= cend) {
				start -= coffset;
				end -= coffset;
				phys = sc->sc_ranges[i].poffset |
				    ((bus_addr_t)sc->sc_ranges[i].pspace << 32);
				res = bus_generic_alloc_resource(bus, child,
				    type, rid, phys + start, phys + end,
				    count, flags);
				if (!passthrough)
					rle->res = res;
				break;
			}
		}
		break;
	}
	return (res);
}
static int
jz4780_pinctrl_attach(device_t dev)
{
	struct jz4780_pinctrl_softc *sc;
	struct resource_list *rs;
	struct resource_list_entry *re;
	phandle_t dt_parent, dt_child;
	int i, ret;

	sc = device_get_softc(dev);
	sc->dev = dev;

	/*
	 * Fetch our own resource list to dole memory between children
	 */
	rs = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
	if (rs == NULL)
		return (ENXIO);
	re = resource_list_find(rs, SYS_RES_MEMORY, 0);
	if (re == NULL)
		return (ENXIO);

	simplebus_init(dev, 0);

	/* Iterate over this node children, looking for pin controllers */
	dt_parent = ofw_bus_get_node(dev);
	i = 0;
	for (dt_child = OF_child(dt_parent); dt_child != 0;
	    dt_child = OF_peer(dt_child)) {
		struct simplebus_devinfo *ndi;
		device_t child;
		bus_addr_t phys;
		bus_size_t size;

		/* Add gpio controller child */
		if (!OF_hasprop(dt_child, "gpio-controller"))
			continue;
		child = simplebus_add_device(dev, dt_child, 0,  NULL, -1, NULL);
		if (child == NULL)
			break;
		/* Setup child resources */
		phys = CHIP_REG_OFFSET(re->start, i);
		size = CHIP_REG_STRIDE;
		if (phys + size - 1 <= re->end) {
			ndi = device_get_ivars(child);
			resource_list_add(&ndi->rl, SYS_RES_MEMORY, 0,
			    phys, phys + size - 1, size);
		}
		i++;
	}

	ret = bus_generic_attach(dev);
	if (ret == 0) {
	    fdt_pinctrl_register(dev, "ingenic,pins");
	    fdt_pinctrl_configure_tree(dev);
	}
	return (ret);
}
Exemple #9
0
static int
chipc_release_resource(device_t dev, device_t child, int type, int rid,
    struct resource *r)
{
	struct chipc_softc		*sc;
	struct chipc_region		*cr;
	struct rman			*rm;
	struct resource_list_entry	*rle;
	int			 	 error;

	sc = device_get_softc(dev);

	/* Handled by parent bus? */
	rm = chipc_get_rman(sc, type);
	if (rm == NULL || !rman_is_region_manager(r, rm)) {
		return (bus_generic_rl_release_resource(dev, child, type, rid,
		    r));
	}

	/* Locate the mapping region */
	cr = chipc_find_region(sc, rman_get_start(r), rman_get_end(r));
	if (cr == NULL)
		return (EINVAL);

	/* Deactivate resources */
	if (rman_get_flags(r) & RF_ACTIVE) {
		error = BUS_DEACTIVATE_RESOURCE(dev, child, type, rid, r);
		if (error)
			return (error);
	}

	if ((error = rman_release_resource(r)))
		return (error);

	/* Drop allocation reference */
	chipc_release_region(sc, cr, RF_ALLOCATED);

	/* Clear reference from the resource list entry if exists */
	rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child), type, rid);
	if (rle != NULL)
		rle->res = NULL;

	return (0);
}
Exemple #10
0
static int
ofwbus_release_resource(device_t bus, device_t child, int type,
    int rid, struct resource *r)
{
	struct resource_list_entry *rle;
	int error;

	/* Clean resource list entry */
	rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), type, rid);
	if (rle != NULL)
		rle->res = NULL;

	if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
		error = bus_deactivate_resource(child, type, rid, r);
		if (error)
			return (error);
	}
	return (rman_release_resource(r));
}
Exemple #11
0
static void
chipc_probe_nomatch(device_t dev, device_t child)
{
	struct resource_list	*rl;
	const char		*name;

	name = device_get_name(child);
	if (name == NULL)
		name = "unknown device";

	device_printf(dev, "<%s> at", name);

	rl = BUS_GET_RESOURCE_LIST(dev, child);
	if (rl != NULL) {
		resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
		resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
	}

	printf(" (no driver attached)\n");
}
Exemple #12
0
static struct resource *
gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
	struct gpiobus_softc *sc;
	struct resource *rv;
	struct resource_list *rl;
	struct resource_list_entry *rle;
	int isdefault;

	if (type != SYS_RES_IRQ)
		return (NULL);
	isdefault = (start == 0UL && end == ~0UL && count == 1);
	rle = NULL;
	if (isdefault) {
		rl = BUS_GET_RESOURCE_LIST(bus, child);
		if (rl == NULL)
			return (NULL);
		rle = resource_list_find(rl, type, *rid);
		if (rle == NULL)
			return (NULL);
		if (rle->res != NULL)
			panic("%s: resource entry is busy", __func__);
		start = rle->start;
		count = rle->count;
		end = rle->end;
	}
	sc = device_get_softc(bus);
	rv = rman_reserve_resource(&sc->sc_intr_rman, start, end, count, flags,
	    child);
	if (rv == NULL)
		return (NULL);
	rman_set_rid(rv, *rid);
	if ((flags & RF_ACTIVE) != 0 &&
	    bus_activate_resource(child, type, *rid, rv) != 0) {
		rman_release_resource(rv);
		return (NULL);
	}

	return (rv);
}
Exemple #13
0
static int
chipc_print_child(device_t dev, device_t child)
{
	struct resource_list	*rl;
	int			 retval = 0;

	retval += bus_print_child_header(dev, child);

	rl = BUS_GET_RESOURCE_LIST(dev, child);
	if (rl != NULL) {
		retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
		    "%#jx");
		retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ,
		    "%jd");
	}

	retval += bus_print_child_domain(dev, child);
	retval += bus_print_child_footer(dev, child);

	return (retval);
}
Exemple #14
0
/**
 * Helper function for implementing BUS_PRINT_CHILD().
 * 
 * This implementation requests the device's struct resource_list via
 * BUS_GET_RESOURCE_LIST.
 */
int
bhnd_generic_print_child(device_t dev, device_t child)
{
	struct resource_list	*rl;
	int			retval = 0;

	retval += bus_print_child_header(dev, child);

	rl = BUS_GET_RESOURCE_LIST(dev, child);
	if (rl != NULL) {
		retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
		    "%#lx");
	}

	retval += printf(" at core %u", bhnd_get_core_index(child));

	retval += bus_print_child_domain(dev, child);
	retval += bus_print_child_footer(dev, child);

	return (retval);
}
Exemple #15
0
/**
 * Helper function for implementing BUS_PRINT_CHILD().
 * 
 * This implementation requests the device's struct resource_list via
 * BUS_GET_RESOURCE_LIST.
 */
void
bhnd_generic_probe_nomatch(device_t dev, device_t child)
{
	struct resource_list		*rl;
	const struct bhnd_nomatch	*nm;
	bool				 report;

	/* Fetch reporting configuration for this device */
	report = true;
	for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) {
		if (nm->vendor != bhnd_get_vendor(child))
			continue;

		if (nm->device != bhnd_get_device(child))
			continue;

		report = false;
		if (bootverbose && nm->if_verbose)
			report = true;
		break;
	}
	
	if (!report)
		return;

	/* Print the non-matched device info */
	device_printf(dev, "<%s %s>", bhnd_get_vendor_name(child),
		bhnd_get_device_name(child));

	rl = BUS_GET_RESOURCE_LIST(dev, child);
	if (rl != NULL)
		resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");

	printf(" at core %u (no driver attached)\n",
	    bhnd_get_core_index(child));
}
Exemple #16
0
static struct resource *
chipc_alloc_resource(device_t dev, device_t child, int type,
    int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
	struct chipc_softc		*sc;
	struct chipc_region		*cr;
	struct resource_list_entry	*rle;
	struct resource			*rv;
	struct rman			*rm;
	int				 error;
	bool				 passthrough, isdefault;

	sc = device_get_softc(dev);
	passthrough = (device_get_parent(child) != dev);
	isdefault = RMAN_IS_DEFAULT_RANGE(start, end);
	rle = NULL;

	/* Fetch the resource manager, delegate request if necessary */
	rm = chipc_get_rman(sc, type);
	if (rm == NULL) {
		/* Requested resource type is delegated to our parent */
		rv = bus_generic_rl_alloc_resource(dev, child, type, rid,
		    start, end, count, flags);
		return (rv);
	}

	/* Populate defaults */
	if (!passthrough && isdefault) {
		/* Fetch the resource list entry. */
		rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child),
		    type, *rid);
		if (rle == NULL) {
			device_printf(dev,
			    "default resource %#x type %d for child %s "
			    "not found\n", *rid, type,
			    device_get_nameunit(child));			
			return (NULL);
		}
		
		if (rle->res != NULL) {
			device_printf(dev,
			    "resource entry %#x type %d for child %s is busy "
			    "[%d]\n",
			    *rid, type, device_get_nameunit(child),
			    rman_get_flags(rle->res));
			
			return (NULL);
		}

		start = rle->start;
		end = rle->end;
		count = ulmax(count, rle->count);
	}

	/* Locate a mapping region */
	if ((cr = chipc_find_region(sc, start, end)) == NULL) {
		/* Resource requests outside our shared port regions can be
		 * delegated to our parent. */
		rv = bus_generic_rl_alloc_resource(dev, child, type, rid,
		    start, end, count, flags);
		return (rv);
	}

	/* Try to retain a region reference */
	if ((error = chipc_retain_region(sc, cr, RF_ALLOCATED)))
		return (NULL);

	/* Make our rman reservation */
	rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
	    child);
	if (rv == NULL) {
		chipc_release_region(sc, cr, RF_ALLOCATED);
		return (NULL);
	}

	rman_set_rid(rv, *rid);

	/* Activate */
	if (flags & RF_ACTIVE) {
		error = bus_activate_resource(child, type, *rid, rv);
		if (error) {
			device_printf(dev,
			    "failed to activate entry %#x type %d for "
				"child %s: %d\n",
			     *rid, type, device_get_nameunit(child), error);

			chipc_release_region(sc, cr, RF_ALLOCATED);
			rman_release_resource(rv);

			return (NULL);
		}
	}

	/* Update child's resource list entry */
	if (rle != NULL) {
		rle->res = rv;
		rle->start = rman_get_start(rv);
		rle->end = rman_get_end(rv);
		rle->count = rman_get_size(rv);
	}

	return (rv);
}
static struct resource *
ebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
	struct ebus_softc *sc;
	struct resource_list *rl;
	struct resource_list_entry *rle = NULL;
	struct resource *res;
	struct ebus_rinfo *ri;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int passthrough = (device_get_parent(child) != bus);
	int isdefault = (start == 0UL && end == ~0UL);
	int ridx, rv;

	sc = (struct ebus_softc *)device_get_softc(bus);
	rl = BUS_GET_RESOURCE_LIST(bus, child);
	/*
	 * Map EBus ranges to PCI ranges.  This may include changing the
	 * allocation type.
	 */
	switch (type) {
	case SYS_RES_MEMORY:
		KASSERT(!(isdefault && passthrough),
		    ("ebus_alloc_resource: passthrough of default alloc"));
		if (!passthrough) {
			rle = resource_list_find(rl, type, *rid);
			if (rle == NULL)
				return (NULL);
			KASSERT(rle->res == NULL,
			    ("ebus_alloc_resource: resource entry is busy"));
			if (isdefault) {
				start = rle->start;
				count = ulmax(count, rle->count);
				end = ulmax(rle->end, start + count - 1);
			}
		}

		(void)ofw_isa_range_map(sc->sc_range, sc->sc_nrange,
		    &start, &end, &ridx);

		ri = &sc->sc_rinfo[ridx];
		res = rman_reserve_resource(&ri->eri_rman, start, end, count,
		    flags, child);
		if (res == NULL)
			return (NULL);
		rman_set_rid(res, *rid);
		bt = rman_get_bustag(ri->eri_res);
		rman_set_bustag(res, bt);
		rv = bus_space_subregion(bt, rman_get_bushandle(ri->eri_res),
		    rman_get_start(res) - rman_get_start(ri->eri_res), count,
		    &bh);
		if (rv != 0) {
			rman_release_resource(res);
			return (NULL);
		}
		rman_set_bushandle(res, bh);
		if (!passthrough)
			rle->res = res;
		return (res);
	case SYS_RES_IRQ:
		return (resource_list_alloc(rl, bus, child, type, rid, start,
		    end, count, flags));
	}
	return (NULL);
}
Exemple #18
0
static struct resource *
ebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
	struct ebus_softc *sc;
	struct resource_list *rl;
	struct resource_list_entry *rle = NULL;
	struct resource *res;
	struct ebus_rinfo *eri;
	struct ebus_nexus_ranges *enr;
	uint64_t cend, cstart, offset;
	int i, isdefault, passthrough, ridx;

	isdefault = (start == 0UL && end == ~0UL);
	passthrough = (device_get_parent(child) != bus);
	sc = device_get_softc(bus);
	rl = BUS_GET_RESOURCE_LIST(bus, child);
	switch (type) {
	case SYS_RES_MEMORY:
		KASSERT(!(isdefault && passthrough),
		    ("%s: passthrough of default allocation", __func__));
		if (!passthrough) {
			rle = resource_list_find(rl, type, *rid);
			if (rle == NULL)
				return (NULL);
			KASSERT(rle->res == NULL,
			    ("%s: resource entry is busy", __func__));
			if (isdefault) {
				start = rle->start;
				count = ulmax(count, rle->count);
				end = ulmax(rle->end, start + count - 1);
			}
		}

		res = NULL;
		if ((sc->sc_flags & EBUS_PCI) != 0) {
			/*
			 * Map EBus ranges to PCI ranges.  This may include
			 * changing the allocation type.
			 */
			(void)ofw_isa_range_map(sc->sc_range, sc->sc_nrange,
			    &start, &end, &ridx);
			eri = &sc->sc_rinfo[ridx];
			res = rman_reserve_resource(&eri->eri_rman, start,
			    end, count, flags & ~RF_ACTIVE, child);
			if (res == NULL)
				return (NULL);
			rman_set_rid(res, *rid);
			if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(
			    child, type, *rid, res) != 0) {
				rman_release_resource(res);
				return (NULL);
			}
		} else {
			/* Map EBus ranges to nexus ranges. */
			for (i = 0; i < sc->sc_nrange; i++) {
				enr = &((struct ebus_nexus_ranges *)
				    sc->sc_range)[i];
				cstart = (((uint64_t)enr->child_hi) << 32) |
				    enr->child_lo;
				cend = cstart + enr->size - 1;
				if (start >= cstart && end <= cend) {
					offset =
					    (((uint64_t)enr->phys_hi) << 32) |
					    enr->phys_lo;
					start += offset - cstart;
					end += offset - cstart;
					res = bus_generic_alloc_resource(bus,
					    child, type, rid, start, end,
					    count, flags);
					break;
				}
			}
		}
		if (!passthrough)
			rle->res = res;
		return (res);
	case SYS_RES_IRQ:
		return (resource_list_alloc(rl, bus, child, type, rid, start,
		    end, count, flags));
	}
	return (NULL);
}
Exemple #19
0
int
openpic_attach(device_t dev)
{
	struct openpic_softc *sc;
	u_int     cpu, ipi, irq;
	u_int32_t x;

	sc = device_get_softc(dev);
	sc->sc_dev = dev;

	sc->sc_rid = 0;
	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
	    RF_ACTIVE);

	if (sc->sc_memr == NULL) {
		device_printf(dev, "Could not alloc mem resource!\n");
		return (ENXIO);
	}

	sc->sc_bt = rman_get_bustag(sc->sc_memr);
	sc->sc_bh = rman_get_bushandle(sc->sc_memr);

	/* Reset the PIC */
	x = openpic_read(sc, OPENPIC_CONFIG);
	x |= OPENPIC_CONFIG_RESET;
	openpic_write(sc, OPENPIC_CONFIG, x);

	while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) {
		powerpc_sync();
		DELAY(100);
	}

	/* Check if this is a cascaded PIC */
	sc->sc_irq = 0;
	sc->sc_intr = NULL;
	do {
		struct resource_list *rl;

		rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
		if (rl == NULL)
			break;
		if (resource_list_find(rl, SYS_RES_IRQ, 0) == NULL)
			break;

		sc->sc_intr = bus_alloc_resource_any(dev, SYS_RES_IRQ,
		    &sc->sc_irq, RF_ACTIVE);

		/* XXX Cascaded PICs pass NULL trapframes! */
		bus_setup_intr(dev, sc->sc_intr, INTR_TYPE_MISC | INTR_MPSAFE,
		    openpic_intr, NULL, dev, &sc->sc_icookie);
	} while (0);

	/* Reset the PIC */
	x = openpic_read(sc, OPENPIC_CONFIG);
	x |= OPENPIC_CONFIG_RESET;
	openpic_write(sc, OPENPIC_CONFIG, x);

	while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) {
		powerpc_sync();
		DELAY(100);
	}

	x = openpic_read(sc, OPENPIC_FEATURE);
	switch (x & OPENPIC_FEATURE_VERSION_MASK) {
	case 1:
		sc->sc_version = "1.0";
		break;
	case 2:
		sc->sc_version = "1.2";
		break;
	case 3:
		sc->sc_version = "1.3";
		break;
	default:
		sc->sc_version = "unknown";
		break;
	}

	sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >>
	    OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1;
	sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >>
	    OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1;

	/*
	 * PSIM seems to report 1 too many IRQs and CPUs
	 */
	if (sc->sc_psim) {
		sc->sc_nirq--;
		sc->sc_ncpu--;
	}

	if (bootverbose)
		device_printf(dev,
		    "Version %s, supports %d CPUs and %d irqs\n",
		    sc->sc_version, sc->sc_ncpu, sc->sc_nirq);

	for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
		openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 15);

	/* Reset and disable all interrupts. */
	for (irq = 0; irq < sc->sc_nirq; irq++) {
		x = irq;                /* irq == vector. */
		x |= OPENPIC_IMASK;
		x |= OPENPIC_POLARITY_NEGATIVE;
		x |= OPENPIC_SENSE_LEVEL;
		x |= 8 << OPENPIC_PRIORITY_SHIFT;
		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
	}

	/* Reset and disable all IPIs. */
	for (ipi = 0; ipi < 4; ipi++) {
		x = sc->sc_nirq + ipi;
		x |= OPENPIC_IMASK;
		x |= 15 << OPENPIC_PRIORITY_SHIFT;
		openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x);
	}

	/* we don't need 8259 passthrough mode */
	x = openpic_read(sc, OPENPIC_CONFIG);
	x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
	openpic_write(sc, OPENPIC_CONFIG, x);

	/* send all interrupts to cpu 0 */
	for (irq = 0; irq < sc->sc_nirq; irq++)
		openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0);

	/* clear all pending interrupts from cpu 0 */
	for (irq = 0; irq < sc->sc_nirq; irq++) {
		(void)openpic_read(sc, OPENPIC_PCPU_IACK(0));
		openpic_write(sc, OPENPIC_PCPU_EOI(0), 0);
	}

	for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
		openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0);

	powerpc_register_pic(dev, sc->sc_nirq);

	/* If this is not a cascaded PIC, it must be the root PIC */
	if (sc->sc_intr == NULL)
		root_pic = dev;

	return (0);
}
Exemple #20
0
static void
isa_setup_children(device_t dev, phandle_t parent)
{
	struct isa_regs *regs;
	struct resource_list *rl;
	device_t cdev;
	u_int64_t end, start;
	ofw_isa_intr_t *intrs, rintr;
	phandle_t node;
	uint32_t *drqs, *regidx;
	int i, ndrq, nintr, nreg, nregidx, rid, rtype;
	char *name;

	/*
	 * Loop through children and fake up PnP devices for them.
	 * Their resources are added as fully mapped and specified because
	 * adjusting the resources and the resource list entries respectively
	 * in isa_alloc_resource() causes trouble with drivers which use
	 * rman_get_start(), pass-through or allocate and release resources
	 * multiple times, etc. Adjusting the resources might be better off
	 * in a bus_activate_resource method but the common ISA code doesn't
	 * allow for an isa_activate_resource().
	 */
	for (node = OF_child(parent); node != 0; node = OF_peer(node)) {
		if ((OF_getprop_alloc(node, "name", 1, (void **)&name)) == -1)
			continue;

		/*
		 * Keyboard and mouse controllers hang off of the `8042'
		 * node but we have no real use for the `8042' itself.
		 */
		if (strcmp(name, "8042") == 0) {
			isa_setup_children(dev, node);
			free(name, M_OFWPROP);
			continue;
		}

		for (i = 0; ofw_isa_pnp_map[i].name != NULL; i++)
			if (strcmp(ofw_isa_pnp_map[i].name, name) == 0)
				break;
		if (ofw_isa_pnp_map[i].name == NULL) {
			device_printf(dev, "no PnP map entry for node "
			    "0x%lx: %s\n", (unsigned long)node, name);
			free(name, M_OFWPROP);
			continue;
		}

		if ((cdev = BUS_ADD_CHILD(dev, ISA_ORDER_PNPBIOS, NULL, -1)) ==
		    NULL)
			panic("isa_setup_children: BUS_ADD_CHILD failed");
		isa_set_logicalid(cdev, ofw_isa_pnp_map[i].id);
		isa_set_vendorid(cdev, ofw_isa_pnp_map[i].id);

		rl = BUS_GET_RESOURCE_LIST(dev, cdev);
		nreg = OF_getprop_alloc(node, "reg", sizeof(*regs),
		    (void **)&regs);
		for (i = 0; i < nreg; i++) {
			start = ISA_REG_PHYS(&regs[i]);
			end = start + regs[i].size - 1;
			rtype = ofw_isa_range_map(isab_ranges, isab_nrange,
			    &start, &end, NULL);
			rid = 0;
			while (resource_list_find(rl, rtype, rid) != NULL)
				rid++;
			bus_set_resource(cdev, rtype, rid, start,
			    end - start + 1);
		}
		if (nreg == -1 && parent != isab_node) {
			/*
			 * The "reg" property still might be an index into
			 * the set of registers of the parent device like
			 * with the nodes hanging off of the `8042' node.
			 */
			nregidx = OF_getprop_alloc(node, "reg", sizeof(*regidx),
			    (void **)&regidx);
			if (nregidx > 2)
				panic("isa_setup_children: impossible number "
				    "of register indices");
			if (nregidx != -1 && (nreg = OF_getprop_alloc(parent,
			    "reg", sizeof(*regs), (void **)&regs)) >= nregidx) {
				for (i = 0; i < nregidx; i++) {
					start = ISA_REG_PHYS(&regs[regidx[i]]);
					end = start + regs[regidx[i]].size - 1;
					rtype = ofw_isa_range_map(isab_ranges,
					    isab_nrange, &start, &end, NULL);
					rid = 0;
					while (resource_list_find(rl, rtype,
					    rid) != NULL)
						rid++;
					bus_set_resource(cdev, rtype, rid,
					    start, end - start + 1);
				}
			}
			if (regidx != NULL)
				free(regidx, M_OFWPROP);
		}
		if (regs != NULL)
			free(regs, M_OFWPROP);

		nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs),
		    (void **)&intrs);
		for (i = 0; i < nintr; i++) {
			if (intrs[i] > 7)
				panic("isa_setup_children: intr too large");
			rintr = ofw_isa_route_intr(device_get_parent(dev), node,
			    &isa_iinfo, intrs[i]);
			if (rintr == PCI_INVALID_IRQ) {
				device_printf(dev, "could not map ISA "
				    "interrupt %d for node 0x%lx: %s\n",
				    intrs[i], (unsigned long)node, name);
				continue;
			}
			bus_set_resource(cdev, SYS_RES_IRQ, i, rintr, 1);
		}
		if (intrs != NULL)
			free(intrs, M_OFWPROP);

		ndrq = OF_getprop_alloc(node, "dma-channel", sizeof(*drqs),
		    (void **)&drqs);
		for (i = 0; i < ndrq; i++)
			bus_set_resource(cdev, SYS_RES_DRQ, i, drqs[i], 1);
		if (drqs != NULL)
			free(drqs, M_OFWPROP);

		/*
		 * Devices using DMA hang off of the `dma' node instead of
		 * directly from the ISA bridge node.
		 */
		if (strcmp(name, "dma") == 0)
			isa_setup_children(dev, node);

		free(name, M_OFWPROP);
	}
}
Exemple #21
0
/**
 * Helper function for implementing BHND_BUS_ALLOC_RESOURCE().
 * 
 * This simple implementation of BHND_BUS_ALLOC_RESOURCE() determines
 * any default values via BUS_GET_RESOURCE_LIST(), and calls
 * BHND_BUS_ALLOC_RESOURCE() method of the parent of @p dev.
 * 
 * If no parent device is available, the request is instead delegated to
 * BUS_ALLOC_RESOURCE().
 */
struct bhnd_resource *
bhnd_generic_alloc_bhnd_resource(device_t dev, device_t child, int type,
	int *rid, rman_res_t start, rman_res_t end, rman_res_t count,
	u_int flags)
{
	struct bhnd_resource		*r;
	struct resource_list		*rl;
	struct resource_list_entry	*rle;
	bool				 isdefault;
	bool				 passthrough;

	passthrough = (device_get_parent(child) != dev);
	isdefault = RMAN_IS_DEFAULT_RANGE(start, end);

	/* the default RID must always be the first device port/region. */
	if (!passthrough && *rid == 0) {
		int rid0 = bhnd_get_port_rid(child, BHND_PORT_DEVICE, 0, 0);
		KASSERT(*rid == rid0,
		    ("rid 0 does not map to the first device port (%d)", rid0));
	}

	/* Determine locally-known defaults before delegating the request. */
	if (!passthrough && isdefault) {
		/* fetch resource list from child's bus */
		rl = BUS_GET_RESOURCE_LIST(dev, child);
		if (rl == NULL)
			return (NULL); /* no resource list */

		/* look for matching type/rid pair */
		rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child),
		    type, *rid);
		if (rle == NULL)
			return (NULL);

		/* set default values */
		start = rle->start;
		end = rle->end;
		count = ulmax(count, rle->count);
	}

	/* Try to delegate to our parent. */
	if (device_get_parent(dev) != NULL) {
		return (BHND_BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
		    type, rid, start, end, count, flags));
	}

	/* If this is the bus root, use a real bus-allocated resource */
	r = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT);
	if (r == NULL)
		return NULL;

	/* Allocate the bus resource, marking it as 'direct' (not requiring
	 * any bus window remapping to perform I/O) */
	r->direct = true;
	r->res = BUS_ALLOC_RESOURCE(dev, child, type, rid, start, end,
	    count, flags);

	if (r->res == NULL) {
		free(r, M_BHND);
		return NULL;
	}

	return (r);
}
Exemple #22
0
static int
acpi_sysres_attach(device_t dev)
{
    device_t bus;
    struct resource_list_entry *bus_rle, *dev_rle;
    struct resource_list *bus_rl, *dev_rl;
    int done, type;
    u_long start, end, count;

    /*
     * Loop through all current resources to see if the new one overlaps
     * any existing ones.  If so, grow the old one up and/or down
     * accordingly.  Discard any that are wholly contained in the old.  If
     * the resource is unique, add it to the parent.  It will later go into
     * the rman pool.
     */
    bus = device_get_parent(dev);
    dev_rl = BUS_GET_RESOURCE_LIST(bus, dev);
    bus_rl = BUS_GET_RESOURCE_LIST(device_get_parent(bus), bus);
    STAILQ_FOREACH(dev_rle, dev_rl, link) {
	if (dev_rle->type != SYS_RES_IOPORT && dev_rle->type != SYS_RES_MEMORY)
	    continue;

	start = dev_rle->start;
	end = dev_rle->end;
	count = dev_rle->count;
	type = dev_rle->type;
	done = FALSE;

	STAILQ_FOREACH(bus_rle, bus_rl, link) {
	    if (bus_rle->type != type)
		continue;

	    /* New resource wholly contained in old, discard. */
	    if (start >= bus_rle->start && end <= bus_rle->end)
		break;

	    /* New tail overlaps old head, grow existing resource downward. */
	    if (start < bus_rle->start && end >= bus_rle->start) {
		bus_rle->count += bus_rle->start - start;
		bus_rle->start = start;
		done = TRUE;
	    }

	    /* New head overlaps old tail, grow existing resource upward. */
	    if (start <= bus_rle->end && end > bus_rle->end) {
		bus_rle->count += end - bus_rle->end;
		bus_rle->end = end;
		done = TRUE;
	    }

	    /* If we adjusted the old resource, we're finished. */
	    if (done)
		break;
	}

	/* If we didn't merge with anything, add this resource. */
	if (bus_rle == NULL)
	    bus_set_resource(bus, type, acpi_sysres_rid++, start, count);
    }

    /* After merging/moving resources to the parent, free the list. */
    resource_list_free(dev_rl);

    return (0);
}
Exemple #23
0
static int
sbus_attach(device_t dev)
{
    struct sbus_softc *sc;
    struct sbus_devinfo *sdi;
    struct sbus_icarg *sica;
    struct sbus_ranges *range;
    struct resource *res;
    struct resource_list *rl;
    device_t cdev;
    bus_addr_t intrclr, intrmap, phys;
    bus_size_t size;
    u_long vec;
    phandle_t child, node;
    uint32_t prop;
    int i, j;

    sc = device_get_softc(dev);
    sc->sc_dev = dev;
    node = ofw_bus_get_node(dev);

    i = 0;
    sc->sc_sysio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
                       RF_ACTIVE);
    if (sc->sc_sysio_res == NULL)
        panic("%s: cannot allocate device memory", __func__);

    if (OF_getprop(node, "interrupts", &prop, sizeof(prop)) == -1)
        panic("%s: cannot get IGN", __func__);
    sc->sc_ign = INTIGN(prop);

    /*
     * Record clock frequency for synchronous SCSI.
     * IS THIS THE CORRECT DEFAULT??
     */
    if (OF_getprop(node, "clock-frequency", &prop, sizeof(prop)) == -1)
        prop = 25000000;
    sc->sc_clockfreq = prop;
    prop /= 1000;
    device_printf(dev, "clock %d.%03d MHz\n", prop / 1000, prop % 1000);

    /*
     * Collect address translations from the OBP.
     */
    if ((sc->sc_nrange = OF_getprop_alloc(node, "ranges",
                                          sizeof(*range), (void **)&range)) == -1) {
        panic("%s: error getting ranges property", __func__);
    }
    sc->sc_rd = malloc(sizeof(*sc->sc_rd) * sc->sc_nrange, M_DEVBUF,
                       M_NOWAIT | M_ZERO);
    if (sc->sc_rd == NULL)
        panic("%s: cannot allocate rmans", __func__);
    /*
     * Preallocate all space that the SBus bridge decodes, so that nothing
     * else gets in the way; set up rmans etc.
     */
    rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
    for (i = 0; i < sc->sc_nrange; i++) {
        phys = range[i].poffset | ((bus_addr_t)range[i].pspace << 32);
        size = range[i].size;
        sc->sc_rd[i].rd_slot = range[i].cspace;
        sc->sc_rd[i].rd_coffset = range[i].coffset;
        sc->sc_rd[i].rd_cend = sc->sc_rd[i].rd_coffset + size;
        j = resource_list_add_next(rl, SYS_RES_MEMORY, phys,
                                   phys + size - 1, size);
        if ((res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &j,
                                          RF_ACTIVE)) == NULL)
            panic("%s: cannot allocate decoded range", __func__);
        sc->sc_rd[i].rd_bushandle = rman_get_bushandle(res);
        sc->sc_rd[i].rd_rman.rm_type = RMAN_ARRAY;
        sc->sc_rd[i].rd_rman.rm_descr = "SBus Device Memory";
        if (rman_init(&sc->sc_rd[i].rd_rman) != 0 ||
                rman_manage_region(&sc->sc_rd[i].rd_rman, 0, size) != 0)
            panic("%s: failed to set up memory rman", __func__);
        sc->sc_rd[i].rd_poffset = phys;
        sc->sc_rd[i].rd_pend = phys + size;
        sc->sc_rd[i].rd_res = res;
    }
    free(range, M_OFWPROP);

    /*
     * Get the SBus burst transfer size if burst transfers are supported.
     */
    if (OF_getprop(node, "up-burst-sizes", &sc->sc_burst,
                   sizeof(sc->sc_burst)) == -1 || sc->sc_burst == 0)
        sc->sc_burst =
            (SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF;

    /* initalise the IOMMU */

    /* punch in our copies */
    sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(SBUS_IOMMU_BITS);
    sc->sc_is.is_bustag = rman_get_bustag(sc->sc_sysio_res);
    sc->sc_is.is_bushandle = rman_get_bushandle(sc->sc_sysio_res);
    sc->sc_is.is_iommu = SBR_IOMMU;
    sc->sc_is.is_dtag = SBR_IOMMU_TLB_TAG_DIAG;
    sc->sc_is.is_ddram = SBR_IOMMU_TLB_DATA_DIAG;
    sc->sc_is.is_dqueue = SBR_IOMMU_QUEUE_DIAG;
    sc->sc_is.is_dva = SBR_IOMMU_SVADIAG;
    sc->sc_is.is_dtcmp = 0;
    sc->sc_is.is_sb[0] = SBR_STRBUF;
    sc->sc_is.is_sb[1] = 0;

    /*
     * Note: the SBus IOMMU ignores the high bits of an address, so a NULL
     * DMA pointer will be translated by the first page of the IOTSB.
     * To detect bugs we'll allocate and ignore the first entry.
     */
    iommu_init(device_get_nameunit(dev), &sc->sc_is, 3, -1, 1);

    /* Create the DMA tag. */
    if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0,
                           sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr,
                           0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_cdmatag) != 0)
        panic("%s: bus_dma_tag_create failed", __func__);
    /* Customize the tag. */
    sc->sc_cdmatag->dt_cookie = &sc->sc_is;
    sc->sc_cdmatag->dt_mt = &iommu_dma_methods;

    /*
     * Hunt through all the interrupt mapping regs and register our
     * interrupt controller for the corresponding interrupt vectors.
     * We do this early in order to be able to catch stray interrupts.
     */
    for (i = 0; i <= SBUS_MAX_INO; i++) {
        if (sbus_find_intrmap(sc, i, &intrmap, &intrclr) == 0)
            continue;
        sica = malloc(sizeof(*sica), M_DEVBUF, M_NOWAIT);
        if (sica == NULL)
            panic("%s: could not allocate interrupt controller "
                  "argument", __func__);
        sica->sica_sc = sc;
        sica->sica_map = intrmap;
        sica->sica_clr = intrclr;
#ifdef SBUS_DEBUG
        device_printf(dev,
                      "intr map (INO %d, %s) %#lx: %#lx, clr: %#lx\n",
                      i, (i & INTMAP_OBIO_MASK) == 0 ? "SBus slot" : "OBIO",
                      (u_long)intrmap, (u_long)SYSIO_READ8(sc, intrmap),
                      (u_long)intrclr);
#endif
        j = intr_controller_register(INTMAP_VEC(sc->sc_ign, i),
                                     &sbus_ic, sica);
        if (j != 0)
            device_printf(dev, "could not register interrupt "
                          "controller for INO %d (%d)\n", i, j);
    }

    /* Enable the over-temperature and power-fail interrupts. */
    i = 4;
    sc->sc_ot_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
                                            RF_ACTIVE);
    if (sc->sc_ot_ires == NULL ||
            INTIGN(vec = rman_get_start(sc->sc_ot_ires)) != sc->sc_ign ||
            INTVEC(SYSIO_READ8(sc, SBR_THERM_INT_MAP)) != vec ||
            intr_vectors[vec].iv_ic != &sbus_ic ||
            bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC | INTR_BRIDGE,
                           NULL, sbus_overtemp, sc, &sc->sc_ot_ihand) != 0)
        panic("%s: failed to set up temperature interrupt", __func__);
    i = 3;
    sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
                                            RF_ACTIVE);
    if (sc->sc_pf_ires == NULL ||
            INTIGN(vec = rman_get_start(sc->sc_pf_ires)) != sc->sc_ign ||
            INTVEC(SYSIO_READ8(sc, SBR_POWER_INT_MAP)) != vec ||
            intr_vectors[vec].iv_ic != &sbus_ic ||
            bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC | INTR_BRIDGE,
                           NULL, sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0)
        panic("%s: failed to set up power fail interrupt", __func__);

    /* Initialize the counter-timer. */
    sparc64_counter_init(device_get_nameunit(dev),
                         rman_get_bustag(sc->sc_sysio_res),
                         rman_get_bushandle(sc->sc_sysio_res), SBR_TC0);

    /*
     * Loop through ROM children, fixing any relative addresses
     * and then configuring each device.
     */
    for (child = OF_child(node); child != 0; child = OF_peer(child)) {
        if ((sdi = sbus_setup_dinfo(dev, sc, child)) == NULL)
            continue;
        /*
         * For devices where there are variants that are actually
         * split into two SBus devices (as opposed to the first
         * half of the device being a SBus device and the second
         * half hanging off of the first one) like 'auxio' and
         * 'SUNW,fdtwo' or 'dma' and 'esp' probe the SBus device
         * which is a prerequisite to the driver attaching to the
         * second one with a lower order. Saves us from dealing
         * with different probe orders in the respective device
         * drivers which generally is more hackish.
         */
        cdev = device_add_child_ordered(dev, (OF_child(child) == 0 &&
                                              sbus_inlist(sdi->sdi_obdinfo.obd_name, sbus_order_first)) ?
                                        SBUS_ORDER_FIRST : SBUS_ORDER_NORMAL, NULL, -1);
        if (cdev == NULL) {
            device_printf(dev,
                          "<%s>: device_add_child_ordered failed\n",
                          sdi->sdi_obdinfo.obd_name);
            sbus_destroy_dinfo(sdi);
            continue;
        }
        device_set_ivars(cdev, sdi);
    }
    return (bus_generic_attach(dev));
}
Exemple #24
0
/*
 * All resources are assigned directly to us by acpi,
 * so 'child' is bypassed here.
 */
static struct resource_list *
acpi_cpu_get_rlist(device_t dev, device_t child __unused)
{
    return BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
}
Exemple #25
0
static struct resource *
sbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
                    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
    struct sbus_softc *sc;
    struct rman *rm;
    struct resource *rv;
    struct resource_list *rl;
    struct resource_list_entry *rle;
    device_t schild;
    bus_addr_t toffs;
    bus_size_t tend;
    int i, slot;
    int isdefault, passthrough;

    isdefault = RMAN_IS_DEFAULT_RANGE(start, end);
    passthrough = (device_get_parent(child) != bus);
    rle = NULL;
    sc = device_get_softc(bus);
    rl = BUS_GET_RESOURCE_LIST(bus, child);
    switch (type) {
    case SYS_RES_IRQ:
        return (resource_list_alloc(rl, bus, child, type, rid, start,
                                    end, count, flags));
    case SYS_RES_MEMORY:
        if (!passthrough) {
            rle = resource_list_find(rl, type, *rid);
            if (rle == NULL)
                return (NULL);
            if (rle->res != NULL)
                panic("%s: resource entry is busy", __func__);
            if (isdefault) {
                start = rle->start;
                count = ulmax(count, rle->count);
                end = ulmax(rle->end, start + count - 1);
            }
        }
        rm = NULL;
        schild = child;
        while (device_get_parent(schild) != bus)
            schild = device_get_parent(schild);
        slot = sbus_get_slot(schild);
        for (i = 0; i < sc->sc_nrange; i++) {
            if (sc->sc_rd[i].rd_slot != slot ||
                    start < sc->sc_rd[i].rd_coffset ||
                    start > sc->sc_rd[i].rd_cend)
                continue;
            /* Disallow cross-range allocations. */
            if (end > sc->sc_rd[i].rd_cend)
                return (NULL);
            /* We've found the connection to the parent bus */
            toffs = start - sc->sc_rd[i].rd_coffset;
            tend = end - sc->sc_rd[i].rd_coffset;
            rm = &sc->sc_rd[i].rd_rman;
            break;
        }
        if (rm == NULL)
            return (NULL);

        rv = rman_reserve_resource(rm, toffs, tend, count, flags &
                                   ~RF_ACTIVE, child);
        if (rv == NULL)
            return (NULL);
        rman_set_rid(rv, *rid);

        if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child,
                type, *rid, rv)) {
            rman_release_resource(rv);
            return (NULL);
        }
        if (!passthrough)
            rle->res = rv;
        return (rv);
    default:
        return (NULL);
    }
}
Exemple #26
0
struct resource *
isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
	/*
	 * Consider adding a resource definition.
	 */
	int passthrough = (device_get_parent(child) != bus);
	int isdefault = (start == 0UL && end == ~0UL);
	struct resource_list *rl;
	struct resource_list_entry *rle;
	u_long base, limit;

	rl = BUS_GET_RESOURCE_LIST(bus, child);
	if (!passthrough && !isdefault) {
		rle = resource_list_find(rl, type, *rid);
		if (!rle) {
			if (*rid < 0)
				return (NULL);
			switch (type) {
			case SYS_RES_IRQ:
				if (*rid >= ISA_NIRQ)
					return (NULL);
				break;
			case SYS_RES_DRQ:
				if (*rid >= ISA_NDRQ)
					return (NULL);
				break;
			case SYS_RES_MEMORY:
				if (*rid >= ISA_NMEM)
					return (NULL);
				break;
			case SYS_RES_IOPORT:
				if (*rid >= ISA_NPORT)
					return (NULL);
				break;
			default:
				return (NULL);
			}
			resource_list_add(rl, type, *rid, start, end, count);
		}
	}

	/*
	 * Sanity check if the resource in the respective entry is fully
	 * mapped and specified and its type allocable. A driver could
	 * have added an out of range resource on its own.
	 */
	if (!passthrough) {
		if ((rle = resource_list_find(rl, type, *rid)) == NULL)
			return (NULL);
		base = limit = 0;
		switch (type) {
		case SYS_RES_MEMORY:
			base = isa_mem_base;
			limit = base + isa_mem_limit;
			break;
		case SYS_RES_IOPORT:
			base = isa_io_base;
			limit = base + isa_io_limit;
			break;
		case SYS_RES_IRQ:
			if (rle->start != rle->end || rle->start <= 7)
				return (NULL);
			break;
		case SYS_RES_DRQ:
			break;
		default:
			return (NULL);
		}
		if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
			if (!INRANGE(rle->start, base, limit) ||
			    !INRANGE(rle->end, base, limit))
				return (NULL);
		}
	}

	return (resource_list_alloc(rl, bus, child, type, rid, start, end,
	    count, flags));
}
Exemple #27
0
static struct resource *
nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
                     u_long start, u_long end, u_long count, u_int flags)
{
    struct nexus_softc *sc;
    struct rman *rm;
    struct resource *rv;
    struct resource_list_entry *rle;
    device_t nexus;
    int isdefault, needactivate, passthrough;

    isdefault = (start == 0UL && end == ~0UL);
    needactivate = flags & RF_ACTIVE;
    passthrough = (device_get_parent(child) != bus);
    nexus = bus;
    while (strcmp(device_get_name(device_get_parent(nexus)), "root") != 0)
        nexus = device_get_parent(nexus);
    sc = device_get_softc(nexus);
    rle = NULL;

    if (!passthrough) {
        rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child),
                                 type, *rid);
        if (rle == NULL)
            return (NULL);
        if (rle->res != NULL)
            panic("%s: resource entry is busy", __func__);
        if (isdefault) {
            start = rle->start;
            count = ulmax(count, rle->count);
            end = ulmax(rle->end, start + count - 1);
        }
    }

    switch (type) {
    case SYS_RES_IRQ:
        rm = &sc->sc_intr_rman;
        break;
    case SYS_RES_MEMORY:
        rm = &sc->sc_mem_rman;
        break;
    default:
        return (NULL);
    }

    flags &= ~RF_ACTIVE;
    rv = rman_reserve_resource(rm, start, end, count, flags, child);
    if (rv == NULL)
        return (NULL);
    rman_set_rid(rv, *rid);
    if (type == SYS_RES_MEMORY) {
        rman_set_bustag(rv, &nexus_bustag);
        rman_set_bushandle(rv, rman_get_start(rv));
    }

    if (needactivate) {
        if (bus_activate_resource(child, type, *rid, rv) != 0) {
            rman_release_resource(rv);
            return (NULL);
        }
    }

    if (!passthrough) {
        rle->res = rv;
        rle->start = rman_get_start(rv);
        rle->end = rman_get_end(rv);
        rle->count = rle->end - rle->start + 1;
    }

    return (rv);
}