]> mj.ucw.cz Git - pciutils.git/blob - lspci.c
Intermediate version of pciutils.
[pciutils.git] / lspci.c
1 /*
2  *      $Id: lspci.c,v 1.10 1998/03/31 21:02:16 mj Exp $
3  *
4  *      Linux PCI Utilities -- List All PCI Devices
5  *
6  *      Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
7  *
8  *      Can be freely distributed and used under the terms of the GNU GPL.
9  */
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16
17 #include "pciutils.h"
18
19 /* Options */
20
21 static int verbose;                     /* Show detailed information */
22 static int buscentric_view;             /* Show bus addresses/IRQ's instead of CPU-visible ones */
23 static int show_hex;                    /* Show contents of config space as hexadecimal numbers */
24 static struct pci_filter filter;        /* Device filter */
25 static int show_tree;                   /* Show bus tree */
26 static int machine_readable;            /* Generate machine-readable output */
27 static char *pci_dir = PROC_BUS_PCI;
28
29 static char options[] = "nvbxs:d:ti:p:m";
30
31 static char help_msg[] = "\
32 Usage: lspci [<switches>]\n\
33 \n\
34 -v\t\tBe verbose\n\
35 -n\t\tShow numeric ID's\n\
36 -b\t\tBus-centric view (PCI addresses and IRQ's instead of those seen by the CPU)\n\
37 -x\t\tShow hex-dump of config space (-xx shows full 256 bytes)\n\
38 -s [[<bus>]:][<slot>][.[<func>]]\tShow only devices in selected slots\n\
39 -d [<vendor>]:[<device>]\tShow only selected devices\n\
40 -t\t\tShow bus tree\n\
41 -m\t\tProduce machine-readable output\n\
42 -i <file>\tUse specified ID database instead of " ETC_PCI_IDS "\n\
43 -p <dir>\tUse specified bus directory instead of " PROC_BUS_PCI "\n\
44 ";
45
46 /* Format strings used for IRQ numbers */
47
48 #ifdef ARCH_SPARC64
49 #define IRQ_FORMAT "%08x"
50 #else
51 #define IRQ_FORMAT "%d"
52 #endif
53
54 /* Our view of the PCI bus */
55
56 struct device {
57   struct device *next;
58   byte bus, devfn;
59   word vendid, devid;
60   unsigned int kernel_irq;
61   unsigned long kernel_base_addr[6];
62   byte config[256];
63 };
64
65 static struct device *first_dev, **last_dev = &first_dev;
66
67 /* Miscellaneous routines */
68
69 void *
70 xmalloc(unsigned int howmuch)
71 {
72   void *p = malloc(howmuch);
73   if (!p)
74     {
75       fprintf(stderr, "lspci: Unable to allocate %d bytes of memory\n", howmuch);
76       exit(1);
77     }
78   return p;
79 }
80
81 /* Interface for /proc/bus/pci */
82
83 static void
84 scan_dev_list(void)
85 {
86   FILE *f;
87   byte line[256];
88   byte name[256];
89
90   sprintf(name, "%s/devices", pci_dir);
91   if (! (f = fopen(name, "r")))
92     {
93       perror(name);
94       exit(1);
95     }
96   while (fgets(line, sizeof(line), f))
97     {
98       struct device *d = xmalloc(sizeof(struct device));
99       unsigned int dfn, vend;
100
101       sscanf(line, "%x %x %x %lx %lx %lx %lx %lx %lx",
102              &dfn,
103              &vend,
104              &d->kernel_irq,
105              &d->kernel_base_addr[0],
106              &d->kernel_base_addr[1],
107              &d->kernel_base_addr[2],
108              &d->kernel_base_addr[3],
109              &d->kernel_base_addr[4],
110              &d->kernel_base_addr[5]);
111       d->bus = dfn >> 8U;
112       d->devfn = dfn & 0xff;
113       d->vendid = vend >> 16U;
114       d->devid = vend & 0xffff;
115       if (filter_match(&filter, d->bus, d->devfn, d->vendid, d->devid))
116         {
117           *last_dev = d;
118           last_dev = &d->next;
119           d->next = NULL;
120         }
121     }
122   fclose(f);
123 }
124
125 static inline void
126 make_proc_pci_name(struct device *d, char *p)
127 {
128   sprintf(p, "%s/%02x/%02x.%x",
129           pci_dir, d->bus, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
130 }
131
132 static void
133 scan_config(void)
134 {
135   struct device *d;
136   char name[64];
137   int fd, res;
138   int how_much = (show_hex > 1) ? 256 : 64;
139
140   for(d=first_dev; d; d=d->next)
141     {
142       make_proc_pci_name(d, name);
143       if ((fd = open(name, O_RDONLY)) < 0)
144         {
145           fprintf(stderr, "lspci: Unable to open %s: %m\n", name);
146           exit(1);
147         }
148       res = read(fd, d->config, how_much);
149       if (res < 0)
150         {
151           fprintf(stderr, "lspci: Error reading %s: %m\n", name);
152           exit(1);
153         }
154       if (res != how_much)
155         {
156           fprintf(stderr, "lspci: Only %d bytes of config space available to you\n", res);
157           exit(1);
158         }
159       close(fd);
160     }
161 }
162
163 static void
164 scan_proc(void)
165 {
166   scan_dev_list();
167   scan_config();
168 }
169
170 /* Config space accesses */
171
172 static inline byte
173 get_conf_byte(struct device *d, unsigned int pos)
174 {
175   return d->config[pos];
176 }
177
178 static word
179 get_conf_word(struct device *d, unsigned int pos)
180 {
181   return d->config[pos] | (d->config[pos+1] << 8);
182 }
183
184 static u32
185 get_conf_long(struct device *d, unsigned int pos)
186 {
187   return d->config[pos] |
188     (d->config[pos+1] << 8) |
189     (d->config[pos+2] << 16) |
190     (d->config[pos+3] << 24);
191 }
192
193 /* Sorting */
194
195 static int
196 compare_them(const void *A, const void *B)
197 {
198   const struct device *a = *(const struct device **)A;
199   const struct device *b = *(const struct device **)B;
200
201   if (a->bus < b->bus)
202     return -1;
203   if (a->bus > b->bus)
204     return 1;
205   if (a->devfn < b->devfn)
206     return -1;
207   if (a->devfn > b->devfn)
208     return 1;
209   return 0;
210 }
211
212 static void
213 sort_them(void)
214 {
215   struct device **index, **h;
216   int cnt;
217   struct device *d;
218
219   cnt = 0;
220   for(d=first_dev; d; d=d->next)
221     cnt++;
222   h = index = alloca(sizeof(struct device *) * cnt);
223   for(d=first_dev; d; d=d->next)
224     *h++ = d;
225   qsort(index, cnt, sizeof(struct device *), compare_them);
226   last_dev = &first_dev;
227   h = index;
228   while (cnt--)
229     {
230       *last_dev = *h;
231       last_dev = &(*h)->next;
232       h++;
233     }
234   *last_dev = NULL;
235 }
236
237 /* Normal output */
238
239 static void
240 show_terse(struct device *d)
241 {
242   int c;
243
244   printf("%02x:%02x.%x %s: %s",
245          d->bus,
246          PCI_SLOT(d->devfn),
247          PCI_FUNC(d->devfn),
248          lookup_class(get_conf_word(d, PCI_CLASS_DEVICE)),
249          lookup_device_full(d->vendid, d->devid));
250   if (c = get_conf_byte(d, PCI_REVISION_ID))
251     printf(" (rev %02x)", c);
252   if (verbose && (c = get_conf_byte(d, PCI_CLASS_PROG)))
253     printf(" (prog-if %02x)", c);
254   putchar('\n');
255 }
256
257 static void
258 show_bases(struct device *d, int cnt)
259 {
260   word cmd = get_conf_word(d, PCI_COMMAND);
261   int i;
262
263   for(i=0; i<6; i++)
264     {
265       unsigned long pos;
266       unsigned int flg = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i);
267       if (buscentric_view)
268         pos = flg;
269       else
270         pos = d->kernel_base_addr[i];
271       if (!pos || pos == 0xffffffff)
272         continue;
273       if (flg & PCI_BASE_ADDRESS_SPACE_IO)
274         {
275           if (cmd & PCI_COMMAND_IO)
276             {
277               if (verbose > 1)
278                 printf("\tRegion %d: ", i);
279               else
280                 putchar('\t');
281               printf("I/O ports at %04lx\n", pos & PCI_BASE_ADDRESS_IO_MASK);
282             }
283         }
284       else if (cmd & PCI_COMMAND_MEMORY)
285         {
286           int t = flg & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
287           if (verbose > 1)
288             printf("\tRegion %d: ", i);
289           else
290             putchar('\t');
291           printf("Memory at ");
292           if (t == PCI_BASE_ADDRESS_MEM_TYPE_64)
293             {
294               if (i < cnt - 1)
295                 {
296                   i++;
297                   if (!buscentric_view)
298                     printf("%08x", get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i));
299                 }
300               else
301                 printf("????????");
302             }
303           printf("%08lx (%s, %sprefetchable)\n",
304                  pos & PCI_BASE_ADDRESS_MEM_MASK,
305                  (t == PCI_BASE_ADDRESS_MEM_TYPE_32) ? "32-bit" :
306                  (t == PCI_BASE_ADDRESS_MEM_TYPE_64) ? "64-bit" :
307                  (t == PCI_BASE_ADDRESS_MEM_TYPE_1M) ? "low-1M 32-bit" : "???",
308                  (flg & PCI_BASE_ADDRESS_MEM_PREFETCH) ? "" : "non-");
309         }
310     }
311 }
312
313 static void
314 show_htype0(struct device *d)
315 {
316   u32 rom = get_conf_long(d, PCI_ROM_ADDRESS);
317
318   show_bases(d, 6);
319
320   if (rom & 1)
321     {
322       word cmd = get_conf_word(d, PCI_COMMAND);
323       printf("\tExpansion ROM at %08x%s\n", rom & ~0xfff,
324              (cmd & PCI_COMMAND_MEMORY) ? "" : " [disabled]");
325     }
326 }
327
328 static void
329 show_htype1(struct device *d)
330 {
331   u32 io_base = get_conf_byte(d, PCI_IO_BASE);
332   u32 io_limit = get_conf_byte(d, PCI_IO_LIMIT);
333   u32 io_type = io_base & PCI_IO_RANGE_TYPE_MASK;
334   u32 mem_base = get_conf_word(d, PCI_MEMORY_BASE);
335   u32 mem_limit = get_conf_word(d, PCI_MEMORY_LIMIT);
336   u32 mem_type = mem_base & PCI_MEMORY_RANGE_TYPE_MASK;
337   u32 pref_base = get_conf_word(d, PCI_PREF_MEMORY_BASE);
338   u32 pref_limit = get_conf_word(d, PCI_PREF_MEMORY_LIMIT);
339   u32 pref_type = pref_base & PCI_PREF_RANGE_TYPE_MASK;
340   u32 rom = get_conf_long(d, PCI_ROM_ADDRESS1);
341   word brc = get_conf_word(d, PCI_BRIDGE_CONTROL);
342
343   show_bases(d, 2);
344   printf("\tBus: primary=%02x, secondary=%02x, subordinate=%02x, sec-latency=%d\n",
345          get_conf_byte(d, PCI_PRIMARY_BUS),
346          get_conf_byte(d, PCI_SECONDARY_BUS),
347          get_conf_byte(d, PCI_SUBORDINATE_BUS),
348          get_conf_byte(d, PCI_SEC_LATENCY_TIMER));
349
350   if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
351       (io_type != PCI_IO_RANGE_TYPE_16 && io_type != PCI_IO_RANGE_TYPE_32))
352     printf("\t!!! Unknown I/O range types %x/%x\n", io_base, io_limit);
353   else
354     {
355       io_base = (io_base & PCI_IO_RANGE_MASK) << 8;
356       io_limit = (io_limit & PCI_IO_RANGE_MASK) << 8;
357       if (io_type == PCI_IO_RANGE_TYPE_32)
358         {
359           io_base |= (get_conf_word(d, PCI_IO_BASE_UPPER16) << 16);
360           io_limit |= (get_conf_word(d, PCI_IO_LIMIT_UPPER16) << 16);
361         }
362       if (io_base)
363         printf("\tI/O behind bridge: %08x-%08x\n", io_base, io_limit+0xfff);
364     }
365
366   if (mem_type != (mem_limit & PCI_MEMORY_RANGE_TYPE_MASK) ||
367       mem_type)
368     printf("\t!!! Unknown memory range types %x/%x\n", mem_base, mem_limit);
369   else if (mem_base)
370     {
371       mem_base = (mem_base & PCI_MEMORY_RANGE_MASK) << 16;
372       mem_limit = (mem_limit & PCI_MEMORY_RANGE_MASK) << 16;
373       printf("\tMemory behind bridge: %08x-%08x\n", mem_base, mem_limit + 0xfffff);
374     }
375
376   if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
377       (pref_type != PCI_PREF_RANGE_TYPE_32 && pref_type != PCI_PREF_RANGE_TYPE_64))
378     printf("\t!!! Unknown prefetchable memory range types %x/%x\n", pref_base, pref_limit);
379   else if (pref_base)
380     {
381       pref_base = (pref_base & PCI_PREF_RANGE_MASK) << 16;
382       pref_limit = (pref_limit & PCI_PREF_RANGE_MASK) << 16;
383       if (pref_type == PCI_PREF_RANGE_TYPE_32)
384         printf("\tPrefetchable memory behind bridge: %08x-%08x\n", pref_base, pref_limit);
385       else
386         printf("\tPrefetchable memory behind bridge: %08x%08x-%08x%08x\n",
387                get_conf_long(d, PCI_PREF_BASE_UPPER32),
388                pref_base,
389                get_conf_long(d, PCI_PREF_LIMIT_UPPER32),
390                pref_limit);
391     }
392
393   if (get_conf_word(d, PCI_SEC_STATUS) & PCI_STATUS_SIG_SYSTEM_ERROR)
394     printf("\tSecondary status: SERR\n");
395
396   if (rom & 1)
397     {
398       word cmd = get_conf_word(d, PCI_COMMAND);
399       printf("\tExpansion ROM at %08x%s\n", rom & ~0xfff,
400              (cmd & PCI_COMMAND_MEMORY) ? "" : " [disabled]");
401     }
402
403   if (verbose > 1)
404     printf("\tBridgeCtl: Parity%c SERR%c NoISA%c VGA%c MAbort%c >Reset%c FastB2B%c\n",
405            (brc & PCI_BRIDGE_CTL_PARITY) ? '+' : '-',
406            (brc & PCI_BRIDGE_CTL_SERR) ? '+' : '-',
407            (brc & PCI_BRIDGE_CTL_NO_ISA) ? '+' : '-',
408            (brc & PCI_BRIDGE_CTL_VGA) ? '+' : '-',
409            (brc & PCI_BRIDGE_CTL_MASTER_ABORT) ? '+' : '-',
410            (brc & PCI_BRIDGE_CTL_BUS_RESET) ? '+' : '-',
411            (brc & PCI_BRIDGE_CTL_FAST_BACK) ? '+' : '-');
412 }
413
414 static void
415 show_htype2(struct device *d)
416 {
417 }
418
419 static void
420 show_verbose(struct device *d)
421 {
422   word status = get_conf_word(d, PCI_STATUS);
423   word cmd = get_conf_word(d, PCI_COMMAND);
424   word class = get_conf_word(d, PCI_CLASS_DEVICE);
425   byte bist = get_conf_byte(d, PCI_BIST);
426   byte htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
427   byte latency = get_conf_byte(d, PCI_LATENCY_TIMER);
428   byte cache_line = get_conf_byte(d, PCI_CACHE_LINE_SIZE);
429   byte max_lat, min_gnt;
430   byte int_pin = get_conf_byte(d, PCI_INTERRUPT_PIN);
431   byte int_line = get_conf_byte(d, PCI_INTERRUPT_LINE);
432   unsigned int irq;
433   word subsys_v, subsys_d;
434
435   show_terse(d);
436
437   switch (htype)
438     {
439     case PCI_HEADER_TYPE_NORMAL:
440       if (class == PCI_CLASS_BRIDGE_PCI)
441         {
442         badhdr:
443           printf("\t!!! Header type %02x doesn't match class code %04x\n", htype, class);
444           return;
445         }
446       max_lat = get_conf_byte(d, PCI_MAX_LAT);
447       min_gnt = get_conf_byte(d, PCI_MIN_GNT);
448       subsys_v = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID);
449       subsys_d = get_conf_word(d, PCI_SUBSYSTEM_ID);
450       break;
451     case PCI_HEADER_TYPE_BRIDGE:
452       if (class != PCI_CLASS_BRIDGE_PCI)
453         goto badhdr;
454       irq = int_line = int_pin = min_gnt = max_lat = 0;
455       subsys_v = subsys_d = 0;
456       break;
457     case PCI_HEADER_TYPE_CARDBUS:
458       if ((class >> 8) != PCI_BASE_CLASS_BRIDGE)
459         goto badhdr;
460       irq = int_line = int_pin = min_gnt = max_lat = 0;
461       subsys_v = subsys_d = 0;
462       break;
463     default:
464       printf("\t!!! Unknown header type %02x\n", htype);
465       return;
466     }
467
468   if (buscentric_view)
469     irq = int_line;
470   else
471     irq = d->kernel_irq;
472
473   if (verbose > 1)
474     {
475       if (subsys_v)
476         printf("\tSubsystem ID: %04x:%04x\n", subsys_v, subsys_d);
477       printf("\tControl: I/O%c Mem%c BusMaster%c SpecCycle%c MemWINV%c VGASnoop%c ParErr%c Stepping%c SERR%c FastB2B%c\n",
478              (cmd & PCI_COMMAND_IO) ? '+' : '-',
479              (cmd & PCI_COMMAND_MEMORY) ? '+' : '-',
480              (cmd & PCI_COMMAND_MASTER) ? '+' : '-',
481              (cmd & PCI_COMMAND_SPECIAL) ? '+' : '-',
482              (cmd & PCI_COMMAND_INVALIDATE) ? '+' : '-',
483              (cmd & PCI_COMMAND_VGA_PALETTE) ? '+' : '-',
484              (cmd & PCI_COMMAND_PARITY) ? '+' : '-',
485              (cmd & PCI_COMMAND_WAIT) ? '+' : '-',
486              (cmd & PCI_COMMAND_SERR) ? '+' : '-',
487              (cmd & PCI_COMMAND_FAST_BACK) ? '+' : '-');
488       printf("\tStatus: 66Mhz%c UDF%c FastB2B%c ParErr%c DEVSEL=%s >TAbort%c <TAbort%c <MAbort%c >SERR%c <PERR%c\n",
489              (status & PCI_STATUS_66MHZ) ? '+' : '-',
490              (status & PCI_STATUS_UDF) ? '+' : '-',
491              (status & PCI_STATUS_FAST_BACK) ? '+' : '-',
492              (status & PCI_STATUS_PARITY) ? '+' : '-',
493              ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) ? "slow" :
494              ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) ? "medium" :
495              ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) ? "fast" : "??",
496              (status & PCI_STATUS_SIG_TARGET_ABORT) ? '+' : '-',
497              (status & PCI_STATUS_REC_TARGET_ABORT) ? '+' : '-',
498              (status & PCI_STATUS_REC_MASTER_ABORT) ? '+' : '-',
499              (status & PCI_STATUS_SIG_SYSTEM_ERROR) ? '+' : '-',
500              (status & PCI_STATUS_DETECTED_PARITY) ? '+' : '-');
501       if (cmd & PCI_COMMAND_MASTER)
502         {
503           printf("\tLatency: ");
504           if (min_gnt)
505             printf("%d min, ", min_gnt);
506           if (max_lat)
507             printf("%d max, ", max_lat);
508           printf("%d set", latency);
509           if (cache_line)
510             printf(", cache line size %02x", cache_line);
511           putchar('\n');
512         }
513       if (int_pin)
514         printf("\tInterrupt: pin %c routed to IRQ " IRQ_FORMAT "\n", 'A' + int_pin - 1, irq);
515     }
516   else
517     {
518       printf("\tFlags: ");
519       if (cmd & PCI_COMMAND_MASTER)
520         printf("bus master, ");
521       if (cmd & PCI_COMMAND_VGA_PALETTE)
522         printf("VGA palette snoop, ");
523       if (cmd & PCI_COMMAND_WAIT)
524         printf("stepping, ");
525       if (cmd & PCI_COMMAND_FAST_BACK)
526         printf("fast Back2Back, ");
527       if (status & PCI_STATUS_66MHZ)
528         printf("66Mhz, ");
529       if (status & PCI_STATUS_UDF)
530         printf("user-definable features, ");
531       printf("%s devsel",
532              ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) ? "slow" :
533              ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) ? "medium" :
534              ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) ? "fast" : "??");
535       if (cmd & PCI_COMMAND_MASTER)
536         printf(", latency %d", latency);
537       if (int_pin)
538         if (d->kernel_irq)
539           printf(", IRQ " IRQ_FORMAT, irq);
540         else
541           printf(", IRQ ?");
542       putchar('\n');
543     }
544
545   if (bist & PCI_BIST_CAPABLE)
546     {
547       if (bist & PCI_BIST_START)
548         printf("\tBIST is running\n");
549       else
550         printf("\tBIST result: %02x\n", bist & PCI_BIST_CODE_MASK);
551     }
552
553   switch (htype)
554     {
555     case PCI_HEADER_TYPE_NORMAL:
556       show_htype0(d);
557       break;
558     case PCI_HEADER_TYPE_BRIDGE:
559       show_htype1(d);
560       break;
561     case PCI_HEADER_TYPE_CARDBUS:
562       show_htype2(d);
563       break;
564     }
565 }
566
567 static void
568 show_hex_dump(struct device *d)
569 {
570   int i;
571   int limit = (show_hex > 1) ? 256 : 64;
572
573   for(i=0; i<limit; i++)
574     {
575       if (! (i & 15))
576         printf("%02x:", i);
577       printf(" %02x", get_conf_byte(d, i));
578       if ((i & 15) == 15)
579         putchar('\n');
580     }
581 }
582
583 static void
584 show_machine(struct device *d)
585 {
586   int c;
587
588   if (verbose)
589     {
590       printf("Device:\t%02x:%02x.%x\n", d->bus, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
591       printf("Class:\t%s\n", lookup_class(get_conf_word(d, PCI_CLASS_DEVICE)));
592       printf("Vendor:\t%s\n", lookup_vendor(d->vendid));
593       printf("Device:\t%s\n", lookup_device(d->vendid, d->devid));
594       if (c = get_conf_byte(d, PCI_REVISION_ID))
595         printf("Rev:\t%02x\n", c);
596       if (c = get_conf_byte(d, PCI_CLASS_PROG))
597         printf("ProgIf:\t%02x\n", c);
598     }
599   else
600     {
601       printf("%02x:%02x.%x ", d->bus, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
602       printf("\"%s\" \"%s\" \"%s\"",
603              lookup_class(get_conf_word(d, PCI_CLASS_DEVICE)),
604              lookup_vendor(d->vendid),
605              lookup_device(d->vendid, d->devid));
606       if (c = get_conf_byte(d, PCI_REVISION_ID))
607         printf(" -r%02x", c);
608       if (c = get_conf_byte(d, PCI_CLASS_PROG))
609         printf(" -p%02x", c);
610       putchar('\n');
611     }
612 }
613
614 static void
615 show(void)
616 {
617   struct device *d;
618
619   for(d=first_dev; d; d=d->next)
620     {
621       if (machine_readable)
622         show_machine(d);
623       else if (verbose)
624         show_verbose(d);
625       else
626         show_terse(d);
627       if (show_hex)
628         show_hex_dump(d);
629       if (verbose || show_hex)
630         putchar('\n');
631     }
632 }
633
634 /* Tree output */
635
636 struct bridge {
637   struct bridge *chain;                 /* Single-linked list of bridges */
638   struct bridge *next, *child;          /* Tree of bridges */
639   struct bus *first_bus;                /* List of busses connected to this bridge */
640   unsigned int primary, secondary, subordinate; /* Bus numbers */
641   struct device *br_dev;
642 };
643
644 struct bus {
645   unsigned int number;
646   struct bus *sibling;
647   struct device *first_dev, **last_dev;
648 };
649
650 static struct bridge host_bridge = { NULL, NULL, NULL, NULL, ~0, 0, ~0, NULL };
651
652 static struct bus *
653 find_bus(struct bridge *b, unsigned int n)
654 {
655   struct bus *bus;
656
657   for(bus=b->first_bus; bus; bus=bus->sibling)
658     if (bus->number == n)
659       break;
660   return bus;
661 }
662
663 static struct bus *
664 new_bus(struct bridge *b, unsigned int n)
665 {
666   struct bus *bus = xmalloc(sizeof(struct bus));
667
668   bus = xmalloc(sizeof(struct bus));
669   bus->number = n;
670   bus->sibling = b->first_bus;
671   bus->first_dev = NULL;
672   bus->last_dev = &bus->first_dev;
673   b->first_bus = bus;
674   return bus;
675 }
676
677 static void
678 insert_dev(struct device *d, struct bridge *b)
679 {
680   struct bus *bus;
681
682   if (! (bus = find_bus(b, d->bus)))
683     {
684       struct bridge *c;
685       for(c=b->child; c; c=c->next)
686         if (c->secondary <= d->bus && d->bus <= c->subordinate)
687           return insert_dev(d, c);
688       bus = new_bus(b, d->bus);
689     }
690   /* Simple insertion at the end _does_ guarantee the correct order as the
691    * original device list was sorted by (bus, devfn) lexicographically
692    * and all devices on the new list have the same bus number.
693    */
694   *bus->last_dev = d;
695   bus->last_dev = &d->next;
696   d->next = NULL;
697 }
698
699 static void
700 grow_tree(void)
701 {
702   struct device *d, *d2;
703   struct bridge **last_br, *b;
704
705   /* Build list of bridges */
706
707   last_br = &host_bridge.chain;
708   for(d=first_dev; d; d=d->next)
709     {
710       word class = get_conf_word(d, PCI_CLASS_DEVICE);
711       if (class == PCI_CLASS_BRIDGE_PCI && (get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f) == 1)
712         {
713           b = xmalloc(sizeof(struct bridge));
714           b->primary = get_conf_byte(d, PCI_PRIMARY_BUS);
715           b->secondary = get_conf_byte(d, PCI_SECONDARY_BUS);
716           b->subordinate = get_conf_byte(d, PCI_SUBORDINATE_BUS);
717           *last_br = b;
718           last_br = &b->chain;
719           b->next = b->child = NULL;
720           b->first_bus = NULL;
721           b->br_dev = d;
722         }
723     }
724   *last_br = NULL;
725
726   /* Create a bridge tree */
727
728   for(b=&host_bridge; b; b=b->chain)
729     {
730       struct bridge *c, *best;
731       best = NULL;
732       for(c=&host_bridge; c; c=c->chain)
733         if (c != b && b->primary >= c->secondary && b->primary <= c->subordinate &&
734             (!best || best->subordinate - best->primary > c->subordinate - c->primary))
735           best = c;
736       if (best)
737         {
738           b->next = best->child;
739           best->child = b;
740         }
741     }
742
743   /* Insert secondary bus for each bridge */
744
745   for(b=&host_bridge; b; b=b->chain)
746     if (!find_bus(b, b->secondary))
747       new_bus(b, b->secondary);
748
749   /* Create bus structs and link devices */
750
751   for(d=first_dev; d;)
752     {
753       d2 = d->next;
754       insert_dev(d, &host_bridge);
755       d = d2;
756     }
757 }
758
759 static void
760 print_it(byte *line, byte *p)
761 {
762   *p++ = '\n';
763   *p = 0;
764   fputs(line, stdout);
765   for(p=line; *p; p++)
766     if (*p == '+' || *p == '|')
767       *p = '|';
768     else
769       *p = ' ';
770 }
771
772 static void show_tree_bridge(struct bridge *, byte *, byte *);
773
774 static void
775 show_tree_dev(struct device *d, byte *line, byte *p)
776 {
777   struct bridge *b;
778
779   p += sprintf(p, "%02x.%x", PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
780   for(b=&host_bridge; b; b=b->chain)
781     if (b->br_dev == d)
782       {
783         if (b->secondary == b->subordinate)
784           p += sprintf(p, "-[%02x]-", b->secondary);
785         else
786           p += sprintf(p, "-[%02x-%02x]-", b->secondary, b->subordinate);
787         show_tree_bridge(b, line, p);
788         return;
789       }
790   if (verbose)
791     p += sprintf(p, "  %s", lookup_device_full(d->vendid, d->devid));
792   print_it(line, p);
793 }
794
795 static void
796 show_tree_bus(struct bus *b, byte *line, byte *p)
797 {
798   if (!b->first_dev)
799     print_it(line, p);
800   else if (!b->first_dev->next)
801     {
802       *p++ = '-';
803       *p++ = '-';
804       show_tree_dev(b->first_dev, line, p);
805     }
806   else
807     {
808       struct device *d = b->first_dev;
809       while (d->next)
810         {
811           p[0] = '+';
812           p[1] = '-';
813           show_tree_dev(d, line, p+2);
814           d = d->next;
815         }
816       p[0] = '\\';
817       p[1] = '-';
818       show_tree_dev(d, line, p+2);
819     }
820 }
821
822 static void
823 show_tree_bridge(struct bridge *b, byte *line, byte *p)
824 {
825   *p++ = '-';
826   if (!b->first_bus->sibling)
827     {
828       if (b == &host_bridge)
829         p += sprintf(p, "[%02x]-", b->first_bus->number);
830       show_tree_bus(b->first_bus, line, p);
831     }
832   else
833     {
834       struct bus *u = b->first_bus;
835       byte *k;
836
837       while (u->sibling)
838         {
839           k = p + sprintf(p, "+-[%02x]-", u->number);
840           show_tree_bus(u, line, k);
841           u = u->sibling;
842         }
843       k = p + sprintf(p, "\\-[%02x]-", u->number);
844       show_tree_bus(u, line, k);
845     }
846 }
847
848 static void
849 show_forest(void)
850 {
851   char line[256];
852
853   grow_tree();
854   show_tree_bridge(&host_bridge, line, line);
855 }
856
857 /* Main */
858
859 int
860 main(int argc, char **argv)
861 {
862   int i;
863   char *msg;
864
865   filter_init(&filter);
866   while ((i = getopt(argc, argv, options)) != -1)
867     switch (i)
868       {
869       case 'n':
870         show_numeric_ids = 1;
871         break;
872       case 'v':
873         verbose++;
874         break;
875       case 'b':
876         buscentric_view = 1;
877         break;
878       case 's':
879         if (msg = filter_parse_slot(&filter, optarg))
880           {
881             fprintf(stderr, "lspci: -f: %s\n", msg);
882             return 1;
883           }
884         break;
885       case 'd':
886         if (msg = filter_parse_id(&filter, optarg))
887           {
888             fprintf(stderr, "lspci: -d: %s\n", msg);
889             return 1;
890           }
891         break;
892       case 'x':
893         show_hex++;
894         break;
895       case 't':
896         show_tree++;
897         break;
898       case 'i':
899         pci_ids = optarg;
900         break;
901       case 'p':
902         pci_dir = optarg;
903         break;
904       case 'm':
905         machine_readable++;
906         break;
907       default:
908       bad:
909         fprintf(stderr, help_msg);
910         return 1;
911       }
912   if (optind < argc)
913     goto bad;
914
915   scan_proc();
916   sort_them();
917   if (show_tree)
918     show_forest();
919   else
920     show();
921
922   return 0;
923 }