Example #1
0
static struct resource *
mptable_hostb_alloc_resource(device_t dev, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
	struct mptable_hostb_softc *sc;

	sc = device_get_softc(dev);
	if (type == SYS_RES_IOPORT && start + count - 1 == end) {
		if (mptable_is_isa_range(start, end)) {
			switch (sc->sc_decodes_isa_io) {
			case -1:
				return (NULL);
			case 1:
				return (bus_generic_alloc_resource(dev, child,
				    type, rid, start, end, count, flags));
			default:
				break;
			}
		}
		if (mptable_is_vga_range(start, end)) {
			switch (sc->sc_decodes_vga_io) {
			case -1:
				return (NULL);
			case 1:
				return (bus_generic_alloc_resource(dev, child,
				    type, rid, start, end, count, flags));
			default:
				break;
			}
		}
	}
	start = hostb_alloc_start(type, start, end, count);
	return (pcib_host_res_alloc(&sc->sc_host_res, child, type, rid, start,
	    end, count, flags));
}
Example #2
0
struct resource *
pcib_host_res_alloc(struct pcib_host_resources *hr, device_t dev, int type,
    int *rid, u_long start, u_long end, u_long count, u_int flags)
{
	struct resource_list_entry *rle;
	struct resource *r;
	u_long new_start, new_end;

	if (flags & RF_PREFETCHABLE)
		KASSERT(type == SYS_RES_MEMORY,
		    ("only memory is prefetchable"));

	rle = resource_list_find(&hr->hr_rl, type, 0);
	if (rle == NULL) {
		/*
		 * No decoding ranges for this resource type, just pass
		 * the request up to the parent.
		 */
		return (bus_generic_alloc_resource(hr->hr_pcib, dev, type, rid,
		    start, end, count, flags));
	}

restart:
	/* Try to allocate from each decoded range. */
	for (; rle != NULL; rle = STAILQ_NEXT(rle, link)) {
		if (rle->type != type)
			continue;
		if (((flags & RF_PREFETCHABLE) != 0) !=
		    ((rle->flags & RLE_PREFETCH) != 0))
			continue;
		new_start = ulmax(start, rle->start);
		new_end = ulmin(end, rle->end);
		if (new_start > new_end ||
		    new_start + count - 1 > new_end ||
		    new_start + count < new_start)
			continue;
		r = bus_generic_alloc_resource(hr->hr_pcib, dev, type, rid,
		    new_start, new_end, count, flags);
		if (r != NULL) {
			if (bootverbose)
				device_printf(hr->hr_pcib,
			    "allocated type %d (%#lx-%#lx) for rid %x of %s\n",
				    type, rman_get_start(r), rman_get_end(r),
				    *rid, pcib_child_name(dev));
			return (r);
		}
	}

	/*
	 * If we failed to find a prefetch range for a memory
	 * resource, try again without prefetch.
	 */
	if (flags & RF_PREFETCHABLE) {
		flags &= ~RF_PREFETCHABLE;
		rle = resource_list_find(&hr->hr_rl, type, 0);
		goto restart;
	}
	return (NULL);
}
Example #3
0
static struct resource *
zbpci_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 resource *res;

	/*
	 * Handle PCI I/O port resources here and pass everything else to nexus.
	 */
	if (type != SYS_RES_IOPORT) {
		res = bus_generic_alloc_resource(bus, child, type, rid,
						 start, end, count, flags);
		return (res);
	}

	res = rman_reserve_resource(&port_rman, start, end, count,
				    flags, child);
	if (res == NULL)
		return (NULL);

	rman_set_rid(res, *rid);

	/* Activate the resource is requested */
	if (flags & RF_ACTIVE) {
		if (bus_activate_resource(child, type, *rid, res) != 0) {
			rman_release_resource(res);
			return (NULL);
		}
	}

	return (res);
}
Example #4
0
static struct resource *
acpi_pcib_acpi_alloc_resource(device_t dev, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags, int cpuid)
{
    /*
     * If no memory preference is given, use upper 32MB slot most
     * bioses use for their memory window.  Typically other bridges
     * before us get in the way to assert their preferences on memory.
     * Hardcoding like this sucks, so a more MD/MI way needs to be
     * found to do it.  This is typically only used on older laptops
     * that don't have pci busses behind pci bridge, so assuming > 32MB
     * is likely OK.
     *
     * PCI-PCI bridges may allocate smaller ranges for their windows,
     * but the heuristics here should apply to those, so we allow
     * several different end addresses.
     */
    if (type == SYS_RES_MEMORY && start == 0UL && (end == ~0UL ||
	end == 0xffffffff))
	start = acpi_host_mem_start;
    if (type == SYS_RES_IOPORT && start == 0UL && (end == ~0UL ||
	end == 0xffff || end == 0xffffffff))
	start = 0x1000;
    return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
	count, flags, cpuid));
}
Example #5
0
static struct resource *
gic_v3_acpi_bus_alloc_res(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 gic_v3_acpi_devinfo *di;
	struct resource_list_entry *rle;

	/* We only allocate memory */
	if (type != SYS_RES_MEMORY)
		return (NULL);

	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
		if ((di = device_get_ivars(child)) == NULL)
			return (NULL);

		/* Find defaults for this rid */
		rle = resource_list_find(&di->di_rl, type, *rid);
		if (rle == NULL)
			return (NULL);

		start = rle->start;
		end = rle->end;
		count = rle->count;
	}

	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
