xref: /pciutils/ls-ecaps.c (revision b78c087b)
1c7a34993SMartin Mares /*
2c7a34993SMartin Mares  *	The PCI Utilities -- Show Extended Capabilities
3c7a34993SMartin Mares  *
42849db67SMartin Mares  *	Copyright (c) 1997--2022 Martin Mares <[email protected]>
5c7a34993SMartin Mares  *
661829219SMartin Mares  *	Can be freely distributed and used under the terms of the GNU GPL v2+.
761829219SMartin Mares  *
861829219SMartin Mares  *	SPDX-License-Identifier: GPL-2.0-or-later
9c7a34993SMartin Mares  */
10c7a34993SMartin Mares 
11c7a34993SMartin Mares #include <stdio.h>
12c7a34993SMartin Mares #include <string.h>
13c7a34993SMartin Mares 
14c7a34993SMartin Mares #include "lspci.h"
15c7a34993SMartin Mares 
16c7a34993SMartin Mares static void
cap_tph(struct device * d,int where)1767da1792SMartin Mares cap_tph(struct device *d, int where)
1867da1792SMartin Mares {
1967da1792SMartin Mares   u32 tph_cap;
2067da1792SMartin Mares   printf("Transaction Processing Hints\n");
2167da1792SMartin Mares   if (verbose < 2)
2267da1792SMartin Mares     return;
2367da1792SMartin Mares 
2467da1792SMartin Mares   if (!config_fetch(d, where + PCI_TPH_CAPABILITIES, 4))
2567da1792SMartin Mares     return;
2667da1792SMartin Mares 
2767da1792SMartin Mares   tph_cap = get_conf_long(d, where + PCI_TPH_CAPABILITIES);
2867da1792SMartin Mares 
2967da1792SMartin Mares   if (tph_cap & PCI_TPH_INTVEC_SUP)
3067da1792SMartin Mares     printf("\t\tInterrupt vector mode supported\n");
3167da1792SMartin Mares   if (tph_cap & PCI_TPH_DEV_SUP)
3267da1792SMartin Mares     printf("\t\tDevice specific mode supported\n");
3367da1792SMartin Mares   if (tph_cap & PCI_TPH_EXT_REQ_SUP)
3467da1792SMartin Mares     printf("\t\tExtended requester support\n");
3567da1792SMartin Mares 
3667da1792SMartin Mares   switch (tph_cap & PCI_TPH_ST_LOC_MASK) {
3767da1792SMartin Mares   case PCI_TPH_ST_NONE:
3867da1792SMartin Mares     printf("\t\tNo steering table available\n");
3967da1792SMartin Mares     break;
4067da1792SMartin Mares   case PCI_TPH_ST_CAP:
4167da1792SMartin Mares     printf("\t\tSteering table in TPH capability structure\n");
4267da1792SMartin Mares     break;
4367da1792SMartin Mares   case PCI_TPH_ST_MSIX:
4467da1792SMartin Mares     printf("\t\tSteering table in MSI-X table\n");
4567da1792SMartin Mares     break;
4667da1792SMartin Mares   default:
4767da1792SMartin Mares     printf("\t\tReserved steering table location\n");
4867da1792SMartin Mares     break;
4967da1792SMartin Mares   }
5067da1792SMartin Mares }
5167da1792SMartin Mares 
5267da1792SMartin Mares static u32
cap_ltr_scale(u8 scale)5367da1792SMartin Mares cap_ltr_scale(u8 scale)
5467da1792SMartin Mares {
5567da1792SMartin Mares   return 1 << (scale * 5);
5667da1792SMartin Mares }
5767da1792SMartin Mares 
5867da1792SMartin Mares static void
cap_ltr(struct device * d,int where)5967da1792SMartin Mares cap_ltr(struct device *d, int where)
6067da1792SMartin Mares {
6167da1792SMartin Mares   u32 scale;
6267da1792SMartin Mares   u16 snoop, nosnoop;
6367da1792SMartin Mares   printf("Latency Tolerance Reporting\n");
6467da1792SMartin Mares   if (verbose < 2)
6567da1792SMartin Mares     return;
6667da1792SMartin Mares 
6767da1792SMartin Mares   if (!config_fetch(d, where + PCI_LTR_MAX_SNOOP, 4))
6867da1792SMartin Mares     return;
6967da1792SMartin Mares 
7067da1792SMartin Mares   snoop = get_conf_word(d, where + PCI_LTR_MAX_SNOOP);
7167da1792SMartin Mares   scale = cap_ltr_scale((snoop >> PCI_LTR_SCALE_SHIFT) & PCI_LTR_SCALE_MASK);
72c3d1d465SPali Rohár   printf("\t\tMax snoop latency: %" PCI_U64_FMT_U "ns\n",
736811edb8SPali Rohár 	 ((u64)snoop & PCI_LTR_VALUE_MASK) * scale);
7467da1792SMartin Mares 
7567da1792SMartin Mares   nosnoop = get_conf_word(d, where + PCI_LTR_MAX_NOSNOOP);
7667da1792SMartin Mares   scale = cap_ltr_scale((nosnoop >> PCI_LTR_SCALE_SHIFT) & PCI_LTR_SCALE_MASK);
77c3d1d465SPali Rohár   printf("\t\tMax no snoop latency: %" PCI_U64_FMT_U "ns\n",
786811edb8SPali Rohár 	 ((u64)nosnoop & PCI_LTR_VALUE_MASK) * scale);
7967da1792SMartin Mares }
8067da1792SMartin Mares 
8167da1792SMartin Mares static void
cap_sec(struct device * d,int where)829225e71dSMartin Mares cap_sec(struct device *d, int where)
8321ff9851SBasavaraja M S {
8421ff9851SBasavaraja M S   u32 ctrl3, lane_err_stat;
8521ff9851SBasavaraja M S   u8 lane;
8621ff9851SBasavaraja M S   printf("Secondary PCI Express\n");
879225e71dSMartin Mares   if (verbose < 2)
8821ff9851SBasavaraja M S     return;
8921ff9851SBasavaraja M S 
9021ff9851SBasavaraja M S   if (!config_fetch(d, where + PCI_SEC_LNKCTL3, 12))
9121ff9851SBasavaraja M S     return;
9221ff9851SBasavaraja M S 
9321ff9851SBasavaraja M S   ctrl3 = get_conf_word(d, where + PCI_SEC_LNKCTL3);
94018f413cSBjorn Helgaas   printf("\t\tLnkCtl3: LnkEquIntrruptEn%c PerformEqu%c\n",
9521ff9851SBasavaraja M S 	FLAG(ctrl3, PCI_SEC_LNKCTL3_LNK_EQU_REQ_INTR_EN),
9621ff9851SBasavaraja M S 	FLAG(ctrl3, PCI_SEC_LNKCTL3_PERFORM_LINK_EQU));
9721ff9851SBasavaraja M S 
9821ff9851SBasavaraja M S   lane_err_stat = get_conf_word(d, where + PCI_SEC_LANE_ERR);
9921ff9851SBasavaraja M S   printf("\t\tLaneErrStat: ");
10021ff9851SBasavaraja M S   if (lane_err_stat)
10121ff9851SBasavaraja M S     {
1029f7dc65cSMartin Mares       printf("LaneErr at lane:");
10321ff9851SBasavaraja M S       for (lane = 0; lane_err_stat; lane_err_stat >>= 1, lane += 1)
10421ff9851SBasavaraja M S         if (BITS(lane_err_stat, 0, 1))
10521ff9851SBasavaraja M S           printf(" %u", lane);
10621ff9851SBasavaraja M S     }
10721ff9851SBasavaraja M S   else
10821ff9851SBasavaraja M S     printf("0");
10921ff9851SBasavaraja M S   printf("\n");
11021ff9851SBasavaraja M S }
11121ff9851SBasavaraja M S 
11221ff9851SBasavaraja M S static void
cap_dsn(struct device * d,int where)113c7a34993SMartin Mares cap_dsn(struct device *d, int where)
114c7a34993SMartin Mares {
115c7a34993SMartin Mares   u32 t1, t2;
116c7a34993SMartin Mares   if (!config_fetch(d, where + 4, 8))
117c7a34993SMartin Mares     return;
118c7a34993SMartin Mares   t1 = get_conf_long(d, where + 4);
119c7a34993SMartin Mares   t2 = get_conf_long(d, where + 8);
120c7a34993SMartin Mares   printf("Device Serial Number %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n",
1216f9f8fd7SMatthew Wilcox 	t2 >> 24, (t2 >> 16) & 0xff, (t2 >> 8) & 0xff, t2 & 0xff,
1226f9f8fd7SMatthew Wilcox 	t1 >> 24, (t1 >> 16) & 0xff, (t1 >> 8) & 0xff, t1 & 0xff);
123c7a34993SMartin Mares }
124c7a34993SMartin Mares 
125c7a34993SMartin Mares static void
cap_aer(struct device * d,int where,int type)126a1492b88SBjorn Helgaas cap_aer(struct device *d, int where, int type)
127c7a34993SMartin Mares {
128a6625432SBjorn Helgaas   u32 l, l0, l1, l2, l3;
129a1492b88SBjorn Helgaas   u16 w;
130c7a34993SMartin Mares 
131c7a34993SMartin Mares   printf("Advanced Error Reporting\n");
1329a2e4b35SYu Zhao   if (verbose < 2)
1339a2e4b35SYu Zhao     return;
1349a2e4b35SYu Zhao 
135a6625432SBjorn Helgaas   if (!config_fetch(d, where + PCI_ERR_UNCOR_STATUS, 40))
136c7a34993SMartin Mares     return;
137c7a34993SMartin Mares 
138c7a34993SMartin Mares   l = get_conf_long(d, where + PCI_ERR_UNCOR_STATUS);
139144b0911SShuai Xue   printf("\t\tUESta:\tDLP%c SDES%c TLP%c FCP%c CmpltTO%c CmpltAbrt%c UnxCmplt%c RxOF%c MalfTLP%c\n"
140144b0911SShuai Xue   "\t\t\tECRC%c UnsupReq%c ACSViol%c UncorrIntErr%c BlockedTLP%c AtomicOpBlocked%c TLPBlockedErr%c\n"
141144b0911SShuai Xue   "\t\t\tPoisonTLPBlocked%c DMWrReqBlocked%c IDECheck%c MisIDETLP%c PCRC_CHECK%c TLPXlatBlocked%c\n",
142c7a34993SMartin Mares 	FLAG(l, PCI_ERR_UNC_DLP), FLAG(l, PCI_ERR_UNC_SDES), FLAG(l, PCI_ERR_UNC_POISON_TLP),
143c7a34993SMartin Mares 	FLAG(l, PCI_ERR_UNC_FCP), FLAG(l, PCI_ERR_UNC_COMP_TIME), FLAG(l, PCI_ERR_UNC_COMP_ABORT),
144c7a34993SMartin Mares 	FLAG(l, PCI_ERR_UNC_UNX_COMP), FLAG(l, PCI_ERR_UNC_RX_OVER), FLAG(l, PCI_ERR_UNC_MALF_TLP),
145144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_ECRC), FLAG(l, PCI_ERR_UNC_UNSUP), FLAG(l, PCI_ERR_UNC_ACS_VIOL),
146144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_INTERNAL), FLAG(l, PCI_ERR_UNC_MC_BLOCKED_TLP),
147144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_ATOMICOP_EGRESS_BLOCKED), FLAG(l, PCI_ERR_UNC_TLP_PREFIX_BLOCKED),
148144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_POISONED_TLP_EGRESS), FLAG(l, PCI_ERR_UNC_DMWR_REQ_EGRESS_BLOCKED),
149144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_IDE_CHECK), FLAG(l, PCI_ERR_UNC_MISR_IDE_TLP), FLAG(l, PCI_ERR_UNC_PCRC_CHECK),
150144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_TLP_XLAT_EGRESS_BLOCKED));
151c7a34993SMartin Mares   l = get_conf_long(d, where + PCI_ERR_UNCOR_MASK);
152144b0911SShuai Xue   printf("\t\tUEMsk:\tDLP%c SDES%c TLP%c FCP%c CmpltTO%c CmpltAbrt%c UnxCmplt%c RxOF%c MalfTLP%c\n"
153144b0911SShuai Xue   "\t\t\tECRC%c UnsupReq%c ACSViol%c UncorrIntErr%c BlockedTLP%c AtomicOpBlocked%c TLPBlockedErr%c\n"
154144b0911SShuai Xue   "\t\t\tPoisonTLPBlocked%c DMWrReqBlocked%c IDECheck%c MisIDETLP%c PCRC_CHECK%c TLPXlatBlocked%c\n",
155c7a34993SMartin Mares 	FLAG(l, PCI_ERR_UNC_DLP), FLAG(l, PCI_ERR_UNC_SDES), FLAG(l, PCI_ERR_UNC_POISON_TLP),
156c7a34993SMartin Mares 	FLAG(l, PCI_ERR_UNC_FCP), FLAG(l, PCI_ERR_UNC_COMP_TIME), FLAG(l, PCI_ERR_UNC_COMP_ABORT),
157c7a34993SMartin Mares 	FLAG(l, PCI_ERR_UNC_UNX_COMP), FLAG(l, PCI_ERR_UNC_RX_OVER), FLAG(l, PCI_ERR_UNC_MALF_TLP),
158144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_ECRC), FLAG(l, PCI_ERR_UNC_UNSUP), FLAG(l, PCI_ERR_UNC_ACS_VIOL),
159144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_INTERNAL), FLAG(l, PCI_ERR_UNC_MC_BLOCKED_TLP),
160144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_ATOMICOP_EGRESS_BLOCKED), FLAG(l, PCI_ERR_UNC_TLP_PREFIX_BLOCKED),
161144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_POISONED_TLP_EGRESS), FLAG(l, PCI_ERR_UNC_DMWR_REQ_EGRESS_BLOCKED),
162144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_IDE_CHECK), FLAG(l, PCI_ERR_UNC_MISR_IDE_TLP), FLAG(l, PCI_ERR_UNC_PCRC_CHECK),
163144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_TLP_XLAT_EGRESS_BLOCKED));
164c7a34993SMartin Mares   l = get_conf_long(d, where + PCI_ERR_UNCOR_SEVER);
165144b0911SShuai Xue   printf("\t\tUESvrt:\tDLP%c SDES%c TLP%c FCP%c CmpltTO%c CmpltAbrt%c UnxCmplt%c RxOF%c MalfTLP%c\n"
166144b0911SShuai Xue   "\t\t\tECRC%c UnsupReq%c ACSViol%c UncorrIntErr%c BlockedTLP%c AtomicOpBlocked%c TLPBlockedErr%c\n"
167144b0911SShuai Xue   "\t\t\tPoisonTLPBlocked%c DMWrReqBlocked%c IDECheck%c MisIDETLP%c PCRC_CHECK%c TLPXlatBlocked%c\n",
168c7a34993SMartin Mares 	FLAG(l, PCI_ERR_UNC_DLP), FLAG(l, PCI_ERR_UNC_SDES), FLAG(l, PCI_ERR_UNC_POISON_TLP),
169c7a34993SMartin Mares 	FLAG(l, PCI_ERR_UNC_FCP), FLAG(l, PCI_ERR_UNC_COMP_TIME), FLAG(l, PCI_ERR_UNC_COMP_ABORT),
170c7a34993SMartin Mares 	FLAG(l, PCI_ERR_UNC_UNX_COMP), FLAG(l, PCI_ERR_UNC_RX_OVER), FLAG(l, PCI_ERR_UNC_MALF_TLP),
171144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_ECRC), FLAG(l, PCI_ERR_UNC_UNSUP), FLAG(l, PCI_ERR_UNC_ACS_VIOL),
172144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_INTERNAL), FLAG(l, PCI_ERR_UNC_MC_BLOCKED_TLP),
173144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_ATOMICOP_EGRESS_BLOCKED), FLAG(l, PCI_ERR_UNC_TLP_PREFIX_BLOCKED),
174144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_POISONED_TLP_EGRESS), FLAG(l, PCI_ERR_UNC_DMWR_REQ_EGRESS_BLOCKED),
175144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_IDE_CHECK), FLAG(l, PCI_ERR_UNC_MISR_IDE_TLP), FLAG(l, PCI_ERR_UNC_PCRC_CHECK),
176144b0911SShuai Xue 	FLAG(l, PCI_ERR_UNC_TLP_XLAT_EGRESS_BLOCKED));
177c7a34993SMartin Mares   l = get_conf_long(d, where + PCI_ERR_COR_STATUS);
178144b0911SShuai Xue   printf("\t\tCESta:\tRxErr%c BadTLP%c BadDLLP%c Rollover%c Timeout%c AdvNonFatalErr%c "
179144b0911SShuai Xue   "CorrIntErr%c HeaderOF%c\n",
180c7a34993SMartin Mares 	FLAG(l, PCI_ERR_COR_RCVR), FLAG(l, PCI_ERR_COR_BAD_TLP), FLAG(l, PCI_ERR_COR_BAD_DLLP),
181144b0911SShuai Xue 	FLAG(l, PCI_ERR_COR_REP_ROLL), FLAG(l, PCI_ERR_COR_REP_TIMER), FLAG(l, PCI_ERR_COR_REP_ANFE),
182144b0911SShuai Xue 	FLAG(l, PCI_ERR_COR_INTERNAL), FLAG(l, PCI_ERR_COR_HDRLOG_OVER));
183c7a34993SMartin Mares   l = get_conf_long(d, where + PCI_ERR_COR_MASK);
184144b0911SShuai Xue   printf("\t\tCEMsk:\tRxErr%c BadTLP%c BadDLLP%c Rollover%c Timeout%c AdvNonFatalErr%c "
185144b0911SShuai Xue   "CorrIntErr%c HeaderOF%c\n",
186c7a34993SMartin Mares 	FLAG(l, PCI_ERR_COR_RCVR), FLAG(l, PCI_ERR_COR_BAD_TLP), FLAG(l, PCI_ERR_COR_BAD_DLLP),
187144b0911SShuai Xue 	FLAG(l, PCI_ERR_COR_REP_ROLL), FLAG(l, PCI_ERR_COR_REP_TIMER), FLAG(l, PCI_ERR_COR_REP_ANFE),
188144b0911SShuai Xue 	FLAG(l, PCI_ERR_COR_INTERNAL), FLAG(l, PCI_ERR_COR_HDRLOG_OVER));
189c7a34993SMartin Mares   l = get_conf_long(d, where + PCI_ERR_CAP);
1909a54979eSBjorn Helgaas   printf("\t\tAERCap:\tFirst Error Pointer: %02x, ECRCGenCap%c ECRCGenEn%c ECRCChkCap%c ECRCChkEn%c\n"
191b33a4a2bSBjorn Helgaas 	"\t\t\tMultHdrRecCap%c MultHdrRecEn%c TLPPfxPres%c HdrLogCap%c\n",
192c7a34993SMartin Mares 	PCI_ERR_CAP_FEP(l), FLAG(l, PCI_ERR_CAP_ECRC_GENC), FLAG(l, PCI_ERR_CAP_ECRC_GENE),
193b33a4a2bSBjorn Helgaas 	FLAG(l, PCI_ERR_CAP_ECRC_CHKC), FLAG(l, PCI_ERR_CAP_ECRC_CHKE),
194b33a4a2bSBjorn Helgaas 	FLAG(l, PCI_ERR_CAP_MULT_HDRC), FLAG(l, PCI_ERR_CAP_MULT_HDRE),
195b33a4a2bSBjorn Helgaas 	FLAG(l, PCI_ERR_CAP_TLP_PFX), FLAG(l, PCI_ERR_CAP_HDR_LOG));
196a6625432SBjorn Helgaas 
197a6625432SBjorn Helgaas   l0 = get_conf_long(d, where + PCI_ERR_HEADER_LOG);
198a6625432SBjorn Helgaas   l1 = get_conf_long(d, where + PCI_ERR_HEADER_LOG + 4);
199a6625432SBjorn Helgaas   l2 = get_conf_long(d, where + PCI_ERR_HEADER_LOG + 8);
200a6625432SBjorn Helgaas   l3 = get_conf_long(d, where + PCI_ERR_HEADER_LOG + 12);
201a6625432SBjorn Helgaas   printf("\t\tHeaderLog: %08x %08x %08x %08x\n", l0, l1, l2, l3);
202a1492b88SBjorn Helgaas 
203a1492b88SBjorn Helgaas   if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_ROOT_EC)
204a1492b88SBjorn Helgaas     {
205a1492b88SBjorn Helgaas       if (!config_fetch(d, where + PCI_ERR_ROOT_COMMAND, 12))
206a1492b88SBjorn Helgaas         return;
207a1492b88SBjorn Helgaas 
208a1492b88SBjorn Helgaas       l = get_conf_long(d, where + PCI_ERR_ROOT_COMMAND);
209a1492b88SBjorn Helgaas       printf("\t\tRootCmd: CERptEn%c NFERptEn%c FERptEn%c\n",
210a1492b88SBjorn Helgaas 	    FLAG(l, PCI_ERR_ROOT_CMD_COR_EN),
211a1492b88SBjorn Helgaas 	    FLAG(l, PCI_ERR_ROOT_CMD_NONFATAL_EN),
212a1492b88SBjorn Helgaas 	    FLAG(l, PCI_ERR_ROOT_CMD_FATAL_EN));
213a1492b88SBjorn Helgaas 
214a1492b88SBjorn Helgaas       l = get_conf_long(d, where + PCI_ERR_ROOT_STATUS);
215a1492b88SBjorn Helgaas       printf("\t\tRootSta: CERcvd%c MultCERcvd%c UERcvd%c MultUERcvd%c\n"
216aeb74fe2SBjorn Helgaas 	    "\t\t\t FirstFatal%c NonFatalMsg%c FatalMsg%c IntMsgNum %d\n",
217a1492b88SBjorn Helgaas 	    FLAG(l, PCI_ERR_ROOT_COR_RCV),
218a1492b88SBjorn Helgaas 	    FLAG(l, PCI_ERR_ROOT_MULTI_COR_RCV),
219a1492b88SBjorn Helgaas 	    FLAG(l, PCI_ERR_ROOT_UNCOR_RCV),
220a1492b88SBjorn Helgaas 	    FLAG(l, PCI_ERR_ROOT_MULTI_UNCOR_RCV),
221a1492b88SBjorn Helgaas 	    FLAG(l, PCI_ERR_ROOT_FIRST_FATAL),
222a1492b88SBjorn Helgaas 	    FLAG(l, PCI_ERR_ROOT_NONFATAL_RCV),
223a1492b88SBjorn Helgaas 	    FLAG(l, PCI_ERR_ROOT_FATAL_RCV),
224a1492b88SBjorn Helgaas 	    PCI_ERR_MSG_NUM(l));
225a1492b88SBjorn Helgaas 
226a1492b88SBjorn Helgaas       w = get_conf_word(d, where + PCI_ERR_ROOT_COR_SRC);
227a1492b88SBjorn Helgaas       printf("\t\tErrorSrc: ERR_COR: %04x ", w);
228a1492b88SBjorn Helgaas 
229a1492b88SBjorn Helgaas       w = get_conf_word(d, where + PCI_ERR_ROOT_SRC);
230a1492b88SBjorn Helgaas       printf("ERR_FATAL/NONFATAL: %04x\n", w);
231a1492b88SBjorn Helgaas     }
232c7a34993SMartin Mares }
233c7a34993SMartin Mares 
cap_dpc(struct device * d,int where)234de91b6f2SKeith Busch static void cap_dpc(struct device *d, int where)
235de91b6f2SKeith Busch {
236de91b6f2SKeith Busch   u16 l;
237de91b6f2SKeith Busch 
238de91b6f2SKeith Busch   printf("Downstream Port Containment\n");
239de91b6f2SKeith Busch   if (verbose < 2)
240de91b6f2SKeith Busch     return;
241de91b6f2SKeith Busch 
242de91b6f2SKeith Busch   if (!config_fetch(d, where + PCI_DPC_CAP, 8))
243de91b6f2SKeith Busch     return;
244de91b6f2SKeith Busch 
245de91b6f2SKeith Busch   l = get_conf_word(d, where + PCI_DPC_CAP);
246aeb74fe2SBjorn Helgaas   printf("\t\tDpcCap:\tIntMsgNum %d, RPExt%c PoisonedTLP%c SwTrigger%c RP PIO Log %d, DL_ActiveErr%c\n",
247de91b6f2SKeith Busch     PCI_DPC_CAP_INT_MSG(l), FLAG(l, PCI_DPC_CAP_RP_EXT), FLAG(l, PCI_DPC_CAP_TLP_BLOCK),
248de91b6f2SKeith Busch     FLAG(l, PCI_DPC_CAP_SW_TRIGGER), PCI_DPC_CAP_RP_LOG(l), FLAG(l, PCI_DPC_CAP_DL_ACT_ERR));
249de91b6f2SKeith Busch 
250de91b6f2SKeith Busch   l = get_conf_word(d, where + PCI_DPC_CTL);
251de91b6f2SKeith Busch   printf("\t\tDpcCtl:\tTrigger:%x Cmpl%c INT%c ErrCor%c PoisonedTLP%c SwTrigger%c DL_ActiveErr%c\n",
252de91b6f2SKeith Busch     PCI_DPC_CTL_TRIGGER(l), FLAG(l, PCI_DPC_CTL_CMPL), FLAG(l, PCI_DPC_CTL_INT),
253de91b6f2SKeith Busch     FLAG(l, PCI_DPC_CTL_ERR_COR), FLAG(l, PCI_DPC_CTL_TLP), FLAG(l, PCI_DPC_CTL_SW_TRIGGER),
254de91b6f2SKeith Busch     FLAG(l, PCI_DPC_CTL_DL_ACTIVE));
255de91b6f2SKeith Busch 
256de91b6f2SKeith Busch   l = get_conf_word(d, where + PCI_DPC_STATUS);
257de91b6f2SKeith Busch   printf("\t\tDpcSta:\tTrigger%c Reason:%02x INT%c RPBusy%c TriggerExt:%02x RP PIO ErrPtr:%02x\n",
258de91b6f2SKeith Busch     FLAG(l, PCI_DPC_STS_TRIGGER), PCI_DPC_STS_REASON(l), FLAG(l, PCI_DPC_STS_INT),
259de91b6f2SKeith Busch     FLAG(l, PCI_DPC_STS_RP_BUSY), PCI_DPC_STS_TRIGGER_EXT(l), PCI_DPC_STS_PIO_FEP(l));
260de91b6f2SKeith Busch 
261de91b6f2SKeith Busch   l = get_conf_word(d, where + PCI_DPC_SOURCE);
262de91b6f2SKeith Busch   printf("\t\tSource:\t%04x\n", l);
263de91b6f2SKeith Busch }
264de91b6f2SKeith Busch 
265c7a34993SMartin Mares static void
cap_acs(struct device * d,int where)266c7a34993SMartin Mares cap_acs(struct device *d, int where)
267c7a34993SMartin Mares {
268c7a34993SMartin Mares   u16 w;
269c7a34993SMartin Mares 
270c7a34993SMartin Mares   printf("Access Control Services\n");
2719a2e4b35SYu Zhao   if (verbose < 2)
2729a2e4b35SYu Zhao     return;
2739a2e4b35SYu Zhao 
274c7a34993SMartin Mares   if (!config_fetch(d, where + PCI_ACS_CAP, 4))
275c7a34993SMartin Mares     return;
276c7a34993SMartin Mares 
277c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_ACS_CAP);
278c7a34993SMartin Mares   printf("\t\tACSCap:\tSrcValid%c TransBlk%c ReqRedir%c CmpltRedir%c UpstreamFwd%c EgressCtrl%c "
279c7a34993SMartin Mares 	"DirectTrans%c\n",
280c7a34993SMartin Mares 	FLAG(w, PCI_ACS_CAP_VALID), FLAG(w, PCI_ACS_CAP_BLOCK), FLAG(w, PCI_ACS_CAP_REQ_RED),
281c7a34993SMartin Mares 	FLAG(w, PCI_ACS_CAP_CMPLT_RED), FLAG(w, PCI_ACS_CAP_FORWARD), FLAG(w, PCI_ACS_CAP_EGRESS),
282c7a34993SMartin Mares 	FLAG(w, PCI_ACS_CAP_TRANS));
283c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_ACS_CTRL);
284c7a34993SMartin Mares   printf("\t\tACSCtl:\tSrcValid%c TransBlk%c ReqRedir%c CmpltRedir%c UpstreamFwd%c EgressCtrl%c "
285c7a34993SMartin Mares 	"DirectTrans%c\n",
286c7a34993SMartin Mares 	FLAG(w, PCI_ACS_CTRL_VALID), FLAG(w, PCI_ACS_CTRL_BLOCK), FLAG(w, PCI_ACS_CTRL_REQ_RED),
287c7a34993SMartin Mares 	FLAG(w, PCI_ACS_CTRL_CMPLT_RED), FLAG(w, PCI_ACS_CTRL_FORWARD), FLAG(w, PCI_ACS_CTRL_EGRESS),
288c7a34993SMartin Mares 	FLAG(w, PCI_ACS_CTRL_TRANS));
289c7a34993SMartin Mares }
290c7a34993SMartin Mares 
291c7a34993SMartin Mares static void
cap_ari(struct device * d,int where)292c7a34993SMartin Mares cap_ari(struct device *d, int where)
293c7a34993SMartin Mares {
294c7a34993SMartin Mares   u16 w;
295c7a34993SMartin Mares 
296c7a34993SMartin Mares   printf("Alternative Routing-ID Interpretation (ARI)\n");
2979a2e4b35SYu Zhao   if (verbose < 2)
2989a2e4b35SYu Zhao     return;
2999a2e4b35SYu Zhao 
300c7a34993SMartin Mares   if (!config_fetch(d, where + PCI_ARI_CAP, 4))
301c7a34993SMartin Mares     return;
302c7a34993SMartin Mares 
303c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_ARI_CAP);
304c7a34993SMartin Mares   printf("\t\tARICap:\tMFVC%c ACS%c, Next Function: %d\n",
305c7a34993SMartin Mares 	FLAG(w, PCI_ARI_CAP_MFVC), FLAG(w, PCI_ARI_CAP_ACS),
306c7a34993SMartin Mares 	PCI_ARI_CAP_NFN(w));
307c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_ARI_CTRL);
308c7a34993SMartin Mares   printf("\t\tARICtl:\tMFVC%c ACS%c, Function Group: %d\n",
309c7a34993SMartin Mares 	FLAG(w, PCI_ARI_CTRL_MFVC), FLAG(w, PCI_ARI_CTRL_ACS),
310c7a34993SMartin Mares 	PCI_ARI_CTRL_FG(w));
311c7a34993SMartin Mares }
312c7a34993SMartin Mares 
313c7a34993SMartin Mares static void
cap_ats(struct device * d,int where)314c7a34993SMartin Mares cap_ats(struct device *d, int where)
315c7a34993SMartin Mares {
316c7a34993SMartin Mares   u16 w;
317c7a34993SMartin Mares 
318c7a34993SMartin Mares   printf("Address Translation Service (ATS)\n");
3199a2e4b35SYu Zhao   if (verbose < 2)
3209a2e4b35SYu Zhao     return;
3219a2e4b35SYu Zhao 
322c7a34993SMartin Mares   if (!config_fetch(d, where + PCI_ATS_CAP, 4))
323c7a34993SMartin Mares     return;
324c7a34993SMartin Mares 
325c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_ATS_CAP);
326c7a34993SMartin Mares   printf("\t\tATSCap:\tInvalidate Queue Depth: %02x\n", PCI_ATS_CAP_IQD(w));
327c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_ATS_CTRL);
328c7a34993SMartin Mares   printf("\t\tATSCtl:\tEnable%c, Smallest Translation Unit: %02x\n",
329c7a34993SMartin Mares 	FLAG(w, PCI_ATS_CTRL_ENABLE), PCI_ATS_CTRL_STU(w));
330c7a34993SMartin Mares }
331c7a34993SMartin Mares 
332c7a34993SMartin Mares static void
cap_pri(struct device * d,int where)333a858df0dSDavid Woodhouse cap_pri(struct device *d, int where)
334a858df0dSDavid Woodhouse {
335a858df0dSDavid Woodhouse   u16 w;
336a858df0dSDavid Woodhouse   u32 l;
337a858df0dSDavid Woodhouse 
338a858df0dSDavid Woodhouse   printf("Page Request Interface (PRI)\n");
339a858df0dSDavid Woodhouse   if (verbose < 2)
340a858df0dSDavid Woodhouse     return;
341a858df0dSDavid Woodhouse 
342a858df0dSDavid Woodhouse   if (!config_fetch(d, where + PCI_PRI_CTRL, 0xc))
343a858df0dSDavid Woodhouse     return;
344a858df0dSDavid Woodhouse 
345a858df0dSDavid Woodhouse   w = get_conf_word(d, where + PCI_PRI_CTRL);
346bfd8658fSMartin Mares   printf("\t\tPRICtl: Enable%c Reset%c\n",
347a858df0dSDavid Woodhouse 	FLAG(w, PCI_PRI_CTRL_ENABLE), FLAG(w, PCI_PRI_CTRL_RESET));
348a858df0dSDavid Woodhouse   w = get_conf_word(d, where + PCI_PRI_STATUS);
349548a6e3bSAshok Raj   printf("\t\tPRISta: RF%c UPRGI%c Stopped%c PASID%c\n",
350a858df0dSDavid Woodhouse 	FLAG(w, PCI_PRI_STATUS_RF), FLAG(w, PCI_PRI_STATUS_UPRGI),
351548a6e3bSAshok Raj 	FLAG(w, PCI_PRI_STATUS_STOPPED), FLAG(w, PCI_PRI_STATUS_PASID));
352a858df0dSDavid Woodhouse   l = get_conf_long(d, where + PCI_PRI_MAX_REQ);
353a858df0dSDavid Woodhouse   printf("\t\tPage Request Capacity: %08x, ", l);
354a858df0dSDavid Woodhouse   l = get_conf_long(d, where + PCI_PRI_ALLOC_REQ);
355a858df0dSDavid Woodhouse   printf("Page Request Allocation: %08x\n", l);
356a858df0dSDavid Woodhouse }
357a858df0dSDavid Woodhouse 
358a858df0dSDavid Woodhouse static void
cap_pasid(struct device * d,int where)359a858df0dSDavid Woodhouse cap_pasid(struct device *d, int where)
360a858df0dSDavid Woodhouse {
361a858df0dSDavid Woodhouse   u16 w;
362a858df0dSDavid Woodhouse 
363a858df0dSDavid Woodhouse   printf("Process Address Space ID (PASID)\n");
364a858df0dSDavid Woodhouse   if (verbose < 2)
365a858df0dSDavid Woodhouse     return;
366a858df0dSDavid Woodhouse 
367a858df0dSDavid Woodhouse   if (!config_fetch(d, where + PCI_PASID_CAP, 4))
368a858df0dSDavid Woodhouse     return;
369a858df0dSDavid Woodhouse 
370a858df0dSDavid Woodhouse   w = get_conf_word(d, where + PCI_PASID_CAP);
371bfd8658fSMartin Mares   printf("\t\tPASIDCap: Exec%c Priv%c, Max PASID Width: %02x\n",
372a858df0dSDavid Woodhouse 	FLAG(w, PCI_PASID_CAP_EXEC), FLAG(w, PCI_PASID_CAP_PRIV),
373a858df0dSDavid Woodhouse 	PCI_PASID_CAP_WIDTH(w));
374a858df0dSDavid Woodhouse   w = get_conf_word(d, where + PCI_PASID_CTRL);
375bfd8658fSMartin Mares   printf("\t\tPASIDCtl: Enable%c Exec%c Priv%c\n",
376a858df0dSDavid Woodhouse 	FLAG(w, PCI_PASID_CTRL_ENABLE), FLAG(w, PCI_PASID_CTRL_EXEC),
377a858df0dSDavid Woodhouse 	FLAG(w, PCI_PASID_CTRL_PRIV));
378a858df0dSDavid Woodhouse }
379a858df0dSDavid Woodhouse 
380a858df0dSDavid Woodhouse static void
cap_sriov(struct device * d,int where)381c7a34993SMartin Mares cap_sriov(struct device *d, int where)
382c7a34993SMartin Mares {
383c7a34993SMartin Mares   u16 b;
384c7a34993SMartin Mares   u16 w;
385c7a34993SMartin Mares   u32 l;
38667e78b32SChris Wright   int i;
387c7a34993SMartin Mares 
388c7a34993SMartin Mares   printf("Single Root I/O Virtualization (SR-IOV)\n");
3899a2e4b35SYu Zhao   if (verbose < 2)
3909a2e4b35SYu Zhao     return;
3919a2e4b35SYu Zhao 
392c7a34993SMartin Mares   if (!config_fetch(d, where + PCI_IOV_CAP, 0x3c))
393c7a34993SMartin Mares     return;
394c7a34993SMartin Mares 
395c7a34993SMartin Mares   l = get_conf_long(d, where + PCI_IOV_CAP);
396aeb74fe2SBjorn Helgaas   printf("\t\tIOVCap:\tMigration%c 10BitTagReq%c IntMsgNum %d\n",
397053d08d2SDongdong Liu 	FLAG(l, PCI_IOV_CAP_VFM), FLAG(l, PCI_IOV_CAP_VF_10BIT_TAG_REQ), PCI_IOV_CAP_IMN(l));
398c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_IOV_CTRL);
399053d08d2SDongdong Liu   printf("\t\tIOVCtl:\tEnable%c Migration%c Interrupt%c MSE%c ARIHierarchy%c 10BitTagReq%c\n",
400c7a34993SMartin Mares 	FLAG(w, PCI_IOV_CTRL_VFE), FLAG(w, PCI_IOV_CTRL_VFME),
401c7a34993SMartin Mares 	FLAG(w, PCI_IOV_CTRL_VFMIE), FLAG(w, PCI_IOV_CTRL_MSE),
402053d08d2SDongdong Liu 	FLAG(w, PCI_IOV_CTRL_ARI), FLAG(w, PCI_IOV_CTRL_VF_10BIT_TAG_REQ_EN));
403c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_IOV_STATUS);
404c7a34993SMartin Mares   printf("\t\tIOVSta:\tMigration%c\n", FLAG(w, PCI_IOV_STATUS_MS));
405c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_IOV_INITIALVF);
406c7a34993SMartin Mares   printf("\t\tInitial VFs: %d, ", w);
407c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_IOV_TOTALVF);
408c7a34993SMartin Mares   printf("Total VFs: %d, ", w);
409c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_IOV_NUMVF);
410c7a34993SMartin Mares   printf("Number of VFs: %d, ", w);
411c7a34993SMartin Mares   b = get_conf_byte(d, where + PCI_IOV_FDL);
412c7a34993SMartin Mares   printf("Function Dependency Link: %02x\n", b);
413c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_IOV_OFFSET);
414c7a34993SMartin Mares   printf("\t\tVF offset: %d, ", w);
415c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_IOV_STRIDE);
416c7a34993SMartin Mares   printf("stride: %d, ", w);
417c7a34993SMartin Mares   w = get_conf_word(d, where + PCI_IOV_DID);
418c7a34993SMartin Mares   printf("Device ID: %04x\n", w);
419c7a34993SMartin Mares   l = get_conf_long(d, where + PCI_IOV_SUPPS);
420c7a34993SMartin Mares   printf("\t\tSupported Page Size: %08x, ", l);
421c7a34993SMartin Mares   l = get_conf_long(d, where + PCI_IOV_SYSPS);
422c7a34993SMartin Mares   printf("System Page Size: %08x\n", l);
423b9e11c65SMartin Mares 
424b9e11c65SMartin Mares   for (i=0; i < PCI_IOV_NUM_BAR; i++)
425b9e11c65SMartin Mares     {
426187bf2f5SMartin Mares       u32 addr;
42767e78b32SChris Wright       int type;
42867e78b32SChris Wright       u32 h;
429b9e11c65SMartin Mares       l = get_conf_long(d, where + PCI_IOV_BAR_BASE + 4*i);
43067e78b32SChris Wright       if (l == 0xffffffff)
43167e78b32SChris Wright 	l = 0;
43267e78b32SChris Wright       if (!l)
43367e78b32SChris Wright 	continue;
43467e78b32SChris Wright       printf("\t\tRegion %d: Memory at ", i);
43567e78b32SChris Wright       addr = l & PCI_ADDR_MEM_MASK;
43667e78b32SChris Wright       type = l & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
437b9e11c65SMartin Mares       if (type == PCI_BASE_ADDRESS_MEM_TYPE_64)
438b9e11c65SMartin Mares 	{
43967e78b32SChris Wright 	  i++;
44067e78b32SChris Wright 	  h = get_conf_long(d, where + PCI_IOV_BAR_BASE + (i*4));
441187bf2f5SMartin Mares 	  printf("%08x", h);
44267e78b32SChris Wright 	}
443187bf2f5SMartin Mares       printf("%08x (%s-bit, %sprefetchable)\n",
444187bf2f5SMartin Mares 	addr,
44567e78b32SChris Wright 	(type == PCI_BASE_ADDRESS_MEM_TYPE_32) ? "32" : "64",
44667e78b32SChris Wright 	(l & PCI_BASE_ADDRESS_MEM_PREFETCH) ? "" : "non-");
44767e78b32SChris Wright     }
448b9e11c65SMartin Mares 
449edca3520SYu Zhao   l = get_conf_long(d, where + PCI_IOV_MSAO);
450c7a34993SMartin Mares   printf("\t\tVF Migration: offset: %08x, BIR: %x\n", PCI_IOV_MSA_OFFSET(l),
451c7a34993SMartin Mares 	PCI_IOV_MSA_BIR(l));
452c7a34993SMartin Mares }
453c7a34993SMartin Mares 
45433088c24SMartin Mares static void
cap_multicast(struct device * d,int where,int type)455c0d9545cSBjorn Helgaas cap_multicast(struct device *d, int where, int type)
456c0d9545cSBjorn Helgaas {
457c0d9545cSBjorn Helgaas   u16 w;
458c0d9545cSBjorn Helgaas   u32 l;
459c0d9545cSBjorn Helgaas   u64 bar, rcv, block;
460c0d9545cSBjorn Helgaas 
461c0d9545cSBjorn Helgaas   printf("Multicast\n");
462c0d9545cSBjorn Helgaas   if (verbose < 2)
463c0d9545cSBjorn Helgaas     return;
464c0d9545cSBjorn Helgaas 
465c0d9545cSBjorn Helgaas   if (!config_fetch(d, where + PCI_MCAST_CAP, 0x30))
466c0d9545cSBjorn Helgaas     return;
467c0d9545cSBjorn Helgaas 
468c0d9545cSBjorn Helgaas   w = get_conf_word(d, where + PCI_MCAST_CAP);
469c0d9545cSBjorn Helgaas   printf("\t\tMcastCap: MaxGroups %d", PCI_MCAST_CAP_MAX_GROUP(w) + 1);
470c0d9545cSBjorn Helgaas   if (type == PCI_EXP_TYPE_ENDPOINT || type == PCI_EXP_TYPE_ROOT_INT_EP)
471c0d9545cSBjorn Helgaas     printf(", WindowSz %d (%d bytes)",
472c0d9545cSBjorn Helgaas       PCI_MCAST_CAP_WIN_SIZE(w), 1 << PCI_MCAST_CAP_WIN_SIZE(w));
473c0d9545cSBjorn Helgaas   if (type == PCI_EXP_TYPE_ROOT_PORT ||
474c0d9545cSBjorn Helgaas       type == PCI_EXP_TYPE_UPSTREAM || type == PCI_EXP_TYPE_DOWNSTREAM)
475c0d9545cSBjorn Helgaas     printf(", ECRCRegen%c\n", FLAG(w, PCI_MCAST_CAP_ECRC));
476c0d9545cSBjorn Helgaas   w = get_conf_word(d, where + PCI_MCAST_CTRL);
477c0d9545cSBjorn Helgaas   printf("\t\tMcastCtl: NumGroups %d, Enable%c\n",
478c0d9545cSBjorn Helgaas     PCI_MCAST_CTRL_NUM_GROUP(w) + 1, FLAG(w, PCI_MCAST_CTRL_ENABLE));
479c0d9545cSBjorn Helgaas   bar = get_conf_long(d, where + PCI_MCAST_BAR);
480c0d9545cSBjorn Helgaas   l = get_conf_long(d, where + PCI_MCAST_BAR + 4);
481c0d9545cSBjorn Helgaas   bar |= (u64) l << 32;
482c0d9545cSBjorn Helgaas   printf("\t\tMcastBAR: IndexPos %d, BaseAddr %016" PCI_U64_FMT_X "\n",
483c0d9545cSBjorn Helgaas     PCI_MCAST_BAR_INDEX_POS(bar), bar & PCI_MCAST_BAR_MASK);
484c0d9545cSBjorn Helgaas   rcv = get_conf_long(d, where + PCI_MCAST_RCV);
485c0d9545cSBjorn Helgaas   l = get_conf_long(d, where + PCI_MCAST_RCV + 4);
486c0d9545cSBjorn Helgaas   rcv |= (u64) l << 32;
487c0d9545cSBjorn Helgaas   printf("\t\tMcastReceiveVec:      %016" PCI_U64_FMT_X "\n", rcv);
488c0d9545cSBjorn Helgaas   block = get_conf_long(d, where + PCI_MCAST_BLOCK);
489c0d9545cSBjorn Helgaas   l = get_conf_long(d, where + PCI_MCAST_BLOCK + 4);
490c0d9545cSBjorn Helgaas   block |= (u64) l << 32;
491c0d9545cSBjorn Helgaas   printf("\t\tMcastBlockAllVec:     %016" PCI_U64_FMT_X "\n", block);
492c0d9545cSBjorn Helgaas   block = get_conf_long(d, where + PCI_MCAST_BLOCK_UNTRANS);
493c0d9545cSBjorn Helgaas   l = get_conf_long(d, where + PCI_MCAST_BLOCK_UNTRANS + 4);
494c0d9545cSBjorn Helgaas   block |= (u64) l << 32;
495c0d9545cSBjorn Helgaas   printf("\t\tMcastBlockUntransVec: %016" PCI_U64_FMT_X "\n", block);
496c0d9545cSBjorn Helgaas 
497c0d9545cSBjorn Helgaas   if (type == PCI_EXP_TYPE_ENDPOINT || type == PCI_EXP_TYPE_ROOT_INT_EP)
498c0d9545cSBjorn Helgaas     return;
499c0d9545cSBjorn Helgaas   bar = get_conf_long(d, where + PCI_MCAST_OVL_BAR);
500c0d9545cSBjorn Helgaas   l = get_conf_long(d, where + PCI_MCAST_OVL_BAR + 4);
501c0d9545cSBjorn Helgaas   bar |= (u64) l << 32;
502c0d9545cSBjorn Helgaas   printf("\t\tMcastOverlayBAR: OverlaySize %d ", PCI_MCAST_OVL_SIZE(bar));
503c0d9545cSBjorn Helgaas   if (PCI_MCAST_OVL_SIZE(bar) >= 6)
504c0d9545cSBjorn Helgaas     printf("(%d bytes)", 1 << PCI_MCAST_OVL_SIZE(bar));
505c0d9545cSBjorn Helgaas   else
506c0d9545cSBjorn Helgaas     printf("(disabled)");
507c0d9545cSBjorn Helgaas   printf(", BaseAddr %016" PCI_U64_FMT_X "\n", bar & PCI_MCAST_OVL_MASK);
508c0d9545cSBjorn Helgaas }
509c0d9545cSBjorn Helgaas 
510c0d9545cSBjorn Helgaas static void
cap_vc(struct device * d,int where)51133088c24SMartin Mares cap_vc(struct device *d, int where)
51233088c24SMartin Mares {
51333088c24SMartin Mares   u32 cr1, cr2;
51433088c24SMartin Mares   u16 ctrl, status;
51533088c24SMartin Mares   int evc_cnt;
51633088c24SMartin Mares   int arb_table_pos;
51733088c24SMartin Mares   int i, j;
5183d8b5258SMartin Mares   static const char ref_clocks[][6] = { "100ns" };
5193edae14aSMartin Mares   static const char arb_selects[8][7] = { "Fixed", "WRR32", "WRR64", "WRR128", "??4", "??5", "??6", "??7" };
5203edae14aSMartin Mares   static const char vc_arb_selects[8][8] = { "Fixed", "WRR32", "WRR64", "WRR128", "TWRR128", "WRR256", "??6", "??7" };
5213d8b5258SMartin Mares   char buf[8];
52233088c24SMartin Mares 
52333088c24SMartin Mares   printf("Virtual Channel\n");
52433088c24SMartin Mares   if (verbose < 2)
52533088c24SMartin Mares     return;
52633088c24SMartin Mares 
52733088c24SMartin Mares   if (!config_fetch(d, where + 4, 0x1c - 4))
52833088c24SMartin Mares     return;
52933088c24SMartin Mares 
53033088c24SMartin Mares   cr1 = get_conf_long(d, where + PCI_VC_PORT_REG1);
53133088c24SMartin Mares   cr2 = get_conf_long(d, where + PCI_VC_PORT_REG2);
53233088c24SMartin Mares   ctrl = get_conf_word(d, where + PCI_VC_PORT_CTRL);
53333088c24SMartin Mares   status = get_conf_word(d, where + PCI_VC_PORT_STATUS);
53433088c24SMartin Mares 
5353d8b5258SMartin Mares   evc_cnt = BITS(cr1, 0, 3);
536d676f20dSMartin Mares   printf("\t\tCaps:\tLPEVC=%d RefClk=%s PATEntryBits=%d\n",
5373d8b5258SMartin Mares     BITS(cr1, 4, 3),
5383d8b5258SMartin Mares     TABLE(ref_clocks, BITS(cr1, 8, 2), buf),
539d676f20dSMartin Mares     1 << BITS(cr1, 10, 2));
54033088c24SMartin Mares 
541d676f20dSMartin Mares   printf("\t\tArb:");
54233088c24SMartin Mares   for (i=0; i<8; i++)
54333088c24SMartin Mares     if (arb_selects[i][0] != '?' || cr2 & (1 << i))
544d676f20dSMartin Mares       printf("%c%s%c", (i ? ' ' : '\t'), arb_selects[i], FLAG(cr2, 1 << i));
5453d8b5258SMartin Mares   arb_table_pos = BITS(cr2, 24, 8);
54633088c24SMartin Mares 
547d676f20dSMartin Mares   printf("\n\t\tCtrl:\tArbSelect=%s\n", TABLE(arb_selects, BITS(ctrl, 1, 3), buf));
54833088c24SMartin Mares   printf("\t\tStatus:\tInProgress%c\n", FLAG(status, 1));
54933088c24SMartin Mares 
55033088c24SMartin Mares   if (arb_table_pos)
551d676f20dSMartin Mares     {
552d676f20dSMartin Mares       arb_table_pos = where + 16*arb_table_pos;
553d676f20dSMartin Mares       printf("\t\tPort Arbitration Table [%x] <?>\n", arb_table_pos);
554d676f20dSMartin Mares     }
55533088c24SMartin Mares 
55633088c24SMartin Mares   for (i=0; i<=evc_cnt; i++)
55733088c24SMartin Mares     {
55833088c24SMartin Mares       int pos = where + PCI_VC_RES_CAP + 12*i;
55933088c24SMartin Mares       u32 rcap, rctrl;
56033088c24SMartin Mares       u16 rstatus;
56133088c24SMartin Mares       int pat_pos;
56233088c24SMartin Mares 
5635a9a932cSMartin Mares       printf("\t\tVC%d:\t", i);
56433088c24SMartin Mares       if (!config_fetch(d, pos, 12))
56533088c24SMartin Mares 	{
5665a9a932cSMartin Mares 	  printf("<unreadable>\n");
56733088c24SMartin Mares 	  continue;
56833088c24SMartin Mares 	}
56933088c24SMartin Mares       rcap = get_conf_long(d, pos);
57033088c24SMartin Mares       rctrl = get_conf_long(d, pos+4);
5717970509bSJ.L. Burr       rstatus = get_conf_word(d, pos+10);
57233088c24SMartin Mares 
5733d8b5258SMartin Mares       pat_pos = BITS(rcap, 24, 8);
5745a9a932cSMartin Mares       printf("Caps:\tPATOffset=%02x MaxTimeSlots=%d RejSnoopTrans%c\n",
57533088c24SMartin Mares 	pat_pos,
5763711e86fSMikhail Bratchikov 	BITS(rcap, 16, 7) + 1,
57733088c24SMartin Mares 	FLAG(rcap, 1 << 15));
57833088c24SMartin Mares 
57933088c24SMartin Mares       printf("\t\t\tArb:");
58033088c24SMartin Mares       for (j=0; j<8; j++)
58133088c24SMartin Mares 	if (vc_arb_selects[j][0] != '?' || rcap & (1 << j))
58233088c24SMartin Mares 	  printf("%c%s%c", (j ? ' ' : '\t'), vc_arb_selects[j], FLAG(rcap, 1 << j));
58333088c24SMartin Mares 
58433088c24SMartin Mares       printf("\n\t\t\tCtrl:\tEnable%c ID=%d ArbSelect=%s TC/VC=%02x\n",
58533088c24SMartin Mares 	FLAG(rctrl, 1 << 31),
5863d8b5258SMartin Mares 	BITS(rctrl, 24, 3),
5873d8b5258SMartin Mares 	TABLE(vc_arb_selects, BITS(rctrl, 17, 3), buf),
5883d8b5258SMartin Mares 	BITS(rctrl, 0, 8));
58933088c24SMartin Mares 
59033088c24SMartin Mares       printf("\t\t\tStatus:\tNegoPending%c InProgress%c\n",
59133088c24SMartin Mares 	FLAG(rstatus, 2),
59233088c24SMartin Mares 	FLAG(rstatus, 1));
59333088c24SMartin Mares 
59433088c24SMartin Mares       if (pat_pos)
59533088c24SMartin Mares 	printf("\t\t\tPort Arbitration Table <?>\n");
59633088c24SMartin Mares     }
59733088c24SMartin Mares }
59833088c24SMartin Mares 
5995a9a932cSMartin Mares static void
cap_rclink(struct device * d,int where)6005a9a932cSMartin Mares cap_rclink(struct device *d, int where)
6015a9a932cSMartin Mares {
6025a9a932cSMartin Mares   u32 esd;
6035a9a932cSMartin Mares   int num_links;
6045a9a932cSMartin Mares   int i;
6055a9a932cSMartin Mares   static const char elt_types[][9] = { "Config", "Egress", "Internal" };
6065a9a932cSMartin Mares   char buf[8];
6075a9a932cSMartin Mares 
6085a9a932cSMartin Mares   printf("Root Complex Link\n");
6095a9a932cSMartin Mares   if (verbose < 2)
6105a9a932cSMartin Mares     return;
6115a9a932cSMartin Mares 
6125a9a932cSMartin Mares   if (!config_fetch(d, where + 4, PCI_RCLINK_LINK1 - 4))
6135a9a932cSMartin Mares     return;
6145a9a932cSMartin Mares 
6155a9a932cSMartin Mares   esd = get_conf_long(d, where + PCI_RCLINK_ESD);
6165a9a932cSMartin Mares   num_links = BITS(esd, 8, 8);
6175a9a932cSMartin Mares   printf("\t\tDesc:\tPortNumber=%02x ComponentID=%02x EltType=%s\n",
6185a9a932cSMartin Mares     BITS(esd, 24, 8),
6195a9a932cSMartin Mares     BITS(esd, 16, 8),
6205a9a932cSMartin Mares     TABLE(elt_types, BITS(esd, 0, 8), buf));
6215a9a932cSMartin Mares 
6225a9a932cSMartin Mares   for (i=0; i<num_links; i++)
6235a9a932cSMartin Mares     {
6245a9a932cSMartin Mares       int pos = where + PCI_RCLINK_LINK1 + i*PCI_RCLINK_LINK_SIZE;
6255a9a932cSMartin Mares       u32 desc;
6265a9a932cSMartin Mares       u32 addr_lo, addr_hi;
6275a9a932cSMartin Mares 
6285a9a932cSMartin Mares       printf("\t\tLink%d:\t", i);
6295a9a932cSMartin Mares       if (!config_fetch(d, pos, PCI_RCLINK_LINK_SIZE))
6305a9a932cSMartin Mares 	{
6315a9a932cSMartin Mares 	  printf("<unreadable>\n");
6325a9a932cSMartin Mares 	  return;
6335a9a932cSMartin Mares 	}
6345a9a932cSMartin Mares       desc = get_conf_long(d, pos + PCI_RCLINK_LINK_DESC);
6355a9a932cSMartin Mares       addr_lo = get_conf_long(d, pos + PCI_RCLINK_LINK_ADDR);
6365a9a932cSMartin Mares       addr_hi = get_conf_long(d, pos + PCI_RCLINK_LINK_ADDR + 4);
6375a9a932cSMartin Mares 
6385a9a932cSMartin Mares       printf("Desc:\tTargetPort=%02x TargetComponent=%02x AssocRCRB%c LinkType=%s LinkValid%c\n",
6395a9a932cSMartin Mares 	BITS(desc, 24, 8),
6405a9a932cSMartin Mares 	BITS(desc, 16, 8),
6415a9a932cSMartin Mares 	FLAG(desc, 4),
6425a9a932cSMartin Mares 	((desc & 2) ? "Config" : "MemMapped"),
6435a9a932cSMartin Mares 	FLAG(desc, 1));
6445a9a932cSMartin Mares 
6455a9a932cSMartin Mares       if (desc & 2)
6465a9a932cSMartin Mares 	{
6475a9a932cSMartin Mares 	  int n = addr_lo & 7;
6485a9a932cSMartin Mares 	  if (!n)
6495a9a932cSMartin Mares 	    n = 8;
6505a9a932cSMartin Mares 	  printf("\t\t\tAddr:\t%02x:%02x.%d  CfgSpace=%08x%08x\n",
6515a9a932cSMartin Mares 	    BITS(addr_lo, 20, n),
6525a9a932cSMartin Mares 	    BITS(addr_lo, 15, 5),
6535a9a932cSMartin Mares 	    BITS(addr_lo, 12, 3),
6545a9a932cSMartin Mares 	    addr_hi, addr_lo);
6555a9a932cSMartin Mares 	}
6565a9a932cSMartin Mares       else
6575a9a932cSMartin Mares 	printf("\t\t\tAddr:\t%08x%08x\n", addr_hi, addr_lo);
6585a9a932cSMartin Mares     }
6595a9a932cSMartin Mares }
6605a9a932cSMartin Mares 
66178ca9582SMartin Mares static void
cap_rcec(struct device * d,int where)662e12bd01eSSean V Kelley cap_rcec(struct device *d, int where)
663e12bd01eSSean V Kelley {
664e12bd01eSSean V Kelley   printf("Root Complex Event Collector Endpoint Association\n");
665e12bd01eSSean V Kelley   if (verbose < 2)
666e12bd01eSSean V Kelley     return;
667e12bd01eSSean V Kelley 
668e12bd01eSSean V Kelley   if (!config_fetch(d, where, 12))
669e12bd01eSSean V Kelley     return;
670e12bd01eSSean V Kelley 
671e12bd01eSSean V Kelley   u32 hdr = get_conf_long(d, where);
672e12bd01eSSean V Kelley   byte cap_ver = PCI_RCEC_EP_CAP_VER(hdr);
673e12bd01eSSean V Kelley   u32 bmap = get_conf_long(d, where + PCI_RCEC_RCIEP_BMAP);
674e12bd01eSSean V Kelley   printf("\t\tRCiEPBitmap: ");
675e12bd01eSSean V Kelley   if (bmap)
676e12bd01eSSean V Kelley     {
677e12bd01eSSean V Kelley       int prevmatched=0;
678e12bd01eSSean V Kelley       int adjcount=0;
679e12bd01eSSean V Kelley       int prevdev=0;
680e12bd01eSSean V Kelley       printf("RCiEP at Device(s):");
681e12bd01eSSean V Kelley       for (int dev=0; dev < 32; dev++)
682e12bd01eSSean V Kelley         {
683e12bd01eSSean V Kelley 	  if (BITS(bmap, dev, 1))
684e12bd01eSSean V Kelley 	    {
685e12bd01eSSean V Kelley 	      if (!adjcount)
686e12bd01eSSean V Kelley 	        printf("%s %u", (prevmatched) ? "," : "", dev);
687e12bd01eSSean V Kelley 	      adjcount++;
688e12bd01eSSean V Kelley 	      prevdev=dev;
689e12bd01eSSean V Kelley 	      prevmatched=1;
690e12bd01eSSean V Kelley             }
691e12bd01eSSean V Kelley 	  else
692e12bd01eSSean V Kelley 	    {
693e12bd01eSSean V Kelley 	      if (adjcount > 1)
694e12bd01eSSean V Kelley 	        printf("-%u", prevdev);
695e12bd01eSSean V Kelley 	      adjcount=0;
696e12bd01eSSean V Kelley             }
697e12bd01eSSean V Kelley         }
698e12bd01eSSean V Kelley    }
699e12bd01eSSean V Kelley   else
700e12bd01eSSean V Kelley     printf("%s", (verbose > 2) ? "00000000 [none]" : "[none]");
701e12bd01eSSean V Kelley   printf("\n");
702e12bd01eSSean V Kelley 
703e12bd01eSSean V Kelley   if (cap_ver < PCI_RCEC_BUSN_REG_VER)
704e12bd01eSSean V Kelley     return;
705e12bd01eSSean V Kelley 
706e12bd01eSSean V Kelley   u32 busn = get_conf_long(d, where + PCI_RCEC_BUSN_REG);
707e12bd01eSSean V Kelley   u8 lastbusn = BITS(busn, 16, 8);
708e12bd01eSSean V Kelley   u8 nextbusn = BITS(busn, 8, 8);
709e12bd01eSSean V Kelley 
710e12bd01eSSean V Kelley   if ((lastbusn == 0x00) && (nextbusn == 0xff))
711e12bd01eSSean V Kelley     printf("\t\tAssociatedBusNumbers: %s\n", (verbose > 2) ? "ff-00 [none]" : "[none]");
712e12bd01eSSean V Kelley   else
713e12bd01eSSean V Kelley     printf("\t\tAssociatedBusNumbers: %02x-%02x\n", nextbusn, lastbusn );
714e12bd01eSSean V Kelley }
715e12bd01eSSean V Kelley 
716e12bd01eSSean V Kelley static void
cap_lmr(struct device * d,int where)717d016c32dSNikita Proshkin cap_lmr(struct device *d, int where)
718d016c32dSNikita Proshkin {
719d016c32dSNikita Proshkin   printf("Lane Margining at the Receiver\n");
720d016c32dSNikita Proshkin 
721d016c32dSNikita Proshkin   if (verbose < 2)
722d016c32dSNikita Proshkin     return;
723d016c32dSNikita Proshkin 
724d016c32dSNikita Proshkin   if (!config_fetch(d, where, 8))
725d016c32dSNikita Proshkin     return;
726d016c32dSNikita Proshkin 
727d016c32dSNikita Proshkin   u16 port_caps = get_conf_word(d, where + PCI_LMR_CAPS);
728d016c32dSNikita Proshkin   u16 port_status = get_conf_word(d, where + PCI_LMR_PORT_STS);
729d016c32dSNikita Proshkin 
730d016c32dSNikita Proshkin   printf("\t\tPortCap: Uses Driver%c\n", FLAG(port_caps, PCI_LMR_CAPS_DRVR));
731d016c32dSNikita Proshkin   printf("\t\tPortSta: MargReady%c MargSoftReady%c\n",
732d016c32dSNikita Proshkin          FLAG(port_status, PCI_LMR_PORT_STS_READY),
733d016c32dSNikita Proshkin          FLAG(port_status, PCI_LMR_PORT_STS_SOFT_READY));
734d016c32dSNikita Proshkin }
735d016c32dSNikita Proshkin 
736d016c32dSNikita Proshkin static void
cap_phy_16gt(struct device * d,int where)7370c6383e9STristan Watts-Willis cap_phy_16gt(struct device *d, int where)
7380c6383e9STristan Watts-Willis {
7390c6383e9STristan Watts-Willis   printf("Physical Layer 16.0 GT/s\n");
7400c6383e9STristan Watts-Willis 
7410c6383e9STristan Watts-Willis   if (verbose < 2)
7420c6383e9STristan Watts-Willis     return;
7430c6383e9STristan Watts-Willis 
7440c6383e9STristan Watts-Willis   if (!config_fetch(d, where + PCI_16GT_CAP, 0x18)) {
7450c6383e9STristan Watts-Willis     printf("\t\t<unreadable>\n");
7460c6383e9STristan Watts-Willis     return;
7470c6383e9STristan Watts-Willis   }
7480c6383e9STristan Watts-Willis 
7490c6383e9STristan Watts-Willis   u32 status = get_conf_long(d, where + PCI_16GT_STATUS);
7500c6383e9STristan Watts-Willis 
7510c6383e9STristan Watts-Willis   printf("\t\tPhy16Sta: EquComplete%c EquPhase1%c EquPhase2%c EquPhase3%c LinkEquRequest%c\n",
7520c6383e9STristan Watts-Willis          FLAG(status, PCI_16GT_STATUS_EQU_COMP),
7530c6383e9STristan Watts-Willis          FLAG(status, PCI_16GT_STATUS_EQU_PHASE1),
7540c6383e9STristan Watts-Willis          FLAG(status, PCI_16GT_STATUS_EQU_PHASE2),
7550c6383e9STristan Watts-Willis          FLAG(status, PCI_16GT_STATUS_EQU_PHASE3),
7560c6383e9STristan Watts-Willis          FLAG(status, PCI_16GT_STATUS_EQU_REQ));
7570c6383e9STristan Watts-Willis }
7580c6383e9STristan Watts-Willis 
7590c6383e9STristan Watts-Willis static void
cap_phy_32gt(struct device * d,int where)7600c6383e9STristan Watts-Willis cap_phy_32gt(struct device *d, int where)
7610c6383e9STristan Watts-Willis {
7620c6383e9STristan Watts-Willis   static const char * const mod_ts_modes[] = {
7630c6383e9STristan Watts-Willis     "PCI Express",
7640c6383e9STristan Watts-Willis     "Training Set Messages",
7650c6383e9STristan Watts-Willis     "Alternate Protocol Negotiation"
7660c6383e9STristan Watts-Willis   };
7670c6383e9STristan Watts-Willis   static const char * const enh_link_ctl[] = {
7680c6383e9STristan Watts-Willis     "Full Equalization required",
7690c6383e9STristan Watts-Willis     "Equalization bypass to highest rate support",
7700c6383e9STristan Watts-Willis     "No Equalization Needed",
7710c6383e9STristan Watts-Willis     "Modified TS1/TS2 Ordered Sets supported"
7720c6383e9STristan Watts-Willis   };
7730c6383e9STristan Watts-Willis   char buf[48];
7740c6383e9STristan Watts-Willis 
7750c6383e9STristan Watts-Willis   printf("Physical Layer 32.0 GT/s\n");
7760c6383e9STristan Watts-Willis 
7770c6383e9STristan Watts-Willis   if (verbose < 2)
7780c6383e9STristan Watts-Willis     return;
7790c6383e9STristan Watts-Willis 
7800c6383e9STristan Watts-Willis   if (!config_fetch(d, where + PCI_32GT_CAP, 0x1C)) {
7810c6383e9STristan Watts-Willis     printf("\t\t<unreadable>\n");
7820c6383e9STristan Watts-Willis     return;
7830c6383e9STristan Watts-Willis   }
7840c6383e9STristan Watts-Willis 
7850c6383e9STristan Watts-Willis   u32 cap = get_conf_long(d, where + PCI_32GT_CAP);
7860c6383e9STristan Watts-Willis   u32 ctl = get_conf_long(d, where + PCI_32GT_CTL);
7870c6383e9STristan Watts-Willis   u32 status = get_conf_long(d, where + PCI_32GT_STATUS);
7880c6383e9STristan Watts-Willis 
7890c6383e9STristan Watts-Willis   printf("\t\tPhy32Cap: EqualizationBypass%c NoEqualizationNeeded%c\n"
7900c6383e9STristan Watts-Willis          "\t\t\t  ModTsMode0%c ModTsMode1%c ModTsMode2%c\n",
7910c6383e9STristan Watts-Willis          FLAG(cap, PCI_32GT_CAP_EQU_BYPASS),
7920c6383e9STristan Watts-Willis          FLAG(cap, PCI_32GT_CAP_NO_EQU_NEEDED),
7930c6383e9STristan Watts-Willis          FLAG(cap, PCI_32GT_CAP_MOD_TS_MODE_0),
7940c6383e9STristan Watts-Willis          FLAG(cap, PCI_32GT_CAP_MOD_TS_MODE_1),
7950c6383e9STristan Watts-Willis          FLAG(cap, PCI_32GT_CAP_MOD_TS_MODE_2));
7960c6383e9STristan Watts-Willis 
7970c6383e9STristan Watts-Willis   printf("\t\tPhy32Ctl: EqualizationBypassDis%c NoEqualizationNeededDis%c\n"
7980c6383e9STristan Watts-Willis          "\t\t\t  Modified TS Usage Mode: %s\n",
7990c6383e9STristan Watts-Willis          FLAG(ctl, PCI_32GT_CTL_EQU_BYPASS_DIS),
8000c6383e9STristan Watts-Willis          FLAG(ctl, PCI_32GT_CTL_NO_EQU_NEEDED_DIS),
8010c6383e9STristan Watts-Willis          TABLE(mod_ts_modes, PCI_32GT_CTL_MOD_TS_MODE(ctl), buf));
8020c6383e9STristan Watts-Willis 
8030c6383e9STristan Watts-Willis   printf("\t\tPhy32Sta: EquComplete%c EquPhase1%c EquPhase2%c EquPhase3%c LinkEquRequest%c\n"
8040c6383e9STristan Watts-Willis          "\t\t\t  Received Enhanced Link Behavior Control: %s\n"
8050c6383e9STristan Watts-Willis          "\t\t\t  ModTsRecv%c TxPrecodeOn%c TxPrecodeReq%c NoEqualizationNeededRecv%c\n",
8060c6383e9STristan Watts-Willis          FLAG(status, PCI_32GT_STATUS_EQU_COMP),
8070c6383e9STristan Watts-Willis          FLAG(status, PCI_32GT_STATUS_EQU_PHASE1),
8080c6383e9STristan Watts-Willis          FLAG(status, PCI_32GT_STATUS_EQU_PHASE2),
8090c6383e9STristan Watts-Willis          FLAG(status, PCI_32GT_STATUS_EQU_PHASE3),
8100c6383e9STristan Watts-Willis          FLAG(status, PCI_32GT_STATUS_EQU_REQ),
8110c6383e9STristan Watts-Willis          TABLE(enh_link_ctl, PCI_32GT_STATUS_RCV_ENH_LINK(status), buf),
8120c6383e9STristan Watts-Willis          FLAG(status, PCI_32GT_STATUS_MOD_TS),
8130c6383e9STristan Watts-Willis          FLAG(status, PCI_32GT_STATUS_TX_PRE_ON),
8140c6383e9STristan Watts-Willis          FLAG(status, PCI_32GT_STATUS_TX_PRE_REQ),
8150c6383e9STristan Watts-Willis          FLAG(status, PCI_32GT_STATUS_NO_EQU));
8160c6383e9STristan Watts-Willis }
8170c6383e9STristan Watts-Willis 
8180c6383e9STristan Watts-Willis static void
cap_phy_64gt(struct device * d,int where)81904d90becSTristan Watts-Willis cap_phy_64gt(struct device *d, int where)
82004d90becSTristan Watts-Willis {
82104d90becSTristan Watts-Willis   printf("Physical Layer 64.0 GT/s\n");
82204d90becSTristan Watts-Willis 
82304d90becSTristan Watts-Willis   if (verbose < 2)
82404d90becSTristan Watts-Willis     return;
82504d90becSTristan Watts-Willis 
82604d90becSTristan Watts-Willis   if (!config_fetch(d, where + PCI_64GT_CAP, 0x0C)) {
82704d90becSTristan Watts-Willis     printf("\t\t<unreadable>\n");
82804d90becSTristan Watts-Willis     return;
82904d90becSTristan Watts-Willis   }
83004d90becSTristan Watts-Willis 
83104d90becSTristan Watts-Willis   u32 status = get_conf_long(d, where + PCI_64GT_STATUS);
83204d90becSTristan Watts-Willis 
83304d90becSTristan Watts-Willis   printf("\t\tPhy64Sta: EquComplete%c EquPhase1%c EquPhase2%c EquPhase3%c LinkEquRequest%c\n"
83404d90becSTristan Watts-Willis          "\t\t\t  TxPrecodeOn%c TxPrecodeReq%c NoEqualizationNeededRecv%c\n",
83504d90becSTristan Watts-Willis          FLAG(status, PCI_64GT_STATUS_EQU_COMP),
83604d90becSTristan Watts-Willis          FLAG(status, PCI_64GT_STATUS_EQU_PHASE1),
83704d90becSTristan Watts-Willis          FLAG(status, PCI_64GT_STATUS_EQU_PHASE2),
83804d90becSTristan Watts-Willis          FLAG(status, PCI_64GT_STATUS_EQU_PHASE3),
83904d90becSTristan Watts-Willis          FLAG(status, PCI_64GT_STATUS_EQU_REQ),
84004d90becSTristan Watts-Willis          FLAG(status, PCI_64GT_STATUS_TX_PRE_ON),
84104d90becSTristan Watts-Willis          FLAG(status, PCI_64GT_STATUS_TX_PRE_REQ),
84204d90becSTristan Watts-Willis          FLAG(status, PCI_64GT_STATUS_NO_EQU));
84304d90becSTristan Watts-Willis }
84404d90becSTristan Watts-Willis 
84504d90becSTristan Watts-Willis static void
cxl_range(u64 base,u64 size,int n)84652097446SBen Widawsky cxl_range(u64 base, u64 size, int n)
84752097446SBen Widawsky {
84852097446SBen Widawsky   u32 interleave[] = { 0, 256, 4096, 512, 1024, 2048, 8192, 16384 };
8492bbe1d46SMartin Mares   const char * const type[] = { "Volatile", "Non-volatile", "CDAT" };
8502bbe1d46SMartin Mares   const char * const class[] = { "DRAM", "Storage", "CDAT" };
85152097446SBen Widawsky   u16 w;
85252097446SBen Widawsky 
85352097446SBen Widawsky   w = (u16) size;
85452097446SBen Widawsky 
85552097446SBen Widawsky   size &= ~0x0fffffffULL;
85652097446SBen Widawsky 
857c0ccce1bSAlexis Gryta   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);
85852097446SBen Widawsky   printf("\t\t\tValid%c Active%c Type=%s Class=%s interleave=%d timeout=%ds\n",
85952097446SBen Widawsky     FLAG(w, PCI_CXL_RANGE_VALID), FLAG(w, PCI_CXL_RANGE_ACTIVE),
86052097446SBen Widawsky     type[PCI_CXL_RANGE_TYPE(w)], class[PCI_CXL_RANGE_CLASS(w)],
86152097446SBen Widawsky     interleave[PCI_CXL_RANGE_INTERLEAVE(w)],
86252097446SBen Widawsky     1 << (PCI_CXL_RANGE_TIMEOUT(w) * 2));
86352097446SBen Widawsky }
86452097446SBen Widawsky 
86552097446SBen Widawsky static void
dvsec_cxl_device(struct device * d,int rev,int where,int len)8662849db67SMartin Mares dvsec_cxl_device(struct device *d, int rev, int where, int len)
867bd853ef8SSean V Kelley {
8682849db67SMartin Mares   u32 cache_size, cache_unit_size;
86952097446SBen Widawsky   u64 range_base, range_size;
870ccf5ff41SBen Widawsky   u16 w;
871bd853ef8SSean V Kelley 
8720d4491cbSBen Widawsky   /* Legacy 1.1 revs aren't handled */
873c0ccce1bSAlexis Gryta   if (rev == 0)
874bd853ef8SSean V Kelley     return;
875bd853ef8SSean V Kelley 
876944bb1dfSMartin Mares   if (rev >= 1 && len >= PCI_CXL_DEV_LEN)
8773d2d69cbSMartin Mares     {
8784c2b4b1bSBen Widawsky       w = get_conf_word(d, where + PCI_CXL_DEV_CAP);
879bd853ef8SSean V Kelley       printf("\t\tCXLCap:\tCache%c IO%c Mem%c MemHWInit%c HDMCount %d Viral%c\n",
8804c2b4b1bSBen Widawsky 	FLAG(w, PCI_CXL_DEV_CAP_CACHE), FLAG(w, PCI_CXL_DEV_CAP_IO), FLAG(w, PCI_CXL_DEV_CAP_MEM),
8814c2b4b1bSBen Widawsky 	FLAG(w, PCI_CXL_DEV_CAP_MEM_HWINIT), PCI_CXL_DEV_CAP_HDM_CNT(w), FLAG(w, PCI_CXL_DEV_CAP_VIRAL));
882bd853ef8SSean V Kelley 
8834c2b4b1bSBen Widawsky       w = get_conf_word(d, where + PCI_CXL_DEV_CTRL);
884bd853ef8SSean V Kelley       printf("\t\tCXLCtl:\tCache%c IO%c Mem%c CacheSFCov %d CacheSFGran %d CacheClean%c Viral%c\n",
8854c2b4b1bSBen Widawsky 	FLAG(w, PCI_CXL_DEV_CTRL_CACHE), FLAG(w, PCI_CXL_DEV_CTRL_IO), FLAG(w, PCI_CXL_DEV_CTRL_MEM),
8864c2b4b1bSBen Widawsky 	PCI_CXL_DEV_CTRL_CACHE_SF_COV(w), PCI_CXL_DEV_CTRL_CACHE_SF_GRAN(w), FLAG(w, PCI_CXL_DEV_CTRL_CACHE_CLN),
8874c2b4b1bSBen Widawsky 	FLAG(w, PCI_CXL_DEV_CTRL_VIRAL));
888bd853ef8SSean V Kelley 
8894c2b4b1bSBen Widawsky       w = get_conf_word(d, where + PCI_CXL_DEV_STATUS);
8904c2b4b1bSBen Widawsky       printf("\t\tCXLSta:\tViral%c\n", FLAG(w, PCI_CXL_DEV_STATUS_VIRAL));
89152097446SBen Widawsky 
892c0ccce1bSAlexis Gryta       w = get_conf_word(d, where + PCI_CXL_DEV_CTRL2);
893c0ccce1bSAlexis Gryta       printf("\t\tCXLCtl2:\tDisableCaching%c InitCacheWB&Inval%c InitRst%c RstMemClrEn%c",
894c0ccce1bSAlexis Gryta 	FLAG(w, PCI_CXL_DEV_CTRL2_DISABLE_CACHING),
895c0ccce1bSAlexis Gryta 	FLAG(w, PCI_CXL_DEV_CTRL2_INIT_WB_INVAL),
896c0ccce1bSAlexis Gryta 	FLAG(w, PCI_CXL_DEV_CTRL2_INIT_CXL_RST),
897c0ccce1bSAlexis Gryta 	FLAG(w, PCI_CXL_DEV_CTRL2_INIT_CXL_RST_CLR_EN));
8983d2d69cbSMartin Mares       if (rev >= 2)
899c0ccce1bSAlexis Gryta 	  printf(" DesiredVolatileHDMStateAfterHotReset%c", FLAG(w, PCI_CXL_DEV_CTRL2_INIT_CXL_HDM_STATE_HOTRST));
900c0ccce1bSAlexis Gryta       printf("\n");
901c0ccce1bSAlexis Gryta 
90252097446SBen Widawsky       w = get_conf_word(d, where + PCI_CXL_DEV_STATUS2);
90352097446SBen Widawsky       printf("\t\tCXLSta2:\tResetComplete%c ResetError%c PMComplete%c\n",
90452097446SBen Widawsky 	FLAG(w, PCI_CXL_DEV_STATUS_RC), FLAG(w,PCI_CXL_DEV_STATUS_RE), FLAG(w, PCI_CXL_DEV_STATUS_PMC));
90552097446SBen Widawsky 
90652097446SBen Widawsky       w = get_conf_word(d, where + PCI_CXL_DEV_CAP2);
907c0ccce1bSAlexis Gryta       printf("\t\tCXLCap2:\t");
90852097446SBen Widawsky       cache_unit_size = BITS(w, 0, 4);
90952097446SBen Widawsky       cache_size = BITS(w, 8, 8);
91052097446SBen Widawsky       switch (cache_unit_size)
91152097446SBen Widawsky 	{
91252097446SBen Widawsky 	case PCI_CXL_DEV_CAP2_CACHE_1M:
913c0ccce1bSAlexis Gryta 	  printf("Cache Size: %08x\n", cache_size * (1<<20));
91452097446SBen Widawsky 	  break;
91552097446SBen Widawsky 	case PCI_CXL_DEV_CAP2_CACHE_64K:
916c0ccce1bSAlexis Gryta 	  printf("Cache Size: %08x\n", cache_size * (64<<10));
91752097446SBen Widawsky 	  break;
91852097446SBen Widawsky 	case PCI_CXL_DEV_CAP2_CACHE_UNK:
919c0ccce1bSAlexis Gryta 	  printf("Cache Size Not Reported\n");
92052097446SBen Widawsky 	  break;
92152097446SBen Widawsky 	default:
922c0ccce1bSAlexis Gryta 	  printf("Cache Size: %d of unknown unit size (%d)\n", cache_size, cache_unit_size);
92352097446SBen Widawsky 	  break;
92452097446SBen Widawsky 	}
92552097446SBen Widawsky 
9262849db67SMartin Mares       range_size = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE1_SIZE_HI) << 32;
9272849db67SMartin Mares       range_size |= get_conf_long(d, where + PCI_CXL_DEV_RANGE1_SIZE_LO);
9282849db67SMartin Mares       range_base = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE1_BASE_HI) << 32;
9292849db67SMartin Mares       range_base |= get_conf_long(d, where + PCI_CXL_DEV_RANGE1_BASE_LO);
93052097446SBen Widawsky       cxl_range(range_base, range_size, 1);
93152097446SBen Widawsky 
9322849db67SMartin Mares       range_size = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE2_SIZE_HI) << 32;
9332849db67SMartin Mares       range_size |= get_conf_long(d, where + PCI_CXL_DEV_RANGE2_SIZE_LO);
9342849db67SMartin Mares       range_base = (u64) get_conf_long(d, where + PCI_CXL_DEV_RANGE2_BASE_HI) << 32;
9352849db67SMartin Mares       range_base |= get_conf_long(d, where + PCI_CXL_DEV_RANGE2_BASE_LO);
93652097446SBen Widawsky       cxl_range(range_base, range_size, 2);
937bd853ef8SSean V Kelley     }
938bd853ef8SSean V Kelley 
939944bb1dfSMartin Mares   if (rev >= 2 && len >= PCI_CXL_DEV_LEN_REV2)
9403d2d69cbSMartin Mares     {
941c0ccce1bSAlexis Gryta       w = get_conf_word(d, where + PCI_CXL_DEV_CAP3);
942c0ccce1bSAlexis Gryta       printf("\t\tCXLCap3:\tDefaultVolatile HDM State After:\tColdReset%c WarmReset%c HotReset%c HotResetConfigurability%c\n",
943c0ccce1bSAlexis Gryta 	FLAG(w, PCI_CXL_DEV_CAP3_HDM_STATE_RST_COLD),
944c0ccce1bSAlexis Gryta 	FLAG(w, PCI_CXL_DEV_CAP3_HDM_STATE_RST_WARM),
945c0ccce1bSAlexis Gryta 	FLAG(w, PCI_CXL_DEV_CAP3_HDM_STATE_RST_HOT),
946c0ccce1bSAlexis Gryta 	FLAG(w, PCI_CXL_DEV_CAP3_HDM_STATE_RST_HOT_CFG));
947c0ccce1bSAlexis Gryta     }
948c0ccce1bSAlexis Gryta 
949c0ccce1bSAlexis Gryta   // Unparsed data
950944bb1dfSMartin Mares   if (len > PCI_CXL_DEV_LEN_REV2)
951c0ccce1bSAlexis Gryta     printf("\t\t<?>\n");
952c0ccce1bSAlexis Gryta }
953c0ccce1bSAlexis Gryta 
954bd853ef8SSean V Kelley static void
dvsec_cxl_port(struct device * d,int where,int len)9552849db67SMartin Mares dvsec_cxl_port(struct device *d, int where, int len)
956c8b83c6cSBen Widawsky {
957c8b83c6cSBen Widawsky   u16 w, m1, m2;
958c8b83c6cSBen Widawsky   u8 b1, b2;
959c8b83c6cSBen Widawsky 
9602849db67SMartin Mares   if (len < PCI_CXL_PORT_EXT_LEN)
9612849db67SMartin Mares     return;
9622849db67SMartin Mares 
963c8b83c6cSBen Widawsky   w = get_conf_word(d, where + PCI_CXL_PORT_EXT_STATUS);
964c8b83c6cSBen Widawsky   printf("\t\tCXLPortSta:\tPMComplete%c\n", FLAG(w, PCI_CXL_PORT_EXT_STATUS));
965c8b83c6cSBen Widawsky 
966c8b83c6cSBen Widawsky   w = get_conf_word(d, where + PCI_CXL_PORT_CTRL);
967c8b83c6cSBen Widawsky   printf("\t\tCXLPortCtl:\tUnmaskSBR%c UnmaskLinkDisable%c AltMem%c AltBME%c ViralEnable%c\n",
968c8b83c6cSBen Widawsky     FLAG(w, PCI_CXL_PORT_UNMASK_SBR), FLAG(w, PCI_CXL_PORT_UNMASK_LINK),
969c8b83c6cSBen Widawsky     FLAG(w, PCI_CXL_PORT_ALT_MEMORY), FLAG(w, PCI_CXL_PORT_ALT_BME),
970c8b83c6cSBen Widawsky     FLAG(w, PCI_CXL_PORT_VIRAL_EN));
971c8b83c6cSBen Widawsky 
972c8b83c6cSBen Widawsky   b1 = get_conf_byte(d, where + PCI_CXL_PORT_ALT_BUS_BASE);
973c8b83c6cSBen Widawsky   b2 = get_conf_byte(d, where + PCI_CXL_PORT_ALT_BUS_LIMIT);
974c8b83c6cSBen Widawsky   printf("\t\tAlternateBus:\t%02x-%02x\n", b1, b2);
975c8b83c6cSBen Widawsky   m1 = get_conf_word(d, where + PCI_CXL_PORT_ALT_MEM_BASE);
976c8b83c6cSBen Widawsky   m2 = get_conf_word(d, where + PCI_CXL_PORT_ALT_MEM_LIMIT);
977c8b83c6cSBen Widawsky   printf("\t\tAlternateBus:\t%04x-%04x\n", m1, m2);
978c8b83c6cSBen Widawsky }
979c8b83c6cSBen Widawsky 
9800dfa1050SBen Widawsky static void
dvsec_cxl_register_locator(struct device * d,int where,int len)9810dfa1050SBen Widawsky dvsec_cxl_register_locator(struct device *d, int where, int len)
9820dfa1050SBen Widawsky {
9832849db67SMartin Mares   static const char * const id_names[] = {
9842849db67SMartin Mares     "empty",
9852849db67SMartin Mares     "component registers",
9862849db67SMartin Mares     "BAR virtualization",
9872849db67SMartin Mares     "CXL device registers",
9882849db67SMartin Mares     "CPMU registers",
9892849db67SMartin Mares   };
9900dfa1050SBen Widawsky 
9912849db67SMartin Mares   for (int i=0; ; i++)
9922849db67SMartin Mares     {
99355704534SJaxon Haws       int pos = where + PCI_CXL_RL_BLOCK1_LO + 8*i;
99455704534SJaxon Haws       if (pos + 7 >= where + len)
9952849db67SMartin Mares 	break;
9962849db67SMartin Mares 
9972849db67SMartin Mares       u32 lo = get_conf_long(d, pos);
9982849db67SMartin Mares       u32 hi = get_conf_long(d, pos + 4);
9992849db67SMartin Mares 
10002849db67SMartin Mares       unsigned int bir = BITS(lo, 0, 3);
10012849db67SMartin Mares       unsigned int block_id = BITS(lo, 8, 8);
10022849db67SMartin Mares       u64 base = (BITS(lo, 16, 16) << 16) | ((u64) hi << 32);
10032849db67SMartin Mares 
10042849db67SMartin Mares       if (!block_id)
10052849db67SMartin Mares 	continue;
10062849db67SMartin Mares 
10072849db67SMartin Mares       const char *id_name;
10082849db67SMartin Mares       if (block_id < sizeof(id_names) / sizeof(*id_names))
10092849db67SMartin Mares 	id_name = id_names[block_id];
10102849db67SMartin Mares       else if (block_id == 0xff)
10112849db67SMartin Mares 	id_name = "vendor-specific";
10122849db67SMartin Mares       else
10132849db67SMartin Mares 	id_name = "<?>";
10142849db67SMartin Mares 
101555704534SJaxon Haws       printf("\t\tBlock%d: BIR: bar%d, ID: %s, offset: %016" PCI_U64_FMT_X "\n", i + 1, bir, id_name, base);
10160dfa1050SBen Widawsky     }
10170dfa1050SBen Widawsky }
10180dfa1050SBen Widawsky 
1019c8b83c6cSBen Widawsky static void
dvsec_cxl_gpf_device(struct device * d,int where)1020d462e89cSJaxon Haws dvsec_cxl_gpf_device(struct device *d, int where)
1021d462e89cSJaxon Haws {
1022d462e89cSJaxon Haws   u32 l;
1023d462e89cSJaxon Haws   u16 w, duration;
1024d462e89cSJaxon Haws   u8 time_base, time_scale;
1025d462e89cSJaxon Haws 
1026d462e89cSJaxon Haws   w = get_conf_word(d, where + PCI_CXL_GPF_DEV_PHASE2_DUR);
1027d462e89cSJaxon Haws   time_base = BITS(w, 0, 4);
1028d462e89cSJaxon Haws   time_scale = BITS(w, 8, 4);
1029d462e89cSJaxon Haws 
1030d462e89cSJaxon Haws   switch (time_scale)
1031d462e89cSJaxon Haws     {
1032d462e89cSJaxon Haws       case PCI_CXL_GPF_DEV_100US:
1033d462e89cSJaxon Haws       case PCI_CXL_GPF_DEV_100MS:
1034d462e89cSJaxon Haws         duration = time_base * 100;
1035d462e89cSJaxon Haws         break;
1036d462e89cSJaxon Haws       case PCI_CXL_GPF_DEV_10US:
1037d462e89cSJaxon Haws       case PCI_CXL_GPF_DEV_10MS:
1038d462e89cSJaxon Haws       case PCI_CXL_GPF_DEV_10S:
1039d462e89cSJaxon Haws         duration = time_base * 10;
1040d462e89cSJaxon Haws         break;
1041d462e89cSJaxon Haws       case PCI_CXL_GPF_DEV_1US:
1042d462e89cSJaxon Haws       case PCI_CXL_GPF_DEV_1MS:
1043d462e89cSJaxon Haws       case PCI_CXL_GPF_DEV_1S:
1044d462e89cSJaxon Haws         duration = time_base;
1045d462e89cSJaxon Haws         break;
1046d462e89cSJaxon Haws       default:
1047d462e89cSJaxon Haws         /* Reserved */
1048d462e89cSJaxon Haws         printf("\t\tReserved time scale encoding %x\n", time_scale);
1049d462e89cSJaxon Haws         duration = time_base;
1050d462e89cSJaxon Haws     }
1051d462e89cSJaxon Haws 
1052d462e89cSJaxon Haws   printf("\t\tGPF Phase 2 Duration: %u%s\n", duration,
1053d462e89cSJaxon Haws       (time_scale < PCI_CXL_GPF_DEV_1MS) ? "us":
1054d462e89cSJaxon Haws       (time_scale < PCI_CXL_GPF_DEV_1S) ? "ms" :
105555209a0aSyeeli       (time_scale <= PCI_CXL_GPF_DEV_10S) ? "s" : "<?>");
1056d462e89cSJaxon Haws 
1057d462e89cSJaxon Haws   l = get_conf_long(d, where + PCI_CXL_GPF_DEV_PHASE2_POW);
1058d462e89cSJaxon Haws   printf("\t\tGPF Phase 2 Power: %umW\n", (unsigned int)l);
1059d462e89cSJaxon Haws }
1060d462e89cSJaxon Haws 
1061d462e89cSJaxon Haws static void
dvsec_cxl_gpf_port(struct device * d,int where)10625c75f737SJaxon Haws dvsec_cxl_gpf_port(struct device *d, int where)
10635c75f737SJaxon Haws {
10645c75f737SJaxon Haws   u16 w, timeout;
10655c75f737SJaxon Haws   u8 time_base, time_scale;
10665c75f737SJaxon Haws 
10675c75f737SJaxon Haws   w = get_conf_word(d, where + PCI_CXL_GPF_PORT_PHASE1_CTRL);
10685c75f737SJaxon Haws   time_base = BITS(w, 0, 4);
10695c75f737SJaxon Haws   time_scale = BITS(w, 8, 4);
10705c75f737SJaxon Haws 
10715c75f737SJaxon Haws   switch (time_scale)
10725c75f737SJaxon Haws     {
10735c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_100US:
10745c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_100MS:
10755c75f737SJaxon Haws         timeout = time_base * 100;
10765c75f737SJaxon Haws         break;
10775c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_10US:
10785c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_10MS:
10795c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_10S:
10805c75f737SJaxon Haws         timeout = time_base * 10;
10815c75f737SJaxon Haws         break;
10825c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_1US:
10835c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_1MS:
10845c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_1S:
10855c75f737SJaxon Haws         timeout = time_base;
10865c75f737SJaxon Haws         break;
10875c75f737SJaxon Haws       default:
10885c75f737SJaxon Haws         /* Reserved */
10895c75f737SJaxon Haws         printf("\t\tReserved time scale encoding %x\n", time_scale);
10905c75f737SJaxon Haws         timeout = time_base;
10915c75f737SJaxon Haws     }
10925c75f737SJaxon Haws 
10935c75f737SJaxon Haws   printf("\t\tGPF Phase 1 Timeout: %d%s\n", timeout,
10945c75f737SJaxon Haws       (time_scale < PCI_CXL_GPF_PORT_1MS) ? "us":
10955c75f737SJaxon Haws       (time_scale < PCI_CXL_GPF_PORT_1S) ? "ms" :
109655209a0aSyeeli       (time_scale <= PCI_CXL_GPF_PORT_10S) ? "s" : "<?>");
10975c75f737SJaxon Haws 
10985c75f737SJaxon Haws   w = get_conf_word(d, where + PCI_CXL_GPF_PORT_PHASE2_CTRL);
10995c75f737SJaxon Haws   time_base = BITS(w, 0, 4);
11005c75f737SJaxon Haws   time_scale = BITS(w, 8, 4);
11015c75f737SJaxon Haws 
11025c75f737SJaxon Haws   switch (time_scale)
11035c75f737SJaxon Haws     {
11045c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_100US:
11055c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_100MS:
11065c75f737SJaxon Haws         timeout = time_base * 100;
11075c75f737SJaxon Haws         break;
11085c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_10US:
11095c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_10MS:
11105c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_10S:
11115c75f737SJaxon Haws         timeout = time_base * 10;
11125c75f737SJaxon Haws         break;
11135c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_1US:
11145c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_1MS:
11155c75f737SJaxon Haws       case PCI_CXL_GPF_PORT_1S:
11165c75f737SJaxon Haws         timeout = time_base;
11175c75f737SJaxon Haws         break;
11185c75f737SJaxon Haws       default:
11195c75f737SJaxon Haws         /* Reserved */
11205c75f737SJaxon Haws         printf("\t\tReserved time scale encoding %x\n", time_scale);
11215c75f737SJaxon Haws         timeout = time_base;
11225c75f737SJaxon Haws     }
11235c75f737SJaxon Haws 
11245c75f737SJaxon Haws   printf("\t\tGPF Phase 2 Timeout: %d%s\n", timeout,
11255c75f737SJaxon Haws       (time_scale < PCI_CXL_GPF_PORT_1MS) ? "us":
11265c75f737SJaxon Haws       (time_scale < PCI_CXL_GPF_PORT_1S) ? "ms" :
112755209a0aSyeeli       (time_scale <= PCI_CXL_GPF_PORT_10S) ? "s" : "<?>");
11285c75f737SJaxon Haws }
11295c75f737SJaxon Haws 
11305c75f737SJaxon Haws static void
dvsec_cxl_flex_bus(struct device * d,int where,int rev,int len)113123b1ee0cSAlexis Gryta dvsec_cxl_flex_bus(struct device *d, int where, int rev, int len)
11329e567a4eSJaxon Haws {
11339e567a4eSJaxon Haws   u16 w;
11349e567a4eSJaxon Haws   u32 l, data;
11359e567a4eSJaxon Haws 
113623b1ee0cSAlexis Gryta   // Sanity check: Does the length correspond to its revision?
113723b1ee0cSAlexis Gryta   switch (rev) {
113823b1ee0cSAlexis Gryta     case 0:
11393d2d69cbSMartin Mares       if (len != PCI_CXL_FB_MOD_TS_DATA)
114023b1ee0cSAlexis Gryta         printf("\t\t<Wrong length for Revision %d>\n", rev);
114123b1ee0cSAlexis Gryta       break;
114223b1ee0cSAlexis Gryta     case 1:
11433d2d69cbSMartin Mares       if (len != PCI_CXL_FB_PORT_CAP2)
114423b1ee0cSAlexis Gryta         printf("\t\t<Wrong length for Revision %d>\n", rev);
114523b1ee0cSAlexis Gryta       break;
114623b1ee0cSAlexis Gryta     case 2:
11473d2d69cbSMartin Mares       if (len != PCI_CXL_FB_NEXT_UNSUPPORTED)
114823b1ee0cSAlexis Gryta         printf("\t\t<Wrong length for Revision %d>\n", rev);
114923b1ee0cSAlexis Gryta       break;
115023b1ee0cSAlexis Gryta     default:
115123b1ee0cSAlexis Gryta       break;
11529e567a4eSJaxon Haws   }
11539e567a4eSJaxon Haws 
115423b1ee0cSAlexis Gryta   // From Rev 0
11559e567a4eSJaxon Haws   w = get_conf_word(d, where + PCI_CXL_FB_PORT_CAP);
11569e567a4eSJaxon Haws   printf("\t\tFBCap:\tCache%c IO%c Mem%c 68BFlit%c MltLogDev%c",
11579e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_CAP_CACHE), FLAG(w, PCI_CXL_FB_CAP_IO),
11589e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_CAP_MEM), FLAG(w, PCI_CXL_FB_CAP_68B_FLIT),
11599e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_CAP_MULT_LOG_DEV));
11609e567a4eSJaxon Haws 
11619e567a4eSJaxon Haws   if (rev > 1)
11629e567a4eSJaxon Haws     printf(" 256BFlit%c PBRFlit%c",
11639e567a4eSJaxon Haws         FLAG(w, PCI_CXL_FB_CAP_256B_FLIT), FLAG(w, PCI_CXL_FB_CAP_PBR_FLIT));
11649e567a4eSJaxon Haws 
11659e567a4eSJaxon Haws   w = get_conf_word(d, where + PCI_CXL_FB_PORT_CTRL);
11669e567a4eSJaxon Haws   printf("\n\t\tFBCtl:\tCache%c IO%c Mem%c SynHdrByp%c DrftBuf%c 68BFlit%c MltLogDev%c RCD%c Retimer1%c Retimer2%c",
11679e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_CTRL_CACHE), FLAG(w, PCI_CXL_FB_CTRL_IO),
11689e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_CTRL_MEM), FLAG(w, PCI_CXL_FB_CTRL_SYNC_HDR_BYP),
11699e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_CTRL_DRFT_BUF), FLAG(w, PCI_CXL_FB_CTRL_68B_FLIT),
11709e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_CTRL_MULT_LOG_DEV), FLAG(w, PCI_CXL_FB_CTRL_RCD),
11719e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_CTRL_RETIMER1), FLAG(w, PCI_CXL_FB_CTRL_RETIMER2));
11729e567a4eSJaxon Haws 
11739e567a4eSJaxon Haws   if (rev > 1)
11749e567a4eSJaxon Haws     printf(" 256BFlit%c PBRFlit%c",
11759e567a4eSJaxon Haws         FLAG(w, PCI_CXL_FB_CTRL_256B_FLIT), FLAG(w, PCI_CXL_FB_CTRL_PBR_FLIT));
11769e567a4eSJaxon Haws 
11779e567a4eSJaxon Haws   w = get_conf_word(d, where + PCI_CXL_FB_PORT_STATUS);
11789e567a4eSJaxon Haws   printf("\n\t\tFBSta:\tCache%c IO%c Mem%c SynHdrByp%c DrftBuf%c 68BFlit%c MltLogDev%c",
11799e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_STAT_CACHE), FLAG(w, PCI_CXL_FB_STAT_IO),
11809e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_STAT_MEM), FLAG(w, PCI_CXL_FB_STAT_SYNC_HDR_BYP),
11819e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_STAT_DRFT_BUF), FLAG(w, PCI_CXL_FB_STAT_68B_FLIT),
11829e567a4eSJaxon Haws       FLAG(w, PCI_CXL_FB_STAT_MULT_LOG_DEV));
11839e567a4eSJaxon Haws 
11849e567a4eSJaxon Haws   if (rev > 1)
11859e567a4eSJaxon Haws     printf(" 256BFlit%c PBRFlit%c",
11869e567a4eSJaxon Haws         FLAG(w, PCI_CXL_FB_STAT_256B_FLIT), FLAG(w, PCI_CXL_FB_STAT_PBR_FLIT));
118723b1ee0cSAlexis Gryta   printf("\n");
11889e567a4eSJaxon Haws 
118923b1ee0cSAlexis Gryta   // From Rev 1
119023b1ee0cSAlexis Gryta   if (rev >= 1)
119123b1ee0cSAlexis Gryta     {
11929e567a4eSJaxon Haws       l = get_conf_long(d, where + PCI_CXL_FB_MOD_TS_DATA);
11939e567a4eSJaxon Haws       data = BITS(l, 0, 24);
119423b1ee0cSAlexis Gryta       printf("\t\tFBModTS:\tReceived FB Data: %06x\n", (unsigned int)data);
119523b1ee0cSAlexis Gryta     }
11969e567a4eSJaxon Haws 
119723b1ee0cSAlexis Gryta   // From Rev 2
119823b1ee0cSAlexis Gryta   if (rev >= 2)
11999e567a4eSJaxon Haws     {
12009e567a4eSJaxon Haws       u8 nop;
12019e567a4eSJaxon Haws 
12029e567a4eSJaxon Haws       l = get_conf_long(d, where + PCI_CXL_FB_PORT_CAP2);
12039e567a4eSJaxon Haws       printf("\t\tFBCap2:\tNOPHint%c\n", FLAG(l, PCI_CXL_FB_CAP2_NOP_HINT));
12049e567a4eSJaxon Haws 
12059e567a4eSJaxon Haws       l = get_conf_long(d, where + PCI_CXL_FB_PORT_CTRL2);
12069e567a4eSJaxon Haws       printf("\t\tFBCtl2:\tNOPHint%c\n", FLAG(l, PCI_CXL_FB_CTRL2_NOP_HINT));
12079e567a4eSJaxon Haws 
12089e567a4eSJaxon Haws       l = get_conf_long(d, where + PCI_CXL_FB_PORT_STATUS2);
12099e567a4eSJaxon Haws       nop = BITS(l, 0, 2);
12109e567a4eSJaxon Haws       printf("\t\tFBSta2:\tNOPHintInfo: %x\n", nop);
12119e567a4eSJaxon Haws     }
121223b1ee0cSAlexis Gryta 
121323b1ee0cSAlexis Gryta   // Unparsed data
12143d2d69cbSMartin Mares   if (len > PCI_CXL_FB_LEN)
121523b1ee0cSAlexis Gryta     printf("\t\t<?>\n");
121623b1ee0cSAlexis Gryta }
12179e567a4eSJaxon Haws 
12189e567a4eSJaxon Haws static void
dvsec_cxl_mld(struct device * d,int where)121945824262SJaxon Haws dvsec_cxl_mld(struct device *d, int where)
122045824262SJaxon Haws {
122145824262SJaxon Haws   u16 w;
122245824262SJaxon Haws 
122345824262SJaxon Haws   w = get_conf_word(d, where + PCI_CXL_MLD_NUM_LD);
122445824262SJaxon Haws 
122545824262SJaxon Haws   /* Encodings greater than 16 are reserved */
122645824262SJaxon Haws   if (w && w <= PCI_CXL_MLD_MAX_LD)
122745824262SJaxon Haws     printf("\t\tNumLogDevs: %d\n", w);
122845824262SJaxon Haws }
122945824262SJaxon Haws 
123045824262SJaxon Haws static void
dvsec_cxl_function_map(struct device * d,int where)1231ec4cd47bSJaxon Haws dvsec_cxl_function_map(struct device *d, int where)
1232ec4cd47bSJaxon Haws {
1233ec4cd47bSJaxon Haws 
1234ec4cd47bSJaxon Haws   printf("\t\tFuncMap 0: %08x\n",
1235ec4cd47bSJaxon Haws       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_0)));
1236ec4cd47bSJaxon Haws 
1237ec4cd47bSJaxon Haws   printf("\t\tFuncMap 1: %08x\n",
1238ec4cd47bSJaxon Haws     (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_1)));
1239ec4cd47bSJaxon Haws 
1240ec4cd47bSJaxon Haws   printf("\t\tFuncMap 2: %08x\n",
1241ec4cd47bSJaxon Haws     (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_2)));
1242ec4cd47bSJaxon Haws 
1243ec4cd47bSJaxon Haws   printf("\t\tFuncMap 3: %08x\n",
1244ec4cd47bSJaxon Haws       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_3)));
1245ec4cd47bSJaxon Haws 
1246ec4cd47bSJaxon Haws   printf("\t\tFuncMap 4: %08x\n",
1247ec4cd47bSJaxon Haws       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_4)));
1248ec4cd47bSJaxon Haws 
1249ec4cd47bSJaxon Haws   printf("\t\tFuncMap 5: %08x\n",
1250ec4cd47bSJaxon Haws       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_5)));
1251ec4cd47bSJaxon Haws 
1252ec4cd47bSJaxon Haws   printf("\t\tFuncMap 6: %08x\n",
1253ec4cd47bSJaxon Haws       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_6)));
1254ec4cd47bSJaxon Haws 
1255ec4cd47bSJaxon Haws   printf("\t\tFuncMap 7: %08x\n",
1256ec4cd47bSJaxon Haws       (unsigned int)(get_conf_word(d, where + PCI_CXL_FUN_MAP_REG_7)));
1257ec4cd47bSJaxon Haws }
1258ec4cd47bSJaxon Haws 
1259ec4cd47bSJaxon Haws static void
cap_dvsec_cxl(struct device * d,int id,int rev,int where,int len)12602849db67SMartin Mares cap_dvsec_cxl(struct device *d, int id, int rev, int where, int len)
12610d4491cbSBen Widawsky {
12620d4491cbSBen Widawsky   printf(": CXL\n");
12630d4491cbSBen Widawsky   if (verbose < 2)
12640d4491cbSBen Widawsky     return;
12650d4491cbSBen Widawsky 
12660dfa1050SBen Widawsky   if (!config_fetch(d, where, len))
12670dfa1050SBen Widawsky     return;
12680dfa1050SBen Widawsky 
12692849db67SMartin Mares   switch (id)
12702849db67SMartin Mares     {
12712849db67SMartin Mares     case 0:
127223b1ee0cSAlexis Gryta       printf("\t\tPCIe DVSEC for CXL Devices\n");
12732849db67SMartin Mares       dvsec_cxl_device(d, rev, where, len);
12740dfa1050SBen Widawsky       break;
1275fe0df5d3SBen Widawsky     case 2:
127623b1ee0cSAlexis Gryta       printf("\t\tNon-CXL Function Map DVSEC\n");
1277ec4cd47bSJaxon Haws       dvsec_cxl_function_map(d, where);
1278fe0df5d3SBen Widawsky       break;
12792849db67SMartin Mares     case 3:
128023b1ee0cSAlexis Gryta       printf("\t\tCXL Extensions DVSEC for Ports\n");
12812849db67SMartin Mares       dvsec_cxl_port(d, where, len);
12822849db67SMartin Mares       break;
1283fe0df5d3SBen Widawsky     case 4:
128423b1ee0cSAlexis Gryta       printf("\t\tGPF DVSEC for CXL Ports\n");
12855c75f737SJaxon Haws       dvsec_cxl_gpf_port(d, where);
1286fe0df5d3SBen Widawsky       break;
1287fe0df5d3SBen Widawsky     case 5:
128823b1ee0cSAlexis Gryta       printf("\t\tGPF DVSEC for CXL Devices\n");
1289d462e89cSJaxon Haws       dvsec_cxl_gpf_device(d, where);
1290fe0df5d3SBen Widawsky       break;
1291fe0df5d3SBen Widawsky     case 7:
129223b1ee0cSAlexis Gryta       printf("\t\tPCIe DVSEC for Flex Bus Port\n");
129323b1ee0cSAlexis Gryta       dvsec_cxl_flex_bus(d, where, rev, len);
1294fe0df5d3SBen Widawsky       break;
12952849db67SMartin Mares     case 8:
129623b1ee0cSAlexis Gryta       printf("\t\tRegister Locator DVSEC\n");
12972849db67SMartin Mares       dvsec_cxl_register_locator(d, where, len);
12982849db67SMartin Mares       break;
1299fe0df5d3SBen Widawsky     case 9:
130023b1ee0cSAlexis Gryta       printf("\t\tMLD DVSEC\n");
130145824262SJaxon Haws       dvsec_cxl_mld(d, where);
1302fe0df5d3SBen Widawsky       break;
130323b1ee0cSAlexis Gryta     case 0xa:
130423b1ee0cSAlexis Gryta       printf("\t\tPCIe DVSEC for Test Capability <?>\n");
130523b1ee0cSAlexis Gryta       break;
1306c8b83c6cSBen Widawsky     default:
13072849db67SMartin Mares       printf("\t\tUnknown ID %04x\n", id);
1308c8b83c6cSBen Widawsky     }
13090d4491cbSBen Widawsky }
13100d4491cbSBen Widawsky 
13110d4491cbSBen Widawsky static void
cap_dvsec(struct device * d,int where)13125f1d1265SSean V Kelley cap_dvsec(struct device *d, int where)
13135f1d1265SSean V Kelley {
131471aeac63SMartin Mares   printf("Designated Vendor-Specific: ");
13155f1d1265SSean V Kelley   if (!config_fetch(d, where + PCI_DVSEC_HEADER1, 8))
13165f1d1265SSean V Kelley     {
13175f1d1265SSean V Kelley       printf("<unreadable>\n");
13185f1d1265SSean V Kelley       return;
13195f1d1265SSean V Kelley     }
13205f1d1265SSean V Kelley 
132171aeac63SMartin Mares   u32 hdr = get_conf_long(d, where + PCI_DVSEC_HEADER1);
132271aeac63SMartin Mares   u16 vendor = BITS(hdr, 0, 16);
132371aeac63SMartin Mares   byte rev = BITS(hdr, 16, 4);
132471aeac63SMartin Mares   u16 len = BITS(hdr, 20, 12);
13255f1d1265SSean V Kelley 
132671aeac63SMartin Mares   u16 id = get_conf_long(d, where + PCI_DVSEC_HEADER2);
132771aeac63SMartin Mares 
132871aeac63SMartin Mares   printf("Vendor=%04x ID=%04x Rev=%d Len=%d", vendor, id, rev, len);
13296c138204SBen Widawsky   if (vendor == PCI_DVSEC_VENDOR_ID_CXL && len >= 16)
13302849db67SMartin Mares     cap_dvsec_cxl(d, id, rev, where, len);
133171aeac63SMartin Mares   else
133271aeac63SMartin Mares     printf(" <?>\n");
13335f1d1265SSean V Kelley }
13345f1d1265SSean V Kelley 
13355f1d1265SSean V Kelley static void
cap_evendor(struct device * d,int where)133678ca9582SMartin Mares cap_evendor(struct device *d, int where)
133778ca9582SMartin Mares {
133878ca9582SMartin Mares   u32 hdr;
133978ca9582SMartin Mares 
134078ca9582SMartin Mares   printf("Vendor Specific Information: ");
134178ca9582SMartin Mares   if (!config_fetch(d, where + PCI_EVNDR_HEADER, 4))
134278ca9582SMartin Mares     {
134378ca9582SMartin Mares       printf("<unreadable>\n");
134478ca9582SMartin Mares       return;
134578ca9582SMartin Mares     }
134678ca9582SMartin Mares 
134778ca9582SMartin Mares   hdr = get_conf_long(d, where + PCI_EVNDR_HEADER);
134878ca9582SMartin Mares   printf("ID=%04x Rev=%d Len=%03x <?>\n",
134978ca9582SMartin Mares     BITS(hdr, 0, 16),
135078ca9582SMartin Mares     BITS(hdr, 16, 4),
135178ca9582SMartin Mares     BITS(hdr, 20, 12));
135278ca9582SMartin Mares }
135378ca9582SMartin Mares 
l1pm_calc_pwron(int scale,int value)1354fb17077dSMartin Mares static int l1pm_calc_pwron(int scale, int value)
13558efbe075SRajat Jain {
13568efbe075SRajat Jain   switch (scale)
13578efbe075SRajat Jain     {
13588efbe075SRajat Jain       case 0:
13598efbe075SRajat Jain 	return 2 * value;
13608efbe075SRajat Jain       case 1:
13618efbe075SRajat Jain 	return 10 * value;
13628efbe075SRajat Jain       case 2:
13638efbe075SRajat Jain 	return 100 * value;
13648efbe075SRajat Jain     }
13658efbe075SRajat Jain   return -1;
13668efbe075SRajat Jain }
13678efbe075SRajat Jain 
1368214c9a95SDavid Box static void
cap_l1pm(struct device * d,int where)1369214c9a95SDavid Box cap_l1pm(struct device *d, int where)
1370214c9a95SDavid Box {
13718efbe075SRajat Jain   u32 l1_cap, val, scale;
13728efbe075SRajat Jain   int time;
1373214c9a95SDavid Box 
1374214c9a95SDavid Box   printf("L1 PM Substates\n");
1375214c9a95SDavid Box 
1376214c9a95SDavid Box   if (verbose < 2)
1377214c9a95SDavid Box     return;
1378214c9a95SDavid Box 
13798efbe075SRajat Jain   if (!config_fetch(d, where + PCI_L1PM_SUBSTAT_CAP, 12))
1380214c9a95SDavid Box     {
1381214c9a95SDavid Box       printf("\t\t<unreadable>\n");
1382214c9a95SDavid Box       return;
1383214c9a95SDavid Box     }
1384214c9a95SDavid Box 
13858efbe075SRajat Jain   l1_cap = get_conf_long(d, where + PCI_L1PM_SUBSTAT_CAP);
1386214c9a95SDavid Box   printf("\t\tL1SubCap: ");
1387e495466cSMartin Mares   printf("PCI-PM_L1.2%c PCI-PM_L1.1%c ASPM_L1.2%c ASPM_L1.1%c L1_PM_Substates%c\n",
13888efbe075SRajat Jain     FLAG(l1_cap, PCI_L1PM_SUBSTAT_CAP_PM_L12),
13898efbe075SRajat Jain     FLAG(l1_cap, PCI_L1PM_SUBSTAT_CAP_PM_L11),
13908efbe075SRajat Jain     FLAG(l1_cap, PCI_L1PM_SUBSTAT_CAP_ASPM_L12),
13918efbe075SRajat Jain     FLAG(l1_cap, PCI_L1PM_SUBSTAT_CAP_ASPM_L11),
13928efbe075SRajat Jain     FLAG(l1_cap, PCI_L1PM_SUBSTAT_CAP_L1PM_SUPP));
1393214c9a95SDavid Box 
1394fb17077dSMartin Mares   if (l1_cap & PCI_L1PM_SUBSTAT_CAP_PM_L12 || l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
1395214c9a95SDavid Box     {
1396fb17077dSMartin Mares       printf("\t\t\t  PortCommonModeRestoreTime=%dus ", BITS(l1_cap, 8, 8));
13978efbe075SRajat Jain       time = l1pm_calc_pwron(BITS(l1_cap, 16, 2), BITS(l1_cap, 19, 5));
13988efbe075SRajat Jain       if (time != -1)
13998efbe075SRajat Jain 	printf("PortTPowerOnTime=%dus\n", time);
14008efbe075SRajat Jain       else
14018efbe075SRajat Jain 	printf("PortTPowerOnTime=<error>\n");
1402214c9a95SDavid Box     }
14038efbe075SRajat Jain 
14048efbe075SRajat Jain   val = get_conf_long(d, where + PCI_L1PM_SUBSTAT_CTL1);
1405fb17077dSMartin Mares   printf("\t\tL1SubCtl1: PCI-PM_L1.2%c PCI-PM_L1.1%c ASPM_L1.2%c ASPM_L1.1%c\n",
14068efbe075SRajat Jain     FLAG(val, PCI_L1PM_SUBSTAT_CTL1_PM_L12),
14078efbe075SRajat Jain     FLAG(val, PCI_L1PM_SUBSTAT_CTL1_PM_L11),
14088efbe075SRajat Jain     FLAG(val, PCI_L1PM_SUBSTAT_CTL1_ASPM_L12),
14098efbe075SRajat Jain     FLAG(val, PCI_L1PM_SUBSTAT_CTL1_ASPM_L11));
14108efbe075SRajat Jain 
1411fb17077dSMartin Mares   if (l1_cap & PCI_L1PM_SUBSTAT_CAP_PM_L12 || l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
14126469d596SVinson Lee     {
1413fb17077dSMartin Mares       printf("\t\t\t   T_CommonMode=%dus", BITS(val, 8, 8));
14148efbe075SRajat Jain 
14158efbe075SRajat Jain       if (l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
14168efbe075SRajat Jain 	{
14178efbe075SRajat Jain 	  scale = BITS(val, 29, 3);
14188efbe075SRajat Jain 	  if (scale > 5)
1419fb17077dSMartin Mares 	    printf(" LTR1.2_Threshold=<error>");
14208efbe075SRajat Jain 	  else
1421c3d1d465SPali Rohár 	    printf(" LTR1.2_Threshold=%" PCI_U64_FMT_U "ns", BITS(val, 16, 10) * (u64) cap_ltr_scale(scale));
14228efbe075SRajat Jain 	}
1423fb17077dSMartin Mares       printf("\n");
14246469d596SVinson Lee     }
14258efbe075SRajat Jain 
14268efbe075SRajat Jain   val = get_conf_long(d, where + PCI_L1PM_SUBSTAT_CTL2);
14278efbe075SRajat Jain   printf("\t\tL1SubCtl2:");
1428fb17077dSMartin Mares   if (l1_cap & PCI_L1PM_SUBSTAT_CAP_PM_L12 || l1_cap & PCI_L1PM_SUBSTAT_CAP_ASPM_L12)
14298efbe075SRajat Jain     {
14308efbe075SRajat Jain       time = l1pm_calc_pwron(BITS(val, 0, 2), BITS(val, 3, 5));
14318efbe075SRajat Jain       if (time != -1)
1432fb17077dSMartin Mares 	printf(" T_PwrOn=%dus", time);
14338efbe075SRajat Jain       else
1434fb17077dSMartin Mares 	printf(" T_PwrOn=<error>");
1435214c9a95SDavid Box     }
1436fb17077dSMartin Mares   printf("\n");
1437214c9a95SDavid Box }
1438214c9a95SDavid Box 
1439415a9c18SYong, Jonathan static void
cap_ptm(struct device * d,int where)1440415a9c18SYong, Jonathan cap_ptm(struct device *d, int where)
1441415a9c18SYong, Jonathan {
1442415a9c18SYong, Jonathan   u32 buff;
1443415a9c18SYong, Jonathan   u16 clock;
1444415a9c18SYong, Jonathan 
1445415a9c18SYong, Jonathan   printf("Precision Time Measurement\n");
1446415a9c18SYong, Jonathan 
1447415a9c18SYong, Jonathan   if (verbose < 2)
1448415a9c18SYong, Jonathan     return;
1449415a9c18SYong, Jonathan 
1450415a9c18SYong, Jonathan   if (!config_fetch(d, where + 4, 8))
1451415a9c18SYong, Jonathan     {
1452415a9c18SYong, Jonathan       printf("\t\t<unreadable>\n");
1453415a9c18SYong, Jonathan       return;
1454415a9c18SYong, Jonathan     }
1455415a9c18SYong, Jonathan 
1456415a9c18SYong, Jonathan   buff = get_conf_long(d, where + 4);
1457415a9c18SYong, Jonathan   printf("\t\tPTMCap: ");
1458b2caca01SBjorn Helgaas   printf("Requester%c Responder%c Root%c\n",
1459415a9c18SYong, Jonathan     FLAG(buff, 0x1),
1460415a9c18SYong, Jonathan     FLAG(buff, 0x2),
1461415a9c18SYong, Jonathan     FLAG(buff, 0x4));
1462415a9c18SYong, Jonathan 
1463415a9c18SYong, Jonathan   clock = BITS(buff, 8, 8);
1464415a9c18SYong, Jonathan   printf("\t\tPTMClockGranularity: ");
1465415a9c18SYong, Jonathan   switch (clock)
1466415a9c18SYong, Jonathan     {
1467415a9c18SYong, Jonathan       case 0x00:
1468415a9c18SYong, Jonathan         printf("Unimplemented\n");
1469415a9c18SYong, Jonathan         break;
1470415a9c18SYong, Jonathan       case 0xff:
1471415a9c18SYong, Jonathan         printf("Greater than 254ns\n");
1472415a9c18SYong, Jonathan         break;
1473415a9c18SYong, Jonathan       default:
1474415a9c18SYong, Jonathan         printf("%huns\n", clock);
1475415a9c18SYong, Jonathan     }
1476415a9c18SYong, Jonathan 
1477415a9c18SYong, Jonathan   buff = get_conf_long(d, where + 8);
1478415a9c18SYong, Jonathan   printf("\t\tPTMControl: ");
1479b2caca01SBjorn Helgaas   printf("Enabled%c RootSelected%c\n",
1480415a9c18SYong, Jonathan     FLAG(buff, 0x1),
1481415a9c18SYong, Jonathan     FLAG(buff, 0x2));
1482415a9c18SYong, Jonathan 
1483415a9c18SYong, Jonathan   clock = BITS(buff, 8, 8);
1484415a9c18SYong, Jonathan   printf("\t\tPTMEffectiveGranularity: ");
1485415a9c18SYong, Jonathan   switch (clock)
1486415a9c18SYong, Jonathan     {
1487415a9c18SYong, Jonathan       case 0x00:
1488415a9c18SYong, Jonathan         printf("Unknown\n");
1489415a9c18SYong, Jonathan         break;
1490415a9c18SYong, Jonathan       case 0xff:
1491415a9c18SYong, Jonathan         printf("Greater than 254ns\n");
1492415a9c18SYong, Jonathan         break;
1493415a9c18SYong, Jonathan       default:
1494415a9c18SYong, Jonathan         printf("%huns\n", clock);
1495415a9c18SYong, Jonathan     }
1496415a9c18SYong, Jonathan }
1497415a9c18SYong, Jonathan 
149844c6c7fcSMartin Mares static void
print_rebar_range_size(int ld2_size)149944c6c7fcSMartin Mares print_rebar_range_size(int ld2_size)
150044c6c7fcSMartin Mares {
150144c6c7fcSMartin Mares   // This function prints the input as a power-of-2 size value
150244c6c7fcSMartin Mares   // It is biased with 1MB = 0, ...
150344c6c7fcSMartin Mares   // Maximum resizable BAR value supported is 2^63 bytes = 43
150444c6c7fcSMartin Mares   // for the extended resizable BAR capability definition
150544c6c7fcSMartin Mares   // (otherwise it would stop at 2^28)
150644c6c7fcSMartin Mares 
150744c6c7fcSMartin Mares   if (ld2_size >= 0 && ld2_size < 10)
150844c6c7fcSMartin Mares     printf(" %dMB", (1 << ld2_size));
150944c6c7fcSMartin Mares   else if (ld2_size >= 10 && ld2_size < 20)
151044c6c7fcSMartin Mares     printf(" %dGB", (1 << (ld2_size-10)));
151144c6c7fcSMartin Mares   else if (ld2_size >= 20 && ld2_size < 30)
151244c6c7fcSMartin Mares     printf(" %dTB", (1 << (ld2_size-20)));
151344c6c7fcSMartin Mares   else if (ld2_size >= 30 && ld2_size < 40)
151444c6c7fcSMartin Mares     printf(" %dPB", (1 << (ld2_size-30)));
151544c6c7fcSMartin Mares   else if (ld2_size >= 40 && ld2_size < 44)
151644c6c7fcSMartin Mares     printf(" %dEB", (1 << (ld2_size-40)));
151744c6c7fcSMartin Mares   else
151844c6c7fcSMartin Mares     printf(" <unknown>");
151944c6c7fcSMartin Mares }
152044c6c7fcSMartin Mares 
152144c6c7fcSMartin Mares static void
cap_rebar(struct device * d,int where,int virtual)152244c6c7fcSMartin Mares cap_rebar(struct device *d, int where, int virtual)
152344c6c7fcSMartin Mares {
152444c6c7fcSMartin Mares   u32 sizes_buffer, control_buffer, ext_sizes, current_size;
1525d10c2aa1SMartin Mares   u16 bar_index, barcount, i;
1526d10c2aa1SMartin Mares   // If the structure exists, at least one bar is defined
152744c6c7fcSMartin Mares   u16 num_bars = 1;
152844c6c7fcSMartin Mares 
152944c6c7fcSMartin Mares   printf("%s Resizable BAR\n", (virtual) ? "Virtual" : "Physical");
153044c6c7fcSMartin Mares 
1531d10c2aa1SMartin Mares   if (verbose < 2)
153244c6c7fcSMartin Mares     return;
153344c6c7fcSMartin Mares 
153444c6c7fcSMartin Mares   // Go through all defined BAR definitions of the caps, at minimum 1
153544c6c7fcSMartin Mares   // (loop also terminates if num_bars read from caps is > 6)
153644c6c7fcSMartin Mares   for (barcount = 0; barcount < num_bars; barcount++)
153744c6c7fcSMartin Mares     {
153844c6c7fcSMartin Mares       where += 4;
153944c6c7fcSMartin Mares 
154044c6c7fcSMartin Mares       // Get the next BAR configuration
154144c6c7fcSMartin Mares       if (!config_fetch(d, where, 8))
154244c6c7fcSMartin Mares         {
154344c6c7fcSMartin Mares           printf("\t\t<unreadable>\n");
154444c6c7fcSMartin Mares           return;
154544c6c7fcSMartin Mares         }
154644c6c7fcSMartin Mares 
154744c6c7fcSMartin Mares       sizes_buffer = get_conf_long(d, where) >> 4;
154844c6c7fcSMartin Mares       where += 4;
154944c6c7fcSMartin Mares       control_buffer = get_conf_long(d, where);
155044c6c7fcSMartin Mares 
1551d10c2aa1SMartin Mares       bar_index  = BITS(control_buffer, 0, 3);
1552d10c2aa1SMartin Mares       current_size = BITS(control_buffer, 8, 6);
1553d10c2aa1SMartin Mares       ext_sizes = BITS(control_buffer, 16, 16);
155444c6c7fcSMartin Mares 
155544c6c7fcSMartin Mares       if (barcount == 0)
155644c6c7fcSMartin Mares         {
155744c6c7fcSMartin Mares           // Only index 0 controlreg has the num_bar count definition
1558d10c2aa1SMartin Mares           num_bars = BITS(control_buffer, 5, 3);
1559d10c2aa1SMartin Mares 	  if (num_bars < 1 || num_bars > 6)
156044c6c7fcSMartin Mares 	    {
1561d10c2aa1SMartin Mares 	      printf("\t\t<error in resizable BAR: num_bars=%d is out of specification>\n", num_bars);
156244c6c7fcSMartin Mares 	      break;
156344c6c7fcSMartin Mares 	    }
156444c6c7fcSMartin Mares         }
156544c6c7fcSMartin Mares 
156644c6c7fcSMartin Mares       // Resizable BAR list entry have an arbitrary index and current size
1567d10c2aa1SMartin Mares       printf("\t\tBAR %d: current size:", bar_index);
156844c6c7fcSMartin Mares       print_rebar_range_size(current_size);
156944c6c7fcSMartin Mares 
1570d10c2aa1SMartin Mares       if (sizes_buffer || ext_sizes)
157144c6c7fcSMartin Mares 	{
1572d10c2aa1SMartin Mares 	  printf(", supported:");
1573d10c2aa1SMartin Mares 
1574d10c2aa1SMartin Mares 	  for (i=0; i<28; i++)
1575d10c2aa1SMartin Mares 	    if (sizes_buffer & (1U << i))
1576d10c2aa1SMartin Mares 	      print_rebar_range_size(i);
1577d10c2aa1SMartin Mares 
1578d10c2aa1SMartin Mares 	  for (i=0; i<16; i++)
1579d10c2aa1SMartin Mares 	    if (ext_sizes & (1U << i))
1580d10c2aa1SMartin Mares 	      print_rebar_range_size(i + 28);
158144c6c7fcSMartin Mares 	}
158244c6c7fcSMartin Mares 
158344c6c7fcSMartin Mares       printf("\n");
158444c6c7fcSMartin Mares     }
158544c6c7fcSMartin Mares }
158644c6c7fcSMartin Mares 
158760be9345SJonathan Cameron static void
cap_doe(struct device * d,int where)158860be9345SJonathan Cameron cap_doe(struct device *d, int where)
158960be9345SJonathan Cameron {
159060be9345SJonathan Cameron   u32 l;
159160be9345SJonathan Cameron 
159260be9345SJonathan Cameron   printf("Data Object Exchange\n");
159360be9345SJonathan Cameron 
159460be9345SJonathan Cameron   if (verbose < 2)
159560be9345SJonathan Cameron     return;
159660be9345SJonathan Cameron 
159760be9345SJonathan Cameron   if (!config_fetch(d, where + PCI_DOE_CAP, 0x14))
159860be9345SJonathan Cameron     {
159960be9345SJonathan Cameron       printf("\t\t<unreadable>\n");
160060be9345SJonathan Cameron       return;
160160be9345SJonathan Cameron     }
160260be9345SJonathan Cameron 
160360be9345SJonathan Cameron   l = get_conf_long(d, where + PCI_DOE_CAP);
160460be9345SJonathan Cameron   printf("\t\tDOECap: IntSup%c\n",
160560be9345SJonathan Cameron 	 FLAG(l, PCI_DOE_CAP_INT_SUPP));
160660be9345SJonathan Cameron   if (l & PCI_DOE_CAP_INT_SUPP)
1607aeb74fe2SBjorn Helgaas     printf("\t\t\tIntMsgNum %d\n",
160860be9345SJonathan Cameron 	   PCI_DOE_CAP_INT_MSG(l));
160960be9345SJonathan Cameron 
161060be9345SJonathan Cameron   l = get_conf_long(d, where + PCI_DOE_CTL);
161160be9345SJonathan Cameron   printf("\t\tDOECtl: IntEn%c\n",
161260be9345SJonathan Cameron 	 FLAG(l, PCI_DOE_CTL_INT));
161360be9345SJonathan Cameron 
161460be9345SJonathan Cameron   l = get_conf_long(d, where + PCI_DOE_STS);
161560be9345SJonathan Cameron   printf("\t\tDOESta: Busy%c IntSta%c Error%c ObjectReady%c\n",
161660be9345SJonathan Cameron 	 FLAG(l, PCI_DOE_STS_BUSY),
161760be9345SJonathan Cameron 	 FLAG(l, PCI_DOE_STS_INT),
161860be9345SJonathan Cameron 	 FLAG(l, PCI_DOE_STS_ERROR),
161960be9345SJonathan Cameron 	 FLAG(l, PCI_DOE_STS_OBJECT_READY));
162060be9345SJonathan Cameron }
162160be9345SJonathan Cameron 
offstr(char * buf,u32 off)162242fc4263SAlexey Kardashevskiy static const char *offstr(char *buf, u32 off)
162342fc4263SAlexey Kardashevskiy {
162442fc4263SAlexey Kardashevskiy     if (verbose < 3)
162542fc4263SAlexey Kardashevskiy         return "";
162642fc4263SAlexey Kardashevskiy 
162742fc4263SAlexey Kardashevskiy     sprintf(buf, "[%x]", off);
162842fc4263SAlexey Kardashevskiy     return buf;
162942fc4263SAlexey Kardashevskiy }
163042fc4263SAlexey Kardashevskiy 
ide_alg(char * buf,size_t len,u32 l)163142fc4263SAlexey Kardashevskiy static const char *ide_alg(char *buf, size_t len, u32 l)
163242fc4263SAlexey Kardashevskiy {
163342fc4263SAlexey Kardashevskiy     const char *algo[] = { "AES-GCM-256-96b" }; // AES-GCM 256 key size, 96b MAC
163442fc4263SAlexey Kardashevskiy 
163542fc4263SAlexey Kardashevskiy     if (l == 0)
163642fc4263SAlexey Kardashevskiy         snprintf(buf, len, "%s", algo[l]);
163742fc4263SAlexey Kardashevskiy     else
163842fc4263SAlexey Kardashevskiy         snprintf(buf, len, "%s", "reserved");
163942fc4263SAlexey Kardashevskiy     return buf;
164042fc4263SAlexey Kardashevskiy }
164142fc4263SAlexey Kardashevskiy 
164242fc4263SAlexey Kardashevskiy static void
cap_ide(struct device * d,int where)164342fc4263SAlexey Kardashevskiy cap_ide(struct device *d, int where)
164442fc4263SAlexey Kardashevskiy {
16452bbe1d46SMartin Mares     const char * const hdr_enc_mode[] = { "no", "17:2", "25:2", "33:2", "41:2" };
16462bbe1d46SMartin Mares     const char * const stream_state[] = { "insecure", "reserved", "secure" };
16472bbe1d46SMartin Mares     const char * const aggr[] = { "-", "=2", "=4", "=8" };
164842fc4263SAlexey Kardashevskiy     u32 l, l2, linknum = 0, selnum = 0, addrnum, off, i, j;
164942fc4263SAlexey Kardashevskiy     char buf1[16], buf2[16], offs[16];
165042fc4263SAlexey Kardashevskiy 
165142fc4263SAlexey Kardashevskiy     printf("Integrity & Data Encryption\n");
165242fc4263SAlexey Kardashevskiy 
165342fc4263SAlexey Kardashevskiy     if (verbose < 2)
165442fc4263SAlexey Kardashevskiy         return;
165542fc4263SAlexey Kardashevskiy 
165642fc4263SAlexey Kardashevskiy     if (!config_fetch(d, where + PCI_IDE_CAP, 8))
165742fc4263SAlexey Kardashevskiy       {
165842fc4263SAlexey Kardashevskiy         printf("\t\t<unreadable>\n");
165942fc4263SAlexey Kardashevskiy         return;
166042fc4263SAlexey Kardashevskiy       }
166142fc4263SAlexey Kardashevskiy 
166242fc4263SAlexey Kardashevskiy     l = get_conf_long(d, where + PCI_IDE_CAP);
166342fc4263SAlexey Kardashevskiy     if (l & PCI_IDE_CAP_LINK_IDE_SUPP)
166442fc4263SAlexey Kardashevskiy         linknum = PCI_IDE_CAP_LINK_TC_NUM(l) + 1;
166542fc4263SAlexey Kardashevskiy     if (l & PCI_IDE_CAP_SELECTIVE_IDE_SUPP)
166642fc4263SAlexey Kardashevskiy         selnum = PCI_IDE_CAP_SELECTIVE_STREAMS_NUM(l) + 1;
166742fc4263SAlexey Kardashevskiy 
166842fc4263SAlexey Kardashevskiy     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",
166942fc4263SAlexey Kardashevskiy       linknum,
167042fc4263SAlexey Kardashevskiy       selnum,
167142fc4263SAlexey Kardashevskiy       FLAG(l, PCI_IDE_CAP_FLOWTHROUGH_IDE_SUPP),
167242fc4263SAlexey Kardashevskiy       FLAG(l, PCI_IDE_CAP_PARTIAL_HEADER_ENC_SUPP),
167342fc4263SAlexey Kardashevskiy       FLAG(l, PCI_IDE_CAP_AGGREGATION_SUPP),
167442fc4263SAlexey Kardashevskiy       FLAG(l, PCI_IDE_CAP_PCRC_SUPP),
167542fc4263SAlexey Kardashevskiy       FLAG(l, PCI_IDE_CAP_IDE_KM_SUPP),
167642fc4263SAlexey Kardashevskiy       ide_alg(buf2, sizeof(buf2), PCI_IDE_CAP_ALG(l)),
167742fc4263SAlexey Kardashevskiy       PCI_IDE_CAP_LINK_TC_NUM(l) + 1,
167842fc4263SAlexey Kardashevskiy       FLAG(l, PCI_IDE_CAP_TEE_LIMITED_SUPP)
167942fc4263SAlexey Kardashevskiy       );
168042fc4263SAlexey Kardashevskiy 
168142fc4263SAlexey Kardashevskiy     l = get_conf_long(d, where + PCI_IDE_CTL);
168242fc4263SAlexey Kardashevskiy     printf("\t\tIDECtl: FTEn%c\n",
168342fc4263SAlexey Kardashevskiy       FLAG(l, PCI_IDE_CTL_FLOWTHROUGH_IDE));
168442fc4263SAlexey Kardashevskiy 
168542fc4263SAlexey Kardashevskiy     // The rest of the capability is variable length arrays
168642fc4263SAlexey Kardashevskiy     off = where + PCI_IDE_LINK_STREAM;
168742fc4263SAlexey Kardashevskiy 
168842fc4263SAlexey Kardashevskiy     // Link IDE Register Block repeated 0 to 8 times
168942fc4263SAlexey Kardashevskiy     if (linknum)
169042fc4263SAlexey Kardashevskiy       {
169142fc4263SAlexey Kardashevskiy         if (!config_fetch(d, off, 8 * linknum))
169242fc4263SAlexey Kardashevskiy           {
169342fc4263SAlexey Kardashevskiy             printf("\t\t<unreadable>\n");
169442fc4263SAlexey Kardashevskiy             return;
169542fc4263SAlexey Kardashevskiy           }
169642fc4263SAlexey Kardashevskiy         for (i = 0; i < linknum; ++i)
169742fc4263SAlexey Kardashevskiy           {
169842fc4263SAlexey Kardashevskiy             // Link IDE Stream Control Register
169942fc4263SAlexey Kardashevskiy             l = get_conf_long(d, off);
170042fc4263SAlexey Kardashevskiy             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",
170142fc4263SAlexey Kardashevskiy               offstr(offs, off),
170242fc4263SAlexey Kardashevskiy               i,
170342fc4263SAlexey Kardashevskiy               FLAG(l, PCI_IDE_LINK_CTL_EN),
170442fc4263SAlexey Kardashevskiy               aggr[PCI_IDE_LINK_CTL_TX_AGGR_NPR(l)],
170542fc4263SAlexey Kardashevskiy               aggr[PCI_IDE_LINK_CTL_TX_AGGR_PR(l)],
170642fc4263SAlexey Kardashevskiy               aggr[PCI_IDE_LINK_CTL_TX_AGGR_CPL(l)],
170742fc4263SAlexey Kardashevskiy               FLAG(l, PCI_IDE_LINK_CTL_EN),
170842fc4263SAlexey Kardashevskiy               TABLE(hdr_enc_mode, PCI_IDE_LINK_CTL_PART_ENC(l), buf1),
170942fc4263SAlexey Kardashevskiy               ide_alg(buf2, sizeof(buf2), PCI_IDE_LINK_CTL_ALG(l)),
171042fc4263SAlexey Kardashevskiy               PCI_IDE_LINK_CTL_TC(l),
171142fc4263SAlexey Kardashevskiy               PCI_IDE_LINK_CTL_ID(l)
171242fc4263SAlexey Kardashevskiy               );
171342fc4263SAlexey Kardashevskiy             off += 4;
171442fc4263SAlexey Kardashevskiy 
171542fc4263SAlexey Kardashevskiy             /* Link IDE Stream Status Register */
171642fc4263SAlexey Kardashevskiy             l = get_conf_long(d, off);
171742fc4263SAlexey Kardashevskiy             printf("\t\t%sLinkIDE#%d Sta: Status=%s RecvChkFail%c\n",
171842fc4263SAlexey Kardashevskiy               offstr(offs, off),
171942fc4263SAlexey Kardashevskiy               i,
172042fc4263SAlexey Kardashevskiy               TABLE(stream_state, PCI_IDE_LINK_STS_STATUS(l), buf1),
172142fc4263SAlexey Kardashevskiy               FLAG(l, PCI_IDE_LINK_STS_RECVD_INTEGRITY_CHECK));
172242fc4263SAlexey Kardashevskiy             off += 4;
172342fc4263SAlexey Kardashevskiy           }
172442fc4263SAlexey Kardashevskiy       }
172542fc4263SAlexey Kardashevskiy 
172642fc4263SAlexey Kardashevskiy     for (i = 0; i < selnum; ++i)
172742fc4263SAlexey Kardashevskiy       {
172842fc4263SAlexey Kardashevskiy         // Fetching Selective IDE Stream Capability/Control/Status/RID1/RID2
172942fc4263SAlexey Kardashevskiy         if (!config_fetch(d, off, 20))
173042fc4263SAlexey Kardashevskiy           {
173142fc4263SAlexey Kardashevskiy             printf("\t\t<unreadable>\n");
173242fc4263SAlexey Kardashevskiy             return;
173342fc4263SAlexey Kardashevskiy           }
173442fc4263SAlexey Kardashevskiy 
173542fc4263SAlexey Kardashevskiy         // Selective IDE Stream Capability Register
173642fc4263SAlexey Kardashevskiy         l = get_conf_long(d, off);
173742fc4263SAlexey Kardashevskiy         printf("\t\t%sSelectiveIDE#%d Cap: RID#=%d\n",
173842fc4263SAlexey Kardashevskiy           offstr(offs, off),
173942fc4263SAlexey Kardashevskiy           i,
174042fc4263SAlexey Kardashevskiy           PCI_IDE_SEL_CAP_BLOCKS_NUM(l));
174142fc4263SAlexey Kardashevskiy         off += 4;
174242fc4263SAlexey Kardashevskiy         addrnum = PCI_IDE_SEL_CAP_BLOCKS_NUM(l);
174342fc4263SAlexey Kardashevskiy 
174442fc4263SAlexey Kardashevskiy         // Selective IDE Stream Control Register
174542fc4263SAlexey Kardashevskiy         l = get_conf_long(d, off);
174642fc4263SAlexey Kardashevskiy 
17478c140beeSAlexey Kardashevskiy         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",
174842fc4263SAlexey Kardashevskiy           offstr(offs, off),
174942fc4263SAlexey Kardashevskiy           i,
175042fc4263SAlexey Kardashevskiy           FLAG(l, PCI_IDE_SEL_CTL_EN),
175142fc4263SAlexey Kardashevskiy           aggr[PCI_IDE_SEL_CTL_TX_AGGR_NPR(l)],
175242fc4263SAlexey Kardashevskiy           aggr[PCI_IDE_SEL_CTL_TX_AGGR_PR(l)],
175342fc4263SAlexey Kardashevskiy           aggr[PCI_IDE_SEL_CTL_TX_AGGR_CPL(l)],
175442fc4263SAlexey Kardashevskiy           FLAG(l, PCI_IDE_SEL_CTL_PCRC_EN),
17558c140beeSAlexey Kardashevskiy           FLAG(l, PCI_IDE_SEL_CTL_CFG_EN),
175642fc4263SAlexey Kardashevskiy           TABLE(hdr_enc_mode, PCI_IDE_SEL_CTL_PART_ENC(l), buf1),
175742fc4263SAlexey Kardashevskiy           ide_alg(buf2, sizeof(buf2), PCI_IDE_SEL_CTL_ALG(l)),
175842fc4263SAlexey Kardashevskiy           PCI_IDE_SEL_CTL_TC(l),
175942fc4263SAlexey Kardashevskiy           PCI_IDE_SEL_CTL_ID(l),
176042fc4263SAlexey Kardashevskiy           (l & PCI_IDE_SEL_CTL_DEFAULT) ? " Default" : ""
176142fc4263SAlexey Kardashevskiy           );
176242fc4263SAlexey Kardashevskiy         off += 4;
176342fc4263SAlexey Kardashevskiy 
176442fc4263SAlexey Kardashevskiy         // Selective IDE Stream Status Register
176542fc4263SAlexey Kardashevskiy         l = get_conf_long(d, off);
176642fc4263SAlexey Kardashevskiy         printf("\t\t%sSelectiveIDE#%d Sta: %s RecvChkFail%c\n",
176742fc4263SAlexey Kardashevskiy           offstr(offs, off),
176842fc4263SAlexey Kardashevskiy           i ,
176942fc4263SAlexey Kardashevskiy           TABLE(stream_state, PCI_IDE_SEL_STS_STATUS(l), buf1),
177042fc4263SAlexey Kardashevskiy           FLAG(l, PCI_IDE_SEL_STS_RECVD_INTEGRITY_CHECK));
177142fc4263SAlexey Kardashevskiy         off += 4;
177242fc4263SAlexey Kardashevskiy 
177342fc4263SAlexey Kardashevskiy         // IDE RID Association Registers
177442fc4263SAlexey Kardashevskiy         l = get_conf_long(d, off);
177542fc4263SAlexey Kardashevskiy         l2 = get_conf_long(d, off + 4);
177642fc4263SAlexey Kardashevskiy 
177742fc4263SAlexey Kardashevskiy         printf("\t\t%sSelectiveIDE#%d RID: Valid%c Base=%x Limit=%x SegBase=%x\n",
177842fc4263SAlexey Kardashevskiy           offstr(offs, off),
177942fc4263SAlexey Kardashevskiy           i,
178042fc4263SAlexey Kardashevskiy           FLAG(l2, PCI_IDE_SEL_RID_2_VALID),
178142fc4263SAlexey Kardashevskiy           PCI_IDE_SEL_RID_2_BASE(l2),
178242fc4263SAlexey Kardashevskiy           PCI_IDE_SEL_RID_1_LIMIT(l),
178342fc4263SAlexey Kardashevskiy           PCI_IDE_SEL_RID_2_SEG_BASE(l2));
178442fc4263SAlexey Kardashevskiy         off += 8;
178542fc4263SAlexey Kardashevskiy 
178642fc4263SAlexey Kardashevskiy         if (!config_fetch(d, off, addrnum * 12))
178742fc4263SAlexey Kardashevskiy           {
178842fc4263SAlexey Kardashevskiy             printf("\t\t<unreadable>\n");
178942fc4263SAlexey Kardashevskiy             return;
179042fc4263SAlexey Kardashevskiy           }
179142fc4263SAlexey Kardashevskiy 
179242fc4263SAlexey Kardashevskiy         // IDE Address Association Registers
179342fc4263SAlexey Kardashevskiy         for (j = 0; j < addrnum; ++j)
179442fc4263SAlexey Kardashevskiy           {
179542fc4263SAlexey Kardashevskiy             u64 limit, base;
179642fc4263SAlexey Kardashevskiy 
179742fc4263SAlexey Kardashevskiy             l = get_conf_long(d, off);
179842fc4263SAlexey Kardashevskiy             limit = get_conf_long(d, off + 4);
17998c140beeSAlexey Kardashevskiy             limit <<= 32;
18008c140beeSAlexey Kardashevskiy             limit |= (PCI_IDE_SEL_ADDR_1_LIMIT_LOW(l) << 20) | 0xFFFFF;
180142fc4263SAlexey Kardashevskiy             base = get_conf_long(d, off + 8);
18028c140beeSAlexey Kardashevskiy             base <<= 32;
18038c140beeSAlexey Kardashevskiy             base |= PCI_IDE_SEL_ADDR_1_BASE_LOW(l) << 20;
1804*b78c087bSMartin Mares             printf("\t\t%sSelectiveIDE#%d RID#%d: Valid%c Base=%" PCI_U64_FMT_X " Limit=%" PCI_U64_FMT_X "\n",
180542fc4263SAlexey Kardashevskiy               offstr(offs, off),
180642fc4263SAlexey Kardashevskiy               i,
180742fc4263SAlexey Kardashevskiy               j,
180842fc4263SAlexey Kardashevskiy               FLAG(l, PCI_IDE_SEL_ADDR_1_VALID),
18098c140beeSAlexey Kardashevskiy               base,
18108c140beeSAlexey Kardashevskiy               limit);
181142fc4263SAlexey Kardashevskiy             off += 12;
181242fc4263SAlexey Kardashevskiy           }
181342fc4263SAlexey Kardashevskiy       }
181442fc4263SAlexey Kardashevskiy }
181542fc4263SAlexey Kardashevskiy 
l0p_exit_latency(int value)18169611db3eSPaul Cassidy static const char *l0p_exit_latency(int value)
18179611db3eSPaul Cassidy {
18182bbe1d46SMartin Mares   static const char * const latencies[] = {
18199611db3eSPaul Cassidy     "Less than 1us",
18209611db3eSPaul Cassidy     "1us to less than 2us",
18219611db3eSPaul Cassidy     "2us to less than 4us",
18229611db3eSPaul Cassidy     "4us to less than 8us",
18239611db3eSPaul Cassidy     "8us to less than 16us",
18249611db3eSPaul Cassidy     "16us to less than 32us",
18259611db3eSPaul Cassidy     "32us-64us",
18269611db3eSPaul Cassidy     "More than 64us"
18279611db3eSPaul Cassidy   };
18289611db3eSPaul Cassidy 
18299611db3eSPaul Cassidy   if (value >= 0 && value <= 7)
18309611db3eSPaul Cassidy     return latencies[value];
18319611db3eSPaul Cassidy   return "Unknown";
18329611db3eSPaul Cassidy }
18339611db3eSPaul Cassidy 
link_width_str(char * buf,size_t buflen,int width)18349611db3eSPaul Cassidy static const char *link_width_str(char *buf, size_t buflen, int width)
18359611db3eSPaul Cassidy {
18369611db3eSPaul Cassidy   switch (width)
18379611db3eSPaul Cassidy     {
18389611db3eSPaul Cassidy       case 0:
18399611db3eSPaul Cassidy         return "x1";
18409611db3eSPaul Cassidy       case 1:
18419611db3eSPaul Cassidy         return "x2";
18429611db3eSPaul Cassidy       case 2:
18439611db3eSPaul Cassidy         return "x4";
18449611db3eSPaul Cassidy       case 3:
18459611db3eSPaul Cassidy         return "x8";
18469611db3eSPaul Cassidy       case 4:
18479611db3eSPaul Cassidy         return "x16";
18489611db3eSPaul Cassidy       case 7:
18499611db3eSPaul Cassidy         return "Dynamic";
18509611db3eSPaul Cassidy       default:
18519611db3eSPaul Cassidy         snprintf(buf, buflen, "Unknown (%d)", width);
18529611db3eSPaul Cassidy         return buf;
18539611db3eSPaul Cassidy     }
18549611db3eSPaul Cassidy }
18559611db3eSPaul Cassidy 
18569611db3eSPaul Cassidy static void
cap_dev3(struct device * d,int where)18579611db3eSPaul Cassidy cap_dev3(struct device *d, int where)
18589611db3eSPaul Cassidy {
18599611db3eSPaul Cassidy   u32 devcap3;
18609611db3eSPaul Cassidy   u16 devctl3, devsta3;
18619611db3eSPaul Cassidy   char buf[16];
18629611db3eSPaul Cassidy 
18639611db3eSPaul Cassidy   printf("Device 3\n");
18649611db3eSPaul Cassidy 
18659611db3eSPaul Cassidy   if (verbose < 2)
18669611db3eSPaul Cassidy     return;
18679611db3eSPaul Cassidy 
18689611db3eSPaul Cassidy   if (!config_fetch(d, where + PCI_DEV3_DEVCAP3, 4))
18699611db3eSPaul Cassidy     return;
18709611db3eSPaul Cassidy   devcap3 = get_conf_long(d, where + PCI_DEV3_DEVCAP3);
18719611db3eSPaul Cassidy 
18729611db3eSPaul Cassidy   printf("\t\tDevCap3: DMWr Request Routing%c, 14-Bit Tag Completer%c, 14-Bit Tag Requester%c\n"
18739611db3eSPaul Cassidy          "\t\t\t L0p%c",
18749611db3eSPaul Cassidy          FLAG(devcap3, PCI_DEV3_DEVCAP3_DMWR_REQ),
18759611db3eSPaul Cassidy          FLAG(devcap3, PCI_DEV3_DEVCAP3_14BIT_TAG_COMP),
18769611db3eSPaul Cassidy          FLAG(devcap3, PCI_DEV3_DEVCAP3_14BIT_TAG_REQ),
18779611db3eSPaul Cassidy          FLAG(devcap3, PCI_DEV3_DEVCAP3_L0P_SUPP));
18789611db3eSPaul Cassidy 
18799611db3eSPaul Cassidy   if (devcap3 & PCI_DEV3_DEVCAP3_L0P_SUPP)
18809611db3eSPaul Cassidy     printf(", Port L0p Exit Latency: %s, Retimer L0p Exit Latency: %s",
18819611db3eSPaul Cassidy            l0p_exit_latency(PCI_DEV3_DEVCAP3_PORT_L0P_EXIT(devcap3)),
18829611db3eSPaul Cassidy            l0p_exit_latency(PCI_DEV3_DEVCAP3_RETIMER_L0P_EXIT(devcap3)));
18839611db3eSPaul Cassidy 
18849611db3eSPaul Cassidy   printf("\n\t\t\t UIO Mem RdWr Completer%c, UIO Mem RdWr Requester%c\n",
18859611db3eSPaul Cassidy          FLAG(devcap3, PCI_DEV3_DEVCAP3_UIO_MEM_RDWR_COMP),
18869611db3eSPaul Cassidy          FLAG(devcap3, PCI_DEV3_DEVCAP3_UIO_MEM_RDWR_REQ));
18879611db3eSPaul Cassidy 
18889611db3eSPaul Cassidy   if (!config_fetch(d, where + PCI_DEV3_DEVCTL3, 2))
18899611db3eSPaul Cassidy     return;
18909611db3eSPaul Cassidy   devctl3 = get_conf_word(d, where + PCI_DEV3_DEVCTL3);
18919611db3eSPaul Cassidy 
18929611db3eSPaul Cassidy   printf("\t\tDevCtl3: DMWr Requester%c, DMWr Egress Blocking%c, 14-Bit Tag Requester%c\n"
18939611db3eSPaul Cassidy          "\t\t\t L0p%c, Target Link Width: %s\n"
18949611db3eSPaul Cassidy          "\t\t\t UIO Mem RdWr Requester%c, UIO Request 256B Boundary%c\n",
18959611db3eSPaul Cassidy          FLAG(devctl3, PCI_DEV3_DEVCTL3_DMWR_REQ_EN),
18969611db3eSPaul Cassidy          FLAG(devctl3, PCI_DEV3_DEVCTL3_DMWR_EGRESS_BLK),
18979611db3eSPaul Cassidy          FLAG(devctl3, PCI_DEV3_DEVCTL3_14BIT_TAG_REQ_EN),
18989611db3eSPaul Cassidy          FLAG(devctl3, PCI_DEV3_DEVCTL3_L0P_EN),
18999611db3eSPaul Cassidy          link_width_str(buf, sizeof(buf), PCI_DEV3_DEVCTL3_TARGET_LINK_WIDTH(devctl3)),
19009611db3eSPaul Cassidy          FLAG(devctl3, PCI_DEV3_DEVCTL3_UIO_MEM_RDWR_REQ_EN),
19019611db3eSPaul Cassidy          FLAG(~devctl3, PCI_DEV3_DEVCTL3_UIO_REQ_256B_DIS));
19029611db3eSPaul Cassidy 
19039611db3eSPaul Cassidy   if (!config_fetch(d, where + PCI_DEV3_DEVSTA3, 2))
19049611db3eSPaul Cassidy     return;
19059611db3eSPaul Cassidy   devsta3 = get_conf_word(d, where + PCI_DEV3_DEVSTA3);
19069611db3eSPaul Cassidy 
19079611db3eSPaul Cassidy   printf("\t\tDevSta3: Initial Link Width: %s, Segment Captured%c, Remote L0p%c\n",
19089611db3eSPaul Cassidy          link_width_str(buf, sizeof(buf), PCI_DEV3_DEVSTA3_INIT_LINK_WIDTH(devsta3)),
19099611db3eSPaul Cassidy          FLAG(devsta3, PCI_DEV3_DEVSTA3_SEGMENT_CAPTURED),
19109611db3eSPaul Cassidy          FLAG(devsta3, PCI_DEV3_DEVSTA3_REMOTE_L0P_SUPP));
19119611db3eSPaul Cassidy }
19129611db3eSPaul Cassidy 
1913c7a34993SMartin Mares void
show_ext_caps(struct device * d,int type)1914a1492b88SBjorn Helgaas show_ext_caps(struct device *d, int type)
1915c7a34993SMartin Mares {
1916c7a34993SMartin Mares   int where = 0x100;
1917c7a34993SMartin Mares   char been_there[0x1000];
1918c7a34993SMartin Mares   memset(been_there, 0, 0x1000);
1919c7a34993SMartin Mares   do
1920c7a34993SMartin Mares     {
1921c7a34993SMartin Mares       u32 header;
192233088c24SMartin Mares       int id, version;
1923c7a34993SMartin Mares 
1924c7a34993SMartin Mares       if (!config_fetch(d, where, 4))
1925c7a34993SMartin Mares 	break;
1926c7a34993SMartin Mares       header = get_conf_long(d, where);
1927861063f3SPali Rohár       if (!header || header == 0xffffffff)
1928c7a34993SMartin Mares 	break;
1929c7a34993SMartin Mares       id = header & 0xffff;
193033088c24SMartin Mares       version = (header >> 16) & 0xf;
193133088c24SMartin Mares       printf("\tCapabilities: [%03x", where);
193233088c24SMartin Mares       if (verbose > 1)
193333088c24SMartin Mares 	printf(" v%d", version);
193433088c24SMartin Mares       printf("] ");
1935c7a34993SMartin Mares       if (been_there[where]++)
1936c7a34993SMartin Mares 	{
1937c7a34993SMartin Mares 	  printf("<chain looped>\n");
1938c7a34993SMartin Mares 	  break;
1939c7a34993SMartin Mares 	}
1940c7a34993SMartin Mares       switch (id)
1941c7a34993SMartin Mares 	{
1942c508d1c9SBjorn Helgaas 	  case PCI_EXT_CAP_ID_NULL:
1943c508d1c9SBjorn Helgaas 	    printf("Null\n");
1944c508d1c9SBjorn Helgaas 	    break;
1945c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_AER:
1946a1492b88SBjorn Helgaas 	    cap_aer(d, where, type);
1947c7a34993SMartin Mares 	    break;
1948de91b6f2SKeith Busch 	  case PCI_EXT_CAP_ID_DPC:
1949de91b6f2SKeith Busch 	    cap_dpc(d, where);
1950de91b6f2SKeith Busch 	    break;
1951c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_VC:
195233088c24SMartin Mares 	  case PCI_EXT_CAP_ID_VC2:
195333088c24SMartin Mares 	    cap_vc(d, where);
1954c7a34993SMartin Mares 	    break;
1955c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_DSN:
1956c7a34993SMartin Mares 	    cap_dsn(d, where);
1957c7a34993SMartin Mares 	    break;
1958c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_PB:
1959c7a34993SMartin Mares 	    printf("Power Budgeting <?>\n");
1960c7a34993SMartin Mares 	    break;
1961c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_RCLINK:
19625a9a932cSMartin Mares 	    cap_rclink(d, where);
1963c7a34993SMartin Mares 	    break;
1964c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_RCILINK:
1965c7a34993SMartin Mares 	    printf("Root Complex Internal Link <?>\n");
1966c7a34993SMartin Mares 	    break;
1967e12bd01eSSean V Kelley 	  case PCI_EXT_CAP_ID_RCEC:
1968e12bd01eSSean V Kelley 	    cap_rcec(d, where);
1969c7a34993SMartin Mares 	    break;
1970c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_MFVC:
1971c7a34993SMartin Mares 	    printf("Multi-Function Virtual Channel <?>\n");
1972c7a34993SMartin Mares 	    break;
1973eff08b33SBjorn Helgaas 	  case PCI_EXT_CAP_ID_RCRB:
1974eff08b33SBjorn Helgaas 	    printf("Root Complex Register Block <?>\n");
1975c7a34993SMartin Mares 	    break;
1976c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_VNDR:
197778ca9582SMartin Mares 	    cap_evendor(d, where);
1978c7a34993SMartin Mares 	    break;
1979c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_ACS:
1980c7a34993SMartin Mares 	    cap_acs(d, where);
1981c7a34993SMartin Mares 	    break;
1982c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_ARI:
1983c7a34993SMartin Mares 	    cap_ari(d, where);
1984c7a34993SMartin Mares 	    break;
1985c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_ATS:
1986c7a34993SMartin Mares 	    cap_ats(d, where);
1987c7a34993SMartin Mares 	    break;
1988c7a34993SMartin Mares 	  case PCI_EXT_CAP_ID_SRIOV:
1989c7a34993SMartin Mares 	    cap_sriov(d, where);
1990c7a34993SMartin Mares 	    break;
1991b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_MRIOV:
1992b8f7cd64SBjorn Helgaas 	    printf("Multi-Root I/O Virtualization <?>\n");
1993b8f7cd64SBjorn Helgaas 	    break;
1994c0d9545cSBjorn Helgaas 	  case PCI_EXT_CAP_ID_MCAST:
1995c0d9545cSBjorn Helgaas 	    cap_multicast(d, where, type);
1996c0d9545cSBjorn Helgaas 	    break;
1997a858df0dSDavid Woodhouse 	  case PCI_EXT_CAP_ID_PRI:
1998a858df0dSDavid Woodhouse 	    cap_pri(d, where);
1999a858df0dSDavid Woodhouse 	    break;
2000b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_REBAR:
200144c6c7fcSMartin Mares 	    cap_rebar(d, where, 0);
2002b8f7cd64SBjorn Helgaas 	    break;
2003b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_DPA:
2004b8f7cd64SBjorn Helgaas 	    printf("Dynamic Power Allocation <?>\n");
2005b8f7cd64SBjorn Helgaas 	    break;
200667da1792SMartin Mares 	  case PCI_EXT_CAP_ID_TPH:
200767da1792SMartin Mares 	    cap_tph(d, where);
200867da1792SMartin Mares 	    break;
200967da1792SMartin Mares 	  case PCI_EXT_CAP_ID_LTR:
201067da1792SMartin Mares 	    cap_ltr(d, where);
201167da1792SMartin Mares 	    break;
2012b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_SECPCI:
20139225e71dSMartin Mares 	    cap_sec(d, where);
2014b8f7cd64SBjorn Helgaas 	    break;
2015b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_PMUX:
2016b8f7cd64SBjorn Helgaas 	    printf("Protocol Multiplexing <?>\n");
2017b8f7cd64SBjorn Helgaas 	    break;
2018a858df0dSDavid Woodhouse 	  case PCI_EXT_CAP_ID_PASID:
2019a858df0dSDavid Woodhouse 	    cap_pasid(d, where);
2020a858df0dSDavid Woodhouse 	    break;
2021b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_LNR:
2022b8f7cd64SBjorn Helgaas 	    printf("LN Requester <?>\n");
2023b8f7cd64SBjorn Helgaas 	    break;
2024214c9a95SDavid Box 	  case PCI_EXT_CAP_ID_L1PM:
2025214c9a95SDavid Box 	    cap_l1pm(d, where);
2026214c9a95SDavid Box 	    break;
2027415a9c18SYong, Jonathan 	  case PCI_EXT_CAP_ID_PTM:
2028415a9c18SYong, Jonathan 	    cap_ptm(d, where);
2029415a9c18SYong, Jonathan 	    break;
2030b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_M_PCIE:
2031b8f7cd64SBjorn Helgaas 	    printf("PCI Express over M_PHY <?>\n");
2032b8f7cd64SBjorn Helgaas 	    break;
2033b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_FRS:
2034b8f7cd64SBjorn Helgaas 	    printf("FRS Queueing <?>\n");
2035b8f7cd64SBjorn Helgaas 	    break;
2036b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_RTR:
2037b8f7cd64SBjorn Helgaas 	    printf("Readiness Time Reporting <?>\n");
2038b8f7cd64SBjorn Helgaas 	    break;
2039b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_DVSEC:
20405f1d1265SSean V Kelley 	    cap_dvsec(d, where);
2041b8f7cd64SBjorn Helgaas 	    break;
2042b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_VF_REBAR:
204344c6c7fcSMartin Mares 	    cap_rebar(d, where, 1);
2044b8f7cd64SBjorn Helgaas 	    break;
2045b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_DLNK:
2046b8f7cd64SBjorn Helgaas 	    printf("Data Link Feature <?>\n");
2047b8f7cd64SBjorn Helgaas 	    break;
2048b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_16GT:
20490c6383e9STristan Watts-Willis 	    cap_phy_16gt(d, where);
2050b8f7cd64SBjorn Helgaas 	    break;
2051b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_LMR:
2052d016c32dSNikita Proshkin 	    cap_lmr(d, where);
2053b8f7cd64SBjorn Helgaas 	    break;
2054b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_HIER_ID:
2055b8f7cd64SBjorn Helgaas 	    printf("Hierarchy ID <?>\n");
2056b8f7cd64SBjorn Helgaas 	    break;
2057b8f7cd64SBjorn Helgaas 	  case PCI_EXT_CAP_ID_NPEM:
2058b8f7cd64SBjorn Helgaas 	    printf("Native PCIe Enclosure Management <?>\n");
2059b8f7cd64SBjorn Helgaas 	    break;
2060db43fb5eSMateusz Nowicki 	  case PCI_EXT_CAP_ID_32GT:
20610c6383e9STristan Watts-Willis 	    cap_phy_32gt(d, where);
2062db43fb5eSMateusz Nowicki 	    break;
206360be9345SJonathan Cameron 	  case PCI_EXT_CAP_ID_DOE:
206460be9345SJonathan Cameron 	    cap_doe(d, where);
206560be9345SJonathan Cameron 	    break;
206642fc4263SAlexey Kardashevskiy 	  case PCI_EXT_CAP_ID_IDE:
206742fc4263SAlexey Kardashevskiy 	    cap_ide(d, where);
206842fc4263SAlexey Kardashevskiy 	    break;
206904d90becSTristan Watts-Willis 	  case PCI_EXT_CAP_ID_64GT:
207004d90becSTristan Watts-Willis 	    cap_phy_64gt(d, where);
207104d90becSTristan Watts-Willis 	    break;
20729611db3eSPaul Cassidy 	  case PCI_EXT_CAP_ID_DEV3:
20739611db3eSPaul Cassidy 	    cap_dev3(d, where);
20749611db3eSPaul Cassidy 	    break;
2075c7a34993SMartin Mares 	  default:
207660a45a7eSBjorn Helgaas 	    printf("Extended Capability ID %#02x\n", id);
2077c7a34993SMartin Mares 	    break;
2078c7a34993SMartin Mares 	}
2079d61c4772SMartin Mares       where = (header >> 20) & ~3;
2080c7a34993SMartin Mares     } while (where);
2081c7a34993SMartin Mares }
2082