int vbus_intr_map(int node, int ino, uint64_t *sysino) { int *imap = NULL, nimap; int *reg = NULL, nreg; int *imap_mask; int parent; int address_cells, interrupt_cells; uint64_t devhandle; uint64_t devino; int len; int err; parent = OF_parent(node); address_cells = getpropint(parent, "#address-cells", 2); interrupt_cells = getpropint(parent, "#interrupt-cells", 1); KASSERT(interrupt_cells == 1); len = OF_getproplen(parent, "interrupt-map-mask"); if (len < (address_cells + interrupt_cells) * sizeof(int)) return (-1); imap_mask = malloc(len, M_DEVBUF, M_NOWAIT); if (imap_mask == NULL) return (-1); if (OF_getprop(parent, "interrupt-map-mask", imap_mask, len) != len) return (-1); getprop(parent, "interrupt-map", sizeof(int), &nimap, (void **)&imap); getprop(node, "reg", sizeof(*reg), &nreg, (void **)®); if (nreg < address_cells) return (-1); while (nimap >= address_cells + interrupt_cells + 2) { if (vbus_cmp_cells(imap, reg, imap_mask, address_cells) && vbus_cmp_cells(&imap[address_cells], &ino, &imap_mask[address_cells], interrupt_cells)) { node = imap[address_cells + interrupt_cells]; devino = imap[address_cells + interrupt_cells + 1]; free(reg, M_DEVBUF, 0); reg = NULL; getprop(node, "reg", sizeof(*reg), &nreg, (void **)®); devhandle = reg[0] & 0x0fffffff; err = hv_intr_devino_to_sysino(devhandle, devino, sysino); if (err != H_EOK) return (-1); KASSERT(*sysino == INTVEC(*sysino)); return (0); } imap += address_cells + interrupt_cells + 2; nimap -= address_cells + interrupt_cells + 2; } return (-1); }
static int vnex_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt,driver_intr_t *intr, void *arg, void **cookiep) { uint64_t reg, nreg; uint64_t ihdl, cfg; uint64_t ino, nino; int error, cpuid; if (res == NULL) panic("%s: NULL interrupt resource!", __func__); if ((error = bus_get_resource(dev, SYS_RES_MEMORY, 0, ®, &nreg))) goto fail; if ((error = bus_get_resource(child, SYS_RES_IRQ, 0, &ino, &nino))) goto fail; cfg = SUN4V_REG_SPEC2CFG_HDL(reg); if (hv_intr_devino_to_sysino(cfg, (uint32_t)ino, &ihdl) != H_EOK) { error = ENXIO; goto fail; } cpuid = 0; if (hv_intr_settarget(ihdl, cpuid) != H_EOK) { error = ENXIO; goto fail; } if (hv_intr_setstate(ihdl, HV_INTR_IDLE_STATE) != H_EOK) { error = ENXIO; goto fail; } if (hv_intr_setenabled(ihdl, HV_INTR_ENABLED) != H_EOK) { error = ENXIO; goto fail; } if ((rman_get_flags(res) & RF_SHAREABLE) == 0) flags |= INTR_EXCL; /* We depend here on rman_activate_resource() being idempotent. */ if ((error = rman_activate_resource(res))) goto fail; error = inthand_add(device_get_nameunit(child), ihdl, filt, intr, arg, flags, cookiep); printf("inthandler added\n"); fail: return (error); }