summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2011-01-09 11:38:11 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2011-01-09 11:38:11 +0000
commitf22fe1669a907667d190bee9310fd0ec8bc95d5d (patch)
treed2aa2e842de3313a315581f8b567ad7deaab5324
parent0b81278beec85aa0319db23c218a2fa6ff0997b3 (diff)
Only use memory mapped extended PCIe config space access for the busses
advertised in the MCFG table, and fall back on the traditional method for other busses. Fixes issue reported by henning@.
-rw-r--r--sys/arch/amd64/pci/pci_machdep.c66
-rw-r--r--sys/arch/i386/pci/pci_machdep.c68
2 files changed, 64 insertions, 70 deletions
diff --git a/sys/arch/amd64/pci/pci_machdep.c b/sys/arch/amd64/pci/pci_machdep.c
index 10a5df20ae0..4e7a6d9f0a5 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.38 2011/01/04 21:17:49 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.39 2011/01/09 11:38:10 kettenis Exp $ */
/* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */
/*-
@@ -108,6 +108,7 @@ bus_addr_t pci_mcfg_addr;
int pci_mcfg_min_bus, pci_mcfg_max_bus;
bus_space_tag_t pci_mcfgt = X86_BUS_SPACE_MEM;
bus_space_handle_t pci_mcfgh[256];
+void pci_mcfg_map_bus(int);
struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH);
@@ -170,14 +171,6 @@ pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
if (bus >= 256 || device >= 32 || function >= 8)
panic("pci_make_tag: bad request");
- if (pci_mcfg_addr) {
- if (bus < pci_mcfg_min_bus || bus > pci_mcfg_max_bus ||
- device >= 32 || function >= 8)
- panic("pci_make_tag: bad request");
-
- return (bus << 20) | (device << 15) | (function << 12);
- }
-
return (PCI_MODE1_ENABLE |
(bus << 16) | (device << 11) | (function << 8));
}
@@ -185,16 +178,6 @@ pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
void
pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
{
- if (pci_mcfg_addr) {
- if (bp != NULL)
- *bp = (tag >> 20) & 0xff;
- if (dp != NULL)
- *dp = (tag >> 15) & 0x1f;
- if (fp != NULL)
- *fp = (tag >> 12) & 0x7;
- return;
- }
-
if (bp != NULL)
*bp = (tag >> 16) & 0xff;
if (dp != NULL)
@@ -206,12 +189,28 @@ pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
int
pci_conf_size(pci_chipset_tag_t pc, pcitag_t tag)
{
- if (pci_mcfg_addr)
- return PCIE_CONFIG_SPACE_SIZE;
+ int bus;
+
+ if (pci_mcfg_addr) {
+ pci_decompose_tag(pc, tag, &bus, NULL, NULL);
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus)
+ return PCIE_CONFIG_SPACE_SIZE;
+ }
return PCI_CONFIG_SPACE_SIZE;
}
+void
+pci_mcfg_map_bus(int bus)
+{
+ if (pci_mcfgh[bus])
+ return;
+
+ if (bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20), 1 << 20,
+ 0, &pci_mcfgh[bus]))
+ panic("pci_conf_read: cannot map mcfg space");
+}
+
pcireg_t
pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
{
@@ -220,12 +219,12 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
if (pci_mcfg_addr) {
pci_decompose_tag(pc, tag, &bus, NULL, NULL);
- if (pci_mcfgh[bus] == 0 &&
- bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
- 1 << 20, 0, &pci_mcfgh[bus]))
- panic("pci_conf_read: cannot map mcfg space");
- return bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
- (tag & 0x000ff000) | reg);
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
+ pci_mcfg_map_bus(bus);
+ data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
+ (tag & 0x000ff00) << 4 | reg);
+ return data;
+ }
}
PCI_CONF_LOCK();
@@ -244,13 +243,12 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
if (pci_mcfg_addr) {
pci_decompose_tag(pc, tag, &bus, NULL, NULL);
- if (pci_mcfgh[bus] == 0 &&
- bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
- 1 << 20, 0, &pci_mcfgh[bus]))
- panic("pci_conf_write: cannot map mcfg space");
- bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
- (tag & 0x000ff000) | reg, data);
- return;
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
+ pci_mcfg_map_bus(bus);
+ bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
+ (tag & 0x000ff00) << 4 | reg, data);
+ return;
+ }
}
PCI_CONF_LOCK();
diff --git a/sys/arch/i386/pci/pci_machdep.c b/sys/arch/i386/pci/pci_machdep.c
index e6404bf3f91..8d684f8f306 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.56 2011/01/04 21:17:49 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.57 2011/01/09 11:38:10 kettenis Exp $ */
/* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */
/*-
@@ -126,6 +126,7 @@ bus_addr_t pci_mcfg_addr;
int pci_mcfg_min_bus, pci_mcfg_max_bus;
bus_space_tag_t pci_mcfgt = I386_BUS_SPACE_MEM;
bus_space_handle_t pci_mcfgh[256];
+void pci_mcfg_map_bus(int);
struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH);
@@ -224,15 +225,6 @@ pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
{
pcitag_t tag;
- if (pci_mcfg_addr) {
- if (bus < pci_mcfg_min_bus || bus > pci_mcfg_max_bus ||
- device >= 32 || function >= 8)
- panic("pci_make_tag: bad request");
-
- tag.mode1 = (bus << 20) | (device << 15) | (function << 12);
- return tag;
- }
-
switch (pci_mode) {
case 1:
if (bus >= 256 || device >= 32 || function >= 8)
@@ -259,16 +251,6 @@ pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
void
pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
{
- if (pci_mcfg_addr) {
- if (bp != NULL)
- *bp = (tag.mode1 >> 20) & 0xff;
- if (dp != NULL)
- *dp = (tag.mode1 >> 15) & 0x1f;
- if (fp != NULL)
- *fp = (tag.mode1 >> 12) & 0x7;
- return;
- }
-
switch (pci_mode) {
case 1:
if (bp != NULL)
@@ -294,12 +276,28 @@ pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
int
pci_conf_size(pci_chipset_tag_t pc, pcitag_t tag)
{
- if (pci_mcfg_addr)
- return PCIE_CONFIG_SPACE_SIZE;
+ int bus;
+
+ if (pci_mcfg_addr) {
+ pci_decompose_tag(pc, tag, &bus, NULL, NULL);
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus)
+ return PCIE_CONFIG_SPACE_SIZE;
+ }
return PCI_CONFIG_SPACE_SIZE;
}
+void
+pci_mcfg_map_bus(int bus)
+{
+ if (pci_mcfgh[bus])
+ return;
+
+ if (bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20), 1 << 20,
+ 0, &pci_mcfgh[bus]))
+ panic("pci_conf_read: cannot map mcfg space");
+}
+
pcireg_t
pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
{
@@ -308,13 +306,12 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
if (pci_mcfg_addr) {
pci_decompose_tag(pc, tag, &bus, NULL, NULL);
- if (pci_mcfgh[bus] == 0 &&
- bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
- 1 << 20, 0, &pci_mcfgh[bus]))
- panic("pci_conf_read: cannot map mcfg space");
- data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
- (tag.mode1 & 0x000ff000) | reg);
- return data;
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
+ pci_mcfg_map_bus(bus);
+ data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
+ (tag.mode1 & 0x000ff00) << 4 | reg);
+ return data;
+ }
}
PCI_CONF_LOCK();
@@ -345,13 +342,12 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
if (pci_mcfg_addr) {
pci_decompose_tag(pc, tag, &bus, NULL, NULL);
- if (pci_mcfgh[bus] == 0 &&
- bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
- 1 << 20, 0, &pci_mcfgh[bus]))
- panic("pci_conf_write: cannot map mcfg space");
- bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
- (tag.mode1 & 0x000ff000) | reg, data);
- return;
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
+ pci_mcfg_map_bus(bus);
+ bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
+ (tag.mode1 & 0x000ff00) << 4 | reg, data);
+ return;
+ }
}
PCI_CONF_LOCK();