예제 #1
0
파일: ata-pci.c 프로젝트: coyizumi/cs111
struct resource *
ata_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 ata_pci_controller *controller = device_get_softc(dev);
	struct resource *res = NULL;

	if (device_get_devclass(child) == ata_devclass) {
		int unit = ((struct ata_channel *)device_get_softc(child))->unit;
		int myrid;

		if (type == SYS_RES_IOPORT) {
			switch (*rid) {
			case ATA_IOADDR_RID:
			    if (controller->legacy) {
				start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
				count = ATA_IOSIZE;
				end = start + count - 1;
			    }
			    myrid = PCIR_BAR(0) + (unit << 3);
			    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
				SYS_RES_IOPORT, &myrid,
				start, end, count, flags);
			    break;
			case ATA_CTLADDR_RID:
			    if (controller->legacy) {
				start = (unit ? ATA_SECONDARY : ATA_PRIMARY) +
				    ATA_CTLOFFSET;
				count = ATA_CTLIOSIZE;
				end = start + count - 1;
			    }
			    myrid = PCIR_BAR(1) + (unit << 3);
			    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
				SYS_RES_IOPORT, &myrid,
				start, end, count, flags);
			    break;
			}
		}
		if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
			if (controller->legacy) {
			    int irq = (unit == 0 ? 14 : 15);
	    
			    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
				SYS_RES_IRQ, rid, irq, irq, 1, flags);
			} else
			    res = controller->r_irq;
		}
	} else {
		if (type == SYS_RES_IRQ) {
			if (*rid != ATA_IRQ_RID)
				return (NULL);
			res = controller->r_irq;
		} else {
			res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
			     type, rid, start, end, count, flags);
		}
	}
	return (res);
}
예제 #2
0
파일: ata_macio.c 프로젝트: MarginC/kame
struct resource *
ata_macio_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 resource *res = NULL;
	int myrid;
	u_int *ofw_regs;

	ofw_regs = macio_get_regs(dev);

	/*
	 * The offset for the register bank is in the first ofw register,
	 * with the base address coming from the parent macio bus (but
	 * accessible via the ata-macio child)
	 */
	if (type == SYS_RES_IOPORT) {
		switch (*rid) {
		case ATA_IOADDR_RID:
			myrid = 0;
			start = ofw_regs[0];
			end = start + (ATA_IOSIZE << 4) - 1;
			count = ATA_IOSIZE << 4;
			res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
						 SYS_RES_IOPORT, &myrid,
						 start, end, count,
						 PPC_BUS_SPARSE4 | flags);
			break;

		case ATA_ALTADDR_RID:		
			myrid = 0;
			start = ofw_regs[0] + ATA_MACIO_ALTOFFSET;
			end = start + (ATA_ALTIOSIZE << 4) - 1;
			count = ATA_ALTIOSIZE << 4;
			res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
						 SYS_RES_IOPORT, &myrid,
						 start, end, count,
						 PPC_BUS_SPARSE4 | flags);
			break;

		case ATA_BMADDR_RID:
			/* looks difficult to support DBDMA in FreeBSD... */
			break;
		}
		return (res);

	} else if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
		/*
		 * Pass this on to the parent, using the IRQ from the
		 * ATA pseudo-bus resource
		 */
		res = bus_generic_rl_alloc_resource(device_get_parent(dev),
		   dev, SYS_RES_IRQ, 0, 0, ~0, 1, flags);
		return (res);

	} else {	
		return (NULL);
	}
}
예제 #3
0
파일: canbus.c 프로젝트: JabirTech/Source
static struct resource *
canbus_alloc_resource(device_t dev, device_t child, int type,
    int *rid, u_long start, u_long end, u_long count, u_int flags)
{
	return (BUS_ALLOC_RESOURCE(device_get_parent(dev),
	    child, type, rid, start, end, count, flags));
}
예제 #4
0
파일: isa_pci.c 프로젝트: coyizumi/cs111
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));
}
예제 #5
0
static struct resource *
thunder_pem_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_pem_softc *sc = device_get_softc(dev);
	struct rman *rm = NULL;
	struct resource *res;
	device_t parent_dev;

	rm = thunder_pem_rman(sc, type);
	if (rm == NULL) {
		/* Find parent device. On ThunderX we know an exact path. */
		parent_dev = device_get_parent(device_get_parent(dev));
		return (BUS_ALLOC_RESOURCE(parent_dev, dev, type, rid, start,
		    end, count, flags));
	}


	if (!RMAN_IS_DEFAULT_RANGE(start, end)) {
		/*
		 * We might get PHYS addresses here inherited from EFI.
		 * Convert to PCI if necessary.
		 */
		if (range_addr_is_phys(sc->ranges, start, count)) {
			start = range_addr_phys_to_pci(sc->ranges, start);
			end = start + count - 1;
		}

	}

	if (bootverbose) {
		device_printf(dev,
		    "thunder_pem_alloc_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)
		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);
}
예제 #6
0
파일: gt.c 프로젝트: hmatyschok/MeshBSD
static struct resource *
gt_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)
{
	return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
		    type, rid, start, end, count, flags));
	
}
예제 #7
0
/* proxying to the parent */
static struct resource *
siba_bwn_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)
{

	return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
	    type, rid, start, end, count, flags, cpuid));
}
예제 #8
0
static struct resource *
at91_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 at91_softc *sc = device_get_softc(dev);
	struct resource_list_entry *rle;
	struct at91_ivar *ivar = device_get_ivars(child);
	struct resource_list *rl = &ivar->resources;

	if (device_get_parent(child) != dev)
		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
		    type, rid, start, end, count, flags));
	
	rle = resource_list_find(rl, type, *rid);
	if (rle == NULL)
		return (NULL);
	if (rle->res)
		panic("Resource rid %d type %d already in use", *rid, type);
	if (start == 0UL && end == ~0UL) {
		start = rle->start;
		count = ulmax(count, rle->count);
		end = ulmax(rle->end, start + count - 1);
	}
	switch (type)
	{
	case SYS_RES_IRQ:
		rle->res = rman_reserve_resource(&sc->sc_irq_rman,
		    start, end, count, flags, child);
		break;
	case SYS_RES_MEMORY:
#if 0
		if (start >= 0x00300000 && start <= 0x003fffff)
			rle->res = rman_reserve_resource(&sc->sc_usbmem_rman,
			    start, end, count, flags, child);
		else
#endif
			rle->res = rman_reserve_resource(&sc->sc_mem_rman,
			    start, end, count, flags, child);
		if (rle->res != NULL) {
			rman_set_bustag(rle->res, &at91_bs_tag);
			rman_set_bushandle(rle->res, start);
		}
		break;
	}
	if (rle->res) {
		rle->start = rman_get_start(rle->res);
		rle->end = rman_get_end(rle->res);
		rle->count = count;
		rman_set_rid(rle->res, *rid);
	}
	return (rle->res);
}
예제 #9
0
/**
 *	omap_alloc_resource
 *
 *	This function will be called when bus_alloc_resource(...) if the memory
 *	region requested is in the range of the managed values set by
 *	rman_manage_region(...) above.
 *
 *	For SYS_RES_MEMORY resource types the omap_attach() calls rman_manage_region
 *	with the list of pyshical mappings defined in the omap_devmap region map.
 *	However because we are working with physical addresses, we need to convert
 *	the physical to virtual within this function and return the virtual address
 *	in the bus tag field.
 *
 */