Example #6
0
static struct resource *
isab_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
	struct isab_pci_softc *sc;
	int bar;

	if (device_get_parent(child) != dev)
		return bus_generic_alloc_resource(dev, child, type, rid, start,
		    end, count, flags);

	switch (type) {
	case SYS_RES_MEMORY:
	case SYS_RES_IOPORT:
		/*
		 * For BARs, we cache the resource so that we only allocate it
		 * from the PCI bus once.
		 */
		bar = PCI_RID2BAR(*rid);
		if (bar < 0 || bar > PCIR_MAX_BAR_0)
			return (NULL);
		sc = device_get_softc(dev);
		if (sc->isab_pci_res[bar].ip_res == NULL)
			sc->isab_pci_res[bar].ip_res = bus_alloc_resource(dev, type,
			    rid, start, end, count, flags);
		if (sc->isab_pci_res[bar].ip_res != NULL)
			sc->isab_pci_res[bar].ip_refs++;
		return (sc->isab_pci_res[bar].ip_res);
	}

	return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid,
		start, end, count, flags));
}
Example #7
0
static struct resource *
simplebus_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 simplebus_devinfo *di;
	struct resource_list_entry *rle;

	/*
	 * Request for the default allocation with a given rid: use resource
	 * list stored in the local device info.
	 */
	if ((start == 0UL) && (end == ~0UL)) {
		if ((di = device_get_ivars(child)) == NULL)
			return (NULL);

		if (type == SYS_RES_IOPORT)
			type = SYS_RES_MEMORY;

		rle = resource_list_find(&di->di_res, type, *rid);
		if (rle == NULL) {
			device_printf(bus, "no default resources for "
			    "rid = %d, type = %d\n", *rid, type);
			return (NULL);
		}
		start = rle->start;
		end = rle->end;
		count = rle->count;
	}

	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
Example #8
0
/*
 * We have to trap resource allocation requests and ensure that the bridge
 * is set up to, or capable of handling them.
 */
