- Add register definitions related to extended capability IDs in
PCI-express. I used PCIZ_* for ID constants (plain capability IDs use PCIY_*). - Add register definitions for the Advanced Error Reporting, Virtual Channels, and Device Serial Number extended capabilities. - Teach pciconf -c to list extended as well as plain capabilities. Adds more detailed parsing for AER, VC, and device serial numbers. MFC after: 2 weeks
This commit is contained in:
parent
3b0620e06c
commit
79c2de35b5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=212326
@ -36,6 +36,7 @@
|
||||
* PCIV_xxx: PCI vendor ID (only required to fixup ancient devices)
|
||||
* PCID_xxx: device ID
|
||||
* PCIY_xxx: capability identification number
|
||||
* PCIZ_xxx: extended capability identification number
|
||||
*/
|
||||
|
||||
/* some PCI bus constants */
|
||||
@ -117,6 +118,28 @@
|
||||
#define PCIY_SATA 0x12 /* SATA */
|
||||
#define PCIY_PCIAF 0x13 /* PCI Advanced Features */
|
||||
|
||||
/* Extended Capability Register Fields */
|
||||
|
||||
#define PCIR_EXTCAP 0x100
|
||||
#define PCIM_EXTCAP_ID 0x0000ffff
|
||||
#define PCIM_EXTCAP_VER 0x000f0000
|
||||
#define PCIM_EXTCAP_NEXTPTR 0xfff00000
|
||||
#define PCI_EXTCAP_ID(ecap) ((ecap) & PCIM_EXTCAP_ID)
|
||||
#define PCI_EXTCAP_VER(ecap) (((ecap) & PCIM_EXTCAP_VER) >> 16)
|
||||
#define PCI_EXTCAP_NEXTPTR(ecap) (((ecap) & PCIM_EXTCAP_NEXTPTR) >> 20)
|
||||
|
||||
/* Extended Capability Identification Numbers */
|
||||
|
||||
#define PCIZ_AER 0x0001 /* Advanced Error Reporting */
|
||||
#define PCIZ_VC 0x0002 /* Virtual Channel */
|
||||
#define PCIZ_SERNUM 0x0003 /* Device Serial Number */
|
||||
#define PCIZ_PWRBDGT 0x0004 /* Power Budgeting */
|
||||
#define PCIZ_VENDOR 0x000b /* Vendor Unique */
|
||||
#define PCIZ_ACS 0x000d /* Access Control Services */
|
||||
#define PCIZ_ARI 0x000e /* Alternative Routing-ID Interpretation */
|
||||
#define PCIZ_ATS 0x000f /* Address Translation Services */
|
||||
#define PCIZ_SRIOV 0x0010 /* Single Root IO Virtualization */
|
||||
|
||||
/* config registers for header type 0 devices */
|
||||
|
||||
#define PCIR_BARS 0x10
|
||||
@ -663,3 +686,64 @@
|
||||
#define PCIR_PCIAFCTRL_FLR 0x01
|
||||
#define PCIR_PCIAF_STATUS 0x5
|
||||
#define PCIR_PCIAFSTATUS_TP 0x01
|
||||
|
||||
/* Advanced Error Reporting */
|
||||
#define PCIR_AER_UC_STATUS 0x04
|
||||
#define PCIR_AER_UC_TRAINING_ERROR 0x00000001
|
||||
#define PCIR_AER_UC_DL_PROTOCOL_ERROR 0x00000010
|
||||
#define PCIR_AER_UC_POISONED_TLP 0x00001000
|
||||
#define PCIR_AER_UC_FC_PROTOCOL_ERROR 0x00002000
|
||||
#define PCIR_AER_UC_COMPLETION_TIMEOUT 0x00004000
|
||||
#define PCIR_AER_UC_COMPLETER_ABORT 0x00008000
|
||||
#define PCIR_AER_UC_UNEXPECTED_COMPLETION 0x00010000
|
||||
#define PCIR_AER_UC_RECEIVER_OVERFLOW 0x00020000
|
||||
#define PCIR_AER_UC_MALFORMED_TLP 0x00040000
|
||||
#define PCIR_AER_UC_ECRC_ERROR 0x00080000
|
||||
#define PCIR_AER_UC_UNSUPPORTED_REQUEST 0x00100000
|
||||
#define PCIR_AER_UC_ACS_VIOLATION 0x00200000
|
||||
#define PCIR_AER_UC_MASK 0x08 /* Shares bits with UC_STATUS */
|
||||
#define PCIR_AER_UC_SEVERITY 0x0c /* Shares bits with UC_STATUS */
|
||||
#define PCIR_AER_COR_STATUS 0x10
|
||||
#define PCIM_AER_COR_RECEIVER_ERROR 0x00000001
|
||||
#define PCIM_AER_COR_BAD_TLP 0x00000040
|
||||
#define PCIM_AER_COR_BAD_DLLP 0x00000080
|
||||
#define PCIM_AER_COR_REPLAY_ROLLOVER 0x00000100
|
||||
#define PCIM_AER_COR_REPLAY_TIMEOUT 0x00001000
|
||||
#define PCIR_AER_COR_MASK 0x14 /* Shares bits with COR_STATUS */
|
||||
#define PCIR_AER_CAP_CONTROL 0x18
|
||||
#define PCIM_AER_FIRST_ERROR_PTR 0x0000001f
|
||||
#define PCIM_AER_ECRC_GEN_CAPABLE 0x00000020
|
||||
#define PCIM_AER_ECRC_GEN_ENABLE 0x00000040
|
||||
#define PCIM_AER_ECRC_CHECK_CAPABLE 0x00000080
|
||||
#define PCIM_AER_ECRC_CHECK_ENABLE 0x00000100
|
||||
#define PCIR_AER_HEADER_LOG 0x1c
|
||||
#define PCIR_AER_ROOTERR_CMD 0x2c /* Only for root complex ports */
|
||||
#define PCIR_AER_ROOTERR_COR_ENABLE 0x00000001
|
||||
#define PCIR_AER_ROOTERR_NF_ENABLE 0x00000002
|
||||
#define PCIR_AER_ROOTERR_F_ENABLE 0x00000004
|
||||
#define PCIR_AER_ROOTERR_STATUS 0x30 /* Only for root complex ports */
|
||||
#define PCIR_AER_ROOTERR_COR_ERR 0x00000001
|
||||
#define PCIR_AER_ROOTERR_MULTI_COR_ERR 0x00000002
|
||||
#define PCIR_AER_ROOTERR_UC_ERR 0x00000004
|
||||
#define PCIR_AER_ROOTERR_MULTI_UC_ERR 0x00000008
|
||||
#define PCIR_AER_ROOTERR_FIRST_UC_FATAL 0x00000010
|
||||
#define PCIR_AER_ROOTERR_NF_ERR 0x00000020
|
||||
#define PCIR_AER_ROOTERR_F_ERR 0x00000040
|
||||
#define PCIR_AER_ROOTERR_INT_MESSAGE 0xf8000000
|
||||
#define PCIR_AER_COR_SOURCE_ID 0x34 /* Only for root complex ports */
|
||||
#define PCIR_AER_ERR_SOURCE_ID 0x36 /* Only for root complex ports */
|
||||
|
||||
/* Virtual Channel definitions */
|
||||
#define PCIR_VC_CAP1 0x04
|
||||
#define PCIM_VC_CAP1_EXT_COUNT 0x00000007
|
||||
#define PCIM_VC_CAP1_LOWPRI_EXT_COUNT 0x00000070
|
||||
#define PCIR_VC_CAP2 0x08
|
||||
#define PCIR_VC_CONTROL 0x0C
|
||||
#define PCIR_VC_STATUS 0x0E
|
||||
#define PCIR_VC_RESOURCE_CAP(n) (0x10 + (n) * 0x0C)
|
||||
#define PCIR_VC_RESOURCE_CTL(n) (0x14 + (n) * 0x0C)
|
||||
#define PCIR_VC_RESOURCE_STA(n) (0x18 + (n) * 0x0C)
|
||||
|
||||
/* Serial Number definitions */
|
||||
#define PCIR_SERIAL_LOW 0x04
|
||||
#define PCIR_SERIAL_HIGH 0x08
|
||||
|
@ -45,6 +45,8 @@ static const char rcsid[] =
|
||||
|
||||
#include "pciconf.h"
|
||||
|
||||
static void list_ecaps(int fd, struct pci_conf *p);
|
||||
|
||||
static void
|
||||
cap_power(int fd, struct pci_conf *p, uint8_t ptr)
|
||||
{
|
||||
@ -530,4 +532,97 @@ list_caps(int fd, struct pci_conf *p)
|
||||
printf("\n");
|
||||
ptr = read_config(fd, &p->pc_sel, ptr + PCICAP_NEXTPTR, 1);
|
||||
}
|
||||
|
||||
list_ecaps(fd, p);
|
||||
}
|
||||
|
||||
/* From <sys/systm.h>. */
|
||||
static __inline uint32_t
|
||||
bitcount32(uint32_t x)
|
||||
{
|
||||
|
||||
x = (x & 0x55555555) + ((x & 0xaaaaaaaa) >> 1);
|
||||
x = (x & 0x33333333) + ((x & 0xcccccccc) >> 2);
|
||||
x = (x + (x >> 4)) & 0x0f0f0f0f;
|
||||
x = (x + (x >> 8));
|
||||
x = (x + (x >> 16)) & 0x000000ff;
|
||||
return (x);
|
||||
}
|
||||
|
||||
static void
|
||||
ecap_aer(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
|
||||
{
|
||||
uint32_t sta, mask;
|
||||
|
||||
printf("AER %d", ver);
|
||||
if (ver != 1)
|
||||
return;
|
||||
sta = read_config(fd, &p->pc_sel, ptr + PCIR_AER_UC_STATUS, 4);
|
||||
mask = read_config(fd, &p->pc_sel, ptr + PCIR_AER_UC_SEVERITY, 4);
|
||||
printf(" %d fatal", bitcount32(sta & mask));
|
||||
printf(" %d non-fatal", bitcount32(sta & ~mask));
|
||||
sta = read_config(fd, &p->pc_sel, ptr + PCIR_AER_COR_STATUS, 4);
|
||||
printf(" %d corrected", bitcount32(sta));
|
||||
}
|
||||
|
||||
static void
|
||||
ecap_vc(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
|
||||
{
|
||||
uint32_t cap1;
|
||||
|
||||
printf("VC %d", ver);
|
||||
if (ver != 1)
|
||||
return;
|
||||
cap1 = read_config(fd, &p->pc_sel, ptr + PCIR_VC_CAP1, 4);
|
||||
printf(" max VC%d", cap1 & PCIM_VC_CAP1_EXT_COUNT);
|
||||
if ((cap1 & PCIM_VC_CAP1_LOWPRI_EXT_COUNT) != 0)
|
||||
printf(" lowpri VC0-VC%d",
|
||||
(cap1 & PCIM_VC_CAP1_LOWPRI_EXT_COUNT) >> 4);
|
||||
}
|
||||
|
||||
static void
|
||||
ecap_sernum(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
|
||||
{
|
||||
uint32_t high, low;
|
||||
|
||||
printf("Serial %d", ver);
|
||||
if (ver != 1)
|
||||
return;
|
||||
low = read_config(fd, &p->pc_sel, ptr + PCIR_SERIAL_LOW, 4);
|
||||
high = read_config(fd, &p->pc_sel, ptr + PCIR_SERIAL_HIGH, 4);
|
||||
printf(" %08x%08x", high, low);
|
||||
}
|
||||
|
||||
static void
|
||||
list_ecaps(int fd, struct pci_conf *p)
|
||||
{
|
||||
uint32_t ecap;
|
||||
uint16_t ptr;
|
||||
|
||||
ptr = PCIR_EXTCAP;
|
||||
ecap = read_config(fd, &p->pc_sel, ptr, 4);
|
||||
if (ecap == 0xffffffff || ecap == 0)
|
||||
return;
|
||||
for (;;) {
|
||||
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));
|
||||
break;
|
||||
case PCIZ_VC:
|
||||
ecap_vc(fd, p, ptr, PCI_EXTCAP_VER(ecap));
|
||||
break;
|
||||
case PCIZ_SERNUM:
|
||||
ecap_sernum(fd, p, ptr, PCI_EXTCAP_VER(ecap));
|
||||
break;
|
||||
default:
|
||||
printf("unknown %d", PCI_EXTCAP_VER(ecap));
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
ptr = PCI_EXTCAP_NEXTPTR(ecap);
|
||||
if (ptr == 0)
|
||||
break;
|
||||
ecap = read_config(fd, &p->pc_sel, ptr, 4);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user