static struct resource *
omap_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 omap_softc *sc = device_get_softc(dev);
	struct resource_list_entry *rle;
	struct omap_ivar *ivar = device_get_ivars(child);
	struct resource_list *rl = &ivar->resources;

	/* If we aren't the parent pass it onto the actual parent */
	if (device_get_parent(child) != dev) {
		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
		    type, rid, start, end, count, flags));
	}
	
	/* Find the resource in the list */
	rle = resource_list_find(rl, type, *rid);
	if (rle == NULL)
		return (NULL);
	if (rle->res)
		panic("Resource rid %d type %d already in use", *rid, type);

	if (start == 0UL && end == ~0UL) {
		start = rle->start;
		count = ulmax(count, rle->count);
		end = ulmax(rle->end, start + count - 1);
	}

	switch (type)
	{
	case SYS_RES_IRQ:
		rle->res = rman_reserve_resource(&sc->sc_irq_rman,
		    start, end, count, flags, child);
		break;
	case SYS_RES_MEMORY:
		rle->res = rman_reserve_resource(&sc->sc_mem_rman,
		    start, end, count, flags, child);
		if (rle->res != NULL) {
			rman_set_bustag(rle->res, &omap_bs_tag);
			rman_set_bushandle(rle->res, omap_devmap_phys2virt(start));
		}
		break;
	}

	if (rle->res) {
		rle->start = rman_get_start(rle->res);
		rle->end = rman_get_end(rle->res);
		rle->count = count;
		rman_set_rid(rle->res, *rid);
	}
	return (rle->res);
}
예제 #10
0
파일: xlp_pci.c 프로젝트: wulf7/freebsd
static struct resource *
xlp_pci_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 *r;
	struct xlp_devinfo *xlp_devinfo;
	int busno;

	/*
	 * Do custom allocation for MEMORY resource for SoC device if 
	 * MEM_RES_EMUL flag is set
	 */
	busno = pci_get_bus(child);
	if ((type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) && busno == 0) {
		xlp_devinfo = (struct xlp_devinfo *)device_get_ivars(child);
		if ((xlp_devinfo->flags & MEM_RES_EMUL) != 0) {
			/* no emulation for IO ports */
			if (type == SYS_RES_IOPORT)
				return (NULL);

			start = xlp_devinfo->mem_res_start;
			count = XLP_PCIE_CFG_SIZE - XLP_IO_PCI_HDRSZ;

			/* MMC needs to 2 slots with rids 16 and 20 and a
			 * fixup for size */
			if (pci_get_device(child) == PCI_DEVICE_ID_NLM_MMC) {
				count = 0x100;
				if (*rid == 16)
					; /* first slot already setup */
				else if (*rid == 20)
					start += 0x100; /* second slot */
				else
					return (NULL);
			}

			end = start + count - 1;
			r = BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
			    type, rid, start, end, count, flags);
			if (r == NULL)
				return (NULL);
			if ((xlp_devinfo->flags & DEV_MMIO32) != 0)
				rman_set_bustag(r, rmi_uart_bus_space);
			return (r);
		}
	}

	/* Not custom alloc, use PCI code */
	return (pci_alloc_resource(bus, child, type, rid, start, end, count,
	    flags));
}
예제 #11
0
struct resource *
pci_host_generic_core_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 generic_pcie_core_softc *sc;
	struct resource *res;
	struct rman *rm;

	sc = device_get_softc(dev);

