]> mj.ucw.cz Git - pciutils.git/commitdiff
Merge remote-tracking branch 'thesamesam/which-hunt'
authorMartin Mares <mj@ucw.cz>
Sun, 30 Oct 2022 12:42:12 +0000 (13:42 +0100)
committerMartin Mares <mj@ucw.cz>
Sun, 30 Oct 2022 12:42:12 +0000 (13:42 +0100)
13 files changed:
lib/Makefile
lib/configure
lib/filter.c
lib/header.h
lib/hurd.c
lib/init.c
lib/internal.h
lib/pci.h
lib/win32-sysdbg.c [new file with mode: 0644]
ls-ecaps.c
ls-tree.c
maint/tag-release
pcilib.man

index b29a48fb8f9ca69b6e2d9f1753ddb07b261319c0..400c32d17df316b0e723532d73fc312f1f4aac4b 100644 (file)
@@ -59,6 +59,10 @@ OBJS += emulated
 OBJS += win32-cfgmgr32
 endif
 
+ifdef PCI_HAVE_PM_WIN32_SYSDBG
+OBJS += win32-sysdbg
+endif
+
 all: $(PCILIB) $(PCILIBPC)
 
 ifeq ($(SHARED),no)
@@ -108,6 +112,7 @@ filter.o: filter.c $(INCL)
 nbsd-libpci.o: nbsd-libpci.c $(INCL)
 hurd.o: hurd.c $(INCL)
 win32-cfgmgr32.o: win32-cfgmgr32.c $(INCL)
+win32-sysdbg.o: win32-sysdbg.c $(INCL)
 
 # MinGW32 toolchain has some required Win32 header files in /ddk subdirectory.
 # But these header files include another header files from /ddk subdirectory
index 85bf0b8fe49e72e184bf1dd3e0dbb59d2d5f880f..7585bfe5b6deb739dc916f1f70629277c7c06177 100755 (executable)
@@ -145,9 +145,10 @@ case $sys in
                EXEEXT=.exe
                ;;
        cygwin|windows)
-               echo_n " win32-cfgmgr32"
+               echo_n " win32-cfgmgr32 win32-sysdbg"
                echo >>$c '#define PCI_HAVE_64BIT_ADDRESS'
                echo >>$c '#define PCI_HAVE_PM_WIN32_CFGMGR32'
+               echo >>$c '#define PCI_HAVE_PM_WIN32_SYSDBG'
                # Warning: MinGW-w64 (incorrectly) provides cfgmgr32 functions
                # also in other import libraries, not only in libcfgmgr32.a.
                # So always set -lcfgmgr32 as a first library parameter which
index b881b6bc90835162014eafae06d7689f5a5f4922..d025a96c8809ed4d894fc37b554d9a05ae7af7ac 100644 (file)
@@ -303,21 +303,25 @@ pci_filter_match_v30(struct pci_filter_v30 *f, struct pci_dev *d)
 // (their positions in struct pci_filter were declared as RFU).
 
 STATIC_ALIAS(void pci_filter_init(struct pci_access *a, struct pci_filter *f), pci_filter_init_v38(a, f));
+DEFINE_ALIAS(void pci_filter_init_v33(struct pci_access *a, struct pci_filter *f), pci_filter_init_v38);
 SYMBOL_VERSION(pci_filter_init_v30, pci_filter_init@LIBPCI_3.0);
-SYMBOL_VERSION(pci_filter_init_v38, pci_filter_init@LIBPCI_3.3);
+SYMBOL_VERSION(pci_filter_init_v33, pci_filter_init@LIBPCI_3.3);
 SYMBOL_VERSION(pci_filter_init_v38, pci_filter_init@@LIBPCI_3.8);
 
 STATIC_ALIAS(char *pci_filter_parse_slot(struct pci_filter *f, char *str), pci_filter_parse_slot_v38(f, str));
+DEFINE_ALIAS(char *pci_filter_parse_slot_v33(struct pci_filter *f, char *str), pci_filter_parse_slot_v38);
 SYMBOL_VERSION(pci_filter_parse_slot_v30, pci_filter_parse_slot@LIBPCI_3.0);
-SYMBOL_VERSION(pci_filter_parse_slot_v38, pci_filter_parse_slot@LIBPCI_3.3);
+SYMBOL_VERSION(pci_filter_parse_slot_v33, pci_filter_parse_slot@LIBPCI_3.3);
 SYMBOL_VERSION(pci_filter_parse_slot_v38, pci_filter_parse_slot@@LIBPCI_3.8);
 
 STATIC_ALIAS(char *pci_filter_parse_id(struct pci_filter *f, char *str), pci_filter_parse_id_v38(f, str));
+DEFINE_ALIAS(char *pci_filter_parse_id_v33(struct pci_filter *f, char *str), pci_filter_parse_id_v38);
 SYMBOL_VERSION(pci_filter_parse_id_v30, pci_filter_parse_id@LIBPCI_3.0);
-SYMBOL_VERSION(pci_filter_parse_id_v38, pci_filter_parse_id@LIBPCI_3.3);
+SYMBOL_VERSION(pci_filter_parse_id_v33, pci_filter_parse_id@LIBPCI_3.3);
 SYMBOL_VERSION(pci_filter_parse_id_v38, pci_filter_parse_id@@LIBPCI_3.8);
 
 STATIC_ALIAS(int pci_filter_match(struct pci_filter *f, struct pci_dev *d), pci_filter_match_v38(f, d));
+DEFINE_ALIAS(int pci_filter_match_v33(struct pci_filter *f, struct pci_dev *d), pci_filter_match_v38);
 SYMBOL_VERSION(pci_filter_match_v30, pci_filter_match@LIBPCI_3.0);
-SYMBOL_VERSION(pci_filter_match_v38, pci_filter_match@LIBPCI_3.3);
+SYMBOL_VERSION(pci_filter_match_v33, pci_filter_match@LIBPCI_3.3);
 SYMBOL_VERSION(pci_filter_match_v38, pci_filter_match@@LIBPCI_3.8);
index 525b910a141896113ae28466b359acab5ca46d33..fb845edf77cacf597de301b0b02fccf75511fb36 100644 (file)
 #define PCI_HT_SEC_CMD         2       /* Command Register */
 #define  PCI_HT_SEC_CMD_WR     0x0001  /* Warm Reset */
 #define  PCI_HT_SEC_CMD_DE     0x0002  /* Double-Ended */
