diff options
-rw-r--r-- | sys/arch/amd64/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/amd64/include/pci_machdep.h | 5 | ||||
-rw-r--r-- | sys/arch/amd64/pci/pci_machdep.c | 60 | ||||
-rw-r--r-- | sys/arch/i386/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_machdep.c | 60 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_machdep.h | 5 | ||||
-rw-r--r-- | sys/dev/acpi/acpimcfg.c | 73 | ||||
-rw-r--r-- | sys/dev/acpi/acpireg.h | 13 | ||||
-rw-r--r-- | sys/dev/acpi/files.acpi | 7 |
9 files changed, 221 insertions, 8 deletions
diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index 6d6388e1198..320c36ec6da 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.310 2010/12/15 11:24:29 jsg Exp $ +# $OpenBSD: GENERIC,v 1.311 2011/01/04 21:17:49 kettenis Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -48,6 +48,7 @@ acpiec* at acpi? acpiprt* at acpi? acpitz* at acpi? acpimadt0 at acpi? +acpimcfg* at acpi? acpiasus* at acpi? acpisony* at acpi? acpithinkpad* at acpi? diff --git a/sys/arch/amd64/include/pci_machdep.h b/sys/arch/amd64/include/pci_machdep.h index dc4522b387e..4b716578e93 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.16 2010/12/04 17:06:31 miod Exp $ */ +/* $OpenBSD: pci_machdep.h,v 1.17 2011/01/04 21:17:49 kettenis Exp $ */ /* $NetBSD: pci_machdep.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ /* @@ -59,6 +59,9 @@ typedef struct { * amd64-specific PCI variables and functions. * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. */ +extern bus_addr_t pci_mcfg_addr; +extern int pci_mcfg_min_bus, pci_mcfg_max_bus; + struct pci_attach_args; extern struct extent *pciio_ex; diff --git a/sys/arch/amd64/pci/pci_machdep.c b/sys/arch/amd64/pci/pci_machdep.c index db78807429d..10a5df20ae0 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.37 2010/12/04 17:06:31 miod Exp $ */ +/* $OpenBSD: pci_machdep.c,v 1.38 2011/01/04 21:17:49 kettenis Exp $ */ /* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */ /*- @@ -96,6 +96,19 @@ #include <machine/mpbiosvar.h> #endif +/* + * Memory Mapped Configuration space access. + * + * Since mapping the whole configuration space will cost us up to + * 256MB of kernel virtual memory, we use seperate mappings per bus. + * The mappings are created on-demand, such that we only use kernel + * virtual memory for busses that are actually present. + */ +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]; + struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH); #define PCI_CONF_LOCK() \ @@ -157,6 +170,14 @@ 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)); } @@ -164,6 +185,16 @@ 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) @@ -175,6 +206,9 @@ 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; + return PCI_CONFIG_SPACE_SIZE; } @@ -182,6 +216,17 @@ pcireg_t pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { pcireg_t data; + int bus; + + 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); + } PCI_CONF_LOCK(); outl(PCI_MODE1_ADDRESS_REG, tag | reg); @@ -195,6 +240,19 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) void pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { + int bus; + + 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; + } + PCI_CONF_LOCK(); outl(PCI_MODE1_ADDRESS_REG, tag | reg); outl(PCI_MODE1_DATA_REG, data); diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC index a59d3efb36e..4905624a876 100644 --- a/sys/arch/i386/conf/GENERIC +++ b/sys/arch/i386/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.704 2010/12/15 11:24:29 jsg Exp $ +# $OpenBSD: GENERIC,v 1.705 2011/01/04 21:17:49 kettenis Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -57,6 +57,7 @@ acpicpu* at acpi? acpidock* at acpi? acpiec* at acpi? acpimadt0 at acpi? +acpimcfg* at acpi? acpiprt* at acpi? acpitz* at acpi? acpiasus* at acpi? diff --git a/sys/arch/i386/pci/pci_machdep.c b/sys/arch/i386/pci/pci_machdep.c index 15a4e0cbfcd..e6404bf3f91 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.55 2010/12/04 17:06:31 miod Exp $ */ +/* $OpenBSD: pci_machdep.c,v 1.56 2011/01/04 21:17:49 kettenis Exp $ */ /* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */ /*- @@ -114,6 +114,19 @@ extern bios_pciinfo_t *bios_pciinfo; int pci_mode = -1; +/* + * Memory Mapped Configuration space access. + * + * Since mapping the whole configuration space will cost us up to + * 256MB of kernel virtual memory, we use seperate mappings per bus. + * The mappings are created on-demand, such that we only use kernel + * virtual memory for busses that are actually present. + */ +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]; + struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH); #define PCI_CONF_LOCK() \ @@ -211,6 +224,15 @@ 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) @@ -237,6 +259,15 @@ 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: @@ -263,6 +294,9 @@ 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; + return PCI_CONFIG_SPACE_SIZE; } @@ -270,6 +304,18 @@ pcireg_t pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { pcireg_t data; + int bus; + + 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; + } PCI_CONF_LOCK(); switch (pci_mode) { @@ -295,6 +341,18 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) void pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { + int bus; + + 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; + } PCI_CONF_LOCK(); switch (pci_mode) { diff --git a/sys/arch/i386/pci/pci_machdep.h b/sys/arch/i386/pci/pci_machdep.h index dcc0f1fa42d..378c684bfb8 100644 --- a/sys/arch/i386/pci/pci_machdep.h +++ b/sys/arch/i386/pci/pci_machdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_machdep.h,v 1.20 2010/12/04 17:06:31 miod Exp $ */ +/* $OpenBSD: pci_machdep.h,v 1.21 2011/01/04 21:17:49 kettenis Exp $ */ /* $NetBSD: pci_machdep.h,v 1.7 1997/06/06 23:29:18 thorpej Exp $ */ /* @@ -75,6 +75,9 @@ struct { * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. */ extern int pci_mode; +extern bus_addr_t pci_mcfg_addr; +extern int pci_mcfg_min_bus, pci_mcfg_max_bus; + int pci_mode_detect(void); extern struct extent *pciio_ex; diff --git a/sys/dev/acpi/acpimcfg.c b/sys/dev/acpi/acpimcfg.c new file mode 100644 index 00000000000..ee265db9918 --- /dev/null +++ b/sys/dev/acpi/acpimcfg.c @@ -0,0 +1,73 @@ +/* $OpenBSD: acpimcfg.c,v 1.1 2011/01/04 21:17:49 kettenis Exp $ */ +/* + * Copyright (c) 2010 Mark Kettenis <kettenis@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/apicvar.h> + +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> +#include <dev/pci/pcivar.h> + +int acpimcfg_match(struct device *, void *, void *); +void acpimcfg_attach(struct device *, struct device *, void *); + +struct cfattach acpimcfg_ca = { + sizeof(struct device), acpimcfg_match, acpimcfg_attach +}; + +struct cfdriver acpimcfg_cd = { + NULL, "acpimcfg", DV_DULL +}; + +int +acpimcfg_match(struct device *parent, void *match, void *aux) +{ + struct acpi_attach_args *aaa = aux; + struct acpi_table_header *hdr; + + /* + * If we do not have a table, it is not us + */ + if (aaa->aaa_table == NULL) + return (0); + + /* + * If it is an MCFG table, we can attach + */ + hdr = (struct acpi_table_header *)aaa->aaa_table; + if (memcmp(hdr->signature, MCFG_SIG, sizeof(MCFG_SIG) - 1) != 0) + return (0); + + return (1); +} + +void +acpimcfg_attach(struct device *parent, struct device *self, void *aux) +{ + struct acpi_attach_args *aaa = aux; + struct acpi_mcfg *mcfg = (struct acpi_mcfg *)aaa->aaa_table; + + printf(" addr 0x%llx, bus %d-%d\n", mcfg->base_address, + mcfg->min_bus_number, mcfg->max_bus_number); + + pci_mcfg_addr = mcfg->base_address; + pci_mcfg_min_bus = mcfg->min_bus_number; + pci_mcfg_max_bus = mcfg->max_bus_number; +} diff --git a/sys/dev/acpi/acpireg.h b/sys/dev/acpi/acpireg.h index 1669bec11bc..7bbb480485c 100644 --- a/sys/dev/acpi/acpireg.h +++ b/sys/dev/acpi/acpireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: acpireg.h,v 1.23 2010/07/21 19:35:15 deraadt Exp $ */ +/* $OpenBSD: acpireg.h,v 1.24 2011/01/04 21:17:49 kettenis Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> @@ -380,6 +380,17 @@ struct acpi_hpet { u_int8_t page_protection; } __packed; +struct acpi_mcfg { + struct acpi_table_header hdr; +#define MCFG_SIG "MCFG" + u_int8_t reserved[8]; + u_int64_t base_address; + u_int16_t segment; + u_int8_t min_bus_number; + u_int8_t max_bus_number; + u_int32_t reserved1; +} __packed; + struct acpi_facs { u_int8_t signature[4]; #define FACS_SIG "FACS" diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi index 58885dfc2f9..f19855b6cd8 100644 --- a/sys/dev/acpi/files.acpi +++ b/sys/dev/acpi/files.acpi @@ -1,4 +1,4 @@ -# $OpenBSD: files.acpi,v 1.24 2010/07/26 11:29:23 pirofti Exp $ +# $OpenBSD: files.acpi,v 1.25 2011/01/04 21:17:49 kettenis Exp $ # # Config file and device description for machine-independent ACPI code. # Included by ports that need it. @@ -56,6 +56,11 @@ device acpimadt attach acpimadt at acpi file dev/acpi/acpimadt.c acpimadt +# Memory Mapped Configuration Space Address Description Table +device acpimcfg +attach acpimcfg at acpi +file dev/acpi/acpimcfg.c acpimcfg + # PCI Routing Table device acpiprt attach acpiprt at acpi |