void * pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, int (*func)(void *), void *arg, char *what) { int pin, irq; struct pic *pic; pic = &i8259_pic; pin = irq = ih; #if NIOAPIC > 0 if (ih & APIC_INT_VIA_APIC) { pic = (struct pic *)ioapic_find(APIC_IRQ_APIC(ih)); if (pic == NULL) { printf("pci_intr_establish: bad ioapic %d\n", APIC_IRQ_APIC(ih)); return NULL; } pin = APIC_IRQ_PIN(ih); irq = APIC_IRQ_LEGACY_IRQ(ih); if (irq < 0 || irq >= NUM_LEGACY_IRQS) irq = -1; } #endif return intr_establish(irq, pic, pin, IST_LEVEL, level, func, arg, what); }
void * pci_intr_establish_xname(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, int (*func)(void *), void *arg, const char *xname) { int pin, irq; struct pic *pic; #if NIOAPIC > 0 struct ioapic_softc *ioapic; #endif bool mpsafe; pci_chipset_tag_t ipc; for (ipc = pc; ipc != NULL; ipc = ipc->pc_super) { if ((ipc->pc_present & PCI_OVERRIDE_INTR_ESTABLISH) == 0) continue; return (*ipc->pc_ov->ov_intr_establish)(ipc->pc_ctx, pc, ih, level, func, arg); } if (INT_VIA_MSI(ih)) { if (MSI_INT_IS_MSIX(ih)) return x86_pci_msix_establish(pc, ih, level, func, arg, xname); else return x86_pci_msi_establish(pc, ih, level, func, arg, xname); } pic = &i8259_pic; pin = irq = APIC_IRQ_LEGACY_IRQ(ih); mpsafe = ((ih & MPSAFE_MASK) != 0); #if NIOAPIC > 0 if (ih & APIC_INT_VIA_APIC) { ioapic = ioapic_find(APIC_IRQ_APIC(ih)); if (ioapic == NULL) { aprint_normal("pci_intr_establish: bad ioapic %d\n", APIC_IRQ_APIC(ih)); return NULL; } pic = &ioapic->sc_pic; pin = APIC_IRQ_PIN(ih); irq = APIC_IRQ_LEGACY_IRQ(ih); if (irq < 0 || irq >= NUM_LEGACY_IRQS) irq = -1; } #endif return intr_establish_xname(irq, pic, pin, IST_LEVEL, level, func, arg, mpsafe, xname); }
void * pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, int (*func)(void *), void *arg, const char *what) { int pin, irq; int bus, dev; pcitag_t tag = ih.tag; struct pic *pic; if (ih.line & APIC_INT_VIA_MSG) { return intr_establish(-1, &msi_pic, tag, IST_PULSE, level, func, arg, what); } pci_decompose_tag(pc, ih.tag, &bus, &dev, NULL); #if NACPIPRT > 0 acpiprt_route_interrupt(bus, dev, ih.pin); #endif pic = &i8259_pic; pin = irq = ih.line; #if NIOAPIC > 0 if (ih.line & APIC_INT_VIA_APIC) { pic = (struct pic *)ioapic_find(APIC_IRQ_APIC(ih.line)); if (pic == NULL) { printf("pci_intr_establish: bad ioapic %d\n", APIC_IRQ_APIC(ih.line)); return NULL; } pin = APIC_IRQ_PIN(ih.line); irq = APIC_IRQ_LEGACY_IRQ(ih.line); if (irq < 0 || irq >= NUM_LEGACY_IRQS) irq = -1; } #endif return intr_establish(irq, pic, pin, IST_LEVEL, level, func, arg, what); }
void * pci_intr_establish(pci_chipset_tag_t pcitag, pci_intr_handle_t intrh, int level, int (*func)(void *), void *arg) { char evname[16]; #if NIOAPIC > 0 struct ioapic_softc *pic; if (intrh.pirq & APIC_INT_VIA_APIC) { pic = ioapic_find(APIC_IRQ_APIC(intrh.pirq)); if (pic == NULL) { printf("pci_intr_establish: bad ioapic %d\n", APIC_IRQ_APIC(intrh.pirq)); return NULL; } snprintf(evname, sizeof(evname), "%s pin %d", device_xname(pic->sc_dev), APIC_IRQ_PIN(intrh.pirq)); } else #endif snprintf(evname, sizeof(evname), "irq%d", intrh.pirq); return (void *)pirq_establish(intrh.pirq & 0xff, intrh.evtch, func, arg, level, evname); }
const char *pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih) { static char buf[64]; #if NIOAPIC > 0 struct ioapic_softc *pic; if (ih.pirq & APIC_INT_VIA_APIC) { pic = ioapic_find(APIC_IRQ_APIC(ih.pirq)); if (pic == NULL) { printf("pci_intr_string: bad ioapic %d\n", APIC_IRQ_APIC(ih.pirq)); return NULL; } snprintf(buf, 64, "%s pin %d, event channel %d", device_xname(pic->sc_dev), APIC_IRQ_PIN(ih.pirq), ih.evtch); return buf; } #endif snprintf(buf, 64, "irq %d, event channel %d", ih.pirq, ih.evtch); return buf; }
void * isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level, int (*ih_fun)(void *), void *ih_arg) { struct pic *pic; int pin; #if NIOAPIC > 0 int mpih; struct ioapic_softc *ioapic; #endif pin = irq; pic = &i8259_pic; #if NIOAPIC > 0 if (mp_busses != NULL) { if (intr_find_mpmapping(mp_isa_bus, irq, &mpih) == 0 || intr_find_mpmapping(mp_eisa_bus, irq, &mpih) == 0) { if (!APIC_IRQ_ISLEGACY(mpih)) { pin = APIC_IRQ_PIN(mpih); ioapic = ioapic_find(APIC_IRQ_APIC(mpih)); if (ioapic == NULL) { printf("isa_intr_establish: " "unknown apic %d\n", APIC_IRQ_APIC(mpih)); return NULL; } pic = &ioapic->sc_pic; } } else printf("isa_intr_establish: no MP mapping found\n"); } #endif return intr_establish(irq, pic, pin, type, level, ih_fun, ih_arg, false); }
/* * can't use bus_space_xxx as we don't have a bus handle ... */ void ioapic_attach(struct device *parent, struct device *self, void *aux) { struct ioapic_softc *sc = (struct ioapic_softc *)self; struct apic_attach_args *aaa = (struct apic_attach_args *) aux; int apic_id; bus_space_handle_t bh; u_int32_t ver_sz; int i; sc->sc_flags = aaa->flags; sc->sc_apicid = aaa->apic_id; printf(" apid %d", aaa->apic_id); if (ioapic_find(aaa->apic_id) != NULL) { printf(", duplicate apic id (ignored)\n"); return; } ioapic_add(sc); printf(" pa 0x%lx", aaa->apic_address); if (x86_mem_add_mapping(aaa->apic_address, PAGE_SIZE, 0, &bh) != 0) { printf(", map failed\n"); return; } sc->sc_reg = (volatile u_int32_t *)(bh + IOAPIC_REG); sc->sc_data = (volatile u_int32_t *)(bh + IOAPIC_DATA); sc->sc_pic.pic_type = PIC_IOAPIC; mtx_init(&sc->sc_pic.pic_mutex, IPL_NONE); sc->sc_pic.pic_hwmask = ioapic_hwmask; sc->sc_pic.pic_hwunmask = ioapic_hwunmask; sc->sc_pic.pic_addroute = ioapic_addroute; sc->sc_pic.pic_delroute = ioapic_delroute; sc->sc_pic.pic_edge_stubs = ioapic_edge_stubs; sc->sc_pic.pic_level_stubs = ioapic_level_stubs; ver_sz = ioapic_read(sc, IOAPIC_VER); sc->sc_apic_vers = (ver_sz & IOAPIC_VER_MASK) >> IOAPIC_VER_SHIFT; sc->sc_apic_sz = (ver_sz & IOAPIC_MAX_MASK) >> IOAPIC_MAX_SHIFT; sc->sc_apic_sz++; if (aaa->apic_vecbase != -1) sc->sc_apic_vecbase = aaa->apic_vecbase; else { /* * XXX this assumes ordering of ioapics in the table. * Only needed for broken BIOS workaround (see mpbios.c) */ sc->sc_apic_vecbase = ioapic_vecbase; ioapic_vecbase += sc->sc_apic_sz; } if (mp_verbose) { printf(", %s mode", aaa->flags & IOAPIC_PICMODE ? "PIC" : "virtual wire"); } printf(", version %x, %d pins\n", sc->sc_apic_vers, sc->sc_apic_sz); apic_id = (ioapic_read(sc, IOAPIC_ID) & IOAPIC_ID_MASK) >> IOAPIC_ID_SHIFT; sc->sc_pins = malloc(sizeof(struct ioapic_pin) * sc->sc_apic_sz, M_DEVBUF, M_WAITOK); for (i=0; i<sc->sc_apic_sz; i++) { sc->sc_pins[i].ip_next = NULL; sc->sc_pins[i].ip_map = NULL; sc->sc_pins[i].ip_vector = 0; sc->sc_pins[i].ip_type = IST_NONE; } /* * In case the APIC is not initialized to the correct ID * do it now. * Maybe we should record the original ID for interrupt * mapping later ... */ if (apic_id != sc->sc_apicid) { printf("%s: misconfigured as apic %d", sc->sc_pic.pic_dev.dv_xname, apic_id); ioapic_set_id(sc); } #if 0 /* output of this was boring. */ if (mp_verbose) for (i=0; i<sc->sc_apic_sz; i++) ioapic_print_redir(sc, "boot", i); #endif }