-#define  PCI_HT_SEC_CMD_DN     0x0076  /* Device Number */
+#define  PCI_HT_SEC_CMD_DN     0x007c  /* Device Number */
 #define  PCI_HT_SEC_CMD_CS     0x0080  /* Chain Side */
 #define  PCI_HT_SEC_CMD_HH     0x0100  /* Host Hide */
 #define  PCI_HT_SEC_CMD_AS     0x0400  /* Act as Slave */
 #define PCI_DVSEC_VENDOR_ID_CXL        0x1e98  /* Designated Vendor-Specific Vendor ID for CXL */
 #define PCI_DVSEC_ID_CXL       0       /* Designated Vendor-Specific ID for Intel CXL */
 
-/* PCIe CXL Designated Vendor-Specific Capabilities, Control, Status */
-#define PCI_CXL_CAP            0x0a    /* CXL Capability Register */
-#define  PCI_CXL_CAP_CACHE     0x0001  /* CXL.cache Protocol Support */
-#define  PCI_CXL_CAP_IO                0x0002  /* CXL.io Protocol Support */
-#define  PCI_CXL_CAP_MEM       0x0004  /* CXL.mem Protocol Support */
-#define  PCI_CXL_CAP_MEM_HWINIT        0x0008  /* CXL.mem Initializes with HW/FW Support */
-#define  PCI_CXL_CAP_HDM_CNT(x)        (((x) & (3 << 4)) >> 4) /* CXL Number of HDM ranges */
-#define  PCI_CXL_CAP_VIRAL     0x4000  /* CXL Viral Handling Support */
-#define PCI_CXL_CTRL           0x0c    /* CXL Control Register */
-#define  PCI_CXL_CTRL_CACHE    0x0001  /* CXL.cache Protocol Enable */
-#define  PCI_CXL_CTRL_IO       0x0002  /* CXL.io Protocol Enable */
-#define  PCI_CXL_CTRL_MEM      0x0004  /* CXL.mem Protocol Enable */
-#define  PCI_CXL_CTRL_CACHE_SF_COV(x)  (((x) & (0x1f << 3)) >> 3) /* Snoop Filter Coverage */
-#define  PCI_CXL_CTRL_CACHE_SF_GRAN(x) (((x) & (0x7 << 8)) >> 8) /* Snoop Filter Granularity */
-#define  PCI_CXL_CTRL_CACHE_CLN        0x0800  /* CXL.cache Performance Hint on Clean Evictions */
-#define  PCI_CXL_CTRL_VIRAL    0x4000  /* CXL Viral Handling Enable */
-#define PCI_CXL_STATUS         0x0e    /* CXL Status Register */
-#define  PCI_CXL_STATUS_VIRAL  0x4000  /* CXL Viral Handling Status */
+/* PCIe CXL Designated Vendor-Specific Capabilities for Devices: Control, Status */
+#define PCI_CXL_DEV_LEN 0x38 /* CXL Device DVSEC Length */
+#define PCI_CXL_DEV_CAP                        0x0a    /* CXL Capability Register */
+#define  PCI_CXL_DEV_CAP_CACHE         0x0001  /* CXL.cache Protocol Support */
+#define  PCI_CXL_DEV_CAP_IO            0x0002  /* CXL.io Protocol Support */
+#define  PCI_CXL_DEV_CAP_MEM           0x0004  /* CXL.mem Protocol Support */
+#define  PCI_CXL_DEV_CAP_MEM_HWINIT    0x0008  /* CXL.mem Initializes with HW/FW Support */
+#define  PCI_CXL_DEV_CAP_HDM_CNT(x)    (((x) & (3 << 4)) >> 4) /* CXL Number of HDM ranges */
+#define  PCI_CXL_DEV_CAP_VIRAL         0x4000  /* CXL Viral Handling Support */
+#define PCI_CXL_DEV_CTRL               0x0c    /* CXL Control Register */
+#define  PCI_CXL_DEV_CTRL_CACHE                0x0001  /* CXL.cache Protocol Enable */
+#define  PCI_CXL_DEV_CTRL_IO           0x0002  /* CXL.io Protocol Enable */
+#define  PCI_CXL_DEV_CTRL_MEM          0x0004  /* CXL.mem Protocol Enable */
+#define  PCI_CXL_DEV_CTRL_CACHE_SF_COV(x) (((x) & (0x1f << 3)) >> 3) /* Snoop Filter Coverage */
+#define  PCI_CXL_DEV_CTRL_CACHE_SF_GRAN(x) (((x) & (0x7 << 8)) >> 8) /* Snoop Filter Granularity */
+#define  PCI_CXL_DEV_CTRL_CACHE_CLN    0x0800  /* CXL.cache Performance Hint on Clean Evictions */
+#define  PCI_CXL_DEV_CTRL_VIRAL                0x4000  /* CXL Viral Handling Enable */
+#define PCI_CXL_DEV_STATUS             0x0e    /* CXL Status Register */
+#define  PCI_CXL_DEV_STATUS_VIRAL      0x4000  /* CXL Viral Handling Status */
+#define PCI_CXL_DEV_STATUS2            0x12
+#define  PCI_CXL_DEV_STATUS_CACHE_INV  0x0001
+#define  PCI_CXL_DEV_STATUS_RC         0x0002  /* Device Reset Complete */
+#define  PCI_CXL_DEV_STATUS_RE         0x0004  /* Device Reset Error */
+#define  PCI_CXL_DEV_STATUS_PMC                0x8000  /* Power Management Init Complete */
+#define PCI_CXL_DEV_CAP2               0x16
+#define  PCI_CXL_DEV_CAP2_CACHE_UNK    0x0000  /* Cache Size Isn't Reported */
+#define  PCI_CXL_DEV_CAP2_CACHE_64K    0x0001  /* Unit Size 64K */
+#define  PCI_CXL_DEV_CAP2_CACHE_1M     0x0002  /* Unit Size 1M */
+#define PCI_CXL_DEV_RANGE1_SIZE_HI     0x18
+#define PCI_CXL_DEV_RANGE1_SIZE_LO     0x1c
+#define  PCI_CXL_RANGE_VALID           0x0001
+#define  PCI_CXL_RANGE_ACTIVE          0x0002
+#define  PCI_CXL_RANGE_TYPE(x)         (((x) >> 2) & 0x7)
+#define  PCI_CXL_RANGE_CLASS(x)                (((x) >> 5) & 0x7)
+#define  PCI_CXL_RANGE_INTERLEAVE(x)   (((x) >> 8) & 0x1f)
+#define  PCI_CXL_RANGE_TIMEOUT(x)      (((x) >> 13) & 0x7)
+#define PCI_CXL_DEV_RANGE1_BASE_HI     0x20
+#define PCI_CXL_DEV_RANGE1_BASE_LO     0x24
+#define PCI_CXL_DEV_RANGE2_SIZE_HI     0x28
+#define PCI_CXL_DEV_RANGE2_SIZE_LO     0x2c
+#define PCI_CXL_DEV_RANGE2_BASE_HI     0x30
+#define PCI_CXL_DEV_RANGE2_BASE_LO     0x34
+
+/* PCIe CXL 2.0 Designated Vendor-Specific Capabilities for Ports */
+#define PCI_CXL_PORT_EXT_LEN 0x28 /* CXL Extensions DVSEC for Ports Length */
+#define PCI_CXL_PORT_EXT_STATUS 0x0a           /* Port Extension Status */
+#define  PCI_CXL_PORT_PM_INIT_COMPLETE 0x1     /* Port Power Management Initialization Complete */
+#define PCI_CXL_PORT_CTRL 0x0c                 /* Port Control Override */
+#define  PCI_CXL_PORT_UNMASK_SBR 0x0001                /* Unmask SBR */
+#define  PCI_CXL_PORT_UNMASK_LINK 0x0002       /* Unmask Link Disable */
+#define  PCI_CXL_PORT_ALT_MEMORY 0x0004                /* Alt Memory and ID Space Enable */
+#define  PCI_CXL_PORT_ALT_BME 0x0008           /* Alt BME */
+#define  PCI_CXL_PORT_VIRAL_EN 0x4000          /* Viral Enable */
+#define PCI_CXL_PORT_ALT_BUS_BASE 0xe
+#define PCI_CXL_PORT_ALT_BUS_LIMIT 0xf
+#define PCI_CXL_PORT_ALT_MEM_BASE 0x10
+#define PCI_CXL_PORT_ALT_MEM_LIMIT 0x12
+
+/* PCIe CXL 2.0 Designated Vendor-Specific Capabilities for Register Locator */
+#define PCI_CXL_RL_BASE0_LO 0x0c
+#define PCI_CXL_RL_BASE0_HI 0x10
+#define PCI_CXL_RL_BASE1_LO 0x14
+#define PCI_CXL_RL_BASE1_HI 0x18
+#define PCI_CXL_RL_BASE2_LO 0x1c
+#define PCI_CXL_RL_BASE2_HI 0x20
 
 /* Access Control Services */
 #define PCI_ACS_CAP            0x04    /* ACS Capability Register */
 #define  PCI_L1PM_SUBSTAT_CAP_PM_L11   0x2     /* PCI-PM L1.1 Supported */
 #define  PCI_L1PM_SUBSTAT_CAP_ASPM_L12 0x4     /* ASPM L1.2 Supported */
 #define  PCI_L1PM_SUBSTAT_CAP_ASPM_L11 0x8     /* ASPM L1.1 Supported */
