summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/amd64/include/i82093var.h3
-rw-r--r--sys/arch/amd64/include/pci_machdep.h3
-rw-r--r--sys/arch/amd64/include/pic.h6
-rw-r--r--sys/arch/amd64/pci/pci_machdep.c84
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, &reg) == 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);