xref: /aosp_15_r20/external/pciutils/ls-map.c (revision c2e0c6b56a71da9abe8df5c8348fb3eb5c2c9251)
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