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, 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(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); }
int pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) { pci_intr_pin_t pin = pa->pa_intrpin; pci_intr_line_t line = pa->pa_intrline; pci_chipset_tag_t ipc, pc = pa->pa_pc; #if NIOAPIC > 0 || NACPICA > 0 pci_intr_pin_t rawpin = pa->pa_rawintrpin; int bus, dev, func; #endif for (ipc = pc; ipc != NULL; ipc = ipc->pc_super) { if ((ipc->pc_present & PCI_OVERRIDE_INTR_MAP) == 0) continue; return (*ipc->pc_ov->ov_intr_map)(ipc->pc_ctx, pa, ihp); } if (pin == 0) { /* No IRQ used. */ goto bad; } *ihp = 0; if (pin > PCI_INTERRUPT_PIN_MAX) { aprint_normal("pci_intr_map: bad interrupt pin %d\n", pin); goto bad; } #if NIOAPIC > 0 || NACPICA > 0 KASSERT(rawpin >= PCI_INTERRUPT_PIN_A); KASSERT(rawpin <= PCI_INTERRUPT_PIN_D); pci_decompose_tag(pc, pa->pa_tag, &bus, &dev, &func); if (mp_busses != NULL) { /* * Note: PCI_INTERRUPT_PIN_A == 1 where intr_find_mpmapping * wants pci bus_pin encoding which uses INT_A == 0. */ if (intr_find_mpmapping(bus, (dev << 2) | (rawpin - PCI_INTERRUPT_PIN_A), ihp) == 0) { if (APIC_IRQ_LEGACY_IRQ(*ihp) == 0) *ihp |= line; return 0; } /* * No explicit PCI mapping found. This is not fatal, * we'll try the ISA (or possibly EISA) mappings next. */ } #endif /* * Section 6.2.4, `Miscellaneous Functions', says that 255 means * `unknown' or `no connection' on a PC. We assume that a device with * `no connection' either doesn't have an interrupt (in which case the * pin number should be 0, and would have been noticed above), or * wasn't configured by the BIOS (in which case we punt, since there's * no real way we can know how the interrupt lines are mapped in the * hardware). * * XXX * Since IRQ 0 is only used by the clock, and we can't actually be sure * that the BIOS did its job, we also recognize that as meaning that * the BIOS has not configured the device. */ if (line == 0 || line == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) { aprint_normal("pci_intr_map: no mapping for pin %c (line=%02x)\n", '@' + pin, line); goto bad; } else { if (line >= NUM_LEGACY_IRQS) { aprint_normal("pci_intr_map: bad interrupt line %d\n", line); goto bad; } if (line == 2) { aprint_normal("pci_intr_map: changed line 2 to line 9\n"); line = 9; } } #if NIOAPIC > 0 || NACPICA > 0 if (mp_busses != NULL) { if (intr_find_mpmapping(mp_isa_bus, line, ihp) == 0) { if ((*ihp & 0xff) == 0) *ihp |= line; return 0; } #if NEISA > 0 if (intr_find_mpmapping(mp_eisa_bus, line, ihp) == 0) { if ((*ihp & 0xff) == 0) *ihp |= line; return 0; } #endif aprint_normal("pci_intr_map: bus %d dev %d func %d pin %d; line %d\n", bus, dev, func, pin, line); aprint_normal("pci_intr_map: no MP mapping found\n"); } #endif *ihp = line; return 0; bad: *ihp = -1; return 1; }