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); }
/** * 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); }
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); }
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); }
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); }
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); }
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)); }