diff options
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/pciconf/pciconf.8 | 28 | ||||
-rw-r--r-- | usr.sbin/pciconf/pciconf.c | 75 |
2 files changed, 96 insertions, 7 deletions
diff --git a/usr.sbin/pciconf/pciconf.8 b/usr.sbin/pciconf/pciconf.8 index 64d2f21..7492b5d 100644 --- a/usr.sbin/pciconf/pciconf.8 +++ b/usr.sbin/pciconf/pciconf.8 @@ -33,7 +33,7 @@ .Nd diagnostic utility for the PCI bus .Sh SYNOPSIS .Nm -.Fl l Op Fl cv +.Fl l Op Fl bcv .Nm .Fl a Ar selector .Nm @@ -112,6 +112,32 @@ device, which contains several (similar or independent) functions on one chip. .Pp If the +.Fl b +option is supplied, +.Nm +will list any base address registers +.Pq BARs +that are assigned resources for each device. +Each BAR will be enumerated via a line in the following format: +.Bd -literal + bar [10] = type Memory, range 32, base 0xda060000, size 131072, enabled +.Ed +.Pp +The first value after the +.Dq Li bar +prefix in the square brackets is the offset of the BAR in config space in +hexadecimal. +The type of a BAR is one of +.Dq Memory , +.Dq Prefetchable Memory , +or +.Dq I/O Port . +The range indicates 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. +.Pp +If the .Fl c option is supplied, .Nm diff --git a/usr.sbin/pciconf/pciconf.c b/usr.sbin/pciconf/pciconf.c index 4234a84..7d1da2d 100644 --- a/usr.sbin/pciconf/pciconf.c +++ b/usr.sbin/pciconf/pciconf.c @@ -37,6 +37,7 @@ static const char rcsid[] = #include <ctype.h> #include <err.h> +#include <inttypes.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -66,7 +67,8 @@ struct pci_vendor_info TAILQ_HEAD(,pci_vendor_info) pci_vendors; -static void list_devs(int verbose, int caps); +static void list_bars(int fd, struct pci_conf *p); +static void list_devs(int verbose, int bars, int caps); static void list_verbose(struct pci_conf *p); static const char *guess_class(struct pci_conf *p); static const char *guess_subclass(struct pci_conf *p); @@ -81,7 +83,7 @@ static void usage(void) { fprintf(stderr, "%s\n%s\n%s\n%s\n", - "usage: pciconf -l [-cv]", + "usage: pciconf -l [-bcv]", " pciconf -a selector", " pciconf -r [-b | -h] selector addr[:addr2]", " pciconf -w [-b | -h] selector addr value"); @@ -92,10 +94,10 @@ int main(int argc, char **argv) { int c; - int listmode, readmode, writemode, attachedmode, caps, verbose; + int listmode, readmode, writemode, attachedmode, bars, caps, verbose; int byte, isshort; - listmode = readmode = writemode = attachedmode = caps = verbose = byte = isshort = 0; + listmode = readmode = writemode = attachedmode = bars = caps = verbose = byte = isshort = 0; while ((c = getopt(argc, argv, "abchlrwv")) != -1) { switch(c) { @@ -104,6 +106,7 @@ main(int argc, char **argv) break; case 'b': + bars = 1; byte = 1; break; @@ -143,7 +146,7 @@ main(int argc, char **argv) usage(); if (listmode) { - list_devs(verbose, caps); + list_devs(verbose, bars, caps); } else if (attachedmode) { chkattached(argv[optind], byte ? 1 : isshort ? 2 : 4); @@ -161,7 +164,7 @@ main(int argc, char **argv) } static void -list_devs(int verbose, int caps) +list_devs(int verbose, int bars, int caps) { int fd; struct pci_conf_io pc; @@ -217,6 +220,8 @@ list_devs(int verbose, int caps) p->pc_revid, p->pc_hdr); if (verbose) list_verbose(p); + if (bars) + list_bars(fd, p); if (caps) list_caps(fd, p); } @@ -226,6 +231,64 @@ list_devs(int verbose, int caps) } static void +list_bars(int fd, struct pci_conf *p) +{ + struct pci_bar_io bar; + uint64_t base; + const char *type; + int i, range, max; + + switch (p->pc_hdr & PCIM_HDRTYPE) { + case PCIM_HDRTYPE_NORMAL: + max = PCIR_MAX_BAR_0; + break; + case PCIM_HDRTYPE_BRIDGE: + max = PCIR_MAX_BAR_1; + break; + case PCIM_HDRTYPE_CARDBUS: + max = PCIR_MAX_BAR_2; + break; + default: + return; + } + + for (i = 0; i <= max; i++) { + bar.pbi_sel = p->pc_sel; + bar.pbi_reg = PCIR_BAR(i); + if (ioctl(fd, PCIOCGETBAR, &bar) < 0) + continue; + if (PCI_BAR_IO(bar.pbi_base)) { + type = "I/O Port"; + range = 32; + base = bar.pbi_base & PCIM_BAR_IO_BASE; + } else { + if (bar.pbi_base & PCIM_BAR_MEM_PREFETCH) + type = "Prefetchable Memory"; + else + type = "Memory"; + switch (bar.pbi_base & PCIM_BAR_MEM_TYPE) { + case PCIM_BAR_MEM_32: + range = 32; + break; + case PCIM_BAR_MEM_1MB: + range = 20; + break; + case PCIM_BAR_MEM_64: + range = 64; + break; + default: + range = -1; + } + base = bar.pbi_base & ~((uint64_t)0xf); + } + 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, + bar.pbi_enabled ? "enabled" : "disabled"); + } +} + +static void list_verbose(struct pci_conf *p) { struct pci_vendor_info *vi; |