1*c2e0c6b5SAndroid Build Coastguard Worker /*
2*c2e0c6b5SAndroid Build Coastguard Worker * The PCI Utilities -- Bus Mapping Mode
3*c2e0c6b5SAndroid Build Coastguard Worker *
4*c2e0c6b5SAndroid Build Coastguard Worker * Copyright (c) 1997--2008 Martin Mares <[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 #include <stdlib.h>
14*c2e0c6b5SAndroid Build Coastguard Worker
15*c2e0c6b5SAndroid Build Coastguard Worker #include "lspci.h"
16*c2e0c6b5SAndroid Build Coastguard Worker
17*c2e0c6b5SAndroid Build Coastguard Worker struct bus_bridge {
18*c2e0c6b5SAndroid Build Coastguard Worker struct bus_bridge *next;
19*c2e0c6b5SAndroid Build Coastguard Worker byte this, dev, func, first, last, bug;
20*c2e0c6b5SAndroid Build Coastguard Worker };
21*c2e0c6b5SAndroid Build Coastguard Worker
22*c2e0c6b5SAndroid Build Coastguard Worker struct bus_info {
23*c2e0c6b5SAndroid Build Coastguard Worker byte exists;
24*c2e0c6b5SAndroid Build Coastguard Worker byte guestbook;
25*c2e0c6b5SAndroid Build Coastguard Worker struct bus_bridge *bridges, *via;
26*c2e0c6b5SAndroid Build Coastguard Worker };
27*c2e0c6b5SAndroid Build Coastguard Worker
28*c2e0c6b5SAndroid Build Coastguard Worker static struct bus_info *bus_info;
29*c2e0c6b5SAndroid Build Coastguard Worker
30*c2e0c6b5SAndroid Build Coastguard Worker static void
map_bridge(struct bus_info * bi,struct device * d,int np,int ns,int nl)31*c2e0c6b5SAndroid Build Coastguard Worker map_bridge(struct bus_info *bi, struct device *d, int np, int ns, int nl)
32*c2e0c6b5SAndroid Build Coastguard Worker {
33*c2e0c6b5SAndroid Build Coastguard Worker struct bus_bridge *b = xmalloc(sizeof(struct bus_bridge));
34*c2e0c6b5SAndroid Build Coastguard Worker struct pci_dev *p = d->dev;
35*c2e0c6b5SAndroid Build Coastguard Worker
36*c2e0c6b5SAndroid Build Coastguard Worker b->next = bi->bridges;
37*c2e0c6b5SAndroid Build Coastguard Worker bi->bridges = b;
38*c2e0c6b5SAndroid Build Coastguard Worker b->this = get_conf_byte(d, np);
39*c2e0c6b5SAndroid Build Coastguard Worker b->dev = p->dev;
40*c2e0c6b5SAndroid Build Coastguard Worker b->func = p->func;
41*c2e0c6b5SAndroid Build Coastguard Worker b->first = get_conf_byte(d, ns);
42*c2e0c6b5SAndroid Build Coastguard Worker b->last = get_conf_byte(d, nl);
43*c2e0c6b5SAndroid Build Coastguard Worker printf("## %02x:%02x.%d is a bridge from %02x to %02x-%02x\n",
44*c2e0c6b5SAndroid Build Coastguard Worker p->bus, p->dev, p->func, b->this, b->first, b->last);
45*c2e0c6b5SAndroid Build Coastguard Worker if (b->this != p->bus)
46*c2e0c6b5SAndroid Build Coastguard Worker printf("!!! Bridge points to invalid primary bus.\n");
47*c2e0c6b5SAndroid Build Coastguard Worker if (b->first > b->last)
48*c2e0c6b5SAndroid Build Coastguard Worker {
49*c2e0c6b5SAndroid Build Coastguard Worker printf("!!! Bridge points to invalid bus range.\n");
50*c2e0c6b5SAndroid Build Coastguard Worker b->last = b->first;
51*c2e0c6b5SAndroid Build Coastguard Worker }
52*c2e0c6b5SAndroid Build Coastguard Worker }
53*c2e0c6b5SAndroid Build Coastguard Worker
54*c2e0c6b5SAndroid Build Coastguard Worker static void
do_map_bus(int bus)55*c2e0c6b5SAndroid Build Coastguard Worker do_map_bus(int bus)
56*c2e0c6b5SAndroid Build Coastguard Worker {
57*c2e0c6b5SAndroid Build Coastguard Worker int domain = (filter.domain >= 0 ? filter.domain : 0);
58*c2e0c6b5SAndroid Build Coastguard Worker int dev, func;
59*c2e0c6b5SAndroid Build Coastguard Worker int verbose = pacc->debugging;
60*c2e0c6b5SAndroid Build Coastguard Worker struct bus_info *bi = bus_info + bus;
61*c2e0c6b5SAndroid Build Coastguard Worker struct device *d;
62*c2e0c6b5SAndroid Build Coastguard Worker
63*c2e0c6b5SAndroid Build Coastguard Worker if (verbose)
64*c2e0c6b5SAndroid Build Coastguard Worker printf("Mapping bus %04x:%02x\n", domain, bus);
65*c2e0c6b5SAndroid Build Coastguard Worker for (dev = 0; dev < 32; dev++)
66*c2e0c6b5SAndroid Build Coastguard Worker if (filter.slot < 0 || filter.slot == dev)
67*c2e0c6b5SAndroid Build Coastguard Worker {
68*c2e0c6b5SAndroid Build Coastguard Worker int func_limit = 1;
69*c2e0c6b5SAndroid Build Coastguard Worker for (func = 0; func < func_limit; func++)
70*c2e0c6b5SAndroid Build Coastguard Worker if (filter.func < 0 || filter.func == func)
71*c2e0c6b5SAndroid Build Coastguard Worker {
72*c2e0c6b5SAndroid Build Coastguard Worker struct pci_dev *p = pci_get_dev(pacc, domain, bus, dev, func);
73*c2e0c6b5SAndroid Build Coastguard Worker u16 vendor = pci_read_word(p, PCI_VENDOR_ID);
74*c2e0c6b5SAndroid Build Coastguard Worker if (vendor && vendor != 0xffff)
75*c2e0c6b5SAndroid Build Coastguard Worker {
76*c2e0c6b5SAndroid Build Coastguard Worker if (!func && (pci_read_byte(p, PCI_HEADER_TYPE) & 0x80))
77*c2e0c6b5SAndroid Build Coastguard Worker func_limit = 8;
78*c2e0c6b5SAndroid Build Coastguard Worker if (verbose)
79*c2e0c6b5SAndroid Build Coastguard Worker printf("Discovered device %04x:%02x:%02x.%d\n", domain, bus, dev, func);
80*c2e0c6b5SAndroid Build Coastguard Worker bi->exists = 1;
81*c2e0c6b5SAndroid Build Coastguard Worker if (d = scan_device(p))
82*c2e0c6b5SAndroid Build Coastguard Worker {
83*c2e0c6b5SAndroid Build Coastguard Worker show_device(d);
84*c2e0c6b5SAndroid Build Coastguard Worker switch (get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f)
85*c2e0c6b5SAndroid Build Coastguard Worker {
86*c2e0c6b5SAndroid Build Coastguard Worker case PCI_HEADER_TYPE_BRIDGE:
87*c2e0c6b5SAndroid Build Coastguard Worker map_bridge(bi, d, PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS);
88*c2e0c6b5SAndroid Build Coastguard Worker break;
89*c2e0c6b5SAndroid Build Coastguard Worker case PCI_HEADER_TYPE_CARDBUS:
90*c2e0c6b5SAndroid Build Coastguard Worker map_bridge(bi, d, PCI_CB_PRIMARY_BUS, PCI_CB_CARD_BUS, PCI_CB_SUBORDINATE_BUS);
91*c2e0c6b5SAndroid Build Coastguard Worker break;
92*c2e0c6b5SAndroid Build Coastguard Worker }
93*c2e0c6b5SAndroid Build Coastguard Worker free(d);
94*c2e0c6b5SAndroid Build Coastguard Worker }
95*c2e0c6b5SAndroid Build Coastguard Worker else if (verbose)
96*c2e0c6b5SAndroid Build Coastguard Worker printf("But it was filtered out.\n");
97*c2e0c6b5SAndroid Build Coastguard Worker }
98*c2e0c6b5SAndroid Build Coastguard Worker pci_free_dev(p);
99*c2e0c6b5SAndroid Build Coastguard Worker }
100*c2e0c6b5SAndroid Build Coastguard Worker }
101*c2e0c6b5SAndroid Build Coastguard Worker }
102*c2e0c6b5SAndroid Build Coastguard Worker
103*c2e0c6b5SAndroid Build Coastguard Worker static void
do_map_bridges(int bus,int min,int max)104*c2e0c6b5SAndroid Build Coastguard Worker do_map_bridges(int bus, int min, int max)
105*c2e0c6b5SAndroid Build Coastguard Worker {
106*c2e0c6b5SAndroid Build Coastguard Worker struct bus_info *bi = bus_info + bus;
107*c2e0c6b5SAndroid Build Coastguard Worker struct bus_bridge *b;
108*c2e0c6b5SAndroid Build Coastguard Worker
109*c2e0c6b5SAndroid Build Coastguard Worker bi->guestbook = 1;
110*c2e0c6b5SAndroid Build Coastguard Worker for (b=bi->bridges; b; b=b->next)
111*c2e0c6b5SAndroid Build Coastguard Worker {
112*c2e0c6b5SAndroid Build Coastguard Worker if (bus_info[b->first].guestbook)
113*c2e0c6b5SAndroid Build Coastguard Worker b->bug = 1;
114*c2e0c6b5SAndroid Build Coastguard Worker else if (b->first < min || b->last > max)
115*c2e0c6b5SAndroid Build Coastguard Worker b->bug = 2;
116*c2e0c6b5SAndroid Build Coastguard Worker else
117*c2e0c6b5SAndroid Build Coastguard Worker {
118*c2e0c6b5SAndroid Build Coastguard Worker bus_info[b->first].via = b;
119*c2e0c6b5SAndroid Build Coastguard Worker do_map_bridges(b->first, b->first, b->last);
120*c2e0c6b5SAndroid Build Coastguard Worker }
121*c2e0c6b5SAndroid Build Coastguard Worker }
122*c2e0c6b5SAndroid Build Coastguard Worker }
123*c2e0c6b5SAndroid Build Coastguard Worker
124*c2e0c6b5SAndroid Build Coastguard Worker static void
map_bridges(void)125*c2e0c6b5SAndroid Build Coastguard Worker map_bridges(void)
126*c2e0c6b5SAndroid Build Coastguard Worker {
127*c2e0c6b5SAndroid Build Coastguard Worker int i;
128*c2e0c6b5SAndroid Build Coastguard Worker
129*c2e0c6b5SAndroid Build Coastguard Worker printf("\nSummary of buses:\n\n");
130*c2e0c6b5SAndroid Build Coastguard Worker for (i=0; i<256; i++)
131*c2e0c6b5SAndroid Build Coastguard Worker if (bus_info[i].exists && !bus_info[i].guestbook)
132*c2e0c6b5SAndroid Build Coastguard Worker do_map_bridges(i, 0, 255);
133*c2e0c6b5SAndroid Build Coastguard Worker for (i=0; i<256; i++)
134*c2e0c6b5SAndroid Build Coastguard Worker {
135*c2e0c6b5SAndroid Build Coastguard Worker struct bus_info *bi = bus_info + i;
136*c2e0c6b5SAndroid Build Coastguard Worker struct bus_bridge *b = bi->via;
137*c2e0c6b5SAndroid Build Coastguard Worker
138*c2e0c6b5SAndroid Build Coastguard Worker if (bi->exists)
139*c2e0c6b5SAndroid Build Coastguard Worker {
140*c2e0c6b5SAndroid Build Coastguard Worker printf("%02x: ", i);
141*c2e0c6b5SAndroid Build Coastguard Worker if (b)
142*c2e0c6b5SAndroid Build Coastguard Worker printf("Entered via %02x:%02x.%d\n", b->this, b->dev, b->func);
143*c2e0c6b5SAndroid Build Coastguard Worker else if (!i)
144*c2e0c6b5SAndroid Build Coastguard Worker printf("Primary host bus\n");
145*c2e0c6b5SAndroid Build Coastguard Worker else
146*c2e0c6b5SAndroid Build Coastguard Worker printf("Secondary host bus (?)\n");
147*c2e0c6b5SAndroid Build Coastguard Worker }
148*c2e0c6b5SAndroid Build Coastguard Worker for (b=bi->bridges; b; b=b->next)
149*c2e0c6b5SAndroid Build Coastguard Worker {
150*c2e0c6b5SAndroid Build Coastguard Worker printf("\t%02x.%d Bridge to %02x-%02x", b->dev, b->func, b->first, b->last);
151*c2e0c6b5SAndroid Build Coastguard Worker switch (b->bug)
152*c2e0c6b5SAndroid Build Coastguard Worker {
153*c2e0c6b5SAndroid Build Coastguard Worker case 1:
154*c2e0c6b5SAndroid Build Coastguard Worker printf(" <overlap bug>");
155*c2e0c6b5SAndroid Build Coastguard Worker break;
156*c2e0c6b5SAndroid Build Coastguard Worker case 2:
157*c2e0c6b5SAndroid Build Coastguard Worker printf(" <crossing bug>");
158*c2e0c6b5SAndroid Build Coastguard Worker break;
159*c2e0c6b5SAndroid Build Coastguard Worker }
160*c2e0c6b5SAndroid Build Coastguard Worker putchar('\n');
161*c2e0c6b5SAndroid Build Coastguard Worker }
162*c2e0c6b5SAndroid Build Coastguard Worker }
163*c2e0c6b5SAndroid Build Coastguard Worker }
164*c2e0c6b5SAndroid Build Coastguard Worker
165*c2e0c6b5SAndroid Build Coastguard Worker void
map_the_bus(void)166*c2e0c6b5SAndroid Build Coastguard Worker map_the_bus(void)
167*c2e0c6b5SAndroid Build Coastguard Worker {
168*c2e0c6b5SAndroid Build Coastguard Worker if (pacc->method == PCI_ACCESS_PROC_BUS_PCI ||
169*c2e0c6b5SAndroid Build Coastguard Worker pacc->method == PCI_ACCESS_SYS_BUS_PCI ||
170*c2e0c6b5SAndroid Build Coastguard Worker pacc->method == PCI_ACCESS_WIN32_CFGMGR32 ||
171*c2e0c6b5SAndroid Build Coastguard Worker pacc->method == PCI_ACCESS_DUMP)
172*c2e0c6b5SAndroid Build Coastguard Worker printf("WARNING: Bus mapping can be reliable only with direct hardware access enabled.\n\n");
173*c2e0c6b5SAndroid Build Coastguard Worker bus_info = xmalloc(sizeof(struct bus_info) * 256);
174*c2e0c6b5SAndroid Build Coastguard Worker memset(bus_info, 0, sizeof(struct bus_info) * 256);
175*c2e0c6b5SAndroid Build Coastguard Worker if (filter.bus >= 0)
176*c2e0c6b5SAndroid Build Coastguard Worker do_map_bus(filter.bus);
177*c2e0c6b5SAndroid Build Coastguard Worker else
178*c2e0c6b5SAndroid Build Coastguard Worker {
179*c2e0c6b5SAndroid Build Coastguard Worker int bus;
180*c2e0c6b5SAndroid Build Coastguard Worker for (bus=0; bus<256; bus++)
181*c2e0c6b5SAndroid Build Coastguard Worker do_map_bus(bus);
182*c2e0c6b5SAndroid Build Coastguard Worker }
183*c2e0c6b5SAndroid Build Coastguard Worker map_bridges();
184*c2e0c6b5SAndroid Build Coastguard Worker }
185