summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2011-05-30 19:24:29 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2011-05-30 19:24:29 +0000
commit50ce6ef4d3c1ab63ee77ac061b649fc8d4a9603f (patch)
tree6aa8cbf0648b20443bd95d6b155d304ef7de5f74 /sys/arch
parentaf1a5338237281a95fe158aeabc08c87f8528487 (diff)
Enable MSI on selected hardware. For now this means:
- Intel chipset supporting Pentium 4 or later. - Any AMD chipset made in this century. - Any NVIDIA chipset that has PCIe. Explicitly disable MSI on chipsets that connect to the CPU over HyperTransport. Enabling MSI on those systems is handled by the HyperTransport support code in our PCI subsystem.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/i386/pci/pci_machdep.c107
1 files changed, 106 insertions, 1 deletions
diff --git a/sys/arch/i386/pci/pci_machdep.c b/sys/arch/i386/pci/pci_machdep.c
index d22f875dc77..13f4e92a488 100644
--- a/sys/arch/i386/pci/pci_machdep.c
+++ b/sys/arch/i386/pci/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.61 2011/05/29 10:47:42 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.62 2011/05/30 19:24:28 kettenis Exp $ */
/* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */
/*-
@@ -195,6 +195,9 @@ void
pci_attach_hook(struct device *parent, struct device *self,
struct pcibus_attach_args *pba)
{
+ pci_chipset_tag_t pc = pba->pba_pc;
+ pcitag_t tag;
+ pcireg_t id, class;
#if NBIOS > 0
if (pba->pba_bus == 0)
@@ -204,6 +207,108 @@ pci_attach_hook(struct device *parent, struct device *self,
if (pba->pba_bus == 0)
printf(": configuration mode %d", pci_mode);
#endif
+
+ if (pba->pba_bus != 0)
+ return;
+
+ /*
+ * In order to decide whether the system supports MSI we look
+ * at the host bridge, which should be device 0 function 0 on
+ * bus 0. It is better to not enable MSI on systems that
+ * support it than the other way around, so be conservative
+ * here. So we don't enable MSI if we don't find a host
+ * bridge there. We also deliberately don't enable MSI on
+ * chipsets from low-end manifacturers like VIA and SiS.
+ */
+ tag = pci_make_tag(pc, 0, 0, 0);
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+ class = pci_conf_read(pc, tag, PCI_CLASS_REG);
+
+ if (PCI_CLASS(class) != PCI_CLASS_BRIDGE ||
+ PCI_SUBCLASS(class) != PCI_SUBCLASS_BRIDGE_HOST)
+ return;
+
+ switch (PCI_VENDOR(id)) {
+ case PCI_VENDOR_INTEL:
+ /*
+ * For Intel platforms, MSI support was introduced
+ * with the new Pentium 4 processor interrupt delivery
+ * mechanism, so we blacklist all PCI chipsets that
+ * support Pentium III and earlier CPUs.
+ */
+ switch (PCI_PRODUCT(id)) {
+ case PCI_PRODUCT_INTEL_PCMC: /* 82434LX/NX */
+ case PCI_PRODUCT_INTEL_82437FX:
+ case PCI_PRODUCT_INTEL_82437MX:
+ case PCI_PRODUCT_INTEL_82437VX:
+ case PCI_PRODUCT_INTEL_82439HX:
+ case PCI_PRODUCT_INTEL_82439TX:
+ case PCI_PRODUCT_INTEL_82440BX:
+ case PCI_PRODUCT_INTEL_82440BX_AGP:
+ case PCI_PRODUCT_INTEL_82440MX_HB:
+ case PCI_PRODUCT_INTEL_82441FX:
+ case PCI_PRODUCT_INTEL_82443BX:
+ case PCI_PRODUCT_INTEL_82443BX_AGP:
+ case PCI_PRODUCT_INTEL_82443BX_NOAGP:
+ case PCI_PRODUCT_INTEL_82443GX:
+ case PCI_PRODUCT_INTEL_82443LX:
+ case PCI_PRODUCT_INTEL_82443LX_AGP:
+ case PCI_PRODUCT_INTEL_82810_HB:
+ case PCI_PRODUCT_INTEL_82810E_HB:
+ case PCI_PRODUCT_INTEL_82815_HB:
+ case PCI_PRODUCT_INTEL_82820_HB:
+ case PCI_PRODUCT_INTEL_82830M_HB:
+ case PCI_PRODUCT_INTEL_82840_HB:
+ break;
+ default:
+ pba->pba_flags |= PCI_FLAGS_MSI_ENABLED;
+ break;
+ }
+ break;
+ case PCI_VENDOR_NVIDIA:
+ /*
+ * Since NVIDIA chipsets are completely undocumented,
+ * we have to make a guess here. We assume that all
+ * chipsets that support PCIe include support for MSI,
+ * since support for MSI is mandated by the PCIe
+ * standard.
+ */
+ switch (PCI_PRODUCT(id)) {
+ case PCI_PRODUCT_NVIDIA_NFORCE_PCHB:
+ case PCI_PRODUCT_NVIDIA_NFORCE2_PCHB:
+ break;
+ default:
+ pba->pba_flags |= PCI_FLAGS_MSI_ENABLED;
+ break;
+ }
+ break;
+ case PCI_VENDOR_AMD:
+ /*
+ * The AMD-750 and AMD-760 chipsets don't support MSI.
+ */
+ switch (PCI_PRODUCT(id)) {
+ case PCI_PRODUCT_AMD_SC751_SC:
+ case PCI_PRODUCT_AMD_761_PCHB:
+ case PCI_PRODUCT_AMD_762_PCHB:
+ break;
+ default:
+ pba->pba_flags |= PCI_FLAGS_MSI_ENABLED;
+ break;
+ }
+ break;
+ }
+
+ /*
+ * Don't enable MSI on a HyperTransport bus. In order to
+ * determine that bus 0 is a HyperTransport bus, we look at
+ * device 24 function 0, which is the HyperTransport
+ * host/primary interface integrated on most 64-bit AMD CPUs.
+ * If that device has a HyperTransport capability, bus 0 must
+ * be a HyperTransport bus and we disable MSI.
+ */
+ tag = pci_make_tag(pc, 0, 24, 0);
+ if (pci_get_capability(pc, tag, PCI_CAP_HT, NULL, NULL))
+ pba->pba_flags &= ~PCI_FLAGS_MSI_ENABLED;
}
int