]> git.ipfire.org Git - thirdparty/pciutils.git/blame - ls-ecaps.c
header.h: Fix type 1 header comment
[thirdparty/pciutils.git] / ls-ecaps.c
CommitLineData
c7a34993
MM
1/*
2 * The PCI Utilities -- Show Extended Capabilities
3 *
2849db67 4 * Copyright (c) 1997--2022 Martin Mares <mj@ucw.cz>
c7a34993 5 *
61829219
MM
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
c7a34993
MM
9 */
10
11#include <stdio.h>
12#include <string.h>
13
14#include "lspci.h"
15
67da1792
MM
16static void
17cap_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
52static u32
53cap_ltr_scale(u8 scale)
54{
55 return 1 << (scale * 5);
56}
57
58static void
59cap_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);
c3d1d465 72 printf("\t\tMax snoop latency: %" PCI_U64_FMT_U "ns\n",
6811edb8 73 ((u64)snoop & PCI_LTR_VALUE_MASK) * scale);
67da1792
MM
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);
c3d1d465 77 printf("\t\tMax no snoop latency: %" PCI_U64_FMT_U "ns\n",
6811edb8 78 ((u64)nosnoop & PCI_LTR_VALUE_MASK) * scale);
67da1792
MM
79}
80
21ff9851 81static void
9225e71d 82cap_sec(struct device *d, int where)
21ff9851
B
83{
84 u32 ctrl3, lane_err_stat;
85 u8 lane;
86 printf("Secondary PCI Express\n");
9225e71d 87 if (verbose < 2)
21ff9851
B
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);
018f413c 94 printf("\t\tLnkCtl3: LnkEquIntrruptEn%c PerformEqu%c\n",
21ff9851
B
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 {
9f7dc65c 102 printf("LaneErr at lane:");
21ff9851
B
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
c7a34993
MM
112static void
113cap_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",
6f9f8fd7
MW
121 t2 >> 24, (t2 >> 16) & 0xff, (t2 >> 8) & 0xff, t2 & 0xff,
122 t1 >> 24, (t1 >> 16) & 0xff, (t1 >> 8) & 0xff, t1 & 0xff);
c7a34993
MM
123}
124
125static void
a1492b88 126cap_aer(struct device *d, int where, int type)
c7a34993 127{
a6625432 128 u32 l, l0, l1, l2, l3;
a1492b88 129 u16 w;
c7a34993
MM
130
131 printf("Advanced Error Reporting\n");
9a2e4b35
YZ
132 if (verbose < 2)
133 return;
134
a6625432 135 if (!config_fetch(d, where + PCI_ERR_UNCOR_STATUS, 40))
c7a34993
MM
136 return;
137
138 l = get_conf_long(d, where + PCI_ERR_UNCOR_STATUS);
144b0911
SX
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",
c7a34993
MM
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),
144b0911
SX
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));
c7a34993 151 l = get_conf_long(d, where + PCI_ERR_UNCOR_MASK);
144b0911
SX
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",
c7a34993
MM
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),
144b0911
SX
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));
c7a34993 164 l = get_conf_long(d, where + PCI_ERR_UNCOR_SEVER);
144b0911
SX
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",
c7a34993
MM
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),
144b0911
SX
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));
c7a34993 177 l = get_conf_long(d, where + PCI_ERR_COR_STATUS);
144b0911
SX
178 printf("\t\tCESta:\tRxErr%c BadTLP%c BadDLLP%c Rollover%c Timeout%c AdvNonFatalErr%c "
179 "CorrIntErr%c HeaderOF%c\n",
c7a34993 180 FLAG(l, PCI_ERR_COR_RCVR), FLAG(l, PCI_ERR_COR_BAD_TLP), FLAG(l, PCI_ERR_COR_BAD_DLLP),
144b0911
SX
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));
c7a34993 183 l = get_conf_long(d, where + PCI_ERR_COR_MASK);
144b0911
SX
184 printf("\t\tCEMsk:\tRxErr%c BadTLP%c BadDLLP%c Rollover%c Timeout%c AdvNonFatalErr%c "
185 "CorrIntErr%c HeaderOF%c\n",
c7a34993 186 FLAG(l, PCI_ERR_COR_RCVR), FLAG(l, PCI_ERR_COR_BAD_TLP), FLAG(l, PCI_ERR_COR_BAD_DLLP),
144b0911
SX
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));
c7a34993 189 l = get_conf_long(d, where + PCI_ERR_CAP);
9a54979e 190 printf("\t\tAERCap:\tFirst Error Pointer: %02x, ECRCGenCap%c ECRCGenEn%c ECRCChkCap%c ECRCChkEn%c\n"
b33a4a2b 191 "\t\t\tMultHdrRecCap%c MultHdrRecEn%c TLPPfxPres%c HdrLogCap%c\n",
c7a34993 192 PCI_ERR_CAP_FEP(l), FLAG(l, PCI_ERR_CAP_ECRC_GENC), FLAG(l, PCI_ERR_CAP_ECRC_GENE),
b33a4a2b
BH
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));
a6625432
BH
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);
a1492b88
BH
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"
aeb74fe2 216 "\t\t\t FirstFatal%c NonFatalMsg%c FatalMsg%c IntMsgNum %d\n",
a1492b88
BH
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 }
c7a34993
MM
232}
233
de91b6f2
KB
234static 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);
aeb74fe2 246 printf("\t\tDpcCap:\tIntMsgNum %d, RPExt%c PoisonedTLP%c SwTrigger%c RP PIO Log %d, DL_ActiveErr%c\n",
de91b6f2
KB
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
c7a34993
MM
265static void
266cap_acs(struct device *d, int where)
267{
268 u16 w;
269
270 printf("Access Control Services\n");
9a2e4b35
YZ
271 if (verbose < 2)
272 return;
273
c7a34993
MM
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
291static void
292cap_ari(struct device *d, int where)
293{
294 u16 w;
295
296 printf("Alternative Routing-ID Interpretation (ARI)\n");
9a2e4b35
YZ
297 if (verbose < 2)
298 return;
299
c7a34993
MM
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
313static void
314cap_ats(struct device *d, int where)
315{
316 u16 w;
317
318 printf("Address Translation Service (ATS)\n");
9a2e4b35
YZ
319 if (verbose < 2)
320 return;
321
c7a34993
MM
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
a858df0d
DW
332static void
333cap_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);
bfd8658f 346 printf("\t\tPRICtl: Enable%c Reset%c\n",
a858df0d
DW
347 FLAG(w, PCI_PRI_CTRL_ENABLE), FLAG(w, PCI_PRI_CTRL_RESET));
348 w = get_conf_word(d, where + PCI_PRI_STATUS);
548a6e3b 349 printf("\t\tPRISta: RF%c UPRGI%c Stopped%c PASID%c\n",
a858df0d 350 FLAG(w, PCI_PRI_STATUS_RF), FLAG(w, PCI_PRI_STATUS_UPRGI),
548a6e3b 351 FLAG(w, PCI_PRI_STATUS_STOPPED), FLAG(w, PCI_PRI_STATUS_PASID));
a858df0d
DW
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
358static void
359cap_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);
bfd8658f 371 printf("\t\tPASIDCap: Exec%c Priv%c, Max PASID Width: %02x\n",
a858df0d
DW
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);
bfd8658f 375 printf("\t\tPASIDCtl: Enable%c Exec%c Priv%c\n",
a858df0d
DW
376 FLAG(w, PCI_PASID_CTRL_ENABLE), FLAG(w, PCI_PASID_CTRL_EXEC),
377 FLAG(w, PCI_PASID_CTRL_PRIV));
378}
379
c7a34993
MM
380static void
381cap_sriov(struct device *d, int where)
382{
383 u16 b;
384 u16 w;
385 u32 l;
67e78b32 386 int i;
c7a34993
MM
387
388 printf("Single Root I/O Virtualization (SR-IOV)\n");
9a2e4b35
YZ
389 if (verbose < 2)
390 return;
391
c7a34993
MM
392 if (!config_fetch(d, where + PCI_IOV_CAP, 0x3c))
393 return;
394
395 l = get_conf_long(d, where + PCI_IOV_CAP);
aeb74fe2 396 printf("\t\tIOVCap:\tMigration%c 10BitTagReq%c IntMsgNum %d\n",
053d08d2 397 FLAG(l, PCI_IOV_CAP_VFM), FLAG(l, PCI_IOV_CAP_VF_10BIT_TAG_REQ), PCI_IOV_CAP_IMN(l));
c7a34993 398 w = get_conf_word(d, where + PCI_IOV_CTRL);
053d08d2 399 printf("\t\tIOVCtl:\tEnable%c Migration%c Interrupt%c MSE%c ARIHierarchy%c 10BitTagReq%c\n",
c7a34993
MM
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),
053d08d2 402 FLAG(w, PCI_IOV_CTRL_ARI), FLAG(w, PCI_IOV_CTRL_VF_10BIT_TAG_REQ_EN));
c7a34993
MM
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);
b9e11c65
MM
423
424 for (i=0; i < PCI_IOV_NUM_BAR; i++)
425 {
187bf2f5 426 u32 addr;
b9e11c65
MM
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));
187bf2f5 441 printf("%08x", h);
b9e11c65 442 }
187bf2f5
MM
443 printf("%08x (%s-bit, %sprefetchable)\n",
444 addr,
b9e11c65
MM
445 (type == PCI_BASE_ADDRESS_MEM_TYPE_32) ? "32" : "64",
446 (l & PCI_BASE_ADDRESS_MEM_PREFETCH) ? "" : "non-");
67e78b32 447 }
b9e11c65 448
edca3520 449 l = get_conf_long(d, where + PCI_IOV_MSAO);
c7a34993
MM
450 printf("\t\tVF Migration: offset: %08x, BIR: %x\n", PCI_IOV_MSA_OFFSET(l),
451 PCI_IOV_MSA_BIR(l));
452}
453
c0d9545c
BH
454static void
455cap_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
33088c24
MM
510static void
511cap_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;
3d8b5258 518 static const char ref_clocks[][6] = { "100ns" };
3edae14a
MM
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" };
3d8b5258 521 char buf[8];
33088c24
MM
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
3d8b5258 535 evc_cnt = BITS(cr1, 0, 3);
d676f20d 536 printf("\t\tCaps:\tLPEVC=%d RefClk=%s PATEntryBits=%d\n",
3d8b5258
MM
537 BITS(cr1, 4, 3),
538 TABLE(ref_clocks, BITS(cr1, 8, 2), buf),
d676f20d 539 1 << BITS(cr1, 10, 2));
33088c24 540
d676f20d 541 printf("\t\tArb:");
33088c24
MM
542 for (i=0; i<8; i++)
543 if (arb_selects[i][0] != '?' || cr2 & (1 << i))
d676f20d 544 printf("%c%s%c", (i ? ' ' : '\t'), arb_selects[i], FLAG(cr2, 1 << i));
3d8b5258 545 arb_table_pos = BITS(cr2, 24, 8);
33088c24 546
d676f20d 547 printf("\n\t\tCtrl:\tArbSelect=%s\n", TABLE(arb_selects, BITS(ctrl, 1, 3), buf));
33088c24
MM
548 printf("\t\tStatus:\tInProgress%c\n", FLAG(status, 1));
549
550 if (arb_table_pos)
d676f20d
MM
551 {
552 arb_table_pos = where + 16*arb_table_pos;
553 printf("\t\tPort Arbitration Table [%x] <?>\n", arb_table_pos);
554 }
33088c24
MM
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
5a9a932c 563 printf("\t\tVC%d:\t", i);
33088c24
MM
564 if (!config_fetch(d, pos, 12))
565 {
5a9a932c 566 printf("<unreadable>\n");
33088c24
MM
567 continue;
568 }
569 rcap = get_conf_long(d, pos);
570 rctrl = get_conf_long(d, pos+4);
7970509b 571 rstatus = get_conf_word(d, pos+10);
33088c24 572
3d8b5258 573 pat_pos = BITS(rcap, 24, 8);
5a9a932c 574 printf("Caps:\tPATOffset=%02x MaxTimeSlots=%d RejSnoopTrans%c\n",
33088c24 575 pat_pos,
3711e86f 576 BITS(rcap, 16, 7) + 1,
33088c24
MM
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),
3d8b5258
MM
586 BITS(rctrl, 24, 3),
587 TABLE(vc_arb_selects, BITS(rctrl, 17, 3), buf),
588 BITS(rctrl, 0, 8));
33088c24
MM
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
5a9a932c
MM
599static void
600cap_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
e12bd01e
SK
661static void
662cap_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
d016c32d
NP
716static void
717cap_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
0c6383e9
TWW
736static void
737cap_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
759static void
760cap_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
04d90bec
TWW
818static void
819cap_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
52097446
BW
845static void
846cxl_range(u64 base, u64 size, int n)
847{
848 u32 interleave[] = { 0, 256, 4096, 512, 1024, 2048, 8192, 16384 };
2bbe1d46
MM
849 const char * const type[] = { "Volatile", "Non-volatile", "CDAT" };
850 const char * const class[] = { "DRAM", "Storage", "CDAT" };
52097446
BW
851 u16 w;
852
853 w = (u16) size;
854
855 size &= ~0x0fffffffULL;
856
c0ccce1b 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);
52097446
BW
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
bd853ef8 865static void
2849db67 866dvsec_cxl_device(struct device *d, int rev, int where, int len)
bd853ef8 867{
2849db67 868 u32 cache_size, cache_unit_size;
52097446 869 u64 range_base, range_size;
ccf5ff41 870 u16 w;
bd853ef8 871
0d4491cb 872 /* Legacy 1.1 revs aren't handled */
c0ccce1b 873 if (rev == 0)
bd853ef8
SK
874 return;
875
944bb1df 876 if (rev >= 1 && len >= PCI_CXL_DEV_LEN)
3d2d69cb
MM
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);
c0ccce1b 937 }
52097446 938
944bb1df 939 if (rev >= 2 && len >= PCI_CXL_DEV_LEN_REV2)
3d2d69cb
MM
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 }
52097446 948
c0ccce1b 949 // Unparsed data
944bb1df 950 if (len > PCI_CXL_DEV_LEN_REV2)
c0ccce1b 951 printf("\t\t<?>\n");
bd853ef8
SK
952}
953
c8b83c6c 954static void
2849db67 955dvsec_cxl_port(struct device *d, int where, int len)
c8b83c6c
BW
956{
957 u16 w, m1, m2;
958 u8 b1, b2;
959
2849db67
MM
960 if (len < PCI_CXL_PORT_EXT_LEN)
961 return;
962
c8b83c6c
BW
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
2849db67
MM
980static void
981dvsec_cxl_register_locator(struct device *d, int where, int len)
0dfa1050 982{
2849db67
MM
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 {
55704534
JH
993 int pos = where + PCI_CXL_RL_BLOCK1_LO + 8*i;
994 if (pos + 7 >= where + len)
2849db67 995 break;
0dfa1050 996
2849db67
MM
997 u32 lo = get_conf_long(d, pos);
998 u32 hi = get_conf_long(d, pos + 4);
0dfa1050 999
2849db67
MM
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);
0dfa1050 1003
2849db67
MM
1004 if (!block_id)
1005 continue;
0dfa1050 1006
2849db67
MM
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 = "<?>";
0dfa1050 1014
55704534 1015 printf("\t\tBlock%d: BIR: bar%d, ID: %s, offset: %016" PCI_U64_FMT_X "\n", i + 1, bir, id_name, base);
2849db67 1016 }
0dfa1050
BW
1017}
1018
d462e89c
JH
1019static void
1020dvsec_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" :
55209a0a 1055 (time_scale <= PCI_CXL_GPF_DEV_10S) ? "s" : "<?>");
d462e89c
JH
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
5c75f737
JH
1061static void
1062dvsec_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" :
55209a0a 1096 (time_scale <= PCI_CXL_GPF_PORT_10S) ? "s" : "<?>");
5c75f737
JH
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" :
55209a0a 1127 (time_scale <= PCI_CXL_GPF_PORT_10S) ? "s" : "<?>");
5c75f737
JH
1128}
1129
9e567a4e 1130static void
23b1ee0c 1131dvsec_cxl_flex_bus(struct device *d, int where, int rev, int len)
9e567a4e
JH
1132{
1133 u16 w;
1134 u32 l, data;
1135
23b1ee0c
AG
1136 // Sanity check: Does the length correspond to its revision?
1137 switch (rev) {
1138 case 0:
3d2d69cb 1139 if (len != PCI_CXL_FB_MOD_TS_DATA)
23b1ee0c 1140 printf("\t\t<Wrong length for Revision %d>\n", rev);
23b1ee0c
AG
1141 break;
1142 case 1:
3d2d69cb 1143 if (len != PCI_CXL_FB_PORT_CAP2)
23b1ee0c 1144 printf("\t\t<Wrong length for Revision %d>\n", rev);
23b1ee0c
AG
1145 break;
1146 case 2:
3d2d69cb 1147 if (len != PCI_CXL_FB_NEXT_UNSUPPORTED)
23b1ee0c 1148 printf("\t\t<Wrong length for Revision %d>\n", rev);
23b1ee0c
AG
1149 break;
1150 default:
1151 break;
9e567a4e
JH
1152 }
1153
23b1ee0c 1154 // From Rev 0
9e567a4e
JH
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));
23b1ee0c 1187 printf("\n");
9e567a4e 1188
23b1ee0c
AG
1189 // From Rev 1
1190 if (rev >= 1)
3d2d69cb
MM
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 }
9e567a4e 1196
23b1ee0c
AG
1197 // From Rev 2
1198 if (rev >= 2)
3d2d69cb
MM
1199 {
1200 u8 nop;
9e567a4e 1201
3d2d69cb
MM
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));
9e567a4e 1204
3d2d69cb
MM
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));
9e567a4e 1207
3d2d69cb
MM
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 }
23b1ee0c
AG
1212
1213 // Unparsed data
3d2d69cb 1214 if (len > PCI_CXL_FB_LEN)
23b1ee0c 1215 printf("\t\t<?>\n");
9e567a4e
JH
1216}
1217
45824262
JH
1218static void
1219dvsec_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
ec4cd47b
JH
1230static void
1231dvsec_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
0d4491cb 1259static void
2849db67 1260cap_dvsec_cxl(struct device *d, int id, int rev, int where, int len)
0d4491cb 1261{
0d4491cb
BW
1262 printf(": CXL\n");
1263 if (verbose < 2)
1264 return;
1265
2849db67
MM
1266 if (!config_fetch(d, where, len))
1267 return;
0d4491cb 1268
2849db67
MM
1269 switch (id)
1270 {
c8b83c6c 1271 case 0:
23b1ee0c 1272 printf("\t\tPCIe DVSEC for CXL Devices\n");
2849db67 1273 dvsec_cxl_device(d, rev, where, len);
0dfa1050 1274 break;
fe0df5d3 1275 case 2:
23b1ee0c 1276 printf("\t\tNon-CXL Function Map DVSEC\n");
ec4cd47b 1277 dvsec_cxl_function_map(d, where);
fe0df5d3 1278 break;
2849db67 1279 case 3:
23b1ee0c 1280 printf("\t\tCXL Extensions DVSEC for Ports\n");
2849db67
MM
1281 dvsec_cxl_port(d, where, len);
1282 break;
fe0df5d3 1283 case 4:
23b1ee0c 1284 printf("\t\tGPF DVSEC for CXL Ports\n");
5c75f737 1285 dvsec_cxl_gpf_port(d, where);
fe0df5d3
BW
1286 break;
1287 case 5:
23b1ee0c 1288 printf("\t\tGPF DVSEC for CXL Devices\n");
d462e89c 1289 dvsec_cxl_gpf_device(d, where);
fe0df5d3
BW
1290 break;
1291 case 7:
23b1ee0c
AG
1292 printf("\t\tPCIe DVSEC for Flex Bus Port\n");
1293 dvsec_cxl_flex_bus(d, where, rev, len);
fe0df5d3 1294 break;
2849db67 1295 case 8:
23b1ee0c 1296 printf("\t\tRegister Locator DVSEC\n");
2849db67
MM
1297 dvsec_cxl_register_locator(d, where, len);
1298 break;
fe0df5d3 1299 case 9:
23b1ee0c 1300 printf("\t\tMLD DVSEC\n");
45824262 1301 dvsec_cxl_mld(d, where);
fe0df5d3 1302 break;
23b1ee0c
AG
1303 case 0xa:
1304 printf("\t\tPCIe DVSEC for Test Capability <?>\n");
1305 break;
c8b83c6c 1306 default:
2849db67
MM
1307 printf("\t\tUnknown ID %04x\n", id);
1308 }
0d4491cb
BW
1309}
1310
5f1d1265
SK
1311static void
1312cap_dvsec(struct device *d, int where)
1313{
71aeac63 1314 printf("Designated Vendor-Specific: ");
5f1d1265
SK
1315 if (!config_fetch(d, where + PCI_DVSEC_HEADER1, 8))
1316 {
1317 printf("<unreadable>\n");
1318 return;
1319 }
1320
71aeac63
MM
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);
5f1d1265 1325
71aeac63
MM
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);
6c138204 1329 if (vendor == PCI_DVSEC_VENDOR_ID_CXL && len >= 16)
2849db67 1330 cap_dvsec_cxl(d, id, rev, where, len);
71aeac63
MM
1331 else
1332 printf(" <?>\n");
5f1d1265
SK
1333}
1334
78ca9582
MM
1335static void
1336cap_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
fb17077d 1354static int l1pm_calc_pwron(int scale, int value)
8efbe075
RJ
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
214c9a95
DB
1368static void
1369cap_l1pm(struct device *d, int where)
1370{
8efbe075
RJ
1371 u32 l1_cap, val, scale;
1372 int time;
214c9a95
DB
1373
1374 printf("L1 PM Substates\n");
1375
1376 if (verbose < 2)
1377 return;
1378
8efbe075 1379 if (!config_fetch(d, where + PCI_L1PM_SUBSTAT_CAP, 12))
214c9a95
DB
1380 {
1381 printf("\t\t<unreadable>\n");
1382 return;
1383 }
1384
8efbe075 1385 l1_cap = get_conf_long(d, where + PCI_L1PM_SUBSTAT_CAP);
214c9a95 1386 printf("\t\tL1SubCap: ");
e495466c 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",
8efbe075
RJ
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
fb17077d 1394 if (l1_cap & PCI_L1PM_SUBSTAT_CAP_PM_L12 || l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
214c9a95 1395 {
fb17077d 1396 printf("\t\t\t PortCommonModeRestoreTime=%dus ", BITS(l1_cap, 8, 8));
8efbe075
RJ
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 }
214c9a95 1403
8efbe075 1404 val = get_conf_long(d, where + PCI_L1PM_SUBSTAT_CTL1);
fb17077d 1405 printf("\t\tL1SubCtl1: PCI-PM_L1.2%c PCI-PM_L1.1%c ASPM_L1.2%c ASPM_L1.1%c\n",
8efbe075
RJ
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
fb17077d 1411 if (l1_cap & PCI_L1PM_SUBSTAT_CAP_PM_L12 || l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
8efbe075 1412 {
6469d596
VL
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
c3d1d465 1421 printf(" LTR1.2_Threshold=%" PCI_U64_FMT_U "ns", BITS(val, 16, 10) * (u64) cap_ltr_scale(scale));
6469d596
VL
1422 }
1423 printf("\n");
8efbe075
RJ
1424 }
1425
1426 val = get_conf_long(d, where + PCI_L1PM_SUBSTAT_CTL2);
fb17077d
MM
1427 printf("\t\tL1SubCtl2:");
1428 if (l1_cap & PCI_L1PM_SUBSTAT_CAP_PM_L12 || l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
8efbe075
RJ
1429 {
1430 time = l1pm_calc_pwron(BITS(val, 0, 2), BITS(val, 3, 5));
1431 if (time != -1)
fb17077d 1432 printf(" T_PwrOn=%dus", time);
8efbe075 1433 else
fb17077d 1434 printf(" T_PwrOn=<error>");
214c9a95 1435 }
fb17077d 1436 printf("\n");
214c9a95
DB
1437}
1438
415a9c18
YJ
1439static void
1440cap_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: ");
b2caca01 1458 printf("Requester%c Responder%c Root%c\n",
415a9c18
YJ
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: ");
b2caca01 1479 printf("Enabled%c RootSelected%c\n",
415a9c18
YJ
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
44c6c7fc
MM
1498static void
1499print_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
1521static void
1522cap_rebar(struct device *d, int where, int virtual)
1523{
1524 u32 sizes_buffer, control_buffer, ext_sizes, current_size;
d10c2aa1
MM
1525 u16 bar_index, barcount, i;
1526 // If the structure exists, at least one bar is defined
44c6c7fc
MM
1527 u16 num_bars = 1;
1528
1529 printf("%s Resizable BAR\n", (virtual) ? "Virtual" : "Physical");
1530
d10c2aa1 1531 if (verbose < 2)
44c6c7fc
MM
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;
44c6c7fc 1548 where += 4;
44c6c7fc
MM
1549 control_buffer = get_conf_long(d, where);
1550
d10c2aa1
MM
1551 bar_index = BITS(control_buffer, 0, 3);
1552 current_size = BITS(control_buffer, 8, 6);
1553 ext_sizes = BITS(control_buffer, 16, 16);
44c6c7fc
MM
1554
1555 if (barcount == 0)
1556 {
1557 // Only index 0 controlreg has the num_bar count definition
d10c2aa1
MM
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 }
44c6c7fc
MM
1564 }
1565
1566 // Resizable BAR list entry have an arbitrary index and current size
d10c2aa1 1567 printf("\t\tBAR %d: current size:", bar_index);
44c6c7fc
MM
1568 print_rebar_range_size(current_size);
1569
d10c2aa1
MM
1570 if (sizes_buffer || ext_sizes)
1571 {
1572 printf(", supported:");
44c6c7fc 1573
d10c2aa1
MM
1574 for (i=0; i<28; i++)
1575 if (sizes_buffer & (1U << i))
1576 print_rebar_range_size(i);
44c6c7fc 1577
d10c2aa1
MM
1578 for (i=0; i<16; i++)
1579 if (ext_sizes & (1U << i))
1580 print_rebar_range_size(i + 28);
1581 }
44c6c7fc 1582
44c6c7fc
MM
1583 printf("\n");
1584 }
1585}
1586
60be9345
JC
1587static void
1588cap_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)
aeb74fe2 1607 printf("\t\t\tIntMsgNum %d\n",
60be9345
JC
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
42fc4263
AK
1622static 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
1631static 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
1642static void
1643cap_ide(struct device *d, int where)
1644{
2bbe1d46
MM
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" };
42fc4263
AK
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
8c140bee 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",
42fc4263
AK
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),
8c140bee 1755 FLAG(l, PCI_IDE_SEL_CTL_CFG_EN),
42fc4263
AK
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);
8c140bee
AK
1799 limit <<= 32;
1800 limit |= (PCI_IDE_SEL_ADDR_1_LIMIT_LOW(l) << 20) | 0xFFFFF;
42fc4263 1801 base = get_conf_long(d, off + 8);
8c140bee
AK
1802 base <<= 32;
1803 base |= PCI_IDE_SEL_ADDR_1_BASE_LOW(l) << 20;
b78c087b 1804 printf("\t\t%sSelectiveIDE#%d RID#%d: Valid%c Base=%" PCI_U64_FMT_X " Limit=%" PCI_U64_FMT_X "\n",
42fc4263
AK
1805 offstr(offs, off),
1806 i,
1807 j,
1808 FLAG(l, PCI_IDE_SEL_ADDR_1_VALID),
8c140bee
AK
1809 base,
1810 limit);
42fc4263
AK
1811 off += 12;
1812 }
1813 }
1814}
1815
9611db3e
PC
1816static const char *l0p_exit_latency(int value)
1817{
2bbe1d46 1818 static const char * const latencies[] = {
9611db3e
PC
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 };
18419d2a 1828
9611db3e
PC
1829 if (value >= 0 && value <= 7)
1830 return latencies[value];
1831 return "Unknown";
1832}
1833
1834static 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
1856static void
1857cap_dev3(struct device *d, int where)
1858{
1859 u32 devcap3;
1860 u16 devctl3, devsta3;
1861 char buf[16];
18419d2a 1862
9611db3e 1863 printf("Device 3\n");
18419d2a 1864
9611db3e
PC
1865 if (verbose < 2)
1866 return;
18419d2a 1867
9611db3e
PC
1868 if (!config_fetch(d, where + PCI_DEV3_DEVCAP3, 4))
1869 return;
1870 devcap3 = get_conf_long(d, where + PCI_DEV3_DEVCAP3);
18419d2a 1871
9611db3e
PC
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));
18419d2a 1878
9611db3e
PC
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)));
18419d2a 1883
9611db3e
PC
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));
18419d2a 1887
9611db3e
PC
1888 if (!config_fetch(d, where + PCI_DEV3_DEVCTL3, 2))
1889 return;
1890 devctl3 = get_conf_word(d, where + PCI_DEV3_DEVCTL3);
18419d2a 1891
9611db3e
PC
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));
18419d2a 1902
9611db3e
PC
1903 if (!config_fetch(d, where + PCI_DEV3_DEVSTA3, 2))
1904 return;
1905 devsta3 = get_conf_word(d, where + PCI_DEV3_DEVSTA3);
18419d2a 1906
9611db3e
PC
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
c7a34993 1913void
a1492b88 1914show_ext_caps(struct device *d, int type)
c7a34993
MM
1915{
1916 int where = 0x100;
1917 char been_there[0x1000];
1918 memset(been_there, 0, 0x1000);
1919 do
1920 {
1921 u32 header;
33088c24 1922 int id, version;
c7a34993
MM
1923
1924 if (!config_fetch(d, where, 4))
1925 break;
1926 header = get_conf_long(d, where);
861063f3 1927 if (!header || header == 0xffffffff)
c7a34993
MM
1928 break;
1929 id = header & 0xffff;
33088c24
MM
1930 version = (header >> 16) & 0xf;
1931 printf("\tCapabilities: [%03x", where);
1932 if (verbose > 1)
1933 printf(" v%d", version);
1934 printf("] ");
c7a34993
MM
1935 if (been_there[where]++)
1936 {
1937 printf("<chain looped>\n");
1938 break;
1939 }
1940 switch (id)
1941 {
c508d1c9
BH
1942 case PCI_EXT_CAP_ID_NULL:
1943 printf("Null\n");
1944 break;
c7a34993 1945 case PCI_EXT_CAP_ID_AER:
a1492b88 1946 cap_aer(d, where, type);
c7a34993 1947 break;
de91b6f2
KB
1948 case PCI_EXT_CAP_ID_DPC:
1949 cap_dpc(d, where);
1950 break;
c7a34993 1951 case PCI_EXT_CAP_ID_VC:
33088c24
MM
1952 case PCI_EXT_CAP_ID_VC2:
1953 cap_vc(d, where);
c7a34993
MM
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:
5a9a932c 1962 cap_rclink(d, where);
c7a34993
MM
1963 break;
1964 case PCI_EXT_CAP_ID_RCILINK:
1965 printf("Root Complex Internal Link <?>\n");
1966 break;
e12bd01e
SK
1967 case PCI_EXT_CAP_ID_RCEC:
1968 cap_rcec(d, where);
c7a34993
MM
1969 break;
1970 case PCI_EXT_CAP_ID_MFVC:
1971 printf("Multi-Function Virtual Channel <?>\n");
1972 break;
eff08b33
BH
1973 case PCI_EXT_CAP_ID_RCRB:
1974 printf("Root Complex Register Block <?>\n");
c7a34993
MM
1975 break;
1976 case PCI_EXT_CAP_ID_VNDR:
78ca9582 1977 cap_evendor(d, where);
c7a34993
MM
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;
b8f7cd64
BH
1991 case PCI_EXT_CAP_ID_MRIOV:
1992 printf("Multi-Root I/O Virtualization <?>\n");
1993 break;
c0d9545c
BH
1994 case PCI_EXT_CAP_ID_MCAST:
1995 cap_multicast(d, where, type);
1996 break;
a858df0d
DW
1997 case PCI_EXT_CAP_ID_PRI:
1998 cap_pri(d, where);
1999 break;
b8f7cd64 2000 case PCI_EXT_CAP_ID_REBAR:
44c6c7fc 2001 cap_rebar(d, where, 0);
b8f7cd64
BH
2002 break;
2003 case PCI_EXT_CAP_ID_DPA:
2004 printf("Dynamic Power Allocation <?>\n");
2005 break;
67da1792
MM
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;
b8f7cd64 2012 case PCI_EXT_CAP_ID_SECPCI:
9225e71d 2013 cap_sec(d, where);
b8f7cd64
BH
2014 break;
2015 case PCI_EXT_CAP_ID_PMUX:
2016 printf("Protocol Multiplexing <?>\n");
2017 break;
a858df0d
DW
2018 case PCI_EXT_CAP_ID_PASID:
2019 cap_pasid(d, where);
2020 break;
b8f7cd64
BH
2021 case PCI_EXT_CAP_ID_LNR:
2022 printf("LN Requester <?>\n");
2023 break;
214c9a95
DB
2024 case PCI_EXT_CAP_ID_L1PM:
2025 cap_l1pm(d, where);
2026 break;
415a9c18
YJ
2027 case PCI_EXT_CAP_ID_PTM:
2028 cap_ptm(d, where);
2029 break;
b8f7cd64
BH
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:
71aeac63 2040 cap_dvsec(d, where);
b8f7cd64
BH
2041 break;
2042 case PCI_EXT_CAP_ID_VF_REBAR:
44c6c7fc 2043 cap_rebar(d, where, 1);
b8f7cd64
BH
2044 break;
2045 case PCI_EXT_CAP_ID_DLNK:
2046 printf("Data Link Feature <?>\n");
2047 break;
2048 case PCI_EXT_CAP_ID_16GT:
0c6383e9 2049 cap_phy_16gt(d, where);
b8f7cd64
BH
2050 break;
2051 case PCI_EXT_CAP_ID_LMR:
d016c32d 2052 cap_lmr(d, where);
b8f7cd64
BH
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;
0c6383e9
TWW
2060 case PCI_EXT_CAP_ID_32GT:
2061 cap_phy_32gt(d, where);
2062 break;
60be9345
JC
2063 case PCI_EXT_CAP_ID_DOE:
2064 cap_doe(d, where);
2065 break;
42fc4263
AK
2066 case PCI_EXT_CAP_ID_IDE:
2067 cap_ide(d, where);
2068 break;
04d90bec
TWW
2069 case PCI_EXT_CAP_ID_64GT:
2070 cap_phy_64gt(d, where);
2071 break;
9611db3e
PC
2072 case PCI_EXT_CAP_ID_DEV3:
2073 cap_dev3(d, where);
2074 break;
c7a34993 2075 default:
60a45a7e 2076 printf("Extended Capability ID %#02x\n", id);
c7a34993
MM
2077 break;
2078 }
d61c4772 2079 where = (header >> 20) & ~3;
c7a34993
MM
2080 } while (where);
2081}