예제 #1
0
/*
 * Is a resource from a child device sub-allocated from one of our
 * resource managers?
 */
static int
pcib_is_resource_managed(struct pcib_softc *sc, int type, struct resource *r)
{

	switch (type) {
	case SYS_RES_IOPORT:
		return (rman_is_region_manager(r, &sc->io.rman));
	case SYS_RES_MEMORY:
		/* Prefetchable resources may live in either memory rman. */
		if (rman_get_flags(r) & RF_PREFETCHABLE &&
		    rman_is_region_manager(r, &sc->pmem.rman))
			return (1);
		return (rman_is_region_manager(r, &sc->mem.rman));
	}
	return (0);
}
예제 #2
0
static int
ofwbus_adjust_resource(device_t bus, device_t child __unused, int type,
    struct resource *r, rman_res_t start, rman_res_t end)
{
	struct ofwbus_softc *sc;
	struct rman *rm;
	device_t ofwbus;

	ofwbus = bus;
	while (strcmp(device_get_name(device_get_parent(ofwbus)), "root") != 0)
		ofwbus = device_get_parent(ofwbus);
	sc = device_get_softc(ofwbus);
	switch (type) {
	case SYS_RES_IRQ:
		rm = &sc->sc_intr_rman;
		break;
	case SYS_RES_MEMORY:
		rm = &sc->sc_mem_rman;
		break;
	default:
		return (EINVAL);
	}
	if (rm == NULL)
		return (ENXIO);
	if (rman_is_region_manager(r, rm) == 0)
		return (EINVAL);
	return (rman_adjust_resource(r, start, end));
}
예제 #3
0
파일: ofw_pci.c 프로젝트: embedclub/freebsd
int
ofw_pci_adjust_resource(device_t bus, device_t child, int type,
                        struct resource *r, rman_res_t start, rman_res_t end)
{
    struct ofw_pci_softc *sc;
    struct rman *rm;

    sc = device_get_softc(bus);
    switch (type) {
    case SYS_RES_IRQ:
        return (bus_generic_adjust_resource(bus, child, type, r,
                                            start, end));
    case SYS_RES_MEMORY:
        rm = &sc->sc_pci_mem_rman;
        break;
    case SYS_RES_IOPORT:
        rm = &sc->sc_pci_io_rman;
        break;
    default:
        return (EINVAL);
    }
    if (rman_is_region_manager(r, rm) == 0)
        return (EINVAL);
    return (rman_adjust_resource(r, start, end));
}
예제 #4
0
static int
sbus_activate_resource(device_t bus, device_t child, int type, int rid,
                       struct resource *r)
{
    struct sbus_softc *sc;
    struct bus_space_tag *tag;
    int i;

    switch (type) {
    case SYS_RES_IRQ:
        return (bus_generic_activate_resource(bus, child, type, rid,
                                              r));
    case SYS_RES_MEMORY:
        sc = device_get_softc(bus);
        for (i = 0; i < sc->sc_nrange; i++) {
            if (rman_is_region_manager(r,
                                       &sc->sc_rd[i].rd_rman) != 0) {
                tag = sparc64_alloc_bus_tag(r, SBUS_BUS_SPACE);
                if (tag == NULL)
                    return (ENOMEM);
                rman_set_bustag(r, tag);
                rman_set_bushandle(r,
                                   sc->sc_rd[i].rd_bushandle +
                                   rman_get_start(r));
                return (rman_activate_resource(r));
            }
        }
    /* FALLTHROUGH */
    default:
        return (EINVAL);
    }
}
예제 #5
0
파일: chipc.c 프로젝트: wulf7/freebsd
static int
chipc_adjust_resource(device_t dev, device_t child, int type,
    struct resource *r, rman_res_t start, rman_res_t end)
{
	struct chipc_softc		*sc;
	struct chipc_region		*cr;
	struct rman			*rm;
	
	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_adjust_resource(dev, child, type, r, start,
		    end));
	}

	/* The range is limited to the existing region mapping */
	cr = chipc_find_region(sc, rman_get_start(r), rman_get_end(r));
	if (cr == NULL)
		return (EINVAL);
	
	if (end <= start)
		return (EINVAL);

	if (start < cr->cr_addr || end > cr->cr_end)
		return (EINVAL);

	/* Range falls within the existing region */
	return (rman_adjust_resource(r, start, end));
}
예제 #6
0
파일: chipc.c 프로젝트: wulf7/freebsd
static int
chipc_activate_bhnd_resource(device_t dev, device_t child, int type,
    int rid, struct bhnd_resource *r)
{
	struct chipc_softc	*sc;
	struct rman		*rm;
	int			 error;

	sc = device_get_softc(dev);
	
	/* Delegate non-locally managed resources to parent */
	rm = chipc_get_rman(sc, type);
	if (rm == NULL || !rman_is_region_manager(r->res, rm)) {
		return (bhnd_bus_generic_activate_resource(dev, child, type,
		    rid, r));
	}

	/* Try activating the chipc region resource */
	error = chipc_try_activate_resource(sc, child, type, rid, r->res,
	    false);
	if (error)
		return (error);

	/* Mark the child resource as direct according to the returned resource
	 * state */
	if (rman_get_flags(r->res) & RF_ACTIVE)
		r->direct = true;

	return (0);
}
예제 #7
0
static int
thunder_pem_adjust_resource(device_t dev, device_t child, int type,
    struct resource *res, rman_res_t start, rman_res_t end)
{
	struct thunder_pem_softc *sc;
	struct rman *rm;

