[Midnightbsd-cvs] src [10368] trunk/usr.sbin/pciconf/pciconf.c: sync with freebsd
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sun Jun 3 19:11:43 EDT 2018
Revision: 10368
http://svnweb.midnightbsd.org/src/?rev=10368
Author: laffer1
Date: 2018-06-03 19:11:42 -0400 (Sun, 03 Jun 2018)
Log Message:
-----------
sync with freebsd
Modified Paths:
--------------
trunk/usr.sbin/pciconf/cap.c
trunk/usr.sbin/pciconf/err.c
trunk/usr.sbin/pciconf/pathnames.h
trunk/usr.sbin/pciconf/pciconf.8
trunk/usr.sbin/pciconf/pciconf.c
Property Changed:
----------------
trunk/usr.sbin/pciconf/pciconf.8
Modified: trunk/usr.sbin/pciconf/cap.c
===================================================================
--- trunk/usr.sbin/pciconf/cap.c 2018-06-03 23:10:50 UTC (rev 10367)
+++ trunk/usr.sbin/pciconf/cap.c 2018-06-03 23:11:42 UTC (rev 10368)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2007 Yahoo!, Inc.
* All rights reserved.
@@ -30,7 +31,7 @@
#ifndef lint
static const char rcsid[] =
- "$MidnightBSD$";
+ "$FreeBSD: stable/10/usr.sbin/pciconf/cap.c 290804 2015-11-13 22:33:51Z jhb $";
#endif /* not lint */
#include <sys/types.h>
@@ -391,11 +392,27 @@
}
}
+static const char *
+aspm_string(uint8_t aspm)
+{
+
+ switch (aspm) {
+ case 1:
+ return ("L0s");
+ case 2:
+ return ("L1");
+ case 3:
+ return ("L0s/L1");
+ default:
+ return ("disabled");
+ }
+}
+
static void
cap_express(int fd, struct pci_conf *p, uint8_t ptr)
{
- uint32_t val;
- uint16_t flags;
+ uint32_t cap, cap2;
+ uint16_t ctl, flags, sta;
flags = read_config(fd, &p->pc_sel, ptr + PCIER_FLAGS, 2);
printf("PCI-Express %d ", flags & PCIEM_FLAGS_VERSION);
@@ -435,50 +452,66 @@
printf(" slot");
if (flags & PCIEM_FLAGS_IRQ)
printf(" IRQ %d", (flags & PCIEM_FLAGS_IRQ) >> 9);
- val = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP, 4);
- flags = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CTL, 2);
+ cap = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP, 4);
+ cap2 = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP2, 4);
+ ctl = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CTL, 2);
printf(" max data %d(%d)",
- MAX_PAYLOAD((flags & PCIEM_CTL_MAX_PAYLOAD) >> 5),
- MAX_PAYLOAD(val & PCIEM_CAP_MAX_PAYLOAD));
- if (val & PCIEM_CAP_FLR)
+ MAX_PAYLOAD((ctl & PCIEM_CTL_MAX_PAYLOAD) >> 5),
+ MAX_PAYLOAD(cap & PCIEM_CAP_MAX_PAYLOAD));
+ if ((cap & PCIEM_CAP_FLR) != 0)
printf(" FLR");
- val = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_CAP, 4);
- flags = read_config(fd, &p->pc_sel, ptr+ PCIER_LINK_STA, 2);
- printf(" link x%d(x%d)", (flags & PCIEM_LINK_STA_WIDTH) >> 4,
- (val & PCIEM_LINK_CAP_MAX_WIDTH) >> 4);
- /*
- * Only print link speed info if the link's max width is
- * greater than 0.
- */
- if ((val & PCIEM_LINK_CAP_MAX_WIDTH) != 0) {
- printf("\n speed");
- printf(" %s(%s)", (flags & PCIEM_LINK_STA_WIDTH) == 0 ?
- "0.0" : link_speed_string(flags & PCIEM_LINK_STA_SPEED),
- link_speed_string(val & PCIEM_LINK_CAP_MAX_SPEED));
+ if (ctl & PCIEM_CTL_RELAXED_ORD_ENABLE)
+ printf(" RO");
+ if (ctl & PCIEM_CTL_NOSNOOP_ENABLE)
+ printf(" NS");
+ cap = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_CAP, 4);
+ sta = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_STA, 2);
+ printf(" link x%d(x%d)", (sta & PCIEM_LINK_STA_WIDTH) >> 4,
+ (cap & PCIEM_LINK_CAP_MAX_WIDTH) >> 4);
+ if ((cap & (PCIEM_LINK_CAP_MAX_WIDTH | PCIEM_LINK_CAP_ASPM)) != 0)
+ printf("\n ");
+ if ((cap & PCIEM_LINK_CAP_MAX_WIDTH) != 0) {
+ printf(" speed %s(%s)", (sta & PCIEM_LINK_STA_WIDTH) == 0 ?
+ "0.0" : link_speed_string(sta & PCIEM_LINK_STA_SPEED),
+ link_speed_string(cap & PCIEM_LINK_CAP_MAX_SPEED));
}
+ if ((cap & PCIEM_LINK_CAP_ASPM) != 0) {
+ ctl = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_CTL, 2);
+ printf(" ASPM %s(%s)", aspm_string(ctl & PCIEM_LINK_CTL_ASPMC),
+ aspm_string((cap & PCIEM_LINK_CAP_ASPM) >> 10));
+ }
+ if ((cap2 & PCIEM_CAP2_ARI) != 0) {
+ ctl = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CTL2, 4);
+ printf(" ARI %s",
+ (ctl & PCIEM_CTL2_ARI) ? "enabled" : "disabled");
+ }
}
static void
cap_msix(int fd, struct pci_conf *p, uint8_t ptr)
{
- uint32_t val;
+ uint32_t pba_offset, table_offset, val;
+ int msgnum, pba_bar, table_bar;
uint16_t ctrl;
- int msgnum, table_bar, pba_bar;
ctrl = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_CTRL, 2);
msgnum = (ctrl & PCIM_MSIXCTRL_TABLE_SIZE) + 1;
+
val = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_TABLE, 4);
table_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
+ table_offset = val & ~PCIM_MSIX_BIR_MASK;
+
val = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_PBA, 4);
- pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
- printf("MSI-X supports %d message%s ", msgnum,
- (msgnum == 1) ? "" : "s");
- if (table_bar == pba_bar)
- printf("in map 0x%x", table_bar);
- else
- printf("in maps 0x%x and 0x%x", table_bar, pba_bar);
- if (ctrl & PCIM_MSIXCTRL_MSIX_ENABLE)
- printf(" enabled");
+ pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
+ pba_offset = val & ~PCIM_MSIX_BIR_MASK;
+
+ printf("MSI-X supports %d message%s%s\n", msgnum,
+ (msgnum == 1) ? "" : "s",
+ (ctrl & PCIM_MSIXCTRL_MSIX_ENABLE) ? ", enabled" : "");
+
+ printf(" ");
+ printf("Table in map 0x%x[0x%x], PBA in map 0x%x[0x%x]",
+ table_bar, table_offset, pba_bar, pba_offset);
}
static void
@@ -698,7 +731,7 @@
if (ecap == 0xffffffff || ecap == 0)
return;
for (;;) {
- printf("ecap %04x[%03x] = ", PCI_EXTCAP_ID(ecap), ptr);
+ printf(" ecap %04x[%03x] = ", PCI_EXTCAP_ID(ecap), ptr);
switch (PCI_EXTCAP_ID(ecap)) {
case PCIZ_AER:
ecap_aer(fd, p, ptr, PCI_EXTCAP_VER(ecap));
Modified: trunk/usr.sbin/pciconf/err.c
===================================================================
--- trunk/usr.sbin/pciconf/err.c 2018-06-03 23:10:50 UTC (rev 10367)
+++ trunk/usr.sbin/pciconf/err.c 2018-06-03 23:11:42 UTC (rev 10368)
@@ -1,5 +1,6 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2012 Advanced Computing Technologies LLC
+ * Copyright (c) 2012 Hudson River Trading LLC
* Written by: John H. Baldwin <jhb at FreeBSD.org>
* All rights reserved.
*
@@ -27,7 +28,7 @@
#ifndef lint
static const char rcsid[] =
- "$MidnightBSD$";
+ "$FreeBSD: stable/10/usr.sbin/pciconf/err.c 283927 2015-06-02 19:20:39Z jhb $";
#endif /* not lint */
#include <sys/param.h>
Modified: trunk/usr.sbin/pciconf/pathnames.h
===================================================================
--- trunk/usr.sbin/pciconf/pathnames.h 2018-06-03 23:10:50 UTC (rev 10367)
+++ trunk/usr.sbin/pciconf/pathnames.h 2018-06-03 23:11:42 UTC (rev 10368)
@@ -1,3 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/usr.sbin/pciconf/pathnames.h 287746 2015-09-13 07:15:45Z bapt $ */
#define _PATH_DEVPCI "/dev/pci"
#define _PATH_PCIVDB "/usr/share/misc/pci_vendors"
+#define _PATH_LPCIVDB "/usr/local/share/pciids/pci.ids"
Modified: trunk/usr.sbin/pciconf/pciconf.8
===================================================================
--- trunk/usr.sbin/pciconf/pciconf.8 2018-06-03 23:10:50 UTC (rev 10367)
+++ trunk/usr.sbin/pciconf/pciconf.8 2018-06-03 23:11:42 UTC (rev 10368)
@@ -1,3 +1,4 @@
+.\" $MidnightBSD$
.\" Copyright (c) 1997
.\" Stefan Esser <se at FreeBSD.org>. All rights reserved.
.\"
@@ -23,9 +24,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $MidnightBSD$
+.\" $FreeBSD: stable/10/usr.sbin/pciconf/pciconf.8 294289 2016-01-18 19:52:20Z jhb $
.\"
-.Dd June 1, 2012
+.Dd November 23, 2015
.Dt PCICONF 8
.Os
.Sh NAME
@@ -33,13 +34,13 @@
.Nd diagnostic utility for the PCI bus
.Sh SYNOPSIS
.Nm
-.Fl l Op Fl bcev
+.Fl l Oo Fl BbceVv Oc Op Ar device
.Nm
-.Fl a Ar selector
+.Fl a Ar device
.Nm
-.Fl r Oo Fl b | h Oc Ar selector addr Ns Op : Ns Ar addr2
+.Fl r Oo Fl b | h Oc Ar device addr Ns Op : Ns Ar addr2
.Nm
-.Fl w Oo Fl b | h Oc Ar selector addr value
+.Fl w Oo Fl b | h Oc Ar device addr value
.Sh DESCRIPTION
The
.Nm
@@ -54,7 +55,9 @@
.Pp
With the
.Fl l
-option, it lists all devices found by the boot probe in the following format:
+option,
+.Nm
+lists PCI devices in the following format:
.Bd -literal
foo0 at pci0:0:4:0: class=0x010000 card=0x00000000 chip=0x000f1000 rev=0x01 \
hdr=0x00
@@ -65,16 +68,14 @@
.Ed
.Pp
The first column gives the
-device name, unit number, and
-.Ar selector .
-If there is no device configured in the kernel for the
+driver name, unit number, and selector .
+If there is no driver attached to the
.Tn PCI
-device in question, the device name will be
+device in question, the driver name will be
.Dq none .
-Unit numbers for unconfigured devices start at zero and are incremented for
-each unconfigured device that is encountered.
-The
-.Ar selector
+Unit numbers for detached devices start at zero and are incremented for
+each detached device that is encountered.
+The selector
is in a form which may directly be used for the other forms of the command.
The second column is the class code, with the class byte printed as two
hex digits, followed by the sub-class and the interface bytes.
@@ -112,6 +113,42 @@
one chip.
.Pp
If the
+.Fl B
+option is supplied,
+.Nm
+will list additional information for
+.Tn PCI
+to
+.Tn PCI
+and
+.Tn PCI
+to
+.Tn CardBus
+bridges,
+specifically the resource ranges decoded by the bridge for use by devices
+behind the bridge.
+Each bridge lists a range of bus numbers handled by the bridge and its
+downstream devices.
+Memory and I/O port decoding windows are enumerated via a line in the
+following format:
+.Bd -literal
+ window[1c] = type I/O Port, range 16, addr 0x5000-0x8fff, enabled
+.Ed
+.Pp
+The first value after the
+.Dq Li window
+prefix in the square brackets is the offset of the decoding window in
+config space in hexadecimal.
+The type of a window is one of
+.Dq Memory ,
+.Dq Prefetchable Memory ,
+or
+.Dq I/O Port .
+The range indicates the binary log of the maximum address the window decodes.
+The address field indicates the start and end addresses of the decoded range.
+Finally, the last flag indicates if the window is enabled or disabled.
+.Pp
+If the
.Fl b
option is supplied,
.Nm
@@ -132,7 +169,7 @@
.Dq Prefetchable Memory ,
or
.Dq I/O Port .
-The range indicates the maximum address the BAR decodes.
+The range indicates the binary log of the maximum address the BAR decodes.
The base and size indicate the start and length of the BAR's address window,
respectively.
Finally, the last flag indicates if the BAR is enabled or disabled.
@@ -182,18 +219,58 @@
will attempt to load the vendor/device information database, and print
vendor, device, class and subclass identification strings for each device.
.Pp
+If the
+.Fl V
+option is supplied,
+.Nm
+will list any vital product data
+.Pq VPD
+provided by each device.
+Each VPD keyword is enumerated via a line in the following format:
+.Bd -literal
+ VPD ro PN = '110114640C0 '
+.Ed
+.Pp
+The first string after the
+.Dq Li VPD
+prefix indicates if the keyword is read-only
+.Dq ro
+or read-write
+.Dq rw .
+The second string provides the keyword name.
+The text after the the equals sign lists the value of the keyword which is
+usually an ASCII string.
+.Pp
+If the optional
+.Ar device
+argument is given with the
+.Fl l
+flag,
+.Nm
+will only list details about a single device instead of all devices.
+.Pp
All invocations of
.Nm
except for
.Fl l
require a
-.Ar selector
-of the form
+.Ar device .
+The device can be identified either by a device name if the device is
+attached to a driver or by a selector.
+Selectors identify a PCI device by its address in PCI config space and
+can take one of the following forms:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
.Li pci Ns Va domain Ns \&: Ns Va bus Ns \&: Ns Va device Ns \&: \
-Ns Va function Ns ,
-.Li pci Ns Va bus Ns \&: Ns Va device Ns \&: Ns Va function Ns , or
-.Li pci Ns Va bus Ns \&: Ns Va device Ns .
-In case of an abridged form, omitted selector components are assumed to be 0.
+Ns Va function Ns
+.It
+.Li pci Ns Va bus Ns \&: Ns Va device Ns \&: Ns Va function Ns
+.It
+.Li pci Ns Va bus Ns \&: Ns Va device Ns
+.El
+.Pp
+In the case of an abridged form, omitted selector components are assumed to be 0.
An optional leading device name followed by @ and an optional final colon
will be ignored; this is so that the first column in the output of
.Nm
@@ -241,7 +318,9 @@
The default is to read or
write a longword (four bytes).
.Sh ENVIRONMENT
-The PCI vendor/device information database is normally read from
+PCI vendor and device information is read from
+.Pa /usr/local/share/pciids/pci.ids .
+If that file is not present, it is read from
.Pa /usr/share/misc/pci_vendors .
This path can be overridden by setting the environment variable
.Ev PCICONF_VENDOR_DATABASE .
Property changes on: trunk/usr.sbin/pciconf/pciconf.8
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/usr.sbin/pciconf/pciconf.c
===================================================================
--- trunk/usr.sbin/pciconf/pciconf.c 2018-06-03 23:10:50 UTC (rev 10367)
+++ trunk/usr.sbin/pciconf/pciconf.c 2018-06-03 23:11:42 UTC (rev 10368)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* Copyright 1996 Massachusetts Institute of Technology
*
@@ -29,15 +30,17 @@
#ifndef lint
static const char rcsid[] =
- "$MidnightBSD$";
+ "$FreeBSD: stable/10/usr.sbin/pciconf/pciconf.c 308063 2016-10-28 19:46:08Z mav $";
#endif /* not lint */
#include <sys/types.h>
#include <sys/fcntl.h>
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <inttypes.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -67,9 +70,13 @@
TAILQ_HEAD(,pci_vendor_info) pci_vendors;
+static struct pcisel getsel(const char *str);
+static void list_bridge(int fd, struct pci_conf *p);
static void list_bars(int fd, struct pci_conf *p);
-static void list_devs(int verbose, int bars, int caps, int errors);
+static void list_devs(const char *name, int verbose, int bars, int bridge,
+ int caps, int errors, int vpd);
static void list_verbose(struct pci_conf *p);
+static void list_vpd(int fd, struct pci_conf *p);
static const char *guess_class(struct pci_conf *p);
static const char *guess_subclass(struct pci_conf *p);
static int load_vendors(void);
@@ -83,10 +90,10 @@
usage(void)
{
fprintf(stderr, "%s\n%s\n%s\n%s\n",
- "usage: pciconf -l [-bcev]",
- " pciconf -a selector",
- " pciconf -r [-b | -h] selector addr[:addr2]",
- " pciconf -w [-b | -h] selector addr value");
+ "usage: pciconf -l [-BbcevV] [device]",
+ " pciconf -a device",
+ " pciconf -r [-b | -h] device addr[:addr2]",
+ " pciconf -w [-b | -h] device addr value");
exit (1);
}
@@ -95,18 +102,22 @@
{
int c;
int listmode, readmode, writemode, attachedmode;
- int bars, caps, errors, verbose;
+ int bars, bridge, caps, errors, verbose, vpd;
int byte, isshort;
listmode = readmode = writemode = attachedmode = 0;
- bars = caps = errors = verbose = byte = isshort = 0;
+ bars = bridge = caps = errors = verbose = vpd = byte = isshort = 0;
- while ((c = getopt(argc, argv, "abcehlrwv")) != -1) {
+ while ((c = getopt(argc, argv, "aBbcehlrwVv")) != -1) {
switch(c) {
case 'a':
attachedmode = 1;
break;
+ case 'B':
+ bridge = 1;
+ break;
+
case 'b':
bars = 1;
byte = 1;
@@ -140,12 +151,16 @@
verbose = 1;
break;
+ case 'V':
+ vpd = 1;
+ break;
+
default:
usage();
}
}
- if ((listmode && optind != argc)
+ if ((listmode && optind >= argc + 1)
|| (writemode && optind + 3 != argc)
|| (readmode && optind + 2 != argc)
|| (attachedmode && optind + 1 != argc))
@@ -152,7 +167,8 @@
usage();
if (listmode) {
- list_devs(verbose, bars, caps, errors);
+ list_devs(optind + 1 == argc ? argv[optind] : NULL, verbose,
+ bars, bridge, caps, errors, vpd);
} else if (attachedmode) {
chkattached(argv[optind]);
} else if (readmode) {
@@ -169,17 +185,20 @@
}
static void
-list_devs(int verbose, int bars, int caps, int errors)
+list_devs(const char *name, int verbose, int bars, int bridge, int caps,
+ int errors, int vpd)
{
int fd;
struct pci_conf_io pc;
struct pci_conf conf[255], *p;
+ struct pci_match_conf patterns[1];
int none_count = 0;
if (verbose)
load_vendors();
- fd = open(_PATH_DEVPCI, (caps || errors) ? O_RDWR : O_RDONLY, 0);
+ fd = open(_PATH_DEVPCI, (bridge || caps || errors) ? O_RDWR : O_RDONLY,
+ 0);
if (fd < 0)
err(1, "%s", _PATH_DEVPCI);
@@ -186,6 +205,16 @@
bzero(&pc, sizeof(struct pci_conf_io));
pc.match_buf_len = sizeof(conf);
pc.matches = conf;
+ if (name != NULL) {
+ bzero(&patterns, sizeof(patterns));
+ patterns[0].pc_sel = getsel(name);
+ patterns[0].flags = PCI_GETCONF_MATCH_DOMAIN |
+ PCI_GETCONF_MATCH_BUS | PCI_GETCONF_MATCH_DEV |
+ PCI_GETCONF_MATCH_FUNC;
+ pc.num_patterns = 1;
+ pc.pat_buf_len = sizeof(patterns);
+ pc.patterns = patterns;
+ }
do {
if (ioctl(fd, PCIOCGETCONF, &pc) == -1)
@@ -194,10 +223,10 @@
/*
* 255 entries should be more than enough for most people,
* but if someone has more devices, and then changes things
- * around between ioctls, we'll do the cheezy thing and
+ * around between ioctls, we'll do the cheesy thing and
* just bail. The alternative would be to go back to the
* beginning of the list, and print things twice, which may
- * not be desireable.
+ * not be desirable.
*/
if (pc.status == PCI_GETCONF_LIST_CHANGED) {
warnx("PCI device list changed, please try again");
@@ -227,10 +256,14 @@
list_verbose(p);
if (bars)
list_bars(fd, p);
+ if (bridge)
+ list_bridge(fd, p);
if (caps)
list_caps(fd, p);
if (errors)
list_errors(fd, p);
+ if (vpd)
+ list_vpd(fd, p);
}
} while (pc.status == PCI_GETCONF_MORE_DEVS);
@@ -238,6 +271,189 @@
}
static void
+print_bus_range(int fd, struct pci_conf *p, int secreg, int subreg)
+{
+ uint8_t secbus, subbus;
+
+ secbus = read_config(fd, &p->pc_sel, secreg, 1);
+ subbus = read_config(fd, &p->pc_sel, subreg, 1);
+ printf(" bus range = %u-%u\n", secbus, subbus);
+}
+
+static void
+print_window(int reg, const char *type, int range, uint64_t base,
+ uint64_t limit)
+{
+
+ printf(" window[%02x] = type %s, range %2d, addr %#jx-%#jx, %s\n",
+ reg, type, range, (uintmax_t)base, (uintmax_t)limit,
+ base < limit ? "enabled" : "disabled");
+}
+
+static void
+print_special_decode(bool isa, bool vga, bool subtractive)
+{
+ bool comma;
+
+ if (isa || vga || subtractive) {
+ comma = false;
+ printf(" decode = ");
+ if (isa) {
+ printf("ISA");
+ comma = true;
+ }
+ if (vga) {
+ printf("%sVGA", comma ? ", " : "");
+ comma = true;
+ }
+ if (subtractive)
+ printf("%ssubtractive", comma ? ", " : "");
+ printf("\n");
+ }
+}
+
+static void
+print_bridge_windows(int fd, struct pci_conf *p)
+{
+ uint64_t base, limit;
+ uint32_t val;
+ uint16_t bctl;
+ bool subtractive;
+ int range;
+
+ /*
+ * XXX: This assumes that a window with a base and limit of 0
+ * is not implemented. In theory a window might be programmed
+ * at the smallest size with a base of 0, but those do not seem
+ * common in practice.
+ */
+ val = read_config(fd, &p->pc_sel, PCIR_IOBASEL_1, 1);
+ if (val != 0 || read_config(fd, &p->pc_sel, PCIR_IOLIMITL_1, 1) != 0) {
+ if ((val & PCIM_BRIO_MASK) == PCIM_BRIO_32) {
+ base = PCI_PPBIOBASE(
+ read_config(fd, &p->pc_sel, PCIR_IOBASEH_1, 2),
+ val);
+ limit = PCI_PPBIOLIMIT(
+ read_config(fd, &p->pc_sel, PCIR_IOLIMITH_1, 2),
+ read_config(fd, &p->pc_sel, PCIR_IOLIMITL_1, 1));
+ range = 32;
+ } else {
+ base = PCI_PPBIOBASE(0, val);
+ limit = PCI_PPBIOLIMIT(0,
+ read_config(fd, &p->pc_sel, PCIR_IOLIMITL_1, 1));
+ range = 16;
+ }
+ print_window(PCIR_IOBASEL_1, "I/O Port", range, base, limit);
+ }
+
+ base = PCI_PPBMEMBASE(0,
+ read_config(fd, &p->pc_sel, PCIR_MEMBASE_1, 2));
+ limit = PCI_PPBMEMLIMIT(0,
+ read_config(fd, &p->pc_sel, PCIR_MEMLIMIT_1, 2));
+ print_window(PCIR_MEMBASE_1, "Memory", 32, base, limit);
+
+ val = read_config(fd, &p->pc_sel, PCIR_PMBASEL_1, 2);
+ if (val != 0 || read_config(fd, &p->pc_sel, PCIR_PMLIMITL_1, 2) != 0) {
+ if ((val & PCIM_BRPM_MASK) == PCIM_BRPM_64) {
+ base = PCI_PPBMEMBASE(
+ read_config(fd, &p->pc_sel, PCIR_PMBASEH_1, 4),
+ val);
+ limit = PCI_PPBMEMLIMIT(
+ read_config(fd, &p->pc_sel, PCIR_PMLIMITH_1, 4),
+ read_config(fd, &p->pc_sel, PCIR_PMLIMITL_1, 2));
+ range = 64;
+ } else {
+ base = PCI_PPBMEMBASE(0, val);
+ limit = PCI_PPBMEMLIMIT(0,
+ read_config(fd, &p->pc_sel, PCIR_PMLIMITL_1, 2));
+ range = 32;
+ }
+ print_window(PCIR_PMBASEL_1, "Prefetchable Memory", range, base,
+ limit);
+ }
+
+ /*
+ * XXX: This list of bridges that are subtractive but do not set
+ * progif to indicate it is copied from pci_pci.c.
+ */
+ subtractive = p->pc_progif == PCIP_BRIDGE_PCI_SUBTRACTIVE;
+ switch (p->pc_device << 16 | p->pc_vendor) {
+ case 0xa002177d: /* Cavium ThunderX */
+ case 0x124b8086: /* Intel 82380FB Mobile */
+ case 0x060513d7: /* Toshiba ???? */
+ subtractive = true;
+ }
+ if (p->pc_vendor == 0x8086 && (p->pc_device & 0xff00) == 0x2400)
+ subtractive = true;
+
+ bctl = read_config(fd, &p->pc_sel, PCIR_BRIDGECTL_1, 2);
+ print_special_decode(bctl & PCIB_BCR_ISA_ENABLE,
+ bctl & PCIB_BCR_VGA_ENABLE, subtractive);
+}
+
+static void
+print_cardbus_mem_window(int fd, struct pci_conf *p, int basereg, int limitreg,
+ bool prefetch)
+{
+
+ print_window(basereg, prefetch ? "Prefetchable Memory" : "Memory", 32,
+ PCI_CBBMEMBASE(read_config(fd, &p->pc_sel, basereg, 4)),
+ PCI_CBBMEMLIMIT(read_config(fd, &p->pc_sel, limitreg, 4)));
+}
+
+static void
+print_cardbus_io_window(int fd, struct pci_conf *p, int basereg, int limitreg)
+{
+ uint32_t base, limit;
+ uint32_t val;
+ int range;
+
+ val = read_config(fd, &p->pc_sel, basereg, 2);
+ if ((val & PCIM_CBBIO_MASK) == PCIM_CBBIO_32) {
+ base = PCI_CBBIOBASE(read_config(fd, &p->pc_sel, basereg, 4));
+ limit = PCI_CBBIOBASE(read_config(fd, &p->pc_sel, limitreg, 4));
+ range = 32;
+ } else {
+ base = PCI_CBBIOBASE(val);
+ limit = PCI_CBBIOBASE(read_config(fd, &p->pc_sel, limitreg, 2));
+ range = 16;
+ }
+ print_window(basereg, "I/O Port", range, base, limit);
+}
+
+static void
+print_cardbus_windows(int fd, struct pci_conf *p)
+{
+ uint16_t bctl;
+
+ bctl = read_config(fd, &p->pc_sel, PCIR_BRIDGECTL_2, 2);
+ print_cardbus_mem_window(fd, p, PCIR_MEMBASE0_2, PCIR_MEMLIMIT0_2,
+ bctl & CBB_BCR_PREFETCH_0_ENABLE);
+ print_cardbus_mem_window(fd, p, PCIR_MEMBASE1_2, PCIR_MEMLIMIT1_2,
+ bctl & CBB_BCR_PREFETCH_1_ENABLE);
+ print_cardbus_io_window(fd, p, PCIR_IOBASE0_2, PCIR_IOLIMIT0_2);
+ print_cardbus_io_window(fd, p, PCIR_IOBASE1_2, PCIR_IOLIMIT1_2);
+ print_special_decode(bctl & CBB_BCR_ISA_ENABLE,
+ bctl & CBB_BCR_VGA_ENABLE, false);
+}
+
+static void
+list_bridge(int fd, struct pci_conf *p)
+{
+
+ switch (p->pc_hdr & PCIM_HDRTYPE) {
+ case PCIM_HDRTYPE_BRIDGE:
+ print_bus_range(fd, p, PCIR_SECBUS_1, PCIR_SUBBUS_1);
+ print_bridge_windows(fd, p);
+ break;
+ case PCIM_HDRTYPE_CARDBUS:
+ print_bus_range(fd, p, PCIR_SECBUS_2, PCIR_SUBBUS_2);
+ print_cardbus_windows(fd, p);
+ break;
+ }
+}
+
+static void
list_bars(int fd, struct pci_conf *p)
{
struct pci_bar_io bar;
@@ -290,7 +506,7 @@
}
printf(" bar [%02x] = type %s, range %2d, base %#jx, ",
PCIR_BAR(i), type, range, (uintmax_t)base);
- printf("size %2d, %s\n", (int)bar.pbi_length,
+ printf("size %ju, %s\n", (uintmax_t)bar.pbi_length,
bar.pbi_enabled ? "enabled" : "disabled");
}
}
@@ -324,6 +540,63 @@
printf(" subclass = %s\n", dp);
}
+static void
+list_vpd(int fd, struct pci_conf *p)
+{
+ struct pci_list_vpd_io list;
+ struct pci_vpd_element *vpd, *end;
+
+ list.plvi_sel = p->pc_sel;
+ list.plvi_len = 0;
+ list.plvi_data = NULL;
+ if (ioctl(fd, PCIOCLISTVPD, &list) < 0 || list.plvi_len == 0)
+ return;
+
+ list.plvi_data = malloc(list.plvi_len);
+ if (ioctl(fd, PCIOCLISTVPD, &list) < 0) {
+ free(list.plvi_data);
+ return;
+ }
+
+ vpd = list.plvi_data;
+ end = (struct pci_vpd_element *)((char *)vpd + list.plvi_len);
+ for (; vpd < end; vpd = PVE_NEXT(vpd)) {
+ if (vpd->pve_flags == PVE_FLAG_IDENT) {
+ printf(" VPD ident = '%.*s'\n",
+ (int)vpd->pve_datalen, vpd->pve_data);
+ continue;
+ }
+
+ /* Ignore the checksum keyword. */
+ if (!(vpd->pve_flags & PVE_FLAG_RW) &&
+ memcmp(vpd->pve_keyword, "RV", 2) == 0)
+ continue;
+
+ /* Ignore remaining read-write space. */
+ if (vpd->pve_flags & PVE_FLAG_RW &&
+ memcmp(vpd->pve_keyword, "RW", 2) == 0)
+ continue;
+
+ /* Handle extended capability keyword. */
+ if (!(vpd->pve_flags & PVE_FLAG_RW) &&
+ memcmp(vpd->pve_keyword, "CP", 2) == 0) {
+ printf(" VPD ro CP = ID %02x in map 0x%x[0x%x]\n",
+ (unsigned int)vpd->pve_data[0],
+ PCIR_BAR((unsigned int)vpd->pve_data[1]),
+ (unsigned int)vpd->pve_data[3] << 8 |
+ (unsigned int)vpd->pve_data[2]);
+ continue;
+ }
+
+ /* Remaining keywords should all have ASCII values. */
+ printf(" VPD %s %c%c = '%.*s'\n",
+ vpd->pve_flags & PVE_FLAG_RW ? "rw" : "ro",
+ vpd->pve_keyword[0], vpd->pve_keyword[1],
+ (int)vpd->pve_datalen, vpd->pve_data);
+ }
+ free(list.plvi_data);
+}
+
/*
* This is a direct cut-and-paste from the table in sys/dev/pci/pci.c.
*/
@@ -386,6 +659,7 @@
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_RTC, "realtime clock"},
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_PCIHOT, "PCI hot-plug controller"},
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_SDHC, "SD host controller"},
+ {PCIC_BASEPERIPH, PCIS_BASEPERIPH_IOMMU, "IOMMU"},
{PCIC_INPUTDEV, -1, "input device"},
{PCIC_INPUTDEV, PCIS_INPUTDEV_KEYBOARD, "keyboard"},
{PCIC_INPUTDEV, PCIS_INPUTDEV_DIGITIZER,"digitizer"},
@@ -417,6 +691,9 @@
{PCIC_CRYPTO, PCIS_CRYPTO_NETCOMP, "entertainment crypto"},
{PCIC_DASP, -1, "dasp"},
{PCIC_DASP, PCIS_DASP_DPIO, "DPIO module"},
+ {PCIC_DASP, PCIS_DASP_PERFCNTRS, "performance counters"},
+ {PCIC_DASP, PCIS_DASP_COMM_SYNC, "communication synchronizer"},
+ {PCIC_DASP, PCIS_DASP_MGMT_CARD, "signal processing management"},
{0, 0, NULL}
};
@@ -461,9 +738,12 @@
*/
TAILQ_INIT(&pci_vendors);
if ((dbf = getenv("PCICONF_VENDOR_DATABASE")) == NULL)
+ dbf = _PATH_LPCIVDB;
+ if ((db = fopen(dbf, "r")) == NULL) {
dbf = _PATH_PCIVDB;
- if ((db = fopen(dbf, "r")) == NULL)
- return(1);
+ if ((db = fopen(dbf, "r")) == NULL)
+ return(1);
+ }
cv = NULL;
cd = NULL;
error = 0;
@@ -557,8 +837,62 @@
}
static struct pcisel
-getsel(const char *str)
+getdevice(const char *name)
{
+ struct pci_conf_io pc;
+ struct pci_conf conf[1];
+ struct pci_match_conf patterns[1];
+ char *cp;
+ int fd;
+
+ fd = open(_PATH_DEVPCI, O_RDONLY, 0);
+ if (fd < 0)
+ err(1, "%s", _PATH_DEVPCI);
+
+ bzero(&pc, sizeof(struct pci_conf_io));
+ pc.match_buf_len = sizeof(conf);
+ pc.matches = conf;
+
+ bzero(&patterns, sizeof(patterns));
+
+ /*
+ * The pattern structure requires the unit to be split out from
+ * the driver name. Walk backwards from the end of the name to
+ * find the start of the unit.
+ */
+ if (name[0] == '\0')
+ errx(1, "Empty device name");
+ cp = strchr(name, '\0');
+ assert(cp != NULL && cp != name);
+ cp--;
+ while (cp != name && isdigit(cp[-1]))
+ cp--;
+ if (cp == name || !isdigit(*cp))
+ errx(1, "Invalid device name");
+ if ((size_t)(cp - name) + 1 > sizeof(patterns[0].pd_name))
+ errx(1, "Device name is too long");
+ memcpy(patterns[0].pd_name, name, cp - name);
+ patterns[0].pd_unit = strtol(cp, &cp, 10);
+ assert(*cp == '\0');
+ patterns[0].flags = PCI_GETCONF_MATCH_NAME | PCI_GETCONF_MATCH_UNIT;
+ pc.num_patterns = 1;
+ pc.pat_buf_len = sizeof(patterns);
+ pc.patterns = patterns;
+
+ if (ioctl(fd, PCIOCGETCONF, &pc) == -1)
+ err(1, "ioctl(PCIOCGETCONF)");
+ if (pc.status != PCI_GETCONF_LAST_DEVICE &&
+ pc.status != PCI_GETCONF_MORE_DEVS)
+ errx(1, "error returned from PCIOCGETCONF ioctl");
+ close(fd);
+ if (pc.num_matches == 0)
+ errx(1, "Device not found");
+ return (conf[0].pc_sel);
+}
+
+static struct pcisel
+parsesel(const char *str)
+{
char *ep = strchr(str, '@');
char *epbase;
struct pcisel sel;
@@ -595,6 +929,20 @@
return sel;
}
+static struct pcisel
+getsel(const char *str)
+{
+
+ /*
+ * No device names contain colons and selectors always contain
+ * at least one colon.
+ */
+ if (strchr(str, ':') == NULL)
+ return (getdevice(str));
+ else
+ return (parsesel(str));
+}
+
static void
readone(int fd, struct pcisel *sel, long reg, int width)
{
More information about the Midnightbsd-cvs
mailing list