-#define  PCI_L1PM_SUBSTAT_CAP_L1PM_SUPP        0x16    /* L1 PM Substates supported */
+#define  PCI_L1PM_SUBSTAT_CAP_L1PM_SUPP        0x10    /* L1 PM Substates supported */
 #define PCI_L1PM_SUBSTAT_CTL1  0x8     /* L1 PM Substate Control 1 */
 #define  PCI_L1PM_SUBSTAT_CTL1_PM_L12  0x1     /* PCI-PM L1.2 Enable */
 #define  PCI_L1PM_SUBSTAT_CTL1_PM_L11  0x2     /* PCI-PM L1.1 Enable */
index 0939a20707cad5c7f58e0e1e63afc51bd2118434..c5a381e78fa91999093c113f920fa34b645cb607 100644 (file)
@@ -260,7 +260,7 @@ hurd_write(struct pci_dev *d, int pos, byte * buf, int len)
 
 /* Get requested info from the server */
 
-static void
+static int
 hurd_fill_regions(struct pci_dev *d)
 {
   mach_port_t device_port = device_port_lookup(d);
@@ -270,7 +270,7 @@ hurd_fill_regions(struct pci_dev *d)
 
   int err = pci_get_dev_regions(device_port, &buf, &size);
   if (err)
-    return;
+    return 0;
 
   if ((char *) &regions != buf)
     {
@@ -278,7 +278,7 @@ hurd_fill_regions(struct pci_dev *d)
       if (size > sizeof(regions))
        {
          vm_deallocate(mach_task_self(), (vm_address_t) buf, size);
-         return;
+         return 0;
        }
 
       memcpy(&regions, buf, size);
@@ -297,9 +297,11 @@ hurd_fill_regions(struct pci_dev *d)
 
       d->size[i] = regions[i].size;
     }
+
+  return 1;
 }
 
-static void
+static int
 hurd_fill_rom(struct pci_dev *d)
 {
   struct pci_xrom_bar rom;
@@ -309,7 +311,7 @@ hurd_fill_rom(struct pci_dev *d)
 
   int err = pci_get_dev_rom(device_port, &buf, &size);
   if (err)
-    return;
+    return 0;
 
   if ((char *) &rom != buf)
     {
@@ -317,7 +319,7 @@ hurd_fill_rom(struct pci_dev *d)
       if (size > sizeof(rom))
        {
          vm_deallocate(mach_task_self(), (vm_address_t) buf, size);
-         return;
+         return 0;
        }
 
       memcpy(&rom, buf, size);
@@ -326,6 +328,8 @@ hurd_fill_rom(struct pci_dev *d)
 
   d->rom_base_addr = rom.base_addr;
   d->rom_size = rom.size;
+
+  return 1;
 }
 
 static void
@@ -334,10 +338,18 @@ hurd_fill_info(struct pci_dev *d, unsigned int flags)
   if (!d->access->buscentric)
     {
       if (want_fill(d, flags, PCI_FILL_BASES | PCI_FILL_SIZES))
-       hurd_fill_regions(d);
+       {
+         if (hurd_fill_regions(d))
+           clear_fill(d, PCI_FILL_BASES | PCI_FILL_SIZES);
+       }
       if (want_fill(d, flags, PCI_FILL_ROM_BASE))
-       hurd_fill_rom(d);
+       {
+         if (hurd_fill_rom(d))
+           clear_fill(d, PCI_FILL_ROM_BASE);
+       }
     }
+
+  pci_generic_fill_info(d, flags);
 }
 
 struct pci_methods pm_hurd = {
index f997b2bd83db39396c961bf0f01442aa9e52067c..de7d6f24a9e065c2e378e935a8c180ccbad9755b 100644 (file)
@@ -81,6 +81,11 @@ static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
 #else
   NULL,
 #endif
+#ifdef PCI_HAVE_PM_WIN32_SYSDBG
+  &pm_win32_sysdbg,
+#else
+  NULL,
+#endif
 };
 
 // If PCI_ACCESS_AUTO is selected, we probe the access methods in this order
