]>
Commit | Line | Data |
---|---|---|
c7a34993 MM |
1 | /* |
2 | * The PCI Utilities -- Show Extended Capabilities | |
3 | * | |
4 | * Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz> | |
5 | * | |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
9 | #include <stdio.h> | |
10 | #include <string.h> | |
11 | ||
12 | #include "lspci.h" | |
13 | ||
14 | static void | |
15 | cap_dsn(struct device *d, int where) | |
16 | { | |
17 | u32 t1, t2; | |
18 | if (!config_fetch(d, where + 4, 8)) | |
19 | return; | |
20 | t1 = get_conf_long(d, where + 4); | |
21 | t2 = get_conf_long(d, where + 8); | |
22 | printf("Device Serial Number %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", | |
23 | t1 & 0xff, (t1 >> 8) & 0xff, (t1 >> 16) & 0xff, t1 >> 24, | |
24 | t2 & 0xff, (t2 >> 8) & 0xff, (t2 >> 16) & 0xff, t2 >> 24); | |
25 | } | |
26 | ||
27 | static void | |
28 | cap_aer(struct device *d, int where) | |
29 | { | |
30 | u32 l; | |
31 | ||
32 | printf("Advanced Error Reporting\n"); | |
33 | if (!config_fetch(d, where + PCI_ERR_UNCOR_STATUS, 24)) | |
34 | return; | |
35 | ||
36 | l = get_conf_long(d, where + PCI_ERR_UNCOR_STATUS); | |
37 | printf("\t\tUESta:\tDLP%c SDES%c TLP%c FCP%c CmpltTO%c CmpltAbrt%c UnxCmplt%c RxOF%c " | |
38 | "MalfTLP%c ECRC%c UnsupReq%c ACSViol%c\n", | |
39 | FLAG(l, PCI_ERR_UNC_DLP), FLAG(l, PCI_ERR_UNC_SDES), FLAG(l, PCI_ERR_UNC_POISON_TLP), | |
40 | FLAG(l, PCI_ERR_UNC_FCP), FLAG(l, PCI_ERR_UNC_COMP_TIME), FLAG(l, PCI_ERR_UNC_COMP_ABORT), | |
41 | FLAG(l, PCI_ERR_UNC_UNX_COMP), FLAG(l, PCI_ERR_UNC_RX_OVER), FLAG(l, PCI_ERR_UNC_MALF_TLP), | |
42 | FLAG(l, PCI_ERR_UNC_ECRC), FLAG(l, PCI_ERR_UNC_UNSUP), FLAG(l, PCI_ERR_UNC_ACS_VIOL)); | |
43 | l = get_conf_long(d, where + PCI_ERR_UNCOR_MASK); | |
44 | printf("\t\tUEMsk:\tDLP%c SDES%c TLP%c FCP%c CmpltTO%c CmpltAbrt%c UnxCmplt%c RxOF%c " | |
45 | "MalfTLP%c ECRC%c UnsupReq%c ACSViol%c\n", | |
46 | FLAG(l, PCI_ERR_UNC_DLP), FLAG(l, PCI_ERR_UNC_SDES), FLAG(l, PCI_ERR_UNC_POISON_TLP), | |
47 | FLAG(l, PCI_ERR_UNC_FCP), FLAG(l, PCI_ERR_UNC_COMP_TIME), FLAG(l, PCI_ERR_UNC_COMP_ABORT), | |
48 | FLAG(l, PCI_ERR_UNC_UNX_COMP), FLAG(l, PCI_ERR_UNC_RX_OVER), FLAG(l, PCI_ERR_UNC_MALF_TLP), | |
49 | FLAG(l, PCI_ERR_UNC_ECRC), FLAG(l, PCI_ERR_UNC_UNSUP), FLAG(l, PCI_ERR_UNC_ACS_VIOL)); | |
50 | l = get_conf_long(d, where + PCI_ERR_UNCOR_SEVER); | |
51 | printf("\t\tUESvrt:\tDLP%c SDES%c TLP%c FCP%c CmpltTO%c CmpltAbrt%c UnxCmplt%c RxOF%c " | |
52 | "MalfTLP%c ECRC%c UnsupReq%c ACSViol%c\n", | |
53 | FLAG(l, PCI_ERR_UNC_DLP), FLAG(l, PCI_ERR_UNC_SDES), FLAG(l, PCI_ERR_UNC_POISON_TLP), | |
54 | FLAG(l, PCI_ERR_UNC_FCP), FLAG(l, PCI_ERR_UNC_COMP_TIME), FLAG(l, PCI_ERR_UNC_COMP_ABORT), | |
55 | FLAG(l, PCI_ERR_UNC_UNX_COMP), FLAG(l, PCI_ERR_UNC_RX_OVER), FLAG(l, PCI_ERR_UNC_MALF_TLP), | |
56 | FLAG(l, PCI_ERR_UNC_ECRC), FLAG(l, PCI_ERR_UNC_UNSUP), FLAG(l, PCI_ERR_UNC_ACS_VIOL)); | |
57 | l = get_conf_long(d, where + PCI_ERR_COR_STATUS); | |
58 | printf("\t\tCESta:\tRxErr%c BadTLP%c BadDLLP%c Rollover%c Timeout%c NonFatalErr%c\n", | |
59 | FLAG(l, PCI_ERR_COR_RCVR), FLAG(l, PCI_ERR_COR_BAD_TLP), FLAG(l, PCI_ERR_COR_BAD_DLLP), | |
60 | FLAG(l, PCI_ERR_COR_REP_ROLL), FLAG(l, PCI_ERR_COR_REP_TIMER), FLAG(l, PCI_ERR_COR_REP_ANFE)); | |
61 | l = get_conf_long(d, where + PCI_ERR_COR_MASK); | |
62 | printf("\t\tCEMsk:\tRxErr%c BadTLP%c BadDLLP%c Rollover%c Timeout%c NonFatalErr%c\n", | |
63 | FLAG(l, PCI_ERR_COR_RCVR), FLAG(l, PCI_ERR_COR_BAD_TLP), FLAG(l, PCI_ERR_COR_BAD_DLLP), | |
64 | FLAG(l, PCI_ERR_COR_REP_ROLL), FLAG(l, PCI_ERR_COR_REP_TIMER), FLAG(l, PCI_ERR_COR_REP_ANFE)); | |
65 | l = get_conf_long(d, where + PCI_ERR_CAP); | |
66 | printf("\t\tAERCap:\tFirst Error Pointer: %02x, GenCap%c CGenEn%c ChkCap%c ChkEn%c\n", | |
67 | PCI_ERR_CAP_FEP(l), FLAG(l, PCI_ERR_CAP_ECRC_GENC), FLAG(l, PCI_ERR_CAP_ECRC_GENE), | |
68 | FLAG(l, PCI_ERR_CAP_ECRC_CHKC), FLAG(l, PCI_ERR_CAP_ECRC_CHKE)); | |
69 | ||
70 | } | |
71 | ||
72 | static void | |
73 | cap_acs(struct device *d, int where) | |
74 | { | |
75 | u16 w; | |
76 | ||
77 | printf("Access Control Services\n"); | |
78 | if (!config_fetch(d, where + PCI_ACS_CAP, 4)) | |
79 | return; | |
80 | ||
81 | w = get_conf_word(d, where + PCI_ACS_CAP); | |
82 | printf("\t\tACSCap:\tSrcValid%c TransBlk%c ReqRedir%c CmpltRedir%c UpstreamFwd%c EgressCtrl%c " | |
83 | "DirectTrans%c\n", | |
84 | FLAG(w, PCI_ACS_CAP_VALID), FLAG(w, PCI_ACS_CAP_BLOCK), FLAG(w, PCI_ACS_CAP_REQ_RED), | |
85 | FLAG(w, PCI_ACS_CAP_CMPLT_RED), FLAG(w, PCI_ACS_CAP_FORWARD), FLAG(w, PCI_ACS_CAP_EGRESS), | |
86 | FLAG(w, PCI_ACS_CAP_TRANS)); | |
87 | w = get_conf_word(d, where + PCI_ACS_CTRL); | |
88 | printf("\t\tACSCtl:\tSrcValid%c TransBlk%c ReqRedir%c CmpltRedir%c UpstreamFwd%c EgressCtrl%c " | |
89 | "DirectTrans%c\n", | |
90 | FLAG(w, PCI_ACS_CTRL_VALID), FLAG(w, PCI_ACS_CTRL_BLOCK), FLAG(w, PCI_ACS_CTRL_REQ_RED), | |
91 | FLAG(w, PCI_ACS_CTRL_CMPLT_RED), FLAG(w, PCI_ACS_CTRL_FORWARD), FLAG(w, PCI_ACS_CTRL_EGRESS), | |
92 | FLAG(w, PCI_ACS_CTRL_TRANS)); | |
93 | } | |
94 | ||
95 | static void | |
96 | cap_ari(struct device *d, int where) | |
97 | { | |
98 | u16 w; | |
99 | ||
100 | printf("Alternative Routing-ID Interpretation (ARI)\n"); | |
101 | if (!config_fetch(d, where + PCI_ARI_CAP, 4)) | |
102 | return; | |
103 | ||
104 | w = get_conf_word(d, where + PCI_ARI_CAP); | |
105 | printf("\t\tARICap:\tMFVC%c ACS%c, Next Function: %d\n", | |
106 | FLAG(w, PCI_ARI_CAP_MFVC), FLAG(w, PCI_ARI_CAP_ACS), | |
107 | PCI_ARI_CAP_NFN(w)); | |
108 | w = get_conf_word(d, where + PCI_ARI_CTRL); | |
109 | printf("\t\tARICtl:\tMFVC%c ACS%c, Function Group: %d\n", | |
110 | FLAG(w, PCI_ARI_CTRL_MFVC), FLAG(w, PCI_ARI_CTRL_ACS), | |
111 | PCI_ARI_CTRL_FG(w)); | |
112 | } | |
113 | ||
114 | static void | |
115 | cap_ats(struct device *d, int where) | |
116 | { | |
117 | u16 w; | |
118 | ||
119 | printf("Address Translation Service (ATS)\n"); | |
120 | if (!config_fetch(d, where + PCI_ATS_CAP, 4)) | |
121 | return; | |
122 | ||
123 | w = get_conf_word(d, where + PCI_ATS_CAP); | |
124 | printf("\t\tATSCap:\tInvalidate Queue Depth: %02x\n", PCI_ATS_CAP_IQD(w)); | |
125 | w = get_conf_word(d, where + PCI_ATS_CTRL); | |
126 | printf("\t\tATSCtl:\tEnable%c, Smallest Translation Unit: %02x\n", | |
127 | FLAG(w, PCI_ATS_CTRL_ENABLE), PCI_ATS_CTRL_STU(w)); | |
128 | } | |
129 | ||
130 | static void | |
131 | cap_sriov(struct device *d, int where) | |
132 | { | |
133 | u16 b; | |
134 | u16 w; | |
135 | u32 l; | |
136 | ||
137 | printf("Single Root I/O Virtualization (SR-IOV)\n"); | |
138 | if (!config_fetch(d, where + PCI_IOV_CAP, 0x3c)) | |
139 | return; | |
140 | ||
141 | l = get_conf_long(d, where + PCI_IOV_CAP); | |
142 | printf("\t\tIOVCap:\tMigration%c, Interrupt Message Number: %03x\n", | |
143 | FLAG(l, PCI_IOV_CAP_VFM), PCI_IOV_CAP_IMN(l)); | |
144 | w = get_conf_word(d, where + PCI_IOV_CTRL); | |
145 | printf("\t\tIOVCtl:\tEnable%c Migration%c Interrupt%c MSE%c ARIHierarchy%c\n", | |
146 | FLAG(w, PCI_IOV_CTRL_VFE), FLAG(w, PCI_IOV_CTRL_VFME), | |
147 | FLAG(w, PCI_IOV_CTRL_VFMIE), FLAG(w, PCI_IOV_CTRL_MSE), | |
148 | FLAG(w, PCI_IOV_CTRL_ARI)); | |
149 | w = get_conf_word(d, where + PCI_IOV_STATUS); | |
150 | printf("\t\tIOVSta:\tMigration%c\n", FLAG(w, PCI_IOV_STATUS_MS)); | |
151 | w = get_conf_word(d, where + PCI_IOV_INITIALVF); | |
152 | printf("\t\tInitial VFs: %d, ", w); | |
153 | w = get_conf_word(d, where + PCI_IOV_TOTALVF); | |
154 | printf("Total VFs: %d, ", w); | |
155 | w = get_conf_word(d, where + PCI_IOV_NUMVF); | |
156 | printf("Number of VFs: %d, ", w); | |
157 | b = get_conf_byte(d, where + PCI_IOV_FDL); | |
158 | printf("Function Dependency Link: %02x\n", b); | |
159 | w = get_conf_word(d, where + PCI_IOV_OFFSET); | |
160 | printf("\t\tVF offset: %d, ", w); | |
161 | w = get_conf_word(d, where + PCI_IOV_STRIDE); | |
162 | printf("stride: %d, ", w); | |
163 | w = get_conf_word(d, where + PCI_IOV_DID); | |
164 | printf("Device ID: %04x\n", w); | |
165 | l = get_conf_long(d, where + PCI_IOV_SUPPS); | |
166 | printf("\t\tSupported Page Size: %08x, ", l); | |
167 | l = get_conf_long(d, where + PCI_IOV_SYSPS); | |
168 | printf("System Page Size: %08x\n", l); | |
169 | printf("\t\tVF Migration: offset: %08x, BIR: %x\n", PCI_IOV_MSA_OFFSET(l), | |
170 | PCI_IOV_MSA_BIR(l)); | |
171 | } | |
172 | ||
173 | void | |
174 | show_ext_caps(struct device *d) | |
175 | { | |
176 | int where = 0x100; | |
177 | char been_there[0x1000]; | |
178 | memset(been_there, 0, 0x1000); | |
179 | do | |
180 | { | |
181 | u32 header; | |
182 | int id; | |
183 | ||
184 | if (!config_fetch(d, where, 4)) | |
185 | break; | |
186 | header = get_conf_long(d, where); | |
187 | if (!header) | |
188 | break; | |
189 | id = header & 0xffff; | |
190 | printf("\tCapabilities: [%03x] ", where); | |
191 | if (been_there[where]++) | |
192 | { | |
193 | printf("<chain looped>\n"); | |
194 | break; | |
195 | } | |
196 | switch (id) | |
197 | { | |
198 | case PCI_EXT_CAP_ID_AER: | |
199 | cap_aer(d, where); | |
200 | break; | |
201 | case PCI_EXT_CAP_ID_VC: | |
202 | printf("Virtual Channel <?>\n"); | |
203 | break; | |
204 | case PCI_EXT_CAP_ID_DSN: | |
205 | cap_dsn(d, where); | |
206 | break; | |
207 | case PCI_EXT_CAP_ID_PB: | |
208 | printf("Power Budgeting <?>\n"); | |
209 | break; | |
210 | case PCI_EXT_CAP_ID_RCLINK: | |
211 | printf("Root Complex Link <?>\n"); | |
212 | break; | |
213 | case PCI_EXT_CAP_ID_RCILINK: | |
214 | printf("Root Complex Internal Link <?>\n"); | |
215 | break; | |
216 | case PCI_EXT_CAP_ID_RCECOLL: | |
217 | printf("Root Complex Event Collector <?>\n"); | |
218 | break; | |
219 | case PCI_EXT_CAP_ID_MFVC: | |
220 | printf("Multi-Function Virtual Channel <?>\n"); | |
221 | break; | |
222 | case PCI_EXT_CAP_ID_RBCB: | |
223 | printf("Root Bridge Control Block <?>\n"); | |
224 | break; | |
225 | case PCI_EXT_CAP_ID_VNDR: | |
226 | printf("Vendor Specific Information <?>\n"); | |
227 | break; | |
228 | case PCI_EXT_CAP_ID_ACS: | |
229 | cap_acs(d, where); | |
230 | break; | |
231 | case PCI_EXT_CAP_ID_ARI: | |
232 | cap_ari(d, where); | |
233 | break; | |
234 | case PCI_EXT_CAP_ID_ATS: | |
235 | cap_ats(d, where); | |
236 | break; | |
237 | case PCI_EXT_CAP_ID_SRIOV: | |
238 | cap_sriov(d, where); | |
239 | break; | |
240 | default: | |
241 | printf("#%02x\n", id); | |
242 | break; | |
243 | } | |
244 | where = header >> 20; | |
245 | } while (where); | |
246 | } |