xref: /pciutils/ls-caps-vendor.c (revision b78c087b)
17ff8a323SGerd Hoffmann /*
27ff8a323SGerd Hoffmann  *	The PCI Utilities -- Show Vendor-specific Capabilities
37ff8a323SGerd Hoffmann  *
47ff8a323SGerd Hoffmann  *	Copyright (c) 2014 Gerd Hoffmann <[email protected]>
57ff8a323SGerd Hoffmann  *
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
97ff8a323SGerd Hoffmann  */
107ff8a323SGerd Hoffmann 
117ff8a323SGerd Hoffmann #include <stdio.h>
127ff8a323SGerd Hoffmann #include <string.h>
137ff8a323SGerd Hoffmann 
147ff8a323SGerd Hoffmann #include "lspci.h"
157ff8a323SGerd Hoffmann 
166ebebbaaSMartin Mares static int
show_vendor_caps_virtio(struct device * d,int where,int cap)177ff8a323SGerd Hoffmann show_vendor_caps_virtio(struct device *d, int where, int cap)
187ff8a323SGerd Hoffmann {
197ff8a323SGerd Hoffmann   int length = BITS(cap, 0, 8);
207ff8a323SGerd Hoffmann   int type = BITS(cap, 8, 8);
217ff8a323SGerd Hoffmann   char *tname;
221bfc2be0SChangyuan Lyu   u32 offset;
231bfc2be0SChangyuan Lyu   u32 size;
241bfc2be0SChangyuan Lyu   u32 offset_hi;
251bfc2be0SChangyuan Lyu   u32 size_hi;
267ff8a323SGerd Hoffmann 
277ff8a323SGerd Hoffmann   if (length < 16)
286ebebbaaSMartin Mares     return 0;
297ff8a323SGerd Hoffmann   if (!config_fetch(d, where, length))
306ebebbaaSMartin Mares     return 0;
317ff8a323SGerd Hoffmann 
327ff8a323SGerd Hoffmann   switch (type)
337ff8a323SGerd Hoffmann     {
347ff8a323SGerd Hoffmann     case 1:
357ff8a323SGerd Hoffmann       tname = "CommonCfg";
367ff8a323SGerd Hoffmann       break;
377ff8a323SGerd Hoffmann     case 2:
387ff8a323SGerd Hoffmann       tname = "Notify";
397ff8a323SGerd Hoffmann       break;
407ff8a323SGerd Hoffmann     case 3:
417ff8a323SGerd Hoffmann       tname = "ISR";
427ff8a323SGerd Hoffmann       break;
437ff8a323SGerd Hoffmann     case 4:
447ff8a323SGerd Hoffmann       tname = "DeviceCfg";
457ff8a323SGerd Hoffmann       break;
461bfc2be0SChangyuan Lyu     case 8:
471bfc2be0SChangyuan Lyu       tname = "SharedMemory";
481bfc2be0SChangyuan Lyu       break;
497ff8a323SGerd Hoffmann     default:
507ff8a323SGerd Hoffmann       tname = "<unknown>";
517ff8a323SGerd Hoffmann       break;
527ff8a323SGerd Hoffmann     }
537ff8a323SGerd Hoffmann 
547ff8a323SGerd Hoffmann   printf("VirtIO: %s\n", tname);
557ff8a323SGerd Hoffmann 
567ff8a323SGerd Hoffmann   if (verbose < 2)
576ebebbaaSMartin Mares     return 1;
587ff8a323SGerd Hoffmann 
591bfc2be0SChangyuan Lyu   offset = get_conf_long(d, where + 8);
601bfc2be0SChangyuan Lyu   size = get_conf_long(d, where + 12);
611bfc2be0SChangyuan Lyu   if (type != 8)
626ebebbaaSMartin Mares     printf("\t\tBAR=%d offset=%08x size=%08x",
631bfc2be0SChangyuan Lyu           get_conf_byte(d, where +  4), offset, size);
641bfc2be0SChangyuan Lyu   else {
651bfc2be0SChangyuan Lyu     offset_hi = get_conf_long(d, where + 16);
661bfc2be0SChangyuan Lyu     size_hi = get_conf_long(d, where + 20);
67*b78c087bSMartin Mares     printf("\t\tBAR=%d offset=%016" PCI_U64_FMT_X " size=%016" PCI_U64_FMT_X " id=%d",
687ff8a323SGerd Hoffmann           get_conf_byte(d, where +  4),
691bfc2be0SChangyuan Lyu           (u64) offset | (u64) offset_hi << 32,
701bfc2be0SChangyuan Lyu           (u64) size | (u64) size_hi << 32,
711bfc2be0SChangyuan Lyu           get_conf_byte(d, where + 5));
721bfc2be0SChangyuan Lyu   }
737ff8a323SGerd Hoffmann 
746ebebbaaSMartin Mares   if (type == 2 && length >= 20)
756ebebbaaSMartin Mares     printf(" multiplier=%08x", get_conf_long(d, where+16));
767ff8a323SGerd Hoffmann 
776ebebbaaSMartin Mares   printf("\n");
786ebebbaaSMartin Mares   return 1;
797ff8a323SGerd Hoffmann }
807ff8a323SGerd Hoffmann 
816ebebbaaSMartin Mares static int
show_vendor_caps_intel(struct device * d,int where,int cap)82faa79db9SPali Rohár show_vendor_caps_intel(struct device *d, int where, int cap)
83faa79db9SPali Rohár {
84faa79db9SPali Rohár   int length = BITS(cap, 0, 8);
85faa79db9SPali Rohár   int version = BITS(cap, 8, 4);
86faa79db9SPali Rohár   int type = BITS(cap, 12, 4);
87faa79db9SPali Rohár   u32 l;
88faa79db9SPali Rohár 
89faa79db9SPali Rohár   if (type == 0)
90faa79db9SPali Rohár     {
91faa79db9SPali Rohár       printf("Intel Capabilities v%d\n", version);
92faa79db9SPali Rohár       /*
93faa79db9SPali Rohár        * Intel Capabilities is used at least on Intel Host Bridge / DRAM Controller
94faa79db9SPali Rohár        * and Intel Integrated Graphics Controller. Format of the CAPID0_<X>
95faa79db9SPali Rohár        * registers parsed below matches Cap Version 1 which is used since second
96faa79db9SPali Rohár        * generation of the Intel Core processors (Sandy Bridge). Parsing of other
97faa79db9SPali Rohár        * versions is not currently supported.
98faa79db9SPali Rohár        */
99faa79db9SPali Rohár       if (version != 1)
100faa79db9SPali Rohár         return 1;
101faa79db9SPali Rohár     }
102faa79db9SPali Rohár   else if (type == 1)
103faa79db9SPali Rohár     {
104faa79db9SPali Rohár       printf("Intel Feature Detection\n");
105faa79db9SPali Rohár       /*
106faa79db9SPali Rohár        * Intel Feature Detection Capabilities is used on Intel LPC Controller.
107faa79db9SPali Rohár        * Capabilities are accessed indirectly by writing indirect capability
108faa79db9SPali Rohár        * register to PCI config space. Because lspci cannot write to PCI config
109faa79db9SPali Rohár        * space, it is not possible to read or parse Intel Feature Vector Space.
110faa79db9SPali Rohár        */
111faa79db9SPali Rohár       return 1;
112faa79db9SPali Rohár     }
113faa79db9SPali Rohár   else
114faa79db9SPali Rohár     {
115faa79db9SPali Rohár       printf("Intel <unknown>\n");
116faa79db9SPali Rohár       return 1;
117faa79db9SPali Rohár     }
118faa79db9SPali Rohár 
119faa79db9SPali Rohár   if (!config_fetch(d, where, length))
120faa79db9SPali Rohár     return 0;
121faa79db9SPali Rohár 
122faa79db9SPali Rohár   /* CAPID0_A */
123faa79db9SPali Rohár   if (length >= 8)
124faa79db9SPali Rohár     {
125faa79db9SPali Rohár       l = get_conf_long(d, where + 4);
126faa79db9SPali Rohár       printf("\t\tCapA:");
127faa79db9SPali Rohár       printf(" Peg60Dis%c", FLAG(l, BIT(31)));
128faa79db9SPali Rohár       printf(" Peg12Dis%c", FLAG(l, BIT(30)));
129faa79db9SPali Rohár       printf(" Peg11Dis%c", FLAG(l, BIT(29)));
130faa79db9SPali Rohár       printf(" Peg10Dis%c", FLAG(l, BIT(28)));
131faa79db9SPali Rohár       printf(" PeLWUDis%c", FLAG(l, BIT(27)));
132faa79db9SPali Rohár       printf(" DmiWidth=x%u", (l & BIT(26)) ? 2 : 4);
133faa79db9SPali Rohár       printf("\n\t\t     ");
134faa79db9SPali Rohár       printf(" EccDis%c", FLAG(l, BIT(25)));
135faa79db9SPali Rohár       printf(" ForceEccEn%c", FLAG(l, BIT(24)));
136faa79db9SPali Rohár       printf(" VTdDis%c", FLAG(l, BIT(23)));
137faa79db9SPali Rohár       printf(" DmiG2Dis%c", FLAG(l, BIT(22)));
138faa79db9SPali Rohár       printf(" PegG2Dis%c", FLAG(l, BIT(21)));
139faa79db9SPali Rohár       printf(" DDRMaxSize=");
140faa79db9SPali Rohár       if (BITS(l, 19, 2) == 0)
141faa79db9SPali Rohár         printf("Unlimited");
142faa79db9SPali Rohár       else
143faa79db9SPali Rohár         printf("%gGB/chan", 512 * (1 << ((3-BITS(l, 19, 2))*2)) / 1024.0);
144faa79db9SPali Rohár       printf("\n\t\t     ");
145faa79db9SPali Rohár       printf(" 1NDis%c", FLAG(l, BIT(17)));
146faa79db9SPali Rohár       printf(" CDDis%c", FLAG(l, BIT(15)));
147faa79db9SPali Rohár       printf(" DDPCDis%c", FLAG(l, BIT(14)));
148faa79db9SPali Rohár       printf(" X2APICEn%c", FLAG(l, BIT(13)));
149faa79db9SPali Rohár       printf(" PDCDis%c", FLAG(l, BIT(12)));
150faa79db9SPali Rohár       printf(" IGDis%c", FLAG(l, BIT(11)));
151faa79db9SPali Rohár       printf(" CDID=%u", BITS(l, 8, 2));
152faa79db9SPali Rohár       printf(" CRID=%u", BITS(l, 4, 4));
153faa79db9SPali Rohár       printf("\n\t\t     ");
154faa79db9SPali Rohár       printf(" DDROCCAP%c", FLAG(l, BIT(3)));
155faa79db9SPali Rohár       printf(" OCEn%c", FLAG(l, BIT(2)));
156faa79db9SPali Rohár       printf(" DDRWrtVrefEn%c", FLAG(l, BIT(1)));
157faa79db9SPali Rohár       printf(" DDR3LEn%c", FLAG(l, BIT(0)));
158faa79db9SPali Rohár       printf("\n");
159faa79db9SPali Rohár     }
160faa79db9SPali Rohár 
161faa79db9SPali Rohár   /* CAPID0_B */
162faa79db9SPali Rohár   if (length >= 12)
163faa79db9SPali Rohár     {
164faa79db9SPali Rohár       l = get_conf_long(d, where + 8);
165faa79db9SPali Rohár       printf("\t\tCapB:");
166faa79db9SPali Rohár       printf(" ImguDis%c", FLAG(l, BIT(31)));
167faa79db9SPali Rohár       printf(" OCbySSKUCap%c", FLAG(l, BIT(30)));
168faa79db9SPali Rohár       printf(" OCbySSKUEn%c", FLAG(l, BIT(29)));
169faa79db9SPali Rohár       printf(" SMTCap%c", FLAG(l, BIT(28)));
170faa79db9SPali Rohár       printf(" CacheSzCap 0x%x", BITS(l, 25, 3));
171faa79db9SPali Rohár       printf("\n\t\t     ");
172faa79db9SPali Rohár       printf(" SoftBinCap%c", FLAG(l, BIT(24)));
173faa79db9SPali Rohár       printf(" DDR3MaxFreqWithRef100=");
174faa79db9SPali Rohár       if (BITS(l, 21, 3) == 0)
175faa79db9SPali Rohár         printf("Disabled");
176faa79db9SPali Rohár       else if (BITS(l, 21, 3) == 7)
177faa79db9SPali Rohár         printf("Unlimited");
178faa79db9SPali Rohár       else
179faa79db9SPali Rohár         printf("%uMHz", (6+BITS(l, 21, 3)) * 200);
180faa79db9SPali Rohár       printf(" PegG3Dis%c", FLAG(l, BIT(20)));
181faa79db9SPali Rohár       printf("\n\t\t     ");
182faa79db9SPali Rohár       printf(" PkgTyp%c", FLAG(l, BIT(19)));
183faa79db9SPali Rohár       printf(" AddGfxEn%c", FLAG(l, BIT(18)));
184faa79db9SPali Rohár       printf(" AddGfxCap%c", FLAG(l, BIT(17)));
185faa79db9SPali Rohár       printf(" PegX16Dis%c", FLAG(l, BIT(16)));
186faa79db9SPali Rohár       printf(" DmiG3Dis%c", FLAG(l, BIT(15)));
187faa79db9SPali Rohár       printf(" GmmDis%c", FLAG(l, BIT(8)));
188faa79db9SPali Rohár       printf("\n\t\t     ");
189faa79db9SPali Rohár       printf(" DDR3MaxFreq=%uMHz", (11-BITS(l, 4, 2)) * 2666 / 10);
190faa79db9SPali Rohár       printf(" LPDDR3En%c", FLAG(l, BIT(2)));
191faa79db9SPali Rohár       printf("\n");
192faa79db9SPali Rohár     }
193faa79db9SPali Rohár 
194faa79db9SPali Rohár   /* CAPID0_C */
195faa79db9SPali Rohár   if (length >= 16)
196faa79db9SPali Rohár     {
197faa79db9SPali Rohár       l = get_conf_long(d, where + 12);
198faa79db9SPali Rohár       printf("\t\tCapC:");
199faa79db9SPali Rohár       printf(" PegG4Dis%c", FLAG(l, BIT(28)));
200faa79db9SPali Rohár       printf(" DDR4MaxFreq=");
201faa79db9SPali Rohár       if (BITS(l, 23, 4) == 0)
202faa79db9SPali Rohár         printf("Unlimited");
203faa79db9SPali Rohár       else
204faa79db9SPali Rohár         printf("%uMHz", BITS(l, 0, 4) * 2666 / 10);
205faa79db9SPali Rohár       printf(" LPDDREn%c", FLAG(l, BIT(22)));
206faa79db9SPali Rohár       printf(" LPDDR4MaxFreq=");
207faa79db9SPali Rohár       if (BITS(l, 17, 4) == 0)
208faa79db9SPali Rohár         printf("Unlimited");
209faa79db9SPali Rohár       else
210faa79db9SPali Rohár         printf("%uMHz", BITS(l, 0, 4) * 2666 / 10);
211faa79db9SPali Rohár       printf(" LPDDR4En%c", FLAG(l, BIT(16)));
212faa79db9SPali Rohár       printf("\n\t\t     ");
213faa79db9SPali Rohár       printf(" QClkGvDis%c", FLAG(l, BIT(14)));
214faa79db9SPali Rohár       printf(" SgxDis%c", FLAG(l, BIT(9)));
215faa79db9SPali Rohár       printf(" BClkOC=%s", BITS(l, 7, 2) == 0 ? "Disabled" :
216faa79db9SPali Rohár                            BITS(l, 7, 2) == 1 ? "115MHz" :
217faa79db9SPali Rohár                            BITS(l, 7, 2) == 2 ? "130MHz" :
218faa79db9SPali Rohár                                                 "Unlimited");
219faa79db9SPali Rohár       printf(" IddDis%c", FLAG(l, BIT(6)));
220faa79db9SPali Rohár       printf(" Pipe3Dis%c", FLAG(l, BIT(5)));
221faa79db9SPali Rohár       printf(" Gear1MaxFreq=");
222faa79db9SPali Rohár       if (BITS(l, 0, 4) == 0)
223faa79db9SPali Rohár         printf("Unlimited");
224faa79db9SPali Rohár       else
225faa79db9SPali Rohár         printf("%uMHz", BITS(l, 0, 4) * 2666 / 10);
226faa79db9SPali Rohár       printf("\n");
227faa79db9SPali Rohár     }
228faa79db9SPali Rohár 
229faa79db9SPali Rohár   return 1;
230faa79db9SPali Rohár }
231faa79db9SPali Rohár 
232faa79db9SPali Rohár static int
do_show_vendor_caps(struct device * d,int where,int cap)2336ebebbaaSMartin Mares do_show_vendor_caps(struct device *d, int where, int cap)
2347ff8a323SGerd Hoffmann {
235adf7de0eSDavid Edmondson   switch (d->dev->vendor_id)
2367ff8a323SGerd Hoffmann     {
2377ff8a323SGerd Hoffmann     case 0x1af4: /* Red Hat */
238adf7de0eSDavid Edmondson       if (d->dev->device_id >= 0x1000 &&
239adf7de0eSDavid Edmondson 	  d->dev->device_id <= 0x107f)
2406ebebbaaSMartin Mares 	return show_vendor_caps_virtio(d, where, cap);
2417ff8a323SGerd Hoffmann       break;
242faa79db9SPali Rohár     case 0x8086: /* Intel */
243faa79db9SPali Rohár       return show_vendor_caps_intel(d, where, cap);
2447ff8a323SGerd Hoffmann     }
2456ebebbaaSMartin Mares   return 0;
2466ebebbaaSMartin Mares }
2476ebebbaaSMartin Mares 
2486ebebbaaSMartin Mares void
show_vendor_caps(struct device * d,int where,int cap)2496ebebbaaSMartin Mares show_vendor_caps(struct device *d, int where, int cap)
2506ebebbaaSMartin Mares {
2516ebebbaaSMartin Mares   printf("Vendor Specific Information: ");
2526ebebbaaSMartin Mares   if (!do_show_vendor_caps(d, where, cap))
2536ebebbaaSMartin Mares     printf("Len=%02x <?>\n", BITS(cap, 0, 8));
2547ff8a323SGerd Hoffmann }
255