@@ -96,6 +101,7 @@ static int probe_sequence[] = {
   PCI_ACCESS_SYLIXOS_DEVICE,
   PCI_ACCESS_HURD,
   PCI_ACCESS_WIN32_CFGMGR32,
+  PCI_ACCESS_WIN32_SYSDBG,
   // Low-level methods poking the hardware directly
   PCI_ACCESS_I386_TYPE1,
   PCI_ACCESS_I386_TYPE2,
index e0185dde7134f399fc5b18f0dc7356b67a3ea5bb..0a5dce462a541e7dfbc717975b6e0e641ef3e16f 100644 (file)
@@ -116,4 +116,4 @@ void pci_free_caps(struct pci_dev *);
 extern struct pci_methods pm_intel_conf1, pm_intel_conf2, pm_linux_proc,
        pm_fbsd_device, pm_aix_device, pm_nbsd_libpci, pm_obsd_device,
        pm_dump, pm_linux_sysfs, pm_darwin, pm_sylixos_device, pm_hurd,
-       pm_win32_cfgmgr32;
+       pm_win32_cfgmgr32, pm_win32_sysdbg;
index eeb4a55cb18db40c0bafd9babaa4a9454f357779..41a162b9a3970bf29178ae2373dbdf4bde94ac2d 100644 (file)
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -44,6 +44,7 @@ enum pci_access_type {
   PCI_ACCESS_SYLIXOS_DEVICE,           /* SylixOS pci */
   PCI_ACCESS_HURD,                     /* GNU/Hurd */
   PCI_ACCESS_WIN32_CFGMGR32,           /* Win32 cfgmgr32.dll */
+  PCI_ACCESS_WIN32_SYSDBG,             /* Win32 NT SysDbg */
   PCI_ACCESS_MAX
 };
 
diff --git a/lib/win32-sysdbg.c b/lib/win32-sysdbg.c
new file mode 100644 (file)
index 0000000..5d0c07a
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ *      The PCI Library -- PCI config space access using NT SysDbg interface
+ *
+ *      Copyright (c) 2022 Pali Rohár <pali@kernel.org>
+ *
+ *      Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <windows.h>
+
+#include "internal.h"
+#include "i386-io-windows.h"
+
+#ifndef NTSTATUS
+#define NTSTATUS LONG
+#endif
+#ifndef STATUS_UNSUCCESSFUL
+#define STATUS_UNSUCCESSFUL (NTSTATUS)0xC0000001
+#endif
+#ifndef STATUS_NOT_IMPLEMENTED
+#define STATUS_NOT_IMPLEMENTED (NTSTATUS)0xC0000002
+#endif
+#ifndef STATUS_INVALID_INFO_CLASS
+#define STATUS_INVALID_INFO_CLASS (NTSTATUS)0xC0000003
+#endif
+#ifndef STATUS_ACCESS_DENIED
+#define STATUS_ACCESS_DENIED (NTSTATUS)0xC0000022
+#endif
+#ifndef STATUS_DEBUGGER_INACTIVE
+#define STATUS_DEBUGGER_INACTIVE (NTSTATUS)0xC0000354
+#endif
+
+#ifndef BUS_DATA_TYPE
+#define BUS_DATA_TYPE LONG
+#endif
+#ifndef PCIConfiguration
+#define PCIConfiguration (BUS_DATA_TYPE)4
+#endif
+
+#ifndef SYSDBG_COMMAND
+#define SYSDBG_COMMAND ULONG
+#endif
+#ifndef SysDbgReadBusData
+#define SysDbgReadBusData (SYSDBG_COMMAND)18
+#endif
+#ifndef SysDbgWriteBusData
+#define SysDbgWriteBusData (SYSDBG_COMMAND)19
+#endif
+
+#ifndef SYSDBG_BUS_DATA
+typedef struct _SYSDBG_BUS_DATA {
+  ULONG Address;
+  PVOID Buffer;
+  ULONG Request;
+  BUS_DATA_TYPE BusDataType;
+  ULONG BusNumber;
+  ULONG SlotNumber;
+} SYSDBG_BUS_DATA, *PSYSDBG_BUS_DATA;
+#define SYSDBG_BUS_DATA SYSDBG_BUS_DATA
+#endif
+
+#ifndef PCI_SLOT_NUMBER
+typedef struct _PCI_SLOT_NUMBER {
+  union {
+    struct {
+      ULONG DeviceNumber:5;
+      ULONG FunctionNumber:3;
+      ULONG Reserved:24;
+    } bits;
+    ULONG AsULONG;
+  } u;
+} PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER;
+#define PCI_SLOT_NUMBER PCI_SLOT_NUMBER
+#endif
+
+#ifdef NtSystemDebugControl
+#undef NtSystemDebugControl
+#endif
+static NTSTATUS (NTAPI *MyNtSystemDebugControl)(SYSDBG_COMMAND Command, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, PULONG ReturnLength);
+#define NtSystemDebugControl MyNtSystemDebugControl
+
+static BOOL debug_privilege_enabled;
+static LUID luid_debug_privilege;
+static BOOL revert_only_privilege;
+static HANDLE revert_token;
+static HMODULE ntdll;
+
+static int win32_sysdbg_initialized;
+
+static NTSTATUS
+win32_sysdbg_pci_bus_data(BOOL WriteBusData, BYTE BusNumber, BYTE DeviceNumber, BYTE FunctionNumber, BYTE Address, PVOID Buffer, BYTE BufferSize, PULONG Length)
+{
+  SYSDBG_BUS_DATA sysdbg_cmd;
+  PCI_SLOT_NUMBER pci_slot;
+
+  if (!NtSystemDebugControl)
+    return STATUS_NOT_IMPLEMENTED;
+
+  memset(&pci_slot, 0, sizeof(pci_slot));
+  memset(&sysdbg_cmd, 0, sizeof(sysdbg_cmd));
+
+  sysdbg_cmd.Address = Address;
+  sysdbg_cmd.Buffer = Buffer;
+  sysdbg_cmd.Request = BufferSize;
+  sysdbg_cmd.BusDataType = PCIConfiguration;
+  sysdbg_cmd.BusNumber = BusNumber;
+  pci_slot.u.bits.DeviceNumber = DeviceNumber;
+  pci_slot.u.bits.FunctionNumber = FunctionNumber;
+  sysdbg_cmd.SlotNumber = pci_slot.u.AsULONG;
+
+  *Length = 0;
+  return NtSystemDebugControl(WriteBusData ? SysDbgWriteBusData : SysDbgReadBusData, &sysdbg_cmd, sizeof(sysdbg_cmd), NULL, 0, Length);
+}
+
+static int
+win32_sysdbg_setup(struct pci_access *a)
+{
+  UINT prev_error_mode;
+  NTSTATUS status;
+  ULONG ret_len;
+  DWORD id;
+
+  if (win32_sysdbg_initialized)
+    return 1;
+
+  prev_error_mode = change_error_mode(SEM_FAILCRITICALERRORS);
+  ntdll = LoadLibrary(TEXT("ntdll.dll"));
+  change_error_mode(prev_error_mode);
+  if (!ntdll)
+    {
+      a->debug("Cannot open ntdll.dll library.");
+      return 0;
+    }
+
+  NtSystemDebugControl = (LPVOID)GetProcAddress(ntdll, "NtSystemDebugControl");
+  if (!NtSystemDebugControl)
+    {
+      a->debug("Function NtSystemDebugControl() is not supported.");
+      FreeLibrary(ntdll);
+      ntdll = NULL;
+      return 0;
+    }
+
+  /*
+   * Try to read PCI id register from PCI device 00:00.0.
+   * If this device does not exist and NT SysDbg API is working then
+   * NT SysDbg returns STATUS_UNSUCCESSFUL.
+   */
+  status = win32_sysdbg_pci_bus_data(FALSE, 0, 0, 0, 0, &id, sizeof(id), &ret_len);
+  if ((status >= 0 && ret_len == sizeof(id)) || status == STATUS_UNSUCCESSFUL)
+    {
+      win32_sysdbg_initialized = 1;
+      return 1;
+    }
+  else if (status != STATUS_ACCESS_DENIED)
+    {
+      if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS)
+        a->debug("NT SysDbg is not supported.");
+      else if (status == STATUS_DEBUGGER_INACTIVE)
+        a->debug("NT SysDbg is disabled.");
+      else
+        a->debug("NT SysDbg returned error 0x%lx.", status);
+      FreeLibrary(ntdll);
+      ntdll = NULL;
+      NtSystemDebugControl = NULL;
+      return 0;
+    }
+
+  a->debug("NT SysDbg returned Access Denied, trying again with Debug privilege...");
+
+  if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid_debug_privilege))
+    {
+      a->debug("Debug privilege is not supported.");
+      FreeLibrary(ntdll);
+      ntdll = NULL;
+      NtSystemDebugControl = NULL;
+      return 0;
+    }
+
+  if (!enable_privilege(luid_debug_privilege, &revert_token, &revert_only_privilege))
+    {
+      a->debug("Cannot enable Debug privilege.");
+      FreeLibrary(ntdll);
+      ntdll = NULL;
+      NtSystemDebugControl = NULL;
+      return 0;
+    }
+
+  status = win32_sysdbg_pci_bus_data(FALSE, 0, 0, 0, 0, &id, sizeof(id), &ret_len);
+  if ((status >= 0 && ret_len == sizeof(id)) || status == STATUS_UNSUCCESSFUL)
+    {
+      a->debug("Succeeded.");
+      debug_privilege_enabled = TRUE;
+      win32_sysdbg_initialized = 1;
+      return 1;
+    }
+
+  revert_privilege(luid_debug_privilege, revert_token, revert_only_privilege);
+  revert_token = NULL;
+  revert_only_privilege = FALSE;
+
+  FreeLibrary(ntdll);
+  ntdll = NULL;
+  NtSystemDebugControl = NULL;
+
+  if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS)
+    a->debug("NT SysDbg is not supported.");
+  else if (status == STATUS_DEBUGGER_INACTIVE)
+    a->debug("NT SysDbg is disabled.");
+  else if (status == STATUS_ACCESS_DENIED)
+    a->debug("NT SysDbg returned Access Denied.");
+  else
+    a->debug("NT SysDbg returned error 0x%lx.", status);
+
+  return 0;
+}
+
+static int
+win32_sysdbg_detect(struct pci_access *a)
+{
+  if (!win32_sysdbg_setup(a))
+    return 0;
+
+  return 1;
+}
+
+static void
+win32_sysdbg_init(struct pci_access *a)
+{
+  if (!win32_sysdbg_setup(a))
+    {
+      a->debug("\n");
+      a->error("NT SysDbg PCI Bus Data interface cannot be accessed.");
+    }
+}
+
+static void
+win32_sysdbg_cleanup(struct pci_access *a UNUSED)
+{
+  if (!win32_sysdbg_initialized)
+    return;
+
+  if (debug_privilege_enabled)
+    {
+      revert_privilege(luid_debug_privilege, revert_token, revert_only_privilege);
+      revert_token = NULL;
+      revert_only_privilege = FALSE;
+      debug_privilege_enabled = FALSE;
+    }
+
+  FreeLibrary(ntdll);
+  ntdll = NULL;
+  NtSystemDebugControl = NULL;
+
+  win32_sysdbg_initialized = 0;
+}
+
+static int
+win32_sysdbg_read(struct pci_dev *d, int pos, byte *buf, int len)
+{
+  NTSTATUS status;
+  ULONG ret_len;
+
+  if ((unsigned int)d->domain > 0 || (unsigned int)pos > 255 || (unsigned int)(pos+len) > 256)
+    return 0;
+
+  status = win32_sysdbg_pci_bus_data(FALSE, d->bus, d->dev, d->func, pos, buf, len, &ret_len);
+  if (status < 0 || ret_len != (unsigned int)len)
+    return 0;
+
+  return 1;
+}
+
+static int
+win32_sysdbg_write(struct pci_dev *d, int pos, byte *buf, int len)
+{
+  NTSTATUS status;
+  ULONG ret_len;
+
+  if ((unsigned int)d->domain > 0 || (unsigned int)pos > 255 || (unsigned int)(pos+len) > 256)
+    return 0;
+
+  status = win32_sysdbg_pci_bus_data(TRUE, d->bus, d->dev, d->func, pos, buf, len, &ret_len);
+  if (status < 0 || ret_len != (unsigned int)len)
+    return 0;
+
+  return 1;
+}
+
+struct pci_methods pm_win32_sysdbg = {
+  "win32-sysdbg",
+  "Win32 PCI config space access using NT SysDbg Bus Data interface",
+  NULL,                                        /* config */
+  win32_sysdbg_detect,
+  win32_sysdbg_init,
+  win32_sysdbg_cleanup,
+  pci_generic_scan,
+  pci_generic_fill_info,
+  win32_sysdbg_read,
+  win32_sysdbg_write,
+  NULL,                                        /* read_vpd */
+  NULL,                                        /* init_dev */
+  NULL                                 /* cleanup_dev */
+};
index 32a2cbcb4b0caa8da7798c8f1426ee1986d7e289..f7ffd833b85418dabcca77d9a97fe32e8d56124f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     The PCI Utilities -- Show Extended Capabilities
  *