	sc = device_get_softc(dev);
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
	if (type == PCI_RES_BUS)
		return (pci_domain_adjust_bus(sc->id, child, res, start, end));
#endif

	rm = thunder_pem_rman(sc, type);
	if (rm == NULL)
		return (bus_generic_adjust_resource(dev, child, type, res,
		    start, end));
	if (!rman_is_region_manager(res, rm))
		/*
		 * This means a child device has a memory or I/O
		 * resource not from you which shouldn't happen.
		 */
		return (EINVAL);
	return (rman_adjust_resource(res, start, end));
}
예제 #8
0
파일: chipc.c 프로젝트: wulf7/freebsd
/**
 * Default bhndb(4) implementation of BUS_DEACTIVATE_RESOURCE().
 */
static int
chipc_deactivate_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;
	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_deactivate_resource(dev, child, type, rid,
		    r));
	}

	/* Find the corresponding chipc region */
	cr = chipc_find_region(sc, rman_get_start(r), rman_get_end(r));
	if (cr == NULL)
		return (EINVAL);

	/* Mark inactive */
	if ((error = rman_deactivate_resource(r)))
		return (error);

	/* Drop associated RF_ACTIVE reference */
	chipc_release_region(sc, cr, RF_ACTIVE);

	return (0);
}
예제 #9
0
파일: ebus.c 프로젝트: AhmadTux/freebsd
static int
ebus_activate_resource(device_t bus, device_t child, int type, int rid,
    struct resource *res)
{
	struct ebus_softc *sc;
	struct ebus_rinfo *eri;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int i, rv;

	sc = device_get_softc(bus);
	if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) {
		for (i = 0; i < sc->sc_nrange; i++) {
			eri = &sc->sc_rinfo[i];
			if (rman_is_region_manager(res, &eri->eri_rman) != 0) {
				bt = rman_get_bustag(eri->eri_res);
				rv = bus_space_subregion(bt,
				    rman_get_bushandle(eri->eri_res),
				    rman_get_start(res) -
				    rman_get_start(eri->eri_res),
				    rman_get_size(res), &bh);
				if (rv != 0)
					return (rv);
				rman_set_bustag(res, bt);
				rman_set_bushandle(res, bh);
				return (rman_activate_resource(res));
			}
		}
		return (EINVAL);
	}
	return (bus_generic_activate_resource(bus, child, type, rid, res));
}
예제 #10
0
static int
ofw_pci_adjust_resource(device_t bus, device_t child, int type,
    struct resource *res, u_long start, u_long end)
{
	struct rman *rm = NULL;
	struct ofw_pci_softc *sc = device_get_softc(bus);

	KASSERT(!(rman_get_flags(res) & RF_ACTIVE),
	    ("active resources cannot be adjusted"));
	if (rman_get_flags(res) & RF_ACTIVE)
		return (EINVAL);

	switch (type) {
	case SYS_RES_MEMORY:
		rm = &sc->sc_mem_rman;
		break;
	case SYS_RES_IOPORT:
		rm = &sc->sc_io_rman;
		break;
	default:
		return (ENXIO);
	}

	if (!rman_is_region_manager(res, rm))
		return (EINVAL);

	return (rman_adjust_resource(res, start, end));
}
예제 #11
0
static int
nexus_adjust_resource(device_t bus, device_t child, int type,
    struct resource *r, u_long start, u_long end)
{
	struct rman *rm;

	rm = nexus_rman(type);
	if (rm == NULL)
		return (ENXIO);
	if (!rman_is_region_manager(r, rm))
		return (EINVAL);
	return (rman_adjust_resource(r, start, end));
}
예제 #12
0
파일: chipc.c 프로젝트: wulf7/freebsd
/**
 * Retain an RF_ACTIVE reference to the region mapping @p r, and
 * configure @p r with its subregion values.
 *
 * @param sc Driver instance state.
 * @param child Requesting child device.
 * @param type resource type of @p r.
 * @param rid resource id of @p r
 * @param r resource to be activated.
 * @param req_direct If true, failure to allocate a direct bhnd resource
 * will be treated as an error. If false, the resource will not be marked
 * as RF_ACTIVE if bhnd direct resource allocation fails.
 */
