Ejemplo n.º 1
0
int
puc_bus_setup_intr(device_t dev, device_t child, struct resource *res,
    int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep)
{
	struct puc_port *port;
	struct puc_softc *sc;
	device_t originator;
	int i, isrc, serdev;

	sc = device_get_softc(dev);

	/* 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 (cookiep == NULL || res != port->p_ires)
		return (EINVAL);
	/* We demand that serdev devices use filter_only interrupts. */
	if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL)
		return (ENXIO);
	if (rman_get_device(port->p_ires) != originator)
		return (ENXIO);

	/*
	 * Have non-serdev ports handled by the bus implementation. It
	 * supports multiple handlers for a single interrupt as it is,
	 * so we wouldn't add value if we did it ourselves.
	 */
	serdev = 0;
	if (port->p_type == PUC_TYPE_SERIAL) {
		i = 0, isrc = SER_INT_OVERRUN;
		while (i < PUC_ISRCCNT) {
			port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc);
			if (port->p_ihsrc[i] != NULL)
				serdev = 1;
			i++, isrc <<= 1;
		}
	}
	if (!serdev)
		return (BUS_SETUP_INTR(device_get_parent(dev), originator,
		    sc->sc_ires, flags, filt, ihand, arg, cookiep));

	sc->sc_serdevs |= 1UL << (port->p_nr - 1);

	port->p_hasintr = 1;
	port->p_iharg = arg;

	*cookiep = port;
	return (0);
}
Ejemplo n.º 2
0
/**
 * Open an EROM table for reading.
 * 
 * @param[out] erom On success, will be populated with a valid EROM
 * read state.
 * @param r An active resource mapping the EROM core.
 * @param offset Offset of the EROM core within @p resource.
 *
 * @retval 0 success
 * @retval non-zero if the erom table could not be opened.
 */
int
bcma_erom_open(struct bcma_erom *erom, struct resource *r, bus_size_t offset)
{
	/* Initialize the EROM reader */
	erom->dev = rman_get_device(r);
	erom->r = r;
	erom->start = offset + BCMA_EROM_TABLE_START;
	erom->offset = 0;

	return (0);
}
Ejemplo n.º 3
0
struct resource *
puc_bus_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 puc_port *port;
	struct resource *res;
	device_t assigned, originator;
	int error;

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

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

	if (rid == NULL || *rid != 0)
		return (NULL);

	/* We only support default allocations. */
	if (start != 0UL || end != ~0UL)
		return (NULL);

	if (type == port->p_bar->b_type)
		res = port->p_rres;
	else if (type == SYS_RES_IRQ)
		res = port->p_ires;
	else
		return (NULL);

	if (res == NULL)
		return (NULL);

	assigned = rman_get_device(res);
	if (assigned == NULL)	/* Not allocated */
		rman_set_device(res, originator);
	else if (assigned != originator)
		return (NULL);

	if (flags & RF_ACTIVE) {
		error = rman_activate_resource(res);
		if (error) {
			if (assigned == NULL)
				rman_set_device(res, NULL);
			return (NULL);
		}
	}

	return (res);
}
Ejemplo n.º 4
0
t_Error
XX_SetIntr(uintptr_t irq, t_Isr *f_Isr, t_Handle handle)
{
	device_t dev;
	struct resource *r;
	unsigned int flags;
	int err;

	r = (struct resource *)irq;
	dev = rman_get_device(r);
	irq = rman_get_start(r);

	/* Handle preallocated interrupts */
	if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) {
		if (XX_IntrInfo[irq].handler != NULL)
			return (E_BUSY);

		XX_IntrInfo[irq].handler = f_Isr;
		XX_IntrInfo[irq].arg = handle;

		return (E_OK);
	}

	flags = INTR_TYPE_NET | INTR_MPSAFE;

	/* BMAN/QMAN Portal interrupts must be exlusive */
	if (XX_IsPortalIntr(irq))
		flags |= INTR_EXCL;

	err = bus_setup_intr(dev, r, flags, NULL, f_Isr, handle,
		    &XX_IntrInfo[irq].cookie);
	if (err)
		goto finish;

	/*
	 * XXX: Bind FMan IRQ to CPU0. Current interrupt subsystem directs each
	 * interrupt to all CPUs. Race between an interrupt assertion and
	 * masking may occur and interrupt handler may be called multiple times
	 * per one interrupt. FMan doesn't support such a situation. Workaround
	 * is to bind FMan interrupt to one CPU0 only.
	 */
#ifdef SMP
	if (XX_FmanNeedsIntrFix(irq))
		err = powerpc_bind_intr(irq, 0);
#endif
finish:
	return (err);
}
Ejemplo n.º 5
0
int
puc_bus_teardown_intr(device_t dev, device_t child, struct resource *res,
    void *cookie)
{
	struct puc_port *port;
	struct puc_softc *sc;
	device_t originator;
	int i;

	sc = device_get_softc(dev);

	/* 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 (res != port->p_ires)
		return (EINVAL);
	if (rman_get_device(port->p_ires) != originator)
		return (ENXIO);

	if (!port->p_hasintr)
		return (BUS_TEARDOWN_INTR(device_get_parent(dev), originator,
		    sc->sc_ires, cookie));

	if (cookie != port)
		return (EINVAL);

	port->p_hasintr = 0;
	port->p_iharg = NULL;

	for (i = 0; i < PUC_ISRCCNT; i++)
		port->p_ihsrc[i] = NULL;

	return (0);
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
t_Error
XX_FreeIntr(uintptr_t irq)
{
	device_t dev;
	struct resource *r;

	r = (struct resource *)irq;
	dev = rman_get_device(r);
	irq = rman_get_start(r);

	/* Handle preallocated interrupts */
	if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) {
		if (XX_IntrInfo[irq].handler == NULL)
			return (E_INVALID_STATE);

		XX_IntrInfo[irq].handler = NULL;
		XX_IntrInfo[irq].arg = NULL;

		return (E_OK);
	}

	return (bus_teardown_intr(dev, r, XX_IntrInfo[irq].cookie));
}