static int ofw_pcibus_assign_interrupt(device_t dev, device_t child) { ofw_pci_intr_t intr; int isz; isz = OF_getprop(ofw_bus_get_node(child), "interrupts", &intr, sizeof(intr)); if (isz != sizeof(intr)) { /* No property; our best guess is the intpin. */ intr = pci_get_intpin(child); #ifndef SUN4V } else if (intr >= 255) { /* * A fully specified interrupt (including IGN), as present on * SPARCengine Ultra AX and E450. Extract the INO and return * it. */ return (INTINO(intr)); #endif } /* * If we got intr from a property, it may or may not be an intpin. * For on-board devices, it frequently is not, and is completely out * of the valid intpin range. For PCI slots, it hopefully is, * otherwise we will have trouble interfacing with non-OFW buses * such as cardbus. * Since we cannot tell which it is without violating layering, we * will always use the route_interrupt method, and treat exceptions * on the level they become apparent. */ return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); }
void * vbus_intr_establish(bus_space_tag_t t, int ihandle, int level, int (*handler)(void *), void *arg, void (*fastvec)(void) /* ignored */) { uint64_t sysino = INTVEC(ihandle); struct intrhand *ih; int ino; int err; DPRINTF(VBUS_INTR, ("vbus_intr_establish()\n")); ino = INTINO(ihandle); ih = intrhand_alloc(); ih->ih_ivec = ihandle; ih->ih_fun = handler; ih->ih_arg = arg; ih->ih_pil = level; ih->ih_number = ino; ih->ih_pending = 0; intr_establish(ih->ih_pil, level != IPL_VM, ih); ih->ih_ack = vbus_intr_ack; err = hv_intr_settarget(sysino, cpus->ci_cpuid); if (err != H_EOK) { printf("hv_intr_settarget(%lu, %u) failed - err = %d\n", (long unsigned int)sysino, cpus->ci_cpuid, err); return (NULL); } /* Clear pending interrupts. */ err = hv_intr_setstate(sysino, INTR_IDLE); if (err != H_EOK) { printf("hv_intr_setstate(%lu, INTR_IDLE) failed - err = %d\n", (long unsigned int)sysino, err); return (NULL); } err = hv_intr_setenabled(sysino, INTR_ENABLED); if (err != H_EOK) { printf("hv_intr_setenabled(%lu) failed - err = %d\n", (long unsigned int)sysino, err); return (NULL); } return (ih); }
struct resource * fhc_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_list_entry *rle; struct fhc_devinfo *fdi; struct fhc_softc *sc; struct resource *res; bus_addr_t coffset; bus_addr_t cend; bus_addr_t phys; int isdefault; uint32_t map; uint32_t vec; int i; isdefault = (start == 0UL && end == ~0UL); res = NULL; sc = device_get_softc(bus); switch (type) { case SYS_RES_IRQ: if (!isdefault || count != 1 || *rid < FHC_FANFAIL || *rid > FHC_TOD) break; map = bus_space_read_4(sc->sc_bt[*rid], sc->sc_bh[*rid], FHC_IMAP); vec = INTINO(map) | (sc->sc_ign << INTMAP_IGN_SHIFT); bus_space_write_4(sc->sc_bt[*rid], sc->sc_bh[*rid], FHC_IMAP, vec); bus_space_read_4(sc->sc_bt[*rid], sc->sc_bh[*rid], FHC_IMAP); res = bus_generic_alloc_resource(bus, child, type, rid, vec, vec, 1, flags); if (res != NULL) rman_set_rid(res, *rid); break; case SYS_RES_MEMORY: fdi = device_get_ivars(child); rle = resource_list_find(&fdi->fdi_rl, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("fhc_alloc_resource: resource entry is busy"); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } for (i = 0; i < sc->sc_nrange; i++) { coffset = sc->sc_ranges[i].coffset; cend = coffset + sc->sc_ranges[i].size - 1; if (start >= coffset && end <= cend) { start -= coffset; end -= coffset; phys = sc->sc_ranges[i].poffset | ((bus_addr_t)sc->sc_ranges[i].pspace << 32); res = bus_generic_alloc_resource(bus, child, type, rid, phys + start, phys + end, count, flags); rle->res = res; break; } } break; default: break; } return (res); }