static struct resource *
apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
                   u_long start, u_long end, u_long count, u_int flags)
{
    struct apb_softc *sc;

    sc = device_get_softc(dev);

    /*
     * If this is a "default" allocation against this rid, we can't work
     * out where it's coming from (we should actually never see these) so
     * we just have to punt.
     */
    if (start == 0 && end == ~0) {
        device_printf(dev, "can't decode default resource id %d for "
                      "%s, bypassing\n", *rid, device_get_nameunit(child));
        goto passup;
    }

    /*
     * Fail the allocation for this range if it's not supported.
     * XXX we should probably just fix up the bridge decode and
     * soldier on.
     */
    switch (type) {
    case SYS_RES_IOPORT:
        if (!apb_checkrange(sc->sc_iomap, APB_IO_SCALE, start, end)) {
            device_printf(dev, "device %s requested unsupported "
                          "I/O range 0x%lx-0x%lx\n",
                          device_get_nameunit(child), start, end);
            return (NULL);
        }
        if (bootverbose)
            device_printf(sc->sc_bsc.ops_pcib_sc.dev, "device "
                          "%s requested decoded I/O range 0x%lx-0x%lx\n",
                          device_get_nameunit(child), start, end);
        break;
    case SYS_RES_MEMORY:
        if (!apb_checkrange(sc->sc_memmap, APB_MEM_SCALE, start,
                            end)) {
            device_printf(dev, "device %s requested unsupported "
                          "memory range 0x%lx-0x%lx\n",
                          device_get_nameunit(child), start, end);
            return (NULL);
        }
        if (bootverbose)
            device_printf(sc->sc_bsc.ops_pcib_sc.dev, "device "
                          "%s requested decoded memory range 0x%lx-0x%lx\n",
                          device_get_nameunit(child), start, end);
        break;
    }

passup:
    /*
     * Bridge is OK decoding this resource, so pass it up.
     */
    return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
                                       count, flags));
}
Example #9
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);
}
Example #10
0
static struct resource *
simplebus_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 simplebus_softc *sc;
	struct simplebus_devinfo *di;
	struct resource_list_entry *rle;
	int j;

	sc = device_get_softc(bus);

	/*
	 * Request for the default allocation with a given rid: use resource
	 * list stored in the local device info.
	 */
	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
		if ((di = device_get_ivars(child)) == NULL)
			return (NULL);

		if (type == SYS_RES_IOPORT)
			type = SYS_RES_MEMORY;

		rle = resource_list_find(&di->rl, 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;
		end = rle->end;
		count = rle->count;
        }

	if (type == SYS_RES_MEMORY) {
		/* Remap through ranges property */
		for (j = 0; j < sc->nranges; j++) {
			if (start >= sc->ranges[j].bus && end <
			    sc->ranges[j].bus + sc->ranges[j].size) {
				start -= sc->ranges[j].bus;
				start += sc->ranges[j].host;
				end -= sc->ranges[j].bus;
				end += sc->ranges[j].host;
				break;
			}
		}
		if (j == sc->nranges && sc->nranges != 0) {
			if (bootverbose)
				device_printf(bus, "Could not map resource "
				    "%#jx-%#jx\n", start, end);

			return (NULL);
		}
	}

	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
