]>
git.ipfire.org Git - thirdparty/pciutils.git/blob - ls-tree.c
2 * The PCI Utilities -- Show Bus Tree
4 * Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
15 struct bridge
*chain
; /* Single-linked list of bridges */
16 struct bridge
*next
, *child
; /* Tree of bridges */
17 struct bus
*first_bus
; /* List of buses connected to this bridge */
19 unsigned int primary
, secondary
, subordinate
; /* Bus numbers */
20 struct device
*br_dev
;
27 struct device
*first_dev
, **last_dev
;
30 static struct bridge host_bridge
= { NULL
, NULL
, NULL
, NULL
, 0, ~0, 0, ~0, NULL
};
33 find_bus(struct bridge
*b
, unsigned int domain
, unsigned int n
)
37 for (bus
=b
->first_bus
; bus
; bus
=bus
->sibling
)
38 if (bus
->domain
== domain
&& bus
->number
== n
)
44 new_bus(struct bridge
*b
, unsigned int domain
, unsigned int n
)
46 struct bus
*bus
= xmalloc(sizeof(struct bus
));
49 bus
->sibling
= b
->first_bus
;
50 bus
->first_dev
= NULL
;
51 bus
->last_dev
= &bus
->first_dev
;
57 insert_dev(struct device
*d
, struct bridge
*b
)
59 struct pci_dev
*p
= d
->dev
;
62 if (! (bus
= find_bus(b
, p
->domain
, p
->bus
)))
65 for (c
=b
->child
; c
; c
=c
->next
)
66 if (c
->domain
== p
->domain
&& c
->secondary
<= p
->bus
&& p
->bus
<= c
->subordinate
)
71 bus
= new_bus(b
, p
->domain
, p
->bus
);
73 /* Simple insertion at the end _does_ guarantee the correct order as the
74 * original device list was sorted by (domain, bus, devfn) lexicographically
75 * and all devices on the new list have the same bus number.
78 bus
->last_dev
= &d
->next
;
85 struct device
*d
, *d2
;
86 struct bridge
**last_br
, *b
;
88 /* Build list of bridges */
90 last_br
= &host_bridge
.chain
;
91 for (d
=first_dev
; d
; d
=d
->next
)
93 word
class = d
->dev
->device_class
;
94 byte ht
= get_conf_byte(d
, PCI_HEADER_TYPE
) & 0x7f;
95 if (class == PCI_CLASS_BRIDGE_PCI
&&
96 (ht
== PCI_HEADER_TYPE_BRIDGE
|| ht
== PCI_HEADER_TYPE_CARDBUS
))
98 b
= xmalloc(sizeof(struct bridge
));
99 b
->domain
= d
->dev
->domain
;
100 if (ht
== PCI_HEADER_TYPE_BRIDGE
)
102 b
->primary
= get_conf_byte(d
, PCI_PRIMARY_BUS
);
103 b
->secondary
= get_conf_byte(d
, PCI_SECONDARY_BUS
);
104 b
->subordinate
= get_conf_byte(d
, PCI_SUBORDINATE_BUS
);
108 b
->primary
= get_conf_byte(d
, PCI_CB_PRIMARY_BUS
);
109 b
->secondary
= get_conf_byte(d
, PCI_CB_CARD_BUS
);
110 b
->subordinate
= get_conf_byte(d
, PCI_CB_SUBORDINATE_BUS
);
114 b
->next
= b
->child
= NULL
;
121 /* Create a bridge tree */
123 for (b
=&host_bridge
; b
; b
=b
->chain
)
125 struct bridge
*c
, *best
;
127 for (c
=&host_bridge
; c
; c
=c
->chain
)
128 if (c
!= b
&& (c
== &host_bridge
|| b
->domain
== c
->domain
) &&
129 b
->primary
>= c
->secondary
&& b
->primary
<= c
->subordinate
&&
130 (!best
|| best
->subordinate
- best
->primary
> c
->subordinate
- c
->primary
))
134 b
->next
= best
->child
;
139 /* Insert secondary bus for each bridge */
141 for (b
=&host_bridge
; b
; b
=b
->chain
)
142 if (!find_bus(b
, b
->domain
, b
->secondary
))
143 new_bus(b
, b
->domain
, b
->secondary
);
145 /* Create bus structs and link devices */
147 for (d
=first_dev
; d
;)
150 insert_dev(d
, &host_bridge
);
156 print_it(char *line
, char *p
)
161 for (p
=line
; *p
; p
++)
162 if (*p
== '+' || *p
== '|')
168 static void show_tree_bridge(struct bridge
*, char *, char *);
171 show_tree_dev(struct device
*d
, char *line
, char *p
)
173 struct pci_dev
*q
= d
->dev
;
177 p
+= sprintf(p
, "%02x.%x", q
->dev
, q
->func
);
178 for (b
=&host_bridge
; b
; b
=b
->chain
)
181 if (b
->secondary
== b
->subordinate
)
182 p
+= sprintf(p
, "-[%04x:%02x]-", b
->domain
, b
->secondary
);
184 p
+= sprintf(p
, "-[%04x:%02x-%02x]-", b
->domain
, b
->secondary
, b
->subordinate
);
185 show_tree_bridge(b
, line
, p
);
189 p
+= sprintf(p
, " %s",
190 pci_lookup_name(pacc
, namebuf
, sizeof(namebuf
),
191 PCI_LOOKUP_VENDOR
| PCI_LOOKUP_DEVICE
,
192 q
->vendor_id
, q
->device_id
));
197 show_tree_bus(struct bus
*b
, char *line
, char *p
)
201 else if (!b
->first_dev
->next
)
205 show_tree_dev(b
->first_dev
, line
, p
);
209 struct device
*d
= b
->first_dev
;
214 show_tree_dev(d
, line
, p
+2);
219 show_tree_dev(d
, line
, p
+2);
224 show_tree_bridge(struct bridge
*b
, char *line
, char *p
)
227 if (!b
->first_bus
->sibling
)
229 if (b
== &host_bridge
)
230 p
+= sprintf(p
, "[%04x:%02x]-", b
->domain
, b
->first_bus
->number
);
231 show_tree_bus(b
->first_bus
, line
, p
);
235 struct bus
*u
= b
->first_bus
;
240 k
= p
+ sprintf(p
, "+-[%04x:%02x]-", u
->domain
, u
->number
);
241 show_tree_bus(u
, line
, k
);
244 k
= p
+ sprintf(p
, "\\-[%04x:%02x]-", u
->domain
, u
->number
);
245 show_tree_bus(u
, line
, k
);
255 show_tree_bridge(&host_bridge
, line
, line
);