- *     Copyright (c) 1997--2020 Martin Mares <mj@ucw.cz>
+ *     Copyright (c) 1997--2022 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -549,7 +549,7 @@ cap_vc(struct device *d, int where)
       pat_pos = BITS(rcap, 24, 8);
       printf("Caps:\tPATOffset=%02x MaxTimeSlots=%d RejSnoopTrans%c\n",
        pat_pos,
-       BITS(rcap, 16, 6) + 1,
+       BITS(rcap, 16, 7) + 1,
        FLAG(rcap, 1 << 15));
 
       printf("\t\t\tArb:");
@@ -690,30 +690,193 @@ cap_rcec(struct device *d, int where)
 }
 
 static void
-cap_dvsec_cxl(struct device *d, int where)
+cxl_range(u64 base, u64 size, int n)
 {
-  u16 l;
+  u32 interleave[] = { 0, 256, 4096, 512, 1024, 2048, 8192, 16384 };
+  const char *type[] = { "Volatile", "Non-volatile", "CDAT" };
+  const char *class[] = { "DRAM", "Storage", "CDAT" };
+  u16 w;
 
-  printf(": CXL\n");
-  if (verbose < 2)
+  w = (u16) size;
+
+  size &= ~0x0fffffffULL;
+
+  printf("\t\tRange%d: %016"PCI_U64_FMT_X"-%016"PCI_U64_FMT_X"\n", n, base, base + size - 1);
+  printf("\t\t\tValid%c Active%c Type=%s Class=%s interleave=%d timeout=%ds\n",
+    FLAG(w, PCI_CXL_RANGE_VALID), FLAG(w, PCI_CXL_RANGE_ACTIVE),
+    type[PCI_CXL_RANGE_TYPE(w)], class[PCI_CXL_RANGE_CLASS(w)],
+    interleave[PCI_CXL_RANGE_INTERLEAVE(w)],
+    1 << (PCI_CXL_RANGE_TIMEOUT(w) * 2));
+}
+
+static void
+dvsec_cxl_device(struct device *d, int rev, int where, int len)
+{
+  u32 cache_size, cache_unit_size;
+  u64 range_base, range_size;
+  u16 w;
+
+  if (len < PCI_CXL_DEV_LEN)
     return;
 
-  if (!config_fetch(d, where + PCI_CXL_CAP, 12))
+  /* Legacy 1.1 revs aren't handled */
+  if (rev < 1)
     return;
 
-  l = get_conf_word(d, where + PCI_CXL_CAP);
+  w = get_conf_word(d, where + PCI_CXL_DEV_CAP);
   printf("\t\tCXLCap:\tCache%c IO%c Mem%c Mem HW Init%c HDMCount %d Viral%c\n",
-    FLAG(l, PCI_CXL_CAP_CACHE), FLAG(l, PCI_CXL_CAP_IO), FLAG(l, PCI_CXL_CAP_MEM),
-    FLAG(l, PCI_CXL_CAP_MEM_HWINIT), PCI_CXL_CAP_HDM_CNT(l), FLAG(l, PCI_CXL_CAP_VIRAL));
+    FLAG(w, PCI_CXL_DEV_CAP_CACHE), FLAG(w, PCI_CXL_DEV_CAP_IO), FLAG(w, PCI_CXL_DEV_CAP_MEM),
+    FLAG(w, PCI_CXL_DEV_CAP_MEM_HWINIT), PCI_CXL_DEV_CAP_HDM_CNT(w), FLAG(w, PCI_CXL_DEV_CAP_VIRAL));
 