Example #11
0
static struct resource *
arm_gic_fdt_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 arm_gic_fdt_softc *sc = device_get_softc(bus);
	struct gic_devinfo *di;
	struct resource_list_entry *rle;
	int j;

	KASSERT(type == SYS_RES_MEMORY, ("Invalid resoure type %x", type));

	/*
	 * Request for the default allocation with a given rid: use resource
	 * list stored in the local device info.
	 */
	if ((start == 0UL) && (end == ~0UL)) {
		if ((di = device_get_ivars(child)) == NULL)
			return (NULL);

		if (type == SYS_RES_IOPORT)
			type = SYS_RES_MEMORY;

		rle = resource_list_find(&di->rl, 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;
		end = rle->end;
		count = rle->count;
	}

	/* Remap through ranges property */
	for (j = 0; j < sc->sc_nranges; j++) {
		if (start >= sc->sc_ranges[j].bus && end <
		    sc->sc_ranges[j].bus + sc->sc_ranges[j].size) {
			start -= sc->sc_ranges[j].bus;
			start += sc->sc_ranges[j].host;
			end -= sc->sc_ranges[j].bus;
			end += sc->sc_ranges[j].host;
			break;
		}
	}
	if (j == sc->sc_nranges && sc->sc_nranges != 0) {
		if (bootverbose)
			device_printf(bus, "Could not map resource "
			    "%#lx-%#lx\n", start, end);

		return (NULL);
	}

	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
Example #12
0
File: qpi.c Project: 2asoft/freebsd
static struct resource *
qpi_pcib_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)
{

	if (type == PCI_RES_BUS)
		return (pci_domain_alloc_bus(0, child, rid, start, end, count,
		    flags));
	return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
	    count, flags));
}
Example #13
0
static struct resource *
mv_pcib_ctrl_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 mv_pcib_ctrl_devinfo *di;
	struct resource_list_entry *rle;
	struct mv_pcib_ctrl_softc *sc;
	int i;

	if (RMAN_IS_DEFAULT_RANGE(start, end)) {

		if ((di = device_get_ivars(child)) == NULL)
			return (NULL);
		if (type != SYS_RES_MEMORY)
			return (NULL);

		/* Find defaults for this rid */
		rle = resource_list_find(&di->di_rl, type, *rid);

		if (rle == NULL)
			return (NULL);

		start = rle->start;
		end = rle->end;
		count = rle->count;
	}

	sc = device_get_softc(bus);
	if (type == SYS_RES_MEMORY) {
		/* Remap through ranges property */
		for (i = 0; i < sc->nranges; i++) {
			if (start >= sc->ranges[i].bus && end <
			    sc->ranges[i].bus + sc->ranges[i].size) {
				start -= sc->ranges[i].bus;
				start += sc->ranges[i].host;
				end -= sc->ranges[i].bus;
				end += sc->ranges[i].host;
				break;
			}
		}

		if (i == sc->nranges && sc->nranges != 0) {
			device_printf(bus, "Could not map resource "
			    "%#llx-%#llx\n", start, end);
			return (NULL);
		}
	}

	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
Example #14
0
struct resource *
ofw_pci_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 ofw_pci_softc *sc;
    struct resource *rv;
    struct rman *rm;

    sc = device_get_softc(bus);
    switch (type) {
    case SYS_RES_IRQ:
        /*
         * XXX: Don't accept blank ranges for now, only single
         * interrupts.  The other case should not happen with
         * the MI PCI code ...
         * XXX: This may return a resource that is out of the
         * range that was specified.  Is this correct ...?
         */
        if (start != end)
            panic("%s: XXX: interrupt range", __func__);
        return (bus_generic_alloc_resource(bus, child, type, rid,
                                           start, end, count, flags));
    case SYS_RES_MEMORY:
        rm = &sc->sc_pci_mem_rman;
        break;
    case SYS_RES_IOPORT:
        rm = &sc->sc_pci_io_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);
    }
    return (rv);
}
Example #15
0
struct resource *
acpi_pcib_acpi_alloc_resource(device_t dev, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
    /*
     * If no memory preference is given, use upper 32MB slot most
     * bioses use for their memory window.  Typically other bridges
     * before us get in the way to assert their preferences on memory.
     * Hardcoding like this sucks, so a more MD/MI way needs to be
     * found to do it.  This is typically only used on older laptops
     * that don't have pci busses behind pci bridge, so assuming > 32MB
     * is liekly OK.
     */
    if (type == SYS_RES_MEMORY && start == 0UL && end == ~0UL)
	start = acpi_host_mem_start;
    if (type == SYS_RES_IOPORT && start == 0UL && end == ~0UL)
	start = 0x1000;
    return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
	count, flags));
}
Example #16
0
static struct resource *
gic_v3_ofw_bus_alloc_res(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 gic_v3_ofw_devinfo *di;
	struct resource_list_entry *rle;
	int ranges_len;

	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
		if ((di = device_get_ivars(child)) == NULL)
			return (NULL);
		if (type != SYS_RES_MEMORY)
			return (NULL);

		/* Find defaults for this rid */
		rle = resource_list_find(&di->di_rl, type, *rid);
		if (rle == NULL)
			return (NULL);

		start = rle->start;
		end = rle->end;
		count = rle->count;
	}
	/*
	 * XXX: No ranges remap!
	 *	Absolute address is expected.
	 */
	if (ofw_bus_has_prop(bus, "ranges")) {
		ranges_len = OF_getproplen(ofw_bus_get_node(bus), "ranges");
		if (ranges_len != 0) {
			if (bootverbose) {
				device_printf(child,
				    "Ranges remap not supported\n");
			}
			return (NULL);
		}
	}
	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
	    count, flags));
}
Example #17
0
/*
 * We have to trap resource allocation requests and ensure that the bridge
 * is set up to, or capable of handling them.
 */
