]>
git.ipfire.org Git - thirdparty/pciutils.git/blob - ls-tree.c
2 * The PCI Utilities -- Show Bus Tree
4 * Copyright (c) 1997--2018 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
14 struct bridge host_bridge
= { NULL
, NULL
, NULL
, NULL
, 0, ~0, 0, ~0, NULL
};
17 find_bus(struct bridge
*b
, unsigned int domain
, unsigned int n
)
21 for (bus
=b
->first_bus
; bus
; bus
=bus
->sibling
)
22 if (bus
->domain
== domain
&& bus
->number
== n
)
28 new_bus(struct bridge
*b
, unsigned int domain
, unsigned int n
)
30 struct bus
*bus
= xmalloc(sizeof(struct bus
));
33 bus
->sibling
= b
->first_bus
;
34 bus
->first_dev
= NULL
;
35 bus
->last_dev
= &bus
->first_dev
;
36 bus
->parent_bridge
= b
;
42 insert_dev(struct device
*d
, struct bridge
*b
)
44 struct pci_dev
*p
= d
->dev
;
47 if (! (bus
= find_bus(b
, p
->domain
, p
->bus
)))
50 for (c
=b
->child
; c
; c
=c
->next
)
51 if (c
->domain
== (unsigned)p
->domain
&& c
->secondary
<= p
->bus
&& p
->bus
<= c
->subordinate
)
56 bus
= new_bus(b
, p
->domain
, p
->bus
);
58 /* Simple insertion at the end _does_ guarantee the correct order as the
59 * original device list was sorted by (domain, bus, devfn) lexicographically
60 * and all devices on the new list have the same bus number.
63 bus
->last_dev
= &d
->bus_next
;
72 struct bridge
**last_br
, *b
;
74 /* Build list of bridges */
76 last_br
= &host_bridge
.chain
;
77 for (d
=first_dev
; d
; d
=d
->next
)
79 word
class = d
->dev
->device_class
;
80 byte ht
= get_conf_byte(d
, PCI_HEADER_TYPE
) & 0x7f;
81 if (class == PCI_CLASS_BRIDGE_PCI
&&
82 (ht
== PCI_HEADER_TYPE_BRIDGE
|| ht
== PCI_HEADER_TYPE_CARDBUS
))
84 b
= xmalloc(sizeof(struct bridge
));
85 b
->domain
= d
->dev
->domain
;
86 if (ht
== PCI_HEADER_TYPE_BRIDGE
)
88 b
->primary
= get_conf_byte(d
, PCI_PRIMARY_BUS
);
89 b
->secondary
= get_conf_byte(d
, PCI_SECONDARY_BUS
);
90 b
->subordinate
= get_conf_byte(d
, PCI_SUBORDINATE_BUS
);
94 b
->primary
= get_conf_byte(d
, PCI_CB_PRIMARY_BUS
);
95 b
->secondary
= get_conf_byte(d
, PCI_CB_CARD_BUS
);
96 b
->subordinate
= get_conf_byte(d
, PCI_CB_SUBORDINATE_BUS
);
100 b
->next
= b
->child
= NULL
;
108 /* Create a bridge tree */
110 for (b
=&host_bridge
; b
; b
=b
->chain
)
112 struct bridge
*c
, *best
;
114 for (c
=&host_bridge
; c
; c
=c
->chain
)
115 if (c
!= b
&& (c
== &host_bridge
|| b
->domain
== c
->domain
) &&
116 b
->primary
>= c
->secondary
&& b
->primary
<= c
->subordinate
&&
117 (!best
|| best
->subordinate
- best
->primary
> c
->subordinate
- c
->primary
))
121 b
->next
= best
->child
;
126 /* Insert secondary bus for each bridge */
128 for (b
=&host_bridge
; b
; b
=b
->chain
)
129 if (!find_bus(b
, b
->domain
, b
->secondary
))
130 new_bus(b
, b
->domain
, b
->secondary
);
132 /* Create bus structs and link devices */
134 for (d
=first_dev
; d
; d
=d
->next
)
135 insert_dev(d
, &host_bridge
);
139 print_it(char *line
, char *p
)
144 for (p
=line
; *p
; p
++)
145 if (*p
== '+' || *p
== '|')
151 static void show_tree_bridge(struct bridge
*, char *, char *);
154 show_tree_dev(struct device
*d
, char *line
, char *p
)
156 struct pci_dev
*q
= d
->dev
;
160 p
+= sprintf(p
, "%02x.%x", q
->dev
, q
->func
);
161 for (b
=&host_bridge
; b
; b
=b
->chain
)
164 if (b
->secondary
== b
->subordinate
)
165 p
+= sprintf(p
, "-[%02x]-", b
->secondary
);
167 p
+= sprintf(p
, "-[%02x-%02x]-", b
->secondary
, b
->subordinate
);
168 show_tree_bridge(b
, line
, p
);
172 p
+= sprintf(p
, " %s",
173 pci_lookup_name(pacc
, namebuf
, sizeof(namebuf
),
174 PCI_LOOKUP_VENDOR
| PCI_LOOKUP_DEVICE
,
175 q
->vendor_id
, q
->device_id
));
180 show_tree_bus(struct bus
*b
, char *line
, char *p
)
184 else if (!b
->first_dev
->bus_next
)
188 show_tree_dev(b
->first_dev
, line
, p
);
192 struct device
*d
= b
->first_dev
;
197 show_tree_dev(d
, line
, p
+2);
202 show_tree_dev(d
, line
, p
+2);
207 show_tree_bridge(struct bridge
*b
, char *line
, char *p
)
210 if (!b
->first_bus
->sibling
)
212 if (b
== &host_bridge
)
213 p
+= sprintf(p
, "[%04x:%02x]-", b
->domain
, b
->first_bus
->number
);
214 show_tree_bus(b
->first_bus
, line
, p
);
218 struct bus
*u
= b
->first_bus
;
223 k
= p
+ sprintf(p
, "+-[%04x:%02x]-", u
->domain
, u
->number
);
224 show_tree_bus(u
, line
, k
);
227 k
= p
+ sprintf(p
, "\\-[%04x:%02x]-", u
->domain
, u
->number
);
228 show_tree_bus(u
, line
, k
);
238 show_tree_bridge(&host_bridge
, line
, line
);