summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>2022-11-18 10:46:22 +0100
committerMartin Mares <mj@ucw.cz>2022-11-18 10:46:22 +0100
commitf9447371463eb6bb4c001be132a0d7c495df00d0 (patch)
treedc1b612a6d84e732ed157b3239206a4f0d58fc33
parentc7d9aa0bcee872630ae4f543a5b4e61aa2139974 (diff)
parent0a7350fb9442dbfb8b0328ec9f7080947a28c2a1 (diff)
downloadpciutils-f9447371463eb6bb4c001be132a0d7c495df00d0.tar.gz
Merge remote-tracking branch 'pali/intel-conf1-memio'
-rw-r--r--lib/Makefile5
-rw-r--r--lib/aix-device.c2
-rwxr-xr-xlib/configure18
-rw-r--r--lib/generic.c16
-rw-r--r--lib/init.c6
-rw-r--r--lib/internal.h4
-rw-r--r--lib/mmio-ports.c387
-rw-r--r--lib/pci.h2
-rw-r--r--lib/sylixos-device.c2
-rw-r--r--pcilib.man16
10 files changed, 450 insertions, 8 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 05db1ec..76ef0d4 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -18,6 +18,10 @@ ifdef PCI_HAVE_PM_INTEL_CONF
OBJS += i386-ports
endif
+ifdef PCI_HAVE_PM_MMIO_CONF
+OBJS += mmio-ports
+endif
+
ifdef PCI_HAVE_PM_DUMP
OBJS += dump
endif
@@ -111,6 +115,7 @@ init.o: init.c $(INCL)
access.o: access.c $(INCL)
params.o: params.c $(INCL)
i386-ports.o: i386-ports.c $(INCL) i386-io-hurd.h i386-io-linux.h i386-io-sunos.h i386-io-windows.h i386-io-cygwin.h
+mmio-ports.o: mmio-ports.c $(INCL)
proc.o: proc.c $(INCL) pread.h
sysfs.o: sysfs.c $(INCL) pread.h
generic.o: generic.c $(INCL)
diff --git a/lib/aix-device.c b/lib/aix-device.c
index f7d8e78..9355395 100644
--- a/lib/aix-device.c
+++ b/lib/aix-device.c
@@ -206,7 +206,7 @@ aix_scan(struct pci_access *a)
bus_number = pci_buses[i].bus_number;
if (!busmap[bus_number])
{
- pci_generic_scan_bus(a, busmap, bus_number);
+ pci_generic_scan_bus(a, busmap, 0, bus_number);
}
}
}
diff --git a/lib/configure b/lib/configure
index f5c2c0d..978b21c 100755
--- a/lib/configure
+++ b/lib/configure
@@ -68,12 +68,14 @@ LSPCIDIR=SBINDIR
case $sys in
linux*)
- echo_n " sysfs proc"
+ echo_n " sysfs proc mem-ports"
echo >>$c '#define PCI_HAVE_PM_LINUX_SYSFS'
echo >>$c '#define PCI_HAVE_PM_LINUX_PROC'
+ echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
echo >>$c '#define PCI_HAVE_LINUX_BYTEORDER_H'
echo >>$c '#define PCI_PATH_PROC_BUS_PCI "/proc/bus/pci"'
echo >>$c '#define PCI_PATH_SYS_BUS_PCI "/sys/bus/pci"'
+ echo >>$c '#define PCI_PATH_DEVMEM_DEVICE "/dev/mem"'
case $cpu in
i?86|x86_64) echo_n " i386-ports"
echo >>$c '#define PCI_HAVE_PM_INTEL_CONF'
@@ -97,7 +99,9 @@ case $sys in
freebsd*|kfreebsd*)
echo_n " fbsd-device"
echo >>$c '#define PCI_HAVE_PM_FBSD_DEVICE'
+ echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
echo >>$c '#define PCI_PATH_FBSD_DEVICE "/dev/pci"'
+ echo >>$c '#define PCI_PATH_DEVMEM_DEVICE "/dev/mem"'
if [ "$sys" != "kfreebsd" ] ; then
LIBRESOLV=
fi
@@ -105,13 +109,17 @@ case $sys in
openbsd)
echo_n " obsd-device"
echo >>$c '#define PCI_HAVE_PM_OBSD_DEVICE'
+ echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
echo >>$c '#define PCI_PATH_OBSD_DEVICE "/dev/pci"'
+ echo >>$c '#define PCI_PATH_DEVMEM_DEVICE "/dev/mem"'
LIBRESOLV=
;;
darwin*)
echo_n " darwin"
echo >>$c '#define PCI_HAVE_PM_DARWIN_DEVICE'
+ echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
+ echo >>$c '#define PCI_PATH_DEVMEM_DEVICE "/dev/mem"'
echo >>$m 'WITH_LIBS+=-lresolv -framework CoreFoundation -framework IOKit'
echo >>$c '#define PCI_HAVE_64BIT_ADDRESS'
LIBRESOLV=
@@ -121,6 +129,8 @@ case $sys in
aix)
echo_n " aix-device"
echo >>$c '#define PCI_HAVE_PM_AIX_DEVICE'
+ echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
+ echo >>$c '#define PCI_PATH_DEVMEM_DEVICE "/dev/mem"'
echo >>$m 'CFLAGS=-g'
echo >>$m 'INSTALL=installbsd'
echo >>$m 'DIRINSTALL=mkdir -p'
@@ -128,7 +138,9 @@ case $sys in
netbsd)
echo_n " nbsd-libpci"
echo >>$c '#define PCI_HAVE_PM_NBSD_LIBPCI'
+ echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
echo >>$c '#define PCI_PATH_NBSD_DEVICE "/dev/pci0"'
+ echo >>$c '#define PCI_PATH_DEVMEM_DEVICE "/dev/mem"'
echo >>$c '#define PCI_HAVE_64BIT_ADDRESS'
echo >>$m 'LIBNAME=libpciutils'
echo >>$m 'WITH_LIBS+=-lpci'
@@ -138,6 +150,8 @@ case $sys in
echo_n " hurd i386-ports"
echo >>$c '#define PCI_HAVE_PM_HURD_CONF'
echo >>$c '#define PCI_HAVE_PM_INTEL_CONF'
+ echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
+ echo >>$c '#define PCI_PATH_DEVMEM_DEVICE "/dev/mem"'
;;
djgpp)
echo_n " i386-ports"
@@ -174,6 +188,8 @@ case $sys in
echo >>$c '#define PCI_HAVE_PM_INTEL_CONF'
;;
esac
+ echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
+ echo >>$c '#define PCI_PATH_DEVMEM_DEVICE "/dev/misc/mem"'
echo >>$c '#define PCI_HAVE_STDINT_H'
;;
sylixos)
diff --git a/lib/generic.c b/lib/generic.c
index d178a44..6211c90 100644
--- a/lib/generic.c
+++ b/lib/generic.c
@@ -11,7 +11,7 @@
#include "internal.h"
void
-pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
+pci_generic_scan_bus(struct pci_access *a, byte *busmap, int domain, int bus)
{
int dev, multi, ht;
struct pci_dev *t;
@@ -24,6 +24,7 @@ pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
}
busmap[bus] = 1;
t = pci_alloc_dev(a);
+ t->domain = domain;
t->bus = bus;
for (dev=0; dev<32; dev++)
{
@@ -41,6 +42,7 @@ pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
multi = ht & 0x80;
ht &= 0x7f;
d = pci_alloc_dev(a);
+ d->domain = t->domain;
d->bus = t->bus;
d->dev = t->dev;
d->func = t->func;
@@ -55,7 +57,7 @@ pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
break;
case PCI_HEADER_TYPE_BRIDGE:
case PCI_HEADER_TYPE_CARDBUS:
- pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
+ pci_generic_scan_bus(a, busmap, domain, pci_read_byte(t, PCI_SECONDARY_BUS));
break;
default:
a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht);
@@ -66,12 +68,18 @@ pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
}
void
-pci_generic_scan(struct pci_access *a)
+pci_generic_scan_domain(struct pci_access *a, int domain)
{
byte busmap[256];
memset(busmap, 0, sizeof(busmap));
- pci_generic_scan_bus(a, busmap, 0);
+ pci_generic_scan_bus(a, busmap, domain, 0);
+}
+
+void
+pci_generic_scan(struct pci_access *a)
+{
+ pci_generic_scan_domain(a, 0);
}
static int
diff --git a/lib/init.c b/lib/init.c
index de7d6f2..c81d90c 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -86,6 +86,11 @@ static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
#else
NULL,
#endif
+#ifdef PCI_HAVE_PM_MMIO_CONF
+ &pm_mmio_conf1,
+#else
+ NULL,
+#endif
};
// If PCI_ACCESS_AUTO is selected, we probe the access methods in this order
@@ -105,6 +110,7 @@ static int probe_sequence[] = {
// Low-level methods poking the hardware directly
PCI_ACCESS_I386_TYPE1,
PCI_ACCESS_I386_TYPE2,
+ PCI_ACCESS_MMIO_TYPE1,
-1,
};
diff --git a/lib/internal.h b/lib/internal.h
index 11cf5a6..6bfcde7 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -67,7 +67,8 @@ struct pci_methods {
};
/* generic.c */
-void pci_generic_scan_bus(struct pci_access *, byte *busmap, int bus);
+void pci_generic_scan_bus(struct pci_access *, byte *busmap, int domain, int bus);
+void pci_generic_scan_domain(struct pci_access *, int domain);
void pci_generic_scan(struct pci_access *);
void pci_generic_fill_info(struct pci_dev *, unsigned int flags);
int pci_generic_block_read(struct pci_dev *, int pos, byte *buf, int len);
@@ -133,4 +134,5 @@ 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_mmio_conf1,
pm_win32_cfgmgr32, pm_win32_sysdbg;
diff --git a/lib/mmio-ports.c b/lib/mmio-ports.c
new file mode 100644
index 0000000..b9e3926
--- /dev/null
+++ b/lib/mmio-ports.c
@@ -0,0 +1,387 @@
+/*
+ * The PCI Library -- Direct Configuration access via memory mapped ports
+ *
+ * Copyright (c) 2022 Pali Rohár <pali@kernel.org>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+/*
+ * Tell 32-bit platforms that we are interested in 64-bit variant of off_t type
+ * as 32-bit variant of off_t type is signed and so it cannot represent all
+ * possible 32-bit offsets. It is required because off_t type is used by mmap().
+ */
+#define _FILE_OFFSET_BITS 64
+
+#include "internal.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifndef OFF_MAX
+#define OFF_MAX (off_t)((1ULL << (sizeof(off_t) * CHAR_BIT - 1)) - 1)
+#endif
+
+struct mmio_cache
+{
+ off_t addr_page;
+ off_t data_page;
+ void *addr_map;
+ void *data_map;
+};
+
+static long pagesize;
+
+static void
+munmap_regs(struct pci_access *a)
+{
+ struct mmio_cache *cache = a->aux;
+
+ if (!cache)
+ return;
+
+ munmap(cache->addr_map, pagesize);
+ if (cache->addr_page != cache->data_page)
+ munmap(cache->data_map, pagesize);
+
+ pci_mfree(a->aux);
+ a->aux = NULL;
+}
+
+static int
+mmap_regs(struct pci_access *a, off_t addr_reg, off_t data_reg, int data_off, volatile void **addr, volatile void **data)
+{
+ struct mmio_cache *cache = a->aux;
+ off_t addr_page = addr_reg & ~(pagesize-1);
+ off_t data_page = data_reg & ~(pagesize-1);
+ void *addr_map = MAP_FAILED;
+ void *data_map = MAP_FAILED;
+
+ if (cache && cache->addr_page == addr_page)
+ addr_map = cache->addr_map;
+
+ if (cache && cache->data_page == data_page)
+ data_map = cache->data_map;
+
+ if (addr_map == MAP_FAILED)
+ addr_map = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, a->fd, addr_page);
+
+ if (addr_map == MAP_FAILED)
+ return 0;
+
+ if (data_map == MAP_FAILED)
+ {
+ if (data_page == addr_page)
+ data_map = addr_map;
+ else
+ data_map = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, a->fd, data_page);
+ }
+
+ if (data_map == MAP_FAILED)
+ {
+ if (!cache || cache->addr_map != addr_map)
+ munmap(addr_map, pagesize);
+ return 0;
+ }
+
+ if (cache && cache->addr_page != addr_page)
+ munmap(cache->addr_map, pagesize);
+
+ if (cache && cache->data_page != data_page && cache->data_page != cache->addr_page)
+ munmap(cache->data_map, pagesize);
+
+ if (!cache)
+ cache = a->aux = pci_malloc(a, sizeof(*cache));
+
+ cache->addr_page = addr_page;
+ cache->data_page = data_page;
+ cache->addr_map = addr_map;
+ cache->data_map = data_map;
+
+ *addr = (unsigned char *)addr_map + (addr_reg & (pagesize-1));
+ *data = (unsigned char *)data_map + (data_reg & (pagesize-1)) + data_off;
+ return 1;
+}
+
+static void
+writeb(unsigned char value, volatile void *addr)
+{
+ *(volatile unsigned char *)addr = value;
+}
+
+static void
+writew(unsigned short value, volatile void *addr)
+{
+ *(volatile unsigned short *)addr = value;
+}
+
+static void
+writel(unsigned long value, volatile void *addr)
+{
+ *(volatile unsigned long *)addr = value;
+}
+
+static unsigned char
+readb(volatile void *addr)
+{
+ return *(volatile unsigned char *)addr;
+}
+
+static unsigned short
+readw(volatile void *addr)
+{
+ return *(volatile unsigned short *)addr;
+}
+
+static unsigned long
+readl(volatile void *addr)
+{
+ return *(volatile unsigned long *)addr;
+}
+
+static int
+validate_addrs(const char *addrs)
+{
+ const char *sep, *next;
+ unsigned long long num;
+ char *endptr;
+
+ if (!*addrs)
+ return 0;
+
+ while (1)
+ {
+ next = strchr(addrs, ',');
+ if (!next)
+ next = addrs + strlen(addrs);
+
+ sep = strchr(addrs, '/');
+ if (!sep)
+ return 0;
+
+ if (!isxdigit(*addrs) || !isxdigit(*(sep+1)))
+ return 0;
+
+ errno = 0;
+ num = strtoull(addrs, &endptr, 16);
+ if (errno || endptr != sep || (num & 3) || num > OFF_MAX)
+ return 0;
+
+ errno = 0;
+ num = strtoull(sep+1, &endptr, 16);
+ if (errno || endptr != next || (num & 3) || num > OFF_MAX)
+ return 0;
+
+ if (!*next)
+ return 1;
+
+ addrs = next + 1;
+ }
+}
+
+static int
+get_domain_count(const char *addrs)
+{
+ int count = 1;
+ while (addrs = strchr(addrs, ','))
+ {
+ addrs++;
+ count++;
+ }
+ return count;
+}
+
+static int
+get_domain_addr(const char *addrs, int domain, off_t *addr_reg, off_t *data_reg)
+{
+ char *endptr;
+
+ while (domain-- > 0)
+ {
+ addrs = strchr(addrs, ',');
+ if (!addrs)
+ return 0;
+ addrs++;
+ }
+
+ *addr_reg = strtoull(addrs, &endptr, 16);
+ *data_reg = strtoull(endptr+1, NULL, 16);
+
+ return 1;
+}
+
+static void
+conf1_config(struct pci_access *a)
+{
+ pci_define_param(a, "devmem.path", PCI_PATH_DEVMEM_DEVICE, "Path to the /dev/mem device");
+ pci_define_param(a, "mmio-conf1.addrs", "", "Physical addresses of memory mapped Intel conf1 interface"); /* format: 0xaddr1/0xdata1,0xaddr2/0xdata2,... */
+}
+
+static int
+conf1_detect(struct pci_access *a)
+{
+ char *addrs = pci_get_param(a, "mmio-conf1.addrs");
+ char *devmem = pci_get_param(a, "devmem.path");
+
+ if (!*addrs)
+ {
+ a->debug("mmio-conf1.addrs was not specified");
+ return 0;
+ }
+
+ if (!validate_addrs(addrs))
+ {
+ a->debug("mmio-conf1.addrs has invalid address format %s", addrs);
+ return 0;
+ }
+
+ if (access(devmem, R_OK))
+ {
+ a->debug("cannot access %s", devmem);
+ return 0;
+ }
+
+ a->debug("using %s with %s", devmem, addrs);
+ return 1;
+}
+
+static void
+conf1_init(struct pci_access *a)
+{
+ char *addrs = pci_get_param(a, "mmio-conf1.addrs");
+ char *devmem = pci_get_param(a, "devmem.path");
+
+ pagesize = sysconf(_SC_PAGESIZE);
+ if (pagesize < 0)
+ a->error("Cannot get page size: %s", strerror(errno));
+
+ if (!*addrs)
+ a->error("Option mmio-conf1.addrs was not specified.");
+
+ if (!validate_addrs(addrs))
+ a->error("Option mmio-conf1.addrs has invalid address format \"%s\".", addrs);
+
+ a->fd = open(devmem, O_RDWR);
+ if (a->fd < 0)
+ a->error("Cannot open %s: %s.", devmem, strerror(errno));
+}
+
+static void
+conf1_cleanup(struct pci_access *a)
+{
+ if (a->fd < 0)
+ return;
+
+ munmap_regs(a);
+ close(a->fd);
+ a->fd = -1;
+}
+
+static void
+conf1_scan(struct pci_access *a)
+{
+ char *addrs = pci_get_param(a, "mmio-conf1.addrs");
+ int domain_count = get_domain_count(addrs);
+ int domain;
+
+ for (domain = 0; domain < domain_count; domain++)
+ pci_generic_scan_domain(a, domain);
+}
+
+static int
+conf1_read(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ char *addrs = pci_get_param(d->access, "mmio-conf1.addrs");
+ volatile void *addr, *data;
+ off_t addr_reg, data_reg;
+
+ if (pos >= 256)
+ return 0;
+
+ if (len != 1 && len != 2 && len != 4)
+ return pci_generic_block_read(d, pos, buf, len);
+
+ if (!get_domain_addr(addrs, d->domain, &addr_reg, &data_reg))
+ return 0;
+
+ if (!mmap_regs(d->access, addr_reg, data_reg, pos&3, &addr, &data))
+ return 0;
+
+ writel(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos & 0xfc), addr);
+
+ switch (len)
+ {
+ case 1:
+ buf[0] = readb(data);
+ break;
+ case 2:
+ ((u16 *) buf)[0] = readw(data);
+ break;
+ case 4:
+ ((u32 *) buf)[0] = readl(data);
+ break;
+ }
+
+ return 1;
+}
+
+static int
+conf1_write(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ char *addrs = pci_get_param(d->access, "mmio-conf1.addrs");
+ volatile void *addr, *data;
+ off_t addr_reg, data_reg;
+
+ if (pos >= 256)
+ return 0;
+
+ if (len != 1 && len != 2 && len != 4)
+ return pci_generic_block_write(d, pos, buf, len);
+
+ if (!get_domain_addr(addrs, d->domain, &addr_reg, &data_reg))
+ return 0;
+
+ if (!mmap_regs(d->access, addr_reg, data_reg, pos&3, &addr, &data))
+ return 0;
+
+ writel(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos & 0xfc), addr);
+
+ switch (len)
+ {
+ case 1:
+ writeb(buf[0], data);
+ break;
+ case 2:
+ writew(((u16 *) buf)[0], data);
+ break;
+ case 4:
+ writel(((u32 *) buf)[0], data);
+ break;
+ }
+
+ return 1;
+}
+
+struct pci_methods pm_mmio_conf1 = {
+ "mmio-conf1",
+ "Raw memory mapped I/O port access using Intel conf1 interface",
+ conf1_config,
+ conf1_detect,
+ conf1_init,
+ conf1_cleanup,
+ conf1_scan,
+ pci_generic_fill_info,
+ conf1_read,
+ conf1_write,
+ NULL, /* read_vpd */
+ NULL, /* init_dev */
+ NULL /* cleanup_dev */
+};
diff --git a/lib/pci.h b/lib/pci.h
index 41a162b..f6197c4 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -45,6 +45,7 @@ enum pci_access_type {
PCI_ACCESS_HURD, /* GNU/Hurd */
PCI_ACCESS_WIN32_CFGMGR32, /* Win32 cfgmgr32.dll */
PCI_ACCESS_WIN32_SYSDBG, /* Win32 NT SysDbg */
+ PCI_ACCESS_MMIO_TYPE1, /* MMIO ports, type 1 */
PCI_ACCESS_MAX
};
@@ -84,6 +85,7 @@ struct pci_access {
int fd_pos; /* proc/sys: current position */
int fd_vpd; /* sys: fd for VPD */
struct pci_dev *cached_dev; /* proc/sys: device the fds are for */
+ void *aux; /* Auxiliary data for use by the back-end */
};
/* Initialize PCI access */
diff --git a/lib/sylixos-device.c b/lib/sylixos-device.c
index a23438e..07195d5 100644
--- a/lib/sylixos-device.c
+++ b/lib/sylixos-device.c
@@ -25,7 +25,7 @@ sylixos_scan(struct pci_access *a)
for (bus = 0; bus < PCI_MAX_BUS; bus++)
if (!busmap[bus])
- pci_generic_scan_bus(a, busmap, bus);
+ pci_generic_scan_bus(a, busmap, 0, bus);
}
static void
diff --git a/pcilib.man b/pcilib.man
index 115f1f3..ae6af9f 100644
--- a/pcilib.man
+++ b/pcilib.man
@@ -40,6 +40,13 @@ on Linux, Solaris/x86, GNU Hurd, Windows, BeOS and Haiku. Requires root privileg
is able to address only the first 16 devices on any bus and it seems to be very
unreliable in many cases.
.TP
+.B mmio-conf1
+Direct hardware access via Intel configuration mechanism 1 via memory-mapped I/O.
+Mostly used on non-i386 platforms. Requires root privileges. Warning: This method
+needs to be properly configured via the
+.B mmio-conf1.addrs
+parameter.
+.TP
.B fbsd-device
The
.B /dev/pci
@@ -111,6 +118,15 @@ Path to the procfs bus tree.
.TP
.B sysfs.path
Path to the sysfs device tree.
+.TP
+.B devmem.path
+Path to the /dev/mem device.
+.TP
+.B mmio-conf1.addrs
+Physical addresses of memory-mapped I/O ports for Intel configuration mechanism 1.
+CF8 (address) and CFC (data) I/O port addresses are separated by slash and
+multiple addresses for different PCI domains are separated by commas.
+Format: 0xaddr1/0xdata1,0xaddr2/0xdata2,...
.SS Parameters for resolving of ID's via DNS
.TP