summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authormsaitoh <msaitoh@NetBSD.org>2015-10-02 05:22:49 +0000
committermsaitoh <msaitoh@NetBSD.org>2015-10-02 05:22:49 +0000
commit998866035fb2f446df656a6ae9e4b0ee4ddc445c (patch)
treed95622964c21680e079f5097dd6a20e673e3c349 /sys/dev
parent058cde2471e6b21a2d85f267a5be1ec6b7a472b9 (diff)
PCI Extended Configuration stuff written by nonaka@:
- Add PCI Extended Configuration Space support into x86. - Check register offset of pci_conf_read() in MD part. It returns (pcireg_t)-1 if it isn't accessible. - Decode Extended Capability in PCI Extended Configuration Space. Currently the following extended capabilities are decoded: - Advanced Error Reporting - Virtual Channel - Device Serial Number - Power Budgeting - Root Complex Link Declaration - Root Complex Event Collector Association - Access Control Services - Alternative Routing-ID Interpretation - Address Translation Services - Single Root IO Virtualization - Page Request - TPH Requester - Latency Tolerance Reporting - Secondary PCI Express - Process Address Space ID - LN Requester - L1 PM Substates The following extended capabilities are not decoded yet: - Root Complex Internal Link Control - Multi-Function Virtual Channel - RCRB Header - Vendor Unique - Configuration Access Correction - Multiple Root IO Virtualization - Multicast - Resizable BAR - Dynamic Power Allocation - Protocol Multiplexing - Downstream Port Containment - Precision Time Management - M-PCIe - Function Reading Status Queueing - Readiness Time Reporting - Designated Vendor-Specific
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpi/acpi.c10
-rw-r--r--sys/dev/acpi/acpi_mcfg.c697
-rw-r--r--sys/dev/acpi/acpi_mcfg.h58
-rw-r--r--sys/dev/acpi/files.acpi3
-rw-r--r--sys/dev/marvell/gtpci.c10
-rw-r--r--sys/dev/marvell/mvpex.c10
-rw-r--r--sys/dev/pci/pci.c44
-rw-r--r--sys/dev/pci/pci_subr.c1225
-rw-r--r--sys/dev/pci/pcireg.h500
-rw-r--r--sys/dev/pci/pcivar.h14
10 files changed, 2540 insertions, 31 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index 3780df0d982..d55896a8f6a 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi.c,v 1.260 2015/08/18 10:41:28 christos Exp $ */
+/* $NetBSD: acpi.c,v 1.261 2015/10/02 05:22:52 msaitoh Exp $ */
/*-
* Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.260 2015/08/18 10:41:28 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.261 2015/10/02 05:22:52 msaitoh Exp $");
#include "opt_acpi.h"
#include "opt_pcifixup.h"
@@ -118,6 +118,7 @@ __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.260 2015/08/18 10:41:28 christos Exp $");
#include <dev/acpi/acpireg.h>
#include <dev/acpi/acpivar.h>
+#include <dev/acpi/acpi_mcfg.h>
#include <dev/acpi/acpi_osd.h>
#include <dev/acpi/acpi_pci.h>
#include <dev/acpi/acpi_power.h>
@@ -483,6 +484,11 @@ acpi_attach(device_t parent, device_t self, void *aux)
*/
acpi_build_tree(sc);
+ /*
+ * Probe MCFG table
+ */
+ acpimcfg_probe(sc);
+
acpi_md_callback(sc);
/*
diff --git a/sys/dev/acpi/acpi_mcfg.c b/sys/dev/acpi/acpi_mcfg.c
new file mode 100644
index 00000000000..87d8153ee27
--- /dev/null
+++ b/sys/dev/acpi/acpi_mcfg.c
@@ -0,0 +1,697 @@
+/* $NetBSD: acpi_mcfg.c,v 1.1 2015/10/02 05:22:52 msaitoh Exp $ */
+
+/*-
+ * Copyright (C) 2015 NONAKA Kimihiro <nonaka@NetBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: acpi_mcfg.c,v 1.1 2015/10/02 05:22:52 msaitoh Exp $");
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+#include <dev/acpi/acpi_mcfg.h>
+
+#include "locators.h"
+
+#define EXTCONF_OFFSET(d, f, r) ((((d) * 8 + (f)) * PCI_EXTCONF_SIZE) + (r))
+
+#define EXTCONF_SET_VALID(mb, d, f) ((mb)->valid_devs[(d)] |= __BIT((f)))
+#define EXTCONF_SET_INVALID(mb, d, f) ((mb)->valid_devs[(d)] &= ~__BIT((f)))
+#define EXTCONF_IS_VALID(mb, d, f) ((mb)->valid_devs[(d)] & __BIT((f)))
+
+struct mcfg_segment {
+ uint64_t ms_address; /* Base address */
+ int ms_segment; /* Segment # */
+ int ms_bus_start; /* Start bus # */
+ int ms_bus_end; /* End bus # */
+ bus_space_tag_t ms_bst;
+ struct mcfg_bus {
+ bus_space_handle_t bsh[32][8];
+ uint8_t valid_devs[32];
+ int valid_ndevs;
+ pcitag_t last_probed;
+ } *ms_bus;
+};
+
+static struct mcfg_segment *mcfg_segs;
+static int mcfg_nsegs;
+static ACPI_TABLE_MCFG *mcfg;
+static int mcfg_inited;
+static struct acpi_softc *acpi_sc;
+
+static const struct acpimcfg_ops mcfg_default_ops = {
+ .ao_validate = acpimcfg_default_validate,
+
+ .ao_read = acpimcfg_default_read,
+ .ao_write = acpimcfg_default_write,
+};
+static const struct acpimcfg_ops *mcfg_ops = &mcfg_default_ops;
+
+/*
+ * default operations.
+ */
+bool
+acpimcfg_default_validate(uint64_t address, int bus_start, int *bus_end)
+{
+
+ /* Always Ok */
+ return true;
+}
+
+uint32_t
+acpimcfg_default_read(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_addr_t addr)
+{
+
+ return bus_space_read_4(bst, bsh, addr);
+}
+
+void
+acpimcfg_default_write(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_addr_t addr, uint32_t data)
+{
+
+ bus_space_write_4(bst, bsh, addr, data);
+}
+
+
+/*
+ * Check MCFG memory region at system resource
+ */
+struct acpimcfg_memrange {
+ const char *hid;
+ uint64_t address;
+ int bus_start;
+ int bus_end;
+ bool found;
+};
+
+static ACPI_STATUS
+acpimcfg_parse_callback(ACPI_RESOURCE *res, void *ctx)
+{
+ struct acpimcfg_memrange *mr = ctx;
+ const char *type;
+ uint64_t size, mapaddr, mapsize;
+ int n;
+
+ switch (res->Type) {
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+ type = "FIXED_MEMORY32";
+ mapaddr = res->Data.FixedMemory32.Address;
+ mapsize = res->Data.FixedMemory32.AddressLength;
+ break;
+
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ /* XXX Only fixed size supported for now */
+ if (res->Data.Address32.Address.AddressLength == 0 ||
+ res->Data.Address32.ProducerConsumer != ACPI_CONSUMER)
+ goto out;
+
+ if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE)
+ goto out;
+
+ if (res->Data.Address32.MinAddressFixed != ACPI_ADDRESS_FIXED ||
+ res->Data.Address32.MaxAddressFixed != ACPI_ADDRESS_FIXED)
+ goto out;
+
+ type = "ADDRESS32";
+ mapaddr = res->Data.Address32.Address.Minimum;
+ mapsize = res->Data.Address32.Address.AddressLength;
+ break;
+
+#ifdef _LP64
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ /* XXX Only fixed size supported for now */
+ if (res->Data.Address64.Address.AddressLength == 0 ||
+ res->Data.Address64.ProducerConsumer != ACPI_CONSUMER)
+ goto out;
+
+ if (res->Data.Address64.ResourceType != ACPI_MEMORY_RANGE)
+ goto out;
+
+ if (res->Data.Address64.MinAddressFixed != ACPI_ADDRESS_FIXED ||
+ res->Data.Address64.MaxAddressFixed != ACPI_ADDRESS_FIXED)
+ goto out;
+
+ type = "ADDRESS64";
+ mapaddr = res->Data.Address64.Address.Minimum;
+ mapsize = res->Data.Address64.Address.AddressLength;
+ break;
+#endif
+
+ default:
+ out:
+ aprint_debug_dev(acpi_sc->sc_dev, "MCFG: %s: Type=%d\n",
+ mr->hid, res->Type);
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ aprint_debug_dev(acpi_sc->sc_dev, "MCFG: %s: Type=%d(%s), "
+ "Address=0x%016" PRIx64 ", Length=0x%016" PRIx64 "\n",
+ mr->hid, res->Type, type, mapaddr, mapsize);
+
+ if (mr->address < mapaddr || mr->address >= mapaddr + mapsize)
+ return_ACPI_STATUS(AE_OK);
+
+ size = (mr->bus_end - mr->bus_start + 1) * ACPIMCFG_SIZE_PER_BUS;
+
+ /* full map */
+ if (mr->address + size <= mapaddr + mapsize) {
+ mr->found = true;
+ return_ACPI_STATUS(AE_CTRL_TERMINATE);
+ }
+
+ /* partial map */
+ n = (mapsize - (mr->address - mapaddr)) / ACPIMCFG_SIZE_PER_BUS;
+ /* bus_start == bus_end is not allowed. */
+ if (n > 1) {
+ mr->bus_end = mr->bus_start + n - 1;
+ mr->found = true;
+ return_ACPI_STATUS(AE_CTRL_TERMINATE);
+ }
+
+ aprint_debug_dev(acpi_sc->sc_dev, "MCFG: bus %d-%d, "
+ "address 0x%016" PRIx64 ": invalid size: request 0x%016" PRIx64
+ ", actual 0x%016" PRIx64 "\n",
+ mr->bus_start, mr->bus_end, mr->address, size, mapsize);
+
+ return_ACPI_STATUS(AE_OK);
+}
+
+static ACPI_STATUS
+acpimcfg_check_system_resource(ACPI_HANDLE handle, UINT32 level, void *ctx,
+ void **retval)
+{
+ struct acpimcfg_memrange *mr = ctx;
+ ACPI_STATUS status;
+
+ status = AcpiWalkResources(handle, "_CRS", acpimcfg_parse_callback, mr);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(status);
+
+ if (mr->found)
+ return_ACPI_STATUS(AE_CTRL_TERMINATE);
+
+ aprint_debug_dev(acpi_sc->sc_dev, "MCFG: %s: bus %d-%d, "
+ "address 0x%016" PRIx64 ": no valid region\n", mr->hid,
+ mr->bus_start, mr->bus_end, mr->address);
+
+ return_ACPI_STATUS(AE_OK);
+}
+
+static bool
+acpimcfg_find_system_resource(uint64_t address, int bus_start, int *bus_end)
+{
+ static const char *system_resource_hid[] = {
+ "PNP0C01", /* System Board */
+ "PNP0C02" /* General ID for reserving resources */
+ };
+ struct acpimcfg_memrange mr;
+ ACPI_STATUS status;
+ int i;
+
+ mr.address = address;
+ mr.bus_start = bus_start;
+ mr.bus_end = *bus_end;
+ mr.found = false;
+
+ for (i = 0; i < __arraycount(system_resource_hid); i++) {
+ mr.hid = system_resource_hid[i];
+ status = AcpiGetDevices(__UNCONST(system_resource_hid[i]),
+ acpimcfg_check_system_resource, &mr, NULL);
+ if (ACPI_FAILURE(status))
+ continue;
+ if (mr.found) {
+ *bus_end = mr.bus_end;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/*
+ * ACPI MCFG
+ */
+void
+acpimcfg_probe(struct acpi_softc *sc)
+{
+ ACPI_MCFG_ALLOCATION *ama;
+ ACPI_STATUS status;
+ uint32_t offset;
+ int i, nsegs;
+
+ if (acpi_sc != NULL)
+ panic("acpi_sc != NULL");
+ acpi_sc = sc;
+
+ status = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg);
+ if (ACPI_FAILURE(status)) {
+ mcfg = NULL;
+ return;
+ }
+
+ nsegs = 0;
+ offset = sizeof(ACPI_TABLE_MCFG);
+ ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, mcfg, offset);
+ for (i = 0; offset < mcfg->Header.Length; i++) {
+ aprint_debug_dev(sc->sc_dev,
+ "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 "\n",
+ ama->PciSegment, ama->StartBusNumber, ama->EndBusNumber,
+ ama->Address);
+ nsegs++;
+ offset += sizeof(ACPI_MCFG_ALLOCATION);
+ ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, ama, offset);
+ }
+ if (nsegs == 0) {
+ mcfg = NULL;
+ return;
+ }
+
+ mcfg_segs = kmem_zalloc(sizeof(*mcfg_segs) * nsegs, KM_SLEEP);
+ mcfg_nsegs = nsegs;
+}
+
+int
+acpimcfg_init(bus_space_tag_t memt, const struct acpimcfg_ops *ops)
+{
+ ACPI_MCFG_ALLOCATION *ama;
+ struct mcfg_segment *seg;
+ uint32_t offset;
+ int i, n, nsegs, bus_end;
+
+ if (mcfg == NULL)
+ return ENXIO;
+
+ if (mcfg_inited)
+ return 0;
+
+ if (ops != NULL)
+ mcfg_ops = ops;
+
+ nsegs = 0;
+ offset = sizeof(ACPI_TABLE_MCFG);
+ ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, mcfg, offset);
+ for (i = 0; offset < mcfg->Header.Length; i++) {
+#ifndef _LP64
+ if (ama->Address >= 0x100000000ULL) {
+ aprint_debug_dev(acpi_sc->sc_dev,
+ "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64
+ ": ignore (64bit address)\n", ama->PciSegment,
+ ama->StartBusNumber, ama->EndBusNumber,
+ ama->Address);
+ goto next;
+ }
+#endif
+ /*
+ * Some (broken?) BIOSen have an MCFG table for an empty
+ * bus range. Ignore those tables.
+ */
+ if (ama->StartBusNumber == ama->EndBusNumber) {
+ aprint_debug_dev(acpi_sc->sc_dev,
+ "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64
+ ": ignore (bus %d == %d)\n", ama->PciSegment,
+ ama->StartBusNumber, ama->EndBusNumber,
+ ama->Address, ama->StartBusNumber,
+ ama->EndBusNumber);
+ goto next;
+ }
+ if (ama->StartBusNumber > ama->EndBusNumber) {
+ aprint_debug_dev(acpi_sc->sc_dev,
+ "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64
+ ": ignore (bus %d > %d)\n", ama->PciSegment,
+ ama->StartBusNumber, ama->EndBusNumber,
+ ama->Address, ama->StartBusNumber,
+ ama->EndBusNumber);
+ goto next;
+ }
+
+ /* Validate MCFG memory range */
+ bus_end = ama->EndBusNumber;
+ if (mcfg_ops->ao_validate != NULL &&
+ !mcfg_ops->ao_validate(ama->Address, ama->StartBusNumber,
+ &bus_end)) {
+ if (!acpimcfg_find_system_resource( ama->Address,
+ ama->StartBusNumber, &bus_end)) {
+ aprint_debug_dev(acpi_sc->sc_dev,
+ "MCFG: segment %d, bus %d-%d, "
+ "address 0x%016" PRIx64
+ ": ignore (invalid address)\n",
+ ama->PciSegment,
+ ama->StartBusNumber, ama->EndBusNumber,
+ ama->Address);
+ goto next;
+ }
+ }
+ if (ama->EndBusNumber != bus_end) {
+ aprint_debug_dev(acpi_sc->sc_dev,
+ "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64
+ " -> bus %d-%d\n", ama->PciSegment,
+ ama->StartBusNumber, ama->EndBusNumber,
+ ama->Address, ama->StartBusNumber, bus_end);
+ }
+
+ if (ama->PciSegment != 0) {
+ aprint_debug_dev(acpi_sc->sc_dev,
+ "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64
+ ": ignore (non PCI segment 0)\n", ama->PciSegment,
+ ama->StartBusNumber, bus_end, ama->Address);
+ goto next;
+ }
+
+ seg = &mcfg_segs[nsegs++];
+ seg->ms_address = ama->Address;
+ seg->ms_segment = ama->PciSegment;
+ seg->ms_bus_start = ama->StartBusNumber;
+ seg->ms_bus_end = bus_end;
+ seg->ms_bst = memt;
+ n = seg->ms_bus_end - seg->ms_bus_start + 1;
+ seg->ms_bus = kmem_zalloc(sizeof(*seg->ms_bus) * n, KM_SLEEP);
+
+ next:
+ offset += sizeof(ACPI_MCFG_ALLOCATION);
+ ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, ama, offset);
+ }
+ if (nsegs == 0)
+ return ENOENT;
+
+ for (i = 0; i < nsegs; i++) {
+ seg = &mcfg_segs[i];
+ aprint_verbose_dev(acpi_sc->sc_dev,
+ "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 "\n",
+ seg->ms_segment, seg->ms_bus_start, seg->ms_bus_end,
+ seg->ms_address);
+ }
+
+ /* Update # of segment */
+ mcfg_nsegs = nsegs;
+ mcfg_inited = true;
+
+ return 0;
+}
+
+static int
+acpimcfg_ext_conf_is_aliased(pci_chipset_tag_t pc, pcitag_t tag)
+{
+ pcireg_t id;
+ int i;
+
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+ for (i = PCI_CONF_SIZE; i < PCI_EXTCONF_SIZE; i += PCI_CONF_SIZE) {
+ if (pci_conf_read(pc, tag, i) != id)
+ return false;
+ }
+ return true;
+}
+
+static struct mcfg_segment *
+acpimcfg_get_segment(int bus)
+{
+ struct mcfg_segment *seg;
+ int i;
+
+ for (i = 0; i < mcfg_nsegs; i++) {
+ seg = &mcfg_segs[i];
+ if (bus >= seg->ms_bus_start && bus <= seg->ms_bus_end)
+ return seg;
+ }
+ return NULL;
+}
+
+static int
+acpimcfg_device_probe(const struct pci_attach_args *pa)
+{
+ pci_chipset_tag_t pc = pa->pa_pc;
+ struct mcfg_segment *seg;
+ struct mcfg_bus *mb;
+ pcitag_t tag;
+ pcireg_t reg;
+ int bus = pa->pa_bus;
+ int dev = pa->pa_device;
+ int func = pa->pa_function;
+ int last_dev, last_func, end_func;
+ int alias = 0;
+ int i, j;
+
+ seg = acpimcfg_get_segment(bus);
+ if (seg == NULL)
+ return 0;
+
+ mb = &seg->ms_bus[bus - seg->ms_bus_start];
+ tag = pci_make_tag(pc, bus, dev, func);
+
+ /* Mark invalid between last probed device to probed device. */
+ pci_decompose_tag(pc, mb->last_probed, NULL, &last_dev, &last_func);
+ if (dev != 0 || func != 0) {
+ for (i = last_dev; i <= dev; i++) {
+ end_func = (i == dev) ? func : 8;
+ for (j = last_func; j < end_func; j++) {
+ if (i == last_dev && j == last_func)
+ continue;
+ EXTCONF_SET_INVALID(mb, i, j);
+ }
+ last_func = 0;
+ }
+ }
+ mb->last_probed = tag;
+
+ /* Probe extended configuration space. */
+ if (((reg = pci_conf_read(pc, tag, PCI_CONF_SIZE)) == (pcireg_t)-1) ||
+ (alias = acpimcfg_ext_conf_is_aliased(pc, tag))) {
+ aprint_debug_dev(acpi_sc->sc_dev,
+ "MCFG: %03d:%02d:%d: invalid config space "
+ "(cfg[0x%03x]=0x%08x, alias=%s)\n", bus, dev, func,
+ PCI_CONF_SIZE, reg, alias ? "true" : "false");
+ EXTCONF_SET_INVALID(mb, dev, func);
+ } else {
+ aprint_debug_dev(acpi_sc->sc_dev,
+ "MCFG: %03d:%02d:%d: Ok (cfg[0x%03x]=0x%08x)\n",
+ bus, dev, func, PCI_CONF_SIZE, reg);
+ mb->valid_ndevs++;
+ }
+
+ return 0;
+}
+
+static void
+acpimcfg_scan_bus(struct pci_softc *sc, pci_chipset_tag_t pc, int bus)
+{
+ static const int wildcard[PCICF_NLOCS] = {
+ PCICF_DEV_DEFAULT, PCICF_FUNCTION_DEFAULT
+ };
+
+ sc->sc_bus = bus; /* XXX */
+
+ pci_enumerate_bus(sc, wildcard, acpimcfg_device_probe, NULL);
+}
+
+int
+acpimcfg_map_bus(device_t self, pci_chipset_tag_t pc, int bus)
+{
+ struct pci_softc *sc = device_private(self);
+ struct mcfg_segment *seg = NULL;
+ struct mcfg_bus *mb;
+ bus_space_handle_t bsh;
+ bus_addr_t baddr;
+ int boff;
+ int last_dev, last_func;
+ int i, j;
+ int error;
+
+ if (!mcfg_inited)
+ return ENXIO;
+
+ seg = acpimcfg_get_segment(bus);
+ if (seg == NULL)
+ return ENOENT;
+
+ boff = bus - seg->ms_bus_start;
+ if (seg->ms_bus[boff].valid_ndevs > 0)
+ return 0;
+
+ mb = &seg->ms_bus[boff];
+ baddr = seg->ms_address + (boff * ACPIMCFG_SIZE_PER_BUS);
+
+ /* Map extended configration space of all dev/func. */
+ error = bus_space_map(seg->ms_bst, baddr, ACPIMCFG_SIZE_PER_BUS, 0,
+ &bsh);
+ if (error != 0)
+ return error;
+ for (i = 0; i < 32; i++) {
+ for (j = 0; j < 8; j++) {
+ error = bus_space_subregion(seg->ms_bst, bsh,
+ EXTCONF_OFFSET(i, j, 0), PCI_EXTCONF_SIZE,
+ &mb->bsh[i][j]);
+ if (error != 0)
+ break;
+ }
+ }
+ if (error != 0)
+ return error;
+
+ aprint_debug("\n");
+
+ /* Probe extended configuration space of all devices. */
+ memset(mb->valid_devs, 0xff, sizeof(mb->valid_devs));
+ mb->valid_ndevs = 0;
+ mb->last_probed = pci_make_tag(pc, bus, 0, 0);
+
+ acpimcfg_scan_bus(sc, pc, bus);
+
+ /* Unmap extended configration space of all dev/func. */
+ bus_space_unmap(seg->ms_bst, bsh, ACPIMCFG_SIZE_PER_BUS);
+ memset(mb->bsh, 0, sizeof(mb->bsh));
+
+ if (mb->valid_ndevs == 0) {
+ aprint_debug_dev(acpi_sc->sc_dev,
+ "MCFG: bus %d: no valid devices.\n", bus);
+ memset(mb->valid_devs, 0, sizeof(mb->valid_devs));
+ goto out;
+ }
+
+ /* Mark invalid on remaining all devices. */
+ pci_decompose_tag(pc, mb->last_probed, NULL, &last_dev, &last_func);
+ for (i = last_dev; i < 32; i++) {
+ for (j = last_func; j < 8; j++) {
+ if (i == last_dev && j == last_func) {
+ /* Don't mark invalid to last probed device. */
+ continue;
+ }
+ EXTCONF_SET_INVALID(mb, i, j);
+ }
+ last_func = 0;
+ }
+
+ /* Map extended configuration space per dev/func. */
+ for (i = 0; i < 32; i++) {
+ for (j = 0; j < 8; j++) {
+ if (!EXTCONF_IS_VALID(mb, i, j))
+ continue;
+ error = bus_space_map(seg->ms_bst,
+ baddr + EXTCONF_OFFSET(i, j, 0), PCI_EXTCONF_SIZE,
+ 0, &mb->bsh[i][j]);
+ if (error != 0) {
+ /* Unmap all handles when map failed. */
+ do {
+ while (--j >= 0) {
+ if (!EXTCONF_IS_VALID(mb, i, j))
+ continue;
+ bus_space_unmap(seg->ms_bst,
+ mb->bsh[i][j],
+ PCI_EXTCONF_SIZE);
+ }
+ j = 8;
+ } while (--i >= 0);
+ memset(mb->valid_devs, 0,
+ sizeof(mb->valid_devs));
+ goto out;
+ }
+ }
+ }
+
+ aprint_debug_dev(acpi_sc->sc_dev, "MCFG: bus %d: valid devices\n", bus);
+ for (i = 0; i < 32; i++) {
+ for (j = 0; j < 8; j++) {
+ if (EXTCONF_IS_VALID(mb, i, j)) {
+ aprint_debug_dev(acpi_sc->sc_dev,
+ "MCFG: %03d:%02d:%d\n", bus, i, j);
+ }
+ }
+ }
+
+ error = 0;
+out:
+ aprint_debug_dev(acpi_sc->sc_dev, "%s done", __func__);
+
+ return error;
+}
+
+int
+acpimcfg_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t *data)
+{
+ struct mcfg_segment *seg = NULL;
+ struct mcfg_bus *mb;
+ int bus, dev, func;
+
+ KASSERT(reg < PCI_EXTCONF_SIZE);
+ KASSERT((reg & 3) == 0);
+
+ if (!mcfg_inited) {
+ *data = -1;
+ return ENXIO;
+ }
+
+ pci_decompose_tag(pc, tag, &bus, &dev, &func);
+
+ seg = acpimcfg_get_segment(bus);
+ if (seg == NULL) {
+ *data = -1;
+ return ERANGE;
+ }
+
+ mb = &seg->ms_bus[bus - seg->ms_bus_start];
+ if (!EXTCONF_IS_VALID(mb, dev, func)) {
+ *data = -1;
+ return EINVAL;
+ }
+
+ *data = mcfg_ops->ao_read(seg->ms_bst, mb->bsh[dev][func], reg);
+ return 0;
+}
+
+int
+acpimcfg_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
+{
+ struct mcfg_segment *seg = NULL;
+ struct mcfg_bus *mb;
+ int bus, dev, func;
+
+ KASSERT(reg < PCI_EXTCONF_SIZE);
+ KASSERT((reg & 3) == 0);
+
+ if (!mcfg_inited)
+ return ENXIO;
+
+ pci_decompose_tag(pc, tag, &bus, &dev, &func);
+
+ seg = acpimcfg_get_segment(bus);
+ if (seg == NULL)
+ return ERANGE;
+
+ mb = &seg->ms_bus[bus - seg->ms_bus_start];
+ if (!EXTCONF_IS_VALID(mb, dev, func))
+ return EINVAL;
+
+ mcfg_ops->ao_write(seg->ms_bst, mb->bsh[dev][func], reg, data);
+ return 0;
+}
diff --git a/sys/dev/acpi/acpi_mcfg.h b/sys/dev/acpi/acpi_mcfg.h
new file mode 100644
index 00000000000..b67c360373c
--- /dev/null
+++ b/sys/dev/acpi/acpi_mcfg.h
@@ -0,0 +1,58 @@
+/* $NetBSD: acpi_mcfg.h,v 1.1 2015/10/02 05:22:52 msaitoh Exp $ */
+
+/*-
+ * Copyright (C) 2015 NONAKA Kimihiro <nonaka@NetBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_DEV_ACPI_ACPI_MCFG_H
+#define _SYS_DEV_ACPI_ACPI_MCFG_H
+
+struct acpimcfg_ops;
+void acpimcfg_probe(struct acpi_softc *);
+int acpimcfg_init(bus_space_tag_t, const struct acpimcfg_ops *);
+int acpimcfg_map_bus(device_t, pci_chipset_tag_t, int);
+
+int acpimcfg_conf_read(pci_chipset_tag_t, pcitag_t, int, pcireg_t *);
+int acpimcfg_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t);
+
+struct acpimcfg_ops {
+ /* validate MCFG memory region */
+ bool (*ao_validate)(uint64_t, int, int *);
+
+ /* override default bus_space(9) function */
+ uint32_t (*ao_read)(bus_space_tag_t, bus_space_handle_t,
+ bus_addr_t);
+ void (*ao_write)(bus_space_tag_t, bus_space_handle_t,
+ bus_addr_t, uint32_t);
+};
+
+#define ACPIMCFG_SIZE_PER_BUS (PCI_EXTCONF_SIZE * 32/*dev*/ * 8/*func*/)
+
+bool acpimcfg_default_validate(uint64_t, int, int *);
+uint32_t acpimcfg_default_read(bus_space_tag_t, bus_space_handle_t,
+ bus_addr_t);
+void acpimcfg_default_write(bus_space_tag_t, bus_space_handle_t,
+ bus_addr_t, uint32_t);
+
+#endif /* _SYS_DEV_ACPI_ACPI_PCI_H */
diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi
index e08e4fed80d..514f27df64d 100644
--- a/sys/dev/acpi/files.acpi
+++ b/sys/dev/acpi/files.acpi
@@ -1,4 +1,4 @@
-# $NetBSD: files.acpi,v 1.96 2015/09/21 12:32:06 nonaka Exp $
+# $NetBSD: files.acpi,v 1.97 2015/10/02 05:22:52 msaitoh Exp $
include "dev/acpi/acpica/files.acpica"
@@ -18,6 +18,7 @@ device acpi: acpica, acpiapmbus, acpinodebus, acpiecdtbus, acpihpetbus, acpiwdrt
attach acpi at acpibus
file dev/acpi/acpi.c acpi
file dev/acpi/acpi_debug.c acpi
+file dev/acpi/acpi_mcfg.c acpi
file dev/acpi/acpi_pci.c acpi
file dev/acpi/acpi_pci_link.c acpi
file dev/acpi/acpi_power.c acpi
diff --git a/sys/dev/marvell/gtpci.c b/sys/dev/marvell/gtpci.c
index 5d52cd7f866..88014b130f0 100644
--- a/sys/dev/marvell/gtpci.c
+++ b/sys/dev/marvell/gtpci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: gtpci.c,v 1.31 2013/11/06 06:20:12 mrg Exp $ */
+/* $NetBSD: gtpci.c,v 1.32 2015/10/02 05:22:52 msaitoh Exp $ */
/*
* Copyright (c) 2008, 2009 KIYOHARA Takashi
* All rights reserved.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gtpci.c,v 1.31 2013/11/06 06:20:12 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gtpci.c,v 1.32 2015/10/02 05:22:52 msaitoh Exp $");
#include "opt_pci.h"
#include "pci.h"
@@ -567,6 +567,9 @@ gtpci_conf_read(void *v, pcitag_t tag, int reg)
struct gtpci_softc *sc = v;
const pcireg_t addr = tag | reg;
+ if ((unsigned int)reg >= PCI_CONF_SIZE)
+ return -1;
+
GTPCI_WRITE(sc, GTPCI_CA, addr | GTPCI_CA_CONFIGEN);
if ((addr | GTPCI_CA_CONFIGEN) != GTPCI_READ(sc, GTPCI_CA))
return -1;
@@ -580,6 +583,9 @@ gtpci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
struct gtpci_softc *sc = v;
pcireg_t addr = tag | (reg & 0xfc);
+ if ((unsigned int)reg >= PCI_CONF_SIZE)
+ return;
+
GTPCI_WRITE(sc, GTPCI_CA, addr | GTPCI_CA_CONFIGEN);
if ((addr | GTPCI_CA_CONFIGEN) != GTPCI_READ(sc, GTPCI_CA))
return;
diff --git a/sys/dev/marvell/mvpex.c b/sys/dev/marvell/mvpex.c
index 2a697022ec3..f291b01ebea 100644
--- a/sys/dev/marvell/mvpex.c
+++ b/sys/dev/marvell/mvpex.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mvpex.c,v 1.14 2015/07/28 01:57:55 knakahara Exp $ */
+/* $NetBSD: mvpex.c,v 1.15 2015/10/02 05:22:52 msaitoh Exp $ */
/*
* Copyright (c) 2008 KIYOHARA Takashi
* All rights reserved.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mvpex.c,v 1.14 2015/07/28 01:57:55 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvpex.c,v 1.15 2015/10/02 05:22:52 msaitoh Exp $");
#include "opt_pci.h"
#include "pci.h"
@@ -507,6 +507,9 @@ mvpex_conf_read(void *v, pcitag_t tag, int reg)
uint32_t stat;
int bus, dev, func, pexbus, pexdev;
+ if ((unsigned int)reg >= PCI_EXTCONF_SIZE)
+ return -1;
+
mvpex_decompose_tag(v, tag, &bus, &dev, &func);
stat = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVPEX_STAT);
@@ -552,6 +555,9 @@ mvpex_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
uint32_t stat;
int bus, dev, func, pexbus, pexdev;
+ if ((unsigned int)reg >= PCI_EXTCONF_SIZE)
+ return;
+
mvpex_decompose_tag(v, tag, &bus, &dev, &func);
stat = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVPEX_STAT);
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index ec928d5909e..674e1332623 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pci.c,v 1.148 2015/08/24 23:55:04 pooka Exp $ */
+/* $NetBSD: pci.c,v 1.149 2015/10/02 05:22:53 msaitoh Exp $ */
/*
* Copyright (c) 1995, 1996, 1997, 1998
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.148 2015/08/24 23:55:04 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.149 2015/10/02 05:22:53 msaitoh Exp $");
#ifdef _KERNEL_OPT
#include "opt_pci.h"
@@ -68,9 +68,6 @@ int pciprint(void *, const char *);
#ifdef PCI_MACHDEP_ENUMERATE_BUS
#define pci_enumerate_bus PCI_MACHDEP_ENUMERATE_BUS
-#else
-int pci_enumerate_bus(struct pci_softc *, const int *,
- int (*)(const struct pci_attach_args *), struct pci_attach_args *);
#endif
/*
@@ -614,6 +611,43 @@ pci_msix_count(pci_chipset_tag_t pc, pcitag_t tag)
}
int
+pci_get_ext_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid,
+ int *offset, pcireg_t *value)
+{
+ pcireg_t reg;
+ unsigned int ofs;
+
+ /* Only supported for PCI-express devices */
+ if (!pci_get_capability(pc, tag, PCI_CAP_PCIEXPRESS, NULL, NULL))
+ return 0;
+
+ ofs = PCI_EXTCAPLIST_BASE;
+ reg = pci_conf_read(pc, tag, ofs);
+ if (reg == 0xffffffff || reg == 0)
+ return 0;
+
+ for (;;) {
+#ifdef DIAGNOSTIC
+ if ((ofs & 3) || ofs < PCI_EXTCAPLIST_BASE)
+ panic("%s: invalid offset %u", __func__, ofs);
+#endif
+ if (PCI_EXTCAPLIST_CAP(reg) == capid) {
+ if (offset != NULL)
+ *offset = ofs;
+ if (value != NULL)
+ *value = reg;
+ return 1;
+ }
+ ofs = PCI_EXTCAPLIST_NEXT(reg);
+ if (ofs == 0)
+ break;
+ reg = pci_conf_read(pc, tag, ofs);
+ }
+
+ return 0;
+}
+
+int
pci_find_device(struct pci_attach_args *pa,
int (*match)(const struct pci_attach_args *))
{
diff --git a/sys/dev/pci/pci_subr.c b/sys/dev/pci/pci_subr.c
index a2353191c4a..20a8b669a66 100644
--- a/sys/dev/pci/pci_subr.c
+++ b/sys/dev/pci/pci_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_subr.c,v 1.134 2015/07/27 15:46:03 msaitoh Exp $ */
+/* $NetBSD: pci_subr.c,v 1.135 2015/10/02 05:22:53 msaitoh Exp $ */
/*
* Copyright (c) 1997 Zubin D. Dittia. All rights reserved.
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.134 2015/07/27 15:46:03 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.135 2015/10/02 05:22:53 msaitoh Exp $");
#ifdef _KERNEL_OPT
#include "opt_pci.h"
@@ -56,6 +56,7 @@ __KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.134 2015/07/27 15:46:03 msaitoh Exp $
#include <pci.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#endif
@@ -1841,6 +1842,26 @@ static struct {
{ PCI_CAP_PCIAF, "Advanced Features", pci_conf_print_pciaf_cap }
};
+static int
+pci_conf_find_cap(const pcireg_t *regs, int capoff, unsigned int capid,
+ int *offsetp)
+{
+ pcireg_t rval;
+ int off;
+
+ for (off = PCI_CAPLIST_PTR(regs[o2i(capoff)]);
+ off != 0;
+ off = PCI_CAPLIST_NEXT(rval)) {
+ rval = regs[o2i(off)];
+ if (capid == PCI_CAPLIST_CAP(rval)) {
+ if (offsetp != NULL)
+ *offsetp = off;
+ return 1;
+ }
+ }
+ return 0;
+}
+
static void
pci_conf_print_caplist(
#ifdef _KERNEL
@@ -1889,16 +1910,1177 @@ pci_conf_print_caplist(
* the same. This is required because some capabilities
* appear multiple times (e.g. HyperTransport capability).
*/
- for (off = PCI_CAPLIST_PTR(regs[o2i(capoff)]);
- off != 0;
- off = PCI_CAPLIST_NEXT(regs[o2i(off)])) {
+ if (pci_conf_find_cap(regs, capoff, i, &off)) {
rval = regs[o2i(off)];
- foundcap = PCI_CAPLIST_CAP(rval);
- if ((i == foundcap)
- && (pci_captab[foundcap].printfunc != NULL))
- pci_captab[foundcap].printfunc(regs, off);
+ if (pci_captab[i].printfunc != NULL)
+ pci_captab[i].printfunc(regs, off);
+ }
+ }
+}
+
+/* Extended Capability */
+
+static void
+pci_conf_print_aer_cap_uc(pcireg_t reg)
+{
+
+ onoff("Undefined", reg, PCI_AER_UC_UNDEFINED);
+ onoff("Data Link Protocol Error", reg, PCI_AER_UC_DL_PROTOCOL_ERROR);
+ onoff("Surprise Down Error", reg, PCI_AER_UC_SURPRISE_DOWN_ERROR);
+ onoff("Poisoned TLP", reg, PCI_AER_UC_POISONED_TLP);
+ onoff("Flow Control Protocol Error", reg, PCI_AER_UC_FC_PROTOCOL_ERROR);
+ onoff("Completion Timeout", reg, PCI_AER_UC_COMPLETION_TIMEOUT);
+ onoff("Completer Abort", reg, PCI_AER_UC_COMPLETER_ABORT);
+ onoff("Unexpected Completion", reg, PCI_AER_UC_UNEXPECTED_COMPLETION);
+ onoff("Receiver Overflow", reg, PCI_AER_UC_RECEIVER_OVERFLOW);
+ onoff("Malformed TLP", reg, PCI_AER_UC_MALFORMED_TLP);
+ onoff("ECRC Error", reg, PCI_AER_UC_ECRC_ERROR);
+ onoff("Unsupported Request Error", reg,
+ PCI_AER_UC_UNSUPPORTED_REQUEST_ERROR);
+ onoff("ACS Violation", reg, PCI_AER_UC_ACS_VIOLATION);
+ onoff("Uncorrectable Internal Error", reg, PCI_AER_UC_INTERNAL_ERROR);
+ onoff("MC Blocked TLP", reg, PCI_AER_UC_MC_BLOCKED_TLP);
+ onoff("AtomicOp Egress BLK", reg, PCI_AER_UC_ATOMIC_OP_EGRESS_BLOCKED);
+ onoff("TLP Prefix Blocked Error", reg,
+ PCI_AER_UC_TLP_PREFIX_BLOCKED_ERROR);
+}
+
+static void
+pci_conf_print_aer_cap_cor(pcireg_t reg)
+{
+
+ onoff("Receiver Error", reg, PCI_AER_COR_RECEIVER_ERROR);
+ onoff("Bad TLP", reg, PCI_AER_COR_BAD_TLP);
+ onoff("Bad DLLP", reg, PCI_AER_COR_BAD_DLLP);
+ onoff("REPLAY_NUM Rollover", reg, PCI_AER_COR_REPLAY_NUM_ROLLOVER);
+ onoff("Replay Timer Timeout", reg, PCI_AER_COR_REPLAY_TIMER_TIMEOUT);
+ onoff("Advisory Non-Fatal Error", reg, PCI_AER_COR_ADVISORY_NF_ERROR);
+ onoff("Corrected Internal Error", reg, PCI_AER_COR_INTERNAL_ERROR);
+ onoff("Header Log Overflow", reg, PCI_AER_COR_HEADER_LOG_OVERFLOW);
+}
+
+static void
+pci_conf_print_aer_cap_control(pcireg_t reg, bool *tlp_prefix_log)
+{
+
+ printf(" First Error Pointer: 0x%04x\n",
+ (pcireg_t)__SHIFTOUT(reg, PCI_AER_FIRST_ERROR_PTR));
+ onoff("ECRC Generation Capable", reg, PCI_AER_ECRC_GEN_CAPABLE);
+ onoff("ECRC Generation Enable", reg, PCI_AER_ECRC_GEN_ENABLE);
+ onoff("ECRC Check Capable", reg, PCI_AER_ECRC_CHECK_CAPABLE);
+ onoff("ECRC Check Enab", reg, PCI_AER_ECRC_CHECK_ENABLE);
+ onoff("Multiple Header Recording Capable", reg,
+ PCI_AER_MULT_HDR_CAPABLE);
+ onoff("Multiple Header Recording Enable", reg, PCI_AER_MULT_HDR_ENABLE);
+
+ /* This bit is RsvdP if the End-End TLP Prefix Supported bit is Clear */
+ if (!tlp_prefix_log)
+ return;
+ onoff("TLP Prefix Log Present", reg, PCI_AER_TLP_PREFIX_LOG_PRESENT);
+ *tlp_prefix_log = (reg & PCI_AER_TLP_PREFIX_LOG_PRESENT) ? true : false;
+}
+
+static void
+pci_conf_print_aer_cap_rooterr_cmd(pcireg_t reg)
+{
+
+ onoff("Correctable Error Reporting Enable", reg,
+ PCI_AER_ROOTERR_COR_ENABLE);
+ onoff("Non-Fatal Error Reporting Enable", reg,
+ PCI_AER_ROOTERR_NF_ENABLE);
+ onoff("Fatal Error Reporting Enable", reg, PCI_AER_ROOTERR_F_ENABLE);
+}
+
+static void
+pci_conf_print_aer_cap_rooterr_status(pcireg_t reg)
+{
+
+ onoff("ERR_COR Received", reg, PCI_AER_ROOTERR_COR_ERR);
+ onoff("Multiple ERR_COR Received", reg, PCI_AER_ROOTERR_MULTI_COR_ERR);
+ onoff("ERR_FATAL/NONFATAL_ERR Received", reg, PCI_AER_ROOTERR_UC_ERR);
+ onoff("Multiple ERR_FATAL/NONFATAL_ERR Received", reg,
+ PCI_AER_ROOTERR_MULTI_UC_ERR);
+ onoff("First Uncorrectable Fatal", reg, PCI_AER_ROOTERR_FIRST_UC_FATAL);
+ onoff("Non-Fatal Error Messages Received", reg, PCI_AER_ROOTERR_NF_ERR);
+ onoff("Fatal Error Messages Received", reg, PCI_AER_ROOTERR_F_ERR);
+ printf(" Advanced Error Interrupt Message Number: 0x%u\n",
+ (pcireg_t)__SHIFTOUT(reg, PCI_AER_ROOTERR_INT_MESSAGE));
+}
+
+static void
+pci_conf_print_aer_cap_errsrc_id(pcireg_t reg)
+{
+
+ printf(" Correctable Source ID: 0x%04x\n",
+ (pcireg_t)__SHIFTOUT(reg, PCI_AER_ERRSRC_ID_ERR_COR));
+ printf(" ERR_FATAL/NONFATAL Source ID: 0x%04x\n",
+ (pcireg_t)__SHIFTOUT(reg, PCI_AER_ERRSRC_ID_ERR_UC));
+}
+
+static void
+pci_conf_print_aer_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg;
+ int pcie_capoff;
+ int pcie_devtype = -1;
+ bool tlp_prefix_log = false;
+
+ if (pci_conf_find_cap(regs, capoff, PCI_CAP_PCIEXPRESS, &pcie_capoff)) {
+ reg = regs[o2i(pcie_capoff)];
+ pcie_devtype = reg & PCIE_XCAP_TYPE_MASK;
+ /* PCIe DW9 to DW14 is for PCIe 2.0 and newer */
+ if (__SHIFTOUT(reg, PCIE_XCAP_VER_MASK) >= 2) {
+ reg = regs[o2i(pcie_capoff + PCIE_DCAP2)];
+ /* End-End TLP Prefix Supported */
+ if (reg & PCIE_DCAP2_EETLP_PREF) {
+ tlp_prefix_log = true;
+ }
}
}
+
+ printf("\n Advanced Error Reporting Register\n");
+
+ reg = regs[o2i(extcapoff + PCI_AER_UC_STATUS)];
+ printf(" Uncorrectable Error Status register: 0x%08x\n", reg);
+ pci_conf_print_aer_cap_uc(reg);
+ reg = regs[o2i(extcapoff + PCI_AER_UC_MASK)];
+ printf(" Uncorrectable Error Mask register: 0x%08x\n", reg);
+ pci_conf_print_aer_cap_uc(reg);
+ reg = regs[o2i(extcapoff + PCI_AER_UC_SEVERITY)];
+ printf(" Uncorrectable Error Severity register: 0x%08x\n", reg);
+ pci_conf_print_aer_cap_uc(reg);
+
+ reg = regs[o2i(extcapoff + PCI_AER_COR_STATUS)];
+ printf(" Correctable Error Status register: 0x%08x\n", reg);
+ pci_conf_print_aer_cap_cor(reg);
+ reg = regs[o2i(extcapoff + PCI_AER_COR_MASK)];
+ printf(" Correctable Error Mask register: 0x%08x\n", reg);
+ pci_conf_print_aer_cap_cor(reg);
+
+ reg = regs[o2i(extcapoff + PCI_AER_CAP_CONTROL)];
+ printf(" Advanced Error Capabilities and Control register: 0x%08x\n",
+ reg);
+ pci_conf_print_aer_cap_control(reg, &tlp_prefix_log);
+ reg = regs[o2i(extcapoff + PCI_AER_HEADER_LOG)];
+ printf(" Header Log register:\n");
+ pci_conf_print_regs(regs, extcapoff + PCI_AER_HEADER_LOG,
+ extcapoff + PCI_AER_ROOTERR_CMD);
+
+ switch (pcie_devtype) {
+ case PCIE_XCAP_TYPE_ROOT: /* Root Port of PCI Express Root Complex */
+ case PCIE_XCAP_TYPE_ROOT_EVNTC: /* Root Complex Event Collector */
+ reg = regs[o2i(extcapoff + PCI_AER_ROOTERR_CMD)];
+ printf(" Root Error Command register: 0x%08x\n", reg);
+ pci_conf_print_aer_cap_rooterr_cmd(reg);
+ reg = regs[o2i(extcapoff + PCI_AER_ROOTERR_STATUS)];
+ printf(" Root Error Status register: 0x%08x\n", reg);
+ pci_conf_print_aer_cap_rooterr_status(reg);
+
+ reg = regs[o2i(extcapoff + PCI_AER_ERRSRC_ID)];
+ printf(" Error Source Identification: 0x%04x\n", reg);
+ pci_conf_print_aer_cap_errsrc_id(reg);
+ break;
+ }
+
+ if (tlp_prefix_log) {
+ reg = regs[o2i(extcapoff + PCI_AER_TLP_PREFIX_LOG)];
+ printf(" TLP Prefix Log register: 0x%08x\n", reg);
+ }
+}
+
+static void
+pci_conf_print_vc_cap_arbtab(const pcireg_t *regs, int off, const char *name,
+ pcireg_t parbsel, int parbsize)
+{
+ pcireg_t reg;
+ int num = 16 << parbsel;
+ int num_per_reg = sizeof(pcireg_t) / parbsize;
+ int i, j;
+
+ /* First, dump the table */
+ for (i = 0; i < num; i += num_per_reg) {
+ reg = regs[o2i(off + i / num_per_reg)];
+ printf(" %s Arbitration Table: 0x%08x\n", name, reg);
+ }
+ /* And then, decode each entry */
+ for (i = 0; i < num; i += num_per_reg) {
+ reg = regs[o2i(off + i / num_per_reg)];
+ for (j = 0; j < num_per_reg; j++)
+ printf(" Phase[%d]: %d\n", j, reg);
+ }
+}
+
+static void
+pci_conf_print_vc_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg, n;
+ int parbtab, parbsize;
+ pcireg_t parbsel;
+ int varbtab, varbsize;
+ pcireg_t varbsel;
+ int i, count;
+
+ printf("\n Virtual Channel Register\n");
+ reg = regs[o2i(extcapoff + PCI_VC_CAP1)];
+ printf(" Port VC Capability register 1: 0x%08x\n", reg);
+ count = __SHIFTOUT(reg, PCI_VC_CAP1_EXT_COUNT);
+ printf(" Extended VC Count: %d\n", count);
+ n = __SHIFTOUT(reg, PCI_VC_CAP1_LOWPRI_EXT_COUNT);
+ printf(" Low Priority Extended VC Count: %u\n", n);
+ n = __SHIFTOUT(reg, PCI_VC_CAP1_REFCLK);
+ printf(" Reference Clock: %s\n",
+ (n == PCI_VC_CAP1_REFCLK_100NS) ? "100" : "unknown");
+ parbsize = 1 << __SHIFTOUT(reg, PCI_VC_CAP1_PORT_ARB_TABLE_SIZE);
+ printf(" Port Arbitration Table Entry Size: %dbit\n", parbsize);
+
+ reg = regs[o2i(extcapoff + PCI_VC_CAP2)];
+ printf(" Port VC Capability register 2: 0x%08x\n", reg);
+ onoff("Hardware fixed arbitration scheme",
+ reg, PCI_VC_CAP2_ARB_CAP_HW_FIXED_SCHEME);
+ onoff("WRR arbitration with 32 phases",
+ reg, PCI_VC_CAP2_ARB_CAP_WRR_32);
+ onoff("WRR arbitration with 64 phases",
+ reg, PCI_VC_CAP2_ARB_CAP_WRR_64);
+ onoff("WRR arbitration with 128 phases",
+ reg, PCI_VC_CAP2_ARB_CAP_WRR_128);
+ varbtab = __SHIFTOUT(reg, PCI_VC_CAP2_ARB_TABLE_OFFSET);
+ printf(" VC Arbitration Table Offset: 0x%x\n", varbtab);
+
+ reg = regs[o2i(extcapoff + PCI_VC_CONTROL)] & 0xffff;
+ printf(" Port VC Control register: 0x%04x\n", reg);
+ varbsel = __SHIFTOUT(reg, PCI_VC_CONTROL_VC_ARB_SELECT);
+ printf(" VC Arbitration Select: 0x%x\n", varbsel);
+
+ reg = regs[o2i(extcapoff + PCI_VC_STATUS)] >> 16;
+ printf(" Port VC Status register: 0x%04x\n", reg);
+ onoff("VC Arbitration Table Status",
+ reg, PCI_VC_STATUS_LOAD_VC_ARB_TABLE);
+
+ for (i = 0; i < count + 1; i++) {
+ reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_CAP(i))];
+ printf(" VC number %d\n", i);
+ printf(" VC Resource Capability Register: 0x%08x\n", reg);
+ onoff(" Non-configurable Hardware fixed arbitration scheme",
+ reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_HW_FIXED_SCHEME);
+ onoff(" WRR arbitration with 32 phases",
+ reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_32);
+ onoff(" WRR arbitration with 64 phases",
+ reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_64);
+ onoff(" WRR arbitration with 128 phases",
+ reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_128);
+ onoff(" Time-based WRR arbitration with 128 phases",
+ reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_TWRR_128);
+ onoff(" WRR arbitration with 256 phases",
+ reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_256);
+ onoff(" Advanced Packet Switching",
+ reg, PCI_VC_RESOURCE_CAP_ADV_PKT_SWITCH);
+ onoff(" Reject Snoop Transaction",
+ reg, PCI_VC_RESOURCE_CAP_REJCT_SNOOP_TRANS);
+ n = __SHIFTOUT(reg, PCI_VC_RESOURCE_CAP_MAX_TIME_SLOTS) + 1;
+ printf(" Maximum Time Slots: %d\n", n);
+ parbtab = reg >> PCI_VC_RESOURCE_CAP_PORT_ARB_TABLE_OFFSET_S;
+ printf(" Port Arbitration Table offset: 0x%02x\n",
+ parbtab);
+
+ reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_CTL(i))];
+ printf(" VC Resource Control Register: 0x%08x\n", reg);
+ printf(" TC/VC Map: %02x\n",
+ (pcireg_t)__SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_TCVC_MAP));
+ /*
+ * The load Port Arbitration Table bit is used to update
+ * the Port Arbitration logic and it's always 0 on read, so
+ * we don't print it.
+ */
+ parbsel = __SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_PORT_ARB_SELECT);
+ printf(" Port Arbitration Select: %x\n", parbsel);
+ n = __SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_VC_ID);
+ printf(" VC ID %d\n", n);
+ onoff(" VC Enable", reg, PCI_VC_RESOURCE_CTL_VC_ENABLE);
+
+ reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_STA(i))] >> 16;
+ printf(" VC Resource Status Register: 0x%08x\n", reg);
+ onoff(" Port Arbitration Table Status",
+ reg, PCI_VC_RESOURCE_STA_PORT_ARB_TABLE);
+ onoff(" VC Negotiation Pending",
+ reg, PCI_VC_RESOURCE_STA_VC_NEG_PENDING);
+
+ if ((parbtab != 0) && (parbsel != 0))
+ pci_conf_print_vc_cap_arbtab(regs, extcapoff + parbtab,
+ "Port", parbsel, parbsize);
+ }
+
+ varbsize = 8;
+ if ((varbtab != 0) && (varbsel != 0))
+ pci_conf_print_vc_cap_arbtab(regs, extcapoff + varbtab,
+ " VC", varbsel, varbsize);
+}
+
+static const char *
+pci_conf_print_pwrbdgt_base_power(uint8_t reg)
+{
+
+ switch (reg) {
+ case 0xf0:
+ return "250W";
+ case 0xf1:
+ return "275W";
+ case 0xf2:
+ return "300W";
+ default:
+ return "Unknown";
+ }
+}
+
+static const char *
+pci_conf_print_pwrbdgt_data_scale(uint8_t reg)
+{
+
+ switch (reg) {
+ case 0x00:
+ return "1.0x";
+ case 0x01:
+ return "0.1x";
+ case 0x02:
+ return "0.01x";
+ case 0x03:
+ return "0.001x";
+ default:
+ return "wrong value!";
+ }
+}
+
+static const char *
+pci_conf_print_pwrbdgt_type(uint8_t reg)
+{
+
+ switch (reg) {
+ case 0x00:
+ return "PME Aux";
+ case 0x01:
+ return "Auxilary";
+ case 0x02:
+ return "Idle";
+ case 0x03:
+ return "Sustained";
+ case 0x07:
+ return "Maximun";
+ default:
+ return "Unknown";
+ }
+}
+
+static const char *
+pci_conf_print_pwrbdgt_pwrrail(uint8_t reg)
+{
+
+ switch (reg) {
+ case 0x00:
+ return "Power(12V)";
+ case 0x01:
+ return "Power(3.3V)";
+ case 0x02:
+ return "Power(1.5V or 1.8V)";
+ case 0x07:
+ return "Thermal";
+ default:
+ return "Unknown";
+ }
+}
+
+static void
+pci_conf_print_pwrbdgt_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg;
+
+ printf("\n Power Budget Register\n");
+
+ reg = regs[o2i(extcapoff + PCI_PWRBDGT_DSEL)];
+ printf(" Data Select register: 0x%08x\n", reg);
+
+ reg = regs[o2i(extcapoff + PCI_PWRBDGT_DATA)];
+ printf(" Data register: 0x%08x\n", reg);
+ printf(" Base Power: %s\n",
+ pci_conf_print_pwrbdgt_base_power((uint8_t)reg));
+ printf(" Data Scale: %s\n",
+ pci_conf_print_pwrbdgt_data_scale(
+ (uint8_t)(__SHIFTOUT(reg, PCI_PWRBDGT_DATA_SCALE))));
+ printf(" PM Sub State: 0x%hhx\n",
+ (uint8_t)__SHIFTOUT(reg, PCI_PWRBDGT_PM_SUBSTAT));
+ printf(" PM State: D%u\n",
+ (unsigned int)__SHIFTOUT(reg, PCI_PWRBDGT_PM_STAT));
+ printf(" Type: %s\n",
+ pci_conf_print_pwrbdgt_type(
+ (uint8_t)(__SHIFTOUT(reg, PCI_PWRBDGT_TYPE))));
+ printf(" Power Rail: %s\n",
+ pci_conf_print_pwrbdgt_pwrrail(
+ (uint8_t)(__SHIFTOUT(reg, PCI_PWRBDGT_PWRRAIL))));
+
+ reg = regs[o2i(extcapoff + PCI_PWRBDGT_CAP)];
+ printf(" Power Budget Capability register: 0x%08x\n", reg);
+ onoff("System Allocated",
+ reg, PCI_PWRBDGT_CAP_SYSALLOC);
+}
+
+static const char *
+pci_conf_print_rclink_dcl_cap_elmtype(unsigned char type)
+{
+
+ switch (type) {
+ case 0x00:
+ return "Configuration Space Element";
+ case 0x01:
+ return "System Egress Port or internal sink (memory)";
+ case 0x02:
+ return "Internal Root Complex Link";
+ default:
+ return "Unknown";
+ }
+}
+
+static void
+pci_conf_print_rclink_dcl_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg;
+ unsigned char nent, linktype;
+ int i;
+
+ printf("\n Root Complex Link Declaration\n");
+
+ reg = regs[o2i(extcapoff + PCI_RCLINK_DCL_ESDESC)];
+ printf(" Element Self Description Register: 0x%08x\n", reg);
+ printf(" Element Type: %s\n",
+ pci_conf_print_rclink_dcl_cap_elmtype((unsigned char)reg));
+ nent = __SHIFTOUT(reg, PCI_RCLINK_DCL_ESDESC_NUMLINKENT);
+ printf(" Number of Link Entries: %hhu\n", nent);
+ printf(" Component ID: %hhu\n",
+ (uint8_t)__SHIFTOUT(reg, PCI_RCLINK_DCL_ESDESC_COMPID));
+ printf(" Port Number: %hhu\n",
+ (uint8_t)__SHIFTOUT(reg, PCI_RCLINK_DCL_ESDESC_PORTNUM));
+ for (i = 0; i < nent; i++) {
+ reg = regs[o2i(extcapoff + PCI_RCLINK_DCL_LINKDESC(i))];
+ printf(" Link Description Register: 0x%08x\n", reg);
+ onoff("Link Valid", reg,PCI_RCLINK_DCL_LINKDESC_LVALID);
+ linktype = reg & PCI_RCLINK_DCL_LINKDESC_LTYPE;
+ onoff2("Link Type", reg, PCI_RCLINK_DCL_LINKDESC_LTYPE,
+ "Configuration Space", "Memory-Mapped Space");
+ onoff("Associated RCRB Header", reg,
+ PCI_RCLINK_DCL_LINKDESC_ARCRBH);
+ printf(" Target Component ID: %hhu\n",
+ (unsigned char)__SHIFTOUT(reg,
+ PCI_RCLINK_DCL_LINKDESC_TCOMPID));
+ printf(" Target Port Number: %hhu\n",
+ (unsigned char)__SHIFTOUT(reg,
+ PCI_RCLINK_DCL_LINKDESC_TPNUM));
+
+ if (linktype == 0) {
+ /* Memory-Mapped Space */
+ reg = regs[o2i(extcapoff
+ + PCI_RCLINK_DCL_LINKADDR_LT0_LO(i))];
+ printf(" Link Address Low Register: 0x%08x\n", reg);
+ reg = regs[o2i(extcapoff
+ + PCI_RCLINK_DCL_LINKADDR_LT0_HI(i))];
+ printf(" Link Address High Register: 0x%08x\n",reg);
+ } else {
+ unsigned int nb;
+ pcireg_t lo, hi;
+
+ /* Configuration Space */
+ lo = regs[o2i(extcapoff
+ + PCI_RCLINK_DCL_LINKADDR_LT1_LO(i))];
+ printf(" Configuration Space Low Register: 0x%08x"
+ "\n", lo);
+ hi = regs[o2i(extcapoff
+ + PCI_RCLINK_DCL_LINKADDR_LT1_HI(i))];
+ printf(" Configuration Space High Register: 0x%08x"
+ "\n", hi);
+ nb = __SHIFTOUT(lo, PCI_RCLINK_DCL_LINKADDR_LT1_N);
+ printf(" N: %u\n", nb);
+ printf(" Func: %hhu\n",
+ (unsigned char)__SHIFTOUT(lo,
+ PCI_RCLINK_DCL_LINKADDR_LT1_FUNC));
+ printf(" Dev: %hhu\n",
+ (unsigned char)__SHIFTOUT(lo,
+ PCI_RCLINK_DCL_LINKADDR_LT1_DEV));
+ printf(" Bus: %hhu\n",
+ (unsigned char)__SHIFTOUT(lo,
+ PCI_RCLINK_DCL_LINKADDR_LT1_BUS(nb)));
+ lo &= PCI_RCLINK_DCL_LINKADDR_LT1_BAL(i);
+ printf(" Configuration Space Base Address: 0x%016"
+ PRIx64 "\n", ((uint64_t)hi << 32) + lo);
+ }
+ }
+}
+
+/* XXX pci_conf_print_rclink_ctl_cap */
+
+static void
+pci_conf_print_rcec_assoc_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg;
+
+ printf("\n Root Complex Event Collector Association\n");
+
+ reg = regs[o2i(extcapoff + PCI_RCEC_ASSOC_ASSOCBITMAP)];
+ printf(" Association Bitmap for Root Complex Integrated Devices:"
+ " 0x%08x\n", reg);
+}
+
+/* XXX pci_conf_print_mfvc_cap */
+/* XXX pci_conf_print_vc2_cap */
+/* XXX pci_conf_print_rcrb_cap */
+/* XXX pci_conf_print_vendor_cap */
+/* XXX pci_conf_print_cac_cap */
+
+static void
+pci_conf_print_acs_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg, cap, ctl;
+ unsigned int size, i;
+
+ printf("\n Access Control Services\n");
+
+ reg = regs[o2i(extcapoff + PCI_ACS_CAP)];
+ cap = reg & 0xffff;
+ ctl = reg >> 16;
+ printf(" ACS Capability register: 0x%08x\n", cap);
+ onoff("ACS Source Validation", cap, PCI_ACS_CAP_V);
+ onoff("ACS Transaction Blocking", cap, PCI_ACS_CAP_B);
+ onoff("ACS P2P Request Redirect", cap, PCI_ACS_CAP_R);
+ onoff("ACS P2P Completion Redirect", cap, PCI_ACS_CAP_C);
+ onoff("ACS Upstream Forwarding", cap, PCI_ACS_CAP_U);
+ onoff("ACS Egress Control", cap, PCI_ACS_CAP_E);
+ onoff("ACS Direct Translated P2P", cap, PCI_ACS_CAP_T);
+ size = __SHIFTOUT(cap, PCI_ACS_CAP_ECVSIZE);
+ if (size == 0)
+ size = 256;
+ printf(" Egress Control Vector Size: %u\n", size);
+ printf(" ACS Control register: 0x%08x\n", ctl);
+ onoff("ACS Source Validation Enable", ctl, PCI_ACS_CTL_V);
+ onoff("ACS Transaction Blocking Enable", ctl, PCI_ACS_CTL_B);
+ onoff("ACS P2P Request Redirect Enable", ctl, PCI_ACS_CTL_R);
+ onoff("ACS P2P Completion Redirect Enable", ctl, PCI_ACS_CTL_C);
+ onoff("ACS Upstream Forwarding Enable", ctl, PCI_ACS_CTL_U);
+ onoff("ACS Egress Control Enable", ctl, PCI_ACS_CTL_E);
+ onoff("ACS Direct Translated P2P Enable", ctl, PCI_ACS_CTL_T);
+
+ /*
+ * If the P2P Egress Control Capability bit is 0, ignore the Egress
+ * Control vector.
+ */
+ if ((cap & PCI_ACS_CAP_E) == 0)
+ return;
+ for (i = 0; i < size; i += 32)
+ printf(" Egress Control Vector [%u..%u]: %x\n", i + 31,
+ i, regs[o2i(extcapoff + PCI_ACS_ECV + (i / 32) * 4 )]);
+}
+
+static void
+pci_conf_print_ari_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg, cap, ctl;
+
+ printf("\n Alternative Routing-ID Interpretation Register\n");
+
+ reg = regs[o2i(extcapoff + PCI_ARI_CAP)];
+ cap = reg & 0xffff;
+ ctl = reg >> 16;
+ printf(" Capability register: 0x%08x\n", cap);
+ onoff("MVFC Function Groups Capability", reg, PCI_ARI_CAP_M);
+ onoff("ACS Function Groups Capability", reg, PCI_ARI_CAP_A);
+ printf(" Next Function Number: %u\n",
+ (unsigned int)__SHIFTOUT(reg, PCI_ARI_CAP_NXTFN));
+ printf(" Control register: 0x%08x\n", ctl);
+ onoff("MVFC Function Groups Enable", reg, PCI_ARI_CTL_M);
+ onoff("ACS Function Groups Enable", reg, PCI_ARI_CTL_A);
+ printf(" Function Group: %u\n",
+ (unsigned int)__SHIFTOUT(reg, PCI_ARI_CTL_FUNCGRP));
+}
+
+static void
+pci_conf_print_ats_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg, cap, ctl;
+ unsigned int num;
+
+ printf("\n Address Translation Services\n");
+
+ reg = regs[o2i(extcapoff + PCI_ARI_CAP)];
+ cap = reg & 0xffff;
+ ctl = reg >> 16;
+ printf(" Capability register: 0x%04x\n", cap);
+ num = __SHIFTOUT(reg, PCI_ATS_CAP_INVQDEPTH);
+ if (num == 0)
+ num = 32;
+ printf(" Invalidate Queue Depth: %u\n", num);
+ onoff("Page Aligned Request", reg, PCI_ATS_CAP_PALIGNREQ);
+
+ printf(" Control register: 0x%04x\n", ctl);
+ printf(" Smallest Translation Unit: %u\n",
+ (unsigned int)__SHIFTOUT(reg, PCI_ATS_CTL_STU));
+ onoff("Enable", reg, PCI_ATS_CTL_EN);
+}
+
+static void
+pci_conf_print_sernum_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t lo, hi;
+
+ printf("\n Device Serial Number Register\n");
+
+ lo = regs[o2i(extcapoff + PCI_SERIAL_LOW)];
+ hi = regs[o2i(extcapoff + PCI_SERIAL_HIGH)];
+ printf(" Serial Number: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n",
+ hi >> 24, (hi >> 16) & 0xff, (hi >> 8) & 0xff, hi & 0xff,
+ lo >> 24, (lo >> 16) & 0xff, (lo >> 8) & 0xff, lo & 0xff);
+}
+
+static void
+pci_conf_print_sriov_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ char buf[sizeof("99999 MB")];
+ pcireg_t reg;
+ pcireg_t total_vfs;
+ int i;
+ bool first;
+
+ printf("\n Single Root IO Virtualization Register\n");
+
+ reg = regs[o2i(extcapoff + PCI_SRIOV_CAP)];
+ printf(" Capabilities register: 0x%08x\n", reg);
+ onoff("VF Migration Capable", reg, PCI_SRIOV_CAP_VF_MIGRATION);
+ onoff("ARI Capable Hierarchy Preserved", reg,
+ PCI_SRIOV_CAP_ARI_CAP_HIER_PRESERVED);
+ if (reg & PCI_SRIOV_CAP_VF_MIGRATION) {
+ printf(" VF Migration Interrupt Message Number: 0x%u\n",
+ (pcireg_t)__SHIFTOUT(reg,
+ PCI_SRIOV_CAP_VF_MIGRATION_INTMSG_N));
+ }
+
+ reg = regs[o2i(extcapoff + PCI_SRIOV_CTL)] & 0xffff;
+ printf(" Control register: 0x%04x\n", reg);
+ onoff("VF Enable", reg, PCI_SRIOV_CTL_VF_ENABLE);
+ onoff("VF Migration Enable", reg, PCI_SRIOV_CTL_VF_MIGRATION_SUPPORT);
+ onoff("VF Migration Interrupt Enable", reg,
+ PCI_SRIOV_CTL_VF_MIGRATION_INT_ENABLE);
+ onoff("VF Memory Space Enable", reg, PCI_SRIOV_CTL_VF_MSE);
+ onoff("ARI Capable Hierarchy", reg, PCI_SRIOV_CTL_ARI_CAP_HIER);
+
+ reg = regs[o2i(extcapoff + PCI_SRIOV_STA)] >> 16;
+ printf(" Status register: 0x%04x\n", reg);
+ onoff("VF Migration Status", reg, PCI_SRIOV_STA_VF_MIGRATION);
+
+ reg = regs[o2i(extcapoff + PCI_SRIOV_INITIAL_VFS)] & 0xffff;
+ printf(" InitialVFs register: 0x%04x\n", reg);
+ total_vfs = reg = regs[o2i(extcapoff + PCI_SRIOV_TOTAL_VFS)] >> 16;
+ printf(" TotalVFs register: 0x%04x\n", reg);
+ reg = regs[o2i(extcapoff + PCI_SRIOV_NUM_VFS)] & 0xffff;
+ printf(" NumVFs register: 0x%04x\n", reg);
+
+ reg = regs[o2i(extcapoff + PCI_SRIOV_FUNC_DEP_LINK)] >> 16;
+ printf(" Function Dependency Link register: 0x%04x\n", reg);
+
+ reg = regs[o2i(extcapoff + PCI_SRIOV_VF_OFF)] & 0xffff;
+ printf(" First VF Offset register: 0x%04x\n", reg);
+ reg = regs[o2i(extcapoff + PCI_SRIOV_VF_STRIDE)] >> 16;
+ printf(" VF Stride register: 0x%04x\n", reg);
+
+ reg = regs[o2i(extcapoff + PCI_SRIOV_PAGE_CAP)];
+ printf(" Supported Page Sizes register: 0x%08x\n", reg);
+ printf(" Supported Page Size:");
+ for (i = 0, first = true; i < 32; i++) {
+ if (reg & __BIT(i)) {
+#ifdef _KERNEL
+ format_bytes(buf, sizeof(buf), 1LL << (i + 12));
+#else
+ humanize_number(buf, sizeof(buf), 1LL << (i + 12), "B",
+ HN_AUTOSCALE, 0);
+#endif
+ printf("%s %s", first ? "" : ",", buf);
+ first = false;
+ }
+ }
+ printf("\n");
+
+ reg = regs[o2i(extcapoff + PCI_SRIOV_PAGE_SIZE)];
+ printf(" System Page Sizes register: 0x%08x\n", reg);
+ printf(" Page Size: ");
+ if (reg != 0) {
+#ifdef _KERNEL
+ format_bytes(buf, sizeof(buf), 1LL << (ffs(reg) + 12));
+#else
+ humanize_number(buf, sizeof(buf), 1LL << (ffs(reg) + 12), "B",
+ HN_AUTOSCALE, 0);
+#endif
+ printf("%s", buf);
+ } else {
+ printf("unknown");
+ }
+ printf("\n");
+
+ for (i = 0; i < 6; i++) {
+ reg = regs[o2i(extcapoff + PCI_SRIOV_BAR(i))];
+ printf(" VF BAR%d register: 0x%08x\n", i, reg);
+ }
+
+ if (total_vfs > 0) {
+ reg = regs[o2i(extcapoff + PCI_SRIOV_VF_MIG_STA_AR)];
+ printf(" VF Migration State Array Offset register: 0x%08x\n",
+ reg);
+ printf(" VF Migration State Offset: 0x%08x\n",
+ (pcireg_t)__SHIFTOUT(reg, PCI_SRIOV_VF_MIG_STA_OFFSET));
+ i = __SHIFTOUT(reg, PCI_SRIOV_VF_MIG_STA_BIR);
+ printf(" VF Migration State BIR: ");
+ if (i >= 0 && i <= 5) {
+ printf("BAR%d", i);
+ } else {
+ printf("unknown BAR (%d)", i);
+ }
+ printf("\n");
+ }
+}
+
+/* XXX pci_conf_print_mriov_cap */
+/* XXX pci_conf_print_multicast_cap */
+
+static void
+pci_conf_print_page_req_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg, ctl, sta;
+
+ printf("\n Page Request\n");
+
+ reg = regs[o2i(extcapoff + PCI_PAGE_REQ_CTL)];
+ ctl = reg & 0xffff;
+ sta = reg >> 16;
+ printf(" Control Register: 0x%04x\n", ctl);
+ onoff("Enalbe", reg, PCI_PAGE_REQ_CTL_E);
+ onoff("Reset", reg, PCI_PAGE_REQ_CTL_R);
+
+ printf(" Status Register: 0x%04x\n", sta);
+ onoff("Response Failure", reg, PCI_PAGE_REQ_STA_RF);
+ onoff("Unexpected Page Request Group Index", reg,
+ PCI_PAGE_REQ_STA_UPRGI);
+ onoff("Stopped", reg, PCI_PAGE_REQ_STA_S);
+
+ reg = regs[o2i(extcapoff + PCI_PAGE_REQ_OUTSTCAPA)];
+ printf(" Outstanding Page Request Capacity: %u\n", reg);
+ reg = regs[o2i(extcapoff + PCI_PAGE_REQ_OUTSTALLOC)];
+ printf(" Outstanding Page Request Allocation: %u\n", reg);
+}
+
+/* XXX pci_conf_print_amd_cap */
+/* XXX pci_conf_print_resize_bar_cap */
+/* XXX pci_conf_print_dpa_cap */
+
+static const char *
+pci_conf_print_tph_req_cap_sttabloc(unsigned char val)
+{
+
+ switch (val) {
+ case 0x0:
+ return "Not Present";
+ case 0x1:
+ return "in the TPH Requester Capability Structure";
+ case 0x2:
+ return "in the MSI-X Table";
+ default:
+ return "Unknown";
+ }
+}
+
+static void
+pci_conf_print_tph_req_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg;
+ int size, i, j;
+
+ printf("\n TPH Requester Extended Capability\n");
+
+ reg = regs[o2i(extcapoff + PCI_TPH_REQ_CAP)];
+ printf(" TPH Requester Capabililty register: 0x%08x\n", reg);
+ onoff("No ST Mode Supported", reg, PCI_TPH_REQ_CAP_NOST);
+ onoff("Interrupt Vector Mode Supported", reg, PCI_TPH_REQ_CAP_INTVEC);
+ onoff("Device Specific Mode Supported", reg, PCI_TPH_REQ_CAP_DEVSPEC);
+ onoff("Extend TPH Reqester Supported", reg, PCI_TPH_REQ_CAP_XTPHREQ);
+ printf(" ST Table Location: %s\n",
+ pci_conf_print_tph_req_cap_sttabloc(
+ (unsigned char)__SHIFTOUT(reg, PCI_TPH_REQ_CAP_STTBLLOC)));
+ size = __SHIFTOUT(reg, PCI_TPH_REQ_CAP_STTBLSIZ) + 1;
+ printf(" ST Table Size: %d\n", size);
+ for (i = 0; i < size ; i += 2) {
+ reg = regs[o2i(extcapoff + PCI_TPH_REQ_STTBL + i / 2)];
+ for (j = 0; j < 2 ; j++) {
+ uint16_t entry = reg;
+
+ if (j != 0)
+ entry >>= 16;
+ entry &= 0xffff;
+ printf(" TPH ST Table Entry (%d): 0x%04hx\n",
+ i + j, entry);
+ }
+ }
+}
+
+static void
+pci_conf_print_ltr_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg;
+
+ printf("\n Latency Tolerance Reporting\n");
+ reg = regs[o2i(extcapoff + PCI_LTR_MAXSNOOPLAT)] & 0xffff;
+ printf(" Max Snoop Latency Register: 0x%04x\n", reg);
+ printf(" Max Snoop LatencyValue: %u\n",
+ (pcireg_t)__SHIFTOUT(reg, PCI_LTR_MAXSNOOPLAT_VAL));
+ printf(" Max Snoop LatencyScale: %uns\n",
+ PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_LTR_MAXSNOOPLAT_SCALE)));
+ reg = regs[o2i(extcapoff + PCI_LTR_MAXNOSNOOPLAT)] >> 16;
+ printf(" Max No-Snoop Latency Register: 0x%04x\n", reg);
+ printf(" Max No-Snoop LatencyValue: %u\n",
+ (pcireg_t)__SHIFTOUT(reg, PCI_LTR_MAXNOSNOOPLAT_VAL));
+ printf(" Max No-Snoop LatencyScale: %uns\n",
+ PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_LTR_MAXNOSNOOPLAT_SCALE)));
+}
+
+static void
+pci_conf_print_sec_pcie_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ int pcie_capoff;
+ pcireg_t reg;
+ int i, maxlinkwidth;
+
+ printf("\n Secondary PCI Express Register\n");
+
+ reg = regs[o2i(extcapoff + PCI_SECPCIE_LCTL3)];
+ printf(" Link Control 3 register: 0x%08x\n", reg);
+ onoff("Perform Equalization", reg, PCI_SECPCIE_LCTL3_PERFEQ);
+ onoff("Link Equalization Request Interrupt Enable",
+ reg, PCI_SECPCIE_LCTL3_LINKEQREQ_IE);
+
+ reg = regs[o2i(extcapoff + PCI_SECPCIE_LANEERR_STA)];
+ printf(" Lane Error Status register: 0x%08x\n", reg);
+
+ /* Get Max Link Width */
+ if (pci_conf_find_cap(regs, capoff, PCI_CAP_PCIEXPRESS, &pcie_capoff)){
+ reg = regs[o2i(pcie_capoff + PCIE_LCAP)];
+ maxlinkwidth = __SHIFTOUT(reg, PCIE_LCAP_MAX_WIDTH);
+ } else {
+ printf("error: falied to get PCIe capablity\n");
+ return;
+ }
+ for (i = 0; i < maxlinkwidth; i++) {
+ reg = regs[o2i(extcapoff + PCI_SECPCIE_EQCTL(i))];
+ if (i % 2 != 0)
+ reg >>= 16;
+ else
+ reg &= 0xffff;
+ printf(" Equalization Control Register (Link %d): %04x\n",
+ i, reg);
+ printf(" Downstream Port Transmit Preset: 0x%x\n",
+ (pcireg_t)__SHIFTOUT(reg,
+ PCI_SECPCIE_EQCTL_DP_XMIT_PRESET));
+ printf(" Downstream Port Receive Hint: 0x%x\n",
+ (pcireg_t)__SHIFTOUT(reg, PCI_SECPCIE_EQCTL_DP_RCV_HINT));
+ printf(" Upstream Port Transmit Preset: 0x%x\n",
+ (pcireg_t)__SHIFTOUT(reg,
+ PCI_SECPCIE_EQCTL_UP_XMIT_PRESET));
+ printf(" Upstream Port Receive Hint: 0x%x\n",
+ (pcireg_t)__SHIFTOUT(reg, PCI_SECPCIE_EQCTL_UP_RCV_HINT));
+ }
+}
+
+/* XXX pci_conf_print_pmux_cap */
+
+static void
+pci_conf_print_pasid_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg, cap, ctl;
+ unsigned int num;
+
+ printf("\n Process Address Space ID\n");
+
+ reg = regs[o2i(extcapoff + PCI_PASID_CAP)];
+ cap = reg & 0xffff;
+ ctl = reg >> 16;
+ printf(" PASID Capability Register: 0x%04x\n", cap);
+ onoff("Execute Permission Supported", reg, PCI_PASID_CAP_XPERM);
+ onoff("Privileged Mode Supported", reg, PCI_PASID_CAP_PRIVMODE);
+ num = (1 << __SHIFTOUT(reg, PCI_PASID_CAP_MAXPASIDW)) - 1;
+ printf(" Max PASID Width: %u\n", num);
+
+ printf(" PASID Control Register: 0x%04x\n", ctl);
+ onoff("PASID Enable", reg, PCI_PASID_CTL_PASID_EN);
+ onoff("Execute Permission Enable", reg, PCI_PASID_CTL_XPERM_EN);
+ onoff("Privileged Mode Enable", reg, PCI_PASID_CTL_PRIVMODE_EN);
+}
+
+static void
+pci_conf_print_lnr_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg, cap, ctl;
+ unsigned int num;
+
+ printf("\n LN Requester\n");
+
+ reg = regs[o2i(extcapoff + PCI_LNR_CAP)];
+ cap = reg & 0xffff;
+ ctl = reg >> 16;
+ printf(" LNR Capability register: 0x%04x\n", cap);
+ onoff("LNR-64 Supported", reg, PCI_LNR_CAP_64);
+ onoff("LNR-128 Supported", reg, PCI_LNR_CAP_128);
+ num = 1 << __SHIFTOUT(reg, PCI_LNR_CAP_REGISTMAX);
+ printf(" LNR Registration MAX: %u\n", num);
+
+ printf(" LNR Control register: 0x%04x\n", ctl);
+ onoff("LNR Enable", reg, PCI_LNR_CTL_EN);
+ onoff("LNR CLS", reg, PCI_LNR_CTL_CLS);
+ num = 1 << __SHIFTOUT(reg, PCI_LNR_CTL_REGISTLIM);
+ printf(" LNR Registration Limit: %u\n", num);
+}
+
+/* XXX pci_conf_print_dpc_cap */
+
+static int
+pci_conf_l1pm_cap_tposcale(unsigned char scale)
+{
+
+ /* Return scale in us */
+ switch (scale) {
+ case 0x0:
+ return 2;
+ case 0x1:
+ return 10;
+ case 0x2:
+ return 100;
+ default:
+ return -1;
+ }
+}
+
+static void
+pci_conf_print_l1pm_cap(const pcireg_t *regs, int capoff, int extcapoff)
+{
+ pcireg_t reg;
+ int scale, val;
+
+ printf("\n L1 PM Substates\n");
+
+ reg = regs[o2i(extcapoff + PCI_L1PM_CAP)];
+ printf(" L1 PM Substates Capability register: 0x%08x\n", reg);
+ onoff("PCI-PM L1.2 Supported", reg, PCI_L1PM_CAP_PCIPM12);
+ onoff("PCI-PM L1.1 Supported", reg, PCI_L1PM_CAP_PCIPM11);
+ onoff("ASPM L1.2 Supported", reg, PCI_L1PM_CAP_ASPM12);
+ onoff("ASPM L1.1 Supported", reg, PCI_L1PM_CAP_ASPM11);
+ onoff("L1 PM Substates Supported", reg, PCI_L1PM_CAP_L1PM);
+ printf(" Port Common Mode Restore Time: %uus\n",
+ (unsigned int)__SHIFTOUT(reg, PCI_L1PM_CAP_PCMRT));
+ scale = pci_conf_l1pm_cap_tposcale(
+ __SHIFTOUT(reg, PCI_L1PM_CAP_PTPOSCALE));
+ val = __SHIFTOUT(reg, PCI_L1PM_CAP_PTPOVAL);
+ printf(" Port T_POWER_ON: ");
+ if (scale == -1)
+ printf("unknown\n");
+ else
+ printf("%dus\n", val * scale);
+
+ reg = regs[o2i(extcapoff + PCI_L1PM_CTL1)];
+ printf(" L1 PM Substates Control register 1: 0x%08x\n", reg);
+ onoff("PCI-PM L1.2 Enable", reg, PCI_L1PM_CTL1_PCIPM12_EN);
+ onoff("PCI-PM L1.1 Enable", reg, PCI_L1PM_CTL1_PCIPM11_EN);
+ onoff("ASPM L1.2 Enable", reg, PCI_L1PM_CTL1_ASPM12_EN);
+ onoff("ASPM L1.1 Enable", reg, PCI_L1PM_CTL1_ASPM11_EN);
+ printf(" Common Mode Restore Time: %uus\n",
+ (unsigned int)__SHIFTOUT(reg, PCI_L1PM_CTL1_CMRT));
+ scale = PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_L1PM_CTL1_LTRTHSCALE));
+ val = __SHIFTOUT(reg, PCI_L1PM_CTL1_LTRTHVAL);
+ printf(" LTR L1.2 THRESHOLD: %dus\n", val * scale);
+
+ reg = regs[o2i(extcapoff + PCI_L1PM_CTL2)];
+ printf(" L1 PM Substates Control register 2: 0x%08x\n", reg);
+ scale = pci_conf_l1pm_cap_tposcale(
+ __SHIFTOUT(reg, PCI_L1PM_CTL2_TPOSCALE));
+ val = __SHIFTOUT(reg, PCI_L1PM_CTL2_TPOVAL);
+ printf(" T_POWER_ON: ");
+ if (scale == -1)
+ printf("unknown\n");
+ else
+ printf("%dus\n", val * scale);
+}
+
+/* XXX pci_conf_print_ptm_cap */
+/* XXX pci_conf_print_mpcie_cap */
+/* XXX pci_conf_print_frsq_cap */
+/* XXX pci_conf_print_rtr_cap */
+/* XXX pci_conf_print_desigvndsp_cap */
+
+#undef MS
+#undef SM
+#undef RW
+
+static struct {
+ pcireg_t cap;
+ const char *name;
+ void (*printfunc)(const pcireg_t *, int, int);
+} pci_extcaptab[] = {
+ { 0, "reserved",
+ NULL },
+ { PCI_EXTCAP_AER, "Advanced Error Reporting",
+ pci_conf_print_aer_cap },
+ { PCI_EXTCAP_VC, "Virtual Channel",
+ pci_conf_print_vc_cap },
+ { PCI_EXTCAP_SERNUM, "Device Serial Number",
+ pci_conf_print_sernum_cap },
+ { PCI_EXTCAP_PWRBDGT, "Power Budgeting",
+ pci_conf_print_pwrbdgt_cap },
+ { PCI_EXTCAP_RCLINK_DCL,"Root Complex Link Declaration",
+ pci_conf_print_rclink_dcl_cap },
+ { PCI_EXTCAP_RCLINK_CTL,"Root Complex Internal Link Control",
+ NULL },
+ { PCI_EXTCAP_RCEC_ASSOC,"Root Complex Event Collector Association",
+ pci_conf_print_rcec_assoc_cap },
+ { PCI_EXTCAP_MFVC, "Multi-Function Virtual Channel",
+ NULL },
+ { PCI_EXTCAP_VC2, "Virtual Channel",
+ NULL },
+ { PCI_EXTCAP_RCRB, "RCRB Header",
+ NULL },
+ { PCI_EXTCAP_VENDOR, "Vendor Unique",
+ NULL },
+ { PCI_EXTCAP_CAC, "Configuration Access Correction",
+ NULL },
+ { PCI_EXTCAP_ACS, "Access Control Services",
+ pci_conf_print_acs_cap },
+ { PCI_EXTCAP_ARI, "Alternative Routing-ID Interpretation",
+ pci_conf_print_ari_cap },
+ { PCI_EXTCAP_ATS, "Address Translation Services",
+ pci_conf_print_ats_cap },
+ { PCI_EXTCAP_SRIOV, "Single Root IO Virtualization",
+ pci_conf_print_sriov_cap },
+ { PCI_EXTCAP_MRIOV, "Multiple Root IO Virtualization",
+ NULL },
+ { PCI_EXTCAP_MULTICAST, "Multicast",
+ NULL },
+ { PCI_EXTCAP_PAGE_REQ, "Page Request",
+ pci_conf_print_page_req_cap },
+ { PCI_EXTCAP_AMD, "Reserved for AMD",
+ NULL },
+ { PCI_EXTCAP_RESIZE_BAR,"Resizable BAR",
+ NULL },
+ { PCI_EXTCAP_DPA, "Dynamic Power Allocation",
+ NULL },
+ { PCI_EXTCAP_TPH_REQ, "TPH Requester",
+ pci_conf_print_tph_req_cap },
+ { PCI_EXTCAP_LTR, "Latency Tolerance Reporting",
+ pci_conf_print_ltr_cap },
+ { PCI_EXTCAP_SEC_PCIE, "Secondary PCI Express",
+ pci_conf_print_sec_pcie_cap },
+ { PCI_EXTCAP_PMUX, "Protocol Multiplexing",
+ NULL },
+ { PCI_EXTCAP_PASID, "Process Address Space ID",
+ pci_conf_print_pasid_cap },
+ { PCI_EXTCAP_LN_REQ, "LN Requester",
+ pci_conf_print_lnr_cap },
+ { PCI_EXTCAP_DPC, "Downstream Port Containment",
+ NULL },
+ { PCI_EXTCAP_L1PM, "L1 PM Substates",
+ pci_conf_print_l1pm_cap },
+ { PCI_EXTCAP_PTM, "Precision Time Management",
+ NULL },
+ { PCI_EXTCAP_MPCIE, "M-PCIe",
+ NULL },
+ { PCI_EXTCAP_FRSQ, "Function Reading Status Queueing",
+ NULL },
+ { PCI_EXTCAP_RTR, "Readiness Time Reporting",
+ NULL },
+ { PCI_EXTCAP_DESIGVNDSP, "Designated Vendor-Specific",
+ NULL },
+};
+
+static int
+pci_conf_find_extcap(const pcireg_t *regs, int capoff, unsigned int capid,
+ int *offsetp)
+{
+ int off;
+ pcireg_t rval;
+
+ for (off = PCI_EXTCAPLIST_BASE;
+ off != 0;
+ off = PCI_EXTCAPLIST_NEXT(rval)) {
+ rval = regs[o2i(off)];
+ if (capid == PCI_EXTCAPLIST_CAP(rval)) {
+ if (offsetp != NULL)
+ *offsetp = off;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void
+pci_conf_print_extcaplist(
+#ifdef _KERNEL
+ pci_chipset_tag_t pc, pcitag_t tag,
+#endif
+ const pcireg_t *regs, int capoff)
+{
+ int off;
+ pcireg_t foundcap;
+ pcireg_t rval;
+ bool foundtable[__arraycount(pci_extcaptab)];
+ unsigned int i;
+
+ /* Check Extended capability structure */
+ off = PCI_EXTCAPLIST_BASE;
+ rval = regs[o2i(off)];
+ if (rval == 0xffffffff || rval == 0)
+ return;
+
+ /* Clear table */
+ for (i = 0; i < __arraycount(pci_extcaptab); i++)
+ foundtable[i] = false;
+
+ /* Print extended capability register's offset and the type first */
+ for (;;) {
+ printf(" Extended Capability Register at 0x%02x\n", off);
+
+ foundcap = PCI_EXTCAPLIST_CAP(rval);
+ printf(" type: 0x%04x (", foundcap);
+ if (foundcap < __arraycount(pci_extcaptab)) {
+ printf("%s)\n", pci_extcaptab[foundcap].name);
+ /* Mark as found */
+ foundtable[foundcap] = true;
+ } else
+ printf("unknown)\n");
+ printf(" version: %d\n", PCI_EXTCAPLIST_VERSION(rval));
+
+ off = PCI_EXTCAPLIST_NEXT(rval);
+ if (off == 0)
+ break;
+ rval = regs[o2i(off)];
+ }
+
+ /*
+ * And then, print the detail of each capability registers
+ * in capability value's order.
+ */
+ for (i = 0; i < __arraycount(pci_extcaptab); i++) {
+ if (foundtable[i] == false)
+ continue;
+
+ /*
+ * The type was found. Search capability list again and
+ * print all capabilities that the capabiliy type is
+ * the same.
+ */
+ if (pci_conf_find_extcap(regs, capoff, i, &off) == 0)
+ continue;
+ rval = regs[o2i(off)];
+ if ((PCI_EXTCAPLIST_VERSION(rval) <= 0)
+ || (pci_extcaptab[i].printfunc == NULL))
+ continue;
+
+ pci_extcaptab[i].printfunc(regs, capoff, off);
+
+ }
}
/* Print the Secondary Status Register. */
@@ -2216,8 +3398,8 @@ pci_conf_print_type2(
printf(" Capability list pointer: 0x%02x\n",
PCI_CAPLIST_PTR(rval));
else
- printf(" Reserved @ 0x14: 0x%04" PRIxMAX "\n",
- __SHIFTOUT(rval, __BITS(15, 0)));
+ printf(" Reserved @ 0x14: 0x%04x\n",
+ (pcireg_t)__SHIFTOUT(rval, __BITS(15, 0)));
pci_conf_print_ssr(__SHIFTOUT(rval, __BITS(31, 16)));
rval = regs[o2i(PCI_BRIDGE_BUS_REG)];
@@ -2306,7 +3488,7 @@ pci_conf_print(
#endif
)
{
- pcireg_t regs[o2i(256)];
+ pcireg_t regs[o2i(PCI_EXTCONF_SIZE)];
int off, capoff, endoff, hdrtype;
const char *type_name;
#ifdef _KERNEL
@@ -2319,7 +3501,7 @@ pci_conf_print(
printf("PCI configuration registers:\n");
- for (off = 0; off < 256; off += 4) {
+ for (off = 0; off < PCI_EXTCONF_SIZE; off += 4) {
#ifdef _KERNEL
regs[o2i(off)] = pci_conf_read(pc, tag, off);
#else
@@ -2409,7 +3591,7 @@ pci_conf_print(
/* device-dependent header */
printf(" Device-dependent header:\n");
- pci_conf_print_regs(regs, endoff, 256);
+ pci_conf_print_regs(regs, endoff, PCI_CONF_SIZE);
printf("\n");
#ifdef _KERNEL
if (printfn)
@@ -2418,4 +3600,19 @@ pci_conf_print(
printf(" Don't know how to pretty-print device-dependent header.\n");
printf("\n");
#endif /* _KERNEL */
+
+ if (regs[o2i(PCI_EXTCAPLIST_BASE)] == 0xffffffff ||
+ regs[o2i(PCI_EXTCAPLIST_BASE)] == 0)
+ return;
+
+#ifdef _KERNEL
+ pci_conf_print_extcaplist(pc, tag, regs, capoff);
+#else
+ pci_conf_print_extcaplist(regs, capoff);
+#endif
+ printf("\n");
+
+ /* Extended Configuration Space, if present */
+ printf(" Extended Configuration Space:\n");
+ pci_conf_print_regs(regs, PCI_EXTCAPLIST_BASE, PCI_EXTCONF_SIZE);
}
diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h
index 90911e3e5be..d89c6e7da74 100644
--- a/sys/dev/pci/pcireg.h
+++ b/sys/dev/pci/pcireg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pcireg.h,v 1.103 2015/07/27 15:46:03 msaitoh Exp $ */
+/* $NetBSD: pcireg.h,v 1.104 2015/10/02 05:22:53 msaitoh Exp $ */
/*
* Copyright (c) 1995, 1996, 1999, 2000
@@ -1319,7 +1319,7 @@ struct pci_rom {
#define PCI32_DMA_BOUNCE_THRESHOLD 0x100000000ULL
/*
- * PCI-X 2.0 Extended Capability List
+ * PCI-X 2.0/ PCI-express Extended Capability List
*/
#define PCI_EXTCAPLIST_BASE 0x100
@@ -1328,6 +1328,502 @@ struct pci_rom {
#define PCI_EXTCAPLIST_VERSION(ecr) (((ecr) >> 16) & 0xf)
#define PCI_EXTCAPLIST_NEXT(ecr) (((ecr) >> 20) & 0xfff)
+/* Extended Capability Identification Numbers */
+
+#define PCI_EXTCAP_AER 0x0001 /* Advanced Error Reporting */
+#define PCI_EXTCAP_VC 0x0002 /* Virtual Channel if MFVC Ext Cap not set */
+#define PCI_EXTCAP_SERNUM 0x0003 /* Device Serial Number */
+#define PCI_EXTCAP_PWRBDGT 0x0004 /* Power Budgeting */
+#define PCI_EXTCAP_RCLINK_DCL 0x0005 /* Root Complex Link Declaration */
+#define PCI_EXTCAP_RCLINK_CTL 0x0006 /* Root Complex Internal Link Control */
+#define PCI_EXTCAP_RCEC_ASSOC 0x0007 /* Root Complex Event Collector Association */
+#define PCI_EXTCAP_MFVC 0x0008 /* Multi-Function Virtual Channel */
+#define PCI_EXTCAP_VC2 0x0009 /* Virtual Channel if MFVC Ext Cap set */
+#define PCI_EXTCAP_RCRB 0x000a /* RCRB Header */
+#define PCI_EXTCAP_VENDOR 0x000b /* Vendor Unique */
+#define PCI_EXTCAP_CAC 0x000c /* Configuration Access Correction -- obsolete */
+#define PCI_EXTCAP_ACS 0x000d /* Access Control Services */
+#define PCI_EXTCAP_ARI 0x000e /* Alternative Routing-ID Interpretation */
+#define PCI_EXTCAP_ATS 0x000f /* Address Translation Services */
+#define PCI_EXTCAP_SRIOV 0x0010 /* Single Root IO Virtualization */
+#define PCI_EXTCAP_MRIOV 0x0011 /* Multiple Root IO Virtualization */
+#define PCI_EXTCAP_MULTICAST 0x0012 /* Multicast */
+#define PCI_EXTCAP_PAGE_REQ 0x0013 /* Page Request */
+#define PCI_EXTCAP_AMD 0x0014 /* Reserved for AMD */
+#define PCI_EXTCAP_RESIZE_BAR 0x0015 /* Resizable BAR */
+#define PCI_EXTCAP_DPA 0x0016 /* Dynamic Power Allocation */
+#define PCI_EXTCAP_TPH_REQ 0x0017 /* TPH Requester */
+#define PCI_EXTCAP_LTR 0x0018 /* Latency Tolerance Reporting */
+#define PCI_EXTCAP_SEC_PCIE 0x0019 /* Secondary PCI Express */
+#define PCI_EXTCAP_PMUX 0x001a /* Protocol Multiplexing */
+#define PCI_EXTCAP_PASID 0x001b /* Process Address Space ID */
+#define PCI_EXTCAP_LN_REQ 0x001c /* LN Requester */
+#define PCI_EXTCAP_DPC 0x001d /* Downstream Port Containment */
+#define PCI_EXTCAP_L1PM 0x001e /* L1 PM Substates */
+#define PCI_EXTCAP_PTM 0x001f /* Precision Time Management */
+#define PCI_EXTCAP_MPCIE 0x0020 /* M-PCIe */
+#define PCI_EXTCAP_FRSQ 0x0021 /* Function Reading Status Queueing */
+#define PCI_EXTCAP_RTR 0x0022 /* Readiness Time Reporting */
+#define PCI_EXTCAP_DESIGVNDSP 0x0023 /* Designated Vendor-Specific */
+
+/*
+ * Extended capability ID: 0x0001
+ * Advanced Error Reporting
+ */
+#define PCI_AER_UC_STATUS 0x04 /* Uncorrectable Error Status Register */
+#define PCI_AER_UC_UNDEFINED __BIT(0)
+#define PCI_AER_UC_DL_PROTOCOL_ERROR __BIT(4)
+#define PCI_AER_UC_SURPRISE_DOWN_ERROR __BIT(5)
+#define PCI_AER_UC_POISONED_TLP __BIT(12)
+#define PCI_AER_UC_FC_PROTOCOL_ERROR __BIT(13)
+#define PCI_AER_UC_COMPLETION_TIMEOUT __BIT(14)
+#define PCI_AER_UC_COMPLETER_ABORT __BIT(15)
+#define PCI_AER_UC_UNEXPECTED_COMPLETION __BIT(16)
+#define PCI_AER_UC_RECEIVER_OVERFLOW __BIT(17)
+#define PCI_AER_UC_MALFORMED_TLP __BIT(18)
+#define PCI_AER_UC_ECRC_ERROR __BIT(19)
+#define PCI_AER_UC_UNSUPPORTED_REQUEST_ERROR __BIT(20)
+#define PCI_AER_UC_ACS_VIOLATION __BIT(21)
+#define PCI_AER_UC_INTERNAL_ERROR __BIT(22)
+#define PCI_AER_UC_MC_BLOCKED_TLP __BIT(23)
+#define PCI_AER_UC_ATOMIC_OP_EGRESS_BLOCKED __BIT(24)
+#define PCI_AER_UC_TLP_PREFIX_BLOCKED_ERROR __BIT(25)
+#define PCI_AER_UC_MASK 0x08 /* Uncorrectable Error Mask Register */
+ /* Shares bits with UC_STATUS */
+#define PCI_AER_UC_SEVERITY 0x0c /* Uncorrectable Error Severity Register */
+ /* Shares bits with UC_STATUS */
+#define PCI_AER_COR_STATUS 0x10 /* Correctable Error Status Register */
+#define PCI_AER_COR_RECEIVER_ERROR __BIT(0)
+#define PCI_AER_COR_BAD_TLP __BIT(6)
+#define PCI_AER_COR_BAD_DLLP __BIT(7)
+#define PCI_AER_COR_REPLAY_NUM_ROLLOVER __BIT(8)
+#define PCI_AER_COR_REPLAY_TIMER_TIMEOUT __BIT(12)
+#define PCI_AER_COR_ADVISORY_NF_ERROR __BIT(13)
+#define PCI_AER_COR_INTERNAL_ERROR __BIT(14)
+#define PCI_AER_COR_HEADER_LOG_OVERFLOW __BIT(15)
+#define PCI_AER_COR_MASK 0x14 /* Correctable Error Mask Register */
+ /* Shares bits with COR_STATUS */
+#define PCI_AER_CAP_CONTROL 0x18 /* Advanced Error Capabilities and Control Register */
+#define PCI_AER_FIRST_ERROR_PTR __BITS(4, 0)
+#define PCI_AER_FIRST_ERROR_PTR_S 0
+#define PCI_AER_FIRST_ERROR_PTR_M 0x1f
+#define PCI_AER_ECRC_GEN_CAPABLE __BIT(5)
+#define PCI_AER_ECRC_GEN_ENABLE __BIT(6)
+#define PCI_AER_ECRC_CHECK_CAPABLE __BIT(7)
+#define PCI_AER_ECRC_CHECK_ENABLE __BIT(8)
+#define PCI_AER_MULT_HDR_CAPABLE __BIT(9)
+#define PCI_AER_MULT_HDR_ENABLE __BIT(10)
+#define PCI_AER_TLP_PREFIX_LOG_PRESENT __BIT(11)
+#define PCI_AER_HEADER_LOG 0x1c /* Header Log Register */
+#define PCI_AER_ROOTERR_CMD 0x2c /* Root Error Command Register */
+ /* Only for root complex ports */
+#define PCI_AER_ROOTERR_COR_ENABLE __BIT(0)
+#define PCI_AER_ROOTERR_NF_ENABLE __BIT(1)
+#define PCI_AER_ROOTERR_F_ENABLE __BIT(2)
+#define PCI_AER_ROOTERR_STATUS 0x30 /* Root Error Status Register */
+ /* Only for root complex ports */
+#define PCI_AER_ROOTERR_COR_ERR __BIT(0)
+#define PCI_AER_ROOTERR_MULTI_COR_ERR __BIT(1)
+#define PCI_AER_ROOTERR_UC_ERR __BIT(2)
+#define PCI_AER_ROOTERR_MULTI_UC_ERR __BIT(3)
+#define PCI_AER_ROOTERR_FIRST_UC_FATAL __BIT(4)
+#define PCI_AER_ROOTERR_NF_ERR __BIT(5)
+#define PCI_AER_ROOTERR_F_ERR __BIT(6)
+#define PCI_AER_ROOTERR_INT_MESSAGE __BITS(31, 27)
+#define PCI_AER_ROOTERR_INT_MESSAGE_S 27
+#define PCI_AER_ROOTERR_INT_MESSAGE_M 0x1f
+#define PCI_AER_ERRSRC_ID 0x34 /* Error Source Identification Register */
+#define PCI_AER_ERRSRC_ID_ERR_COR __BITS(15, 0)
+#define PCI_AER_ERRSRC_ID_ERR_COR_S 0
+#define PCI_AER_ERRSRC_ID_ERR_COR_M 0xffff
+#define PCI_AER_ERRSRC_ID_ERR_UC __BITS(31, 16)
+#define PCI_AER_ERRSRC_ID_ERR_UC_S 16
+#define PCI_AER_ERRSRC_ID_ERR_UC_M 0xffff
+ /* Only for root complex ports */
+#define PCI_AER_TLP_PREFIX_LOG 0x38 /*TLP Prefix Log Register */
+ /* Only for TLP prefix functions */
+
+/*
+ * Extended capability ID: 0x0002, 0x0009
+ * Virtual Channel
+ */
+#define PCI_VC_CAP1 0x04 /* Port VC Capability Register 1 */
+#define PCI_VC_CAP1_EXT_COUNT __BITS(2, 0)
+#define PCI_VC_CAP1_EXT_COUNT_S 0
+#define PCI_VC_CAP1_EXT_COUNT_M 0x7
+#define PCI_VC_CAP1_LOWPRI_EXT_COUNT __BITS(6, 4)
+#define PCI_VC_CAP1_LOWPRI_EXT_COUNT_S 4
+#define PCI_VC_CAP1_LOWPRI_EXT_COUNT_M 0x7
+#define PCI_VC_CAP1_REFCLK __BITS(9, 8)
+#define PCI_VC_CAP1_REFCLK_S 8
+#define PCI_VC_CAP1_REFCLK_M 0x3
+#define PCI_VC_CAP1_REFCLK_100NS 0x0
+#define PCI_VC_CAP1_PORT_ARB_TABLE_SIZE __BITS(11, 10)
+#define PCI_VC_CAP1_PORT_ARB_TABLE_SIZE_S 10
+#define PCI_VC_CAP1_PORT_ARB_TABLE_SIZE_M 0x3
+#define PCI_VC_CAP2 0x08 /* Port VC Capability Register 2 */
+#define PCI_VC_CAP2_ARB_CAP_HW_FIXED_SCHEME __BIT(0)
+#define PCI_VC_CAP2_ARB_CAP_WRR_32 __BIT(1)
+#define PCI_VC_CAP2_ARB_CAP_WRR_64 __BIT(2)
+#define PCI_VC_CAP2_ARB_CAP_WRR_128 __BIT(3)
+#define PCI_VC_CAP2_ARB_TABLE_OFFSET __BITS(31, 24)
+#define PCI_VC_CAP2_ARB_TABLE_OFFSET_S 24
+#define PCI_VC_CAP2_ARB_TABLE_OFFSET_M 0xff
+#define PCI_VC_CONTROL 0x0c /* Port VC Control Register (16bit) */
+#define PCI_VC_CONTROL_LOAD_VC_ARB_TABLE __BIT(0)
+#define PCI_VC_CONTROL_VC_ARB_SELECT __BITS(3, 1)
+#define PCI_VC_CONTROL_VC_ARB_SELECT_S 1
+#define PCI_VC_CONTROL_VC_ARB_SELECT_M 0x7
+#define PCI_VC_STATUS 0x0e /* Port VC Status Register (16bit) */
+#define PCI_VC_STATUS_LOAD_VC_ARB_TABLE __BIT(0)
+#define PCI_VC_RESOURCE_CAP(n) (0x10 + ((n) * 0x0c)) /* VC Resource Capability Register */
+#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_HW_FIXED_SCHEME __BIT(0)
+#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_32 __BIT(1)
+#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_64 __BIT(2)
+#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_128 __BIT(3)
+#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_TWRR_128 __BIT(4)
+#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_256 __BIT(5)
+#define PCI_VC_RESOURCE_CAP_ADV_PKT_SWITCH __BIT(14)
+#define PCI_VC_RESOURCE_CAP_REJCT_SNOOP_TRANS __BIT(15)
+#define PCI_VC_RESOURCE_CAP_MAX_TIME_SLOTS __BITS(22, 16)
+#define PCI_VC_RESOURCE_CAP_MAX_TIME_SLOTS_S 16
+#define PCI_VC_RESOURCE_CAP_MAX_TIME_SLOTS_M 0x7f
+#define PCI_VC_RESOURCE_CAP_PORT_ARB_TABLE_OFFSET __BITS(31, 24)
+#define PCI_VC_RESOURCE_CAP_PORT_ARB_TABLE_OFFSET_S 24
+#define PCI_VC_RESOURCE_CAP_PORT_ARB_TABLE_OFFSET_M 0xff
+#define PCI_VC_RESOURCE_CTL(n) (0x14 + ((n) * 0x0c)) /* VC Resource Control Register */
+#define PCI_VC_RESOURCE_CTL_TCVC_MAP __BITS(7, 0)
+#define PCI_VC_RESOURCE_CTL_TCVC_MAP_S 0
+#define PCI_VC_RESOURCE_CTL_TCVC_MAP_M 0xff
+#define PCI_VC_RESOURCE_CTL_LOAD_PORT_ARB_TABLE __BIT(16)
+#define PCI_VC_RESOURCE_CTL_PORT_ARB_SELECT __BITS(19, 17)
+#define PCI_VC_RESOURCE_CTL_PORT_ARB_SELECT_S 17
+#define PCI_VC_RESOURCE_CTL_PORT_ARB_SELECT_M 0x7
+#define PCI_VC_RESOURCE_CTL_VC_ID __BITS(26, 24)
+#define PCI_VC_RESOURCE_CTL_VC_ID_S 24
+#define PCI_VC_RESOURCE_CTL_VC_ID_M 0x7
+#define PCI_VC_RESOURCE_CTL_VC_ENABLE __BIT(31)
+#define PCI_VC_RESOURCE_STA(n) (0x18 + ((n) * 0x0c)) /* VC Resource Status Register */
+#define PCI_VC_RESOURCE_STA_PORT_ARB_TABLE __BIT(0)
+#define PCI_VC_RESOURCE_STA_VC_NEG_PENDING __BIT(1)
+
+/*
+ * Extended capability ID: 0x0003
+ * Serial Number
+ */
+#define PCI_SERIAL_LOW 0x04
+#define PCI_SERIAL_HIGH 0x08
+
+/*
+ * Extended capability ID: 0x0004
+ * Power Budgeting
+ */
+#define PCI_PWRBDGT_DSEL 0x04 /* Data Select */
+#define PCI_PWRBDGT_DATA 0x08 /* Data */
+#define PCI_PWRBDGT_DATA_BASEPWR __BITS(7, 0) /* Base Power */
+#define PCI_PWRBDGT_DATA_SCALE __BITS(9, 8) /* Data Scale */
+#define PCI_PWRBDGT_PM_SUBSTAT __BITS(12, 10) /* PM Sub State */
+#define PCI_PWRBDGT_PM_STAT __BITS(14, 13) /* PM State */
+#define PCI_PWRBDGT_TYPE __BITS(17, 15) /* Type */
+#define PCI_PWRBDGT_PWRRAIL __BITS(20, 18) /* Power Rail */
+#define PCI_PWRBDGT_CAP 0x0c /* Capability */
+#define PCI_PWRBDGT_CAP_SYSALLOC __BIT(0) /* System Allocated */
+
+/*
+ * Extended capability ID: 0x0005
+ * Root Complex Link Declaration
+ */
+#define PCI_RCLINK_DCL_ESDESC 0x04 /* Element Self Description */
+#define PCI_RCLINK_DCL_ESDESC_ELMTYPE __BITS(3, 0) /* Element Type */
+#define PCI_RCLINK_DCL_ESDESC_NUMLINKENT __BITS(15, 8) /* Num of Link Entries*/
+#define PCI_RCLINK_DCL_ESDESC_COMPID __BITS(23, 16) /* Component ID */
+#define PCI_RCLINK_DCL_ESDESC_PORTNUM __BITS(31, 24) /* Port Number */
+#define PCI_RCLINK_DCL_LINKENTS 0x10 /* Link Entries */
+#define PCI_RCLINK_DCL_LINKDESC(x) /* Link Description */ \
+ (PCI_RCLINK_DCL_LINKENTS + ((x) * 16))
+#define PCI_RCLINK_DCL_LINKDESC_LVALID __BIT(0) /* Link Valid */
+#define PCI_RCLINK_DCL_LINKDESC_LTYPE __BIT(1) /* Link Type */
+#define PCI_RCLINK_DCL_LINKDESC_ARCRBH __BIT(2) /* Associate RCRB Header */
+#define PCI_RCLINK_DCL_LINKDESC_TCOMPID __BITS(23, 16) /* Target Component ID*/
+#define PCI_RCLINK_DCL_LINKDESC_TPNUM __BITS(31, 24) /* Target Port Number */
+#define PCI_RCLINK_DCL_LINKADDR_LT0_LO(x) /* LT0: Link Address Low */ \
+ (PCI_RCLINK_DCL_LINKENTS + ((x) * 16) + 0x08)
+#define PCI_RCLINK_DCL_LINKADDR_LT0_HI(x) /* LT0: Link Address High */ \
+ (PCI_RCLINK_DCL_LINKENTS + ((x) * 16) + 0x0c)
+#define PCI_RCLINK_DCL_LINKADDR_LT1_LO(x) /* LT1: Config Space (low) */ \
+ (PCI_RCLINK_DCL_LINKENTS + ((x) * 16) + 0x08)
+#define PCI_RCLINK_DCL_LINKADDR_LT1_N __BITS(2, 0) /* N */
+#define PCI_RCLINK_DCL_LINKADDR_LT1_FUNC __BITS(14, 12) /* Function Number */
+#define PCI_RCLINK_DCL_LINKADDR_LT1_DEV __BITS(19, 15) /* Device Number */
+#define PCI_RCLINK_DCL_LINKADDR_LT1_BUS(N) __BITS(19 + (N), 20) /* Bus Number*/
+#define PCI_RCLINK_DCL_LINKADDR_LT1_BAL(N) __BITS(31, 20 + (N)) /* BAddr(L) */
+#define PCI_RCLINK_DCL_LINKADDR_LT1_HI(x) /* LT1: Config Space Base Addr(H) */\
+ (PCI_RCLINK_DCL_LINKENTS + ((x) * 16) + 0x0c)
+
+/*
+ * Extended capability ID: 0x0006
+ * Root Complex Internal Link Control
+ */
+
+/*
+ * Extended capability ID: 0x0007
+ * Root Complex Event Collector Association
+ */
+#define PCI_RCEC_ASSOC_ASSOCBITMAP 0x04
+
+/*
+ * Extended capability ID: 0x0008
+ * Multi-Function Virtual Channel
+ */
+
+/*
+ * Extended capability ID: 0x0009
+ * Virtual Channel if MFVC Ext Cap set
+ */
+
+/*
+ * Extended capability ID: 0x000a
+ * RCRB Header
+ */
+
+/*
+ * Extended capability ID: 0x000b
+ * Vendor Unique
+ */
+
+/*
+ * Extended capability ID: 0x000c
+ * Configuration Access Correction
+ */
+
+/*
+ * Extended capability ID: 0x000d
+ * Access Control Services
+ */
+#define PCI_ACS_CAP 0x04 /* Capability Register */
+#define PCI_ACS_CAP_V __BIT(0) /* Source Validation */
+#define PCI_ACS_CAP_B __BIT(1) /* Transaction Blocking */
+#define PCI_ACS_CAP_R __BIT(2) /* P2P Request Redirect */
+#define PCI_ACS_CAP_C __BIT(3) /* P2P Completion Redirect */
+#define PCI_ACS_CAP_U __BIT(4) /* Upstream Forwarding */
+#define PCI_ACS_CAP_E __BIT(5) /* Egress Control */
+#define PCI_ACS_CAP_T __BIT(6) /* Direct Translated P2P */
+#define PCI_ACS_CAP_ECVSIZE __BITS(15, 8) /* Egress Control Vector Size */
+#define PCI_ACS_CTL 0x04 /* Control Register */
+#define PCI_ACS_CTL_V __BIT(0 + 16) /* Source Validation Enable */
+#define PCI_ACS_CTL_B __BIT(1 + 16) /* Transaction Blocking Enable */
+#define PCI_ACS_CTL_R __BIT(2 + 16) /* P2P Request Redirect Enable */
+#define PCI_ACS_CTL_C __BIT(3 + 16) /* P2P Completion Redirect Enable */
+#define PCI_ACS_CTL_U __BIT(4 + 16) /* Upstream Forwarding Enable */
+#define PCI_ACS_CTL_E __BIT(5 + 16) /* Egress Control Enable */
+#define PCI_ACS_CTL_T __BIT(6 + 16) /* Direct Translated P2P Enable */
+#define PCI_ACS_ECV 0x08 /* Egress Control Vector */
+
+/*
+ * Extended capability ID: 0x000e
+ * ARI
+ */
+#define PCI_ARI_CAP 0x04 /* Capability Register */
+#define PCI_ARI_CAP_M __BIT(0) /* MFVC Function Groups Cap. */
+#define PCI_ARI_CAP_A __BIT(1) /* ACS Function Groups Cap. */
+#define PCI_ARI_CAP_NXTFN __BITS(15, 8) /* Next Function Number */
+#define PCI_ARI_CTL 0x04 /* Control Register */
+#define PCI_ARI_CTL_M __BIT(16) /* MFVC Function Groups Ena. */
+#define PCI_ARI_CTL_A __BIT(17) /* ACS Function Groups Ena. */
+#define PCI_ARI_CTL_FUNCGRP __BITS(31, 24) /* Function Group */
+
+/*
+ * Extended capability ID: 0x000f
+ * Address Translation Services
+ */
+#define PCI_ATS_CAP 0x04 /* Capability Register */
+#define PCI_ATS_CAP_INVQDEPTH __BITS(4, 0) /* Invalidate Queue Depth */
+#define PCI_ATS_CAP_PALIGNREQ __BIT(5) /* Page Aligned Request */
+#define PCI_ATS_CTL 0x04 /* Control Register */
+#define PCI_ATS_CTL_STU __BITS(20, 16) /* Smallest Translation Unit */
+#define PCI_ATS_CTL_EN __BIT(31) /* Enable */
+
+/*
+ * Extended capability ID: 0x0010
+ * SR-IOV
+ */
+#define PCI_SRIOV_CAP 0x04 /* SR-IOV Capabilities */
+#define PCI_SRIOV_CAP_VF_MIGRATION __BIT(0)
+#define PCI_SRIOV_CAP_ARI_CAP_HIER_PRESERVED __BIT(1)
+#define PCI_SRIOV_CAP_VF_MIGRATION_INTMSG_N __BITS(31, 21)
+#define PCI_SRIOV_CAP_VF_MIGRATION_INTMSG_N_S 21
+#define PCI_SRIOV_CAP_VF_MIGRATION_INTMSG_N_M 0x7ff
+#define PCI_SRIOV_CTL 0x08 /* SR-IOV Control (16bit) */
+#define PCI_SRIOV_CTL_VF_ENABLE __BIT(0)
+#define PCI_SRIOV_CTL_VF_MIGRATION_SUPPORT __BIT(1)
+#define PCI_SRIOV_CTL_VF_MIGRATION_INT_ENABLE __BIT(2)
+#define PCI_SRIOV_CTL_VF_MSE __BIT(3)
+#define PCI_SRIOV_CTL_ARI_CAP_HIER __BIT(4)
+#define PCI_SRIOV_STA 0x0a /* SR-IOV Status (16bit) */
+#define PCI_SRIOV_STA_VF_MIGRATION __BIT(0)
+#define PCI_SRIOV_INITIAL_VFS 0x0c /* InitialVFs (16bit) */
+#define PCI_SRIOV_TOTAL_VFS 0x0e /* TotalVFs (16bit) */
+#define PCI_SRIOV_NUM_VFS 0x10 /* NumVFs (16bit) */
+#define PCI_SRIOV_FUNC_DEP_LINK 0x12 /* Function Dependency Link (16bit) */
+#define PCI_SRIOV_VF_OFF 0x14 /* First VF Offset (16bit) */
+#define PCI_SRIOV_VF_STRIDE 0x16 /* VF Stride (16bit) */
+#define PCI_SRIOV_VF_DID 0x1a /* VF Device ID (16bit) */
+#define PCI_SRIOV_PAGE_CAP 0x1c /* Supported Page Sizes */
+#define PCI_SRIOV_PAGE_SIZE 0x20 /* System Page Size */
+#define PCI_SRIOV_BASE_PAGE_SHIFT 12
+#define PCI_SRIOV_BARS 0x24 /* VF BAR0-5 */
+#define PCI_SRIOV_BAR(x) (PCI_SRIOV_BARS + ((x) * 4))
+#define PCI_SRIOV_VF_MIG_STA_AR 0x3c /* VF Migration State Array Offset */
+#define PCI_SRIOV_VF_MIG_STA_OFFSET __BITS(31, 3)
+#define PCI_SRIOV_VF_MIG_STA_OFFSET_S 3
+#define PCI_SRIOV_VF_MIG_STA_OFFSET_M 0x1fffffff
+#define PCI_SRIOV_VF_MIG_STA_BIR __BITS(2, 0)
+#define PCI_SRIOV_VF_MIG_STA_BIR_S 0
+#define PCI_SRIOV_VF_MIG_STA_BIR_M 0x7
+
+/*
+ * Extended capability ID: 0x0011
+ * Multiple Root IO Virtualization
+ */
+
+/*
+ * Extended capability ID: 0x0012
+ * Multicast
+ */
+
+/*
+ * Extended capability ID: 0x0013
+ * Page Request
+ */
+#define PCI_PAGE_REQ_CTL 0x04 /* Control Register */
+#define PCI_PAGE_REQ_CTL_E __BIT(0) /* Enalbe */
+#define PCI_PAGE_REQ_CTL_R __BIT(1) /* Reset */
+#define PCI_PAGE_REQ_STA 0x04 /* Status Register */
+#define PCI_PAGE_REQ_STA_RF __BIT(0+16) /* Response Failure */
+#define PCI_PAGE_REQ_STA_UPRGI __BIT(1+16) /* Unexpected Page Req Grp Idx */
+#define PCI_PAGE_REQ_STA_S __BIT(8+16) /* Stopped */
+#define PCI_PAGE_REQ_OUTSTCAPA 0x08 /* Outstanding Page Request Capacity */
+#define PCI_PAGE_REQ_OUTSTALLOC 0x0c /* Outstanding Page Request Allocation */
+
+/*
+ * Extended capability ID: 0x0014
+ * (Reserved for AMD)
+ */
+
+/*
+ * Extended capability ID: 0x0015
+ * Resizable BAR
+ */
+
+/*
+ * Extended capability ID: 0x0016
+ * Dynamic Power Allocation
+ */
+
+/*
+ * Extended capability ID: 0x0017
+ * TPH Requester
+ */
+#define PCI_TPH_REQ_CAP 0x04 /* TPH Requester Capability */
+#define PCI_TPH_REQ_CAP_NOST __BIT(0) /* No ST Mode Supported */
+#define PCI_TPH_REQ_CAP_INTVEC __BIT(1) /* Intr Vec Mode Supported */
+#define PCI_TPH_REQ_CAP_DEVSPEC __BIT(2) /* Device Specific Mode Supported */
+#define PCI_TPH_REQ_CAP_XTPHREQ __BIT(8) /* Extend TPH Reqester Supported */
+#define PCI_TPH_REQ_CAP_STTBLLOC __BITS(10, 9) /* ST Table Location */
+#define PCI_TPH_REQ_CAP_STTBLSIZ __BITS(26, 16) /* ST Table Size */
+#define PCI_TPH_REQ_CTL 0x08 /* TPH Requester Control */
+#define PCI_TPH_REQ_CTL_STSEL _BITS(2, 0) /* ST Mode Select */
+#define PCI_TPH_REQ_CTL_TPHREQEN _BITS(9, 8) /* TPH Requester Enable */
+#define PCI_TPH_REQ_STTBL 0x0c /* TPH ST Table */
+
+/*
+ * Extended capability ID: 0x0018
+ * Latency Tolerance Reporting
+ */
+#define PCI_LTR_MAXSNOOPLAT 0x04 /* Max Snoop Latency */
+#define PCI_LTR_MAXSNOOPLAT_VAL __BITS(9, 0) /* Max Snoop LatencyValue */
+#define PCI_LTR_MAXSNOOPLAT_SCALE __BITS(12, 10) /* Max Snoop LatencyScale */
+#define PCI_LTR_MAXNOSNOOPLAT 0x04 /* Max No-Snoop Latency */
+#define PCI_LTR_MAXNOSNOOPLAT_VAL __BITS(25, 16) /* Max No-Snoop LatencyValue*/
+#define PCI_LTR_MAXNOSNOOPLAT_SCALE __BITS(28, 26) /*Max NoSnoop LatencyScale*/
+#define PCI_LTR_SCALETONS(x) ((32 << (x)) / 32)
+
+/*
+ * Extended capability ID: 0x0019
+ * Seconday PCI Express Extended Capability
+ */
+#define PCI_SECPCIE_LCTL3 0x04 /* Link Control 3 */
+#define PCI_SECPCIE_LCTL3_PERFEQ __BIT(0) /* Perform Equalization */
+#define PCI_SECPCIE_LCTL3_LINKEQREQ_IE __BIT(1) /* Link Eq. Req. Int. Ena. */
+#define PCI_SECPCIE_LANEERR_STA 0x08 /* Lane Error Status */
+#define PCI_SECPCIE_EQCTLS 0x0c /* Equalization Control [0-maxlane] */
+#define PCI_SECPCIE_EQCTL(x) (PCI_SECPCIE_EQCTLS + ((x) * 2))
+#define PCI_SECPCIE_EQCTL_DP_XMIT_PRESET __BITS(3, 0) /* DwnStPort Xmit Pres */
+#define PCI_SECPCIE_EQCTL_DP_RCV_HINT __BITS(6, 4) /* DwnStPort Rcv PreHnt */
+#define PCI_SECPCIE_EQCTL_UP_XMIT_PRESET __BITS(11, 8) /* UpStPort Xmit Pres */
+#define PCI_SECPCIE_EQCTL_UP_RCV_HINT __BITS(14, 12) /* UpStPort Rcv PreHnt*/
+
+/*
+ * Extended capability ID: 0x001a
+ * Protocol Multiplexing
+ */
+
+/*
+ * Extended capability ID: 0x001b
+ * Process Address Space ID
+ */
+#define PCI_PASID_CAP 0x04 /* Capability Register */
+#define PCI_PASID_CAP_XPERM __BIT(1) /* Execute Permission Supported */
+#define PCI_PASID_CAP_PRIVMODE __BIT(2) /* Privileged Mode Supported */
+#define PCI_PASID_CAP_MAXPASIDW __BITS(12, 8) /* Max PASID Width */
+#define PCI_PASID_CTL 0x04 /* Control Register */
+#define PCI_PASID_CTL_PASID_EN __BIT(0) /* PASID Enable */
+#define PCI_PASID_CTL_XPERM_EN __BIT(1) /* Execute Permission Enable */
+#define PCI_PASID_CTL_PRIVMODE_EN __BIT(2) /* Privileged Mode Enable */
+
+/*
+ * Extended capability ID: 0x001c
+ * LN Requester
+ */
+#define PCI_LNR_CAP 0x04 /* Capability Register */
+#define PCI_LNR_CAP_64 __BIT(0) /* LNR-64 Supported */
+#define PCI_LNR_CAP_128 __BIT(1) /* LNR-128 Supported */
+#define PCI_LNR_CAP_REGISTMAX __BITS(12, 8) /* LNR Registration MAX */
+#define PCI_LNR_CTL 0x04 /* Control Register */
+#define PCI_LNR_CTL_EN __BIT(0+16) /* LNR Enable */
+#define PCI_LNR_CTL_CLS __BIT(1+16) /* LNR CLS */
+#define PCI_LNR_CTL_REGISTLIM __BITS(28, 24) /* LNR Registration Limit */
+
+/*
+ * Extended capability ID: 0x001d
+ * Downstream Port Containment
+ */
+
+/*
+ * Extended capability ID: 0x001e
+ * L1 PM Substates
+ */
+#define PCI_L1PM_CAP 0x04 /* Capabilities Register */
+#define PCI_L1PM_CAP_PCIPM12 __BIT(0) /* PCI-PM L1.2 Supported */
+#define PCI_L1PM_CAP_PCIPM11 __BIT(1) /* PCI-PM L1.1 Supported */
+#define PCI_L1PM_CAP_ASPM12 __BIT(2) /* ASPM L1.2 Supported */
+#define PCI_L1PM_CAP_ASPM11 __BIT(3) /* ASPM L1.1 Supported */
+#define PCI_L1PM_CAP_L1PM __BIT(4) /* L1 PM Substates Supported */
+#define PCI_L1PM_CAP_PCMRT __BITS(15, 8) /*Port Common Mode Restore Time*/
+#define PCI_L1PM_CAP_PTPOSCALE __BITS(17, 16) /* Port T_POWER_ON Scale */
+#define PCI_L1PM_CAP_PTPOVAL __BITS(23, 19) /* Port T_POWER_ON Value */
+#define PCI_L1PM_CTL1 0x08 /* Control Register 1 */
+#define PCI_L1PM_CTL1_PCIPM12_EN __BIT(0) /* PCI-PM L1.2 Enable */
+#define PCI_L1PM_CTL1_PCIPM11_EN __BIT(1) /* PCI-PM L1.1 Enable */
+#define PCI_L1PM_CTL1_ASPM12_EN __BIT(2) /* ASPM L1.2 Enable */
+#define PCI_L1PM_CTL1_ASPM11_EN __BIT(3) /* ASPM L1.1 Enable */
+#define PCI_L1PM_CTL1_CMRT __BITS(15, 8) /* Common Mode Restore Time */
+#define PCI_L1PM_CTL1_LTRTHVAL __BITS(25, 16) /* LTR L1.2 THRESHOLD Value */
+#define PCI_L1PM_CTL1_LTRTHSCALE __BITS(31, 29) /* LTR L1.2 THRESHOLD Scale */
+#define PCI_L1PM_CTL2 0x0c /* Control Register 2 */
+#define PCI_L1PM_CTL2_TPOSCALE __BITS(1, 0) /* T_POWER_ON Scale */
+#define PCI_L1PM_CTL2_TPOVAL __BITS(7, 3) /* T_POWER_ON Value */
+
/*
* Local constants
*/
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 8bd2fcb1e5d..5bdd392cf75 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pcivar.h,v 1.104 2015/08/17 06:16:03 knakahara Exp $ */
+/* $NetBSD: pcivar.h,v 1.105 2015/10/02 05:22:53 msaitoh Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@@ -278,14 +278,22 @@ int pci_find_rom(const struct pci_attach_args *, bus_space_tag_t,
bus_space_handle_t, bus_size_t,
int, bus_space_handle_t *, bus_size_t *);
-int pci_get_capability(pci_chipset_tag_t, pcitag_t, int, int *, pcireg_t *);
-int pci_get_ht_capability(pci_chipset_tag_t, pcitag_t, int, int *, pcireg_t *);
+int pci_get_capability(pci_chipset_tag_t, pcitag_t, int, int *, pcireg_t *);
+int pci_get_ht_capability(pci_chipset_tag_t, pcitag_t, int, int *,
+ pcireg_t *);
+int pci_get_ext_capability(pci_chipset_tag_t, pcitag_t, int, int *,
+ pcireg_t *);
+
int pci_msi_count(pci_chipset_tag_t, pcitag_t);
int pci_msix_count(pci_chipset_tag_t, pcitag_t);
/*
* Helper functions for autoconfiguration.
*/
+#ifndef PCI_MACHDEP_ENUMERATE_BUS
+int pci_enumerate_bus(struct pci_softc *, const int *,
+ int (*)(const struct pci_attach_args *), struct pci_attach_args *);
+#endif
int pci_probe_device(struct pci_softc *, pcitag_t tag,
int (*)(const struct pci_attach_args *),
struct pci_attach_args *);