static int
chipc_try_activate_resource(struct chipc_softc *sc, device_t child, int type,
    int rid, struct resource *r, bool req_direct)
{
	struct rman		*rm;
	struct chipc_region	*cr;
	bhnd_size_t		 cr_offset;
	rman_res_t		 r_start, r_end, r_size;
	int			 error;

	rm = chipc_get_rman(sc, type);
	if (rm == NULL || !rman_is_region_manager(r, rm))
		return (EINVAL);

	r_start = rman_get_start(r);
	r_end = rman_get_end(r);
	r_size = rman_get_size(r);

	/* Find the corresponding chipc region */
	cr = chipc_find_region(sc, r_start, r_end);
	if (cr == NULL)
		return (EINVAL);
	
	/* Calculate subregion offset within the chipc region */
	cr_offset = r_start - cr->cr_addr;

	/* Retain (and activate, if necessary) the chipc region */
	if ((error = chipc_retain_region(sc, cr, RF_ACTIVE)))
		return (error);

	/* Configure child resource with its subregion values. */
	if (cr->cr_res->direct) {
		error = chipc_init_child_resource(r, cr->cr_res->res,
		    cr_offset, r_size);
		if (error)
			goto cleanup;

		/* Mark active */
		if ((error = rman_activate_resource(r)))
			goto cleanup;
	} else if (req_direct) {
		error = ENOMEM;
		goto cleanup;
	}

	return (0);

cleanup:
	chipc_release_region(sc, cr, RF_ACTIVE);
	return (error);
}
예제 #13
0
static int
cbb_pci_adjust_resource(device_t bus, device_t child, int type,
    struct resource *r, rman_res_t start, rman_res_t end)
{
	struct cbb_softc *sc;

	sc = device_get_softc(bus);
	if (type == PCI_RES_BUS) {
		if (!rman_is_region_manager(r, &sc->bus.rman))
			return (EINVAL);
		return (rman_adjust_resource(r, start, end));
	}
	return (bus_generic_adjust_resource(bus, child, type, r, start, end));
}
예제 #14
0
static int
sbus_adjust_resource(device_t bus, device_t child, int type,
                     struct resource *r, rman_res_t start, rman_res_t end)
{
    struct sbus_softc *sc;
    int i;

    if (type == SYS_RES_MEMORY) {
        sc = device_get_softc(bus);
        for (i = 0; i < sc->sc_nrange; i++)
            if (rman_is_region_manager(r,
                                       &sc->sc_rd[i].rd_rman) != 0)
                return (rman_adjust_resource(r, start, end));
        return (EINVAL);
    }
    return (bus_generic_adjust_resource(bus, child, type, r, start, end));
}
예제 #15
0
파일: chipc.c 프로젝트: wulf7/freebsd
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);
}
예제 #16
0
파일: chipc.c 프로젝트: wulf7/freebsd
static int
chipc_activate_resource(device_t dev, device_t child, int type, int rid,
    struct resource *r)
{
	struct chipc_softc	*sc;
	struct rman		*rm;

	sc = device_get_softc(dev);

	/* Delegate non-locally managed resources to parent */
	rm = chipc_get_rman(sc, type);
	if (rm == NULL || !rman_is_region_manager(r, rm)) {
		return (bus_generic_activate_resource(dev, child, type, rid,
		    r));
	}

	/* Try activating the chipc region-based resource */
	return (chipc_try_activate_resource(sc, child, type, rid, r, true));
}
예제 #17
0
static int
cbb_pci_release_resource(device_t bus, device_t child, int type, int rid,
    struct resource *r)
{
	struct cbb_softc *sc;
	int error;

	sc = device_get_softc(bus);
	if (type == PCI_RES_BUS) {
		if (!rman_is_region_manager(r, &sc->bus.rman))
			return (EINVAL);
		if (rman_get_flags(r) & RF_ACTIVE) {
			error = bus_deactivate_resource(child, type, rid, r);
			if (error)
				return (error);
		}
		return (rman_release_resource(r));
	}
	return (cbb_release_resource(bus, child, type, rid, r));
}
예제 #18
0
static int
thunder_pem_adjust_resource(device_t dev, device_t child, int type,
    struct resource *res, rman_res_t start, rman_res_t end)
{
	struct thunder_pem_softc *sc;
	struct rman *rm;

	sc = device_get_softc(dev);

	rm = thunder_pem_rman(sc, type);
	if (rm == NULL)
		return (bus_generic_adjust_resource(dev, child, type, res,
		    start, end));
	if (!rman_is_region_manager(res, rm))
		/*
		 * This means a child device has a memory or I/O
		 * resource not from you which shouldn't happen.
		 */
		return (EINVAL);
	return (rman_adjust_resource(res, start, end));
}
예제 #19
0
int
pci_host_generic_core_release_resource(device_t dev, device_t child, int type,
    int rid, struct resource *res)
{
	struct generic_pcie_core_softc *sc;
	struct rman *rm;

	sc = device_get_softc(dev);

#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
	if (type == PCI_RES_BUS) {
		return (pci_domain_release_bus(sc->ecam, child, rid, res));
	}
#endif

	rm = generic_pcie_rman(sc, type);
	if (rm != NULL) {
		KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
		rman_release_resource(res);
	}

	return (bus_generic_release_resource(dev, child, type, rid, res));
}