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