#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
	if (type == PCI_RES_BUS) {
		return (pci_domain_alloc_bus(sc->ecam, child, rid, start, end,
		    count, flags));
	}
#endif

	rm = generic_pcie_rman(sc, type);
	if (rm == NULL)
		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
		    type, rid, start, end, count, flags));

	if (bootverbose) {
		device_printf(dev,
		    "rman_reserve_resource: start=%#jx, end=%#jx, count=%#jx\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)
		if (bus_activate_resource(child, type, *rid, res)) {
			rman_release_resource(res);
			goto fail;
		}

	return (res);

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

	return (NULL);
}
예제 #12
0
파일: at91.c 프로젝트: embedclub/freebsd
static struct resource *
at91_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 at91_softc *sc = device_get_softc(dev);
	struct resource_list_entry *rle;
	struct at91_ivar *ivar = device_get_ivars(child);
	struct resource_list *rl = &ivar->resources;
	bus_space_handle_t bsh;

	if (device_get_parent(child) != dev)
		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
		    type, rid, start, end, count, flags));
	
	rle = resource_list_find(rl, type, *rid);
	if (rle == NULL)
		return (NULL);
	if (rle->res)
		panic("Resource rid %d type %d already in use", *rid, type);
	if (start == 0UL && end == ~0UL) {
		start = rle->start;
		count = ulmax(count, rle->count);
		end = ulmax(rle->end, start + count - 1);
	}
	switch (type)
	{
	case SYS_RES_IRQ:
		rle->res = rman_reserve_resource(&sc->sc_irq_rman,
		    start, end, count, flags, child);
		break;
	case SYS_RES_MEMORY:
		rle->res = rman_reserve_resource(&sc->sc_mem_rman,
		    start, end, count, flags, child);
		if (rle->res != NULL) {
			bus_space_map(arm_base_bs_tag, start,
			    rman_get_size(rle->res), 0, &bsh);
			rman_set_bustag(rle->res, arm_base_bs_tag);
			rman_set_bushandle(rle->res, bsh);
		}
		break;
	}
	if (rle->res) {
		rle->start = rman_get_start(rle->res);
		rle->end = rman_get_end(rle->res);
		rle->count = count;
		rman_set_rid(rle->res, *rid);
	}
	return (rle->res);
}
예제 #13
0
/*
 * These can disappear when I update the pci code to use the new
 * device framework.
 */
