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