-  l = get_conf_word(d, where + PCI_CXL_CTRL);
+  w = get_conf_word(d, where + PCI_CXL_DEV_CTRL);
   printf("\t\tCXLCtl:\tCache%c IO%c Mem%c Cache SF Cov %d Cache SF Gran %d Cache Clean%c Viral%c\n",
-    FLAG(l, PCI_CXL_CTRL_CACHE), FLAG(l, PCI_CXL_CTRL_IO), FLAG(l, PCI_CXL_CTRL_MEM),
-    PCI_CXL_CTRL_CACHE_SF_COV(l), PCI_CXL_CTRL_CACHE_SF_GRAN(l), FLAG(l, PCI_CXL_CTRL_CACHE_CLN),
-    FLAG(l, PCI_CXL_CTRL_VIRAL));
+    FLAG(w, PCI_CXL_DEV_CTRL_CACHE), FLAG(w, PCI_CXL_DEV_CTRL_IO), FLAG(w, PCI_CXL_DEV_CTRL_MEM),
+    PCI_CXL_DEV_CTRL_CACHE_SF_COV(w), PCI_CXL_DEV_CTRL_CACHE_SF_GRAN(w), FLAG(w, PCI_CXL_DEV_CTRL_CACHE_CLN),
+    FLAG(w, PCI_CXL_DEV_CTRL_VIRAL));
+
+  w = get_conf_word(d, where + PCI_CXL_DEV_STATUS);
+  printf("\t\tCXLSta:\tViral%c\n", FLAG(w, PCI_CXL_DEV_STATUS_VIRAL));
+
+  w = get_conf_word(d, where + PCI_CXL_DEV_STATUS2);
+  printf("\t\tCXLSta2:\tResetComplete%c ResetError%c PMComplete%c\n",
+    FLAG(w, PCI_CXL_DEV_STATUS_RC), FLAG(w,PCI_CXL_DEV_STATUS_RE), FLAG(w, PCI_CXL_DEV_STATUS_PMC));
 
