Annotation of embedaddon/pciutils/ls-tree.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     The PCI Utilities -- Show Bus Tree
                      3:  *
                      4:  *     Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
                      5:  *
                      6:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      7:  */
                      8: 
                      9: #include <stdio.h>
                     10: #include <string.h>
                     11: 
                     12: #include "lspci.h"
                     13: 
                     14: struct bridge {
                     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 */
                     18:   unsigned int domain;
                     19:   unsigned int primary, secondary, subordinate;        /* Bus numbers */
                     20:   struct device *br_dev;
                     21: };
                     22: 
                     23: struct bus {
                     24:   unsigned int domain;
                     25:   unsigned int number;
                     26:   struct bus *sibling;
                     27:   struct device *first_dev, **last_dev;
                     28: };
                     29: 
                     30: static struct bridge host_bridge = { NULL, NULL, NULL, NULL, 0, ~0, 0, ~0, NULL };
                     31: 
                     32: static struct bus *
                     33: find_bus(struct bridge *b, unsigned int domain, unsigned int n)
                     34: {
                     35:   struct bus *bus;
                     36: 
                     37:   for (bus=b->first_bus; bus; bus=bus->sibling)
                     38:     if (bus->domain == domain && bus->number == n)
                     39:       break;
                     40:   return bus;
                     41: }
                     42: 
                     43: static struct bus *
                     44: new_bus(struct bridge *b, unsigned int domain, unsigned int n)
                     45: {
                     46:   struct bus *bus = xmalloc(sizeof(struct bus));
                     47:   bus->domain = domain;
                     48:   bus->number = n;
                     49:   bus->sibling = b->first_bus;
                     50:   bus->first_dev = NULL;
                     51:   bus->last_dev = &bus->first_dev;
                     52:   b->first_bus = bus;
                     53:   return bus;
                     54: }
                     55: 
                     56: static void
                     57: insert_dev(struct device *d, struct bridge *b)
                     58: {
                     59:   struct pci_dev *p = d->dev;
                     60:   struct bus *bus;
                     61: 
                     62:   if (! (bus = find_bus(b, p->domain, p->bus)))
                     63:     {
                     64:       struct bridge *c;
                     65:       for (c=b->child; c; c=c->next)
                     66:        if (c->domain == p->domain && c->secondary <= p->bus && p->bus <= c->subordinate)
                     67:           {
                     68:             insert_dev(d, c);
                     69:             return;
                     70:           }
                     71:       bus = new_bus(b, p->domain, p->bus);
                     72:     }
                     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.
                     76:    */
                     77:   *bus->last_dev = d;
                     78:   bus->last_dev = &d->next;
                     79:   d->next = NULL;
                     80: }
                     81: 
                     82: static void
                     83: grow_tree(void)
                     84: {
                     85:   struct device *d, *d2;
                     86:   struct bridge **last_br, *b;
                     87: 
                     88:   /* Build list of bridges */
                     89: 
                     90:   last_br = &host_bridge.chain;
                     91:   for (d=first_dev; d; d=d->next)
                     92:     {
                     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))
                     97:        {
                     98:          b = xmalloc(sizeof(struct bridge));
                     99:          b->domain = d->dev->domain;
                    100:          if (ht == PCI_HEADER_TYPE_BRIDGE)
                    101:            {
                    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);
                    105:            }
                    106:          else
                    107:            {
                    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);
                    111:            }
                    112:          *last_br = b;
                    113:          last_br = &b->chain;
                    114:          b->next = b->child = NULL;
                    115:          b->first_bus = NULL;
                    116:          b->br_dev = d;
                    117:        }
                    118:     }
                    119:   *last_br = NULL;
                    120: 
                    121:   /* Create a bridge tree */
                    122: 
                    123:   for (b=&host_bridge; b; b=b->chain)
                    124:     {
                    125:       struct bridge *c, *best;
                    126:       best = NULL;
                    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))
                    131:          best = c;
                    132:       if (best)
                    133:        {
                    134:          b->next = best->child;
                    135:          best->child = b;
                    136:        }
                    137:     }
                    138: 
                    139:   /* Insert secondary bus for each bridge */
                    140: 
                    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);
                    144: 
                    145:   /* Create bus structs and link devices */
                    146: 
                    147:   for (d=first_dev; d;)
                    148:     {
                    149:       d2 = d->next;
                    150:       insert_dev(d, &host_bridge);
                    151:       d = d2;
                    152:     }
                    153: }
                    154: 
                    155: static void
                    156: print_it(char *line, char *p)
                    157: {
                    158:   *p++ = '\n';
                    159:   *p = 0;
                    160:   fputs(line, stdout);
                    161:   for (p=line; *p; p++)
                    162:     if (*p == '+' || *p == '|')
                    163:       *p = '|';
                    164:     else
                    165:       *p = ' ';
                    166: }
                    167: 
                    168: static void show_tree_bridge(struct bridge *, char *, char *);
                    169: 
                    170: static void
                    171: show_tree_dev(struct device *d, char *line, char *p)
                    172: {
                    173:   struct pci_dev *q = d->dev;
                    174:   struct bridge *b;
                    175:   char namebuf[256];
                    176: 
                    177:   p += sprintf(p, "%02x.%x", q->dev, q->func);
                    178:   for (b=&host_bridge; b; b=b->chain)
                    179:     if (b->br_dev == d)
                    180:       {
                    181:        if (b->secondary == b->subordinate)
                    182:          p += sprintf(p, "-[%02x]-", b->secondary);
                    183:        else
                    184:          p += sprintf(p, "-[%02x-%02x]-", b->secondary, b->subordinate);
                    185:         show_tree_bridge(b, line, p);
                    186:         return;
                    187:       }
                    188:   if (verbose)
                    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));
                    193:   print_it(line, p);
                    194: }
                    195: 
                    196: static void
                    197: show_tree_bus(struct bus *b, char *line, char *p)
                    198: {
                    199:   if (!b->first_dev)
                    200:     print_it(line, p);
                    201:   else if (!b->first_dev->next)
                    202:     {
                    203:       *p++ = '-';
                    204:       *p++ = '-';
                    205:       show_tree_dev(b->first_dev, line, p);
                    206:     }
                    207:   else
                    208:     {
                    209:       struct device *d = b->first_dev;
                    210:       while (d->next)
                    211:        {
                    212:          p[0] = '+';
                    213:          p[1] = '-';
                    214:          show_tree_dev(d, line, p+2);
                    215:          d = d->next;
                    216:        }
                    217:       p[0] = '\\';
                    218:       p[1] = '-';
                    219:       show_tree_dev(d, line, p+2);
                    220:     }
                    221: }
                    222: 
                    223: static void
                    224: show_tree_bridge(struct bridge *b, char *line, char *p)
                    225: {
                    226:   *p++ = '-';
                    227:   if (!b->first_bus->sibling)
                    228:     {
                    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);
                    232:     }
                    233:   else
                    234:     {
                    235:       struct bus *u = b->first_bus;
                    236:       char *k;
                    237: 
                    238:       while (u->sibling)
                    239:         {
                    240:           k = p + sprintf(p, "+-[%04x:%02x]-", u->domain, u->number);
                    241:           show_tree_bus(u, line, k);
                    242:           u = u->sibling;
                    243:         }
                    244:       k = p + sprintf(p, "\\-[%04x:%02x]-", u->domain, u->number);
                    245:       show_tree_bus(u, line, k);
                    246:     }
                    247: }
                    248: 
                    249: void
                    250: show_forest(void)
                    251: {
                    252:   char line[256];
                    253: 
                    254:   grow_tree();
                    255:   show_tree_bridge(&host_bridge, line, line);
                    256: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>