summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2011-05-21 15:58:28 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2011-05-21 15:58:28 +0000
commit9d73e2d0fca8dd5b0b79cfd3b5fa85318623e73c (patch)
treeb00d61eb37411d005dabcda46d1e46d7af1c202d /sys/arch
parentb0d2fea50996d8267d0cbc0aa0c2835e25b0a85a (diff)
First stab at suporting Message Signaled Interrupts on amd64. Unfortunately
this code differs somewhat from the i386 code because the amd64 interrupt subsystem is quite different. Still disabled like on i386.
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);