Exemple #1
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));
}
Exemple #2
0
int
pci_vf_release_mem_resource(device_t dev, device_t child, int rid,
    struct resource *r)
{
	struct pci_devinfo *dinfo;
	struct resource_list_entry *rle;
	int error;

	dinfo = device_get_ivars(child);

	if (rman_get_flags(r) & RF_ACTIVE) {
		error = bus_deactivate_resource(child, SYS_RES_MEMORY, rid, r);
		if (error != 0)
			return (error);
	}

	rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, rid);
	if (rle != NULL) {
		rle->res = NULL;
		resource_list_delete(&dinfo->resources, SYS_RES_MEMORY,
		    rid);
	}

	return (rman_release_resource(r));
}
Exemple #3
0
static int
nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r,
                 int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
                 void **cookiep)
{
    int error;

    if (r == NULL)
        panic("%s: NULL interrupt resource!", __func__);

    if ((rman_get_flags(r) & RF_SHAREABLE) == 0)
        flags |= INTR_EXCL;

    /* We depend here on rman_activate_resource() being idempotent. */
    error = rman_activate_resource(r);
    if (error)
        return (error);

    error = inthand_add(device_get_nameunit(child), rman_get_start(r),
                        filt, intr, arg, flags, cookiep);

    /*
     * XXX in case of the AFB/FFB interrupt and a Psycho, Sabre or U2S
     * bridge enable the interrupt in the respective bridge.
     */

    return (error);
}
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_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));
}
static int
ocpbus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
    driver_filter_t *filter, driver_intr_t *ihand, void *arg, void **cookiep)
{
	int error;

	if (res == NULL)
		panic("ocpbus_setup_intr: NULL irq resource!");

	*cookiep = 0;
	if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	/*
	 * We depend here on rman_activate_resource() being idempotent.
	 */
	error = rman_activate_resource(res);
	if (error)
		return (error);

	error = powerpc_setup_intr(device_get_nameunit(child),
	    rman_get_start(res), filter, ihand, arg, flags, cookiep);

	return (error);
}
Exemple #6
0
static int
nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r,
    int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
    void **cookiep)
{
	int error, domain;

	if (r == NULL)
		panic("%s: NULL interrupt resource!", __func__);

	if (cookiep != NULL)
		*cookiep = NULL;
	if ((rman_get_flags(r) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	/* We depend here on rman_activate_resource() being idempotent. */
	error = rman_activate_resource(r);
	if (error)
		return (error);

	if (bus_get_domain(child, &domain) != 0) {
		if(bootverbose)
			device_printf(child, "no domain found\n");
		domain = 0;
	}
	error = powerpc_setup_intr(device_get_nameunit(child),
	    rman_get_start(r), filt, intr, arg, flags, cookiep, domain);

	return (error);
}
Exemple #7
0
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);
}
Exemple #8
0
/*
 * Currently this uses the really grody interface from kern/kern_intr.c
 * (which really doesn't belong in kern/anything.c).  Eventually, all of
 * the code in kern_intr.c and machdep_intr.c should get moved here, since
 * this is going to be the official interface.
 */
