Index: head/sys/dev/pci/pcireg.h =================================================================== --- head/sys/dev/pci/pcireg.h +++ head/sys/dev/pci/pcireg.h @@ -1049,6 +1049,13 @@ #define PCIR_SRIOV_BARS 0x24 #define PCIR_SRIOV_BAR(x) (PCIR_SRIOV_BARS + (x) * 4) +/* Extended Capability Vendor-Specific definitions */ +#define PCIR_VSEC_HEADER 0x04 +#define PCIR_VSEC_ID(hdr) ((hdr) & 0xffff) +#define PCIR_VSEC_REV(hdr) (((hdr) & 0xf0000) >> 16) +#define PCIR_VSEC_LENGTH(hdr) (((hdr) & 0xfff00000) >> 20) +#define PCIR_VSEC_DATA 0x08 + /* * PCI Express Firmware Interface definitions */ Index: head/usr.sbin/pciconf/cap.c =================================================================== --- head/usr.sbin/pciconf/cap.c +++ head/usr.sbin/pciconf/cap.c @@ -50,6 +50,8 @@ static void list_ecaps(int fd, struct pci_conf *p); +static int cap_level; + static void cap_power(int fd, struct pci_conf *p, uint8_t ptr) { @@ -729,7 +731,7 @@ } void -list_caps(int fd, struct pci_conf *p) +list_caps(int fd, struct pci_conf *p, int level) { int express; uint16_t sta; @@ -740,6 +742,8 @@ if (!(sta & PCIM_STATUS_CAPPRESENT)) return; + cap_level = level; + switch (p->pc_hdr & PCIM_HDRTYPE) { case PCIM_HDRTYPE_NORMAL: case PCIM_HDRTYPE_BRIDGE: @@ -875,13 +879,33 @@ static void ecap_vendor(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver) { - uint32_t val; + uint32_t val, hdr; + uint16_t nextptr, len; + int i; - printf("Vendor %d", ver); - if (ver < 1) + val = read_config(fd, &p->pc_sel, ptr, 4); + nextptr = PCI_EXTCAP_NEXTPTR(val); + hdr = read_config(fd, &p->pc_sel, ptr + PCIR_VSEC_HEADER, 4); + len = PCIR_VSEC_LENGTH(hdr); + if (len == 0) { + if (nextptr == 0) + nextptr = 0x1000; + len = nextptr - ptr; + } + + printf("Vendor [%d] ID %04x Rev %d Length %d\n", ver, + PCIR_VSEC_ID(hdr), PCIR_VSEC_REV(hdr), len); + if ((ver < 1) || (cap_level <= 1)) return; - val = read_config(fd, &p->pc_sel, ptr + 4, 4); - printf(" ID %d\n", val & 0xffff); + for (i = 0; i < len; i += 4) { + val = read_config(fd, &p->pc_sel, ptr + PCIR_VSEC_DATA + i, 4); + if ((i % 16) == 0) + printf(" "); + printf("%02x %02x %02x %02x ", val & 0xff, (val >> 8) & 0xff, + (val >> 16) & 0xff, (val >> 24) & 0xff); + if ((((i + 4) % 16) == 0 ) || ((i + 4) >= len)) + printf("\n"); + } } static void Index: head/usr.sbin/pciconf/pciconf.h =================================================================== --- head/usr.sbin/pciconf/pciconf.h +++ head/usr.sbin/pciconf/pciconf.h @@ -35,7 +35,7 @@ #ifndef __PCICONF_H__ #define __PCICONF_H__ -void list_caps(int fd, struct pci_conf *p); +void list_caps(int fd, struct pci_conf *p, int level); void list_errors(int fd, struct pci_conf *p); uint8_t pci_find_cap(int fd, struct pci_conf *p, uint8_t id); uint16_t pcie_find_cap(int fd, struct pci_conf *p, uint16_t id); Index: head/usr.sbin/pciconf/pciconf.8 =================================================================== --- head/usr.sbin/pciconf/pciconf.8 +++ head/usr.sbin/pciconf/pciconf.8 @@ -177,6 +177,9 @@ option is supplied, .Nm will list any capabilities supported by each device. +A second invocation of +.Fl c +will print additional data for certain capabilities. Each capability is enumerated via a line in the following format: .Bd -literal cap 10[40] = PCI-Express 1 root port Index: head/usr.sbin/pciconf/pciconf.c =================================================================== --- head/usr.sbin/pciconf/pciconf.c +++ head/usr.sbin/pciconf/pciconf.c @@ -131,7 +131,7 @@ break; case 'c': - caps = 1; + caps++; break; case 'D': @@ -282,7 +282,7 @@ if (bridge) list_bridge(fd, p); if (caps) - list_caps(fd, p); + list_caps(fd, p, caps); if (errors) list_errors(fd, p); if (vpd)