]> mj.ucw.cz Git - pciutils.git/blob - ls-caps-vendor.c
lspci: add VirtIO SharedMemory capability support
[pciutils.git] / ls-caps-vendor.c
1 /*
2  *      The PCI Utilities -- Show Vendor-specific Capabilities
3  *
4  *      Copyright (c) 2014 Gerd Hoffmann <kraxel@redhat.com>
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
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=%016lx size=%016lx 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
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
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
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 }