static int
nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
		 int flags, driver_filter_t filter, void (*ihand)(void *),
		 void *arg, void **cookiep)
{
	int		error;

	/* somebody tried to setup an irq that failed to allocate! */
	if (irq == NULL)
		panic("nexus_setup_intr: NULL irq resource!");

	*cookiep = 0;
	if ((rman_get_flags(irq) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	/*
	 * We depend here on rman_activate_resource() being idempotent.
	 */
	error = rman_activate_resource(irq);
	if (error)
		return (error);

	error = intr_add_handler(device_get_nameunit(child),
	    rman_get_start(irq), filter, ihand, arg, flags, cookiep);

	return (error);
}
Exemple #9
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 #10
0
static int
vnex_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
                driver_filter_t *filt,driver_intr_t *intr, void *arg, void **cookiep)
{

    uint64_t reg, nreg;
    uint64_t ihdl, cfg;
    uint64_t ino, nino;
    int error, cpuid;

    if (res == NULL)
        panic("%s: NULL interrupt resource!", __func__);

    if ((error = bus_get_resource(dev, SYS_RES_MEMORY, 0, &reg, &nreg)))
        goto fail;

    if ((error = bus_get_resource(child, SYS_RES_IRQ, 0, &ino, &nino)))
        goto fail;

    cfg = SUN4V_REG_SPEC2CFG_HDL(reg);

    if (hv_intr_devino_to_sysino(cfg, (uint32_t)ino, &ihdl) != H_EOK) {
        error = ENXIO;
        goto fail;
    }

    cpuid = 0;

    if (hv_intr_settarget(ihdl, cpuid) != H_EOK) {
        error = ENXIO;
        goto fail;
    }

    if (hv_intr_setstate(ihdl, HV_INTR_IDLE_STATE) != H_EOK) {
        error = ENXIO;
        goto fail;
    }

    if (hv_intr_setenabled(ihdl, HV_INTR_ENABLED) != H_EOK) {
        error = ENXIO;
        goto fail;
    }

    if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
        flags |= INTR_EXCL;

    /* We depend here on rman_activate_resource() being idempotent. */
    if ((error = rman_activate_resource(res)))
        goto fail;

    error = inthand_add(device_get_nameunit(child), ihdl,
                        filt, intr, arg, flags, cookiep);

    printf("inthandler added\n");
fail:

    return (error);
}
Exemple #11
0
static int
nexus_release_resource(device_t bus, device_t child, int type, int rid,
		       struct resource *r)
{
	if (rman_get_flags(r) & RF_ACTIVE) {
		int error = bus_deactivate_resource(child, type, rid, r);
		if (error)
			return error;
	}
	return (rman_release_resource(r));
}
Exemple #12
0
static int
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
    driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
{

	if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	arm_setup_irqhandler(device_get_nameunit(child), 
	    filt, intr, arg, rman_get_start(res), flags, cookiep);
	return (0);
}
Exemple #13
0
static int
ofwbus_release_resource(device_t bus __unused, device_t child, int type,
    int rid, struct resource *r)
{
	int error;

	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 #14
0
static int
lbc_release_resource(device_t dev, device_t child, int type, int rid,
    struct resource *res)
{
	int err;

	if (rman_get_flags(res) & RF_ACTIVE) {
		err = bus_deactivate_resource(child, type, rid, res);
		if (err)
			return (err);
	}

	return (rman_release_resource(res));
}
Exemple #15
0
static int
ofw_pci_release_resource(device_t bus, device_t child, int type, int rid,
    struct resource *res)
{

	if (rman_get_flags(res) & RF_ACTIVE) {
		int error;

		error = bus_deactivate_resource(child, type, rid, res);
		if (error != 0)
			return (error);
	}

	return (rman_release_resource(res));
}
Exemple #16
0
static int
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
    driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
{
	int irq;

	if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) {
		arm_setup_irqhandler(device_get_nameunit(child),
		    filt, intr, arg, irq, flags, cookiep);
		arm_unmask_irq(irq);
	}
	return (0);
}
Exemple #17
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);
}
Exemple #18
0
static int
nexus_release_resource(device_t bus, device_t child, int type, int rid,
		       struct resource *r)
{
	if (rman_get_flags(r) & RF_ACTIVE) {
		int error = bus_deactivate_resource(child, type, rid, r);
		if (error)
			return error;
	}
#ifdef PC98
	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
		i386_bus_space_handle_free(r->r_bustag, r->r_bushandle,
					   r->r_bushandle->bsh_sz);
	}
#endif
	return (rman_release_resource(r));
}
Exemple #19
0
static int
zbpci_release_resource(device_t bus, device_t child, int type, int rid,
		       struct resource *r)
{
	int error;

	if (type != SYS_RES_IOPORT)
		return (bus_generic_release_resource(bus, child, type, rid, r));

	if (rman_get_flags(r) & RF_ACTIVE) {
		error = bus_deactivate_resource(child, type, rid, r);
		if (error)
			return (error);
	}

	return (rman_release_resource(r));
}
static int
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
    driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
{
	int error;

	if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	/* We depend here on rman_activate_resource() being idempotent. */
	error = rman_activate_resource(res);
	if (error)
		return (error);

	error = intr_setup_irq(child, res, filt, intr, arg, flags, cookiep);

	return (error);
}
Exemple #21
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 #22
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 #23
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));
}
Exemple #24
0
int
puc_bus_release_resource(device_t dev, device_t child, int type, int rid,
    struct resource *res)
{
	struct puc_port *port;
	device_t originator;

	/* Get our immediate child. */
	originator = child;
	while (child != NULL && device_get_parent(child) != dev)
		child = device_get_parent(child);
	if (child == NULL)
		return (EINVAL);

