summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2010-02-09 19:36:06 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2010-02-09 19:36:06 +0000
commit5ec303afa34da1dad80ec11cf4e02ff19e5e2ccc (patch)
tree470568f3138c78ba3cfee38ef68c9129d7b476f8
parent13bd74560baae4e828c8bccda35ddca3be220c8a (diff)
Switching the strange VIA VT8251 PCIE host bridge into a PCI-PCI bridge
didn't quite work since the bridge seems to end up largely unconfigured, and our PCI resource configuration code isn't quite smart enough (yet) to fix things up. So instead switch it only into PCI-PCI bridge mode long enough to snoop the bus number, and attach pci(4) using that number. This is probably safer anyway, since ACPI may not like us switching things around behind its back. Fixes PR 6253 & 6304.
-rw-r--r--sys/arch/amd64/pci/pchb.c50
-rw-r--r--sys/arch/i386/pci/pchb.c34
2 files changed, 61 insertions, 23 deletions
diff --git a/sys/arch/amd64/pci/pchb.c b/sys/arch/amd64/pci/pchb.c
index 6b13b95ff59..dee6033b0bd 100644
--- a/sys/arch/amd64/pci/pchb.c
+++ b/sys/arch/amd64/pci/pchb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pchb.c,v 1.31 2009/11/23 15:33:37 deraadt Exp $ */
+/* $OpenBSD: pchb.c,v 1.32 2010/02/09 19:36:05 kettenis Exp $ */
/* $NetBSD: pchb.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */
/*
* Copyright (c) 2000 Michael Shalayeff
@@ -66,6 +66,7 @@
#include <dev/pci/pcidevs.h>
#include <dev/pci/agpvar.h>
+#include <dev/pci/ppbreg.h>
#include <dev/rndvar.h>
@@ -143,8 +144,12 @@ pchbattach(struct device *parent, struct device *self, void *aux)
{
struct pchb_softc *sc = (struct pchb_softc *)self;
struct pci_attach_args *pa = aux;
- pcireg_t bcreg;
+ struct pcibus_attach_args pba;
+ pcireg_t bcreg, bir;
+ u_char pbnum;
+ pcitag_t tag;
int i, r;
+ int doattach = 0;
switch (PCI_VENDOR(pa->pa_id)) {
case PCI_VENDOR_AMD:
@@ -201,17 +206,27 @@ pchbattach(struct device *parent, struct device *self, void *aux)
break;
case PCI_VENDOR_VIATECH:
switch (PCI_PRODUCT(pa->pa_id)) {
- case PCI_PRODUCT_VIATECH_VT8251_VLINK:
+ case PCI_PRODUCT_VIATECH_VT8251_PCIE_0:
/*
- * For some strange reason, the VIA VT8251
- * chipset can be configured to its PCIe
- * bridge show up as a host bridge. We whack
- * it into PCI bridge mode here such that we
- * can see the devices behind it.
+ * Bump the host bridge into PCI-PCI bridge
+ * mode by clearing magic bit on the VLINK
+ * device. This allows us to read the bus
+ * number for the PCI bus attached to this
+ * host bridge.
*/
- bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0xfc);
+ tag = pci_make_tag(pa->pa_pc, 0, 17, 7);
+ bcreg = pci_conf_read(pa->pa_pc, tag, 0xfc);
bcreg &= ~0x00000004; /* XXX Magic */
- pci_conf_write(pa->pa_pc, pa->pa_tag, 0xfc, bcreg);
+ pci_conf_write(pa->pa_pc, tag, 0xfc, bcreg);
+
+ bir = pci_conf_read(pa->pa_pc,
+ pa->pa_tag, PPB_REG_BUSINFO);
+ pbnum = PPB_BUSINFO_PRIMARY(bir);
+ doattach = 1;
+
+ /* Switch back to host bridge mode. */
+ bcreg |= 0x00000004; /* XXX Magic */
+ pci_conf_write(pa->pa_pc, tag, 0xfc, bcreg);
break;
}
printf("\n");
@@ -223,7 +238,7 @@ pchbattach(struct device *parent, struct device *self, void *aux)
#if NAGP > 0
/*
- * Intel IGD have an odd interface and attach at vga, however
+ * Intel IGD have an odd interface and attach at vga, however,
* in that mode they don't have the AGP cap bit, so this
* test should be sufficient
*/
@@ -236,6 +251,19 @@ pchbattach(struct device *parent, struct device *self, void *aux)
config_found(self, &aa, agpdev_print);
}
#endif /* NAGP > 0 */
+
+ if (doattach == 0)
+ return;
+
+ bzero(&pba, sizeof(pba));
+ pba.pba_busname = "pci";
+ pba.pba_iot = pa->pa_iot;
+ pba.pba_memt = pa->pa_memt;
+ pba.pba_dmat = pa->pa_dmat;
+ pba.pba_domain = pa->pa_domain;
+ pba.pba_bus = pbnum;
+ pba.pba_pc = pa->pa_pc;
+ config_found(self, &pba, pchb_print);
}
int
diff --git a/sys/arch/i386/pci/pchb.c b/sys/arch/i386/pci/pchb.c
index 7b8a4b1676d..2321e146130 100644
--- a/sys/arch/i386/pci/pchb.c
+++ b/sys/arch/i386/pci/pchb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pchb.c,v 1.79 2009/11/23 15:33:37 deraadt Exp $ */
+/* $OpenBSD: pchb.c,v 1.80 2010/02/09 19:36:05 kettenis Exp $ */
/* $NetBSD: pchb.c,v 1.65 2007/08/15 02:26:13 markd Exp $ */
/*
@@ -67,6 +67,7 @@
#include <dev/pci/pcidevs.h>
#include <dev/pci/agpvar.h>
+#include <dev/pci/ppbreg.h>
#include <dev/rndvar.h>
@@ -169,7 +170,7 @@ pchbattach(struct device *parent, struct device *self, void *aux)
struct pchb_softc *sc = (struct pchb_softc *)self;
struct pci_attach_args *pa = aux;
struct pcibus_attach_args pba;
- pcireg_t bcreg;
+ pcireg_t bcreg, bir;
u_char bdnum, pbnum;
pcitag_t tag;
int i, r;
@@ -348,17 +349,27 @@ pchbattach(struct device *parent, struct device *self, void *aux)
break;
case PCI_VENDOR_VIATECH:
switch (PCI_PRODUCT(pa->pa_id)) {
- case PCI_PRODUCT_VIATECH_VT8251_VLINK:
+ case PCI_PRODUCT_VIATECH_VT8251_PCIE_0:
/*
- * For some strange reason, the VIA VT8251
- * chipset can be configured to its PCIe
- * bridge show up as a host bridge. We whack
- * it into PCI bridge mode here such that we
- * can see the devices behind it.
+ * Bump the host bridge into PCI-PCI bridge
+ * mode by clearing magic bit on the VLINK
+ * device. This allows us to read the bus
+ * number for the PCI bus attached to this
+ * host bridge.
*/
- bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0xfc);
+ tag = pci_make_tag(pa->pa_pc, 0, 17, 7);
+ bcreg = pci_conf_read(pa->pa_pc, tag, 0xfc);
bcreg &= ~0x00000004; /* XXX Magic */
- pci_conf_write(pa->pa_pc, pa->pa_tag, 0xfc, bcreg);
+ pci_conf_write(pa->pa_pc, tag, 0xfc, bcreg);
+
+ bir = pci_conf_read(pa->pa_pc,
+ pa->pa_tag, PPB_REG_BUSINFO);
+ pbnum = PPB_BUSINFO_PRIMARY(bir);
+ doattach = 1;
+
+ /* Switch back to host bridge mode. */
+ bcreg |= 0x00000004; /* XXX Magic */
+ pci_conf_write(pa->pa_pc, tag, 0xfc, bcreg);
break;
}
printf("\n");
@@ -383,7 +394,7 @@ pchbattach(struct device *parent, struct device *self, void *aux)
config_found(self, &aa, agpdev_print);
}
#endif /* NAGP > 0 */
-#ifdef __i386__
+
if (doattach == 0)
return;
@@ -396,7 +407,6 @@ pchbattach(struct device *parent, struct device *self, void *aux)
pba.pba_bus = pbnum;
pba.pba_pc = pa->pa_pc;
config_found(self, &pba, pchb_print);
-#endif /* __i386__ */
}
int