-  l = get_conf_word(d, where + PCI_CXL_STATUS);
-  printf("\t\tCXLSta:\tViral%c\n", FLAG(l, PCI_CXL_STATUS_VIRAL));
+  w = get_conf_word(d, where + PCI_CXL_DEV_CAP2);
+  cache_unit_size = BITS(w, 0, 4);
+  cache_size = BITS(w, 8, 8);
+  switch (cache_unit_size)
+    {
+      case PCI_CXL_DEV_CAP2_CACHE_1M:
+        printf("\t\tCache Size: %08x\n", cache_size * (1<<20));
+       break;
+      case PCI_CXL_DEV_CAP2_CACHE_64K:
+        printf("\t\tCache Size: %08x\n", cache_size * (64<<10));
+       break;
+      case PCI_CXL_DEV_CAP2_CACHE_UNK:
+        printf("\t\tCache Size Not Reported\n");
+       break;
+      default:
+        printf("\t\tCache Size: %d of unknown unit size (%d)\n", cache_size, cache_unit_size);
+       break;
+    }
+
+  range_size = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE1_SIZE_HI) << 32;
+  range_size |= get_conf_long(d, where + PCI_CXL_DEV_RANGE1_SIZE_LO);
+  range_base = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE1_BASE_HI) << 32;
+  range_base |= get_conf_long(d, where + PCI_CXL_DEV_RANGE1_BASE_LO);
+  cxl_range(range_base, range_size, 1);
+
+  range_size = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE2_SIZE_HI) << 32;
+  range_size |= get_conf_long(d, where + PCI_CXL_DEV_RANGE2_SIZE_LO);
+  range_base = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE2_BASE_HI) << 32;
+  range_base |= get_conf_long(d, where + PCI_CXL_DEV_RANGE2_BASE_LO);
+  cxl_range(range_base, range_size, 2);
+}
+
+static void
+dvsec_cxl_port(struct device *d, int where, int len)
+{
+  u16 w, m1, m2;
+  u8 b1, b2;
+
+  if (len < PCI_CXL_PORT_EXT_LEN)
+    return;
+
+  w = get_conf_word(d, where + PCI_CXL_PORT_EXT_STATUS);
+  printf("\t\tCXLPortSta:\tPMComplete%c\n", FLAG(w, PCI_CXL_PORT_EXT_STATUS));
+
+  w = get_conf_word(d, where + PCI_CXL_PORT_CTRL);
+  printf("\t\tCXLPortCtl:\tUnmaskSBR%c UnmaskLinkDisable%c AltMem%c AltBME%c ViralEnable%c\n",
+    FLAG(w, PCI_CXL_PORT_UNMASK_SBR), FLAG(w, PCI_CXL_PORT_UNMASK_LINK),
+    FLAG(w, PCI_CXL_PORT_ALT_MEMORY), FLAG(w, PCI_CXL_PORT_ALT_BME),
+    FLAG(w, PCI_CXL_PORT_VIRAL_EN));
+
+  b1 = get_conf_byte(d, where + PCI_CXL_PORT_ALT_BUS_BASE);
+  b2 = get_conf_byte(d, where + PCI_CXL_PORT_ALT_BUS_LIMIT);
+  printf("\t\tAlternateBus:\t%02x-%02x\n", b1, b2);
+  m1 = get_conf_word(d, where + PCI_CXL_PORT_ALT_MEM_BASE);
+  m2 = get_conf_word(d, where + PCI_CXL_PORT_ALT_MEM_LIMIT);
+  printf("\t\tAlternateBus:\t%04x-%04x\n", m1, m2);
+}
+
+static void
+dvsec_cxl_register_locator(struct device *d, int where, int len)
+{
+  static const char * const id_names[] = {
+    "empty",
+    "component registers",
+    "BAR virtualization",
+    "CXL device registers",
+    "CPMU registers",
+  };
+
+  for (int i=0; ; i++)
+    {
+      int pos = where + 8*i;
+      if (pos + 7 >= len)
+       break;
+
+      u32 lo = get_conf_long(d, pos);
+      u32 hi = get_conf_long(d, pos + 4);
+
+      unsigned int bir = BITS(lo, 0, 3);
+      unsigned int block_id = BITS(lo, 8, 8);
+      u64 base = (BITS(lo, 16, 16) << 16) | ((u64) hi << 32);
+
+      if (!block_id)
+       continue;
+
+      const char *id_name;
+      if (block_id < sizeof(id_names) / sizeof(*id_names))
+       id_name = id_names[block_id];
+      else if (block_id == 0xff)
+       id_name = "vendor-specific";
+      else
+       id_name = "<?>";
+
+      printf("\t\tBlock%d: BIR: bar%d, ID: %s, offset: %016" PCI_U64_FMT_X "\n", i, bir, id_name, base);
+    }
+}
+
+static void
+cap_dvsec_cxl(struct device *d, int id, int rev, int where, int len)
+{
+  printf(": CXL\n");
+  if (verbose < 2)
+    return;
+
+  if (!config_fetch(d, where, len))
+    return;
+
+  switch (id)
+    {
+    case 0:
+      dvsec_cxl_device(d, rev, where, len);
+      break;
+    case 2:
+      printf("\t\tNon-CXL Function Map DVSEC\n");
+      break;
+    case 3:
+      dvsec_cxl_port(d, where, len);
+      break;
+    case 4:
+      printf("\t\tGPF DVSEC for Port\n");
+      break;
+    case 5:
+      printf("\t\tGPF DVSEC for Device\n");
+      break;
+    case 7:
+      printf("\t\tPCIe DVSEC Flex Bus Port\n");
+      break;
+    case 8:
+      dvsec_cxl_register_locator(d, where, len);
+      break;
+    case 9:
+      printf("\t\tMLD DVSEC\n");
+      break;
+    default:
+      printf("\t\tUnknown ID %04x\n", id);
+    }
 }
 
 static void
@@ -734,8 +897,8 @@ cap_dvsec(struct device *d, int where)
   u16 id = get_conf_long(d, where + PCI_DVSEC_HEADER2);
 
   printf("Vendor=%04x ID=%04x Rev=%d Len=%d", vendor, id, rev, len);
-  if (vendor == PCI_DVSEC_VENDOR_ID_CXL && id == PCI_DVSEC_ID_CXL && len >= 16)
-    cap_dvsec_cxl(d, where);
+  if (vendor == PCI_DVSEC_VENDOR_ID_CXL && len >= 16)
+    cap_dvsec_cxl(d, id, rev, where, len);
   else
     printf(" <?>\n");
 }
index cc65ac472097b36d93100e7ba6821ebf873fecfd..af1e659105c8613696a1ff2e290806a908a6721d 100644 (file)
--- a/ls-tree.c
+++ b/ls-tree.c
@@ -219,7 +219,7 @@ print_it(char *line, char *p)
       *p = ' ';
 }
 
-static void show_tree_bridge(struct bridge *, char *, char *);
+static void show_tree_bridge(struct pci_filter *filter, struct bridge *, char *, char *);
 
 static char * FORMAT_CHECK(printf, 3, 4)
 tree_printf(char *line, char *p, char *fmt, ...)
@@ -252,7 +252,7 @@ tree_printf(char *line, char *p, char *fmt, ...)
 }
 
 static void