struct resource *
pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, 
		    u_long start, u_long end, u_long count, u_int flags)
{
    struct pcib_softc	*sc = device_get_softc(dev);
    int ok;

    /*
     * If this is a "default" allocation against this rid, we can't work
     * out where it's coming from (we should actually never see these) so we
     * just have to punt.
     */
    if ((start == 0) && (end == ~0)) {
	device_printf(dev, "can't decode default resource id %d for %s%d, bypassing\n",
		      *rid, device_get_name(child), device_get_unit(child));
    } else {
	/*
	 * Fail the allocation for this range if it's not supported.
	 */
	switch (type) {
	case SYS_RES_IOPORT:
	    ok = 1;
	    if (!pcib_is_isa_io(start)) {
		ok = 0;
		if (pcib_is_io_open(sc))
		    ok = (start >= sc->iobase && end <= sc->iolimit);
		if (!pci_allow_unsupported_io_range) {
		    if (!ok) {
			if (start < sc->iobase)
			    start = sc->iobase;
			if (end > sc->iolimit)
			    end = sc->iolimit;
		    }
		} else {
		    if (start < sc->iobase)
			printf("start (%lx) < sc->iobase (%x)\n", start,
				sc->iobase);
		    if (end > sc->iolimit)
			printf("end (%lx) > sc->iolimit (%x)\n",
				end, sc->iolimit);
		    if (end < start)
			printf("end (%lx) < start (%lx)\n", end, start);
		}
	    }
	    if (end < start) {
		start = 0;
		end = 0;
		ok = 0;
	    }
	    if (!ok) {
		device_printf(dev, "device %s%d requested unsupported I/O "
		  "range 0x%lx-0x%lx (decoding 0x%x-0x%x)\n",
		  device_get_name(child), device_get_unit(child), start, end,
		  sc->iobase, sc->iolimit);
		return (NULL);
	    }
	    if (bootverbose)
		device_printf(sc->dev, "device %s%d requested decoded I/O range 0x%lx-0x%lx\n",
			      device_get_name(child), device_get_unit(child), start, end);
	    break;

	case SYS_RES_MEMORY:
	    ok = 1;
	    if (!pcib_is_isa_mem(start)) {
		ok = 0;
		if (pcib_is_nonprefetch_open(sc))
		    ok = ok || (start >= sc->membase && end <= sc->memlimit);
		if (pcib_is_prefetch_open(sc))
		    ok = ok || (start >= sc->pmembase && end <= sc->pmemlimit);
		if (!pci_allow_unsupported_io_range) {
		    if (!ok) {
			ok = 1;
			if (flags & RF_PREFETCHABLE) {
			    if (pcib_is_prefetch_open(sc)) {
				if (start < sc->pmembase)
				    start = sc->pmembase;
				if (end > sc->pmemlimit)
				    end = sc->pmemlimit;
			    } else {
				ok = 0;
			    }
			} else {	/* non-prefetchable */
			    if (pcib_is_nonprefetch_open(sc)) {
				if (start < sc->membase)
				    start = sc->membase;
				if (end > sc->memlimit)
				    end = sc->memlimit;
			    } else {
				ok = 0;
			    }
			}
		    }
		} else if (!ok) {
		    ok = 1;	/* pci_allow_unsupported_ranges -> always ok */
		    if (pcib_is_nonprefetch_open(sc)) {
			if (start < sc->membase)
			    printf("start (%lx) < sc->membase (%x)\n",
			      start, sc->membase);
			if (end > sc->memlimit)
			    printf("end (%lx) > sc->memlimit (%x)\n",
			      end, sc->memlimit);
		    }
		    if (pcib_is_prefetch_open(sc)) {
			if (start < sc->pmembase)
			    printf("start (%lx) < sc->pmembase (%x)\n",
			      start, sc->pmembase);
			if (end > sc->pmemlimit)
			    printf("end (%lx) > sc->pmemlimit (%x)\n",
			      end, sc->memlimit);
		    }
		    if (end < start)
			printf("end (%lx) < start (%lx)\n", end, start);
		}
	    }
	    if (end < start) {
		start = 0;
		end = 0;
		ok = 0;
	    }
	    if (!ok && bootverbose)
		device_printf(dev,
		  "device %s%d requested unsupported memory range "
		  "0x%lx-0x%lx (decoding 0x%x-0x%x, 0x%x-0x%x)\n",
		  device_get_name(child), device_get_unit(child), start,
		  end, sc->membase, sc->memlimit, sc->pmembase,
		  sc->pmemlimit);
	    if (!ok)
		return (NULL);
	    if (bootverbose)
		device_printf(sc->dev, "device %s%d requested decoded memory range 0x%lx-0x%lx\n",
		  device_get_name(child), device_get_unit(child), start, end);
	    break;

	default:
	    break;
	}
    }

    /*
     * Bridge is OK decoding this resource, so pass it up.
     */
    return(bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags));
}
Example #18
0
struct resource *
thunder_pcie_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 thunder_pcie_softc *sc = device_get_softc(dev);
	struct rman *rm = NULL;
	struct resource *res;
	pci_addr_t map, testval;

	switch (type) {
	case SYS_RES_IOPORT:
		goto fail;
		break;
	case SYS_RES_MEMORY:
		rm = &sc->mem_rman;
		break;
	default:
		return (bus_generic_alloc_resource(dev, child,
		    type, rid, start, end, count, flags));
	};

	if ((start == 0UL) && (end == ~0UL)) {

		/* Read BAR manually to get resource address and size */
		pci_read_bar(child, *rid, &map, &testval, NULL);

		/* Mask the information bits */
		if (PCI_BAR_MEM(map))
			map &= PCIM_BAR_MEM_BASE;
		else
			map &= PCIM_BAR_IO_BASE;

		if (PCI_BAR_MEM(testval))
			testval &= PCIM_BAR_MEM_BASE;
		else
			testval &= PCIM_BAR_IO_BASE;

		start = map;
		count = (~testval) + 1;
		/*
		 * Internal ThunderX devices supports up to 3 64-bit BARs.
		 * If we're allocating anything above, that means upper layer
		 * wants us to allocate VF-BAR. In that case reserve bigger
		 * slice to make a room for other VFs adjacent to this one.
		 */
		if (*rid > PCIR_BAR(5))
			count = count * thunder_pcie_max_vfs;
		end = start + count - 1;
	}

	/* Convert input BUS address to required PHYS */
	if (range_addr_is_pci(sc->ranges, start, count) == 0)
		goto fail;
	start = range_addr_pci_to_phys(sc->ranges, start);
	end = start + count - 1;

	if (bootverbose) {
		device_printf(dev,
		    "rman_reserve_resource: start=%#lx, end=%#lx, count=%#lx\n",
		    start, end, count);
	}

	res = rman_reserve_resource(rm, start, end, count, flags, child);
	if (res == NULL)
		goto fail;

	rman_set_rid(res, *rid);

	if ((flags & RF_ACTIVE) != 0)
		if (bus_activate_resource(child, type, *rid, res)) {
			rman_release_resource(res);
			goto fail;
		}

	return (res);

