- if (show_hex)
- show_hex_dump(d);
- if (verbose || show_hex)
- putchar('\n');
- }
-}
-
-/* Tree output */
-
-struct bridge {
- struct bridge *chain; /* Single-linked list of bridges */
- struct bridge *next, *child; /* Tree of bridges */
- struct bus *first_bus; /* List of busses connected to this bridge */
- unsigned int primary, secondary, subordinate; /* Bus numbers */
- struct device *br_dev;
-};
-
-struct bus {
- unsigned int number;
- struct bus *sibling;
- struct device *first_dev, **last_dev;
-};
-
-static struct bridge host_bridge = { NULL, NULL, NULL, NULL, ~0, 0, ~0, NULL };
-
-static struct bus *
-find_bus(struct bridge *b, unsigned int n)
-{
- struct bus *bus;
-
- for(bus=b->first_bus; bus; bus=bus->sibling)
- if (bus->number == n)
- break;
- return bus;
-}
-
-static struct bus *
-new_bus(struct bridge *b, unsigned int n)
-{
- struct bus *bus = xmalloc(sizeof(struct bus));
-
- bus = xmalloc(sizeof(struct bus));
- bus->number = n;
- bus->sibling = b->first_bus;
- bus->first_dev = NULL;
- bus->last_dev = &bus->first_dev;
- b->first_bus = bus;
- return bus;
-}
-
-static void
-insert_dev(struct device *d, struct bridge *b)
-{
- struct bus *bus;
-
- if (! (bus = find_bus(b, d->bus)))
- {
- struct bridge *c;
- for(c=b->child; c; c=c->next)
- if (c->secondary <= d->bus && d->bus <= c->subordinate)
- return insert_dev(d, c);
- bus = new_bus(b, d->bus);
- }
- /* Simple insertion at the end _does_ guarantee the correct order as the
- * original device list was sorted by (bus, devfn) lexicographically
- * and all devices on the new list have the same bus number.
- */
- *bus->last_dev = d;
- bus->last_dev = &d->next;
- d->next = NULL;
-}
-
-static void
-grow_tree(void)
-{
- struct device *d, *d2;
- struct bridge **last_br, *b;
-
- /* Build list of bridges */
-
- last_br = &host_bridge.chain;
- for(d=first_dev; d; d=d->next)
- {
- word class = get_conf_word(d, PCI_CLASS_DEVICE);
- byte ht = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
- if (class == PCI_CLASS_BRIDGE_PCI &&
- (ht == PCI_HEADER_TYPE_BRIDGE || ht == PCI_HEADER_TYPE_CARDBUS))
- {
- b = xmalloc(sizeof(struct bridge));
- if (ht == PCI_HEADER_TYPE_BRIDGE)
- {
- b->primary = get_conf_byte(d, PCI_CB_PRIMARY_BUS);
- b->secondary = get_conf_byte(d, PCI_CB_CARD_BUS);
- b->subordinate = get_conf_byte(d, PCI_CB_SUBORDINATE_BUS);
- }
- else
- {
- b->primary = get_conf_byte(d, PCI_PRIMARY_BUS);
- b->secondary = get_conf_byte(d, PCI_SECONDARY_BUS);
- b->subordinate = get_conf_byte(d, PCI_SUBORDINATE_BUS);
- }
- *last_br = b;
- last_br = &b->chain;
- b->next = b->child = NULL;
- b->first_bus = NULL;
- b->br_dev = d;
- }
- }
- *last_br = NULL;
-
- /* Create a bridge tree */
-
- for(b=&host_bridge; b; b=b->chain)
- {
- struct bridge *c, *best;
- best = NULL;
- for(c=&host_bridge; c; c=c->chain)
- if (c != b && b->primary >= c->secondary && b->primary <= c->subordinate &&
- (!best || best->subordinate - best->primary > c->subordinate - c->primary))
- best = c;
- if (best)
- {
- b->next = best->child;
- best->child = b;
- }
- }
-
- /* Insert secondary bus for each bridge */
-
- for(b=&host_bridge; b; b=b->chain)
- if (!find_bus(b, b->secondary))
- new_bus(b, b->secondary);
-
- /* Create bus structs and link devices */
-
- for(d=first_dev; d;)
- {
- d2 = d->next;
- insert_dev(d, &host_bridge);
- d = d2;
- }
-}
-
-static void
-print_it(byte *line, byte *p)
-{
- *p++ = '\n';
- *p = 0;
- fputs(line, stdout);
- for(p=line; *p; p++)
- if (*p == '+' || *p == '|')
- *p = '|';
- else
- *p = ' ';
-}
-
-static void show_tree_bridge(struct bridge *, byte *, byte *);
-
-static void
-show_tree_dev(struct device *d, byte *line, byte *p)
-{
- struct bridge *b;
-
- p += sprintf(p, "%02x.%x", PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
- for(b=&host_bridge; b; b=b->chain)
- if (b->br_dev == d)
- {
- if (b->secondary == b->subordinate)
- p += sprintf(p, "-[%02x]-", b->secondary);
- else
- p += sprintf(p, "-[%02x-%02x]-", b->secondary, b->subordinate);
- show_tree_bridge(b, line, p);
- return;
- }
- if (verbose)
- p += sprintf(p, " %s", lookup_device_full(d->vendid, d->devid));
- print_it(line, p);
-}
-
-static void
-show_tree_bus(struct bus *b, byte *line, byte *p)
-{
- if (!b->first_dev)
- print_it(line, p);
- else if (!b->first_dev->next)
- {
- *p++ = '-';
- *p++ = '-';
- show_tree_dev(b->first_dev, line, p);
- }
- else
- {
- struct device *d = b->first_dev;
- while (d->next)
- {
- p[0] = '+';
- p[1] = '-';
- show_tree_dev(d, line, p+2);
- d = d->next;
- }
- p[0] = '\\';
- p[1] = '-';
- show_tree_dev(d, line, p+2);