1c7a34993SMartin Mares /*
2c7a34993SMartin Mares * The PCI Utilities -- Show Capabilities
3c7a34993SMartin Mares *
4b47b5bd4SMartin Mares * Copyright (c) 1997--2018 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>
1349efa87fSKobayashi Daisuke #include <stdlib.h>
14c7a34993SMartin Mares
15c7a34993SMartin Mares #include "lspci.h"
16c7a34993SMartin Mares
17c7a34993SMartin Mares static void
cap_pm(struct device * d,int where,int cap)18c7a34993SMartin Mares cap_pm(struct device *d, int where, int cap)
19c7a34993SMartin Mares {
20c7a34993SMartin Mares int t, b;
21c7a34993SMartin Mares static int pm_aux_current[8] = { 0, 55, 100, 160, 220, 270, 320, 375 };
22c7a34993SMartin Mares
23c7a34993SMartin Mares printf("Power Management version %d\n", cap & PCI_PM_CAP_VER_MASK);
24c7a34993SMartin Mares if (verbose < 2)
25c7a34993SMartin Mares return;
26c7a34993SMartin Mares printf("\t\tFlags: PMEClk%c DSI%c D1%c D2%c AuxCurrent=%dmA PME(D0%c,D1%c,D2%c,D3hot%c,D3cold%c)\n",
27c7a34993SMartin Mares FLAG(cap, PCI_PM_CAP_PME_CLOCK),
28c7a34993SMartin Mares FLAG(cap, PCI_PM_CAP_DSI),
29c7a34993SMartin Mares FLAG(cap, PCI_PM_CAP_D1),
30c7a34993SMartin Mares FLAG(cap, PCI_PM_CAP_D2),
3102d761b4SBjorn Helgaas pm_aux_current[(cap & PCI_PM_CAP_AUX_C_MASK) >> 6],
32c7a34993SMartin Mares FLAG(cap, PCI_PM_CAP_PME_D0),
33c7a34993SMartin Mares FLAG(cap, PCI_PM_CAP_PME_D1),
34c7a34993SMartin Mares FLAG(cap, PCI_PM_CAP_PME_D2),
35c7a34993SMartin Mares FLAG(cap, PCI_PM_CAP_PME_D3_HOT),
36c7a34993SMartin Mares FLAG(cap, PCI_PM_CAP_PME_D3_COLD));
37c7a34993SMartin Mares if (!config_fetch(d, where + PCI_PM_CTRL, PCI_PM_SIZEOF - PCI_PM_CTRL))
38c7a34993SMartin Mares return;
39c7a34993SMartin Mares t = get_conf_word(d, where + PCI_PM_CTRL);
401c702facSYu Zhao printf("\t\tStatus: D%d NoSoftRst%c PME-Enable%c DSel=%d DScale=%d PME%c\n",
41c7a34993SMartin Mares t & PCI_PM_CTRL_STATE_MASK,
421c702facSYu Zhao FLAG(t, PCI_PM_CTRL_NO_SOFT_RST),
43c7a34993SMartin Mares FLAG(t, PCI_PM_CTRL_PME_ENABLE),
44c7a34993SMartin Mares (t & PCI_PM_CTRL_DATA_SEL_MASK) >> 9,
45c7a34993SMartin Mares (t & PCI_PM_CTRL_DATA_SCALE_MASK) >> 13,
46c7a34993SMartin Mares FLAG(t, PCI_PM_CTRL_PME_STATUS));
47c7a34993SMartin Mares b = get_conf_byte(d, where + PCI_PM_PPB_EXTENSIONS);
48c7a34993SMartin Mares if (b)
49c7a34993SMartin Mares printf("\t\tBridge: PM%c B3%c\n",
506da04fbbSMikhail Bratchikov FLAG(b, PCI_PM_BPCC_ENABLE),
516da04fbbSMikhail Bratchikov FLAG(~b, PCI_PM_PPB_B2_B3));
52c7a34993SMartin Mares }
53c7a34993SMartin Mares
54c7a34993SMartin Mares static void
format_agp_rate(int rate,char * buf,int agp3)55c7a34993SMartin Mares format_agp_rate(int rate, char *buf, int agp3)
56c7a34993SMartin Mares {
57c7a34993SMartin Mares char *c = buf;
58c7a34993SMartin Mares int i;
59c7a34993SMartin Mares
60c7a34993SMartin Mares for (i=0; i<=2; i++)
61c7a34993SMartin Mares if (rate & (1 << i))
62c7a34993SMartin Mares {
63c7a34993SMartin Mares if (c != buf)
64c7a34993SMartin Mares *c++ = ',';
65c7a34993SMartin Mares c += sprintf(c, "x%d", 1 << (i + 2*agp3));
66c7a34993SMartin Mares }
67c7a34993SMartin Mares if (c != buf)
68c7a34993SMartin Mares *c = 0;
69c7a34993SMartin Mares else
70c7a34993SMartin Mares strcpy(buf, "<none>");
71c7a34993SMartin Mares }
72c7a34993SMartin Mares
73c7a34993SMartin Mares static void
cap_agp(struct device * d,int where,int cap)74c7a34993SMartin Mares cap_agp(struct device *d, int where, int cap)
75c7a34993SMartin Mares {
76c7a34993SMartin Mares u32 t;
77c7a34993SMartin Mares char rate[16];
78c7a34993SMartin Mares int ver, rev;
79c7a34993SMartin Mares int agp3 = 0;
80c7a34993SMartin Mares
81c7a34993SMartin Mares ver = (cap >> 4) & 0x0f;
82c7a34993SMartin Mares rev = cap & 0x0f;
83c7a34993SMartin Mares printf("AGP version %x.%x\n", ver, rev);
84c7a34993SMartin Mares if (verbose < 2)
85c7a34993SMartin Mares return;
86c7a34993SMartin Mares if (!config_fetch(d, where + PCI_AGP_STATUS, PCI_AGP_SIZEOF - PCI_AGP_STATUS))
87c7a34993SMartin Mares return;
88c7a34993SMartin Mares t = get_conf_long(d, where + PCI_AGP_STATUS);
89c7a34993SMartin Mares if (ver >= 3 && (t & PCI_AGP_STATUS_AGP3))
90c7a34993SMartin Mares agp3 = 1;
91c7a34993SMartin Mares format_agp_rate(t & 7, rate, agp3);
92c7a34993SMartin Mares printf("\t\tStatus: RQ=%d Iso%c ArqSz=%d Cal=%d SBA%c ITACoh%c GART64%c HTrans%c 64bit%c FW%c AGP3%c Rate=%s\n",
93c7a34993SMartin Mares ((t & PCI_AGP_STATUS_RQ_MASK) >> 24U) + 1,
94c7a34993SMartin Mares FLAG(t, PCI_AGP_STATUS_ISOCH),
95c7a34993SMartin Mares ((t & PCI_AGP_STATUS_ARQSZ_MASK) >> 13),
96c7a34993SMartin Mares ((t & PCI_AGP_STATUS_CAL_MASK) >> 10),
97c7a34993SMartin Mares FLAG(t, PCI_AGP_STATUS_SBA),
98c7a34993SMartin Mares FLAG(t, PCI_AGP_STATUS_ITA_COH),
99c7a34993SMartin Mares FLAG(t, PCI_AGP_STATUS_GART64),
100c7a34993SMartin Mares FLAG(t, PCI_AGP_STATUS_HTRANS),
101c7a34993SMartin Mares FLAG(t, PCI_AGP_STATUS_64BIT),
102c7a34993SMartin Mares FLAG(t, PCI_AGP_STATUS_FW),
103c7a34993SMartin Mares FLAG(t, PCI_AGP_STATUS_AGP3),
104c7a34993SMartin Mares rate);
105c7a34993SMartin Mares t = get_conf_long(d, where + PCI_AGP_COMMAND);
106c7a34993SMartin Mares format_agp_rate(t & 7, rate, agp3);
107c7a34993SMartin Mares printf("\t\tCommand: RQ=%d ArqSz=%d Cal=%d SBA%c AGP%c GART64%c 64bit%c FW%c Rate=%s\n",
108c7a34993SMartin Mares ((t & PCI_AGP_COMMAND_RQ_MASK) >> 24U) + 1,
109c7a34993SMartin Mares ((t & PCI_AGP_COMMAND_ARQSZ_MASK) >> 13),
110c7a34993SMartin Mares ((t & PCI_AGP_COMMAND_CAL_MASK) >> 10),
111c7a34993SMartin Mares FLAG(t, PCI_AGP_COMMAND_SBA),
112c7a34993SMartin Mares FLAG(t, PCI_AGP_COMMAND_AGP),
113c7a34993SMartin Mares FLAG(t, PCI_AGP_COMMAND_GART64),
114c7a34993SMartin Mares FLAG(t, PCI_AGP_COMMAND_64BIT),
115c7a34993SMartin Mares FLAG(t, PCI_AGP_COMMAND_FW),
116c7a34993SMartin Mares rate);
117c7a34993SMartin Mares }
118c7a34993SMartin Mares
119c7a34993SMartin Mares static void
cap_pcix_nobridge(struct device * d,int where)120c7a34993SMartin Mares cap_pcix_nobridge(struct device *d, int where)
121c7a34993SMartin Mares {
122c7a34993SMartin Mares u16 command;
123c7a34993SMartin Mares u32 status;
124c7a34993SMartin Mares static const byte max_outstanding[8] = { 1, 2, 3, 4, 8, 12, 16, 32 };
125c7a34993SMartin Mares
126c7a34993SMartin Mares printf("PCI-X non-bridge device\n");
127c7a34993SMartin Mares
128c7a34993SMartin Mares if (verbose < 2)
129c7a34993SMartin Mares return;
130c7a34993SMartin Mares
131c7a34993SMartin Mares if (!config_fetch(d, where + PCI_PCIX_STATUS, 4))
132c7a34993SMartin Mares return;
133c7a34993SMartin Mares
134c7a34993SMartin Mares command = get_conf_word(d, where + PCI_PCIX_COMMAND);
135c7a34993SMartin Mares status = get_conf_long(d, where + PCI_PCIX_STATUS);
136c7a34993SMartin Mares printf("\t\tCommand: DPERE%c ERO%c RBC=%d OST=%d\n",
137c7a34993SMartin Mares FLAG(command, PCI_PCIX_COMMAND_DPERE),
138c7a34993SMartin Mares FLAG(command, PCI_PCIX_COMMAND_ERO),
139c7a34993SMartin Mares 1 << (9 + ((command & PCI_PCIX_COMMAND_MAX_MEM_READ_BYTE_COUNT) >> 2U)),
140c7a34993SMartin Mares max_outstanding[(command & PCI_PCIX_COMMAND_MAX_OUTSTANDING_SPLIT_TRANS) >> 4U]);
141c7a34993SMartin Mares printf("\t\tStatus: Dev=%02x:%02x.%d 64bit%c 133MHz%c SCD%c USC%c DC=%s DMMRBC=%u DMOST=%u DMCRS=%u RSCEM%c 266MHz%c 533MHz%c\n",
14202d761b4SBjorn Helgaas (status & PCI_PCIX_STATUS_BUS) >> 8,
14302d761b4SBjorn Helgaas (status & PCI_PCIX_STATUS_DEVICE) >> 3,
144c7a34993SMartin Mares (status & PCI_PCIX_STATUS_FUNCTION),
145c7a34993SMartin Mares FLAG(status, PCI_PCIX_STATUS_64BIT),
146c7a34993SMartin Mares FLAG(status, PCI_PCIX_STATUS_133MHZ),
147c7a34993SMartin Mares FLAG(status, PCI_PCIX_STATUS_SC_DISCARDED),
148c7a34993SMartin Mares FLAG(status, PCI_PCIX_STATUS_UNEXPECTED_SC),
149c7a34993SMartin Mares ((status & PCI_PCIX_STATUS_DEVICE_COMPLEXITY) ? "bridge" : "simple"),
15002d761b4SBjorn Helgaas 1 << (9 + ((status & PCI_PCIX_STATUS_DESIGNED_MAX_MEM_READ_BYTE_COUNT) >> 21)),
15102d761b4SBjorn Helgaas max_outstanding[(status & PCI_PCIX_STATUS_DESIGNED_MAX_OUTSTANDING_SPLIT_TRANS) >> 23],
15202d761b4SBjorn Helgaas 1 << (3 + ((status & PCI_PCIX_STATUS_DESIGNED_MAX_CUMULATIVE_READ_SIZE) >> 26)),
153c7a34993SMartin Mares FLAG(status, PCI_PCIX_STATUS_RCVD_SC_ERR_MESS),
154c7a34993SMartin Mares FLAG(status, PCI_PCIX_STATUS_266MHZ),
155c7a34993SMartin Mares FLAG(status, PCI_PCIX_STATUS_533MHZ));
156c7a34993SMartin Mares }
157c7a34993SMartin Mares
158c7a34993SMartin Mares static void
cap_pcix_bridge(struct device * d,int where)159c7a34993SMartin Mares cap_pcix_bridge(struct device *d, int where)
160c7a34993SMartin Mares {
161c7a34993SMartin Mares static const char * const sec_clock_freq[8] = { "conv", "66MHz", "100MHz", "133MHz", "?4", "?5", "?6", "?7" };
162c7a34993SMartin Mares u16 secstatus;
163c7a34993SMartin Mares u32 status, upstcr, downstcr;
164c7a34993SMartin Mares
165c7a34993SMartin Mares printf("PCI-X bridge device\n");
166c7a34993SMartin Mares
167c7a34993SMartin Mares if (verbose < 2)
168c7a34993SMartin Mares return;
169c7a34993SMartin Mares
170c7a34993SMartin Mares if (!config_fetch(d, where + PCI_PCIX_BRIDGE_STATUS, 12))
171c7a34993SMartin Mares return;
172c7a34993SMartin Mares
173c7a34993SMartin Mares secstatus = get_conf_word(d, where + PCI_PCIX_BRIDGE_SEC_STATUS);
174c7a34993SMartin Mares printf("\t\tSecondary Status: 64bit%c 133MHz%c SCD%c USC%c SCO%c SRD%c Freq=%s\n",
175c7a34993SMartin Mares FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_64BIT),
176c7a34993SMartin Mares FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_133MHZ),
177c7a34993SMartin Mares FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_SC_DISCARDED),
178c7a34993SMartin Mares FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_UNEXPECTED_SC),
179c7a34993SMartin Mares FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_SC_OVERRUN),
180c7a34993SMartin Mares FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_SPLIT_REQUEST_DELAYED),
18102d761b4SBjorn Helgaas sec_clock_freq[(secstatus & PCI_PCIX_BRIDGE_SEC_STATUS_CLOCK_FREQ) >> 6]);
182c7a34993SMartin Mares status = get_conf_long(d, where + PCI_PCIX_BRIDGE_STATUS);
183c7a34993SMartin Mares printf("\t\tStatus: Dev=%02x:%02x.%d 64bit%c 133MHz%c SCD%c USC%c SCO%c SRD%c\n",
18402d761b4SBjorn Helgaas (status & PCI_PCIX_BRIDGE_STATUS_BUS) >> 8,
18502d761b4SBjorn Helgaas (status & PCI_PCIX_BRIDGE_STATUS_DEVICE) >> 3,
186c7a34993SMartin Mares (status & PCI_PCIX_BRIDGE_STATUS_FUNCTION),
187c7a34993SMartin Mares FLAG(status, PCI_PCIX_BRIDGE_STATUS_64BIT),
188c7a34993SMartin Mares FLAG(status, PCI_PCIX_BRIDGE_STATUS_133MHZ),
189c7a34993SMartin Mares FLAG(status, PCI_PCIX_BRIDGE_STATUS_SC_DISCARDED),
190c7a34993SMartin Mares FLAG(status, PCI_PCIX_BRIDGE_STATUS_UNEXPECTED_SC),
191c7a34993SMartin Mares FLAG(status, PCI_PCIX_BRIDGE_STATUS_SC_OVERRUN),
192c7a34993SMartin Mares FLAG(status, PCI_PCIX_BRIDGE_STATUS_SPLIT_REQUEST_DELAYED));
193c7a34993SMartin Mares upstcr = get_conf_long(d, where + PCI_PCIX_BRIDGE_UPSTREAM_SPLIT_TRANS_CTRL);
194c7a34993SMartin Mares printf("\t\tUpstream: Capacity=%u CommitmentLimit=%u\n",
195c7a34993SMartin Mares (upstcr & PCI_PCIX_BRIDGE_STR_CAPACITY),
196c7a34993SMartin Mares (upstcr >> 16) & 0xffff);
197c7a34993SMartin Mares downstcr = get_conf_long(d, where + PCI_PCIX_BRIDGE_DOWNSTREAM_SPLIT_TRANS_CTRL);
198c7a34993SMartin Mares printf("\t\tDownstream: Capacity=%u CommitmentLimit=%u\n",
199c7a34993SMartin Mares (downstcr & PCI_PCIX_BRIDGE_STR_CAPACITY),
200c7a34993SMartin Mares (downstcr >> 16) & 0xffff);
201c7a34993SMartin Mares }
202c7a34993SMartin Mares
203c7a34993SMartin Mares static void
cap_pcix(struct device * d,int where)204c7a34993SMartin Mares cap_pcix(struct device *d, int where)
205c7a34993SMartin Mares {
206c7a34993SMartin Mares switch (get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f)
207c7a34993SMartin Mares {
208c7a34993SMartin Mares case PCI_HEADER_TYPE_NORMAL:
209c7a34993SMartin Mares cap_pcix_nobridge(d, where);
210c7a34993SMartin Mares break;
211c7a34993SMartin Mares case PCI_HEADER_TYPE_BRIDGE:
212c7a34993SMartin Mares cap_pcix_bridge(d, where);
213c7a34993SMartin Mares break;
214c7a34993SMartin Mares }
215c7a34993SMartin Mares }
216c7a34993SMartin Mares
217c7a34993SMartin Mares static inline char *
ht_link_width(unsigned width)218c7a34993SMartin Mares ht_link_width(unsigned width)
219c7a34993SMartin Mares {
220c7a34993SMartin Mares static char * const widths[8] = { "8bit", "16bit", "[2]", "32bit", "2bit", "4bit", "[6]", "N/C" };
221c7a34993SMartin Mares return widths[width];
222c7a34993SMartin Mares }
223c7a34993SMartin Mares
224c7a34993SMartin Mares static inline char *
ht_link_freq(unsigned freq)225c7a34993SMartin Mares ht_link_freq(unsigned freq)
226c7a34993SMartin Mares {
227c7a34993SMartin Mares static char * const freqs[16] = { "200MHz", "300MHz", "400MHz", "500MHz", "600MHz", "800MHz", "1.0GHz", "1.2GHz",
228c7a34993SMartin Mares "1.4GHz", "1.6GHz", "[a]", "[b]", "[c]", "[d]", "[e]", "Vend" };
229c7a34993SMartin Mares return freqs[freq];
230c7a34993SMartin Mares }
231c7a34993SMartin Mares
232c7a34993SMartin Mares static void
cap_ht_pri(struct device * d,int where,int cmd)233c7a34993SMartin Mares cap_ht_pri(struct device *d, int where, int cmd)
234c7a34993SMartin Mares {
235c7a34993SMartin Mares u16 lctr0, lcnf0, lctr1, lcnf1, eh;
236c7a34993SMartin Mares u8 rid, lfrer0, lfcap0, ftr, lfrer1, lfcap1, mbu, mlu, bn;
237c7a34993SMartin Mares
238c7a34993SMartin Mares printf("HyperTransport: Slave or Primary Interface\n");
239c7a34993SMartin Mares if (verbose < 2)
240c7a34993SMartin Mares return;
241c7a34993SMartin Mares
242c7a34993SMartin Mares if (!config_fetch(d, where + PCI_HT_PRI_LCTR0, PCI_HT_PRI_SIZEOF - PCI_HT_PRI_LCTR0))
243c7a34993SMartin Mares return;
244c7a34993SMartin Mares rid = get_conf_byte(d, where + PCI_HT_PRI_RID);
245c7a34993SMartin Mares if (rid < 0x22 && rid > 0x11)
246c7a34993SMartin Mares printf("\t\t!!! Possibly incomplete decoding\n");
247c7a34993SMartin Mares
2480089d489SMartin Mares printf("\t\tCommand: BaseUnitID=%u UnitCnt=%u MastHost%c DefDir%c",
249c7a34993SMartin Mares (cmd & PCI_HT_PRI_CMD_BUID),
250c7a34993SMartin Mares (cmd & PCI_HT_PRI_CMD_UC) >> 5,
251c7a34993SMartin Mares FLAG(cmd, PCI_HT_PRI_CMD_MH),
2520089d489SMartin Mares FLAG(cmd, PCI_HT_PRI_CMD_DD));
253c7a34993SMartin Mares if (rid >= 0x22)
2540089d489SMartin Mares printf(" DUL%c", FLAG(cmd, PCI_HT_PRI_CMD_DUL));
2550089d489SMartin Mares printf("\n");
2560089d489SMartin Mares
2570089d489SMartin Mares lctr0 = get_conf_word(d, where + PCI_HT_PRI_LCTR0);
2580089d489SMartin Mares printf("\t\tLink Control 0: CFlE%c CST%c CFE%c <LkFail%c Init%c EOC%c TXO%c <CRCErr=%x",
259c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_CFLE),
260c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_CST),
261c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_CFE),
262c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_LKFAIL),
263c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_INIT),
264c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_EOC),
265c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_TXO),
2660089d489SMartin Mares (lctr0 & PCI_HT_LCTR_CRCERR) >> 8);
2670089d489SMartin Mares if (rid >= 0x22)
2680089d489SMartin Mares printf(" IsocEn%c LSEn%c ExtCTL%c 64b%c",
269c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_ISOCEN),
270c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_LSEN),
271c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_EXTCTL),
272c7a34993SMartin Mares FLAG(lctr0, PCI_HT_LCTR_64B));
2730089d489SMartin Mares printf("\n");
2740089d489SMartin Mares
275c7a34993SMartin Mares lcnf0 = get_conf_word(d, where + PCI_HT_PRI_LCNF0);
2760089d489SMartin Mares if (rid < 0x22)
2770089d489SMartin Mares printf("\t\tLink Config 0: MLWI=%s MLWO=%s LWI=%s LWO=%s\n",
278c7a34993SMartin Mares ht_link_width(lcnf0 & PCI_HT_LCNF_MLWI),
279c7a34993SMartin Mares ht_link_width((lcnf0 & PCI_HT_LCNF_MLWO) >> 4),
280c7a34993SMartin Mares ht_link_width((lcnf0 & PCI_HT_LCNF_LWI) >> 8),
2810089d489SMartin Mares ht_link_width((lcnf0 & PCI_HT_LCNF_LWO) >> 12));
282c7a34993SMartin Mares else
2830089d489SMartin Mares printf("\t\tLink Config 0: MLWI=%s DwFcIn%c MLWO=%s DwFcOut%c LWI=%s DwFcInEn%c LWO=%s DwFcOutEn%c\n",
2840089d489SMartin Mares ht_link_width(lcnf0 & PCI_HT_LCNF_MLWI),
2850089d489SMartin Mares FLAG(lcnf0, PCI_HT_LCNF_DFI),
2860089d489SMartin Mares ht_link_width((lcnf0 & PCI_HT_LCNF_MLWO) >> 4),
2870089d489SMartin Mares FLAG(lcnf0, PCI_HT_LCNF_DFO),
2880089d489SMartin Mares ht_link_width((lcnf0 & PCI_HT_LCNF_LWI) >> 8),
2890089d489SMartin Mares FLAG(lcnf0, PCI_HT_LCNF_DFIE),
2900089d489SMartin Mares ht_link_width((lcnf0 & PCI_HT_LCNF_LWO) >> 12),
2910089d489SMartin Mares FLAG(lcnf0, PCI_HT_LCNF_DFOE));
2920089d489SMartin Mares
2930089d489SMartin Mares lctr1 = get_conf_word(d, where + PCI_HT_PRI_LCTR1);
2940089d489SMartin Mares printf("\t\tLink Control 1: CFlE%c CST%c CFE%c <LkFail%c Init%c EOC%c TXO%c <CRCErr=%x",
295c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_CFLE),
296c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_CST),
297c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_CFE),
298c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_LKFAIL),
299c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_INIT),
300c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_EOC),
301c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_TXO),
3020089d489SMartin Mares (lctr1 & PCI_HT_LCTR_CRCERR) >> 8);
3030089d489SMartin Mares if (rid >= 0x22)
3040089d489SMartin Mares printf(" IsocEn%c LSEn%c ExtCTL%c 64b%c",
305c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_ISOCEN),
306c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_LSEN),
307c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_EXTCTL),
308c7a34993SMartin Mares FLAG(lctr1, PCI_HT_LCTR_64B));
3090089d489SMartin Mares printf("\n");
3100089d489SMartin Mares
311c7a34993SMartin Mares lcnf1 = get_conf_word(d, where + PCI_HT_PRI_LCNF1);
3120089d489SMartin Mares if (rid < 0x22)
3130089d489SMartin Mares printf("\t\tLink Config 1: MLWI=%s MLWO=%s LWI=%s LWO=%s\n",
314c7a34993SMartin Mares ht_link_width(lcnf1 & PCI_HT_LCNF_MLWI),
315c7a34993SMartin Mares ht_link_width((lcnf1 & PCI_HT_LCNF_MLWO) >> 4),
316c7a34993SMartin Mares ht_link_width((lcnf1 & PCI_HT_LCNF_LWI) >> 8),
3170089d489SMartin Mares ht_link_width((lcnf1 & PCI_HT_LCNF_LWO) >> 12));
3180089d489SMartin Mares else
3190089d489SMartin Mares printf("\t\tLink Config 1: MLWI=%s DwFcIn%c MLWO=%s DwFcOut%c LWI=%s DwFcInEn%c LWO=%s DwFcOutEn%c\n",
3200089d489SMartin Mares ht_link_width(lcnf1 & PCI_HT_LCNF_MLWI),
321c7a34993SMartin Mares FLAG(lcnf1, PCI_HT_LCNF_DFI),
3220089d489SMartin Mares ht_link_width((lcnf1 & PCI_HT_LCNF_MLWO) >> 4),
323c7a34993SMartin Mares FLAG(lcnf1, PCI_HT_LCNF_DFO),
3240089d489SMartin Mares ht_link_width((lcnf1 & PCI_HT_LCNF_LWI) >> 8),
325c7a34993SMartin Mares FLAG(lcnf1, PCI_HT_LCNF_DFIE),
3260089d489SMartin Mares ht_link_width((lcnf1 & PCI_HT_LCNF_LWO) >> 12),
327c7a34993SMartin Mares FLAG(lcnf1, PCI_HT_LCNF_DFOE));
3280089d489SMartin Mares
329c7a34993SMartin Mares printf("\t\tRevision ID: %u.%02u\n",
330c7a34993SMartin Mares (rid & PCI_HT_RID_MAJ) >> 5, (rid & PCI_HT_RID_MIN));
331c7a34993SMartin Mares if (rid < 0x22)
332c7a34993SMartin Mares return;
3330089d489SMartin Mares
334c7a34993SMartin Mares lfrer0 = get_conf_byte(d, where + PCI_HT_PRI_LFRER0);
335c7a34993SMartin Mares printf("\t\tLink Frequency 0: %s\n", ht_link_freq(lfrer0 & PCI_HT_LFRER_FREQ));
336c7a34993SMartin Mares printf("\t\tLink Error 0: <Prot%c <Ovfl%c <EOC%c CTLTm%c\n",
337c7a34993SMartin Mares FLAG(lfrer0, PCI_HT_LFRER_PROT),
338c7a34993SMartin Mares FLAG(lfrer0, PCI_HT_LFRER_OV),
339c7a34993SMartin Mares FLAG(lfrer0, PCI_HT_LFRER_EOC),
340c7a34993SMartin Mares FLAG(lfrer0, PCI_HT_LFRER_CTLT));
3410089d489SMartin Mares
342c7a34993SMartin Mares lfcap0 = get_conf_byte(d, where + PCI_HT_PRI_LFCAP0);
343c7a34993SMartin Mares printf("\t\tLink Frequency Capability 0: 200MHz%c 300MHz%c 400MHz%c 500MHz%c 600MHz%c 800MHz%c 1.0GHz%c 1.2GHz%c 1.4GHz%c 1.6GHz%c Vend%c\n",
344c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_200),
345c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_300),
346c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_400),
347c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_500),
348c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_600),
349c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_800),
350c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_1000),
351c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_1200),
352c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_1400),
353c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_1600),
354c7a34993SMartin Mares FLAG(lfcap0, PCI_HT_LFCAP_VEND));
3550089d489SMartin Mares
356c7a34993SMartin Mares ftr = get_conf_byte(d, where + PCI_HT_PRI_FTR);
357c7a34993SMartin Mares printf("\t\tFeature Capability: IsocFC%c LDTSTOP%c CRCTM%c ECTLT%c 64bA%c UIDRD%c\n",
358c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_ISOCFC),
359c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_LDTSTOP),
360c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_CRCTM),
361c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_ECTLT),
362c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_64BA),
363c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_UIDRD));
3640089d489SMartin Mares
365c7a34993SMartin Mares lfrer1 = get_conf_byte(d, where + PCI_HT_PRI_LFRER1);
366c7a34993SMartin Mares printf("\t\tLink Frequency 1: %s\n", ht_link_freq(lfrer1 & PCI_HT_LFRER_FREQ));
367c7a34993SMartin Mares printf("\t\tLink Error 1: <Prot%c <Ovfl%c <EOC%c CTLTm%c\n",
368c7a34993SMartin Mares FLAG(lfrer1, PCI_HT_LFRER_PROT),
369c7a34993SMartin Mares FLAG(lfrer1, PCI_HT_LFRER_OV),
370c7a34993SMartin Mares FLAG(lfrer1, PCI_HT_LFRER_EOC),
371c7a34993SMartin Mares FLAG(lfrer1, PCI_HT_LFRER_CTLT));
3720089d489SMartin Mares
373c7a34993SMartin Mares lfcap1 = get_conf_byte(d, where + PCI_HT_PRI_LFCAP1);
374c7a34993SMartin Mares printf("\t\tLink Frequency Capability 1: 200MHz%c 300MHz%c 400MHz%c 500MHz%c 600MHz%c 800MHz%c 1.0GHz%c 1.2GHz%c 1.4GHz%c 1.6GHz%c Vend%c\n",
375c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_200),
376c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_300),
377c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_400),
378c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_500),
379c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_600),
380c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_800),
381c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_1000),
382c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_1200),
383c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_1400),
384c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_1600),
385c7a34993SMartin Mares FLAG(lfcap1, PCI_HT_LFCAP_VEND));
3860089d489SMartin Mares
387c7a34993SMartin Mares eh = get_conf_word(d, where + PCI_HT_PRI_EH);
388c7a34993SMartin Mares printf("\t\tError Handling: PFlE%c OFlE%c PFE%c OFE%c EOCFE%c RFE%c CRCFE%c SERRFE%c CF%c RE%c PNFE%c ONFE%c EOCNFE%c RNFE%c CRCNFE%c SERRNFE%c\n",
389c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_PFLE),
390c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_OFLE),
391c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_PFE),
392c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_OFE),
393c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_EOCFE),
394c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_RFE),
395c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_CRCFE),
396c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_SERRFE),
397c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_CF),
398c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_RE),
399c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_PNFE),
400c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_ONFE),
401c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_EOCNFE),
402c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_RNFE),
403c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_CRCNFE),
404c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_SERRNFE));
4050089d489SMartin Mares
406c7a34993SMartin Mares mbu = get_conf_byte(d, where + PCI_HT_PRI_MBU);
407c7a34993SMartin Mares mlu = get_conf_byte(d, where + PCI_HT_PRI_MLU);
408c7a34993SMartin Mares printf("\t\tPrefetchable memory behind bridge Upper: %02x-%02x\n", mbu, mlu);
4090089d489SMartin Mares
410c7a34993SMartin Mares bn = get_conf_byte(d, where + PCI_HT_PRI_BN);
411c7a34993SMartin Mares printf("\t\tBus Number: %02x\n", bn);
412c7a34993SMartin Mares }
413c7a34993SMartin Mares
414c7a34993SMartin Mares static void
cap_ht_sec(struct device * d,int where,int cmd)415c7a34993SMartin Mares cap_ht_sec(struct device *d, int where, int cmd)
416c7a34993SMartin Mares {
417c7a34993SMartin Mares u16 lctr, lcnf, ftr, eh;
418c7a34993SMartin Mares u8 rid, lfrer, lfcap, mbu, mlu;
419c7a34993SMartin Mares char *fmt;
420c7a34993SMartin Mares
421c7a34993SMartin Mares printf("HyperTransport: Host or Secondary Interface\n");
422c7a34993SMartin Mares if (verbose < 2)
423c7a34993SMartin Mares return;
424c7a34993SMartin Mares
425c7a34993SMartin Mares if (!config_fetch(d, where + PCI_HT_SEC_LCTR, PCI_HT_SEC_SIZEOF - PCI_HT_SEC_LCTR))
426c7a34993SMartin Mares return;
427c7a34993SMartin Mares rid = get_conf_byte(d, where + PCI_HT_SEC_RID);
428c7a34993SMartin Mares if (rid < 0x22 && rid > 0x11)
429c7a34993SMartin Mares printf("\t\t!!! Possibly incomplete decoding\n");
430c7a34993SMartin Mares
431c7a34993SMartin Mares if (rid >= 0x22)
432c7a34993SMartin Mares fmt = "\t\tCommand: WarmRst%c DblEnd%c DevNum=%u ChainSide%c HostHide%c Slave%c <EOCErr%c DUL%c\n";
433c7a34993SMartin Mares else
434c7a34993SMartin Mares fmt = "\t\tCommand: WarmRst%c DblEnd%c\n";
435c7a34993SMartin Mares printf(fmt,
436c7a34993SMartin Mares FLAG(cmd, PCI_HT_SEC_CMD_WR),
437c7a34993SMartin Mares FLAG(cmd, PCI_HT_SEC_CMD_DE),
438c7a34993SMartin Mares (cmd & PCI_HT_SEC_CMD_DN) >> 2,
439c7a34993SMartin Mares FLAG(cmd, PCI_HT_SEC_CMD_CS),
440c7a34993SMartin Mares FLAG(cmd, PCI_HT_SEC_CMD_HH),
441c7a34993SMartin Mares FLAG(cmd, PCI_HT_SEC_CMD_AS),
442c7a34993SMartin Mares FLAG(cmd, PCI_HT_SEC_CMD_HIECE),
443c7a34993SMartin Mares FLAG(cmd, PCI_HT_SEC_CMD_DUL));
444c7a34993SMartin Mares lctr = get_conf_word(d, where + PCI_HT_SEC_LCTR);
445c7a34993SMartin Mares if (rid >= 0x22)
446c7a34993SMartin Mares fmt = "\t\tLink Control: CFlE%c CST%c CFE%c <LkFail%c Init%c EOC%c TXO%c <CRCErr=%x IsocEn%c LSEn%c ExtCTL%c 64b%c\n";
447c7a34993SMartin Mares else
448c7a34993SMartin Mares fmt = "\t\tLink Control: CFlE%c CST%c CFE%c <LkFail%c Init%c EOC%c TXO%c <CRCErr=%x\n";
449c7a34993SMartin Mares printf(fmt,
450c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_CFLE),
451c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_CST),
452c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_CFE),
453c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_LKFAIL),
454c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_INIT),
455c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_EOC),
456c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_TXO),
457c7a34993SMartin Mares (lctr & PCI_HT_LCTR_CRCERR) >> 8,
458c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_ISOCEN),
459c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_LSEN),
460c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_EXTCTL),
461c7a34993SMartin Mares FLAG(lctr, PCI_HT_LCTR_64B));
462c7a34993SMartin Mares lcnf = get_conf_word(d, where + PCI_HT_SEC_LCNF);
463c7a34993SMartin Mares if (rid >= 0x22)
464c7a34993SMartin Mares fmt = "\t\tLink Config: MLWI=%1$s DwFcIn%5$c MLWO=%2$s DwFcOut%6$c LWI=%3$s DwFcInEn%7$c LWO=%4$s DwFcOutEn%8$c\n";
465c7a34993SMartin Mares else
466c7a34993SMartin Mares fmt = "\t\tLink Config: MLWI=%s MLWO=%s LWI=%s LWO=%s\n";
467c7a34993SMartin Mares printf(fmt,
468c7a34993SMartin Mares ht_link_width(lcnf & PCI_HT_LCNF_MLWI),
469c7a34993SMartin Mares ht_link_width((lcnf & PCI_HT_LCNF_MLWO) >> 4),
470c7a34993SMartin Mares ht_link_width((lcnf & PCI_HT_LCNF_LWI) >> 8),
471c7a34993SMartin Mares ht_link_width((lcnf & PCI_HT_LCNF_LWO) >> 12),
472c7a34993SMartin Mares FLAG(lcnf, PCI_HT_LCNF_DFI),
473c7a34993SMartin Mares FLAG(lcnf, PCI_HT_LCNF_DFO),
474c7a34993SMartin Mares FLAG(lcnf, PCI_HT_LCNF_DFIE),
475c7a34993SMartin Mares FLAG(lcnf, PCI_HT_LCNF_DFOE));
476c7a34993SMartin Mares printf("\t\tRevision ID: %u.%02u\n",
477c7a34993SMartin Mares (rid & PCI_HT_RID_MAJ) >> 5, (rid & PCI_HT_RID_MIN));
478c7a34993SMartin Mares if (rid < 0x22)
479c7a34993SMartin Mares return;
480c7a34993SMartin Mares lfrer = get_conf_byte(d, where + PCI_HT_SEC_LFRER);
481c7a34993SMartin Mares printf("\t\tLink Frequency: %s\n", ht_link_freq(lfrer & PCI_HT_LFRER_FREQ));
482c7a34993SMartin Mares printf("\t\tLink Error: <Prot%c <Ovfl%c <EOC%c CTLTm%c\n",
483c7a34993SMartin Mares FLAG(lfrer, PCI_HT_LFRER_PROT),
484c7a34993SMartin Mares FLAG(lfrer, PCI_HT_LFRER_OV),
485c7a34993SMartin Mares FLAG(lfrer, PCI_HT_LFRER_EOC),
486c7a34993SMartin Mares FLAG(lfrer, PCI_HT_LFRER_CTLT));
487c7a34993SMartin Mares lfcap = get_conf_byte(d, where + PCI_HT_SEC_LFCAP);
488c7a34993SMartin Mares printf("\t\tLink Frequency Capability: 200MHz%c 300MHz%c 400MHz%c 500MHz%c 600MHz%c 800MHz%c 1.0GHz%c 1.2GHz%c 1.4GHz%c 1.6GHz%c Vend%c\n",
489c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_200),
490c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_300),
491c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_400),
492c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_500),
493c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_600),
494c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_800),
495c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_1000),
496c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_1200),
497c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_1400),
498c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_1600),
499c7a34993SMartin Mares FLAG(lfcap, PCI_HT_LFCAP_VEND));
500c7a34993SMartin Mares ftr = get_conf_word(d, where + PCI_HT_SEC_FTR);
501c7a34993SMartin Mares printf("\t\tFeature Capability: IsocFC%c LDTSTOP%c CRCTM%c ECTLT%c 64bA%c UIDRD%c ExtRS%c UCnfE%c\n",
502c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_ISOCFC),
503c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_LDTSTOP),
504c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_CRCTM),
505c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_ECTLT),
506c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_64BA),
507c7a34993SMartin Mares FLAG(ftr, PCI_HT_FTR_UIDRD),
508c7a34993SMartin Mares FLAG(ftr, PCI_HT_SEC_FTR_EXTRS),
509c7a34993SMartin Mares FLAG(ftr, PCI_HT_SEC_FTR_UCNFE));
510c7a34993SMartin Mares if (ftr & PCI_HT_SEC_FTR_EXTRS)
511c7a34993SMartin Mares {
512c7a34993SMartin Mares eh = get_conf_word(d, where + PCI_HT_SEC_EH);
513c7a34993SMartin Mares printf("\t\tError Handling: PFlE%c OFlE%c PFE%c OFE%c EOCFE%c RFE%c CRCFE%c SERRFE%c CF%c RE%c PNFE%c ONFE%c EOCNFE%c RNFE%c CRCNFE%c SERRNFE%c\n",
514c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_PFLE),
515c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_OFLE),
516c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_PFE),
517c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_OFE),
518c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_EOCFE),
519c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_RFE),
520c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_CRCFE),
521c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_SERRFE),
522c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_CF),
523c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_RE),
524c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_PNFE),
525c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_ONFE),
526c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_EOCNFE),
527c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_RNFE),
528c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_CRCNFE),
529c7a34993SMartin Mares FLAG(eh, PCI_HT_EH_SERRNFE));
530c7a34993SMartin Mares mbu = get_conf_byte(d, where + PCI_HT_SEC_MBU);
531c7a34993SMartin Mares mlu = get_conf_byte(d, where + PCI_HT_SEC_MLU);
532c7a34993SMartin Mares printf("\t\tPrefetchable memory behind bridge Upper: %02x-%02x\n", mbu, mlu);
533c7a34993SMartin Mares }
534c7a34993SMartin Mares }
535c7a34993SMartin Mares
536c7a34993SMartin Mares static void
cap_ht(struct device * d,int where,int cmd)537c7a34993SMartin Mares cap_ht(struct device *d, int where, int cmd)
538c7a34993SMartin Mares {
539c7a34993SMartin Mares int type;
540c7a34993SMartin Mares
541c7a34993SMartin Mares switch (cmd & PCI_HT_CMD_TYP_HI)
542c7a34993SMartin Mares {
543c7a34993SMartin Mares case PCI_HT_CMD_TYP_HI_PRI:
544c7a34993SMartin Mares cap_ht_pri(d, where, cmd);
545c7a34993SMartin Mares return;
546c7a34993SMartin Mares case PCI_HT_CMD_TYP_HI_SEC:
547c7a34993SMartin Mares cap_ht_sec(d, where, cmd);
548c7a34993SMartin Mares return;
549c7a34993SMartin Mares }
550c7a34993SMartin Mares
551c7a34993SMartin Mares type = cmd & PCI_HT_CMD_TYP;
552c7a34993SMartin Mares switch (type)
553c7a34993SMartin Mares {
554c7a34993SMartin Mares case PCI_HT_CMD_TYP_SW:
555c7a34993SMartin Mares printf("HyperTransport: Switch\n");
556c7a34993SMartin Mares break;
557c7a34993SMartin Mares case PCI_HT_CMD_TYP_IDC:
558c7a34993SMartin Mares printf("HyperTransport: Interrupt Discovery and Configuration\n");
559c7a34993SMartin Mares break;
560c7a34993SMartin Mares case PCI_HT_CMD_TYP_RID:
561c7a34993SMartin Mares printf("HyperTransport: Revision ID: %u.%02u\n",
562c7a34993SMartin Mares (cmd & PCI_HT_RID_MAJ) >> 5, (cmd & PCI_HT_RID_MIN));
563c7a34993SMartin Mares break;
564c7a34993SMartin Mares case PCI_HT_CMD_TYP_UIDC:
565c7a34993SMartin Mares printf("HyperTransport: UnitID Clumping\n");
566c7a34993SMartin Mares break;
567c7a34993SMartin Mares case PCI_HT_CMD_TYP_ECSA:
568c7a34993SMartin Mares printf("HyperTransport: Extended Configuration Space Access\n");
569c7a34993SMartin Mares break;
570c7a34993SMartin Mares case PCI_HT_CMD_TYP_AM:
571c7a34993SMartin Mares printf("HyperTransport: Address Mapping\n");
572c7a34993SMartin Mares break;
573c7a34993SMartin Mares case PCI_HT_CMD_TYP_MSIM:
574c7a34993SMartin Mares printf("HyperTransport: MSI Mapping Enable%c Fixed%c\n",
575c7a34993SMartin Mares FLAG(cmd, PCI_HT_MSIM_CMD_EN),
576c7a34993SMartin Mares FLAG(cmd, PCI_HT_MSIM_CMD_FIXD));
577c7a34993SMartin Mares if (verbose >= 2 && !(cmd & PCI_HT_MSIM_CMD_FIXD))
578c7a34993SMartin Mares {
579c7a34993SMartin Mares u32 offl, offh;
580c7a34993SMartin Mares if (!config_fetch(d, where + PCI_HT_MSIM_ADDR_LO, 8))
581c7a34993SMartin Mares break;
582c7a34993SMartin Mares offl = get_conf_long(d, where + PCI_HT_MSIM_ADDR_LO);
583c7a34993SMartin Mares offh = get_conf_long(d, where + PCI_HT_MSIM_ADDR_HI);
5846811edb8SPali Rohár printf("\t\tMapping Address Base: %016" PCI_U64_FMT_X "\n", ((u64)offh << 32) | (offl & ~0xfffff));
585c7a34993SMartin Mares }
586c7a34993SMartin Mares break;
587c7a34993SMartin Mares case PCI_HT_CMD_TYP_DR:
588c7a34993SMartin Mares printf("HyperTransport: DirectRoute\n");
589c7a34993SMartin Mares break;
590c7a34993SMartin Mares case PCI_HT_CMD_TYP_VCS:
591c7a34993SMartin Mares printf("HyperTransport: VCSet\n");
592c7a34993SMartin Mares break;
593c7a34993SMartin Mares case PCI_HT_CMD_TYP_RM:
594c7a34993SMartin Mares printf("HyperTransport: Retry Mode\n");
595c7a34993SMartin Mares break;
596c7a34993SMartin Mares case PCI_HT_CMD_TYP_X86:
597c7a34993SMartin Mares printf("HyperTransport: X86 (reserved)\n");
598c7a34993SMartin Mares break;
599c7a34993SMartin Mares default:
600c7a34993SMartin Mares printf("HyperTransport: #%02x\n", type >> 11);
601c7a34993SMartin Mares }
602c7a34993SMartin Mares }
603c7a34993SMartin Mares
604c7a34993SMartin Mares static void
cap_msi(struct device * d,int where,int cap)605c7a34993SMartin Mares cap_msi(struct device *d, int where, int cap)
606c7a34993SMartin Mares {
607c7a34993SMartin Mares int is64;
608c7a34993SMartin Mares u32 t;
609c7a34993SMartin Mares u16 w;
610c7a34993SMartin Mares
61104885ef7SMatthew Wilcox printf("MSI: Enable%c Count=%d/%d Maskable%c 64bit%c\n",
61204885ef7SMatthew Wilcox FLAG(cap, PCI_MSI_FLAGS_ENABLE),
613c7a34993SMartin Mares 1 << ((cap & PCI_MSI_FLAGS_QSIZE) >> 4),
614c7a34993SMartin Mares 1 << ((cap & PCI_MSI_FLAGS_QMASK) >> 1),
61504885ef7SMatthew Wilcox FLAG(cap, PCI_MSI_FLAGS_MASK_BIT),
61604885ef7SMatthew Wilcox FLAG(cap, PCI_MSI_FLAGS_64BIT));
617c7a34993SMartin Mares if (verbose < 2)
618c7a34993SMartin Mares return;
619c7a34993SMartin Mares is64 = cap & PCI_MSI_FLAGS_64BIT;
620c7a34993SMartin Mares if (!config_fetch(d, where + PCI_MSI_ADDRESS_LO, (is64 ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32) + 2 - PCI_MSI_ADDRESS_LO))
621c7a34993SMartin Mares return;
622c7a34993SMartin Mares printf("\t\tAddress: ");
623c7a34993SMartin Mares if (is64)
624c7a34993SMartin Mares {
625c7a34993SMartin Mares t = get_conf_long(d, where + PCI_MSI_ADDRESS_HI);
626c7a34993SMartin Mares w = get_conf_word(d, where + PCI_MSI_DATA_64);
627c7a34993SMartin Mares printf("%08x", t);
628c7a34993SMartin Mares }
629c7a34993SMartin Mares else
630c7a34993SMartin Mares w = get_conf_word(d, where + PCI_MSI_DATA_32);
631c7a34993SMartin Mares t = get_conf_long(d, where + PCI_MSI_ADDRESS_LO);
632c7a34993SMartin Mares printf("%08x Data: %04x\n", t, w);
633c7a34993SMartin Mares if (cap & PCI_MSI_FLAGS_MASK_BIT)
634c7a34993SMartin Mares {
635c7a34993SMartin Mares u32 mask, pending;
636c7a34993SMartin Mares
637c7a34993SMartin Mares if (is64)
638c7a34993SMartin Mares {
639c7a34993SMartin Mares if (!config_fetch(d, where + PCI_MSI_MASK_BIT_64, 8))
640c7a34993SMartin Mares return;
641c7a34993SMartin Mares mask = get_conf_long(d, where + PCI_MSI_MASK_BIT_64);
642c7a34993SMartin Mares pending = get_conf_long(d, where + PCI_MSI_PENDING_64);
643c7a34993SMartin Mares }
644c7a34993SMartin Mares else
645c7a34993SMartin Mares {
646c7a34993SMartin Mares if (!config_fetch(d, where + PCI_MSI_MASK_BIT_32, 8))
647c7a34993SMartin Mares return;
648c7a34993SMartin Mares mask = get_conf_long(d, where + PCI_MSI_MASK_BIT_32);
649c7a34993SMartin Mares pending = get_conf_long(d, where + PCI_MSI_PENDING_32);
650c7a34993SMartin Mares }
651c7a34993SMartin Mares printf("\t\tMasking: %08x Pending: %08x\n", mask, pending);
652c7a34993SMartin Mares }
653c7a34993SMartin Mares }
654c7a34993SMartin Mares
exp_downstream_port(int type)655623ed0e1SBjorn Helgaas static int exp_downstream_port(int type)
656623ed0e1SBjorn Helgaas {
657623ed0e1SBjorn Helgaas return type == PCI_EXP_TYPE_ROOT_PORT ||
658623ed0e1SBjorn Helgaas type == PCI_EXP_TYPE_DOWNSTREAM ||
659623ed0e1SBjorn Helgaas type == PCI_EXP_TYPE_PCIE_BRIDGE; /* PCI/PCI-X to PCIe Bridge */
660623ed0e1SBjorn Helgaas }
661623ed0e1SBjorn Helgaas
show_power_limit(int value,int scale)66241e49114SPali Rohár static void show_power_limit(int value, int scale)
663c7a34993SMartin Mares {
664c7a34993SMartin Mares static const float scales[4] = { 1.0, 0.1, 0.01, 0.001 };
66541e49114SPali Rohár
666cac545f6SPali Rohár if (scale == 0 && value == 0xFF)
66741e49114SPali Rohár {
668cac545f6SPali Rohár printf(">600W");
66941e49114SPali Rohár return;
67041e49114SPali Rohár }
671cac545f6SPali Rohár
672cac545f6SPali Rohár if (scale == 0 && value >= 0xF0 && value <= 0xFE)
673cac545f6SPali Rohár value = 250 + 25 * (value - 0xF0);
674cac545f6SPali Rohár
67541e49114SPali Rohár printf("%gW", value * scales[scale]);
676c7a34993SMartin Mares }
677c7a34993SMartin Mares
latency_l0s(int value)678c7a34993SMartin Mares static const char *latency_l0s(int value)
679c7a34993SMartin Mares {
6802bbe1d46SMartin Mares static const char * const latencies[] = { "<64ns", "<128ns", "<256ns", "<512ns", "<1us", "<2us", "<4us", "unlimited" };
681c7a34993SMartin Mares return latencies[value];
682c7a34993SMartin Mares }
683c7a34993SMartin Mares
latency_l1(int value)684c7a34993SMartin Mares static const char *latency_l1(int value)
685c7a34993SMartin Mares {
6862bbe1d46SMartin Mares static const char * const latencies[] = { "<1us", "<2us", "<4us", "<8us", "<16us", "<32us", "<64us", "unlimited" };
687c7a34993SMartin Mares return latencies[value];
688c7a34993SMartin Mares }
689c7a34993SMartin Mares
cap_express_dev(struct device * d,int where,int type)690c7a34993SMartin Mares static void cap_express_dev(struct device *d, int where, int type)
691c7a34993SMartin Mares {
692c7a34993SMartin Mares u32 t;
693c7a34993SMartin Mares u16 w;
694c7a34993SMartin Mares
695c7a34993SMartin Mares t = get_conf_long(d, where + PCI_EXP_DEVCAP);
6960dc85d67SBjorn Helgaas printf("\t\tDevCap:\tMaxPayload %d bytes, PhantFunc %d",
697c7a34993SMartin Mares 128 << (t & PCI_EXP_DEVCAP_PAYLOAD),
6980dc85d67SBjorn Helgaas (1 << ((t & PCI_EXP_DEVCAP_PHANTOM) >> 3)) - 1);
6990dc85d67SBjorn Helgaas if ((type == PCI_EXP_TYPE_ENDPOINT) || (type == PCI_EXP_TYPE_LEG_END))
7000dc85d67SBjorn Helgaas printf(", Latency L0s %s, L1 %s",
701c7a34993SMartin Mares latency_l0s((t & PCI_EXP_DEVCAP_L0S) >> 6),
702c7a34993SMartin Mares latency_l1((t & PCI_EXP_DEVCAP_L1) >> 9));
7030dc85d67SBjorn Helgaas printf("\n");
704c7a34993SMartin Mares printf("\t\t\tExtTag%c", FLAG(t, PCI_EXP_DEVCAP_EXT_TAG));
705c7a34993SMartin Mares if ((type == PCI_EXP_TYPE_ENDPOINT) || (type == PCI_EXP_TYPE_LEG_END) ||
706c7a34993SMartin Mares (type == PCI_EXP_TYPE_UPSTREAM) || (type == PCI_EXP_TYPE_PCI_BRIDGE))
707c7a34993SMartin Mares printf(" AttnBtn%c AttnInd%c PwrInd%c",
708c7a34993SMartin Mares FLAG(t, PCI_EXP_DEVCAP_ATN_BUT),
709c7a34993SMartin Mares FLAG(t, PCI_EXP_DEVCAP_ATN_IND), FLAG(t, PCI_EXP_DEVCAP_PWR_IND));
7105d602ff4SBjorn Helgaas printf(" RBE%c",
7115d602ff4SBjorn Helgaas FLAG(t, PCI_EXP_DEVCAP_RBE));
71210168b84SMartin Mares if ((type == PCI_EXP_TYPE_ENDPOINT) || (type == PCI_EXP_TYPE_LEG_END) || (type == PCI_EXP_TYPE_ROOT_INT_EP))
7135d602ff4SBjorn Helgaas printf(" FLReset%c",
714c7a34993SMartin Mares FLAG(t, PCI_EXP_DEVCAP_FLRESET));
715acf56dd2SBjorn Helgaas if ((type == PCI_EXP_TYPE_ENDPOINT) || (type == PCI_EXP_TYPE_UPSTREAM) ||
716acf56dd2SBjorn Helgaas (type == PCI_EXP_TYPE_PCI_BRIDGE))
71741e49114SPali Rohár {
71841e49114SPali Rohár printf(" SlotPowerLimit ");
71941e49114SPali Rohár show_power_limit((t & PCI_EXP_DEVCAP_PWR_VAL) >> 18, (t & PCI_EXP_DEVCAP_PWR_SCL) >> 26);
72041e49114SPali Rohár }
721651a352aSAlexey Kardashevskiy printf(" TEE-IO%c", FLAG(t, PCI_EXP_DEVCAP_TEE_IO));
722c7a34993SMartin Mares printf("\n");
723c7a34993SMartin Mares
724c7a34993SMartin Mares w = get_conf_word(d, where + PCI_EXP_DEVCTL);
725aca48104SBjorn Helgaas printf("\t\tDevCtl:\tCorrErr%c NonFatalErr%c FatalErr%c UnsupReq%c\n",
726c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVCTL_CERE),
727c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVCTL_NFERE),
728c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVCTL_FERE),
729c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVCTL_URRE));
730c7a34993SMartin Mares printf("\t\t\tRlxdOrd%c ExtTag%c PhantFunc%c AuxPwr%c NoSnoop%c",
731c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVCTL_RELAXED),
732c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVCTL_EXT_TAG),
733c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVCTL_PHANTOM),
734c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVCTL_AUX_PME),
735c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVCTL_NOSNOOP));
73677120d53SBjorn Helgaas if (type == PCI_EXP_TYPE_PCI_BRIDGE)
737c7a34993SMartin Mares printf(" BrConfRtry%c", FLAG(w, PCI_EXP_DEVCTL_BCRE));
73810168b84SMartin Mares if (((type == PCI_EXP_TYPE_ENDPOINT) || (type == PCI_EXP_TYPE_LEG_END) || (type == PCI_EXP_TYPE_ROOT_INT_EP)) &&
7395d602ff4SBjorn Helgaas (t & PCI_EXP_DEVCAP_FLRESET))
740c7a34993SMartin Mares printf(" FLReset%c", FLAG(w, PCI_EXP_DEVCTL_FLRESET));
741c7a34993SMartin Mares printf("\n\t\t\tMaxPayload %d bytes, MaxReadReq %d bytes\n",
742c7a34993SMartin Mares 128 << ((w & PCI_EXP_DEVCTL_PAYLOAD) >> 5),
743c7a34993SMartin Mares 128 << ((w & PCI_EXP_DEVCTL_READRQ) >> 12));
744c7a34993SMartin Mares
745c7a34993SMartin Mares w = get_conf_word(d, where + PCI_EXP_DEVSTA);
746aca48104SBjorn Helgaas printf("\t\tDevSta:\tCorrErr%c NonFatalErr%c FatalErr%c UnsupReq%c AuxPwr%c TransPend%c\n",
747c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVSTA_CED),
748c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVSTA_NFED),
749c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVSTA_FED),
750c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVSTA_URD),
751c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVSTA_AUXPD),
752c7a34993SMartin Mares FLAG(w, PCI_EXP_DEVSTA_TRPND));
753c7a34993SMartin Mares }
754c7a34993SMartin Mares
link_speed(int speed)755c7a34993SMartin Mares static char *link_speed(int speed)
756c7a34993SMartin Mares {
757c7a34993SMartin Mares switch (speed)
758c7a34993SMartin Mares {
759c7a34993SMartin Mares case 1:
760c7a34993SMartin Mares return "2.5GT/s";
761c7a34993SMartin Mares case 2:
762c7a34993SMartin Mares return "5GT/s";
7634dc4ff43SMartin Mares case 3:
7644dc4ff43SMartin Mares return "8GT/s";
7659628600bSGavin Shan case 4:
7669628600bSGavin Shan return "16GT/s";
767caca31a0SGustavo Pimentel case 5:
768caca31a0SGustavo Pimentel return "32GT/s";
7695bdf63b6SGustavo Pimentel case 6:
7705bdf63b6SGustavo Pimentel return "64GT/s";
771*3ec74c71SPrabu Thangamuthu case 8:
772*3ec74c71SPrabu Thangamuthu return "128GT/s";
773c7a34993SMartin Mares default:
774c7a34993SMartin Mares return "unknown";
775c7a34993SMartin Mares }
776c7a34993SMartin Mares }
777c7a34993SMartin Mares
link_compare(int type,int sta,int cap)7789f768120SMartin Mares static char *link_compare(int type, int sta, int cap)
779b47b5bd4SMartin Mares {
780b47b5bd4SMartin Mares if (sta > cap)
7819f768120SMartin Mares return " (overdriven)";
7829f768120SMartin Mares if (sta == cap)
7839f768120SMartin Mares return "";
7849f768120SMartin Mares if ((type == PCI_EXP_TYPE_ROOT_PORT) || (type == PCI_EXP_TYPE_DOWNSTREAM) ||
7859f768120SMartin Mares (type == PCI_EXP_TYPE_PCIE_BRIDGE))
7869f768120SMartin Mares return "";
7879f768120SMartin Mares return " (downgraded)";
788b47b5bd4SMartin Mares }
789b47b5bd4SMartin Mares
aspm_support(int code)790c7a34993SMartin Mares static char *aspm_support(int code)
791c7a34993SMartin Mares {
792c7a34993SMartin Mares switch (code)
793c7a34993SMartin Mares {
79487bc7e64SBjorn Helgaas case 0:
79587bc7e64SBjorn Helgaas return "not supported";
796c7a34993SMartin Mares case 1:
797c7a34993SMartin Mares return "L0s";
7984dc4ff43SMartin Mares case 2:
7994dc4ff43SMartin Mares return "L1";
800c7a34993SMartin Mares case 3:
801c7a34993SMartin Mares return "L0s L1";
802c7a34993SMartin Mares default:
803c7a34993SMartin Mares return "unknown";
804c7a34993SMartin Mares }
805c7a34993SMartin Mares }
806c7a34993SMartin Mares
aspm_enabled(int code)807c7a34993SMartin Mares static const char *aspm_enabled(int code)
808c7a34993SMartin Mares {
8092bbe1d46SMartin Mares static const char * const desc[] = { "Disabled", "L0s Enabled", "L1 Enabled", "L0s L1 Enabled" };
810c7a34993SMartin Mares return desc[code];
811c7a34993SMartin Mares }
812c7a34993SMartin Mares
cap_express_link(struct device * d,int where,int type)813c7a34993SMartin Mares static void cap_express_link(struct device *d, int where, int type)
814c7a34993SMartin Mares {
815b47b5bd4SMartin Mares u32 t, aspm, cap_speed, cap_width, sta_speed, sta_width;
816c7a34993SMartin Mares u16 w;
817c7a34993SMartin Mares
818c7a34993SMartin Mares t = get_conf_long(d, where + PCI_EXP_LNKCAP);
81978996f1cSBjorn Helgaas aspm = (t & PCI_EXP_LNKCAP_ASPM) >> 10;
820b47b5bd4SMartin Mares cap_speed = t & PCI_EXP_LNKCAP_SPEED;
821b47b5bd4SMartin Mares cap_width = (t & PCI_EXP_LNKCAP_WIDTH) >> 4;
82278996f1cSBjorn Helgaas printf("\t\tLnkCap:\tPort #%d, Speed %s, Width x%d, ASPM %s",
823c7a34993SMartin Mares t >> 24,
824b47b5bd4SMartin Mares link_speed(cap_speed), cap_width,
82578996f1cSBjorn Helgaas aspm_support(aspm));
82678996f1cSBjorn Helgaas if (aspm)
82778996f1cSBjorn Helgaas {
82878996f1cSBjorn Helgaas printf(", Exit Latency ");
82978996f1cSBjorn Helgaas if (aspm & 1)
83078996f1cSBjorn Helgaas printf("L0s %s", latency_l0s((t & PCI_EXP_LNKCAP_L0S) >> 12));
83178996f1cSBjorn Helgaas if (aspm & 2)
83278996f1cSBjorn Helgaas printf("%sL1 %s", (aspm & 1) ? ", " : "",
833c7a34993SMartin Mares latency_l1((t & PCI_EXP_LNKCAP_L1) >> 15));
83478996f1cSBjorn Helgaas }
83578996f1cSBjorn Helgaas printf("\n");
836b7a807b4SMartin Mares printf("\t\t\tClockPM%c Surprise%c LLActRep%c BwNot%c ASPMOptComp%c\n",
837c7a34993SMartin Mares FLAG(t, PCI_EXP_LNKCAP_CLOCKPM),
838c7a34993SMartin Mares FLAG(t, PCI_EXP_LNKCAP_SURPRISE),
839c7a34993SMartin Mares FLAG(t, PCI_EXP_LNKCAP_DLLA),
840b7a807b4SMartin Mares FLAG(t, PCI_EXP_LNKCAP_LBNC),
841b7a807b4SMartin Mares FLAG(t, PCI_EXP_LNKCAP_AOC));
842c7a34993SMartin Mares
843c7a34993SMartin Mares w = get_conf_word(d, where + PCI_EXP_LNKCTL);
844c7a34993SMartin Mares printf("\t\tLnkCtl:\tASPM %s;", aspm_enabled(w & PCI_EXP_LNKCTL_ASPM));
845c7a34993SMartin Mares if ((type == PCI_EXP_TYPE_ROOT_PORT) || (type == PCI_EXP_TYPE_ENDPOINT) ||
846a1f57a29SBjorn Helgaas (type == PCI_EXP_TYPE_LEG_END) || (type == PCI_EXP_TYPE_PCI_BRIDGE))
847018f413cSBjorn Helgaas printf(" RCB %d bytes,", w & PCI_EXP_LNKCTL_RCB ? 128 : 64);
8489611db3eSPaul Cassidy printf(" LnkDisable%c CommClk%c\n\t\t\tExtSynch%c ClockPM%c AutWidDis%c BWInt%c AutBWInt%c FltModeDis%c\n",
849c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKCTL_DISABLE),
850c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKCTL_CLOCK),
851c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKCTL_XSYNCH),
852c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKCTL_CLOCKPM),
853c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKCTL_HWAUTWD),
854c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKCTL_BWMIE),
8559611db3eSPaul Cassidy FLAG(w, PCI_EXP_LNKCTL_AUTBWIE),
8569611db3eSPaul Cassidy FLAG(w, PCI_EXP_LNKCTL_FLIT_MODE_DIS));
857c7a34993SMartin Mares
858c7a34993SMartin Mares w = get_conf_word(d, where + PCI_EXP_LNKSTA);
859b47b5bd4SMartin Mares sta_speed = w & PCI_EXP_LNKSTA_SPEED;
860b47b5bd4SMartin Mares sta_width = (w & PCI_EXP_LNKSTA_WIDTH) >> 4;
8619f768120SMartin Mares printf("\t\tLnkSta:\tSpeed %s%s, Width x%d%s\n",
862b47b5bd4SMartin Mares link_speed(sta_speed),
8639f768120SMartin Mares link_compare(type, sta_speed, cap_speed),
864b47b5bd4SMartin Mares sta_width,
8659f768120SMartin Mares link_compare(type, sta_width, cap_width));
866b47b5bd4SMartin Mares printf("\t\t\tTrErr%c Train%c SlotClk%c DLActive%c BWMgmt%c ABWMgmt%c\n",
867c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKSTA_TR_ERR),
868c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKSTA_TRAIN),
869c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKSTA_SL_CLK),
870c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKSTA_DL_ACT),
871c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKSTA_BWMGMT),
872c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKSTA_AUTBW));
873c7a34993SMartin Mares }
874c7a34993SMartin Mares
indicator(int code)875c7a34993SMartin Mares static const char *indicator(int code)
876c7a34993SMartin Mares {
8772bbe1d46SMartin Mares static const char * const names[] = { "Unknown", "On", "Blink", "Off" };
878c7a34993SMartin Mares return names[code];
879c7a34993SMartin Mares }
880c7a34993SMartin Mares
cap_express_slot(struct device * d,int where)881c7a34993SMartin Mares static void cap_express_slot(struct device *d, int where)
882c7a34993SMartin Mares {
883c7a34993SMartin Mares u32 t;
884c7a34993SMartin Mares u16 w;
885c7a34993SMartin Mares
886c7a34993SMartin Mares t = get_conf_long(d, where + PCI_EXP_SLTCAP);
8875f6aca18SEd Swierk printf("\t\tSltCap:\tAttnBtn%c PwrCtrl%c MRL%c AttnInd%c PwrInd%c HotPlug%c Surprise%c\n",
888c7a34993SMartin Mares FLAG(t, PCI_EXP_SLTCAP_ATNB),
889c7a34993SMartin Mares FLAG(t, PCI_EXP_SLTCAP_PWRC),
890c7a34993SMartin Mares FLAG(t, PCI_EXP_SLTCAP_MRL),
891c7a34993SMartin Mares FLAG(t, PCI_EXP_SLTCAP_ATNI),
892c7a34993SMartin Mares FLAG(t, PCI_EXP_SLTCAP_PWRI),
893c7a34993SMartin Mares FLAG(t, PCI_EXP_SLTCAP_HPC),
894c7a34993SMartin Mares FLAG(t, PCI_EXP_SLTCAP_HPS));
89541e49114SPali Rohár printf("\t\t\tSlot #%d, PowerLimit ",
89641e49114SPali Rohár (t & PCI_EXP_SLTCAP_PSN) >> 19);
89741e49114SPali Rohár show_power_limit((t & PCI_EXP_SLTCAP_PWR_VAL) >> 7, (t & PCI_EXP_SLTCAP_PWR_SCL) >> 15);
89841e49114SPali Rohár printf("; Interlock%c NoCompl%c\n",
899c7a34993SMartin Mares FLAG(t, PCI_EXP_SLTCAP_INTERLOCK),
900c7a34993SMartin Mares FLAG(t, PCI_EXP_SLTCAP_NOCMDCOMP));
901c7a34993SMartin Mares
902c7a34993SMartin Mares w = get_conf_word(d, where + PCI_EXP_SLTCTL);
903c7a34993SMartin Mares printf("\t\tSltCtl:\tEnable: AttnBtn%c PwrFlt%c MRL%c PresDet%c CmdCplt%c HPIrq%c LinkChg%c\n",
904c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTCTL_ATNB),
905c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTCTL_PWRF),
906c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTCTL_MRLS),
907c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTCTL_PRSD),
908c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTCTL_CMDC),
909c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTCTL_HPIE),
910c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTCTL_LLCHG));
911c7a34993SMartin Mares printf("\t\t\tControl: AttnInd %s, PwrInd %s, Power%c Interlock%c\n",
912c7a34993SMartin Mares indicator((w & PCI_EXP_SLTCTL_ATNI) >> 6),
913c7a34993SMartin Mares indicator((w & PCI_EXP_SLTCTL_PWRI) >> 8),
914c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTCTL_PWRC),
915c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTCTL_INTERLOCK));
916c7a34993SMartin Mares
917c7a34993SMartin Mares w = get_conf_word(d, where + PCI_EXP_SLTSTA);
918c7a34993SMartin Mares printf("\t\tSltSta:\tStatus: AttnBtn%c PowerFlt%c MRL%c CmdCplt%c PresDet%c Interlock%c\n",
919c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTSTA_ATNB),
920c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTSTA_PWRF),
921c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTSTA_MRL_ST),
922c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTSTA_CMDC),
923c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTSTA_PRES),
924c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTSTA_INTERLOCK));
925c7a34993SMartin Mares printf("\t\t\tChanged: MRL%c PresDet%c LinkState%c\n",
926c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTSTA_MRLS),
927c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTSTA_PRSD),
928c7a34993SMartin Mares FLAG(w, PCI_EXP_SLTSTA_LLCHG));
929c7a34993SMartin Mares }
930c7a34993SMartin Mares
cap_express_root(struct device * d,int where)931c7a34993SMartin Mares static void cap_express_root(struct device *d, int where)
932c7a34993SMartin Mares {
933e6a11bb4SBjorn Helgaas u32 w;
934e6a11bb4SBjorn Helgaas
935e6a11bb4SBjorn Helgaas w = get_conf_word(d, where + PCI_EXP_RTCAP);
936e6a11bb4SBjorn Helgaas printf("\t\tRootCap: CRSVisible%c\n",
937e6a11bb4SBjorn Helgaas FLAG(w, PCI_EXP_RTCAP_CRSVIS));
938e6a11bb4SBjorn Helgaas
939e6a11bb4SBjorn Helgaas w = get_conf_word(d, where + PCI_EXP_RTCTL);
940c7a34993SMartin Mares printf("\t\tRootCtl: ErrCorrectable%c ErrNon-Fatal%c ErrFatal%c PMEIntEna%c CRSVisible%c\n",
941c7a34993SMartin Mares FLAG(w, PCI_EXP_RTCTL_SECEE),
942c7a34993SMartin Mares FLAG(w, PCI_EXP_RTCTL_SENFEE),
943c7a34993SMartin Mares FLAG(w, PCI_EXP_RTCTL_SEFEE),
944c7a34993SMartin Mares FLAG(w, PCI_EXP_RTCTL_PMEIE),
945c7a34993SMartin Mares FLAG(w, PCI_EXP_RTCTL_CRSVIS));
946c7a34993SMartin Mares
94723c27798SJeffy Chen w = get_conf_long(d, where + PCI_EXP_RTSTA);
948c7a34993SMartin Mares printf("\t\tRootSta: PME ReqID %04x, PMEStatus%c PMEPending%c\n",
949c7a34993SMartin Mares w & PCI_EXP_RTSTA_PME_REQID,
950c7a34993SMartin Mares FLAG(w, PCI_EXP_RTSTA_PME_STATUS),
951c7a34993SMartin Mares FLAG(w, PCI_EXP_RTSTA_PME_PENDING));
952c7a34993SMartin Mares }
953c7a34993SMartin Mares
cap_express_dev2_timeout_range(int type)954c7a34993SMartin Mares static const char *cap_express_dev2_timeout_range(int type)
955c7a34993SMartin Mares {
956c7a34993SMartin Mares /* Decode Completion Timeout Ranges. */
957c7a34993SMartin Mares switch (type)
958c7a34993SMartin Mares {
959c7a34993SMartin Mares case 0:
960c7a34993SMartin Mares return "Not Supported";
961c7a34993SMartin Mares case 1:
962c7a34993SMartin Mares return "Range A";
963c7a34993SMartin Mares case 2:
964c7a34993SMartin Mares return "Range B";
965c7a34993SMartin Mares case 3:
966c7a34993SMartin Mares return "Range AB";
967c7a34993SMartin Mares case 6:
968c7a34993SMartin Mares return "Range BC";
969c7a34993SMartin Mares case 7:
970c7a34993SMartin Mares return "Range ABC";
971c7a34993SMartin Mares case 14:
972c7a34993SMartin Mares return "Range BCD";
973c7a34993SMartin Mares case 15:
974c7a34993SMartin Mares return "Range ABCD";
975c7a34993SMartin Mares default:
976c7a34993SMartin Mares return "Unknown";
977c7a34993SMartin Mares }
978c7a34993SMartin Mares }
979c7a34993SMartin Mares
cap_express_dev2_timeout_value(int type)980c7a34993SMartin Mares static const char *cap_express_dev2_timeout_value(int type)
981c7a34993SMartin Mares {
982c7a34993SMartin Mares /* Decode Completion Timeout Value. */
983c7a34993SMartin Mares switch (type)
984c7a34993SMartin Mares {
985c7a34993SMartin Mares case 0:
986c7a34993SMartin Mares return "50us to 50ms";
987c7a34993SMartin Mares case 1:
988c7a34993SMartin Mares return "50us to 100us";
989c7a34993SMartin Mares case 2:
990c7a34993SMartin Mares return "1ms to 10ms";
991c7a34993SMartin Mares case 5:
992c7a34993SMartin Mares return "16ms to 55ms";
993c7a34993SMartin Mares case 6:
994c7a34993SMartin Mares return "65ms to 210ms";
995c7a34993SMartin Mares case 9:
996c7a34993SMartin Mares return "260ms to 900ms";
997c7a34993SMartin Mares case 10:
998c7a34993SMartin Mares return "1s to 3.5s";
999c7a34993SMartin Mares case 13:
1000c7a34993SMartin Mares return "4s to 13s";
1001c7a34993SMartin Mares case 14:
1002c7a34993SMartin Mares return "17s to 64s";
1003c7a34993SMartin Mares default:
1004c7a34993SMartin Mares return "Unknown";
1005c7a34993SMartin Mares }
1006c7a34993SMartin Mares }
1007c7a34993SMartin Mares
cap_express_devcap2_obff(int obff)1008d4c91e40SMika Westerberg static const char *cap_express_devcap2_obff(int obff)
1009d4c91e40SMika Westerberg {
1010d4c91e40SMika Westerberg switch (obff)
1011d4c91e40SMika Westerberg {
1012d4c91e40SMika Westerberg case 1:
1013d4c91e40SMika Westerberg return "Via message";
1014d4c91e40SMika Westerberg case 2:
1015d4c91e40SMika Westerberg return "Via WAKE#";
1016d4c91e40SMika Westerberg case 3:
1017d4c91e40SMika Westerberg return "Via message/WAKE#";
1018d4c91e40SMika Westerberg default:
1019d4c91e40SMika Westerberg return "Not Supported";
1020d4c91e40SMika Westerberg }
1021d4c91e40SMika Westerberg }
1022d4c91e40SMika Westerberg
cap_express_devcap2_epr(int epr)102333226851SFrederick Lawler static const char *cap_express_devcap2_epr(int epr)
102433226851SFrederick Lawler {
102533226851SFrederick Lawler switch (epr)
102633226851SFrederick Lawler {
102733226851SFrederick Lawler case 1:
102833226851SFrederick Lawler return "Dev Specific";
102933226851SFrederick Lawler case 2:
103033226851SFrederick Lawler return "Form Factor Dev Specific";
103133226851SFrederick Lawler case 3:
103233226851SFrederick Lawler return "Reserved";
103333226851SFrederick Lawler default:
103433226851SFrederick Lawler return "Not Supported";
103533226851SFrederick Lawler }
103633226851SFrederick Lawler }
103733226851SFrederick Lawler
cap_express_devcap2_lncls(int lncls)103833226851SFrederick Lawler static const char *cap_express_devcap2_lncls(int lncls)
103933226851SFrederick Lawler {
104033226851SFrederick Lawler switch (lncls)
104133226851SFrederick Lawler {
104233226851SFrederick Lawler case 1:
104333226851SFrederick Lawler return "64byte cachelines";
104433226851SFrederick Lawler case 2:
104533226851SFrederick Lawler return "128byte cachelines";
104633226851SFrederick Lawler case 3:
104733226851SFrederick Lawler return "Reserved";
104833226851SFrederick Lawler default:
104933226851SFrederick Lawler return "Not Supported";
105033226851SFrederick Lawler }
105133226851SFrederick Lawler }
105233226851SFrederick Lawler
cap_express_devcap2_tphcomp(int tph)105333226851SFrederick Lawler static const char *cap_express_devcap2_tphcomp(int tph)
105433226851SFrederick Lawler {
105533226851SFrederick Lawler switch (tph)
105633226851SFrederick Lawler {
105733226851SFrederick Lawler case 1:
1058018f413cSBjorn Helgaas return "TPHComp+ ExtTPHComp-";
105933226851SFrederick Lawler case 2:
106033226851SFrederick Lawler /* Reserved; intentionally left blank */
106133226851SFrederick Lawler return "";
106233226851SFrederick Lawler case 3:
1063018f413cSBjorn Helgaas return "TPHComp+ ExtTPHComp+";
106433226851SFrederick Lawler default:
1065018f413cSBjorn Helgaas return "TPHComp- ExtTPHComp-";
106633226851SFrederick Lawler }
106733226851SFrederick Lawler }
106833226851SFrederick Lawler
cap_express_devctl2_obff(int obff)1069d4c91e40SMika Westerberg static const char *cap_express_devctl2_obff(int obff)
1070d4c91e40SMika Westerberg {
1071d4c91e40SMika Westerberg switch (obff)
1072d4c91e40SMika Westerberg {
1073d4c91e40SMika Westerberg case 0:
1074d4c91e40SMika Westerberg return "Disabled";
1075d4c91e40SMika Westerberg case 1:
1076d4c91e40SMika Westerberg return "Via message A";
1077d4c91e40SMika Westerberg case 2:
1078d4c91e40SMika Westerberg return "Via message B";
1079d4c91e40SMika Westerberg case 3:
1080d4c91e40SMika Westerberg return "Via WAKE#";
1081d4c91e40SMika Westerberg default:
1082d4c91e40SMika Westerberg return "Unknown";
1083d4c91e40SMika Westerberg }
1084d4c91e40SMika Westerberg }
1085d4c91e40SMika Westerberg
1086ad431573SSatanand Burla static int
device_has_memory_space_bar(struct device * d)1087ad431573SSatanand Burla device_has_memory_space_bar(struct device *d)
1088ad431573SSatanand Burla {
1089ad431573SSatanand Burla struct pci_dev *p = d->dev;
1090ad431573SSatanand Burla int i, found = 0;
1091ad431573SSatanand Burla
1092ad431573SSatanand Burla for (i=0; i<6; i++)
1093dcd6913eSPali Rohár if (p->base_addr[i] || p->size[i])
1094ad431573SSatanand Burla {
1095ad431573SSatanand Burla if (!(p->base_addr[i] & PCI_BASE_ADDRESS_SPACE_IO))
1096ad431573SSatanand Burla {
1097ad431573SSatanand Burla found = 1;
1098ad431573SSatanand Burla break;
1099ad431573SSatanand Burla }
1100ad431573SSatanand Burla }
1101ad431573SSatanand Burla return found;
1102ad431573SSatanand Burla }
1103ad431573SSatanand Burla
cap_express_dev2(struct device * d,int where,int type)1104c7a34993SMartin Mares static void cap_express_dev2(struct device *d, int where, int type)
1105c7a34993SMartin Mares {
1106c7a34993SMartin Mares u32 l;
1107c7a34993SMartin Mares u16 w;
11085371aab4SMartin Mares int has_mem_bar = device_has_memory_space_bar(d);
1109c7a34993SMartin Mares
1110c7a34993SMartin Mares l = get_conf_long(d, where + PCI_EXP_DEVCAP2);
1111018f413cSBjorn Helgaas printf("\t\tDevCap2: Completion Timeout: %s, TimeoutDis%c NROPrPrP%c LTR%c",
1112e79a4207SDongdong Liu cap_express_dev2_timeout_range(PCI_EXP_DEVCAP2_TIMEOUT_RANGE(l)),
1113e79a4207SDongdong Liu FLAG(l, PCI_EXP_DEVCAP2_TIMEOUT_DIS),
111433226851SFrederick Lawler FLAG(l, PCI_EXP_DEVCAP2_NROPRPRP),
111533226851SFrederick Lawler FLAG(l, PCI_EXP_DEVCAP2_LTR));
1116018f413cSBjorn Helgaas printf("\n\t\t\t 10BitTagComp%c 10BitTagReq%c OBFF %s, ExtFmt%c EETLPPrefix%c",
111733226851SFrederick Lawler FLAG(l, PCI_EXP_DEVCAP2_10BIT_TAG_COMP),
111833226851SFrederick Lawler FLAG(l, PCI_EXP_DEVCAP2_10BIT_TAG_REQ),
111933226851SFrederick Lawler cap_express_devcap2_obff(PCI_EXP_DEVCAP2_OBFF(l)),
112033226851SFrederick Lawler FLAG(l, PCI_EXP_DEVCAP2_EXTFMT),
112133226851SFrederick Lawler FLAG(l, PCI_EXP_DEVCAP2_EE_TLP));
112233226851SFrederick Lawler
112333226851SFrederick Lawler if (PCI_EXP_DEVCAP2_EE_TLP == (l & PCI_EXP_DEVCAP2_EE_TLP))
112433226851SFrederick Lawler {
112533226851SFrederick Lawler printf(", MaxEETLPPrefixes %d",
112633226851SFrederick Lawler PCI_EXP_DEVCAP2_MEE_TLP(l) ? PCI_EXP_DEVCAP2_MEE_TLP(l) : 4);
112733226851SFrederick Lawler }
112833226851SFrederick Lawler
112933226851SFrederick Lawler printf("\n\t\t\t EmergencyPowerReduction %s, EmergencyPowerReductionInit%c",
113033226851SFrederick Lawler cap_express_devcap2_epr(PCI_EXP_DEVCAP2_EPR(l)),
113133226851SFrederick Lawler FLAG(l, PCI_EXP_DEVCAP2_EPR_INIT));
113233226851SFrederick Lawler printf("\n\t\t\t FRS%c", FLAG(l, PCI_EXP_DEVCAP2_FRS));
113333226851SFrederick Lawler
113433226851SFrederick Lawler if (type == PCI_EXP_TYPE_ROOT_PORT)
1135018f413cSBjorn Helgaas printf(" LN System CLS %s,",
113633226851SFrederick Lawler cap_express_devcap2_lncls(PCI_EXP_DEVCAP2_LN_CLS(l)));
113733226851SFrederick Lawler
113833226851SFrederick Lawler if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_ENDPOINT)
1139018f413cSBjorn Helgaas printf(" %s", cap_express_devcap2_tphcomp(PCI_EXP_DEVCAP2_TPH_COMP(l)));
114033226851SFrederick Lawler
1141c7a34993SMartin Mares if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_DOWNSTREAM)
1142e79a4207SDongdong Liu printf(" ARIFwd%c\n", FLAG(l, PCI_EXP_DEVCAP2_ARI));
1143c7a34993SMartin Mares else
1144c7a34993SMartin Mares printf("\n");
1145ad431573SSatanand Burla if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_UPSTREAM ||
1146ad431573SSatanand Burla type == PCI_EXP_TYPE_DOWNSTREAM || has_mem_bar)
1147ad431573SSatanand Burla {
1148c4cf2d1cSBjorn Helgaas printf("\t\t\t AtomicOpsCap:");
1149ad431573SSatanand Burla if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_UPSTREAM ||
1150ad431573SSatanand Burla type == PCI_EXP_TYPE_DOWNSTREAM)
1151ad431573SSatanand Burla printf(" Routing%c", FLAG(l, PCI_EXP_DEVCAP2_ATOMICOP_ROUTING));
1152ad431573SSatanand Burla if (type == PCI_EXP_TYPE_ROOT_PORT || has_mem_bar)
1153ad431573SSatanand Burla printf(" 32bit%c 64bit%c 128bitCAS%c",
1154ad431573SSatanand Burla FLAG(l, PCI_EXP_DEVCAP2_32BIT_ATOMICOP_COMP),
1155ad431573SSatanand Burla FLAG(l, PCI_EXP_DEVCAP2_64BIT_ATOMICOP_COMP),
1156ad431573SSatanand Burla FLAG(l, PCI_EXP_DEVCAP2_128BIT_CAS_COMP));
1157ad431573SSatanand Burla printf("\n");
1158ad431573SSatanand Burla }
1159c7a34993SMartin Mares
1160c7a34993SMartin Mares w = get_conf_word(d, where + PCI_EXP_DEVCTL2);
1161ba06b2f5SBjorn Helgaas printf("\t\tDevCtl2: Completion Timeout: %s, TimeoutDis%c",
1162e79a4207SDongdong Liu cap_express_dev2_timeout_value(PCI_EXP_DEVCTL2_TIMEOUT_VALUE(w)),
1163ba06b2f5SBjorn Helgaas FLAG(w, PCI_EXP_DEVCTL2_TIMEOUT_DIS));
1164c7a34993SMartin Mares if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_DOWNSTREAM)
1165e79a4207SDongdong Liu printf(" ARIFwd%c\n", FLAG(w, PCI_EXP_DEVCTL2_ARI));
1166c7a34993SMartin Mares else
1167c7a34993SMartin Mares printf("\n");
1168ad431573SSatanand Burla if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_UPSTREAM ||
1169ad431573SSatanand Burla type == PCI_EXP_TYPE_DOWNSTREAM || type == PCI_EXP_TYPE_ENDPOINT ||
1170ad431573SSatanand Burla type == PCI_EXP_TYPE_ROOT_INT_EP || type == PCI_EXP_TYPE_LEG_END)
1171ad431573SSatanand Burla {
1172c4cf2d1cSBjorn Helgaas printf("\t\t\t AtomicOpsCtl:");
1173ad431573SSatanand Burla if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_ENDPOINT ||
1174ad431573SSatanand Burla type == PCI_EXP_TYPE_ROOT_INT_EP || type == PCI_EXP_TYPE_LEG_END)
1175e79a4207SDongdong Liu printf(" ReqEn%c", FLAG(w, PCI_EXP_DEVCTL2_ATOMICOP_REQUESTER_EN));
1176ad431573SSatanand Burla if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_UPSTREAM ||
1177ad431573SSatanand Burla type == PCI_EXP_TYPE_DOWNSTREAM)
1178e79a4207SDongdong Liu printf(" EgressBlck%c", FLAG(w, PCI_EXP_DEVCTL2_ATOMICOP_EGRESS_BLOCK));
1179ad431573SSatanand Burla printf("\n");
1180ad431573SSatanand Burla }
1181a99d27a3SBjorn Helgaas printf("\t\t\t IDOReq%c IDOCompl%c LTR%c EmergencyPowerReductionReq%c\n",
11823746111dSBjorn Helgaas FLAG(w, PCI_EXP_DEVCTL2_IDO_REQ_EN),
11833746111dSBjorn Helgaas FLAG(w, PCI_EXP_DEVCTL2_IDO_CMP_EN),
1184ba06b2f5SBjorn Helgaas FLAG(w, PCI_EXP_DEVCTL2_LTR),
1185a99d27a3SBjorn Helgaas FLAG(w, PCI_EXP_DEVCTL2_EPR_REQ));
11867d2b2d69SBjorn Helgaas printf("\t\t\t 10BitTagReq%c OBFF %s, EETLPPrefixBlk%c\n",
1187ba06b2f5SBjorn Helgaas FLAG(w, PCI_EXP_DEVCTL2_10BIT_TAG_REQ),
11887d2b2d69SBjorn Helgaas cap_express_devctl2_obff(PCI_EXP_DEVCTL2_OBFF(w)),
11897d2b2d69SBjorn Helgaas FLAG(w, PCI_EXP_DEVCTL2_EE_TLP_BLK));
1190c7a34993SMartin Mares }
1191c7a34993SMartin Mares
cap_express_link2_speed_cap(int vector)1192623ed0e1SBjorn Helgaas static const char *cap_express_link2_speed_cap(int vector)
1193623ed0e1SBjorn Helgaas {
1194623ed0e1SBjorn Helgaas /*
1195623ed0e1SBjorn Helgaas * Per PCIe r5.0, sec 8.2.1, a device must support 2.5GT/s and is not
1196623ed0e1SBjorn Helgaas * permitted to skip support for any data rates between 2.5GT/s and the
1197623ed0e1SBjorn Helgaas * highest supported rate.
1198623ed0e1SBjorn Helgaas */
119990d270faSIlpo Järvinen if (vector & 0x40)
1200*3ec74c71SPrabu Thangamuthu return "2.5-128GT/s";
120190d270faSIlpo Järvinen if (vector & 0x20)
120290d270faSIlpo Järvinen return "2.5-64GT/s";
1203623ed0e1SBjorn Helgaas if (vector & 0x10)
1204623ed0e1SBjorn Helgaas return "2.5-32GT/s";
1205623ed0e1SBjorn Helgaas if (vector & 0x08)
1206623ed0e1SBjorn Helgaas return "2.5-16GT/s";
1207623ed0e1SBjorn Helgaas if (vector & 0x04)
1208623ed0e1SBjorn Helgaas return "2.5-8GT/s";
1209623ed0e1SBjorn Helgaas if (vector & 0x02)
1210623ed0e1SBjorn Helgaas return "2.5-5GT/s";
1211623ed0e1SBjorn Helgaas if (vector & 0x01)
1212623ed0e1SBjorn Helgaas return "2.5GT/s";
1213623ed0e1SBjorn Helgaas
1214623ed0e1SBjorn Helgaas return "Unknown";
1215623ed0e1SBjorn Helgaas }
1216623ed0e1SBjorn Helgaas
cap_express_link2_speed(int type)1217c7a34993SMartin Mares static const char *cap_express_link2_speed(int type)
1218c7a34993SMartin Mares {
1219c7a34993SMartin Mares switch (type)
1220c7a34993SMartin Mares {
1221c7a34993SMartin Mares case 0: /* hardwire to 0 means only the 2.5GT/s is supported */
1222c7a34993SMartin Mares case 1:
1223c7a34993SMartin Mares return "2.5GT/s";
1224c7a34993SMartin Mares case 2:
1225c7a34993SMartin Mares return "5GT/s";
12264dc4ff43SMartin Mares case 3:
12274dc4ff43SMartin Mares return "8GT/s";
12289628600bSGavin Shan case 4:
12299628600bSGavin Shan return "16GT/s";
1230caca31a0SGustavo Pimentel case 5:
1231caca31a0SGustavo Pimentel return "32GT/s";
12325bdf63b6SGustavo Pimentel case 6:
12335bdf63b6SGustavo Pimentel return "64GT/s";
1234*3ec74c71SPrabu Thangamuthu case 8:
1235*3ec74c71SPrabu Thangamuthu return "128GT/s";
1236c7a34993SMartin Mares default:
1237c7a34993SMartin Mares return "Unknown";
1238c7a34993SMartin Mares }
1239c7a34993SMartin Mares }
1240c7a34993SMartin Mares
cap_express_link2_deemphasis(int type)1241c7a34993SMartin Mares static const char *cap_express_link2_deemphasis(int type)
1242c7a34993SMartin Mares {
1243c7a34993SMartin Mares switch (type)
1244c7a34993SMartin Mares {
1245c7a34993SMartin Mares case 0:
1246c7a34993SMartin Mares return "-6dB";
1247c7a34993SMartin Mares case 1:
1248c7a34993SMartin Mares return "-3.5dB";
1249c7a34993SMartin Mares default:
1250c7a34993SMartin Mares return "Unknown";
1251c7a34993SMartin Mares }
1252c7a34993SMartin Mares }
1253c7a34993SMartin Mares
cap_express_link2_compliance_preset(int type)1254ad140168SLennert Buytenhek static const char *cap_express_link2_compliance_preset(int type)
1255ad140168SLennert Buytenhek {
1256ad140168SLennert Buytenhek switch (type)
1257ad140168SLennert Buytenhek {
1258ad140168SLennert Buytenhek case 0:
1259ad140168SLennert Buytenhek return "-6dB de-emphasis, 0dB preshoot";
1260ad140168SLennert Buytenhek case 1:
1261ad140168SLennert Buytenhek return "-3.5dB de-emphasis, 0dB preshoot";
1262ad140168SLennert Buytenhek case 2:
1263ad140168SLennert Buytenhek return "-4.4dB de-emphasis, 0dB preshoot";
1264ad140168SLennert Buytenhek case 3:
1265ad140168SLennert Buytenhek return "-2.5dB de-emphasis, 0dB preshoot";
1266ad140168SLennert Buytenhek case 4:
1267ad140168SLennert Buytenhek return "0dB de-emphasis, 0dB preshoot";
1268ad140168SLennert Buytenhek case 5:
1269ad140168SLennert Buytenhek return "0dB de-emphasis, 1.9dB preshoot";
1270ad140168SLennert Buytenhek case 6:
1271ad140168SLennert Buytenhek return "0dB de-emphasis, 2.5dB preshoot";
1272ad140168SLennert Buytenhek case 7:
1273ad140168SLennert Buytenhek return "-6.0dB de-emphasis, 3.5dB preshoot";
1274ad140168SLennert Buytenhek case 8:
1275ad140168SLennert Buytenhek return "-3.5dB de-emphasis, 3.5dB preshoot";
1276ad140168SLennert Buytenhek case 9:
1277ad140168SLennert Buytenhek return "0dB de-emphasis, 3.5dB preshoot";
1278ad140168SLennert Buytenhek default:
1279ad140168SLennert Buytenhek return "Unknown";
1280ad140168SLennert Buytenhek }
1281ad140168SLennert Buytenhek }
1282ad140168SLennert Buytenhek
cap_express_link2_transmargin(int type)1283c7a34993SMartin Mares static const char *cap_express_link2_transmargin(int type)
1284c7a34993SMartin Mares {
1285c7a34993SMartin Mares switch (type)
1286c7a34993SMartin Mares {
1287c7a34993SMartin Mares case 0:
1288c7a34993SMartin Mares return "Normal Operating Range";
1289c7a34993SMartin Mares case 1:
1290c7a34993SMartin Mares return "800-1200mV(full-swing)/400-700mV(half-swing)";
1291c7a34993SMartin Mares case 2:
1292c7a34993SMartin Mares case 3:
1293c7a34993SMartin Mares case 4:
1294c7a34993SMartin Mares case 5:
1295c7a34993SMartin Mares return "200-400mV(full-swing)/100-200mV(half-swing)";
1296c7a34993SMartin Mares default:
1297c7a34993SMartin Mares return "Unknown";
1298c7a34993SMartin Mares }
1299c7a34993SMartin Mares }
1300c7a34993SMartin Mares
cap_express_link2_crosslink_res(int crosslink)1301623ed0e1SBjorn Helgaas static const char *cap_express_link2_crosslink_res(int crosslink)
1302623ed0e1SBjorn Helgaas {
1303623ed0e1SBjorn Helgaas switch (crosslink)
1304623ed0e1SBjorn Helgaas {
1305623ed0e1SBjorn Helgaas case 0:
1306623ed0e1SBjorn Helgaas return "unsupported";
1307623ed0e1SBjorn Helgaas case 1:
1308623ed0e1SBjorn Helgaas return "Upstream Port";
1309623ed0e1SBjorn Helgaas case 2:
1310623ed0e1SBjorn Helgaas return "Downstream Port";
1311623ed0e1SBjorn Helgaas default:
1312623ed0e1SBjorn Helgaas return "incomplete";
1313623ed0e1SBjorn Helgaas }
1314623ed0e1SBjorn Helgaas }
1315623ed0e1SBjorn Helgaas
cap_express_link2_component(int presence)1316623ed0e1SBjorn Helgaas static const char *cap_express_link2_component(int presence)
1317623ed0e1SBjorn Helgaas {
1318623ed0e1SBjorn Helgaas switch (presence)
1319623ed0e1SBjorn Helgaas {
1320623ed0e1SBjorn Helgaas case 0:
1321623ed0e1SBjorn Helgaas return "Link Down - Not Determined";
1322623ed0e1SBjorn Helgaas case 1:
1323623ed0e1SBjorn Helgaas return "Link Down - Not Present";
1324623ed0e1SBjorn Helgaas case 2:
1325623ed0e1SBjorn Helgaas return "Link Down - Present";
1326623ed0e1SBjorn Helgaas case 4:
1327623ed0e1SBjorn Helgaas return "Link Up - Present";
1328623ed0e1SBjorn Helgaas case 5:
1329623ed0e1SBjorn Helgaas return "Link Up - Present and DRS Received";
1330623ed0e1SBjorn Helgaas default:
1331623ed0e1SBjorn Helgaas return "Reserved";
1332623ed0e1SBjorn Helgaas }
1333623ed0e1SBjorn Helgaas }
1334623ed0e1SBjorn Helgaas
cap_express_link2(struct device * d,int where,int type)133537f8039dSBen Hutchings static void cap_express_link2(struct device *d, int where, int type)
1336c7a34993SMartin Mares {
1337623ed0e1SBjorn Helgaas u32 l = 0;
1338c7a34993SMartin Mares u16 w;
1339c7a34993SMartin Mares
134037f8039dSBen Hutchings if (!((type == PCI_EXP_TYPE_ENDPOINT || type == PCI_EXP_TYPE_LEG_END) &&
134137f8039dSBen Hutchings (d->dev->dev != 0 || d->dev->func != 0))) {
1342623ed0e1SBjorn Helgaas /* Link Capabilities 2 was reserved before PCIe r3.0 */
1343623ed0e1SBjorn Helgaas l = get_conf_long(d, where + PCI_EXP_LNKCAP2);
1344623ed0e1SBjorn Helgaas if (l) {
1345623ed0e1SBjorn Helgaas printf("\t\tLnkCap2: Supported Link Speeds: %s, Crosslink%c "
1346623ed0e1SBjorn Helgaas "Retimer%c 2Retimers%c DRS%c\n",
1347623ed0e1SBjorn Helgaas cap_express_link2_speed_cap(PCI_EXP_LNKCAP2_SPEED(l)),
1348623ed0e1SBjorn Helgaas FLAG(l, PCI_EXP_LNKCAP2_CROSSLINK),
1349623ed0e1SBjorn Helgaas FLAG(l, PCI_EXP_LNKCAP2_RETIMER),
1350623ed0e1SBjorn Helgaas FLAG(l, PCI_EXP_LNKCAP2_2RETIMERS),
1351623ed0e1SBjorn Helgaas FLAG(l, PCI_EXP_LNKCAP2_DRS));
1352623ed0e1SBjorn Helgaas }
1353623ed0e1SBjorn Helgaas
1354c7a34993SMartin Mares w = get_conf_word(d, where + PCI_EXP_LNKCTL2);
135537f8039dSBen Hutchings printf("\t\tLnkCtl2: Target Link Speed: %s, EnterCompliance%c SpeedDis%c",
1356c7a34993SMartin Mares cap_express_link2_speed(PCI_EXP_LNKCTL2_SPEED(w)),
1357c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKCTL2_CMPLNC),
135837f8039dSBen Hutchings FLAG(w, PCI_EXP_LNKCTL2_SPEED_DIS));
135937f8039dSBen Hutchings if (type == PCI_EXP_TYPE_DOWNSTREAM)
136037f8039dSBen Hutchings printf(", Selectable De-emphasis: %s",
136137f8039dSBen Hutchings cap_express_link2_deemphasis(PCI_EXP_LNKCTL2_DEEMPHASIS(w)));
136237f8039dSBen Hutchings printf("\n"
136337f8039dSBen Hutchings "\t\t\t Transmit Margin: %s, EnterModifiedCompliance%c ComplianceSOS%c\n"
1364ad140168SLennert Buytenhek "\t\t\t Compliance Preset/De-emphasis: %s\n",
1365c7a34993SMartin Mares cap_express_link2_transmargin(PCI_EXP_LNKCTL2_MARGIN(w)),
1366c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKCTL2_MOD_CMPLNC),
1367c7a34993SMartin Mares FLAG(w, PCI_EXP_LNKCTL2_CMPLNC_SOS),
1368ad140168SLennert Buytenhek cap_express_link2_compliance_preset(PCI_EXP_LNKCTL2_COM_DEEMPHASIS(w)));
136937f8039dSBen Hutchings }
1370c7a34993SMartin Mares
1371c7a34993SMartin Mares w = get_conf_word(d, where + PCI_EXP_LNKSTA2);
1372018f413cSBjorn Helgaas printf("\t\tLnkSta2: Current De-emphasis Level: %s, EqualizationComplete%c EqualizationPhase1%c\n"
1373018f413cSBjorn Helgaas "\t\t\t EqualizationPhase2%c EqualizationPhase3%c LinkEqualizationRequest%c\n"
13749611db3eSPaul Cassidy "\t\t\t Retimer%c 2Retimers%c CrosslinkRes: %s, FltMode%c",
13754dc4ff43SMartin Mares cap_express_link2_deemphasis(PCI_EXP_LINKSTA2_DEEMPHASIS(w)),
13764dc4ff43SMartin Mares FLAG(w, PCI_EXP_LINKSTA2_EQU_COMP),
13774dc4ff43SMartin Mares FLAG(w, PCI_EXP_LINKSTA2_EQU_PHASE1),
13784dc4ff43SMartin Mares FLAG(w, PCI_EXP_LINKSTA2_EQU_PHASE2),
13794dc4ff43SMartin Mares FLAG(w, PCI_EXP_LINKSTA2_EQU_PHASE3),
1380623ed0e1SBjorn Helgaas FLAG(w, PCI_EXP_LINKSTA2_EQU_REQ),
1381623ed0e1SBjorn Helgaas FLAG(w, PCI_EXP_LINKSTA2_RETIMER),
1382623ed0e1SBjorn Helgaas FLAG(w, PCI_EXP_LINKSTA2_2RETIMERS),
13839611db3eSPaul Cassidy cap_express_link2_crosslink_res(PCI_EXP_LINKSTA2_CROSSLINK(w)),
13849611db3eSPaul Cassidy FLAG(w, PCI_EXP_LINKSTA2_FLIT_MODE));
1385623ed0e1SBjorn Helgaas
1386623ed0e1SBjorn Helgaas if (exp_downstream_port(type) && (l & PCI_EXP_LNKCAP2_DRS)) {
1387623ed0e1SBjorn Helgaas printf(", DRS%c\n"
1388623ed0e1SBjorn Helgaas "\t\t\t DownstreamComp: %s\n",
1389623ed0e1SBjorn Helgaas FLAG(w, PCI_EXP_LINKSTA2_DRS_RCVD),
1390623ed0e1SBjorn Helgaas cap_express_link2_component(PCI_EXP_LINKSTA2_COMPONENT(w)));
1391623ed0e1SBjorn Helgaas } else
1392623ed0e1SBjorn Helgaas printf("\n");
1393c7a34993SMartin Mares }
1394c7a34993SMartin Mares
cap_express_slot2(struct device * d UNUSED,int where UNUSED)1395c7a34993SMartin Mares static void cap_express_slot2(struct device *d UNUSED, int where UNUSED)
1396c7a34993SMartin Mares {
1397c7a34993SMartin Mares /* No capabilities that require this field in PCIe rev2.0 spec. */
1398c7a34993SMartin Mares }
1399c7a34993SMartin Mares
cap_express_link_rcd(struct device * d)140049efa87fSKobayashi Daisuke static void cap_express_link_rcd(struct device *d)
140149efa87fSKobayashi Daisuke {
140249efa87fSKobayashi Daisuke u32 t, aspm, cap_speed, cap_width, sta_speed, sta_width;
140349efa87fSKobayashi Daisuke u16 w;
140449efa87fSKobayashi Daisuke struct pci_dev *pdev = d->dev;
140549efa87fSKobayashi Daisuke
140649efa87fSKobayashi Daisuke if (!pdev->rcd_link_cap)
140749efa87fSKobayashi Daisuke return;
1408a8a0f810SMartin Mares
140949efa87fSKobayashi Daisuke t = pdev->rcd_link_cap;
141049efa87fSKobayashi Daisuke aspm = (t & PCI_EXP_LNKCAP_ASPM) >> 10;
141149efa87fSKobayashi Daisuke cap_speed = t & PCI_EXP_LNKCAP_SPEED;
141249efa87fSKobayashi Daisuke cap_width = (t & PCI_EXP_LNKCAP_WIDTH) >> 4;
141349efa87fSKobayashi Daisuke printf("\t\tLnkCap:\tPort #%d, Speed %s, Width x%d, ASPM %s",
141449efa87fSKobayashi Daisuke t >> 24,
141549efa87fSKobayashi Daisuke link_speed(cap_speed), cap_width,
141649efa87fSKobayashi Daisuke aspm_support(aspm));
1417a8a0f810SMartin Mares if (aspm)
1418a8a0f810SMartin Mares {
141949efa87fSKobayashi Daisuke printf(", Exit Latency ");
142049efa87fSKobayashi Daisuke if (aspm & 1)
142149efa87fSKobayashi Daisuke printf("L0s %s", latency_l0s((t & PCI_EXP_LNKCAP_L0S) >> 12));
142249efa87fSKobayashi Daisuke if (aspm & 2)
142349efa87fSKobayashi Daisuke printf("%sL1 %s", (aspm & 1) ? ", " : "",
142449efa87fSKobayashi Daisuke latency_l1((t & PCI_EXP_LNKCAP_L1) >> 15));
142549efa87fSKobayashi Daisuke }
142649efa87fSKobayashi Daisuke printf("\n");
142749efa87fSKobayashi Daisuke printf("\t\t\tClockPM%c Surprise%c LLActRep%c BwNot%c ASPMOptComp%c\n",
142849efa87fSKobayashi Daisuke FLAG(t, PCI_EXP_LNKCAP_CLOCKPM),
142949efa87fSKobayashi Daisuke FLAG(t, PCI_EXP_LNKCAP_SURPRISE),
143049efa87fSKobayashi Daisuke FLAG(t, PCI_EXP_LNKCAP_DLLA),
143149efa87fSKobayashi Daisuke FLAG(t, PCI_EXP_LNKCAP_LBNC),
143249efa87fSKobayashi Daisuke FLAG(t, PCI_EXP_LNKCAP_AOC));
143349efa87fSKobayashi Daisuke
143449efa87fSKobayashi Daisuke w = pdev->rcd_link_ctrl;
143549efa87fSKobayashi Daisuke printf("\t\tLnkCtl:\tASPM %s;", aspm_enabled(w & PCI_EXP_LNKCTL_ASPM));
143649efa87fSKobayashi Daisuke printf(" Disabled%c CommClk%c\n\t\t\tExtSynch%c ClockPM%c AutWidDis%c BWInt%c AutBWInt%c\n",
143749efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKCTL_DISABLE),
143849efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKCTL_CLOCK),
143949efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKCTL_XSYNCH),
144049efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKCTL_CLOCKPM),
144149efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKCTL_HWAUTWD),
144249efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKCTL_BWMIE),
144349efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKCTL_AUTBWIE));
144449efa87fSKobayashi Daisuke
144549efa87fSKobayashi Daisuke w = pdev->rcd_link_status;
144649efa87fSKobayashi Daisuke sta_speed = w & PCI_EXP_LNKSTA_SPEED;
144749efa87fSKobayashi Daisuke sta_width = (w & PCI_EXP_LNKSTA_WIDTH) >> 4;
144849efa87fSKobayashi Daisuke printf("\t\tLnkSta:\tSpeed %s%s, Width x%d%s\n",
144949efa87fSKobayashi Daisuke link_speed(sta_speed),
145049efa87fSKobayashi Daisuke link_compare(PCI_EXP_TYPE_ROOT_INT_EP, sta_speed, cap_speed),
145149efa87fSKobayashi Daisuke sta_width,
145249efa87fSKobayashi Daisuke link_compare(PCI_EXP_TYPE_ROOT_INT_EP, sta_width, cap_width));
145349efa87fSKobayashi Daisuke printf("\t\t\tTrErr%c Train%c SlotClk%c DLActive%c BWMgmt%c ABWMgmt%c\n",
145449efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKSTA_TR_ERR),
145549efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKSTA_TRAIN),
145649efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKSTA_SL_CLK),
145749efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKSTA_DL_ACT),
145849efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKSTA_BWMGMT),
145949efa87fSKobayashi Daisuke FLAG(w, PCI_EXP_LNKSTA_AUTBW));
146049efa87fSKobayashi Daisuke }
146149efa87fSKobayashi Daisuke
1462a1492b88SBjorn Helgaas static int
cap_express(struct device * d,int where,int cap)1463c7a34993SMartin Mares cap_express(struct device *d, int where, int cap)
1464c7a34993SMartin Mares {
1465c7a34993SMartin Mares int type = (cap & PCI_EXP_FLAGS_TYPE) >> 4;
1466c7a34993SMartin Mares int size;
1467c7a34993SMartin Mares int slot = 0;
146817ebd1d1SBjorn Helgaas int link = 1;
1469c7a34993SMartin Mares
1470c7a34993SMartin Mares printf("Express ");
1471c7a34993SMartin Mares if (verbose >= 2)
1472c7a34993SMartin Mares printf("(v%d) ", cap & PCI_EXP_FLAGS_VERS);
1473c7a34993SMartin Mares switch (type)
1474c7a34993SMartin Mares {
1475c7a34993SMartin Mares case PCI_EXP_TYPE_ENDPOINT:
1476c7a34993SMartin Mares printf("Endpoint");
1477c7a34993SMartin Mares break;
1478c7a34993SMartin Mares case PCI_EXP_TYPE_LEG_END:
1479c7a34993SMartin Mares printf("Legacy Endpoint");
1480c7a34993SMartin Mares break;
1481c7a34993SMartin Mares case PCI_EXP_TYPE_ROOT_PORT:
1482c7a34993SMartin Mares slot = cap & PCI_EXP_FLAGS_SLOT;
1483c7a34993SMartin Mares printf("Root Port (Slot%c)", FLAG(cap, PCI_EXP_FLAGS_SLOT));
1484c7a34993SMartin Mares break;
1485c7a34993SMartin Mares case PCI_EXP_TYPE_UPSTREAM:
1486c7a34993SMartin Mares printf("Upstream Port");
1487c7a34993SMartin Mares break;
1488c7a34993SMartin Mares case PCI_EXP_TYPE_DOWNSTREAM:
1489c7a34993SMartin Mares slot = cap & PCI_EXP_FLAGS_SLOT;
1490c7a34993SMartin Mares printf("Downstream Port (Slot%c)", FLAG(cap, PCI_EXP_FLAGS_SLOT));
1491c7a34993SMartin Mares break;
1492c7a34993SMartin Mares case PCI_EXP_TYPE_PCI_BRIDGE:
149377120d53SBjorn Helgaas printf("PCI-Express to PCI/PCI-X Bridge");
1494c7a34993SMartin Mares break;
1495c7a34993SMartin Mares case PCI_EXP_TYPE_PCIE_BRIDGE:
1496f41bb847SBjorn Helgaas slot = cap & PCI_EXP_FLAGS_SLOT;
1497f41bb847SBjorn Helgaas printf("PCI/PCI-X to PCI-Express Bridge (Slot%c)",
1498f41bb847SBjorn Helgaas FLAG(cap, PCI_EXP_FLAGS_SLOT));
1499c7a34993SMartin Mares break;
1500c7a34993SMartin Mares case PCI_EXP_TYPE_ROOT_INT_EP:
150117ebd1d1SBjorn Helgaas link = 0;
1502c7a34993SMartin Mares printf("Root Complex Integrated Endpoint");
1503c7a34993SMartin Mares break;
1504c7a34993SMartin Mares case PCI_EXP_TYPE_ROOT_EC:
150517ebd1d1SBjorn Helgaas link = 0;
1506c7a34993SMartin Mares printf("Root Complex Event Collector");
1507c7a34993SMartin Mares break;
1508c7a34993SMartin Mares default:
1509c7a34993SMartin Mares printf("Unknown type %d", type);
1510c7a34993SMartin Mares }
15119611db3eSPaul Cassidy printf(", IntMsgNum %d", (cap & PCI_EXP_FLAGS_IRQ) >> 9);
15129611db3eSPaul Cassidy if (cap & PCI_EXP_FLAGS_FLIT_MODE)
15139611db3eSPaul Cassidy printf(", FLIT Mode Supported\n");
15149611db3eSPaul Cassidy else
15159611db3eSPaul Cassidy printf("\n");
15169611db3eSPaul Cassidy
1517c7a34993SMartin Mares if (verbose < 2)
1518a1492b88SBjorn Helgaas return type;
1519c7a34993SMartin Mares
1520c7a34993SMartin Mares size = 16;
1521c7a34993SMartin Mares if (slot)
1522c7a34993SMartin Mares size = 24;
15237155d510SMasanobu SAITOH if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_ROOT_EC)
1524c7a34993SMartin Mares size = 32;
1525c7a34993SMartin Mares if (!config_fetch(d, where + PCI_EXP_DEVCAP, size))
1526a1492b88SBjorn Helgaas return type;
1527c7a34993SMartin Mares
1528c7a34993SMartin Mares cap_express_dev(d, where, type);
152917ebd1d1SBjorn Helgaas if (link)
1530c7a34993SMartin Mares cap_express_link(d, where, type);
153149efa87fSKobayashi Daisuke else if (d->dev->rcd_link_cap)
153249efa87fSKobayashi Daisuke cap_express_link_rcd(d);
153349efa87fSKobayashi Daisuke
1534c7a34993SMartin Mares if (slot)
1535c7a34993SMartin Mares cap_express_slot(d, where);
15367155d510SMasanobu SAITOH if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_ROOT_EC)
1537c7a34993SMartin Mares cap_express_root(d, where);
1538c7a34993SMartin Mares
1539c7a34993SMartin Mares if ((cap & PCI_EXP_FLAGS_VERS) < 2)
1540a1492b88SBjorn Helgaas return type;
1541c7a34993SMartin Mares
1542c7a34993SMartin Mares size = 16;
1543c7a34993SMartin Mares if (slot)
1544c7a34993SMartin Mares size = 24;
1545c7a34993SMartin Mares if (!config_fetch(d, where + PCI_EXP_DEVCAP2, size))
1546a1492b88SBjorn Helgaas return type;
1547c7a34993SMartin Mares
1548c7a34993SMartin Mares cap_express_dev2(d, where, type);
154917ebd1d1SBjorn Helgaas if (link)
1550c7a34993SMartin Mares cap_express_link2(d, where, type);
1551c7a34993SMartin Mares if (slot)
1552c7a34993SMartin Mares cap_express_slot2(d, where);
1553a1492b88SBjorn Helgaas return type;
1554c7a34993SMartin Mares }
1555c7a34993SMartin Mares
1556c7a34993SMartin Mares static void
cap_msix(struct device * d,int where,int cap)1557c7a34993SMartin Mares cap_msix(struct device *d, int where, int cap)
1558c7a34993SMartin Mares {
1559c7a34993SMartin Mares u32 off;
1560c7a34993SMartin Mares
156104885ef7SMatthew Wilcox printf("MSI-X: Enable%c Count=%d Masked%c\n",
1562c7a34993SMartin Mares FLAG(cap, PCI_MSIX_ENABLE),
156304885ef7SMatthew Wilcox (cap & PCI_MSIX_TABSIZE) + 1,
156404885ef7SMatthew Wilcox FLAG(cap, PCI_MSIX_MASK));
1565c7a34993SMartin Mares if (verbose < 2 || !config_fetch(d, where + PCI_MSIX_TABLE, 8))
1566c7a34993SMartin Mares return;
1567c7a34993SMartin Mares
1568c7a34993SMartin Mares off = get_conf_long(d, where + PCI_MSIX_TABLE);
1569c7a34993SMartin Mares printf("\t\tVector table: BAR=%d offset=%08x\n",
1570c7a34993SMartin Mares off & PCI_MSIX_BIR, off & ~PCI_MSIX_BIR);
1571c7a34993SMartin Mares off = get_conf_long(d, where + PCI_MSIX_PBA);
1572c7a34993SMartin Mares printf("\t\tPBA: BAR=%d offset=%08x\n",
1573c7a34993SMartin Mares off & PCI_MSIX_BIR, off & ~PCI_MSIX_BIR);
1574c7a34993SMartin Mares }
1575c7a34993SMartin Mares
1576c7a34993SMartin Mares static void
cap_slotid(int cap)1577c7a34993SMartin Mares cap_slotid(int cap)
1578c7a34993SMartin Mares {
1579c7a34993SMartin Mares int esr = cap & 0xff;
1580c7a34993SMartin Mares int chs = cap >> 8;
1581c7a34993SMartin Mares
1582c7a34993SMartin Mares printf("Slot ID: %d slots, First%c, chassis %02x\n",
1583c7a34993SMartin Mares esr & PCI_SID_ESR_NSLOTS,
1584c7a34993SMartin Mares FLAG(esr, PCI_SID_ESR_FIC),
1585c7a34993SMartin Mares chs);
1586c7a34993SMartin Mares }
1587c7a34993SMartin Mares
1588c7a34993SMartin Mares static void
cap_ssvid(struct device * d,int where)1589c7a34993SMartin Mares cap_ssvid(struct device *d, int where)
1590c7a34993SMartin Mares {
1591c7a34993SMartin Mares u16 subsys_v, subsys_d;
1592c7a34993SMartin Mares char ssnamebuf[256];
1593c7a34993SMartin Mares
1594c7a34993SMartin Mares if (!config_fetch(d, where, 8))
1595c7a34993SMartin Mares return;
1596c7a34993SMartin Mares subsys_v = get_conf_word(d, where + PCI_SSVID_VENDOR);
1597c7a34993SMartin Mares subsys_d = get_conf_word(d, where + PCI_SSVID_DEVICE);
1598c7a34993SMartin Mares printf("Subsystem: %s\n",
1599c7a34993SMartin Mares pci_lookup_name(pacc, ssnamebuf, sizeof(ssnamebuf),
1600c7a34993SMartin Mares PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
1601c7a34993SMartin Mares d->dev->vendor_id, d->dev->device_id, subsys_v, subsys_d));
1602c7a34993SMartin Mares }
1603c7a34993SMartin Mares
1604c7a34993SMartin Mares static void
cap_debug_port(int cap)1605c7a34993SMartin Mares cap_debug_port(int cap)
1606c7a34993SMartin Mares {
1607c7a34993SMartin Mares int bar = cap >> 13;
1608c7a34993SMartin Mares int pos = cap & 0x1fff;
1609c7a34993SMartin Mares printf("Debug port: BAR=%d offset=%04x\n", bar, pos);
1610c7a34993SMartin Mares }
1611c7a34993SMartin Mares
161299eb76e5SYu Zhao static void
cap_af(struct device * d,int where)161399eb76e5SYu Zhao cap_af(struct device *d, int where)
161499eb76e5SYu Zhao {
161599eb76e5SYu Zhao u8 reg;
161699eb76e5SYu Zhao
161799eb76e5SYu Zhao printf("PCI Advanced Features\n");
161899eb76e5SYu Zhao if (verbose < 2 || !config_fetch(d, where + PCI_AF_CAP, 3))
161999eb76e5SYu Zhao return;
162099eb76e5SYu Zhao
162199eb76e5SYu Zhao reg = get_conf_byte(d, where + PCI_AF_CAP);
162299eb76e5SYu Zhao printf("\t\tAFCap: TP%c FLR%c\n", FLAG(reg, PCI_AF_CAP_TP),
162399eb76e5SYu Zhao FLAG(reg, PCI_AF_CAP_FLR));
162499eb76e5SYu Zhao reg = get_conf_byte(d, where + PCI_AF_CTRL);
162599eb76e5SYu Zhao printf("\t\tAFCtrl: FLR%c\n", FLAG(reg, PCI_AF_CTRL_FLR));
162699eb76e5SYu Zhao reg = get_conf_byte(d, where + PCI_AF_STATUS);
162799eb76e5SYu Zhao printf("\t\tAFStatus: TP%c\n", FLAG(reg, PCI_AF_STATUS_TP));
162899eb76e5SYu Zhao }
162999eb76e5SYu Zhao
1630be9c1b75SMartin Mares static void
cap_sata_hba(struct device * d,int where,int cap)1631be9c1b75SMartin Mares cap_sata_hba(struct device *d, int where, int cap)
1632be9c1b75SMartin Mares {
1633be9c1b75SMartin Mares u32 bars;
1634be9c1b75SMartin Mares int bar;
1635be9c1b75SMartin Mares
1636be9c1b75SMartin Mares printf("SATA HBA v%d.%d", BITS(cap, 4, 4), BITS(cap, 0, 4));
1637be9c1b75SMartin Mares if (verbose < 2 || !config_fetch(d, where + PCI_SATA_HBA_BARS, 4))
1638be9c1b75SMartin Mares {
1639be9c1b75SMartin Mares printf("\n");
1640be9c1b75SMartin Mares return;
1641be9c1b75SMartin Mares }
1642be9c1b75SMartin Mares
1643be9c1b75SMartin Mares bars = get_conf_long(d, where + PCI_SATA_HBA_BARS);
1644be9c1b75SMartin Mares bar = BITS(bars, 0, 4);
1645be9c1b75SMartin Mares if (bar >= 4 && bar <= 9)
1646be9c1b75SMartin Mares printf(" BAR%d Offset=%08x\n", bar - 4, BITS(bars, 4, 20));
1647be9c1b75SMartin Mares else if (bar == 15)
1648be9c1b75SMartin Mares printf(" InCfgSpace\n");
1649be9c1b75SMartin Mares else
1650be9c1b75SMartin Mares printf(" BAR??%d\n", bar);
1651be9c1b75SMartin Mares }
1652be9c1b75SMartin Mares
cap_ea_property(int p,int is_secondary)16534cd841dfSDavid Daney static const char *cap_ea_property(int p, int is_secondary)
16544cd841dfSDavid Daney {
16554cd841dfSDavid Daney switch (p) {
16564cd841dfSDavid Daney case 0x00:
16574cd841dfSDavid Daney return "memory space, non-prefetchable";
16584cd841dfSDavid Daney case 0x01:
16594cd841dfSDavid Daney return "memory space, prefetchable";
16604cd841dfSDavid Daney case 0x02:
16614cd841dfSDavid Daney return "I/O space";
16624cd841dfSDavid Daney case 0x03:
16634cd841dfSDavid Daney return "VF memory space, prefetchable";
16644cd841dfSDavid Daney case 0x04:
16654cd841dfSDavid Daney return "VF memory space, non-prefetchable";
16664cd841dfSDavid Daney case 0x05:
16674cd841dfSDavid Daney return "allocation behind bridge, non-prefetchable memory";
16684cd841dfSDavid Daney case 0x06:
16694cd841dfSDavid Daney return "allocation behind bridge, prefetchable memory";
16704cd841dfSDavid Daney case 0x07:
16714cd841dfSDavid Daney return "allocation behind bridge, I/O space";
16724cd841dfSDavid Daney case 0xfd:
16734cd841dfSDavid Daney return "memory space resource unavailable for use";
16744cd841dfSDavid Daney case 0xfe:
16754cd841dfSDavid Daney return "I/O space resource unavailable for use";
16764cd841dfSDavid Daney case 0xff:
16774cd841dfSDavid Daney if (is_secondary)
16784cd841dfSDavid Daney return "entry unavailable for use, PrimaryProperties should be used";
16794cd841dfSDavid Daney else
16804cd841dfSDavid Daney return "entry unavailable for use";
16814cd841dfSDavid Daney default:
16824cd841dfSDavid Daney return NULL;
16834cd841dfSDavid Daney }
16844cd841dfSDavid Daney }
16854cd841dfSDavid Daney
cap_ea(struct device * d,int where,int cap)16864cd841dfSDavid Daney static void cap_ea(struct device *d, int where, int cap)
16874cd841dfSDavid Daney {
16884cd841dfSDavid Daney int entry;
16894cd841dfSDavid Daney int entry_base = where + 4;
16904cd841dfSDavid Daney int num_entries = BITS(cap, 0, 6);
16914cd841dfSDavid Daney u8 htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
16924cd841dfSDavid Daney
16934cd841dfSDavid Daney printf("Enhanced Allocation (EA): NumEntries=%u", num_entries);
16944cd841dfSDavid Daney if (htype == PCI_HEADER_TYPE_BRIDGE) {
16954cd841dfSDavid Daney byte fixed_sub, fixed_sec;
16964cd841dfSDavid Daney
16974cd841dfSDavid Daney entry_base += 4;
16984cd841dfSDavid Daney if (!config_fetch(d, where + 4, 2)) {
16994cd841dfSDavid Daney printf("\n");
17004cd841dfSDavid Daney return;
17014cd841dfSDavid Daney }
17024cd841dfSDavid Daney fixed_sec = get_conf_byte(d, where + PCI_EA_CAP_TYPE1_SECONDARY);
17034cd841dfSDavid Daney fixed_sub = get_conf_byte(d, where + PCI_EA_CAP_TYPE1_SUBORDINATE);
17044cd841dfSDavid Daney printf(", secondary=%d, subordinate=%d", fixed_sec, fixed_sub);
17054cd841dfSDavid Daney }
17064cd841dfSDavid Daney printf("\n");
17074cd841dfSDavid Daney if (verbose < 2)
17084cd841dfSDavid Daney return;
17094cd841dfSDavid Daney
17104cd841dfSDavid Daney for (entry = 0; entry < num_entries; entry++) {
17114cd841dfSDavid Daney int max_offset_high_pos, has_base_high, has_max_offset_high;
17124cd841dfSDavid Daney u32 entry_header;
17134cd841dfSDavid Daney u32 base, max_offset;
17144cd841dfSDavid Daney int es, bei, pp, sp;
17154cd841dfSDavid Daney const char *prop_text;
17164cd841dfSDavid Daney
17174cd841dfSDavid Daney if (!config_fetch(d, entry_base, 4))
17184cd841dfSDavid Daney return;
17194cd841dfSDavid Daney entry_header = get_conf_long(d, entry_base);
17204cd841dfSDavid Daney es = BITS(entry_header, 0, 3);
17214cd841dfSDavid Daney bei = BITS(entry_header, 4, 4);
17224cd841dfSDavid Daney pp = BITS(entry_header, 8, 8);
17234cd841dfSDavid Daney sp = BITS(entry_header, 16, 8);
17244cd841dfSDavid Daney if (!config_fetch(d, entry_base + 4, es * 4))
17254cd841dfSDavid Daney return;
17264cd841dfSDavid Daney printf("\t\tEntry %u: Enable%c Writable%c EntrySize=%u\n", entry,
17274cd841dfSDavid Daney FLAG(entry_header, PCI_EA_CAP_ENT_ENABLE),
17284cd841dfSDavid Daney FLAG(entry_header, PCI_EA_CAP_ENT_WRITABLE), es);
17294cd841dfSDavid Daney printf("\t\t\t BAR Equivalent Indicator: ");
17304cd841dfSDavid Daney switch (bei) {
17314cd841dfSDavid Daney case 0:
17324cd841dfSDavid Daney case 1:
17334cd841dfSDavid Daney case 2:
17344cd841dfSDavid Daney case 3:
17354cd841dfSDavid Daney case 4:
17364cd841dfSDavid Daney case 5:
17374cd841dfSDavid Daney printf("BAR %u", bei);
17384cd841dfSDavid Daney break;
17394cd841dfSDavid Daney case 6:
17404cd841dfSDavid Daney printf("resource behind function");
17414cd841dfSDavid Daney break;
17424cd841dfSDavid Daney case 7:
17434cd841dfSDavid Daney printf("not indicated");
17444cd841dfSDavid Daney break;
17454cd841dfSDavid Daney case 8:
17464cd841dfSDavid Daney printf("expansion ROM");
17474cd841dfSDavid Daney break;
17484cd841dfSDavid Daney case 9:
17494cd841dfSDavid Daney case 10:
17504cd841dfSDavid Daney case 11:
17514cd841dfSDavid Daney case 12:
17524cd841dfSDavid Daney case 13:
17534cd841dfSDavid Daney case 14:
17544cd841dfSDavid Daney printf("VF-BAR %u", bei - 9);
17554cd841dfSDavid Daney break;
17564cd841dfSDavid Daney default:
17574cd841dfSDavid Daney printf("reserved");
17584cd841dfSDavid Daney break;
17594cd841dfSDavid Daney }
17604cd841dfSDavid Daney printf("\n");
17614cd841dfSDavid Daney
17624cd841dfSDavid Daney prop_text = cap_ea_property(pp, 0);
17634cd841dfSDavid Daney printf("\t\t\t PrimaryProperties: ");
17644cd841dfSDavid Daney if (prop_text)
17654cd841dfSDavid Daney printf("%s\n", prop_text);
17664cd841dfSDavid Daney else
17674cd841dfSDavid Daney printf("[%02x]\n", pp);
17684cd841dfSDavid Daney
17694cd841dfSDavid Daney prop_text = cap_ea_property(sp, 1);
17704cd841dfSDavid Daney printf("\t\t\t SecondaryProperties: ");
17714cd841dfSDavid Daney if (prop_text)
17724cd841dfSDavid Daney printf("%s\n", prop_text);
17734cd841dfSDavid Daney else
17744cd841dfSDavid Daney printf("[%02x]\n", sp);
17754cd841dfSDavid Daney
17764cd841dfSDavid Daney base = get_conf_long(d, entry_base + 4);
17774cd841dfSDavid Daney has_base_high = ((base & 2) != 0);
17784cd841dfSDavid Daney base &= ~3;
17794cd841dfSDavid Daney
17804cd841dfSDavid Daney max_offset = get_conf_long(d, entry_base + 8);
17814cd841dfSDavid Daney has_max_offset_high = ((max_offset & 2) != 0);
17824cd841dfSDavid Daney max_offset |= 3;
17834cd841dfSDavid Daney max_offset_high_pos = entry_base + 12;
17844cd841dfSDavid Daney
17854cd841dfSDavid Daney printf("\t\t\t Base: ");
17864cd841dfSDavid Daney if (has_base_high) {
17874cd841dfSDavid Daney u32 base_high = get_conf_long(d, entry_base + 12);
17884cd841dfSDavid Daney
17894cd841dfSDavid Daney printf("%x", base_high);
17904cd841dfSDavid Daney max_offset_high_pos += 4;
17914cd841dfSDavid Daney }
17924cd841dfSDavid Daney printf("%08x\n", base);
17934cd841dfSDavid Daney
17944cd841dfSDavid Daney printf("\t\t\t MaxOffset: ");
17954cd841dfSDavid Daney if (has_max_offset_high) {
17964cd841dfSDavid Daney u32 max_offset_high = get_conf_long(d, max_offset_high_pos);
17974cd841dfSDavid Daney
17984cd841dfSDavid Daney printf("%x", max_offset_high);
17994cd841dfSDavid Daney }
18004cd841dfSDavid Daney printf("%08x\n", max_offset);
18014cd841dfSDavid Daney
18024cd841dfSDavid Daney entry_base += 4 + 4 * es;
18034cd841dfSDavid Daney }
18044cd841dfSDavid Daney }
18054cd841dfSDavid Daney
1806c7a34993SMartin Mares void
show_caps(struct device * d,int where)180721510591SMatthew Wilcox show_caps(struct device *d, int where)
1808c7a34993SMartin Mares {
1809c7a34993SMartin Mares int can_have_ext_caps = 0;
1810a1492b88SBjorn Helgaas int type = -1;
1811c7a34993SMartin Mares
1812c7a34993SMartin Mares if (get_conf_word(d, PCI_STATUS) & PCI_STATUS_CAP_LIST)
1813c7a34993SMartin Mares {
1814c7a34993SMartin Mares byte been_there[256];
181501de4db1SFrançois Revol where = get_conf_byte(d, where) & ~3;
1816c7a34993SMartin Mares memset(been_there, 0, 256);
1817c7a34993SMartin Mares while (where)
1818c7a34993SMartin Mares {
1819c7a34993SMartin Mares int id, next, cap;
1820c7a34993SMartin Mares printf("\tCapabilities: ");
1821c7a34993SMartin Mares if (!config_fetch(d, where, 4))
1822c7a34993SMartin Mares {
1823c7a34993SMartin Mares puts("<access denied>");
1824c7a34993SMartin Mares break;
1825c7a34993SMartin Mares }
1826c7a34993SMartin Mares id = get_conf_byte(d, where + PCI_CAP_LIST_ID);
1827c7a34993SMartin Mares next = get_conf_byte(d, where + PCI_CAP_LIST_NEXT) & ~3;
1828c7a34993SMartin Mares cap = get_conf_word(d, where + PCI_CAP_FLAGS);
1829c7a34993SMartin Mares printf("[%02x] ", where);
1830c7a34993SMartin Mares if (been_there[where]++)
1831c7a34993SMartin Mares {
1832c7a34993SMartin Mares printf("<chain looped>\n");
1833c7a34993SMartin Mares break;
1834c7a34993SMartin Mares }
1835c7a34993SMartin Mares if (id == 0xff)
1836c7a34993SMartin Mares {
1837c7a34993SMartin Mares printf("<chain broken>\n");
1838c7a34993SMartin Mares break;
1839c7a34993SMartin Mares }
1840c7a34993SMartin Mares switch (id)
1841c7a34993SMartin Mares {
1842c508d1c9SBjorn Helgaas case PCI_CAP_ID_NULL:
1843c508d1c9SBjorn Helgaas printf("Null\n");
1844c508d1c9SBjorn Helgaas break;
1845c7a34993SMartin Mares case PCI_CAP_ID_PM:
1846c7a34993SMartin Mares cap_pm(d, where, cap);
1847c7a34993SMartin Mares break;
1848c7a34993SMartin Mares case PCI_CAP_ID_AGP:
1849c7a34993SMartin Mares cap_agp(d, where, cap);
1850c7a34993SMartin Mares break;
1851c7a34993SMartin Mares case PCI_CAP_ID_VPD:
1852c7a34993SMartin Mares cap_vpd(d);
1853c7a34993SMartin Mares break;
1854c7a34993SMartin Mares case PCI_CAP_ID_SLOTID:
1855c7a34993SMartin Mares cap_slotid(cap);
1856c7a34993SMartin Mares break;
1857c7a34993SMartin Mares case PCI_CAP_ID_MSI:
1858c7a34993SMartin Mares cap_msi(d, where, cap);
1859c7a34993SMartin Mares break;
1860c7a34993SMartin Mares case PCI_CAP_ID_CHSWP:
1861c7a34993SMartin Mares printf("CompactPCI hot-swap <?>\n");
1862c7a34993SMartin Mares break;
1863c7a34993SMartin Mares case PCI_CAP_ID_PCIX:
1864c7a34993SMartin Mares cap_pcix(d, where);
1865c7a34993SMartin Mares can_have_ext_caps = 1;
1866c7a34993SMartin Mares break;
1867c7a34993SMartin Mares case PCI_CAP_ID_HT:
1868c7a34993SMartin Mares cap_ht(d, where, cap);
1869c7a34993SMartin Mares break;
1870c7a34993SMartin Mares case PCI_CAP_ID_VNDR:
18717ff8a323SGerd Hoffmann show_vendor_caps(d, where, cap);
1872c7a34993SMartin Mares break;
1873c7a34993SMartin Mares case PCI_CAP_ID_DBG:
1874c7a34993SMartin Mares cap_debug_port(cap);
1875c7a34993SMartin Mares break;
1876c7a34993SMartin Mares case PCI_CAP_ID_CCRC:
1877c7a34993SMartin Mares printf("CompactPCI central resource control <?>\n");
1878c7a34993SMartin Mares break;
1879c7a34993SMartin Mares case PCI_CAP_ID_HOTPLUG:
1880c7a34993SMartin Mares printf("Hot-plug capable\n");
1881c7a34993SMartin Mares break;
1882c7a34993SMartin Mares case PCI_CAP_ID_SSVID:
1883c7a34993SMartin Mares cap_ssvid(d, where);
1884c7a34993SMartin Mares break;
1885c7a34993SMartin Mares case PCI_CAP_ID_AGP3:
1886c7a34993SMartin Mares printf("AGP3 <?>\n");
1887c7a34993SMartin Mares break;
1888c7a34993SMartin Mares case PCI_CAP_ID_SECURE:
1889c7a34993SMartin Mares printf("Secure device <?>\n");
1890c7a34993SMartin Mares break;
1891c7a34993SMartin Mares case PCI_CAP_ID_EXP:
1892a1492b88SBjorn Helgaas type = cap_express(d, where, cap);
1893c7a34993SMartin Mares can_have_ext_caps = 1;
1894c7a34993SMartin Mares break;
1895c7a34993SMartin Mares case PCI_CAP_ID_MSIX:
1896c7a34993SMartin Mares cap_msix(d, where, cap);
1897c7a34993SMartin Mares break;
1898c7a34993SMartin Mares case PCI_CAP_ID_SATA:
1899be9c1b75SMartin Mares cap_sata_hba(d, where, cap);
1900c7a34993SMartin Mares break;
1901c7a34993SMartin Mares case PCI_CAP_ID_AF:
190299eb76e5SYu Zhao cap_af(d, where);
1903c7a34993SMartin Mares break;
19044cd841dfSDavid Daney case PCI_CAP_ID_EA:
19054cd841dfSDavid Daney cap_ea(d, where, cap);
19064cd841dfSDavid Daney break;
1907c7a34993SMartin Mares default:
190860a45a7eSBjorn Helgaas printf("Capability ID %#02x [%04x]\n", id, cap);
1909c7a34993SMartin Mares }
1910c7a34993SMartin Mares where = next;
1911c7a34993SMartin Mares }
1912c7a34993SMartin Mares }
1913c7a34993SMartin Mares if (can_have_ext_caps)
1914a1492b88SBjorn Helgaas show_ext_caps(d, type);
1915c7a34993SMartin Mares }
1916