xref: /pciutils/ls-ecaps.c (revision b78c087b)
1 /*
2  *	The PCI Utilities -- Show Extended Capabilities
3  *
4  *	Copyright (c) 1997--2022 Martin Mares <[email protected]>
5  *
6  *	Can be freely distributed and used under the terms of the GNU GPL v2+.
7  *
8  *	SPDX-License-Identifier: GPL-2.0-or-later
9  */
10 
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include "lspci.h"
15 
16 static void
cap_tph(struct device * d,int where)17 cap_tph(struct device *d, int where)
18 {
19   u32 tph_cap;
20   printf("Transaction Processing Hints\n");
21   if (verbose < 2)
22     return;
23 
24   if (!config_fetch(d, where + PCI_TPH_CAPABILITIES, 4))
25     return;
26 
27   tph_cap = get_conf_long(d, where + PCI_TPH_CAPABILITIES);
28 
29   if (tph_cap & PCI_TPH_INTVEC_SUP)
30     printf("\t\tInterrupt vector mode supported\n");
31   if (tph_cap & PCI_TPH_DEV_SUP)
32     printf("\t\tDevice specific mode supported\n");
33   if (tph_cap & PCI_TPH_EXT_REQ_SUP)
34     printf("\t\tExtended requester support\n");
35 
36   switch (tph_cap & PCI_TPH_ST_LOC_MASK) {
37   case PCI_TPH_ST_NONE:
38     printf("\t\tNo steering table available\n");
39     break;
40   case PCI_TPH_ST_CAP:
41     printf("\t\tSteering table in TPH capability structure\n");
42     break;
43   case PCI_TPH_ST_MSIX:
44     printf("\t\tSteering table in MSI-X table\n");
45     break;
46   default:
47     printf("\t\tReserved steering table location\n");
48     break;
49   }
50 }
51 
52 static u32
cap_ltr_scale(u8 scale)53 cap_ltr_scale(u8 scale)
54 {
55   return 1 << (scale * 5);
56 }
57 
58 static void
cap_ltr(struct device * d,int where)59 cap_ltr(struct device *d, int where)
60 {
61   u32 scale;
62   u16 snoop, nosnoop;
63   printf("Latency Tolerance Reporting\n");
64   if (verbose < 2)
65     return;
66 
67   if (!config_fetch(d, where + PCI_LTR_MAX_SNOOP, 4))
68     return;
69 
70   snoop = get_conf_word(d, where + PCI_LTR_MAX_SNOOP);
71   scale = cap_ltr_scale((snoop >> PCI_LTR_SCALE_SHIFT) & PCI_LTR_SCALE_MASK);
72   printf("\t\tMax snoop latency: %" PCI_U64_FMT_U "ns\n",
73 	 ((u64)snoop & PCI_LTR_VALUE_MASK) * scale);
74 
75   nosnoop = get_conf_word(d, where + PCI_LTR_MAX_NOSNOOP);
76   scale = cap_ltr_scale((nosnoop >> PCI_LTR_SCALE_SHIFT) & PCI_LTR_SCALE_MASK);
77   printf("\t\tMax no snoop latency: %" PCI_U64_FMT_U "ns\n",
78 	 ((u64)nosnoop & PCI_LTR_VALUE_MASK) * scale);
79 }
80 
81 static void
cap_sec(struct device * d,int where)82 cap_sec(struct device *d, int where)
83 {
84   u32 ctrl3, lane_err_stat;
85   u8 lane;
86   printf("Secondary PCI Express\n");
87   if (verbose < 2)
88     return;
89 
90   if (!config_fetch(d, where + PCI_SEC_LNKCTL3, 12))
91     return;
92 
93   ctrl3 = get_conf_word(d, where + PCI_SEC_LNKCTL3);
94   printf("\t\tLnkCtl3: LnkEquIntrruptEn%c PerformEqu%c\n",
95 	FLAG(ctrl3, PCI_SEC_LNKCTL3_LNK_EQU_REQ_INTR_EN),
96 	FLAG(ctrl3, PCI_SEC_LNKCTL3_PERFORM_LINK_EQU));
97 
98   lane_err_stat = get_conf_word(d, where + PCI_SEC_LANE_ERR);
99   printf("\t\tLaneErrStat: ");
100   if (lane_err_stat)
101     {
102       printf("LaneErr at lane:");
103       for (lane = 0; lane_err_stat; lane_err_stat >>= 1, lane += 1)
104         if (BITS(lane_err_stat, 0, 1))
105           printf(" %u", lane);
106     }
107   else
108     printf("0");
109   printf("\n");
110 }
111 
112 static void
cap_dsn(struct device * d,int where)113 cap_dsn(struct device *d, int where)
114 {
115   u32 t1, t2;
116   if (!config_fetch(d, where + 4, 8))
117     return;
118   t1 = get_conf_long(d, where + 4);
119   t2 = get_conf_long(d, where + 8);
120   printf("Device Serial Number %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n",
121 	t2 >> 24, (t2 >> 16) & 0xff, (t2 >> 8) & 0xff, t2 & 0xff,
122 	t1 >> 24, (t1 >> 16) & 0xff, (t1 >> 8) & 0xff, t1 & 0xff);
123 }
124 
125 static void
cap_aer(struct device * d,int where,int type)126 cap_aer(struct device *d, int where, int type)
127 {
128   u32 l, l0, l1, l2, l3;
129   u16 w;
130 
131   printf("Advanced Error Reporting\n");
132   if (verbose < 2)
133     return;
134 
135   if (!config_fetch(d, where + PCI_ERR_UNCOR_STATUS, 40))
136     return;
137 
138   l = get_conf_long(d, where + PCI_ERR_UNCOR_STATUS);
139   printf("\t\tUESta:\tDLP%c SDES%c TLP%c FCP%c CmpltTO%c CmpltAbrt%c UnxCmplt%c RxOF%c MalfTLP%c\n"
140   "\t\t\tECRC%c UnsupReq%c ACSViol%c UncorrIntErr%c BlockedTLP%c AtomicOpBlocked%c TLPBlockedErr%c\n"
141   "\t\t\tPoisonTLPBlocked%c DMWrReqBlocked%c IDECheck%c MisIDETLP%c PCRC_CHECK%c TLPXlatBlocked%c\n",
142 	FLAG(l, PCI_ERR_UNC_DLP), FLAG(l, PCI_ERR_UNC_SDES), FLAG(l, PCI_ERR_UNC_POISON_TLP),
143 	FLAG(l, PCI_ERR_UNC_FCP), FLAG(l, PCI_ERR_UNC_COMP_TIME), FLAG(l, PCI_ERR_UNC_COMP_ABORT),
144 	FLAG(l, PCI_ERR_UNC_UNX_COMP), FLAG(l, PCI_ERR_UNC_RX_OVER), FLAG(l, PCI_ERR_UNC_MALF_TLP),
145 	FLAG(l, PCI_ERR_UNC_ECRC), FLAG(l, PCI_ERR_UNC_UNSUP), FLAG(l, PCI_ERR_UNC_ACS_VIOL),
146 	FLAG(l, PCI_ERR_UNC_INTERNAL), FLAG(l, PCI_ERR_UNC_MC_BLOCKED_TLP),
147 	FLAG(l, PCI_ERR_UNC_ATOMICOP_EGRESS_BLOCKED), FLAG(l, PCI_ERR_UNC_TLP_PREFIX_BLOCKED),
148 	FLAG(l, PCI_ERR_UNC_POISONED_TLP_EGRESS), FLAG(l, PCI_ERR_UNC_DMWR_REQ_EGRESS_BLOCKED),
149 	FLAG(l, PCI_ERR_UNC_IDE_CHECK), FLAG(l, PCI_ERR_UNC_MISR_IDE_TLP), FLAG(l, PCI_ERR_UNC_PCRC_CHECK),
150 	FLAG(l, PCI_ERR_UNC_TLP_XLAT_EGRESS_BLOCKED));
151   l = get_conf_long(d, where + PCI_ERR_UNCOR_MASK);
152   printf("\t\tUEMsk:\tDLP%c SDES%c TLP%c FCP%c CmpltTO%c CmpltAbrt%c UnxCmplt%c RxOF%c MalfTLP%c\n"
153   "\t\t\tECRC%c UnsupReq%c ACSViol%c UncorrIntErr%c BlockedTLP%c AtomicOpBlocked%c TLPBlockedErr%c\n"
154   "\t\t\tPoisonTLPBlocked%c DMWrReqBlocked%c IDECheck%c MisIDETLP%c PCRC_CHECK%c TLPXlatBlocked%c\n",
155 	FLAG(l, PCI_ERR_UNC_DLP), FLAG(l, PCI_ERR_UNC_SDES), FLAG(l, PCI_ERR_UNC_POISON_TLP),
156 	FLAG(l, PCI_ERR_UNC_FCP), FLAG(l, PCI_ERR_UNC_COMP_TIME), FLAG(l, PCI_ERR_UNC_COMP_ABORT),
157 	FLAG(l, PCI_ERR_UNC_UNX_COMP), FLAG(l, PCI_ERR_UNC_RX_OVER), FLAG(l, PCI_ERR_UNC_MALF_TLP),
158 	FLAG(l, PCI_ERR_UNC_ECRC), FLAG(l, PCI_ERR_UNC_UNSUP), FLAG(l, PCI_ERR_UNC_ACS_VIOL),
159 	FLAG(l, PCI_ERR_UNC_INTERNAL), FLAG(l, PCI_ERR_UNC_MC_BLOCKED_TLP),
160 	FLAG(l, PCI_ERR_UNC_ATOMICOP_EGRESS_BLOCKED), FLAG(l, PCI_ERR_UNC_TLP_PREFIX_BLOCKED),
161 	FLAG(l, PCI_ERR_UNC_POISONED_TLP_EGRESS), FLAG(l, PCI_ERR_UNC_DMWR_REQ_EGRESS_BLOCKED),
162 	FLAG(l, PCI_ERR_UNC_IDE_CHECK), FLAG(l, PCI_ERR_UNC_MISR_IDE_TLP), FLAG(l, PCI_ERR_UNC_PCRC_CHECK),
163 	FLAG(l, PCI_ERR_UNC_TLP_XLAT_EGRESS_BLOCKED));
164   l = get_conf_long(d, where + PCI_ERR_UNCOR_SEVER);
165   printf("\t\tUESvrt:\tDLP%c SDES%c TLP%c FCP%c CmpltTO%c CmpltAbrt%c UnxCmplt%c RxOF%c MalfTLP%c\n"
166   "\t\t\tECRC%c UnsupReq%c ACSViol%c UncorrIntErr%c BlockedTLP%c AtomicOpBlocked%c TLPBlockedErr%c\n"
167   "\t\t\tPoisonTLPBlocked%c DMWrReqBlocked%c IDECheck%c MisIDETLP%c PCRC_CHECK%c TLPXlatBlocked%c\n",
168 	FLAG(l, PCI_ERR_UNC_DLP), FLAG(l, PCI_ERR_UNC_SDES), FLAG(l, PCI_ERR_UNC_POISON_TLP),
169 	FLAG(l, PCI_ERR_UNC_FCP), FLAG(l, PCI_ERR_UNC_COMP_TIME), FLAG(l, PCI_ERR_UNC_COMP_ABORT),
170 	FLAG(l, PCI_ERR_UNC_UNX_COMP), FLAG(l, PCI_ERR_UNC_RX_OVER), FLAG(l, PCI_ERR_UNC_MALF_TLP),
171 	FLAG(l, PCI_ERR_UNC_ECRC), FLAG(l, PCI_ERR_UNC_UNSUP), FLAG(l, PCI_ERR_UNC_ACS_VIOL),
172 	FLAG(l, PCI_ERR_UNC_INTERNAL), FLAG(l, PCI_ERR_UNC_MC_BLOCKED_TLP),
173 	FLAG(l, PCI_ERR_UNC_ATOMICOP_EGRESS_BLOCKED), FLAG(l, PCI_ERR_UNC_TLP_PREFIX_BLOCKED),
174 	FLAG(l, PCI_ERR_UNC_POISONED_TLP_EGRESS), FLAG(l, PCI_ERR_UNC_DMWR_REQ_EGRESS_BLOCKED),
175 	FLAG(l, PCI_ERR_UNC_IDE_CHECK), FLAG(l, PCI_ERR_UNC_MISR_IDE_TLP), FLAG(l, PCI_ERR_UNC_PCRC_CHECK),
176 	FLAG(l, PCI_ERR_UNC_TLP_XLAT_EGRESS_BLOCKED));
177   l = get_conf_long(d, where + PCI_ERR_COR_STATUS);
178   printf("\t\tCESta:\tRxErr%c BadTLP%c BadDLLP%c Rollover%c Timeout%c AdvNonFatalErr%c "
179   "CorrIntErr%c HeaderOF%c\n",
180 	FLAG(l, PCI_ERR_COR_RCVR), FLAG(l, PCI_ERR_COR_BAD_TLP), FLAG(l, PCI_ERR_COR_BAD_DLLP),
181 	FLAG(l, PCI_ERR_COR_REP_ROLL), FLAG(l, PCI_ERR_COR_REP_TIMER), FLAG(l, PCI_ERR_COR_REP_ANFE),
182 	FLAG(l, PCI_ERR_COR_INTERNAL), FLAG(l, PCI_ERR_COR_HDRLOG_OVER));
183   l = get_conf_long(d, where + PCI_ERR_COR_MASK);
184   printf("\t\tCEMsk:\tRxErr%c BadTLP%c BadDLLP%c Rollover%c Timeout%c AdvNonFatalErr%c "
185   "CorrIntErr%c HeaderOF%c\n",
186 	FLAG(l, PCI_ERR_COR_RCVR), FLAG(l, PCI_ERR_COR_BAD_TLP), FLAG(l, PCI_ERR_COR_BAD_DLLP),
187 	FLAG(l, PCI_ERR_COR_REP_ROLL), FLAG(l, PCI_ERR_COR_REP_TIMER), FLAG(l, PCI_ERR_COR_REP_ANFE),
188 	FLAG(l, PCI_ERR_COR_INTERNAL), FLAG(l, PCI_ERR_COR_HDRLOG_OVER));
189   l = get_conf_long(d, where + PCI_ERR_CAP);
190   printf("\t\tAERCap:\tFirst Error Pointer: %02x, ECRCGenCap%c ECRCGenEn%c ECRCChkCap%c ECRCChkEn%c\n"
191 	"\t\t\tMultHdrRecCap%c MultHdrRecEn%c TLPPfxPres%c HdrLogCap%c\n",
192 	PCI_ERR_CAP_FEP(l), FLAG(l, PCI_ERR_CAP_ECRC_GENC), FLAG(l, PCI_ERR_CAP_ECRC_GENE),
193 	FLAG(l, PCI_ERR_CAP_ECRC_CHKC), FLAG(l, PCI_ERR_CAP_ECRC_CHKE),
194 	FLAG(l, PCI_ERR_CAP_MULT_HDRC), FLAG(l, PCI_ERR_CAP_MULT_HDRE),
195 	FLAG(l, PCI_ERR_CAP_TLP_PFX), FLAG(l, PCI_ERR_CAP_HDR_LOG));
196 
197   l0 = get_conf_long(d, where + PCI_ERR_HEADER_LOG);
198   l1 = get_conf_long(d, where + PCI_ERR_HEADER_LOG + 4);
199   l2 = get_conf_long(d, where + PCI_ERR_HEADER_LOG + 8);
200   l3 = get_conf_long(d, where + PCI_ERR_HEADER_LOG + 12);
201   printf("\t\tHeaderLog: %08x %08x %08x %08x\n", l0, l1, l2, l3);
202 
203   if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_ROOT_EC)
204     {
205       if (!config_fetch(d, where + PCI_ERR_ROOT_COMMAND, 12))
206         return;
207 
208       l = get_conf_long(d, where + PCI_ERR_ROOT_COMMAND);
209       printf("\t\tRootCmd: CERptEn%c NFERptEn%c FERptEn%c\n",
210 	    FLAG(l, PCI_ERR_ROOT_CMD_COR_EN),
211 	    FLAG(l, PCI_ERR_ROOT_CMD_NONFATAL_EN),
212 	    FLAG(l, PCI_ERR_ROOT_CMD_FATAL_EN));
213 
214       l = get_conf_long(d, where + PCI_ERR_ROOT_STATUS);
215       printf("\t\tRootSta: CERcvd%c MultCERcvd%c UERcvd%c MultUERcvd%c\n"
216 	    "\t\t\t FirstFatal%c NonFatalMsg%c FatalMsg%c IntMsgNum %d\n",
217 	    FLAG(l, PCI_ERR_ROOT_COR_RCV),
218 	    FLAG(l, PCI_ERR_ROOT_MULTI_COR_RCV),
219 	    FLAG(l, PCI_ERR_ROOT_UNCOR_RCV),
220 	    FLAG(l, PCI_ERR_ROOT_MULTI_UNCOR_RCV),
221 	    FLAG(l, PCI_ERR_ROOT_FIRST_FATAL),
222 	    FLAG(l, PCI_ERR_ROOT_NONFATAL_RCV),
223 	    FLAG(l, PCI_ERR_ROOT_FATAL_RCV),
224 	    PCI_ERR_MSG_NUM(l));
225 
226       w = get_conf_word(d, where + PCI_ERR_ROOT_COR_SRC);
227       printf("\t\tErrorSrc: ERR_COR: %04x ", w);
228 
229       w = get_conf_word(d, where + PCI_ERR_ROOT_SRC);
230       printf("ERR_FATAL/NONFATAL: %04x\n", w);
231     }
232 }
233 
cap_dpc(struct device * d,int where)234 static void cap_dpc(struct device *d, int where)
235 {
236   u16 l;
237 
238   printf("Downstream Port Containment\n");
239   if (verbose < 2)
240     return;
241 
242   if (!config_fetch(d, where + PCI_DPC_CAP, 8))
243     return;
244 
245   l = get_conf_word(d, where + PCI_DPC_CAP);
246   printf("\t\tDpcCap:\tIntMsgNum %d, RPExt%c PoisonedTLP%c SwTrigger%c RP PIO Log %d, DL_ActiveErr%c\n",
247     PCI_DPC_CAP_INT_MSG(l), FLAG(l, PCI_DPC_CAP_RP_EXT), FLAG(l, PCI_DPC_CAP_TLP_BLOCK),
248     FLAG(l, PCI_DPC_CAP_SW_TRIGGER), PCI_DPC_CAP_RP_LOG(l), FLAG(l, PCI_DPC_CAP_DL_ACT_ERR));
249 
250   l = get_conf_word(d, where + PCI_DPC_CTL);
251   printf("\t\tDpcCtl:\tTrigger:%x Cmpl%c INT%c ErrCor%c PoisonedTLP%c SwTrigger%c DL_ActiveErr%c\n",
252     PCI_DPC_CTL_TRIGGER(l), FLAG(l, PCI_DPC_CTL_CMPL), FLAG(l, PCI_DPC_CTL_INT),
253     FLAG(l, PCI_DPC_CTL_ERR_COR), FLAG(l, PCI_DPC_CTL_TLP), FLAG(l, PCI_DPC_CTL_SW_TRIGGER),
254     FLAG(l, PCI_DPC_CTL_DL_ACTIVE));
255 
256   l = get_conf_word(d, where + PCI_DPC_STATUS);
257   printf("\t\tDpcSta:\tTrigger%c Reason:%02x INT%c RPBusy%c TriggerExt:%02x RP PIO ErrPtr:%02x\n",
258     FLAG(l, PCI_DPC_STS_TRIGGER), PCI_DPC_STS_REASON(l), FLAG(l, PCI_DPC_STS_INT),
259     FLAG(l, PCI_DPC_STS_RP_BUSY), PCI_DPC_STS_TRIGGER_EXT(l), PCI_DPC_STS_PIO_FEP(l));
260 
261   l = get_conf_word(d, where + PCI_DPC_SOURCE);
262   printf("\t\tSource:\t%04x\n", l);
263 }
264 
265 static void
cap_acs(struct device * d,int where)266 cap_acs(struct device *d, int where)
267 {
268   u16 w;
269 
270   printf("Access Control Services\n");
271   if (verbose < 2)
272     return;
273 
274   if (!config_fetch(d, where + PCI_ACS_CAP, 4))
275     return;
276 
277   w = get_conf_word(d, where + PCI_ACS_CAP);
278   printf("\t\tACSCap:\tSrcValid%c TransBlk%c ReqRedir%c CmpltRedir%c UpstreamFwd%c EgressCtrl%c "
279 	"DirectTrans%c\n",
280 	FLAG(w, PCI_ACS_CAP_VALID), FLAG(w, PCI_ACS_CAP_BLOCK), FLAG(w, PCI_ACS_CAP_REQ_RED),
281 	FLAG(w, PCI_ACS_CAP_CMPLT_RED), FLAG(w, PCI_ACS_CAP_FORWARD), FLAG(w, PCI_ACS_CAP_EGRESS),
282 	FLAG(w, PCI_ACS_CAP_TRANS));
283   w = get_conf_word(d, where + PCI_ACS_CTRL);
284   printf("\t\tACSCtl:\tSrcValid%c TransBlk%c ReqRedir%c CmpltRedir%c UpstreamFwd%c EgressCtrl%c "
285 	"DirectTrans%c\n",
286 	FLAG(w, PCI_ACS_CTRL_VALID), FLAG(w, PCI_ACS_CTRL_BLOCK), FLAG(w, PCI_ACS_CTRL_REQ_RED),
287 	FLAG(w, PCI_ACS_CTRL_CMPLT_RED), FLAG(w, PCI_ACS_CTRL_FORWARD), FLAG(w, PCI_ACS_CTRL_EGRESS),
288 	FLAG(w, PCI_ACS_CTRL_TRANS));
289 }
290 
291 static void
cap_ari(struct device * d,int where)292 cap_ari(struct device *d, int where)
293 {
294   u16 w;
295 
296   printf("Alternative Routing-ID Interpretation (ARI)\n");
297   if (verbose < 2)
298     return;
299 
300   if (!config_fetch(d, where + PCI_ARI_CAP, 4))
301     return;
302 
303   w = get_conf_word(d, where + PCI_ARI_CAP);
304   printf("\t\tARICap:\tMFVC%c ACS%c, Next Function: %d\n",
305 	FLAG(w, PCI_ARI_CAP_MFVC), FLAG(w, PCI_ARI_CAP_ACS),
306 	PCI_ARI_CAP_NFN(w));
307   w = get_conf_word(d, where + PCI_ARI_CTRL);
308   printf("\t\tARICtl:\tMFVC%c ACS%c, Function Group: %d\n",
309 	FLAG(w, PCI_ARI_CTRL_MFVC), FLAG(w, PCI_ARI_CTRL_ACS),
310 	PCI_ARI_CTRL_FG(w));
311 }
312 
313 static void
cap_ats(struct device * d,int where)314 cap_ats(struct device *d, int where)
315 {
316   u16 w;
317 
318   printf("Address Translation Service (ATS)\n");
319   if (verbose < 2)
320     return;
321 
322   if (!config_fetch(d, where + PCI_ATS_CAP, 4))
323     return;
324 
325   w = get_conf_word(d, where + PCI_ATS_CAP);
326   printf("\t\tATSCap:\tInvalidate Queue Depth: %02x\n", PCI_ATS_CAP_IQD(w));
327   w = get_conf_word(d, where + PCI_ATS_CTRL);
328   printf("\t\tATSCtl:\tEnable%c, Smallest Translation Unit: %02x\n",
329 	FLAG(w, PCI_ATS_CTRL_ENABLE), PCI_ATS_CTRL_STU(w));
330 }
331 
332 static void
cap_pri(struct device * d,int where)333 cap_pri(struct device *d, int where)
334 {
335   u16 w;
336   u32 l;
337 
338   printf("Page Request Interface (PRI)\n");
339   if (verbose < 2)
340     return;
341 
342   if (!config_fetch(d, where + PCI_PRI_CTRL, 0xc))
343     return;
344 
345   w = get_conf_word(d, where + PCI_PRI_CTRL);
346   printf("\t\tPRICtl: Enable%c Reset%c\n",
347 	FLAG(w, PCI_PRI_CTRL_ENABLE), FLAG(w, PCI_PRI_CTRL_RESET));
348   w = get_conf_word(d, where + PCI_PRI_STATUS);
349   printf("\t\tPRISta: RF%c UPRGI%c Stopped%c PASID%c\n",
350 	FLAG(w, PCI_PRI_STATUS_RF), FLAG(w, PCI_PRI_STATUS_UPRGI),
351 	FLAG(w, PCI_PRI_STATUS_STOPPED), FLAG(w, PCI_PRI_STATUS_PASID));
352   l = get_conf_long(d, where + PCI_PRI_MAX_REQ);
353   printf("\t\tPage Request Capacity: %08x, ", l);
354   l = get_conf_long(d, where + PCI_PRI_ALLOC_REQ);
355   printf("Page Request Allocation: %08x\n", l);
356 }
357 
358 static void
cap_pasid(struct device * d,int where)359 cap_pasid(struct device *d, int where)
360 {
361   u16 w;
362 
363   printf("Process Address Space ID (PASID)\n");
364   if (verbose < 2)
365     return;
366 
367   if (!config_fetch(d, where + PCI_PASID_CAP, 4))
368     return;
369 
370   w = get_conf_word(d, where + PCI_PASID_CAP);
371   printf("\t\tPASIDCap: Exec%c Priv%c, Max PASID Width: %02x\n",
372 	FLAG(w, PCI_PASID_CAP_EXEC), FLAG(w, PCI_PASID_CAP_PRIV),
373 	PCI_PASID_CAP_WIDTH(w));
374   w = get_conf_word(d, where + PCI_PASID_CTRL);
375   printf("\t\tPASIDCtl: Enable%c Exec%c Priv%c\n",
376 	FLAG(w, PCI_PASID_CTRL_ENABLE), FLAG(w, PCI_PASID_CTRL_EXEC),
377 	FLAG(w, PCI_PASID_CTRL_PRIV));
378 }
379 
380 static void
cap_sriov(struct device * d,int where)381 cap_sriov(struct device *d, int where)
382 {
383   u16 b;
384   u16 w;
385   u32 l;
386   int i;
387 
388   printf("Single Root I/O Virtualization (SR-IOV)\n");
389   if (verbose < 2)
390     return;
391 
392   if (!config_fetch(d, where + PCI_IOV_CAP, 0x3c))
393     return;
394 
395   l = get_conf_long(d, where + PCI_IOV_CAP);
396   printf("\t\tIOVCap:\tMigration%c 10BitTagReq%c IntMsgNum %d\n",
397 	FLAG(l, PCI_IOV_CAP_VFM), FLAG(l, PCI_IOV_CAP_VF_10BIT_TAG_REQ), PCI_IOV_CAP_IMN(l));
398   w = get_conf_word(d, where + PCI_IOV_CTRL);
399   printf("\t\tIOVCtl:\tEnable%c Migration%c Interrupt%c MSE%c ARIHierarchy%c 10BitTagReq%c\n",
400 	FLAG(w, PCI_IOV_CTRL_VFE), FLAG(w, PCI_IOV_CTRL_VFME),
401 	FLAG(w, PCI_IOV_CTRL_VFMIE), FLAG(w, PCI_IOV_CTRL_MSE),
402 	FLAG(w, PCI_IOV_CTRL_ARI), FLAG(w, PCI_IOV_CTRL_VF_10BIT_TAG_REQ_EN));
403   w = get_conf_word(d, where + PCI_IOV_STATUS);
404   printf("\t\tIOVSta:\tMigration%c\n", FLAG(w, PCI_IOV_STATUS_MS));
405   w = get_conf_word(d, where + PCI_IOV_INITIALVF);
406   printf("\t\tInitial VFs: %d, ", w);
407   w = get_conf_word(d, where + PCI_IOV_TOTALVF);
408   printf("Total VFs: %d, ", w);
409   w = get_conf_word(d, where + PCI_IOV_NUMVF);
410   printf("Number of VFs: %d, ", w);
411   b = get_conf_byte(d, where + PCI_IOV_FDL);
412   printf("Function Dependency Link: %02x\n", b);
413   w = get_conf_word(d, where + PCI_IOV_OFFSET);
414   printf("\t\tVF offset: %d, ", w);
415   w = get_conf_word(d, where + PCI_IOV_STRIDE);
416   printf("stride: %d, ", w);
417   w = get_conf_word(d, where + PCI_IOV_DID);
418   printf("Device ID: %04x\n", w);
419   l = get_conf_long(d, where + PCI_IOV_SUPPS);
420   printf("\t\tSupported Page Size: %08x, ", l);
421   l = get_conf_long(d, where + PCI_IOV_SYSPS);
422   printf("System Page Size: %08x\n", l);
423 
424   for (i=0; i < PCI_IOV_NUM_BAR; i++)
425     {
426       u32 addr;
427       int type;
428       u32 h;
429       l = get_conf_long(d, where + PCI_IOV_BAR_BASE + 4*i);
430       if (l == 0xffffffff)
431 	l = 0;
432       if (!l)
433 	continue;
434       printf("\t\tRegion %d: Memory at ", i);
435       addr = l & PCI_ADDR_MEM_MASK;
436       type = l & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
437       if (type == PCI_BASE_ADDRESS_MEM_TYPE_64)
438 	{
439 	  i++;
440 	  h = get_conf_long(d, where + PCI_IOV_BAR_BASE + (i*4));
441 	  printf("%08x", h);
442 	}
443       printf("%08x (%s-bit, %sprefetchable)\n",
444 	addr,
445 	(type == PCI_BASE_ADDRESS_MEM_TYPE_32) ? "32" : "64",
446 	(l & PCI_BASE_ADDRESS_MEM_PREFETCH) ? "" : "non-");
447     }
448 
449   l = get_conf_long(d, where + PCI_IOV_MSAO);
450   printf("\t\tVF Migration: offset: %08x, BIR: %x\n", PCI_IOV_MSA_OFFSET(l),
451 	PCI_IOV_MSA_BIR(l));
452 }
453 
454 static void
cap_multicast(struct device * d,int where,int type)455 cap_multicast(struct device *d, int where, int type)
456 {
457   u16 w;
458   u32 l;
459   u64 bar, rcv, block;
460 
461   printf("Multicast\n");
462   if (verbose < 2)
463     return;
464 
465   if (!config_fetch(d, where + PCI_MCAST_CAP, 0x30))
466     return;
467 
468   w = get_conf_word(d, where + PCI_MCAST_CAP);
469   printf("\t\tMcastCap: MaxGroups %d", PCI_MCAST_CAP_MAX_GROUP(w) + 1);
470   if (type == PCI_EXP_TYPE_ENDPOINT || type == PCI_EXP_TYPE_ROOT_INT_EP)
471     printf(", WindowSz %d (%d bytes)",
472       PCI_MCAST_CAP_WIN_SIZE(w), 1 << PCI_MCAST_CAP_WIN_SIZE(w));
473   if (type == PCI_EXP_TYPE_ROOT_PORT ||
474       type == PCI_EXP_TYPE_UPSTREAM || type == PCI_EXP_TYPE_DOWNSTREAM)
475     printf(", ECRCRegen%c\n", FLAG(w, PCI_MCAST_CAP_ECRC));
476   w = get_conf_word(d, where + PCI_MCAST_CTRL);
477   printf("\t\tMcastCtl: NumGroups %d, Enable%c\n",
478     PCI_MCAST_CTRL_NUM_GROUP(w) + 1, FLAG(w, PCI_MCAST_CTRL_ENABLE));
479   bar = get_conf_long(d, where + PCI_MCAST_BAR);
480   l = get_conf_long(d, where + PCI_MCAST_BAR + 4);
481   bar |= (u64) l << 32;
482   printf("\t\tMcastBAR: IndexPos %d, BaseAddr %016" PCI_U64_FMT_X "\n",
483     PCI_MCAST_BAR_INDEX_POS(bar), bar & PCI_MCAST_BAR_MASK);
484   rcv = get_conf_long(d, where + PCI_MCAST_RCV);
485   l = get_conf_long(d, where + PCI_MCAST_RCV + 4);
486   rcv |= (u64) l << 32;
487   printf("\t\tMcastReceiveVec:      %016" PCI_U64_FMT_X "\n", rcv);
488   block = get_conf_long(d, where + PCI_MCAST_BLOCK);
489   l = get_conf_long(d, where + PCI_MCAST_BLOCK + 4);
490   block |= (u64) l << 32;
491   printf("\t\tMcastBlockAllVec:     %016" PCI_U64_FMT_X "\n", block);
492   block = get_conf_long(d, where + PCI_MCAST_BLOCK_UNTRANS);
493   l = get_conf_long(d, where + PCI_MCAST_BLOCK_UNTRANS + 4);
494   block |= (u64) l << 32;
495   printf("\t\tMcastBlockUntransVec: %016" PCI_U64_FMT_X "\n", block);
496 
497   if (type == PCI_EXP_TYPE_ENDPOINT || type == PCI_EXP_TYPE_ROOT_INT_EP)
498     return;
499   bar = get_conf_long(d, where + PCI_MCAST_OVL_BAR);
500   l = get_conf_long(d, where + PCI_MCAST_OVL_BAR + 4);
501   bar |= (u64) l << 32;
502   printf("\t\tMcastOverlayBAR: OverlaySize %d ", PCI_MCAST_OVL_SIZE(bar));
503   if (PCI_MCAST_OVL_SIZE(bar) >= 6)
504     printf("(%d bytes)", 1 << PCI_MCAST_OVL_SIZE(bar));
505   else
506     printf("(disabled)");
507   printf(", BaseAddr %016" PCI_U64_FMT_X "\n", bar & PCI_MCAST_OVL_MASK);
508 }
509 
510 static void
cap_vc(struct device * d,int where)511 cap_vc(struct device *d, int where)
512 {
513   u32 cr1, cr2;
514   u16 ctrl, status;
515   int evc_cnt;
516   int arb_table_pos;
517   int i, j;
518   static const char ref_clocks[][6] = { "100ns" };
519   static const char arb_selects[8][7] = { "Fixed", "WRR32", "WRR64", "WRR128", "??4", "??5", "??6", "??7" };
520   static const char vc_arb_selects[8][8] = { "Fixed", "WRR32", "WRR64", "WRR128", "TWRR128", "WRR256", "??6", "??7" };
521   char buf[8];
522 
523   printf("Virtual Channel\n");
524   if (verbose < 2)
525     return;
526 
527   if (!config_fetch(d, where + 4, 0x1c - 4))
528     return;
529 
530   cr1 = get_conf_long(d, where + PCI_VC_PORT_REG1);
531   cr2 = get_conf_long(d, where + PCI_VC_PORT_REG2);
532   ctrl = get_conf_word(d, where + PCI_VC_PORT_CTRL);
533   status = get_conf_word(d, where + PCI_VC_PORT_STATUS);
534 
535   evc_cnt = BITS(cr1, 0, 3);
536   printf("\t\tCaps:\tLPEVC=%d RefClk=%s PATEntryBits=%d\n",
537     BITS(cr1, 4, 3),
538     TABLE(ref_clocks, BITS(cr1, 8, 2), buf),
539     1 << BITS(cr1, 10, 2));
540 
541   printf("\t\tArb:");
542   for (i=0; i<8; i++)
543     if (arb_selects[i][0] != '?' || cr2 & (1 << i))
544       printf("%c%s%c", (i ? ' ' : '\t'), arb_selects[i], FLAG(cr2, 1 << i));
545   arb_table_pos = BITS(cr2, 24, 8);
546 
547   printf("\n\t\tCtrl:\tArbSelect=%s\n", TABLE(arb_selects, BITS(ctrl, 1, 3), buf));
548   printf("\t\tStatus:\tInProgress%c\n", FLAG(status, 1));
549 
550   if (arb_table_pos)
551     {
552       arb_table_pos = where + 16*arb_table_pos;
553       printf("\t\tPort Arbitration Table [%x] <?>\n", arb_table_pos);
554     }
555 
556   for (i=0; i<=evc_cnt; i++)
557     {
558       int pos = where + PCI_VC_RES_CAP + 12*i;
559       u32 rcap, rctrl;
560       u16 rstatus;
561       int pat_pos;
562 
563       printf("\t\tVC%d:\t", i);
564       if (!config_fetch(d, pos, 12))
565 	{
566 	  printf("<unreadable>\n");
567 	  continue;
568 	}
569       rcap = get_conf_long(d, pos);
570       rctrl = get_conf_long(d, pos+4);
571       rstatus = get_conf_word(d, pos+10);
572 
573       pat_pos = BITS(rcap, 24, 8);
574       printf("Caps:\tPATOffset=%02x MaxTimeSlots=%d RejSnoopTrans%c\n",
575 	pat_pos,
576 	BITS(rcap, 16, 7) + 1,
577 	FLAG(rcap, 1 << 15));
578 
579       printf("\t\t\tArb:");
580       for (j=0; j<8; j++)
581 	if (vc_arb_selects[j][0] != '?' || rcap & (1 << j))
582 	  printf("%c%s%c", (j ? ' ' : '\t'), vc_arb_selects[j], FLAG(rcap, 1 << j));
583 
584       printf("\n\t\t\tCtrl:\tEnable%c ID=%d ArbSelect=%s TC/VC=%02x\n",
585 	FLAG(rctrl, 1 << 31),
586 	BITS(rctrl, 24, 3),
587 	TABLE(vc_arb_selects, BITS(rctrl, 17, 3), buf),
588 	BITS(rctrl, 0, 8));
589 
590       printf("\t\t\tStatus:\tNegoPending%c InProgress%c\n",
591 	FLAG(rstatus, 2),
592 	FLAG(rstatus, 1));
593 
594       if (pat_pos)
595 	printf("\t\t\tPort Arbitration Table <?>\n");
596     }
597 }
598 
599 static void
cap_rclink(struct device * d,int where)600 cap_rclink(struct device *d, int where)
601 {
602   u32 esd;
603   int num_links;
604   int i;
605   static const char elt_types[][9] = { "Config", "Egress", "Internal" };
606   char buf[8];
607 
608   printf("Root Complex Link\n");
609   if (verbose < 2)
610     return;
611 
612   if (!config_fetch(d, where + 4, PCI_RCLINK_LINK1 - 4))
613     return;
614 
615   esd = get_conf_long(d, where + PCI_RCLINK_ESD);
616   num_links = BITS(esd, 8, 8);
617   printf("\t\tDesc:\tPortNumber=%02x ComponentID=%02x EltType=%s\n",
618     BITS(esd, 24, 8),
619     BITS(esd, 16, 8),
620     TABLE(elt_types, BITS(esd, 0, 8), buf));
621 
622   for (i=0; i<num_links; i++)
623     {
624       int pos = where + PCI_RCLINK_LINK1 + i*PCI_RCLINK_LINK_SIZE;
625       u32 desc;
626       u32 addr_lo, addr_hi;
627 
628       printf("\t\tLink%d:\t", i);
629       if (!config_fetch(d, pos, PCI_RCLINK_LINK_SIZE))
630 	{
631 	  printf("<unreadable>\n");
632 	  return;
633 	}
634       desc = get_conf_long(d, pos + PCI_RCLINK_LINK_DESC);
635       addr_lo = get_conf_long(d, pos + PCI_RCLINK_LINK_ADDR);
636       addr_hi = get_conf_long(d, pos + PCI_RCLINK_LINK_ADDR + 4);
637 
638       printf("Desc:\tTargetPort=%02x TargetComponent=%02x AssocRCRB%c LinkType=%s LinkValid%c\n",
639 	BITS(desc, 24, 8),
640 	BITS(desc, 16, 8),
641 	FLAG(desc, 4),
642 	((desc & 2) ? "Config" : "MemMapped"),
643 	FLAG(desc, 1));
644 
645       if (desc & 2)
646 	{
647 	  int n = addr_lo & 7;
648 	  if (!n)
649 	    n = 8;
650 	  printf("\t\t\tAddr:\t%02x:%02x.%d  CfgSpace=%08x%08x\n",
651 	    BITS(addr_lo, 20, n),
652 	    BITS(addr_lo, 15, 5),
653 	    BITS(addr_lo, 12, 3),
654 	    addr_hi, addr_lo);
655 	}
656       else
657 	printf("\t\t\tAddr:\t%08x%08x\n", addr_hi, addr_lo);
658     }
659 }
660 
661 static void
cap_rcec(struct device * d,int where)662 cap_rcec(struct device *d, int where)
663 {
664   printf("Root Complex Event Collector Endpoint Association\n");
665   if (verbose < 2)
666     return;
667 
668   if (!config_fetch(d, where, 12))
669     return;
670 
671   u32 hdr = get_conf_long(d, where);
672   byte cap_ver = PCI_RCEC_EP_CAP_VER(hdr);
673   u32 bmap = get_conf_long(d, where + PCI_RCEC_RCIEP_BMAP);
674   printf("\t\tRCiEPBitmap: ");
675   if (bmap)
676     {
677       int prevmatched=0;
678       int adjcount=0;
679       int prevdev=0;
680       printf("RCiEP at Device(s):");
681       for (int dev=0; dev < 32; dev++)
682         {
683 	  if (BITS(bmap, dev, 1))
684 	    {
685 	      if (!adjcount)
686 	        printf("%s %u", (prevmatched) ? "," : "", dev);
687 	      adjcount++;
688 	      prevdev=dev;
689 	      prevmatched=1;
690             }
691 	  else
692 	    {
693 	      if (adjcount > 1)
694 	        printf("-%u", prevdev);
695 	      adjcount=0;
696             }
697         }
698    }
699   else
700     printf("%s", (verbose > 2) ? "00000000 [none]" : "[none]");
701   printf("\n");
702 
703   if (cap_ver < PCI_RCEC_BUSN_REG_VER)
704     return;
705 
706   u32 busn = get_conf_long(d, where + PCI_RCEC_BUSN_REG);
707   u8 lastbusn = BITS(busn, 16, 8);
708   u8 nextbusn = BITS(busn, 8, 8);
709 
710   if ((lastbusn == 0x00) && (nextbusn == 0xff))
711     printf("\t\tAssociatedBusNumbers: %s\n", (verbose > 2) ? "ff-00 [none]" : "[none]");
712   else
713     printf("\t\tAssociatedBusNumbers: %02x-%02x\n", nextbusn, lastbusn );
714 }
715 
716 static void
cap_lmr(struct device * d,int where)717 cap_lmr(struct device *d, int where)
718 {
719   printf("Lane Margining at the Receiver\n");
720 
721   if (verbose < 2)
722     return;
723 
724   if (!config_fetch(d, where, 8))
725     return;
726 
727   u16 port_caps = get_conf_word(d, where + PCI_LMR_CAPS);
728   u16 port_status = get_conf_word(d, where + PCI_LMR_PORT_STS);
729 
730   printf("\t\tPortCap: Uses Driver%c\n", FLAG(port_caps, PCI_LMR_CAPS_DRVR));
731   printf("\t\tPortSta: MargReady%c MargSoftReady%c\n",
732          FLAG(port_status, PCI_LMR_PORT_STS_READY),
733          FLAG(port_status, PCI_LMR_PORT_STS_SOFT_READY));
734 }
735 
736 static void
cap_phy_16gt(struct device * d,int where)737 cap_phy_16gt(struct device *d, int where)
738 {
739   printf("Physical Layer 16.0 GT/s\n");
740 
741   if (verbose < 2)
742     return;
743 
744   if (!config_fetch(d, where + PCI_16GT_CAP, 0x18)) {
745     printf("\t\t<unreadable>\n");
746     return;
747   }
748 
749   u32 status = get_conf_long(d, where + PCI_16GT_STATUS);
750 
751   printf("\t\tPhy16Sta: EquComplete%c EquPhase1%c EquPhase2%c EquPhase3%c LinkEquRequest%c\n",
752          FLAG(status, PCI_16GT_STATUS_EQU_COMP),
753          FLAG(status, PCI_16GT_STATUS_EQU_PHASE1),
754          FLAG(status, PCI_16GT_STATUS_EQU_PHASE2),
755          FLAG(status, PCI_16GT_STATUS_EQU_PHASE3),
756          FLAG(status, PCI_16GT_STATUS_EQU_REQ));
757 }
758 
759 static void
cap_phy_32gt(struct device * d,int where)760 cap_phy_32gt(struct device *d, int where)
761 {
762   static const char * const mod_ts_modes[] = {
763     "PCI Express",
764     "Training Set Messages",
765     "Alternate Protocol Negotiation"
766   };
767   static const char * const enh_link_ctl[] = {
768     "Full Equalization required",
769     "Equalization bypass to highest rate support",
770     "No Equalization Needed",
771     "Modified TS1/TS2 Ordered Sets supported"
772   };
773   char buf[48];
774 
775   printf("Physical Layer 32.0 GT/s\n");
776 
777   if (verbose < 2)
778     return;
779 
780   if (!config_fetch(d, where + PCI_32GT_CAP, 0x1C)) {
781     printf("\t\t<unreadable>\n");
782     return;
783   }
784 
785   u32 cap = get_conf_long(d, where + PCI_32GT_CAP);
786   u32 ctl = get_conf_long(d, where + PCI_32GT_CTL);
787   u32 status = get_conf_long(d, where + PCI_32GT_STATUS);
788 
789   printf("\t\tPhy32Cap: EqualizationBypass%c NoEqualizationNeeded%c\n"
790          "\t\t\t  ModTsMode0%c ModTsMode1%c ModTsMode2%c\n",
791          FLAG(cap, PCI_32GT_CAP_EQU_BYPASS),
792          FLAG(cap, PCI_32GT_CAP_NO_EQU_NEEDED),
793          FLAG(cap, PCI_32GT_CAP_MOD_TS_MODE_0),
794          FLAG(cap, PCI_32GT_CAP_MOD_TS_MODE_1),
795          FLAG(cap, PCI_32GT_CAP_MOD_TS_MODE_2));
796 
797   printf("\t\tPhy32Ctl: EqualizationBypassDis%c NoEqualizationNeededDis%c\n"
798          "\t\t\t  Modified TS Usage Mode: %s\n",
799          FLAG(ctl, PCI_32GT_CTL_EQU_BYPASS_DIS),
800          FLAG(ctl, PCI_32GT_CTL_NO_EQU_NEEDED_DIS),
801          TABLE(mod_ts_modes, PCI_32GT_CTL_MOD_TS_MODE(ctl), buf));
802 
803   printf("\t\tPhy32Sta: EquComplete%c EquPhase1%c EquPhase2%c EquPhase3%c LinkEquRequest%c\n"
804          "\t\t\t  Received Enhanced Link Behavior Control: %s\n"
805          "\t\t\t  ModTsRecv%c TxPrecodeOn%c TxPrecodeReq%c NoEqualizationNeededRecv%c\n",
806          FLAG(status, PCI_32GT_STATUS_EQU_COMP),
807          FLAG(status, PCI_32GT_STATUS_EQU_PHASE1),
808          FLAG(status, PCI_32GT_STATUS_EQU_PHASE2),
809          FLAG(status, PCI_32GT_STATUS_EQU_PHASE3),
810          FLAG(status, PCI_32GT_STATUS_EQU_REQ),
811          TABLE(enh_link_ctl, PCI_32GT_STATUS_RCV_ENH_LINK(status), buf),
812          FLAG(status, PCI_32GT_STATUS_MOD_TS),
813          FLAG(status, PCI_32GT_STATUS_TX_PRE_ON),
814          FLAG(status, PCI_32GT_STATUS_TX_PRE_REQ),
815          FLAG(status, PCI_32GT_STATUS_NO_EQU));
816 }
817 
818 static void
cap_phy_64gt(struct device * d,int where)819 cap_phy_64gt(struct device *d, int where)
820 {
821   printf("Physical Layer 64.0 GT/s\n");
822 
823   if (verbose < 2)
824     return;
825 
826   if (!config_fetch(d, where + PCI_64GT_CAP, 0x0C)) {
827     printf("\t\t<unreadable>\n");
828     return;
829   }
830 
831   u32 status = get_conf_long(d, where + PCI_64GT_STATUS);
832 
833   printf("\t\tPhy64Sta: EquComplete%c EquPhase1%c EquPhase2%c EquPhase3%c LinkEquRequest%c\n"
834          "\t\t\t  TxPrecodeOn%c TxPrecodeReq%c NoEqualizationNeededRecv%c\n",
835          FLAG(status, PCI_64GT_STATUS_EQU_COMP),
836          FLAG(status, PCI_64GT_STATUS_EQU_PHASE1),
837          FLAG(status, PCI_64GT_STATUS_EQU_PHASE2),
838          FLAG(status, PCI_64GT_STATUS_EQU_PHASE3),
839          FLAG(status, PCI_64GT_STATUS_EQU_REQ),
840          FLAG(status, PCI_64GT_STATUS_TX_PRE_ON),
841          FLAG(status, PCI_64GT_STATUS_TX_PRE_REQ),
842          FLAG(status, PCI_64GT_STATUS_NO_EQU));
843 }
844 
845 static void
cxl_range(u64 base,u64 size,int n)846 cxl_range(u64 base, u64 size, int n)
847 {
848   u32 interleave[] = { 0, 256, 4096, 512, 1024, 2048, 8192, 16384 };
849   const char * const type[] = { "Volatile", "Non-volatile", "CDAT" };
850   const char * const class[] = { "DRAM", "Storage", "CDAT" };
851   u16 w;
852 
853   w = (u16) size;
854 
855   size &= ~0x0fffffffULL;
856 
857   printf("\t\tRange%d: %016"PCI_U64_FMT_X"-%016"PCI_U64_FMT_X" [size=0x%"PCI_U64_FMT_X"]\n", n, base, base + size - 1, size);
858   printf("\t\t\tValid%c Active%c Type=%s Class=%s interleave=%d timeout=%ds\n",
859     FLAG(w, PCI_CXL_RANGE_VALID), FLAG(w, PCI_CXL_RANGE_ACTIVE),
860     type[PCI_CXL_RANGE_TYPE(w)], class[PCI_CXL_RANGE_CLASS(w)],
861     interleave[PCI_CXL_RANGE_INTERLEAVE(w)],
862     1 << (PCI_CXL_RANGE_TIMEOUT(w) * 2));
863 }
864 
865 static void
dvsec_cxl_device(struct device * d,int rev,int where,int len)866 dvsec_cxl_device(struct device *d, int rev, int where, int len)
867 {
868   u32 cache_size, cache_unit_size;
869   u64 range_base, range_size;
870   u16 w;
871 
872   /* Legacy 1.1 revs aren't handled */
873   if (rev == 0)
874     return;
875 
876   if (rev >= 1 && len >= PCI_CXL_DEV_LEN)
877     {
878       w = get_conf_word(d, where + PCI_CXL_DEV_CAP);
879       printf("\t\tCXLCap:\tCache%c IO%c Mem%c MemHWInit%c HDMCount %d Viral%c\n",
880 	FLAG(w, PCI_CXL_DEV_CAP_CACHE), FLAG(w, PCI_CXL_DEV_CAP_IO), FLAG(w, PCI_CXL_DEV_CAP_MEM),
881 	FLAG(w, PCI_CXL_DEV_CAP_MEM_HWINIT), PCI_CXL_DEV_CAP_HDM_CNT(w), FLAG(w, PCI_CXL_DEV_CAP_VIRAL));
882 
883       w = get_conf_word(d, where + PCI_CXL_DEV_CTRL);
884       printf("\t\tCXLCtl:\tCache%c IO%c Mem%c CacheSFCov %d CacheSFGran %d CacheClean%c Viral%c\n",
885 	FLAG(w, PCI_CXL_DEV_CTRL_CACHE), FLAG(w, PCI_CXL_DEV_CTRL_IO), FLAG(w, PCI_CXL_DEV_CTRL_MEM),
886 	PCI_CXL_DEV_CTRL_CACHE_SF_COV(w), PCI_CXL_DEV_CTRL_CACHE_SF_GRAN(w), FLAG(w, PCI_CXL_DEV_CTRL_CACHE_CLN),
887 	FLAG(w, PCI_CXL_DEV_CTRL_VIRAL));
888 
889       w = get_conf_word(d, where + PCI_CXL_DEV_STATUS);
890       printf("\t\tCXLSta:\tViral%c\n", FLAG(w, PCI_CXL_DEV_STATUS_VIRAL));
891 
892       w = get_conf_word(d, where + PCI_CXL_DEV_CTRL2);
893       printf("\t\tCXLCtl2:\tDisableCaching%c InitCacheWB&Inval%c InitRst%c RstMemClrEn%c",
894 	FLAG(w, PCI_CXL_DEV_CTRL2_DISABLE_CACHING),
895 	FLAG(w, PCI_CXL_DEV_CTRL2_INIT_WB_INVAL),
896 	FLAG(w, PCI_CXL_DEV_CTRL2_INIT_CXL_RST),
897 	FLAG(w, PCI_CXL_DEV_CTRL2_INIT_CXL_RST_CLR_EN));
898       if (rev >= 2)
899 	  printf(" DesiredVolatileHDMStateAfterHotReset%c", FLAG(w, PCI_CXL_DEV_CTRL2_INIT_CXL_HDM_STATE_HOTRST));
900       printf("\n");
901 
902       w = get_conf_word(d, where + PCI_CXL_DEV_STATUS2);
903       printf("\t\tCXLSta2:\tResetComplete%c ResetError%c PMComplete%c\n",
904 	FLAG(w, PCI_CXL_DEV_STATUS_RC), FLAG(w,PCI_CXL_DEV_STATUS_RE), FLAG(w, PCI_CXL_DEV_STATUS_PMC));
905 
906       w = get_conf_word(d, where + PCI_CXL_DEV_CAP2);
907       printf("\t\tCXLCap2:\t");
908       cache_unit_size = BITS(w, 0, 4);
909       cache_size = BITS(w, 8, 8);
910       switch (cache_unit_size)
911 	{
912 	case PCI_CXL_DEV_CAP2_CACHE_1M:
913 	  printf("Cache Size: %08x\n", cache_size * (1<<20));
914 	  break;
915 	case PCI_CXL_DEV_CAP2_CACHE_64K:
916 	  printf("Cache Size: %08x\n", cache_size * (64<<10));
917 	  break;
918 	case PCI_CXL_DEV_CAP2_CACHE_UNK:
919 	  printf("Cache Size Not Reported\n");
920 	  break;
921 	default:
922 	  printf("Cache Size: %d of unknown unit size (%d)\n", cache_size, cache_unit_size);
923 	  break;
924 	}
925 
926       range_size = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE1_SIZE_HI) << 32;
927       range_size |= get_conf_long(d, where + PCI_CXL_DEV_RANGE1_SIZE_LO);
928       range_base = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE1_BASE_HI) << 32;
929       range_base |= get_conf_long(d, where + PCI_CXL_DEV_RANGE1_BASE_LO);
930       cxl_range(range_base, range_size, 1);
931 
932       range_size = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE2_SIZE_HI) << 32;
933       range_size |= get_conf_long(d, where + PCI_CXL_DEV_RANGE2_SIZE_LO);
934       range_base = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE2_BASE_HI) << 32;
935       range_base |= get_conf_long(d, where + PCI_CXL_DEV_RANGE2_BASE_LO);
936       cxl_range(range_base, range_size, 2);
937     }
938 
939   if (rev >= 2 && len >= PCI_CXL_DEV_LEN_REV2)
940     {
941       w = get_conf_word(d, where + PCI_CXL_DEV_CAP3);
942       printf("\t\tCXLCap3:\tDefaultVolatile HDM State After:\tColdReset%c WarmReset%c HotReset%c HotResetConfigurability%c\n",
943 	FLAG(w, PCI_CXL_DEV_CAP3_HDM_STATE_RST_COLD),
944 	FLAG(w, PCI_CXL_DEV_CAP3_HDM_STATE_RST_WARM),
945 	FLAG(w, PCI_CXL_DEV_CAP3_HDM_STATE_RST_HOT),
946 	FLAG(w, PCI_CXL_DEV_CAP3_HDM_STATE_RST_HOT_CFG));
947     }
948 
949   // Unparsed data
950   if (len > PCI_CXL_DEV_LEN_REV2)
951     printf("\t\t<?>\n");
952 }
953 
954 static void
dvsec_cxl_port(struct device * d,int where,int len)955 dvsec_cxl_port(struct device *d, int where, int len)
956 {
957   u16 w, m1, m2;
958   u8 b1, b2;
959 
960   if (len < PCI_CXL_PORT_EXT_LEN)
961     return;
962 
963   w = get_conf_word(d, where + PCI_CXL_PORT_EXT_STATUS);
964   printf("\t\tCXLPortSta:\tPMComplete%c\n", FLAG(w, PCI_CXL_PORT_EXT_STATUS));
965 
966   w = get_conf_word(d, where + PCI_CXL_PORT_CTRL);
967   printf("\t\tCXLPortCtl:\tUnmaskSBR%c UnmaskLinkDisable%c AltMem%c AltBME%c ViralEnable%c\n",
968     FLAG(w, PCI_CXL_PORT_UNMASK_SBR), FLAG(w, PCI_CXL_PORT_UNMASK_LINK),
969     FLAG(w, PCI_CXL_PORT_ALT_MEMORY), FLAG(w, PCI_CXL_PORT_ALT_BME),
970     FLAG(w, PCI_CXL_PORT_VIRAL_EN));
971 
972   b1 = get_conf_byte(d, where + PCI_CXL_PORT_ALT_BUS_BASE);
973   b2 = get_conf_byte(d, where + PCI_CXL_PORT_ALT_BUS_LIMIT);
974   printf("\t\tAlternateBus:\t%02x-%02x\n", b1, b2);
975   m1 = get_conf_word(d, where + PCI_CXL_PORT_ALT_MEM_BASE);
976   m2 = get_conf_word(d, where + PCI_CXL_PORT_ALT_MEM_LIMIT);
977   printf("\t\tAlternateBus:\t%04x-%04x\n", m1, m2);
978 }
979 
980 static void
dvsec_cxl_register_locator(struct device * d,int where,int len)981 dvsec_cxl_register_locator(struct device *d, int where, int len)
982 {
983   static const char * const id_names[] = {
984     "empty",
985     "component registers",
986     "BAR virtualization",
987     "CXL device registers",
988     "CPMU registers",
989   };
990 
991   for (int i=0; ; i++)
992     {
993       int pos = where + PCI_CXL_RL_BLOCK1_LO + 8*i;
994       if (pos + 7 >= where + len)
995 	break;
996 
997       u32 lo = get_conf_long(d, pos);
998       u32 hi = get_conf_long(d, pos + 4);
999 
1000       unsigned int bir = BITS(lo, 0, 3);
1001       unsigned int block_id = BITS(lo, 8, 8);
1002       u64 base = (BITS(lo, 16, 16) << 16) | ((u64) hi << 32);
1003 
1004       if (!block_id)
1005 	continue;
1006 
1007       const char *id_name;
1008       if (block_id < sizeof(id_names) / sizeof(*id_names))
1009 	id_name = id_names[block_id];
1010       else if (block_id == 0xff)
1011 	id_name = "vendor-specific";
1012       else
1013 	id_name = "<?>";
1014 
1015       printf("\t\tBlock%d: BIR: bar%d, ID: %s, offset: %016" PCI_U64_FMT_X "\n", i + 1, bir, id_name, base);
1016     }
1017 }
1018 
1019 static void
dvsec_cxl_gpf_device(struct device * d,int where)1020 dvsec_cxl_gpf_device(struct device *d, int where)
1021 {
1022   u32 l;
1023   u16 w, duration;
1024   u8 time_base, time_scale;
1025 
1026   w = get_conf_word(d, where + PCI_CXL_GPF_DEV_PHASE2_DUR);
1027   time_base = BITS(w, 0, 4);
1028   time_scale = BITS(w, 8, 4);
1029 
1030   switch (time_scale)
1031     {
1032       case PCI_CXL_GPF_DEV_100US:
1033       case PCI_CXL_GPF_DEV_100MS:
1034         duration = time_base * 100;
1035         break;
1036       case PCI_CXL_GPF_DEV_10US:
1037       case PCI_CXL_GPF_DEV_10MS:
1038       case PCI_CXL_GPF_DEV_10S:
1039         duration = time_base * 10;
1040         break;
1041       case PCI_CXL_GPF_DEV_1US:
1042       case PCI_CXL_GPF_DEV_1MS:
1043       case PCI_CXL_GPF_DEV_1S:
1044         duration = time_base;
1045         break;
1046       default:
1047         /* Reserved */
1048         printf("\t\tReserved time scale encoding %x\n", time_scale);
1049         duration = time_base;
1050     }
1051 
1052   printf("\t\tGPF Phase 2 Duration: %u%s\n", duration,
1053       (time_scale < PCI_CXL_GPF_DEV_1MS) ? "us":
1054       (time_scale < PCI_CXL_GPF_DEV_1S) ? "ms" :
1055       (time_scale <= PCI_CXL_GPF_DEV_10S) ? "s" : "<?>");
1056 
1057   l = get_conf_long(d, where + PCI_CXL_GPF_DEV_PHASE2_POW);
1058   printf("\t\tGPF Phase 2 Power: %umW\n", (unsigned int)l);
1059 }
1060 
1061 static void
dvsec_cxl_gpf_port(struct device * d,int where)1062 dvsec_cxl_gpf_port(struct device *d, int where)
1063 {
1064   u16 w, timeout;
1065   u8 time_base, time_scale;
1066 
1067   w = get_conf_word(d, where + PCI_CXL_GPF_PORT_PHASE1_CTRL);
1068   time_base = BITS(w, 0, 4);
1069   time_scale = BITS(w, 8, 4);
1070 
1071   switch (time_scale)
1072     {
1073       case PCI_CXL_GPF_PORT_100US:
1074       case PCI_CXL_GPF_PORT_100MS:
1075         timeout = time_base * 100;
1076         break;
1077       case PCI_CXL_GPF_PORT_10US:
1078       case PCI_CXL_GPF_PORT_10MS:
1079       case PCI_CXL_GPF_PORT_10S:
1080         timeout = time_base * 10;
1081         break;
1082       case PCI_CXL_GPF_PORT_1US:
1083       case PCI_CXL_GPF_PORT_1MS:
1084       case PCI_CXL_GPF_PORT_1S:
1085         timeout = time_base;
1086         break;
1087       default:
1088         /* Reserved */
1089         printf("\t\tReserved time scale encoding %x\n", time_scale);
1090         timeout = time_base;
1091     }
1092 
1093   printf("\t\tGPF Phase 1 Timeout: %d%s\n", timeout,
1094       (time_scale < PCI_CXL_GPF_PORT_1MS) ? "us":
1095       (time_scale < PCI_CXL_GPF_PORT_1S) ? "ms" :
1096       (time_scale <= PCI_CXL_GPF_PORT_10S) ? "s" : "<?>");
1097 
1098   w = get_conf_word(d, where + PCI_CXL_GPF_PORT_PHASE2_CTRL);
1099   time_base = BITS(w, 0, 4);
1100   time_scale = BITS(w, 8, 4);
1101 
1102   switch (time_scale)
1103     {
1104       case PCI_CXL_GPF_PORT_100US:
1105       case PCI_CXL_GPF_PORT_100MS:
1106         timeout = time_base * 100;
1107         break;
1108       case PCI_CXL_GPF_PORT_10US:
1109       case PCI_CXL_GPF_PORT_10MS:
1110       case PCI_CXL_GPF_PORT_10S:
1111         timeout = time_base * 10;
1112         break;
1113       case PCI_CXL_GPF_PORT_1US:
1114       case PCI_CXL_GPF_PORT_1MS:
1115       case PCI_CXL_GPF_PORT_1S:
1116         timeout = time_base;
1117         break;
1118       default:
1119         /* Reserved */
1120         printf("\t\tReserved time scale encoding %x\n", time_scale);
1121         timeout = time_base;
1122     }
1123 
1124   printf("\t\tGPF Phase 2 Timeout: %d%s\n", timeout,
1125       (time_scale < PCI_CXL_GPF_PORT_1MS) ? "us":
1126       (time_scale < PCI_CXL_GPF_PORT_1S) ? "ms" :
1127       (time_scale <= PCI_CXL_GPF_PORT_10S) ? "s" : "<?>");
1128 }
1129 
1130 static void
dvsec_cxl_flex_bus(struct device * d,int where,int rev,int len)1131 dvsec_cxl_flex_bus(struct device *d, int where, int rev, int len)
1132 {
1133   u16 w;
1134   u32 l, data;
1135 
1136   // Sanity check: Does the length correspond to its revision?
1137   switch (rev) {
1138     case 0:
1139       if (len != PCI_CXL_FB_MOD_TS_DATA)
1140         printf("\t\t<Wrong length for Revision %d>\n", rev);
1141       break;
1142     case 1:
1143       if (len != PCI_CXL_FB_PORT_CAP2)
1144         printf("\t\t<Wrong length for Revision %d>\n", rev);
1145       break;
1146     case 2:
1147       if (len != PCI_CXL_FB_NEXT_UNSUPPORTED)
1148         printf("\t\t<Wrong length for Revision %d>\n", rev);
1149       break;
1150     default:
1151       break;
1152   }
1153 
1154   // From Rev 0
1155   w = get_conf_word(d, where + PCI_CXL_FB_PORT_CAP);
1156   printf("\t\tFBCap:\tCache%c IO%c Mem%c 68BFlit%c MltLogDev%c",
1157       FLAG(w, PCI_CXL_FB_CAP_CACHE), FLAG(w, PCI_CXL_FB_CAP_IO),
1158       FLAG(w, PCI_CXL_FB_CAP_MEM), FLAG(w, PCI_CXL_FB_CAP_68B_FLIT),
1159       FLAG(w, PCI_CXL_FB_CAP_MULT_LOG_DEV));
1160 
1161   if (rev > 1)
1162     printf(" 256BFlit%c PBRFlit%c",
1163         FLAG(w, PCI_CXL_FB_CAP_256B_FLIT), FLAG(w, PCI_CXL_FB_CAP_PBR_FLIT));
1164 
1165   w = get_conf_word(d, where + PCI_CXL_FB_PORT_CTRL);
1166   printf("\n\t\tFBCtl:\tCache%c IO%c Mem%c SynHdrByp%c DrftBuf%c 68BFlit%c MltLogDev%c RCD%c Retimer1%c Retimer2%c",
1167       FLAG(w, PCI_CXL_FB_CTRL_CACHE), FLAG(w, PCI_CXL_FB_CTRL_IO),
1168       FLAG(w, PCI_CXL_FB_CTRL_MEM), FLAG(w, PCI_CXL_FB_CTRL_SYNC_HDR_BYP),
1169       FLAG(w, PCI_CXL_FB_CTRL_DRFT_BUF), FLAG(w, PCI_CXL_FB_CTRL_68B_FLIT),
1170       FLAG(w, PCI_CXL_FB_CTRL_MULT_LOG_DEV), FLAG(w, PCI_CXL_FB_CTRL_RCD),
1171       FLAG(w, PCI_CXL_FB_CTRL_RETIMER1), FLAG(w, PCI_CXL_FB_CTRL_RETIMER2));
1172 
1173   if (rev > 1)
1174     printf(" 256BFlit%c PBRFlit%c",
1175         FLAG(w, PCI_CXL_FB_CTRL_256B_FLIT), FLAG(w, PCI_CXL_FB_CTRL_PBR_FLIT));
1176 
1177   w = get_conf_word(d, where + PCI_CXL_FB_PORT_STATUS);
1178   printf("\n\t\tFBSta:\tCache%c IO%c Mem%c SynHdrByp%c DrftBuf%c 68BFlit%c MltLogDev%c",
1179       FLAG(w, PCI_CXL_FB_STAT_CACHE), FLAG(w, PCI_CXL_FB_STAT_IO),
1180       FLAG(w, PCI_CXL_FB_STAT_MEM), FLAG(w, PCI_CXL_FB_STAT_SYNC_HDR_BYP),
1181       FLAG(w, PCI_CXL_FB_STAT_DRFT_BUF), FLAG(w, PCI_CXL_FB_STAT_68B_FLIT),
1182       FLAG(w, PCI_CXL_FB_STAT_MULT_LOG_DEV));
1183 
1184   if (rev > 1)
1185     printf(" 256BFlit%c PBRFlit%c",
1186         FLAG(w, PCI_CXL_FB_STAT_256B_FLIT), FLAG(w, PCI_CXL_FB_STAT_PBR_FLIT));
1187   printf("\n");
1188 
1189   // From Rev 1
1190   if (rev >= 1)
1191     {
1192       l = get_conf_long(d, where + PCI_CXL_FB_MOD_TS_DATA);
1193       data = BITS(l, 0, 24);
1194       printf("\t\tFBModTS:\tReceived FB Data: %06x\n", (unsigned int)data);
1195     }
1196 
1197   // From Rev 2
1198   if (rev >= 2)
1199     {
1200       u8 nop;
1201 
1202       l = get_conf_long(d, where + PCI_CXL_FB_PORT_CAP2);
1203       printf("\t\tFBCap2:\tNOPHint%c\n", FLAG(l, PCI_CXL_FB_CAP2_NOP_HINT));
1204 
1205       l = get_conf_long(d, where + PCI_CXL_FB_PORT_CTRL2);
1206       printf("\t\tFBCtl2:\tNOPHint%c\n", FLAG(l, PCI_CXL_FB_CTRL2_NOP_HINT));
1207 
1208       l = get_conf_long(d, where + PCI_CXL_FB_PORT_STATUS2);
1209       nop = BITS(l, 0, 2);
1210       printf("\t\tFBSta2:\tNOPHintInfo: %x\n", nop);
1211     }
1212 
1213   // Unparsed data
1214   if (len > PCI_CXL_FB_LEN)
1215     printf("\t\t<?>\n");
1216 }
1217 
1218 static void
dvsec_cxl_mld(struct device * d,int where)1219 dvsec_cxl_mld(struct device *d, int where)
1220 {
1221   u16 w;
1222 
1223   w = get_conf_word(d, where + PCI_CXL_MLD_NUM_LD);
1224 
1225   /* Encodings greater than 16 are reserved */
1226   if (w && w <= PCI_CXL_MLD_MAX_LD)
1227     printf("\t\tNumLogDevs: %d\n", w);
1228 }
1229 
1230 static void
dvsec_cxl_function_map(struct device * d,int where)1231 dvsec_cxl_function_map(struct device *d, int where)
1232 {
1233 
1234   printf("\t\tFuncMap 0: %08x\n",
1235       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_0)));
1236 
1237   printf("\t\tFuncMap 1: %08x\n",
1238     (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_1)));
1239 
1240   printf("\t\tFuncMap 2: %08x\n",
1241     (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_2)));
1242 
1243   printf("\t\tFuncMap 3: %08x\n",
1244       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_3)));
1245 
1246   printf("\t\tFuncMap 4: %08x\n",
1247       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_4)));
1248 
1249   printf("\t\tFuncMap 5: %08x\n",
1250       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_5)));
1251 
1252   printf("\t\tFuncMap 6: %08x\n",
1253       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_6)));
1254 
1255   printf("\t\tFuncMap 7: %08x\n",
1256       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_7)));
1257 }
1258 
1259 static void
cap_dvsec_cxl(struct device * d,int id,int rev,int where,int len)1260 cap_dvsec_cxl(struct device *d, int id, int rev, int where, int len)
1261 {
1262   printf(": CXL\n");
1263   if (verbose < 2)
1264     return;
1265 
1266   if (!config_fetch(d, where, len))
1267     return;
1268 
1269   switch (id)
1270     {
1271     case 0:
1272       printf("\t\tPCIe DVSEC for CXL Devices\n");
1273       dvsec_cxl_device(d, rev, where, len);
1274       break;
1275     case 2:
1276       printf("\t\tNon-CXL Function Map DVSEC\n");
1277       dvsec_cxl_function_map(d, where);
1278       break;
1279     case 3:
1280       printf("\t\tCXL Extensions DVSEC for Ports\n");
1281       dvsec_cxl_port(d, where, len);
1282       break;
1283     case 4:
1284       printf("\t\tGPF DVSEC for CXL Ports\n");
1285       dvsec_cxl_gpf_port(d, where);
1286       break;
1287     case 5:
1288       printf("\t\tGPF DVSEC for CXL Devices\n");
1289       dvsec_cxl_gpf_device(d, where);
1290       break;
1291     case 7:
1292       printf("\t\tPCIe DVSEC for Flex Bus Port\n");
1293       dvsec_cxl_flex_bus(d, where, rev, len);
1294       break;
1295     case 8:
1296       printf("\t\tRegister Locator DVSEC\n");
1297       dvsec_cxl_register_locator(d, where, len);
1298       break;
1299     case 9:
1300       printf("\t\tMLD DVSEC\n");
1301       dvsec_cxl_mld(d, where);
1302       break;
1303     case 0xa:
1304       printf("\t\tPCIe DVSEC for Test Capability <?>\n");
1305       break;
1306     default:
1307       printf("\t\tUnknown ID %04x\n", id);
1308     }
1309 }
1310 
1311 static void
cap_dvsec(struct device * d,int where)1312 cap_dvsec(struct device *d, int where)
1313 {
1314   printf("Designated Vendor-Specific: ");
1315   if (!config_fetch(d, where + PCI_DVSEC_HEADER1, 8))
1316     {
1317       printf("<unreadable>\n");
1318       return;
1319     }
1320 
1321   u32 hdr = get_conf_long(d, where + PCI_DVSEC_HEADER1);
1322   u16 vendor = BITS(hdr, 0, 16);
1323   byte rev = BITS(hdr, 16, 4);
1324   u16 len = BITS(hdr, 20, 12);
1325 
1326   u16 id = get_conf_long(d, where + PCI_DVSEC_HEADER2);
1327 
1328   printf("Vendor=%04x ID=%04x Rev=%d Len=%d", vendor, id, rev, len);
1329   if (vendor == PCI_DVSEC_VENDOR_ID_CXL && len >= 16)
1330     cap_dvsec_cxl(d, id, rev, where, len);
1331   else
1332     printf(" <?>\n");
1333 }
1334 
1335 static void
cap_evendor(struct device * d,int where)1336 cap_evendor(struct device *d, int where)
1337 {
1338   u32 hdr;
1339 
1340   printf("Vendor Specific Information: ");
1341   if (!config_fetch(d, where + PCI_EVNDR_HEADER, 4))
1342     {
1343       printf("<unreadable>\n");
1344       return;
1345     }
1346 
1347   hdr = get_conf_long(d, where + PCI_EVNDR_HEADER);
1348   printf("ID=%04x Rev=%d Len=%03x <?>\n",
1349     BITS(hdr, 0, 16),
1350     BITS(hdr, 16, 4),
1351     BITS(hdr, 20, 12));
1352 }
1353 
l1pm_calc_pwron(int scale,int value)1354 static int l1pm_calc_pwron(int scale, int value)
1355 {
1356   switch (scale)
1357     {
1358       case 0:
1359 	return 2 * value;
1360       case 1:
1361 	return 10 * value;
1362       case 2:
1363 	return 100 * value;
1364     }
1365   return -1;
1366 }
1367 
1368 static void
cap_l1pm(struct device * d,int where)1369 cap_l1pm(struct device *d, int where)
1370 {
1371   u32 l1_cap, val, scale;
1372   int time;
1373 
1374   printf("L1 PM Substates\n");
1375 
1376   if (verbose < 2)
1377     return;
1378 
1379   if (!config_fetch(d, where + PCI_L1PM_SUBSTAT_CAP, 12))
1380     {
1381       printf("\t\t<unreadable>\n");
1382       return;
1383     }
1384 
1385   l1_cap = get_conf_long(d, where + PCI_L1PM_SUBSTAT_CAP);
1386   printf("\t\tL1SubCap: ");
1387   printf("PCI-PM_L1.2%c PCI-PM_L1.1%c ASPM_L1.2%c ASPM_L1.1%c L1_PM_Substates%c\n",
1388     FLAG(l1_cap, PCI_L1PM_SUBSTAT_CAP_PM_L12),
1389     FLAG(l1_cap, PCI_L1PM_SUBSTAT_CAP_PM_L11),
1390     FLAG(l1_cap, PCI_L1PM_SUBSTAT_CAP_ASPM_L12),
1391     FLAG(l1_cap, PCI_L1PM_SUBSTAT_CAP_ASPM_L11),
1392     FLAG(l1_cap, PCI_L1PM_SUBSTAT_CAP_L1PM_SUPP));
1393 
1394   if (l1_cap & PCI_L1PM_SUBSTAT_CAP_PM_L12 || l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
1395     {
1396       printf("\t\t\t  PortCommonModeRestoreTime=%dus ", BITS(l1_cap, 8, 8));
1397       time = l1pm_calc_pwron(BITS(l1_cap, 16, 2), BITS(l1_cap, 19, 5));
1398       if (time != -1)
1399 	printf("PortTPowerOnTime=%dus\n", time);
1400       else
1401 	printf("PortTPowerOnTime=<error>\n");
1402     }
1403 
1404   val = get_conf_long(d, where + PCI_L1PM_SUBSTAT_CTL1);
1405   printf("\t\tL1SubCtl1: PCI-PM_L1.2%c PCI-PM_L1.1%c ASPM_L1.2%c ASPM_L1.1%c\n",
1406     FLAG(val, PCI_L1PM_SUBSTAT_CTL1_PM_L12),
1407     FLAG(val, PCI_L1PM_SUBSTAT_CTL1_PM_L11),
1408     FLAG(val, PCI_L1PM_SUBSTAT_CTL1_ASPM_L12),
1409     FLAG(val, PCI_L1PM_SUBSTAT_CTL1_ASPM_L11));
1410 
1411   if (l1_cap & PCI_L1PM_SUBSTAT_CAP_PM_L12 || l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
1412     {
1413       printf("\t\t\t   T_CommonMode=%dus", BITS(val, 8, 8));
1414 
1415       if (l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
1416 	{
1417 	  scale = BITS(val, 29, 3);
1418 	  if (scale > 5)
1419 	    printf(" LTR1.2_Threshold=<error>");
1420 	  else
1421 	    printf(" LTR1.2_Threshold=%" PCI_U64_FMT_U "ns", BITS(val, 16, 10) * (u64) cap_ltr_scale(scale));
1422 	}
1423       printf("\n");
1424     }
1425 
1426   val = get_conf_long(d, where + PCI_L1PM_SUBSTAT_CTL2);
1427   printf("\t\tL1SubCtl2:");
1428   if (l1_cap & PCI_L1PM_SUBSTAT_CAP_PM_L12 || l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
1429     {
1430       time = l1pm_calc_pwron(BITS(val, 0, 2), BITS(val, 3, 5));
1431       if (time != -1)
1432 	printf(" T_PwrOn=%dus", time);
1433       else
1434 	printf(" T_PwrOn=<error>");
1435     }
1436   printf("\n");
1437 }
1438 
1439 static void
cap_ptm(struct device * d,int where)1440 cap_ptm(struct device *d, int where)
1441 {
1442   u32 buff;
1443   u16 clock;
1444 
1445   printf("Precision Time Measurement\n");
1446 
1447   if (verbose < 2)
1448     return;
1449 
1450   if (!config_fetch(d, where + 4, 8))
1451     {
1452       printf("\t\t<unreadable>\n");
1453       return;
1454     }
1455 
1456   buff = get_conf_long(d, where + 4);
1457   printf("\t\tPTMCap: ");
1458   printf("Requester%c Responder%c Root%c\n",
1459     FLAG(buff, 0x1),
1460     FLAG(buff, 0x2),
1461     FLAG(buff, 0x4));
1462 
1463   clock = BITS(buff, 8, 8);
1464   printf("\t\tPTMClockGranularity: ");
1465   switch (clock)
1466     {
1467       case 0x00:
1468         printf("Unimplemented\n");
1469         break;
1470       case 0xff:
1471         printf("Greater than 254ns\n");
1472         break;
1473       default:
1474         printf("%huns\n", clock);
1475     }
1476 
1477   buff = get_conf_long(d, where + 8);
1478   printf("\t\tPTMControl: ");
1479   printf("Enabled%c RootSelected%c\n",
1480     FLAG(buff, 0x1),
1481     FLAG(buff, 0x2));
1482 
1483   clock = BITS(buff, 8, 8);
1484   printf("\t\tPTMEffectiveGranularity: ");
1485   switch (clock)
1486     {
1487       case 0x00:
1488         printf("Unknown\n");
1489         break;
1490       case 0xff:
1491         printf("Greater than 254ns\n");
1492         break;
1493       default:
1494         printf("%huns\n", clock);
1495     }
1496 }
1497 
1498 static void
print_rebar_range_size(int ld2_size)1499 print_rebar_range_size(int ld2_size)
1500 {
1501   // This function prints the input as a power-of-2 size value
1502   // It is biased with 1MB = 0, ...
1503   // Maximum resizable BAR value supported is 2^63 bytes = 43
1504   // for the extended resizable BAR capability definition
1505   // (otherwise it would stop at 2^28)
1506 
1507   if (ld2_size >= 0 && ld2_size < 10)
1508     printf(" %dMB", (1 << ld2_size));
1509   else if (ld2_size >= 10 && ld2_size < 20)
1510     printf(" %dGB", (1 << (ld2_size-10)));
1511   else if (ld2_size >= 20 && ld2_size < 30)
1512     printf(" %dTB", (1 << (ld2_size-20)));
1513   else if (ld2_size >= 30 && ld2_size < 40)
1514     printf(" %dPB", (1 << (ld2_size-30)));
1515   else if (ld2_size >= 40 && ld2_size < 44)
1516     printf(" %dEB", (1 << (ld2_size-40)));
1517   else
1518     printf(" <unknown>");
1519 }
1520 
1521 static void
cap_rebar(struct device * d,int where,int virtual)1522 cap_rebar(struct device *d, int where, int virtual)
1523 {
1524   u32 sizes_buffer, control_buffer, ext_sizes, current_size;
1525   u16 bar_index, barcount, i;
1526   // If the structure exists, at least one bar is defined
1527   u16 num_bars = 1;
1528 
1529   printf("%s Resizable BAR\n", (virtual) ? "Virtual" : "Physical");
1530 
1531   if (verbose < 2)
1532     return;
1533 
1534   // Go through all defined BAR definitions of the caps, at minimum 1
1535   // (loop also terminates if num_bars read from caps is > 6)
1536   for (barcount = 0; barcount < num_bars; barcount++)
1537     {
1538       where += 4;
1539 
1540       // Get the next BAR configuration
1541       if (!config_fetch(d, where, 8))
1542         {
1543           printf("\t\t<unreadable>\n");
1544           return;
1545         }
1546 
1547       sizes_buffer = get_conf_long(d, where) >> 4;
1548       where += 4;
1549       control_buffer = get_conf_long(d, where);
1550 
1551       bar_index  = BITS(control_buffer, 0, 3);
1552       current_size = BITS(control_buffer, 8, 6);
1553       ext_sizes = BITS(control_buffer, 16, 16);
1554 
1555       if (barcount == 0)
1556         {
1557           // Only index 0 controlreg has the num_bar count definition
1558           num_bars = BITS(control_buffer, 5, 3);
1559 	  if (num_bars < 1 || num_bars > 6)
1560 	    {
1561 	      printf("\t\t<error in resizable BAR: num_bars=%d is out of specification>\n", num_bars);
1562 	      break;
1563 	    }
1564         }
1565 
1566       // Resizable BAR list entry have an arbitrary index and current size
1567       printf("\t\tBAR %d: current size:", bar_index);
1568       print_rebar_range_size(current_size);
1569 
1570       if (sizes_buffer || ext_sizes)
1571 	{
1572 	  printf(", supported:");
1573 
1574 	  for (i=0; i<28; i++)
1575 	    if (sizes_buffer & (1U << i))
1576 	      print_rebar_range_size(i);
1577 
1578 	  for (i=0; i<16; i++)
1579 	    if (ext_sizes & (1U << i))
1580 	      print_rebar_range_size(i + 28);
1581 	}
1582 
1583       printf("\n");
1584     }
1585 }
1586 
1587 static void
cap_doe(struct device * d,int where)1588 cap_doe(struct device *d, int where)
1589 {
1590   u32 l;
1591 
1592   printf("Data Object Exchange\n");
1593 
1594   if (verbose < 2)
1595     return;
1596 
1597   if (!config_fetch(d, where + PCI_DOE_CAP, 0x14))
1598     {
1599       printf("\t\t<unreadable>\n");
1600       return;
1601     }
1602 
1603   l = get_conf_long(d, where + PCI_DOE_CAP);
1604   printf("\t\tDOECap: IntSup%c\n",
1605 	 FLAG(l, PCI_DOE_CAP_INT_SUPP));
1606   if (l & PCI_DOE_CAP_INT_SUPP)
1607     printf("\t\t\tIntMsgNum %d\n",
1608 	   PCI_DOE_CAP_INT_MSG(l));
1609 
1610   l = get_conf_long(d, where + PCI_DOE_CTL);
1611   printf("\t\tDOECtl: IntEn%c\n",
1612 	 FLAG(l, PCI_DOE_CTL_INT));
1613 
1614   l = get_conf_long(d, where + PCI_DOE_STS);
1615   printf("\t\tDOESta: Busy%c IntSta%c Error%c ObjectReady%c\n",
1616 	 FLAG(l, PCI_DOE_STS_BUSY),
1617 	 FLAG(l, PCI_DOE_STS_INT),
1618 	 FLAG(l, PCI_DOE_STS_ERROR),
1619 	 FLAG(l, PCI_DOE_STS_OBJECT_READY));
1620 }
1621 
offstr(char * buf,u32 off)1622 static const char *offstr(char *buf, u32 off)
1623 {
1624     if (verbose < 3)
1625         return "";
1626 
1627     sprintf(buf, "[%x]", off);
1628     return buf;
1629 }
1630 
ide_alg(char * buf,size_t len,u32 l)1631 static const char *ide_alg(char *buf, size_t len, u32 l)
1632 {
1633     const char *algo[] = { "AES-GCM-256-96b" }; // AES-GCM 256 key size, 96b MAC
1634 
1635     if (l == 0)
1636         snprintf(buf, len, "%s", algo[l]);
1637     else
1638         snprintf(buf, len, "%s", "reserved");
1639     return buf;
1640 }
1641 
1642 static void
cap_ide(struct device * d,int where)1643 cap_ide(struct device *d, int where)
1644 {
1645     const char * const hdr_enc_mode[] = { "no", "17:2", "25:2", "33:2", "41:2" };
1646     const char * const stream_state[] = { "insecure", "reserved", "secure" };
1647     const char * const aggr[] = { "-", "=2", "=4", "=8" };
1648     u32 l, l2, linknum = 0, selnum = 0, addrnum, off, i, j;
1649     char buf1[16], buf2[16], offs[16];
1650 
1651     printf("Integrity & Data Encryption\n");
1652 
1653     if (verbose < 2)
1654         return;
1655 
1656     if (!config_fetch(d, where + PCI_IDE_CAP, 8))
1657       {
1658         printf("\t\t<unreadable>\n");
1659         return;
1660       }
1661 
1662     l = get_conf_long(d, where + PCI_IDE_CAP);
1663     if (l & PCI_IDE_CAP_LINK_IDE_SUPP)
1664         linknum = PCI_IDE_CAP_LINK_TC_NUM(l) + 1;
1665     if (l & PCI_IDE_CAP_SELECTIVE_IDE_SUPP)
1666         selnum = PCI_IDE_CAP_SELECTIVE_STREAMS_NUM(l) + 1;
1667 
1668     printf("\t\tIDECap: Lnk=%d Sel=%d FlowThru%c PartHdr%c Aggr%c PCPC%c IDE_KM%c Alg='%s' TCs=%d TeeLim%c\n",
1669       linknum,
1670       selnum,
1671       FLAG(l, PCI_IDE_CAP_FLOWTHROUGH_IDE_SUPP),
1672       FLAG(l, PCI_IDE_CAP_PARTIAL_HEADER_ENC_SUPP),
1673       FLAG(l, PCI_IDE_CAP_AGGREGATION_SUPP),
1674       FLAG(l, PCI_IDE_CAP_PCRC_SUPP),
1675       FLAG(l, PCI_IDE_CAP_IDE_KM_SUPP),
1676       ide_alg(buf2, sizeof(buf2), PCI_IDE_CAP_ALG(l)),
1677       PCI_IDE_CAP_LINK_TC_NUM(l) + 1,
1678       FLAG(l, PCI_IDE_CAP_TEE_LIMITED_SUPP)
1679       );
1680 
1681     l = get_conf_long(d, where + PCI_IDE_CTL);
1682     printf("\t\tIDECtl: FTEn%c\n",
1683       FLAG(l, PCI_IDE_CTL_FLOWTHROUGH_IDE));
1684 
1685     // The rest of the capability is variable length arrays
1686     off = where + PCI_IDE_LINK_STREAM;
1687 
1688     // Link IDE Register Block repeated 0 to 8 times
1689     if (linknum)
1690       {
1691         if (!config_fetch(d, off, 8 * linknum))
1692           {
1693             printf("\t\t<unreadable>\n");
1694             return;
1695           }
1696         for (i = 0; i < linknum; ++i)
1697           {
1698             // Link IDE Stream Control Register
1699             l = get_conf_long(d, off);
1700             printf("\t\t%sLinkIDE#%d Ctl: En%c NPR%s PR%s CPL%s PCRC%c HdrEnc=%s Alg='%s' TC%d ID%d\n",
1701               offstr(offs, off),
1702               i,
1703               FLAG(l, PCI_IDE_LINK_CTL_EN),
1704               aggr[PCI_IDE_LINK_CTL_TX_AGGR_NPR(l)],
1705               aggr[PCI_IDE_LINK_CTL_TX_AGGR_PR(l)],
1706               aggr[PCI_IDE_LINK_CTL_TX_AGGR_CPL(l)],
1707               FLAG(l, PCI_IDE_LINK_CTL_EN),
1708               TABLE(hdr_enc_mode, PCI_IDE_LINK_CTL_PART_ENC(l), buf1),
1709               ide_alg(buf2, sizeof(buf2), PCI_IDE_LINK_CTL_ALG(l)),
1710               PCI_IDE_LINK_CTL_TC(l),
1711               PCI_IDE_LINK_CTL_ID(l)
1712               );
1713             off += 4;
1714 
1715             /* Link IDE Stream Status Register */
1716             l = get_conf_long(d, off);
1717             printf("\t\t%sLinkIDE#%d Sta: Status=%s RecvChkFail%c\n",
1718               offstr(offs, off),
1719               i,
1720               TABLE(stream_state, PCI_IDE_LINK_STS_STATUS(l), buf1),
1721               FLAG(l, PCI_IDE_LINK_STS_RECVD_INTEGRITY_CHECK));
1722             off += 4;
1723           }
1724       }
1725 
1726     for (i = 0; i < selnum; ++i)
1727       {
1728         // Fetching Selective IDE Stream Capability/Control/Status/RID1/RID2
1729         if (!config_fetch(d, off, 20))
1730           {
1731             printf("\t\t<unreadable>\n");
1732             return;
1733           }
1734 
1735         // Selective IDE Stream Capability Register
1736         l = get_conf_long(d, off);
1737         printf("\t\t%sSelectiveIDE#%d Cap: RID#=%d\n",
1738           offstr(offs, off),
1739           i,
1740           PCI_IDE_SEL_CAP_BLOCKS_NUM(l));
1741         off += 4;
1742         addrnum = PCI_IDE_SEL_CAP_BLOCKS_NUM(l);
1743 
1744         // Selective IDE Stream Control Register
1745         l = get_conf_long(d, off);
1746 
1747         printf("\t\t%sSelectiveIDE#%d Ctl: En%c NPR%s PR%s CPL%s PCRC%c CFG%c HdrEnc=%s Alg='%s' TC%d ID%d%s\n",
1748           offstr(offs, off),
1749           i,
1750           FLAG(l, PCI_IDE_SEL_CTL_EN),
1751           aggr[PCI_IDE_SEL_CTL_TX_AGGR_NPR(l)],
1752           aggr[PCI_IDE_SEL_CTL_TX_AGGR_PR(l)],
1753           aggr[PCI_IDE_SEL_CTL_TX_AGGR_CPL(l)],
1754           FLAG(l, PCI_IDE_SEL_CTL_PCRC_EN),
1755           FLAG(l, PCI_IDE_SEL_CTL_CFG_EN),
1756           TABLE(hdr_enc_mode, PCI_IDE_SEL_CTL_PART_ENC(l), buf1),
1757           ide_alg(buf2, sizeof(buf2), PCI_IDE_SEL_CTL_ALG(l)),
1758           PCI_IDE_SEL_CTL_TC(l),
1759           PCI_IDE_SEL_CTL_ID(l),
1760           (l & PCI_IDE_SEL_CTL_DEFAULT) ? " Default" : ""
1761           );
1762         off += 4;
1763 
1764         // Selective IDE Stream Status Register
1765         l = get_conf_long(d, off);
1766         printf("\t\t%sSelectiveIDE#%d Sta: %s RecvChkFail%c\n",
1767           offstr(offs, off),
1768           i ,
1769           TABLE(stream_state, PCI_IDE_SEL_STS_STATUS(l), buf1),
1770           FLAG(l, PCI_IDE_SEL_STS_RECVD_INTEGRITY_CHECK));
1771         off += 4;
1772 
1773         // IDE RID Association Registers
1774         l = get_conf_long(d, off);
1775         l2 = get_conf_long(d, off + 4);
1776 
1777         printf("\t\t%sSelectiveIDE#%d RID: Valid%c Base=%x Limit=%x SegBase=%x\n",
1778           offstr(offs, off),
1779           i,
1780           FLAG(l2, PCI_IDE_SEL_RID_2_VALID),
1781           PCI_IDE_SEL_RID_2_BASE(l2),
1782           PCI_IDE_SEL_RID_1_LIMIT(l),
1783           PCI_IDE_SEL_RID_2_SEG_BASE(l2));
1784         off += 8;
1785 
1786         if (!config_fetch(d, off, addrnum * 12))
1787           {
1788             printf("\t\t<unreadable>\n");
1789             return;
1790           }
1791 
1792         // IDE Address Association Registers
1793         for (j = 0; j < addrnum; ++j)
1794           {
1795             u64 limit, base;
1796 
1797             l = get_conf_long(d, off);
1798             limit = get_conf_long(d, off + 4);
1799             limit <<= 32;
1800             limit |= (PCI_IDE_SEL_ADDR_1_LIMIT_LOW(l) << 20) | 0xFFFFF;
1801             base = get_conf_long(d, off + 8);
1802             base <<= 32;
1803             base |= PCI_IDE_SEL_ADDR_1_BASE_LOW(l) << 20;
1804             printf("\t\t%sSelectiveIDE#%d RID#%d: Valid%c Base=%" PCI_U64_FMT_X " Limit=%" PCI_U64_FMT_X "\n",
1805               offstr(offs, off),
1806               i,
1807               j,
1808               FLAG(l, PCI_IDE_SEL_ADDR_1_VALID),
1809               base,
1810               limit);
1811             off += 12;
1812           }
1813       }
1814 }
1815 
l0p_exit_latency(int value)1816 static const char *l0p_exit_latency(int value)
1817 {
1818   static const char * const latencies[] = {
1819     "Less than 1us",
1820     "1us to less than 2us",
1821     "2us to less than 4us",
1822     "4us to less than 8us",
1823     "8us to less than 16us",
1824     "16us to less than 32us",
1825     "32us-64us",
1826     "More than 64us"
1827   };
1828 
1829   if (value >= 0 && value <= 7)
1830     return latencies[value];
1831   return "Unknown";
1832 }
1833 
link_width_str(char * buf,size_t buflen,int width)1834 static const char *link_width_str(char *buf, size_t buflen, int width)
1835 {
1836   switch (width)
1837     {
1838       case 0:
1839         return "x1";
1840       case 1:
1841         return "x2";
1842       case 2:
1843         return "x4";
1844       case 3:
1845         return "x8";
1846       case 4:
1847         return "x16";
1848       case 7:
1849         return "Dynamic";
1850       default:
1851         snprintf(buf, buflen, "Unknown (%d)", width);
1852         return buf;
1853     }
1854 }
1855 
1856 static void
cap_dev3(struct device * d,int where)1857 cap_dev3(struct device *d, int where)
1858 {
1859   u32 devcap3;
1860   u16 devctl3, devsta3;
1861   char buf[16];
1862 
1863   printf("Device 3\n");
1864 
1865   if (verbose < 2)
1866     return;
1867 
1868   if (!config_fetch(d, where + PCI_DEV3_DEVCAP3, 4))
1869     return;
1870   devcap3 = get_conf_long(d, where + PCI_DEV3_DEVCAP3);
1871 
1872   printf("\t\tDevCap3: DMWr Request Routing%c, 14-Bit Tag Completer%c, 14-Bit Tag Requester%c\n"
1873          "\t\t\t L0p%c",
1874          FLAG(devcap3, PCI_DEV3_DEVCAP3_DMWR_REQ),
1875          FLAG(devcap3, PCI_DEV3_DEVCAP3_14BIT_TAG_COMP),
1876          FLAG(devcap3, PCI_DEV3_DEVCAP3_14BIT_TAG_REQ),
1877          FLAG(devcap3, PCI_DEV3_DEVCAP3_L0P_SUPP));
1878 
1879   if (devcap3 & PCI_DEV3_DEVCAP3_L0P_SUPP)
1880     printf(", Port L0p Exit Latency: %s, Retimer L0p Exit Latency: %s",
1881            l0p_exit_latency(PCI_DEV3_DEVCAP3_PORT_L0P_EXIT(devcap3)),
1882            l0p_exit_latency(PCI_DEV3_DEVCAP3_RETIMER_L0P_EXIT(devcap3)));
1883 
1884   printf("\n\t\t\t UIO Mem RdWr Completer%c, UIO Mem RdWr Requester%c\n",
1885          FLAG(devcap3, PCI_DEV3_DEVCAP3_UIO_MEM_RDWR_COMP),
1886          FLAG(devcap3, PCI_DEV3_DEVCAP3_UIO_MEM_RDWR_REQ));
1887 
1888   if (!config_fetch(d, where + PCI_DEV3_DEVCTL3, 2))
1889     return;
1890   devctl3 = get_conf_word(d, where + PCI_DEV3_DEVCTL3);
1891 
1892   printf("\t\tDevCtl3: DMWr Requester%c, DMWr Egress Blocking%c, 14-Bit Tag Requester%c\n"
1893          "\t\t\t L0p%c, Target Link Width: %s\n"
1894          "\t\t\t UIO Mem RdWr Requester%c, UIO Request 256B Boundary%c\n",
1895          FLAG(devctl3, PCI_DEV3_DEVCTL3_DMWR_REQ_EN),
1896          FLAG(devctl3, PCI_DEV3_DEVCTL3_DMWR_EGRESS_BLK),
1897          FLAG(devctl3, PCI_DEV3_DEVCTL3_14BIT_TAG_REQ_EN),
1898          FLAG(devctl3, PCI_DEV3_DEVCTL3_L0P_EN),
1899          link_width_str(buf, sizeof(buf), PCI_DEV3_DEVCTL3_TARGET_LINK_WIDTH(devctl3)),
1900          FLAG(devctl3, PCI_DEV3_DEVCTL3_UIO_MEM_RDWR_REQ_EN),
1901          FLAG(~devctl3, PCI_DEV3_DEVCTL3_UIO_REQ_256B_DIS));
1902 
1903   if (!config_fetch(d, where + PCI_DEV3_DEVSTA3, 2))
1904     return;
1905   devsta3 = get_conf_word(d, where + PCI_DEV3_DEVSTA3);
1906 
1907   printf("\t\tDevSta3: Initial Link Width: %s, Segment Captured%c, Remote L0p%c\n",
1908          link_width_str(buf, sizeof(buf), PCI_DEV3_DEVSTA3_INIT_LINK_WIDTH(devsta3)),
1909          FLAG(devsta3, PCI_DEV3_DEVSTA3_SEGMENT_CAPTURED),
1910          FLAG(devsta3, PCI_DEV3_DEVSTA3_REMOTE_L0P_SUPP));
1911 }
1912 
1913 void
show_ext_caps(struct device * d,int type)1914 show_ext_caps(struct device *d, int type)
1915 {
1916   int where = 0x100;
1917   char been_there[0x1000];
1918   memset(been_there, 0, 0x1000);
1919   do
1920     {
1921       u32 header;
1922       int id, version;
1923 
1924       if (!config_fetch(d, where, 4))
1925 	break;
1926       header = get_conf_long(d, where);
1927       if (!header || header == 0xffffffff)
1928 	break;
1929       id = header & 0xffff;
1930       version = (header >> 16) & 0xf;
1931       printf("\tCapabilities: [%03x", where);
1932       if (verbose > 1)
1933 	printf(" v%d", version);
1934       printf("] ");
1935       if (been_there[where]++)
1936 	{
1937 	  printf("<chain looped>\n");
1938 	  break;
1939 	}
1940       switch (id)
1941 	{
1942 	  case PCI_EXT_CAP_ID_NULL:
1943 	    printf("Null\n");
1944 	    break;
1945 	  case PCI_EXT_CAP_ID_AER:
1946 	    cap_aer(d, where, type);
1947 	    break;
1948 	  case PCI_EXT_CAP_ID_DPC:
1949 	    cap_dpc(d, where);
1950 	    break;
1951 	  case PCI_EXT_CAP_ID_VC:
1952 	  case PCI_EXT_CAP_ID_VC2:
1953 	    cap_vc(d, where);
1954 	    break;
1955 	  case PCI_EXT_CAP_ID_DSN:
1956 	    cap_dsn(d, where);
1957 	    break;
1958 	  case PCI_EXT_CAP_ID_PB:
1959 	    printf("Power Budgeting <?>\n");
1960 	    break;
1961 	  case PCI_EXT_CAP_ID_RCLINK:
1962 	    cap_rclink(d, where);
1963 	    break;
1964 	  case PCI_EXT_CAP_ID_RCILINK:
1965 	    printf("Root Complex Internal Link <?>\n");
1966 	    break;
1967 	  case PCI_EXT_CAP_ID_RCEC:
1968 	    cap_rcec(d, where);
1969 	    break;
1970 	  case PCI_EXT_CAP_ID_MFVC:
1971 	    printf("Multi-Function Virtual Channel <?>\n");
1972 	    break;
1973 	  case PCI_EXT_CAP_ID_RCRB:
1974 	    printf("Root Complex Register Block <?>\n");
1975 	    break;
1976 	  case PCI_EXT_CAP_ID_VNDR:
1977 	    cap_evendor(d, where);
1978 	    break;
1979 	  case PCI_EXT_CAP_ID_ACS:
1980 	    cap_acs(d, where);
1981 	    break;
1982 	  case PCI_EXT_CAP_ID_ARI:
1983 	    cap_ari(d, where);
1984 	    break;
1985 	  case PCI_EXT_CAP_ID_ATS:
1986 	    cap_ats(d, where);
1987 	    break;
1988 	  case PCI_EXT_CAP_ID_SRIOV:
1989 	    cap_sriov(d, where);
1990 	    break;
1991 	  case PCI_EXT_CAP_ID_MRIOV:
1992 	    printf("Multi-Root I/O Virtualization <?>\n");
1993 	    break;
1994 	  case PCI_EXT_CAP_ID_MCAST:
1995 	    cap_multicast(d, where, type);
1996 	    break;
1997 	  case PCI_EXT_CAP_ID_PRI:
1998 	    cap_pri(d, where);
1999 	    break;
2000 	  case PCI_EXT_CAP_ID_REBAR:
2001 	    cap_rebar(d, where, 0);
2002 	    break;
2003 	  case PCI_EXT_CAP_ID_DPA:
2004 	    printf("Dynamic Power Allocation <?>\n");
2005 	    break;
2006 	  case PCI_EXT_CAP_ID_TPH:
2007 	    cap_tph(d, where);
2008 	    break;
2009 	  case PCI_EXT_CAP_ID_LTR:
2010 	    cap_ltr(d, where);
2011 	    break;
2012 	  case PCI_EXT_CAP_ID_SECPCI:
2013 	    cap_sec(d, where);
2014 	    break;
2015 	  case PCI_EXT_CAP_ID_PMUX:
2016 	    printf("Protocol Multiplexing <?>\n");
2017 	    break;
2018 	  case PCI_EXT_CAP_ID_PASID:
2019 	    cap_pasid(d, where);
2020 	    break;
2021 	  case PCI_EXT_CAP_ID_LNR:
2022 	    printf("LN Requester <?>\n");
2023 	    break;
2024 	  case PCI_EXT_CAP_ID_L1PM:
2025 	    cap_l1pm(d, where);
2026 	    break;
2027 	  case PCI_EXT_CAP_ID_PTM:
2028 	    cap_ptm(d, where);
2029 	    break;
2030 	  case PCI_EXT_CAP_ID_M_PCIE:
2031 	    printf("PCI Express over M_PHY <?>\n");
2032 	    break;
2033 	  case PCI_EXT_CAP_ID_FRS:
2034 	    printf("FRS Queueing <?>\n");
2035 	    break;
2036 	  case PCI_EXT_CAP_ID_RTR:
2037 	    printf("Readiness Time Reporting <?>\n");
2038 	    break;
2039 	  case PCI_EXT_CAP_ID_DVSEC:
2040 	    cap_dvsec(d, where);
2041 	    break;
2042 	  case PCI_EXT_CAP_ID_VF_REBAR:
2043 	    cap_rebar(d, where, 1);
2044 	    break;
2045 	  case PCI_EXT_CAP_ID_DLNK:
2046 	    printf("Data Link Feature <?>\n");
2047 	    break;
2048 	  case PCI_EXT_CAP_ID_16GT:
2049 	    cap_phy_16gt(d, where);
2050 	    break;
2051 	  case PCI_EXT_CAP_ID_LMR:
2052 	    cap_lmr(d, where);
2053 	    break;
2054 	  case PCI_EXT_CAP_ID_HIER_ID:
2055 	    printf("Hierarchy ID <?>\n");
2056 	    break;
2057 	  case PCI_EXT_CAP_ID_NPEM:
2058 	    printf("Native PCIe Enclosure Management <?>\n");
2059 	    break;
2060 	  case PCI_EXT_CAP_ID_32GT:
2061 	    cap_phy_32gt(d, where);
2062 	    break;
2063 	  case PCI_EXT_CAP_ID_DOE:
2064 	    cap_doe(d, where);
2065 	    break;
2066 	  case PCI_EXT_CAP_ID_IDE:
2067 	    cap_ide(d, where);
2068 	    break;
2069 	  case PCI_EXT_CAP_ID_64GT:
2070 	    cap_phy_64gt(d, where);
2071 	    break;
2072 	  case PCI_EXT_CAP_ID_DEV3:
2073 	    cap_dev3(d, where);
2074 	    break;
2075 	  default:
2076 	    printf("Extended Capability ID %#02x\n", id);
2077 	    break;
2078 	}
2079       where = (header >> 20) & ~3;
2080     } while (where);
2081 }
2082