diff options
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/amd64/include/i82093var.h | 3 | ||||
-rw-r--r-- | sys/arch/amd64/include/pci_machdep.h | 3 | ||||
-rw-r--r-- | sys/arch/amd64/include/pic.h | 6 | ||||
-rw-r--r-- | sys/arch/amd64/pci/pci_machdep.c | 84 |
4 files changed, 91 insertions, 5 deletions
diff --git a/sys/arch/amd64/include/i82093var.h b/sys/arch/amd64/include/i82093var.h index 45b3eeb24e2..41b16842da6 100644 --- a/sys/arch/amd64/include/i82093var.h +++ b/sys/arch/amd64/include/i82093var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: i82093var.h,v 1.3 2011/03/23 16:54:34 pirofti Exp $ */ +/* $OpenBSD: i82093var.h,v 1.4 2011/05/21 15:58:27 kettenis Exp $ */ /* $NetBSD: i82093var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ /*- @@ -69,6 +69,7 @@ struct ioapic_softc { */ #define APIC_INT_VIA_APIC 0x10000000 +#define APIC_INT_VIA_MSG 0x20000000 #define APIC_INT_APIC_MASK 0x00ff0000 #define APIC_INT_APIC_SHIFT 16 #define APIC_INT_PIN_MASK 0x0000ff00 diff --git a/sys/arch/amd64/include/pci_machdep.h b/sys/arch/amd64/include/pci_machdep.h index 4b716578e93..75922d1e57c 100644 --- a/sys/arch/amd64/include/pci_machdep.h +++ b/sys/arch/amd64/include/pci_machdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_machdep.h,v 1.17 2011/01/04 21:17:49 kettenis Exp $ */ +/* $OpenBSD: pci_machdep.h,v 1.18 2011/05/21 15:58:27 kettenis Exp $ */ /* $NetBSD: pci_machdep.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ /* @@ -81,6 +81,7 @@ int pci_conf_size(pci_chipset_tag_t, pcitag_t); pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int); void pci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t); +int pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); int pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t); void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, diff --git a/sys/arch/amd64/include/pic.h b/sys/arch/amd64/include/pic.h index f880c524ac8..580738b03cc 100644 --- a/sys/arch/amd64/include/pic.h +++ b/sys/arch/amd64/include/pic.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pic.h,v 1.5 2005/05/31 09:34:23 art Exp $ */ +/* $OpenBSD: pic.h,v 1.6 2011/05/21 15:58:27 kettenis Exp $ */ /* $NetBSD: pic.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ #ifndef _X86_PIC_H @@ -35,9 +35,11 @@ struct pic { #define PIC_I8259 0 #define PIC_IOAPIC 1 #define PIC_LAPIC 2 -#define PIC_SOFT 3 +#define PIC_MSI 3 +#define PIC_SOFT 4 extern struct pic i8259_pic; extern struct pic local_pic; +extern struct pic msi_pic; extern struct pic softintr_pic; #endif diff --git a/sys/arch/amd64/pci/pci_machdep.c b/sys/arch/amd64/pci/pci_machdep.c index 8cf4464e96c..ec795d669d8 100644 --- a/sys/arch/amd64/pci/pci_machdep.c +++ b/sys/arch/amd64/pci/pci_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_machdep.c,v 1.43 2011/04/22 15:02:35 kettenis Exp $ */ +/* $OpenBSD: pci_machdep.c,v 1.44 2011/05/21 15:58:27 kettenis Exp $ */ /* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */ /*- @@ -252,6 +252,55 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) PCI_CONF_UNLOCK(); } +void msi_hwmask(struct pic *, int); +void msi_hwunmask(struct pic *, int); +void msi_setup(struct pic *, struct cpu_info *, int, int, int); + +struct pic msi_pic = { + {0, {NULL}, NULL, 0, "msi", NULL, 0, 0}, + PIC_MSI, +#ifdef MULTIPROCESSOR + {}, +#endif + msi_hwmask, + msi_hwunmask, + msi_setup, + msi_setup, + NULL, + ioapic_edge_stubs +}; + +void +msi_hwmask(struct pic *pic, int pin) +{ +} + +void +msi_hwunmask(struct pic *pic, int pin) +{ +} + +void +msi_setup(struct pic *pic, struct cpu_info *ci, int pin, int idtvec, int type) +{ +} + +int +pci_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp) +{ + pci_chipset_tag_t pc = pa->pa_pc; + pcitag_t tag = pa->pa_tag; + + if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 || + pci_get_capability(pc, tag, PCI_CAP_MSI, NULL, NULL) == 0) + return 1; + + ihp->tag = tag; + ihp->line = APIC_INT_VIA_MSG; + ihp->pin = 0; + return 0; +} + int pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { @@ -360,6 +409,9 @@ pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih) if (ih.line == 0) panic("pci_intr_string: bogus handle 0x%x", ih.line); + if (ih.line & APIC_INT_VIA_MSG) + return ("msi"); + #if NIOAPIC > 0 if (ih.line & APIC_INT_VIA_APIC) snprintf(irqstr, sizeof(irqstr), "apic %d int %d", @@ -384,8 +436,38 @@ pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, { int pin, irq; int bus, dev; + pcitag_t tag = ih.tag; struct pic *pic; + if (ih.line & APIC_INT_VIA_MSG) { + struct intrhand *ih; + struct intrsource *source; + pcireg_t reg; + int off, vec; + + if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, ®) == 0) + panic("%s: no msi capability", __func__); + + ih = intr_establish(-1, &msi_pic, tag, IST_PULSE, level, + func, arg, what); + if (ih == NULL) + return (NULL); + + source = ih->ih_cpu->ci_isources[ih->ih_slot]; + vec = source->is_idtvec; + + if (reg & PCI_MSI_MC_C64) { + pci_conf_write(pc, tag, off + PCI_MSI_MA, 0xfee00000); + pci_conf_write(pc, tag, off + PCI_MSI_MAU32, 0); + pci_conf_write(pc, tag, off + PCI_MSI_MD64, vec); + } else { + pci_conf_write(pc, tag, off + PCI_MSI_MA, 0xfee00000); + pci_conf_write(pc, tag, off + PCI_MSI_MD32, vec); + } + pci_conf_write(pc, tag, off, reg | PCI_MSI_MC_MSIE); + return (ih); + } + pci_decompose_tag(pc, ih.tag, &bus, &dev, NULL); #if NACPIPRT > 0 acpiprt_route_interrupt(bus, dev, ih.pin); |