Add accessors for the Vendor Specific Extended Capability (VSEC)

Parse out the VSEC.  If the user invokes a second -c command line option,
do a hex dump of the vendor data.

Reviewed by:	imp
MFC after:	3 days
Sponsored by:	Intel
Differential Revision:	http://reviews.freebsd.org/D22808
This commit is contained in:
Scott Long 2019-12-13 23:46:59 +00:00
parent 93dafad57a
commit 97faa4c470
5 changed files with 43 additions and 9 deletions

View File

@ -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
*/

View File

@ -50,6 +50,8 @@ static const char rcsid[] =
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 @@ cap_ea(int fd, struct pci_conf *p, uint8_t ptr)
}
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 @@ list_caps(int fd, struct pci_conf *p)
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 @@ ecap_sernum(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
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

View File

@ -177,6 +177,9 @@ If the
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

View File

@ -131,7 +131,7 @@ main(int argc, char **argv)
break;
case 'c':
caps = 1;
caps++;
break;
case 'D':
@ -282,7 +282,7 @@ list_devs(const char *name, int verbose, int bars, int bridge, int caps,
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)

View File

@ -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);