1*c2e0c6b5SAndroid Build Coastguard Worker /*
2*c2e0c6b5SAndroid Build Coastguard Worker * The PCI Utilities -- Show Vendor-specific Capabilities
3*c2e0c6b5SAndroid Build Coastguard Worker *
4*c2e0c6b5SAndroid Build Coastguard Worker * Copyright (c) 2014 Gerd Hoffmann <[email protected]>
5*c2e0c6b5SAndroid Build Coastguard Worker *
6*c2e0c6b5SAndroid Build Coastguard Worker * Can be freely distributed and used under the terms of the GNU GPL v2+.
7*c2e0c6b5SAndroid Build Coastguard Worker *
8*c2e0c6b5SAndroid Build Coastguard Worker * SPDX-License-Identifier: GPL-2.0-or-later
9*c2e0c6b5SAndroid Build Coastguard Worker */
10*c2e0c6b5SAndroid Build Coastguard Worker
11*c2e0c6b5SAndroid Build Coastguard Worker #include <stdio.h>
12*c2e0c6b5SAndroid Build Coastguard Worker #include <string.h>
13*c2e0c6b5SAndroid Build Coastguard Worker
14*c2e0c6b5SAndroid Build Coastguard Worker #include "lspci.h"
15*c2e0c6b5SAndroid Build Coastguard Worker
16*c2e0c6b5SAndroid Build Coastguard Worker static int
show_vendor_caps_virtio(struct device * d,int where,int cap)17*c2e0c6b5SAndroid Build Coastguard Worker show_vendor_caps_virtio(struct device *d, int where, int cap)
18*c2e0c6b5SAndroid Build Coastguard Worker {
19*c2e0c6b5SAndroid Build Coastguard Worker int length = BITS(cap, 0, 8);
20*c2e0c6b5SAndroid Build Coastguard Worker int type = BITS(cap, 8, 8);
21*c2e0c6b5SAndroid Build Coastguard Worker char *tname;
22*c2e0c6b5SAndroid Build Coastguard Worker
23*c2e0c6b5SAndroid Build Coastguard Worker if (length < 16)
24*c2e0c6b5SAndroid Build Coastguard Worker return 0;
25*c2e0c6b5SAndroid Build Coastguard Worker if (!config_fetch(d, where, length))
26*c2e0c6b5SAndroid Build Coastguard Worker return 0;
27*c2e0c6b5SAndroid Build Coastguard Worker
28*c2e0c6b5SAndroid Build Coastguard Worker switch (type)
29*c2e0c6b5SAndroid Build Coastguard Worker {
30*c2e0c6b5SAndroid Build Coastguard Worker case 1:
31*c2e0c6b5SAndroid Build Coastguard Worker tname = "CommonCfg";
32*c2e0c6b5SAndroid Build Coastguard Worker break;
33*c2e0c6b5SAndroid Build Coastguard Worker case 2:
34*c2e0c6b5SAndroid Build Coastguard Worker tname = "Notify";
35*c2e0c6b5SAndroid Build Coastguard Worker break;
36*c2e0c6b5SAndroid Build Coastguard Worker case 3:
37*c2e0c6b5SAndroid Build Coastguard Worker tname = "ISR";
38*c2e0c6b5SAndroid Build Coastguard Worker break;
39*c2e0c6b5SAndroid Build Coastguard Worker case 4:
40*c2e0c6b5SAndroid Build Coastguard Worker tname = "DeviceCfg";
41*c2e0c6b5SAndroid Build Coastguard Worker break;
42*c2e0c6b5SAndroid Build Coastguard Worker default:
43*c2e0c6b5SAndroid Build Coastguard Worker tname = "<unknown>";
44*c2e0c6b5SAndroid Build Coastguard Worker break;
45*c2e0c6b5SAndroid Build Coastguard Worker }
46*c2e0c6b5SAndroid Build Coastguard Worker
47*c2e0c6b5SAndroid Build Coastguard Worker printf("VirtIO: %s\n", tname);
48*c2e0c6b5SAndroid Build Coastguard Worker
49*c2e0c6b5SAndroid Build Coastguard Worker if (verbose < 2)
50*c2e0c6b5SAndroid Build Coastguard Worker return 1;
51*c2e0c6b5SAndroid Build Coastguard Worker
52*c2e0c6b5SAndroid Build Coastguard Worker printf("\t\tBAR=%d offset=%08x size=%08x",
53*c2e0c6b5SAndroid Build Coastguard Worker get_conf_byte(d, where + 4),
54*c2e0c6b5SAndroid Build Coastguard Worker get_conf_long(d, where + 8),
55*c2e0c6b5SAndroid Build Coastguard Worker get_conf_long(d, where + 12));
56*c2e0c6b5SAndroid Build Coastguard Worker
57*c2e0c6b5SAndroid Build Coastguard Worker if (type == 2 && length >= 20)
58*c2e0c6b5SAndroid Build Coastguard Worker printf(" multiplier=%08x", get_conf_long(d, where+16));
59*c2e0c6b5SAndroid Build Coastguard Worker
60*c2e0c6b5SAndroid Build Coastguard Worker printf("\n");
61*c2e0c6b5SAndroid Build Coastguard Worker return 1;
62*c2e0c6b5SAndroid Build Coastguard Worker }
63*c2e0c6b5SAndroid Build Coastguard Worker
64*c2e0c6b5SAndroid Build Coastguard Worker static int
do_show_vendor_caps(struct device * d,int where,int cap)65*c2e0c6b5SAndroid Build Coastguard Worker do_show_vendor_caps(struct device *d, int where, int cap)
66*c2e0c6b5SAndroid Build Coastguard Worker {
67*c2e0c6b5SAndroid Build Coastguard Worker switch (d->dev->vendor_id)
68*c2e0c6b5SAndroid Build Coastguard Worker {
69*c2e0c6b5SAndroid Build Coastguard Worker case 0x1af4: /* Red Hat */
70*c2e0c6b5SAndroid Build Coastguard Worker if (d->dev->device_id >= 0x1000 &&
71*c2e0c6b5SAndroid Build Coastguard Worker d->dev->device_id <= 0x107f)
72*c2e0c6b5SAndroid Build Coastguard Worker return show_vendor_caps_virtio(d, where, cap);
73*c2e0c6b5SAndroid Build Coastguard Worker break;
74*c2e0c6b5SAndroid Build Coastguard Worker }
75*c2e0c6b5SAndroid Build Coastguard Worker return 0;
76*c2e0c6b5SAndroid Build Coastguard Worker }
77*c2e0c6b5SAndroid Build Coastguard Worker
78*c2e0c6b5SAndroid Build Coastguard Worker void
show_vendor_caps(struct device * d,int where,int cap)79*c2e0c6b5SAndroid Build Coastguard Worker show_vendor_caps(struct device *d, int where, int cap)
80*c2e0c6b5SAndroid Build Coastguard Worker {
81*c2e0c6b5SAndroid Build Coastguard Worker printf("Vendor Specific Information: ");
82*c2e0c6b5SAndroid Build Coastguard Worker if (!do_show_vendor_caps(d, where, cap))
83*c2e0c6b5SAndroid Build Coastguard Worker printf("Len=%02x <?>\n", BITS(cap, 0, 8));
84*c2e0c6b5SAndroid Build Coastguard Worker }
85