svn commit: r189080 - in stable/7: sys sys/contrib/pf
sys/dev/ath/ath_hal sys/dev/cardbus sys/dev/cxgb sys/dev/pci
sys/sys usr.sbin/pciconf
John Baldwin
jhb at FreeBSD.org
Thu Feb 26 10:54:26 PST 2009
Author: jhb
Date: Thu Feb 26 18:54:24 2009
New Revision: 189080
URL: http://svn.freebsd.org/changeset/base/189080
Log:
MFC: Add a new ioctl to fetch details about an individual BAR of a device
and add support for displaying BAR details via a new pciconf flag.
Modified:
stable/7/sys/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
stable/7/sys/dev/ath/ath_hal/ (props changed)
stable/7/sys/dev/cardbus/cardbus.c
stable/7/sys/dev/cxgb/ (props changed)
stable/7/sys/dev/pci/pci_user.c
stable/7/sys/dev/pci/pcireg.h
stable/7/sys/sys/pciio.h
stable/7/usr.sbin/pciconf/ (props changed)
stable/7/usr.sbin/pciconf/pciconf.8
stable/7/usr.sbin/pciconf/pciconf.c
Modified: stable/7/sys/dev/cardbus/cardbus.c
==============================================================================
--- stable/7/sys/dev/cardbus/cardbus.c Thu Feb 26 18:46:22 2009 (r189079)
+++ stable/7/sys/dev/cardbus/cardbus.c Thu Feb 26 18:54:24 2009 (r189080)
@@ -145,7 +145,7 @@ cardbus_device_setup_regs(pcicfgregs *cf
* Some cards power up with garbage in their BARs. This
* code clears all that junk out.
*/
- for (i = 0; i < PCI_MAX_BAR_0; i++)
+ for (i = 0; i < PCIR_MAX_BAR_0; i++)
pci_write_config(dev, PCIR_BAR(i), 0, 4);
cfg->intline =
Modified: stable/7/sys/dev/pci/pci_user.c
==============================================================================
--- stable/7/sys/dev/pci/pci_user.c Thu Feb 26 18:46:22 2009 (r189079)
+++ stable/7/sys/dev/pci/pci_user.c Thu Feb 26 18:54:24 2009 (r189080)
@@ -307,7 +307,10 @@ pci_ioctl(struct cdev *dev, u_long cmd,
struct pci_conf_io *cio;
struct pci_devinfo *dinfo;
struct pci_io *io;
+ struct pci_bar_io *bio;
struct pci_match_conf *pattern_buf;
+ struct resource_list_entry *rle;
+ uint32_t value;
size_t confsz, iolen, pbufsz;
int error, ionum, i, num_patterns;
#ifdef PRE7_COMPAT
@@ -319,11 +322,11 @@ pci_ioctl(struct cdev *dev, u_long cmd,
io_old = NULL;
pattern_buf_old = NULL;
- if (!(flag & FWRITE) &&
- (cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD))
+ if (!(flag & FWRITE) && cmd != PCIOCGETBAR &&
+ cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD)
return EPERM;
#else
- if (!(flag & FWRITE) && cmd != PCIOCGETCONF)
+ if (!(flag & FWRITE) && cmd != PCIOCGETBAR && cmd != PCIOCGETCONF)
return EPERM;
#endif
@@ -669,6 +672,70 @@ getconfexit:
}
break;
+ case PCIOCGETBAR:
+ bio = (struct pci_bar_io *)data;
+
+ /*
+ * Assume that the user-level bus number is
+ * in fact the physical PCI bus number.
+ */
+ pcidev = pci_find_dbsf(bio->pbi_sel.pc_domain,
+ bio->pbi_sel.pc_bus, bio->pbi_sel.pc_dev,
+ bio->pbi_sel.pc_func);
+ if (pcidev == NULL) {
+ error = ENODEV;
+ break;
+ }
+ dinfo = device_get_ivars(pcidev);
+
+ /*
+ * Look for a resource list entry matching the requested BAR.
+ *
+ * XXX: This will not find BARs that are not initialized, but
+ * maybe that is ok?
+ */
+ rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY,
+ bio->pbi_reg);
+ if (rle == NULL)
+ rle = resource_list_find(&dinfo->resources,
+ SYS_RES_IOPORT, bio->pbi_reg);
+ if (rle == NULL || rle->res == NULL) {
+ error = EINVAL;
+ break;
+ }
+
+ /*
+ * Ok, we have a resource for this BAR. Read the lower
+ * 32 bits to get any flags.
+ */
+ value = pci_read_config(pcidev, bio->pbi_reg, 4);
+ if (PCI_BAR_MEM(value)) {
+ if (rle->type != SYS_RES_MEMORY) {
+ error = EINVAL;
+ break;
+ }
+ value &= ~PCIM_BAR_MEM_BASE;
+ } else {
+ if (rle->type != SYS_RES_IOPORT) {
+ error = EINVAL;
+ break;
+ }
+ value &= ~PCIM_BAR_IO_BASE;
+ }
+ bio->pbi_base = rman_get_start(rle->res) | value;
+ bio->pbi_length = rman_get_size(rle->res);
+
+ /*
+ * Check the command register to determine if this BAR
+ * is enabled.
+ */
+ value = pci_read_config(pcidev, PCIR_COMMAND, 2);
+ if (rle->type == SYS_RES_MEMORY)
+ bio->pbi_enabled = (value & PCIM_CMD_MEMEN) != 0;
+ else
+ bio->pbi_enabled = (value & PCIM_CMD_PORTEN) != 0;
+ error = 0;
+ break;
default:
error = ENOTTY;
break;
Modified: stable/7/sys/dev/pci/pcireg.h
==============================================================================
--- stable/7/sys/dev/pci/pcireg.h Thu Feb 26 18:46:22 2009 (r189079)
+++ stable/7/sys/dev/pci/pcireg.h Thu Feb 26 18:54:24 2009 (r189080)
@@ -117,7 +117,7 @@
#define PCIR_BARS 0x10
#define PCIR_BAR(x) (PCIR_BARS + (x) * 4)
-#define PCI_MAX_BAR_0 5 /* Number of standard bars */
+#define PCIR_MAX_BAR_0 5
#define PCI_RID2BAR(rid) (((rid) - PCIR_BARS) / 4)
#define PCI_BAR_IO(x) (((x) & PCIM_BAR_SPACE) == PCIM_BAR_IO_SPACE)
#define PCI_BAR_MEM(x) (((x) & PCIM_BAR_SPACE) == PCIM_BAR_MEM_SPACE)
@@ -158,6 +158,7 @@
/* config registers for header type 1 (PCI-to-PCI bridge) devices */
+#define PCIR_MAX_BAR_1 1
#define PCIR_SECSTAT_1 0x1e
#define PCIR_PRIBUS_1 0x18
@@ -188,6 +189,7 @@
/* config registers for header type 2 (CardBus) devices */
+#define PCIR_MAX_BAR_2 0
#define PCIR_CAP_PTR_2 0x14
#define PCIR_SECSTAT_2 0x16
Modified: stable/7/sys/sys/pciio.h
==============================================================================
--- stable/7/sys/sys/pciio.h Thu Feb 26 18:46:22 2009 (r189079)
+++ stable/7/sys/sys/pciio.h Thu Feb 26 18:54:24 2009 (r189080)
@@ -108,9 +108,18 @@ struct pci_io {
u_int32_t pi_data; /* data to write or result of read */
};
+struct pci_bar_io {
+ struct pcisel pbi_sel; /* device to operate on */
+ int pbi_reg; /* starting address of BAR */
+ int pbi_enabled; /* decoding enabled */
+ uint64_t pbi_base; /* current value of BAR */
+ uint64_t pbi_length; /* length of BAR */
+};
+
#define PCIOCGETCONF _IOWR('p', 5, struct pci_conf_io)
#define PCIOCREAD _IOWR('p', 2, struct pci_io)
#define PCIOCWRITE _IOWR('p', 3, struct pci_io)
#define PCIOCATTACHED _IOWR('p', 4, struct pci_io)
+#define PCIOCGETBAR _IOWR('p', 6, struct pci_bar_io)
#endif /* !_SYS_PCIIO_H_ */
Modified: stable/7/usr.sbin/pciconf/pciconf.8
==============================================================================
--- stable/7/usr.sbin/pciconf/pciconf.8 Thu Feb 26 18:46:22 2009 (r189079)
+++ stable/7/usr.sbin/pciconf/pciconf.8 Thu Feb 26 18:54:24 2009 (r189080)
@@ -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
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
Modified: stable/7/usr.sbin/pciconf/pciconf.c
==============================================================================
--- stable/7/usr.sbin/pciconf/pciconf.c Thu Feb 26 18:46:22 2009 (r189079)
+++ stable/7/usr.sbin/pciconf/pciconf.c Thu Feb 26 18:54:24 2009 (r189080)
@@ -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;
More information about the svn-src-stable-7
mailing list