summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2018-08-19 08:23:48 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2018-08-19 08:23:48 +0000
commit63e6caa26564e0dc0de5c358a1401413ea2b7e8c (patch)
treea405a2c32a4101e6ed60be302e4d8a4c085934fa /sys/dev
parent189364187b38c0928ee75abd2ed96ab3637938f6 (diff)
Add support for multiple PCI segments. Only really implemented for arm64
for now as amd64/i386 firmware still caters for legacy OSes that only support a single PCI segment. ok patrick@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpi/acpi.c18
-rw-r--r--sys/dev/acpi/acpimcfg.c24
-rw-r--r--sys/dev/acpi/acpireg.h12
-rw-r--r--sys/dev/acpi/acpivar.h4
-rw-r--r--sys/dev/acpi/dsdt.c13
-rw-r--r--sys/dev/acpi/dsdt.h7
6 files changed, 42 insertions, 36 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index ccc7befe976..ad0bab64b93 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.356 2018/08/03 22:18:13 kettenis Exp $ */
+/* $OpenBSD: acpi.c,v 1.357 2018/08/19 08:23:47 kettenis Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -328,13 +328,6 @@ acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
break;
case GAS_PCI_CFG_SPACE:
- /* format of address:
- * bits 00..15 = register
- * bits 16..31 = function
- * bits 32..47 = device
- * bits 48..63 = bus
- */
-
/*
* The ACPI standard says that a function number of
* FFFF can be used to refer to all functions on a
@@ -349,7 +342,7 @@ acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
return (0);
}
- pc = sc->sc_pc;
+ pc = pci_lookup_segment(ACPI_PCI_SEG(address));
tag = pci_make_tag(pc,
ACPI_PCI_BUS(address), ACPI_PCI_DEV(address),
ACPI_PCI_FN(address));
@@ -564,7 +557,7 @@ acpi_getpci(struct aml_node *node, void *arg)
struct acpi_pci *pci, *ppci;
struct aml_value res;
struct acpi_softc *sc = arg;
- pci_chipset_tag_t pc = sc->sc_pc;
+ pci_chipset_tag_t pc;
pcitag_t tag;
uint64_t val;
uint32_t reg;
@@ -610,6 +603,7 @@ acpi_getpci(struct aml_node *node, void *arg)
return 0;
pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO);
+ pci->seg = ppci->seg;
pci->bus = ppci->sub;
pci->dev = ACPI_ADR_PCIDEV(val);
pci->fun = ACPI_ADR_PCIFUN(val);
@@ -643,6 +637,7 @@ acpi_getpci(struct aml_node *node, void *arg)
free(pci, M_DEVBUF, sizeof(*pci));
return (1);
}
+ pc = pci_lookup_segment(pci->seg);
tag = pci_make_tag(pc, pci->bus, pci->dev, pci->fun);
reg = pci_conf_read(pc, tag, PCI_ID_REG);
if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) {
@@ -815,7 +810,7 @@ int
acpi_pci_notify(struct aml_node *node, int ntype, void *arg)
{
struct acpi_pci *pdev = arg;
- pci_chipset_tag_t pc = acpi_softc->sc_pc;
+ pci_chipset_tag_t pc;
pcitag_t tag;
pcireg_t reg;
int offset;
@@ -824,6 +819,7 @@ acpi_pci_notify(struct aml_node *node, int ntype, void *arg)
if (ntype != 2)
return (0);
+ pc = pci_lookup_segment(pdev->seg);
tag = pci_make_tag(pc, pdev->bus, pdev->dev, pdev->fun);
if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, 0)) {
/* Clear the PME Status bit if it is set. */
diff --git a/sys/dev/acpi/acpimcfg.c b/sys/dev/acpi/acpimcfg.c
index 311016dbd5e..2370c3b8b09 100644
--- a/sys/dev/acpi/acpimcfg.c
+++ b/sys/dev/acpi/acpimcfg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpimcfg.c,v 1.3 2018/07/04 20:46:22 kettenis Exp $ */
+/* $OpenBSD: acpimcfg.c,v 1.4 2018/08/19 08:23:47 kettenis Exp $ */
/*
* Copyright (c) 2010 Mark Kettenis <kettenis@openbsd.org>
*
@@ -59,20 +59,20 @@ acpimcfg_match(struct device *parent, void *match, void *aux)
void
acpimcfg_attach(struct device *parent, struct device *self, void *aux)
{
- struct acpi_softc *sc = (struct acpi_softc *)parent;
struct acpi_attach_args *aaa = aux;
struct acpi_mcfg *mcfg = (struct acpi_mcfg *)aaa->aaa_table;
+ caddr_t addr = (caddr_t)(mcfg + 1);
- printf(" addr 0x%llx, bus %d-%d\n", mcfg->base_address,
- mcfg->min_bus_number, mcfg->max_bus_number);
+ printf("\n");
- /*
- * Some (broken?) BIOSen have an MCFG table for an empty bus
- * range. Ignore those tables.
- */
- if (mcfg->min_bus_number == mcfg->max_bus_number)
- return;
+ while (addr < (caddr_t)mcfg + mcfg->hdr.length) {
+ struct acpi_mcfg_entry *entry = (struct acpi_mcfg_entry *)addr;
+
+ printf("%s: addr 0x%llx, bus %d-%d\n", self->dv_xname,
+ entry->base_address, entry->min_bus_number, entry->max_bus_number);
- sc->sc_pc = pci_mcfg_init(aaa->aaa_memt, mcfg->base_address,
- mcfg->min_bus_number, mcfg->max_bus_number);
+ pci_mcfg_init(aaa->aaa_memt, entry->base_address,
+ entry->segment, entry->min_bus_number, entry->max_bus_number);
+ addr += sizeof(struct acpi_mcfg_entry);
+ }
}
diff --git a/sys/dev/acpi/acpireg.h b/sys/dev/acpi/acpireg.h
index 6906074507d..76e92fcb85d 100644
--- a/sys/dev/acpi/acpireg.h
+++ b/sys/dev/acpi/acpireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpireg.h,v 1.42 2018/07/01 10:26:17 kettenis Exp $ */
+/* $OpenBSD: acpireg.h,v 1.43 2018/08/19 08:23:47 kettenis Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
@@ -410,6 +410,9 @@ struct acpi_mcfg {
struct acpi_table_header hdr;
#define MCFG_SIG "MCFG"
uint8_t reserved[8];
+} __packed;
+
+struct acpi_mcfg_entry {
uint64_t base_address;
uint16_t segment;
uint8_t min_bus_number;
@@ -671,11 +674,12 @@ struct acpi_ivrs {
*/
#define ACPI_ADR_PCIDEV(addr) (uint16_t)(addr >> 16)
#define ACPI_ADR_PCIFUN(addr) (uint16_t)(addr & 0xFFFF)
-#define ACPI_PCI_BUS(addr) (uint16_t)((addr) >> 48)
-#define ACPI_PCI_DEV(addr) (uint16_t)((addr) >> 32)
+
+#define ACPI_PCI_SEG(addr) (uint16_t)((addr) >> 48)
+#define ACPI_PCI_BUS(addr) (uint8_t)((addr) >> 40)
+#define ACPI_PCI_DEV(addr) (uint8_t)((addr) >> 32)
#define ACPI_PCI_FN(addr) (uint16_t)((addr) >> 16)
#define ACPI_PCI_REG(addr) (uint16_t)(addr)
-#define ACPI_PCI_ADDR(b,d,f,r) ((uint64_t)(b)<<48LL | (uint64_t)(d)<<32LL | (f)<<16LL | (r))
/*
* PM1 Status Registers Fixed Hardware Feature Status Bits
diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h
index f10f8478813..dd443491c3d 100644
--- a/sys/dev/acpi/acpivar.h
+++ b/sys/dev/acpi/acpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpivar.h,v 1.97 2018/08/03 22:18:13 kettenis Exp $ */
+/* $OpenBSD: acpivar.h,v 1.98 2018/08/19 08:23:47 kettenis Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
*
@@ -209,8 +209,6 @@ struct acpi_softc {
bus_space_tag_t sc_memt;
bus_dma_tag_t sc_dmat;
- pci_chipset_tag_t sc_pc; /* XXX assume single segment */
-
/*
* First-level ACPI tables
*/
diff --git a/sys/dev/acpi/dsdt.c b/sys/dev/acpi/dsdt.c
index 75ec47e663a..176c067dcf3 100644
--- a/sys/dev/acpi/dsdt.c
+++ b/sys/dev/acpi/dsdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.c,v 1.242 2018/06/29 17:39:18 kettenis Exp $ */
+/* $OpenBSD: dsdt.c,v 1.243 2018/08/19 08:23:47 kettenis Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -2303,14 +2303,21 @@ aml_rdpciaddr(struct aml_node *pcidev, union amlpci_t *addr)
{
int64_t res;
+ addr->bus = 0;
+ addr->seg = 0;
if (aml_evalinteger(acpi_softc, pcidev, "_ADR", 0, NULL, &res) == 0) {
addr->fun = res & 0xFFFF;
addr->dev = res >> 16;
}
while (pcidev != NULL) {
- /* HID device (PCI or PCIE root): eval _BBN */
+ /* HID device (PCI or PCIE root): eval _SEG and _BBN */
if (__aml_search(pcidev, "_HID", 0)) {
- if (aml_evalinteger(acpi_softc, pcidev, "_BBN", 0, NULL, &res) == 0) {
+ if (aml_evalinteger(acpi_softc, pcidev, "_SEG",
+ 0, NULL, &res) == 0) {
+ addr->seg = res;
+ }
+ if (aml_evalinteger(acpi_softc, pcidev, "_BBN",
+ 0, NULL, &res) == 0) {
addr->bus = res;
break;
}
diff --git a/sys/dev/acpi/dsdt.h b/sys/dev/acpi/dsdt.h
index 2a52c9ce832..b49726d75af 100644
--- a/sys/dev/acpi/dsdt.h
+++ b/sys/dev/acpi/dsdt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.h,v 1.76 2018/07/05 19:25:38 kettenis Exp $ */
+/* $OpenBSD: dsdt.h,v 1.77 2018/08/19 08:23:47 kettenis Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
*
@@ -339,8 +339,9 @@ union amlpci_t {
struct {
uint16_t reg;
uint16_t fun;
- uint16_t dev;
- uint16_t bus;
+ uint8_t dev;
+ uint8_t bus;
+ uint16_t seg;
};
};
int aml_rdpciaddr(struct aml_node *pcidev,