struct intrec *
intr_create(void *dev_instance, int irq, inthand2_t handler, void *arg,
	    intrmask_t *maskptr, int flags)
{
	struct resource *res;
	device_t pcib = chipset.intrdev;
	int zero = 0;
	void *cookie;

	res = BUS_ALLOC_RESOURCE(pcib, NULL, SYS_RES_IRQ, &zero,
				irq, irq, 1, RF_SHAREABLE | RF_ACTIVE);
	if (BUS_SETUP_INTR(pcib, pcib, res, (driver_intr_t *)handler, arg, &cookie))
		return 0;

	return (struct intrec *)cookie;
}
예제 #14
0
파일: obio.c 프로젝트: JabirTech/Source
static struct resource *
obio_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 obio_softc		*sc = device_get_softc(bus);
	struct obio_ivar		*ivar = device_get_ivars(child);
	struct resource			*rv;
	struct resource_list_entry	*rle;
	struct rman			*rm;
	int				 isdefault, needactivate, passthrough;

	isdefault = (start == 0UL && end == ~0UL);
	needactivate = flags & RF_ACTIVE;
	passthrough = (device_get_parent(child) != bus);
	rle = NULL;

	if (passthrough)
		return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type,
		    rid, start, end, count, flags));

	/*
	 * If this is an allocation of the "default" range for a given RID,
	 * and we know what the resources for this device are (ie. they aren't
	 * maintained by a child bus), then work out the start/end values.
	 */
	if (isdefault) {
		rle = resource_list_find(&ivar->resources, type, *rid);
		if (rle == NULL)
			return (NULL);
		if (rle->res != NULL) {
			panic("%s: resource entry is busy", __func__);
		}
		start = rle->start;
		end = rle->end;
		count = rle->count;
	}

	switch (type) {
	case SYS_RES_IRQ:
		rm = &sc->oba_irq_rman;
		break;
	case SYS_RES_MEMORY:
		rm = &sc->oba_mem_rman;
		break;
	default:
		printf("%s: unknown resource type %d\n", __func__, type);
		return (0);
	}

	rv = rman_reserve_resource(rm, start, end, count, flags, child);
	if (rv == 0) {
		printf("%s: could not reserve resource\n", __func__);
		return (0);
	}

	rman_set_rid(rv, *rid);

	if (needactivate) {
		if (bus_activate_resource(child, type, *rid, rv)) {
			printf("%s: could not activate resource\n", __func__);
			rman_release_resource(rv);
			return (0);
		}
	}

	return (rv);
}
예제 #15
0
static struct resource *
thunder_pem_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_pem_softc *sc = device_get_softc(dev);
	struct rman *rm = NULL;
	struct resource *res;
	device_t parent_dev;

	switch (type) {
	case SYS_RES_IOPORT:
		rm = &sc->io_rman;
		break;
	case SYS_RES_MEMORY:
		rm = &sc->mem_rman;
		break;
	default:
		/* Find parent device. On ThunderX we know an exact path. */
		parent_dev = device_get_parent(device_get_parent(dev));
		return (BUS_ALLOC_RESOURCE(parent_dev, dev, type, rid, start,
		    end, count, flags));
	};

	if ((start == 0UL) && (end == ~0UL)) {
		device_printf(dev,
		    "Cannot allocate resource with unspecified range\n");
		goto fail;
	}

	/* Translate PCI address to host 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)
		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);
}
예제 #16
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);
}
예제 #17
0
static struct resource *
apb_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 apb_softc		*sc = device_get_softc(bus);
	struct apb_ivar			*ivar = device_get_ivars(child);
	struct resource			*rv;
	struct resource_list_entry	*rle;
	struct rman			*rm;
	int				 isdefault, needactivate, passthrough;

	isdefault = (RMAN_IS_DEFAULT_RANGE(start, end));
	needactivate = flags & RF_ACTIVE;
	/*
	 * Pass memory requests to nexus device
	 */
	passthrough = (device_get_parent(child) != bus);
	rle = NULL;

	dprintf("%s: entry (%p, %p, %d, %d, %p, %p, %jd, %d)\n",
	    __func__, bus, child, type, *rid, (void *)(intptr_t)start,
	    (void *)(intptr_t)end, count, flags);

	if (passthrough)
		return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type,
		    rid, start, end, count, flags));

	/*
	 * If this is an allocation of the "default" range for a given RID,
	 * and we know what the resources for this device are (ie. they aren't
	 * maintained by a child bus), then work out the start/end values.
	 */

	if (isdefault) {
		rle = resource_list_find(&ivar->resources, type, *rid);
		if (rle == NULL) {
			return (NULL);
		}

		if (rle->res != NULL) {
			panic("%s: resource entry is busy", __func__);
		}
		start = rle->start;
		end = rle->end;
		count = rle->count;

		dprintf("%s: default resource (%p, %p, %ld)\n",
		    __func__, (void *)(intptr_t)start,
		    (void *)(intptr_t)end, count);
	}

	switch (type) {
	case SYS_RES_IRQ:
		rm = &sc->apb_irq_rman;
		break;
	case SYS_RES_MEMORY:
		rm = &sc->apb_mem_rman;
		break;
	default:
		printf("%s: unknown resource type %d\n", __func__, type);
		return (0);
	}

	rv = rman_reserve_resource(rm, start, end, count, flags, child);
	if (rv == 0) {
		printf("%s: could not reserve resource\n", __func__);
		return (0);
	}

	rman_set_rid(rv, *rid);

	if (needactivate) {
		if (bus_activate_resource(child, type, *rid, rv)) {
			printf("%s: could not activate resource\n", __func__);
			rman_release_resource(rv);
			return (0);
		}
	}

	return (rv);
}
예제 #18
0
static void
pcib_mbus_identify(driver_t *driver, device_t parent)
{
	const struct obio_pci *info = mv_pci_info;
	struct pcib_mbus_softc *sc;
	uint32_t control;

	while (info->op_base) {
		sc = malloc(driver->size, M_DEVBUF, M_NOWAIT | M_ZERO);
		if (sc == NULL) {
			device_printf(parent, "Could not allocate pcib "
			    "memory\n");
			break;
		}
		sc->sc_info = info++;

		/*
		 * PCI bridge objects are instantiated immediately. PCI-Express
		 * bridges require more complicated handling depending on
		 * platform configuration.
		 */
		if (sc->sc_info->op_type == MV_TYPE_PCI) {
			pcib_mbus_add_child(driver, parent, sc);
			continue;
		}

		/*
		 * Read link configuration
		 */
		sc->sc_rid = 0;
		sc->sc_res = BUS_ALLOC_RESOURCE(parent, parent, SYS_RES_MEMORY,
		    &sc->sc_rid, sc->sc_info->op_base, sc->sc_info->op_base +
		    sc->sc_info->op_size - 1, sc->sc_info->op_size,
		    RF_ACTIVE);
		if (sc->sc_res == NULL) {
			device_printf(parent, "Could not map pcib memory\n");
			break;
		}

		sc->sc_bst = rman_get_bustag(sc->sc_res);
		sc->sc_bsh = rman_get_bushandle(sc->sc_res);

		control = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
		    PCIE_REG_CONTROL);

		BUS_RELEASE_RESOURCE(parent, parent, SYS_RES_MEMORY, sc->sc_rid,
		    sc->sc_res);

		/*
		 * If this PCI-E port (controller) is configured (by the
		 * underlying firmware) with lane width other than 1x, there
		 * are auxiliary resources defined for aggregating more width
		 * on our lane. Skip all such entries as they are not
		 * standalone ports and must not have a device object
		 * instantiated.
		 */
		if ((control & PCIE_CTRL_LINK1X) == 0)
			while (info->op_base &&
			    info->op_type == MV_TYPE_PCIE_AGGR_LANE)
				info++;

		pcib_mbus_add_child(driver, parent, sc);
	}
}
예제 #19
0
static struct resource *
eisa_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 isdefault;
	struct eisa_device *e_dev = device_get_ivars(child);
	struct resource *rv, **rvp = 0;

	isdefault = (device_get_parent(child) == dev &&
	     start == 0UL && end == ~0UL && count == 1);

	switch (type) {
	case SYS_RES_IRQ:
		if (isdefault) {
			struct irq_node * irq = eisa_find_irq(e_dev, *rid);
			if (irq == NULL)
				return (NULL);
			start = end = irq->irq_no;
			count = 1;
			if (irq->irq_trigger == EISA_TRIGGER_LEVEL)
				flags |= RF_SHAREABLE;
			else
				flags &= ~RF_SHAREABLE;
		}
		break;

	case SYS_RES_MEMORY:
		if (isdefault) {
			struct resvaddr *resv;

			resv = eisa_find_maddr(e_dev, *rid);
			if (resv == NULL)
				return (NULL);

			start = resv->addr;
			end = resv->addr + (resv->size - 1);
			count = resv->size;
			rvp = &resv->res;
		}
		break;

	case SYS_RES_IOPORT:
		if (isdefault) {
			struct resvaddr *resv;

			resv = eisa_find_ioaddr(e_dev, *rid);
			if (resv == NULL)
				return (NULL);

			start = resv->addr;
			end = resv->addr + (resv->size - 1);
			count = resv->size;
			rvp = &resv->res;
		}
		break;

	default:
		return 0;
	}

	rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
	     type, rid, start, end, count, flags);
	if (rvp)
		*rvp = rv;

	return (rv);
}
예제 #20
0
파일: gusc.c 프로젝트: ele7enxxh/dtrace-pf
static int
alloc_resource(sc_p scp)
{
	int i, base, lid, flags;
	device_t dev;

	flags = 0;
	if (isa_get_vendorid(scp->dev))
		lid = isa_get_logicalid(scp->dev);
	else {
		lid = LOGICALID_NOPNP;
		flags = device_get_flags(scp->dev);
	}
	switch(lid) {
	case LOGICALID_PCM:
	case LOGICALID_NOPNP:		/* XXX Non-PnP */
		if (lid == LOGICALID_NOPNP)
			base = isa_get_port(scp->dev);
		else
			base = 0;
		for (i = 0 ; i < sizeof(scp->io) / sizeof(*scp->io) ; i++) {
			if (scp->io[i] == NULL) {
				scp->io_rid[i] = i;
				if (base == 0)
					scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i],
									0, ~0, io_range[i], RF_ACTIVE);
				else
					scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i],
									base + io_offset[i],
									base + io_offset[i] + io_range[i] - 1
									, io_range[i], RF_ACTIVE);
				if (scp->io[i] == NULL)
					return (1);
				scp->io_alloced[i] = 0;
			}
		}
		if (scp->irq == NULL) {
			scp->irq_rid = 0;
			scp->irq = 
				bus_alloc_resource_any(scp->dev, SYS_RES_IRQ, 
						       &scp->irq_rid,
						       RF_ACTIVE|RF_SHAREABLE);
			if (scp->irq == NULL)
				return (1);
			scp->irq_alloced = 0;
		}
		for (i = 0 ; i < sizeof(scp->drq) / sizeof(*scp->drq) ; i++) {
			if (scp->drq[i] == NULL) {
				scp->drq_rid[i] = i;
				if (base == 0 || i == 0)
					scp->drq[i] = 
						bus_alloc_resource_any(
							scp->dev, SYS_RES_DRQ,
							&scp->drq_rid[i],
							RF_ACTIVE);
				else if ((flags & DV_F_DUAL_DMA) != 0)
					/* XXX The secondary drq is specified in the flag. */
					scp->drq[i] = bus_alloc_resource(scp->dev, SYS_RES_DRQ, &scp->drq_rid[i],
									 flags & DV_F_DRQ_MASK,
									 flags & DV_F_DRQ_MASK, 1, RF_ACTIVE);
				if (scp->drq[i] == NULL)
					return (1);
				scp->drq_alloced[i] = 0;
			}
		}
		break;
	case LOGICALID_OPL:
		if (scp->io[0] == NULL) {
			scp->io_rid[0] = 0;
			scp->io[0] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[0],
							0, ~0, io_range[0], RF_ACTIVE);
			if (scp->io[0] == NULL)
				return (1);
			scp->io_alloced[0] = 0;
		}
		break;
	case LOGICALID_MIDI:
		if (scp->io[0] == NULL) {
			scp->io_rid[0] = 0;
			scp->io[0] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[0],
							0, ~0, io_range[0], RF_ACTIVE);
			if (scp->io[0] == NULL)
				return (1);
			scp->io_alloced[0] = 0;
		}
		if (scp->irq == NULL) {
			/* The irq is shared with pcm audio. */
			dev = find_masterdev(scp);
			if (dev == NULL)
				return (1);
			scp->irq_rid = 0;
			scp->irq = BUS_ALLOC_RESOURCE(dev, NULL, SYS_RES_IRQ, &scp->irq_rid,
						      0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
			if (scp->irq == NULL)
				return (1);
			scp->irq_alloced = 0;
		}
		break;
	}
	return (0);
}
예제 #21
0
파일: ata_iobus.c 프로젝트: 2asoft/freebsd
struct resource *
ata_iobus_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 resource *res = NULL;
	int myrid;
	u_int *ofw_regs;

	ofw_regs = iobus_get_regs(dev);

	/*
	 * The reg array for the PSIM ata device has 6 start/size entries:
	 *  0 - unused
	 *  1/2/3 - unused
	 *  4/5/6 - primary command
	 *  7/8/9 - secondary command
	 *  10/11/12 - primary control
	 *  13/14/15 - secondary control
	 *  16/17/18 - primary/secondary dma registers, unimplemented
	 *
	 *  The resource values are calculated from these registers
	 */
	if (type == SYS_RES_IOPORT) {
		switch (*rid) {
		case ATA_IOADDR_RID:
			myrid = 0;
			start = ofw_regs[4];
			end = start + ATA_IOSIZE - 1;
			count = ATA_IOSIZE;
			res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
						 SYS_RES_MEMORY, &myrid,
						 start, end, count, flags);
			break;

		case ATA_CTLADDR_RID:
			myrid = 0;
			start = ofw_regs[10];
			end = start + ATA_CTLIOSIZE - 1;
			count = ATA_CTLIOSIZE;
			res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
						 SYS_RES_MEMORY, &myrid,
						 start, end, count, flags);
			break;

		case ATA_BMADDR_RID:
			/* DMA not properly supported by psim */
			break;
		}
		return (res);

	} else if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
		/*
		 * Pass this on to the parent
		 */
		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
					   SYS_RES_IRQ, rid, 0, ~0, 1, flags));

	} else {
		return (NULL);
	}
}
예제 #22
0
파일: uninorth.c 프로젝트: coyizumi/cs111
static struct resource *
unin_chip_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		unin_chip_softc *sc;
	int		needactivate;
	struct		resource *rv;
	struct		rman *rm;
	u_long		adjstart, adjend, adjcount;
	struct		unin_chip_devinfo *dinfo;
	struct		resource_list_entry *rle;

	sc = device_get_softc(bus);
	dinfo = device_get_ivars(child);

	needactivate = flags & RF_ACTIVE;
	flags &= ~RF_ACTIVE;

	switch (type) {
	case SYS_RES_MEMORY:
	case SYS_RES_IOPORT:
		rle = resource_list_find(&dinfo->udi_resources, SYS_RES_MEMORY,
					 *rid);
		if (rle == NULL) {
			device_printf(bus, "no rle for %s memory %d\n",
				      device_get_nameunit(child), *rid);
			return (NULL);
		}

		rle->end = rle->end - 1; /* Hack? */

		if (start < rle->start)
			adjstart = rle->start;
		else if (start > rle->end)
			adjstart = rle->end;
		else
			adjstart = start;

		if (end < rle->start)
			adjend = rle->start;
		else if (end > rle->end)
			adjend = rle->end;
		else
			adjend = end;

		adjcount = adjend - adjstart;

		rm = &sc->sc_mem_rman;
		break;

	case SYS_RES_IRQ:
		/* Check for passthrough from subattachments. */
		if (device_get_parent(child) != bus)
			return BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
						  type, rid, start, end, count,
						  flags);

		rle = resource_list_find(&dinfo->udi_resources, SYS_RES_IRQ,
		    *rid);
		if (rle == NULL) {
			if (dinfo->udi_ninterrupts >= 6) {
				device_printf(bus,
					      "%s has more than 6 interrupts\n",
					      device_get_nameunit(child));
				return (NULL);
			}
			resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
					  dinfo->udi_ninterrupts, start, start,
					  1);

			dinfo->udi_interrupts[dinfo->udi_ninterrupts] = start;
			dinfo->udi_ninterrupts++;
		}

		return (resource_list_alloc(&dinfo->udi_resources, bus, child,
					    type, rid, start, end, count,
					    flags));
	default:
		device_printf(bus, "unknown resource request from %s\n",
			      device_get_nameunit(child));
		return (NULL);
	}

	rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags,
				   child);
	if (rv == NULL) {
		device_printf(bus,
			      "failed to reserve resource %#lx - %#lx (%#lx)"
			      " for %s\n", adjstart, adjend, adjcount,
			      device_get_nameunit(child));
		return (NULL);
	}

	rman_set_rid(rv, *rid);

	if (needactivate) {
		if (bus_activate_resource(child, type, *rid, rv) != 0) {
                        device_printf(bus,
				      "failed to activate resource for %s\n",
				      device_get_nameunit(child));
			rman_release_resource(rv);
			return (NULL);
                }
        }

	return (rv);
}
예제 #23
0
파일: isa.c 프로젝트: MarginC/kame
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. We allow rid 0-1 for
	 * irq and drq, 0-3 for memory and 0-7 for ports which is
	 * sufficient for isapnp.
	 */
	int passthrough = (device_get_parent(child) != bus);
	int isdefault = (start == 0UL && end == ~0UL);
	struct isa_device* idev = DEVTOISA(child);
	struct resource_list *rl = &idev->id_resources;
	struct resource_list_entry *rle;
	u_long base, limit;

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

	/*
	 * Add the base, change default allocations to be between base and
	 * limit, and reject allocations if a resource type is not enabled.
	 */
	base = limit = 0;
	switch(type) {
	case SYS_RES_MEMORY:
		if (isa_mem_bt == NULL)
			return (NULL);
		base = isa_mem_base;
		limit = base + isa_mem_limit;
		break;
	case SYS_RES_IOPORT:
		if (isa_io_bt == NULL)
			return (NULL);
		base = isa_io_base;
		limit = base + isa_io_limit;
		break;
	case SYS_RES_IRQ:
		if (isdefault && passthrough)
			panic("isa_alloc_resource: cannot pass through default "
			    "irq allocation");
		if (!isdefault) {
			start = end = isa_route_intr_res(bus, start, end);
			if (start == 255)
				return (NULL);
		}
		break;
	default:
		panic("isa_alloc_resource: unsupported resource type %d", type);
	}
	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
		start = ulmin(start + base, limit);
		end = ulmin(end + base, limit);
	}
			
	/*
	 * This inlines a modified resource_list_alloc(); this is needed
	 * because the resources need to have offsets added to them, which
	 * cannot be done beforehand without patching the resource list entries
	 * (which is ugly).
	 */
	if (passthrough) {
		return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
		    type, rid, start, end, count, flags));
	}

	rle = resource_list_find(rl, type, *rid);
	if (rle == NULL)
		return (NULL);		/* no resource of that type/rid */

	if (rle->res != NULL)
		panic("isa_alloc_resource: resource entry is busy");

	if (isdefault) {
		start = rle->start;
		count = ulmax(count, rle->count);
		end = ulmax(rle->end, start + count - 1);
		switch (type) {
		case SYS_RES_MEMORY:
		case SYS_RES_IOPORT:
			start += base;
			end += base;
			if (!INRANGE(start, base, limit) ||
			    !INRANGE(end, base, limit))
				return (NULL);
			break;
		case SYS_RES_IRQ:
			start = end = isa_route_intr_res(bus, start, end);
			if (start == 255)
				return (NULL);
			break;
		}
	}

	rle->res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
	    type, rid, start, end, count, flags);

	/*
	 * Record the new range.
	 */
	if (rle->res != NULL) {
		rle->start = rman_get_start(rle->res) - base;
		rle->end = rman_get_end(rle->res) - base;
		rle->count = count;
	}

	return (rle->res);
}