1 /*
2 * The PCI Utilities -- Show Vendor-specific Capabilities
3 *
4 * Copyright (c) 2014 Gerd Hoffmann <[email protected]>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL v2+.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include <stdio.h>
12 #include <string.h>
13
14 #include "lspci.h"
15
16 static int
show_vendor_caps_virtio(struct device * d,int where,int cap)17 show_vendor_caps_virtio(struct device *d, int where, int cap)
18 {
19 int length = BITS(cap, 0, 8);
20 int type = BITS(cap, 8, 8);
21 char *tname;
22 u32 offset;
23 u32 size;
24 u32 offset_hi;
25 u32 size_hi;
26
27 if (length < 16)
28 return 0;
29 if (!config_fetch(d, where, length))
30 return 0;
31
32 switch (type)
33 {
34 case 1:
35 tname = "CommonCfg";
36 break;
37 case 2:
38 tname = "Notify";
39 break;
40 case 3:
41 tname = "ISR";
42 break;
43 case 4:
44 tname = "DeviceCfg";
45 break;
46 case 8:
47 tname = "SharedMemory";
48 break;
49 default:
50 tname = "<unknown>";
51 break;
52 }
53
54 printf("VirtIO: %s\n", tname);
55
56 if (verbose < 2)
57 return 1;
58
59 offset = get_conf_long(d, where + 8);
60 size = get_conf_long(d, where + 12);
61 if (type != 8)
62 printf("\t\tBAR=%d offset=%08x size=%08x",
63 get_conf_byte(d, where + 4), offset, size);
64 else {
65 offset_hi = get_conf_long(d, where + 16);
66 size_hi = get_conf_long(d, where + 20);
67 printf("\t\tBAR=%d offset=%016" PCI_U64_FMT_X " size=%016" PCI_U64_FMT_X " id=%d",
68 get_conf_byte(d, where + 4),
69 (u64) offset | (u64) offset_hi << 32,
70 (u64) size | (u64) size_hi << 32,
71 get_conf_byte(d, where + 5));
72 }
73
74 if (type == 2 && length >= 20)
75 printf(" multiplier=%08x", get_conf_long(d, where+16));
76
77 printf("\n");
78 return 1;
79 }
80
81 static int
show_vendor_caps_intel(struct device * d,int where,int cap)82 show_vendor_caps_intel(struct device *d, int where, int cap)
83 {
84 int length = BITS(cap, 0, 8);
85 int version = BITS(cap, 8, 4);
86 int type = BITS(cap, 12, 4);
87 u32 l;
88
89 if (type == 0)
90 {
91 printf("Intel Capabilities v%d\n", version);
92 /*
93 * Intel Capabilities is used at least on Intel Host Bridge / DRAM Controller
94 * and Intel Integrated Graphics Controller. Format of the CAPID0_<X>
95 * registers parsed below matches Cap Version 1 which is used since second
96 * generation of the Intel Core processors (Sandy Bridge). Parsing of other
97 * versions is not currently supported.
98 */
99 if (version != 1)
100 return 1;
101 }
102 else if (type == 1)
103 {
104 printf("Intel Feature Detection\n");
105 /*
106 * Intel Feature Detection Capabilities is used on Intel LPC Controller.
107 * Capabilities are accessed indirectly by writing indirect capability
108 * register to PCI config space. Because lspci cannot write to PCI config
109 * space, it is not possible to read or parse Intel Feature Vector Space.
110 */
111 return 1;
112 }
113 else
114 {
115 printf("Intel <unknown>\n");
116 return 1;
117 }
118
119 if (!config_fetch(d, where, length))
120 return 0;
121
122 /* CAPID0_A */
123 if (length >= 8)
124 {
125 l = get_conf_long(d, where + 4);
126 printf("\t\tCapA:");
127 printf(" Peg60Dis%c", FLAG(l, BIT(31)));
128 printf(" Peg12Dis%c", FLAG(l, BIT(30)));
129 printf(" Peg11Dis%c", FLAG(l, BIT(29)));
130 printf(" Peg10Dis%c", FLAG(l, BIT(28)));
131 printf(" PeLWUDis%c", FLAG(l, BIT(27)));
132 printf(" DmiWidth=x%u", (l & BIT(26)) ? 2 : 4);
133 printf("\n\t\t ");
134 printf(" EccDis%c", FLAG(l, BIT(25)));
135 printf(" ForceEccEn%c", FLAG(l, BIT(24)));
136 printf(" VTdDis%c", FLAG(l, BIT(23)));
137 printf(" DmiG2Dis%c", FLAG(l, BIT(22)));
138 printf(" PegG2Dis%c", FLAG(l, BIT(21)));
139 printf(" DDRMaxSize=");
140 if (BITS(l, 19, 2) == 0)
141 printf("Unlimited");
142 else
143 printf("%gGB/chan", 512 * (1 << ((3-BITS(l, 19, 2))*2)) / 1024.0);
144 printf("\n\t\t ");
145 printf(" 1NDis%c", FLAG(l, BIT(17)));
146 printf(" CDDis%c", FLAG(l, BIT(15)));
147 printf(" DDPCDis%c", FLAG(l, BIT(14)));
148 printf(" X2APICEn%c", FLAG(l, BIT(13)));
149 printf(" PDCDis%c", FLAG(l, BIT(12)));
150 printf(" IGDis%c", FLAG(l, BIT(11)));
151 printf(" CDID=%u", BITS(l, 8, 2));
152 printf(" CRID=%u", BITS(l, 4, 4));
153 printf("\n\t\t ");
154 printf(" DDROCCAP%c", FLAG(l, BIT(3)));
155 printf(" OCEn%c", FLAG(l, BIT(2)));
156 printf(" DDRWrtVrefEn%c", FLAG(l, BIT(1)));
157 printf(" DDR3LEn%c", FLAG(l, BIT(0)));
158 printf("\n");
159 }
160
161 /* CAPID0_B */
162 if (length >= 12)
163 {
164 l = get_conf_long(d, where + 8);
165 printf("\t\tCapB:");
166 printf(" ImguDis%c", FLAG(l, BIT(31)));
167 printf(" OCbySSKUCap%c", FLAG(l, BIT(30)));
168 printf(" OCbySSKUEn%c", FLAG(l, BIT(29)));
169 printf(" SMTCap%c", FLAG(l, BIT(28)));
170 printf(" CacheSzCap 0x%x", BITS(l, 25, 3));
171 printf("\n\t\t ");
172 printf(" SoftBinCap%c", FLAG(l, BIT(24)));
173 printf(" DDR3MaxFreqWithRef100=");
174 if (BITS(l, 21, 3) == 0)
175 printf("Disabled");
176 else if (BITS(l, 21, 3) == 7)
177 printf("Unlimited");
178 else
179 printf("%uMHz", (6+BITS(l, 21, 3)) * 200);
180 printf(" PegG3Dis%c", FLAG(l, BIT(20)));
181 printf("\n\t\t ");
182 printf(" PkgTyp%c", FLAG(l, BIT(19)));
183 printf(" AddGfxEn%c", FLAG(l, BIT(18)));
184 printf(" AddGfxCap%c", FLAG(l, BIT(17)));
185 printf(" PegX16Dis%c", FLAG(l, BIT(16)));
186 printf(" DmiG3Dis%c", FLAG(l, BIT(15)));
187 printf(" GmmDis%c", FLAG(l, BIT(8)));
188 printf("\n\t\t ");
189 printf(" DDR3MaxFreq=%uMHz", (11-BITS(l, 4, 2)) * 2666 / 10);
190 printf(" LPDDR3En%c", FLAG(l, BIT(2)));
191 printf("\n");
192 }
193
194 /* CAPID0_C */
195 if (length >= 16)
196 {
197 l = get_conf_long(d, where + 12);
198 printf("\t\tCapC:");
199 printf(" PegG4Dis%c", FLAG(l, BIT(28)));
200 printf(" DDR4MaxFreq=");
201 if (BITS(l, 23, 4) == 0)
202 printf("Unlimited");
203 else
204 printf("%uMHz", BITS(l, 0, 4) * 2666 / 10);
205 printf(" LPDDREn%c", FLAG(l, BIT(22)));
206 printf(" LPDDR4MaxFreq=");
207 if (BITS(l, 17, 4) == 0)
208 printf("Unlimited");
209 else
210 printf("%uMHz", BITS(l, 0, 4) * 2666 / 10);
211 printf(" LPDDR4En%c", FLAG(l, BIT(16)));
212 printf("\n\t\t ");
213 printf(" QClkGvDis%c", FLAG(l, BIT(14)));
214 printf(" SgxDis%c", FLAG(l, BIT(9)));
215 printf(" BClkOC=%s", BITS(l, 7, 2) == 0 ? "Disabled" :
216 BITS(l, 7, 2) == 1 ? "115MHz" :
217 BITS(l, 7, 2) == 2 ? "130MHz" :
218 "Unlimited");
219 printf(" IddDis%c", FLAG(l, BIT(6)));
220 printf(" Pipe3Dis%c", FLAG(l, BIT(5)));
221 printf(" Gear1MaxFreq=");
222 if (BITS(l, 0, 4) == 0)
223 printf("Unlimited");
224 else
225 printf("%uMHz", BITS(l, 0, 4) * 2666 / 10);
226 printf("\n");
227 }
228
229 return 1;
230 }
231
232 static int
do_show_vendor_caps(struct device * d,int where,int cap)233 do_show_vendor_caps(struct device *d, int where, int cap)
234 {
235 switch (d->dev->vendor_id)
236 {
237 case 0x1af4: /* Red Hat */
238 if (d->dev->device_id >= 0x1000 &&
239 d->dev->device_id <= 0x107f)
240 return show_vendor_caps_virtio(d, where, cap);
241 break;
242 case 0x8086: /* Intel */
243 return show_vendor_caps_intel(d, where, cap);
244 }
245 return 0;
246 }
247
248 void
show_vendor_caps(struct device * d,int where,int cap)249 show_vendor_caps(struct device *d, int where, int cap)
250 {
251 printf("Vendor Specific Information: ");
252 if (!do_show_vendor_caps(d, where, cap))
253 printf("Len=%02x <?>\n", BITS(cap, 0, 8));
254 }
255