fail:
	if (bootverbose) {
		device_printf(dev, "%s FAIL: type=%d, rid=%d, "
		    "start=%016lx, end=%016lx, count=%016lx, flags=%x\n",
		    __func__, type, *rid, start, end, count, flags);
	}

	return (NULL);
}
Example #19
0
File: fhc.c Project: MarginC/kame
struct resource *
fhc_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_entry *rle;
	struct fhc_devinfo *fdi;
	struct fhc_softc *sc;
	struct resource *res;
	bus_addr_t coffset;
	bus_addr_t cend;
	bus_addr_t phys;
	int isdefault;
	uint32_t map;
	uint32_t vec;
	int i;

	isdefault = (start == 0UL && end == ~0UL);
	res = NULL;
	sc = device_get_softc(bus);
	switch (type) {
	case SYS_RES_IRQ:
		if (!isdefault || count != 1 || *rid < FHC_FANFAIL ||
		    *rid > FHC_TOD)
			break;

		map = bus_space_read_4(sc->sc_bt[*rid], sc->sc_bh[*rid],
		    FHC_IMAP);
		vec = INTINO(map) | (sc->sc_ign << INTMAP_IGN_SHIFT);
		bus_space_write_4(sc->sc_bt[*rid], sc->sc_bh[*rid],
		    FHC_IMAP, vec);
		bus_space_read_4(sc->sc_bt[*rid], sc->sc_bh[*rid], FHC_IMAP);

		res = bus_generic_alloc_resource(bus, child, type, rid,
		    vec, vec, 1, flags);
		if (res != NULL)
			rman_set_rid(res, *rid);
		break;
	case SYS_RES_MEMORY:
		fdi = device_get_ivars(child);
		rle = resource_list_find(&fdi->fdi_rl, type, *rid);
		if (rle == NULL)
			return (NULL);
		if (rle->res != NULL)
			panic("fhc_alloc_resource: resource entry is busy");
		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);
				rle->res = res;
				break;
			}
		}
		break;
	default:
		break;
	}
	return (res);
}
Example #20
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);
}
Example #21
0
static struct resource *
octopci_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 octopci_softc *sc;
	struct resource *res;
	struct rman *rm;
	int error;

	sc = device_get_softc(bus);

	switch (type) {
	case SYS_RES_IRQ:
		res = bus_generic_alloc_resource(bus, child, type, rid, start,
		    end, count, flags);
		if (res != NULL)
			return (res);
		return (NULL);
	case SYS_RES_MEMORY:
		rm = &sc->sc_mem1;
		break;
	case SYS_RES_IOPORT:
		rm = &sc->sc_io;
		break;
	default:
		return (NULL);
	}

	res = rman_reserve_resource(rm, start, end, count, flags, child);
	if (res == NULL)
		return (NULL);

	rman_set_rid(res, *rid);
	rman_set_bustag(res, octopci_bus_space);

	switch (type) {
	case SYS_RES_MEMORY:
		rman_set_bushandle(res, CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, CVMX_OCT_SUBDID_PCI_MEM1)) + rman_get_start(res));
		break;
	case SYS_RES_IOPORT:
		rman_set_bushandle(res, CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, CVMX_OCT_SUBDID_PCI_IO)) + rman_get_start(res));
		/*
		 * XXX
		 * We should just disallow use of io ports on !n64 since without
		 * 64-bit PTEs we can't even do a 32-bit virtual address
		 * mapped to them.
		 */
#if 0
		rman_set_virtual(res, (void *)rman_get_bushandle(res));
#endif
		break;
	}

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

	return (res);
}