-show_tree_dev(struct device *d, char *line, char *p)
+show_tree_dev(struct pci_filter *filter, struct device *d, char *line, char *p)
 {
   struct pci_dev *q = d->dev;
   struct bridge *b;
@@ -268,7 +268,7 @@ show_tree_dev(struct device *d, char *line, char *p)
          p = tree_printf(line, p, "-[%02x]-", b->secondary);
        else
          p = tree_printf(line, p, "-[%02x-%02x]-", b->secondary, b->subordinate);
-        show_tree_bridge(b, line, p);
+        show_tree_bridge(filter, b, line, p);
         return;
       }
   if (verbose)
@@ -279,53 +279,127 @@ show_tree_dev(struct device *d, char *line, char *p)
   print_it(line, p);
 }
 
+static int
+check_bus_filter(struct pci_filter *filter, struct bus *b);
+
+static int
+check_dev_filter(struct pci_filter *filter, struct device *d)
+{
+  struct bridge *br;
+  struct bus *b;
+
+  if (!filter)
+    return 1;
+
+  if (pci_filter_match(filter, d->dev))
+    return 1;
+
+  for (br = &host_bridge; br; br = br->chain)
+    if (br->br_dev == d)
+      {
+        for (b = br->first_bus; b; b = b->sibling)
+          if (check_bus_filter(filter, b))
+            return 1;
+        break;
+      }
+
+  return 0;
+}
+
+static int
+check_bus_filter(struct pci_filter *filter, struct bus *b)
+{
+  struct device *d;
+
+  if (!filter)
+    return 1;
+
+  for (d = b->first_dev; d; d = d->bus_next)
+    if (check_dev_filter(filter, d))
+      return 1;
+
+  return 0;
+}
+
 static void
-show_tree_bus(struct bus *b, char *line, char *p)
+show_tree_bus(struct pci_filter *filter, struct bus *b, char *line, char *p)
 {
   if (!b->first_dev)
     print_it(line, p);
   else if (!b->first_dev->bus_next)
     {
-      p = tree_printf(line, p, "--");
-      show_tree_dev(b->first_dev, line, p);
+      if (check_dev_filter(filter, b->first_dev))
+        {
+          p = tree_printf(line, p, "--");
+          show_tree_dev(filter, b->first_dev, line, p);
+        }
+      else
+        print_it(line, p);
     }
   else
     {
+      int empty = 1;
       struct device *d = b->first_dev;
       while (d->bus_next)
        {
-         char *p2 = tree_printf(line, p, "+-");
-         show_tree_dev(d, line, p2);
+         if (check_dev_filter(filter, d))
+           {
+             char *p2 = tree_printf(line, p, "+-");
+             show_tree_dev(filter, d, line, p2);
+             empty = 0;
+           }
          d = d->bus_next;
        }
-      p = tree_printf(line, p, "\\-");
-      show_tree_dev(d, line, p);
+      if (check_dev_filter(filter, d))
+        {
+          p = tree_printf(line, p, "\\-");
+          show_tree_dev(filter, d, line, p);
+          empty = 0;
+        }
+      if (empty)
+        print_it(line, p);
     }
 }
 
 static void
-show_tree_bridge(struct bridge *b, char *line, char *p)
+show_tree_bridge(struct pci_filter *filter, struct bridge *b, char *line, char *p)
 {
   *p++ = '-';
   if (!b->first_bus->sibling)
     {
-      if (b == &host_bridge)
-        p = tree_printf(line, p, "[%04x:%02x]-", b->domain, b->first_bus->number);
-      show_tree_bus(b->first_bus, line, p);
+      if (check_bus_filter(filter, b->first_bus))
+        {
+          if (b == &host_bridge)
+            p = tree_printf(line, p, "[%04x:%02x]-", b->domain, b->first_bus->number);
+          show_tree_bus(filter, b->first_bus, line, p);
+        }
+      else
+        print_it(line, p);
     }
   else
     {
+      int empty = 1;
       struct bus *u = b->first_bus;
       char *k;
 
       while (u->sibling)
         {
-          k = tree_printf(line, p, "+-[%04x:%02x]-", u->domain, u->number);
-          show_tree_bus(u, line, k);
+          if (check_bus_filter(filter, u))
+            {
+              k = tree_printf(line, p, "+-[%04x:%02x]-", u->domain, u->number);
+              show_tree_bus(filter, u, line, k);
+              empty = 0;
+            }
           u = u->sibling;
         }
-      k = tree_printf(line, p, "\\-[%04x:%02x]-", u->domain, u->number);
-      show_tree_bus(u, line, k);
+      if (check_bus_filter(filter, u))
+        {
+          k = tree_printf(line, p, "\\-[%04x:%02x]-", u->domain, u->number);
+          show_tree_bus(filter, u, line, k);
+          empty = 0;
+        }
+      if (empty)
+        print_it(line, p);
     }
 }
 
@@ -333,20 +407,5 @@ void
 show_forest(struct pci_filter *filter)
 {
   char line[LINE_BUF_SIZE];
-  if (filter == NULL)
-    show_tree_bridge(&host_bridge, line, line);
-  else
-    {
-      struct bridge *b;
-      for (b=&host_bridge; b; b=b->chain)
-        {
-          if (b->br_dev && pci_filter_match(filter, b->br_dev->dev))
-            {
-                struct pci_dev *d = b->br_dev->dev;
-                char *p = line;
-                p = tree_printf(line, p, "%04x:%02x:", d->domain_16, d->bus);
-                show_tree_dev(b->br_dev, line, p);
-            }
-        }
-    }
+  show_tree_bridge(filter, &host_bridge, line, line);
 }
index 2dc3bd681111750d5206074628b74704841bc224..59b3777ca674973282e518de4a1efee745ccad02 100755 (executable)
@@ -3,4 +3,4 @@ if [ -z "$1" -o -n "$2" ] ; then
        echo >&2 'Usage: tag-release vX.Y.Z'
        exit 1
 fi
-git tag -u ED70F82D $1
+git tag -u 1F3D0761D9B65F0B $1
index 63e58c8572feec9048a14541cb4391311f64d465..115f1f350423d03cc0047777c445cb91faf3f39d 100644 (file)
@@ -76,6 +76,13 @@ is no access to the PCI configuration space but libpci provides read-only
 virtual emulation based on information from Configuration Manager. Starting
 with Windows 8 (NT 6.2) it is not possible to retrieve resources from 32-bit
 application or library on 64-bit system.
+.TP
+.B win32-sysdbg
+Access to the PCI configuration space via NT SysDbg interface on Windows
+systems. Process needs to have Debug privilege, which local Administrators
+have by default. Not available on 64-bit systems and neither on recent 32-bit
+systems. Only devices from the first domain are accessible and only first
+256 bytes of the PCI configuration space is accessible via this method.
 
 .SH PARAMETERS