diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2011-01-09 11:38:11 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2011-01-09 11:38:11 +0000 |
commit | f22fe1669a907667d190bee9310fd0ec8bc95d5d (patch) | |
tree | d2aa2e842de3313a315581f8b567ad7deaab5324 /sys/arch/amd64/pci/pci_machdep.c | |
parent | 0b81278beec85aa0319db23c218a2fa6ff0997b3 (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@.
Diffstat (limited to 'sys/arch/amd64/pci/pci_machdep.c')
-rw-r--r-- | sys/arch/amd64/pci/pci_machdep.c | 66 |
1 files changed, 32 insertions, 34 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(); |