	port = device_get_ivars(child);
	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));

	if (rid != 0 || res == NULL)
		return (EINVAL);

	if (type == port->p_bar->b_type) {
		if (res != port->p_rres)
			return (EINVAL);
	} else if (type == SYS_RES_IRQ) {
		if (res != port->p_ires)
			return (EINVAL);
		if (port->p_hasintr)
			return (EBUSY);
	} else
		return (EINVAL);

	if (rman_get_device(res) != originator)
		return (ENXIO);
	if (rman_get_flags(res) & RF_ACTIVE)
		rman_deactivate_resource(res);
	rman_set_device(res, NULL);
	return (0);
}
Exemple #25
0
static int
nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r,
    int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
    void **cookiep)
{
	int error;

	if (r == NULL)
		panic("%s: NULL interrupt resource!", __func__);

	if ((rman_get_flags(r) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	/* We depend here on rman_activate_resource() being idempotent. */
	error = rman_activate_resource(r);
	if (error)
		return (error);

	error = powerpc_setup_intr(device_get_nameunit(child),
	    rman_get_start(r), filt, intr, arg, flags, cookiep);

	return (error);
}
Exemple #26
0
static int
nexus_setup_intr(device_t bus, device_t child, struct resource *res, int flags,
    driver_filter_t *ifilt, driver_intr_t *ihand, void *arg, void **cookiep)
{
	int error;

	*cookiep = NULL;

	/* somebody tried to setup an irq that failed to allocate! */
	if (res == NULL)
		return (EINVAL);

	if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	/* We depend on rman_activate_resource() being idempotent. */
	error = rman_activate_resource(res);
	if (error)
		return (error);

	error = powerpc_setup_intr(device_get_nameunit(child),
	    rman_get_start(res), ifilt, ihand, arg, flags, cookiep);
	return (error);
}
/**
 * Initialize the full bridge configuration.
 * 
 * This is called during the DEVICE_ATTACH() process by the bridged bhndb(4)
 * bus, prior to probe/attachment of child cores.
 * 
 * At this point, we can introspect the enumerated cores, find our host
 * bridge device, and apply any bridge-level hardware workarounds required
 * for proper operation of the bridged device cores.
 */
static int
bhndb_pci_init_full_config(device_t dev, device_t child,
    const struct bhndb_hw_priority *prio_table)
{
	struct bhnd_core_info		 core;
	const struct bhndb_pci_id	*id;
	struct bhndb_pci_softc		*sc;
	struct bhndb_region		*pcir;
	bhnd_addr_t			 pcir_addr;
	bhnd_size_t			 pcir_size;
	int				 error;

	sc = device_get_softc(dev);

	/* Let bhndb perform full discovery and initialization of the
	 * available register windows and bridge resources. */
	if ((error = bhndb_generic_init_full_config(dev, child, prio_table)))
		return (error);

	/* 
	 * Identify our PCI bridge core, its register family, and any
	 * applicable hardware quirks.
	 */
	KASSERT(sc->bhndb.hostb_dev,
	    ("missing hostb device\n"));

	core = bhnd_get_core_info(sc->bhndb.hostb_dev);
	id = bhndb_pci_find_core_id(&core);
	if (id == NULL) {
		device_printf(dev, "%s %s hostb core is not recognized\n",
		    bhnd_vendor_name(core.vendor), bhnd_core_name(&core));
	}

	sc->regfmt = id->regfmt;

	/* Now that we've identified the PCI bridge core, we can determine the
	 * full set of device quirks */
	sc->quirks = bhndb_pci_discover_quirks(sc, id);

	/*
	 * Determine and save a reference to the bhndb resource and offset
	 * at which the bridge core's device registers are mapped.
	 * 
	 * All known bhnd(4) hardware provides a fixed static mapping of
	 * the PCI core's registers. If this changes in the future -- which
	 * is unlikely -- this driver will need to be adjusted to use
	 * dynamic register windows.
	 */

	/* Find base address and size of the PCI core's register block. */
	error = bhnd_get_region_addr(sc->bhndb.hostb_dev, BHND_PORT_DEVICE, 0,
	    0, &pcir_addr, &pcir_size);
	if (error) {
		device_printf(dev,
		    "failed to locate PCI core registers\n");
		return (error);
	}

	/* Find the bhndb_region that statically maps this block */
	pcir = bhndb_find_resource_region(sc->bhndb.bus_res, pcir_addr,
	    pcir_size);
	if (pcir == NULL || pcir->static_regwin == NULL) {
		device_printf(dev,
		    "missing static PCI core register window\n");
		return (ENXIO);
	}

	/* Save borrowed reference to the mapped PCI core registers */
	sc->mem_off = pcir->static_regwin->win_offset;
	sc->mem_res = bhndb_find_regwin_resource(sc->bhndb.bus_res,
	    pcir->static_regwin);
	if (sc->mem_res == NULL || !(rman_get_flags(sc->mem_res) & RF_ACTIVE)) {
		device_printf(dev,
		    "no active resource maps the PCI core register window\n");
		return (ENXIO);
	}

	/* Configure a direct bhnd_resource wrapper that we can pass to
	 * bhnd_resource APIs */
	sc->bhnd_mem_res = (struct bhnd_resource) {
		.res = sc->mem_res,
		.direct = true
	};

	/*
	 * Attach MMIO device (if this is a PCIe device), which is used for
	 * access to the PCIe SerDes required by the quirk workarounds.
	 */
	if (sc->pci_devclass == BHND_DEVCLASS_PCIE) {
		sc->mdio = device_add_child(dev, 
		    devclass_get_name(bhnd_mdio_pci_devclass), 0);
		if (sc->mdio == NULL)
			return (ENXIO);

		if ((error = device_probe_and_attach(sc->mdio))) {
			device_printf(dev, "failed to attach MDIO device\n");
			return (error);
		}
	}

	/* Apply any early one-time quirk workarounds */
	if ((error = bhndb_pci_wars_early_once(sc)))
		return (error);

	/* Apply attach-time quirk workarounds, required before the bridged
	 * bhnd(4) bus itself performs a full attach(). */
	if ((error = bhndb_pci_wars_hwup(sc)))
		return (error);

	return (0);
}

/**
 * Apply any hardware workarounds that must be executed prior to attempting
 * register access on the bridged chipset.
 * 
 * This must be called very early in attach() or resume(), after the basic
 * set of applicable device quirks has been determined.
 */
static int
bhndb_pci_wars_register_access(struct bhndb_pci_softc *sc)
{
	int error;

	if (BHNDB_PCI_QUIRK(sc, EXT_CLOCK_GATING)) {
		if ((error = bhndb_enable_pci_clocks(sc))) {
			device_printf(sc->dev, "failed to enable clocks\n");
			return (error);
		}
	}

	return (0);
}
Exemple #28
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);
}
Exemple #29
0
static int
apb_setup_intr(device_t bus, device_t child, struct resource *ires,
		int flags, driver_filter_t *filt, driver_intr_t *handler,
		void *arg, void **cookiep)
{
	struct apb_softc *sc = device_get_softc(bus);
	int error;
	int irq;
#ifndef INTRNG
	struct intr_event *event;
#endif

#ifdef INTRNG
	struct intr_irqsrc *isrc;
	const char *name;
	
	if ((rman_get_flags(ires) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	irq = rman_get_start(ires);
	isrc = PIC_INTR_ISRC(sc, irq);
	if(isrc->isrc_event == 0) {
		error = intr_event_create(&isrc->isrc_event, (void *)irq,
		    0, irq, apb_mask_irq, apb_unmask_irq,
		    NULL, NULL, "apb intr%d:", irq);
		if(error != 0)
			return(error);
	}
	name = device_get_nameunit(child);
	error = intr_event_add_handler(isrc->isrc_event, name, filt, handler,
            arg, intr_priority(flags), flags, cookiep);
	return(error);
#else
	irq = rman_get_start(ires);

	if (irq > APB_IRQ_END)
		panic("%s: bad irq %d", __func__, irq);

	event = sc->sc_eventstab[irq];
	if (event == NULL) {
		error = intr_event_create(&event, (void *)irq, 0, irq, 
		    apb_mask_irq, apb_unmask_irq,
		    NULL, NULL,
		    "apb intr%d:", irq);

		if (error == 0) {
			sc->sc_eventstab[irq] = event;
			sc->sc_intr_counter[irq] =
			    mips_intrcnt_create(event->ie_name);
		}
		else
			return (error);
	}

	intr_event_add_handler(event, device_get_nameunit(child), filt,
	    handler, arg, intr_priority(flags), flags, cookiep);
	mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname);

	apb_unmask_irq((void*)irq);

	return (0);
#endif
}