Beispiel #1
0
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);
	}
}
Beispiel #2
0
struct resource *
atkbdc_isa_alloc_resource(device_t dev, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
	atkbdc_softc_t	*sc;
	
	sc = *(atkbdc_softc_t **)device_get_softc(dev);
	if (type == SYS_RES_IRQ && *rid == KBDC_RID_KBD && sc->irq != NULL)
		return (sc->irq);
	return (bus_generic_rl_alloc_resource(dev, child, type, rid, start,
	    end, count, flags));
}
Beispiel #3
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);
}