]> git.ipfire.org Git - thirdparty/pciutils.git/blame - lspci.c
Fixed buffer overflows in ls-tree.c
[thirdparty/pciutils.git] / lspci.c
CommitLineData
98e39e09 1/*
4284af58 2 * The PCI Utilities -- List All PCI Devices
98e39e09 3 *
bf72d3e9 4 * Copyright (c) 1997--2020 Martin Mares <mj@ucw.cz>
98e39e09
MM
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#include <stdlib.h>
727ce158 12#include <stdarg.h>
98e39e09 13
c7a34993 14#include "lspci.h"
98e39e09
MM
15
16/* Options */
17
c7a34993 18int verbose; /* Show detailed information */
a387042e 19static int opt_hex; /* Show contents of config space as hexadecimal numbers */
c7a34993 20struct pci_filter filter; /* Device filter */
ce22dfec 21static int opt_filter; /* Any filter was given */
a387042e 22static int opt_tree; /* Show bus tree */
62e78fa6 23static int opt_path; /* Show bridge path */
a387042e
MM
24static int opt_machine; /* Generate machine-readable output */
25static int opt_map_mode; /* Bus mapping mode enabled */
26static int opt_domains; /* Show domain numbers (0=disabled, 1=auto-detected, 2=requested) */
11339c0d 27static int opt_kernel; /* Show kernel drivers */
cca2f7c6
MM
28static int opt_query_dns; /* Query the DNS (0=disabled, 1=enabled, 2=refresh cache) */
29static int opt_query_all; /* Query the DNS for all entries */
c7a34993 30char *opt_pcimap; /* Override path to Linux modules.pcimap */
98e39e09 31
81afa98c
MM
32const char program_name[] = "lspci";
33
62e78fa6 34static char options[] = "nvbxs:d:tPi:mgp:qkMDQ" GENERIC_OPTIONS ;
cca2f7c6
MM
35
36static char help_msg[] =
37"Usage: lspci [<switches>]\n"
38"\n"
1b99a704
MM
39"Basic display modes:\n"
40"-mm\t\tProduce machine-readable output (single -m for an obsolete format)\n"
41"-t\t\tShow bus tree\n"
42"\n"
43"Display options:\n"
c5751fb0 44"-v\t\tBe verbose (-vv or -vvv for higher verbosity)\n"
1b99a704
MM
45#ifdef PCI_OS_LINUX
46"-k\t\tShow kernel drivers handling each device\n"
47#endif
48"-x\t\tShow hex-dump of the standard part of the config space\n"
49"-xxx\t\tShow hex-dump of the whole config space (dangerous; root only)\n"
50"-xxxx\t\tShow hex-dump of the 4096-byte extended config space (root only)\n"
51"-b\t\tBus-centric view (addresses and IRQ's as seen by the bus)\n"
52"-D\t\tAlways show domain numbers\n"
62e78fa6
MM
53"-P\t\tDisplay bridge path in addition to bus and device number\n"
54"-PP\t\tDisplay bus path in addition to bus and device number\n"
1b99a704
MM
55"\n"
56"Resolving of device ID's to names:\n"
cca2f7c6
MM
57"-n\t\tShow numeric ID's\n"
58"-nn\t\tShow both textual and numeric ID's (names & numbers)\n"
59#ifdef PCI_USE_DNS
60"-q\t\tQuery the PCI ID database for unknown ID's via DNS\n"
61"-qq\t\tAs above, but re-query locally cached entries\n"
62"-Q\t\tQuery the PCI ID database for all ID's via DNS\n"
63#endif
1b99a704
MM
64"\n"
65"Selection of devices:\n"
cca2f7c6 66"-s [[[[<domain>]:]<bus>]:][<slot>][.[<func>]]\tShow only devices in selected slots\n"
4d1c9525 67"-d [<vendor>]:[<device>][:<class>]\t\tShow only devices with specified ID's\n"
1b99a704
MM
68"\n"
69"Other options:\n"
cca2f7c6 70"-i <file>\tUse specified ID database instead of %s\n"
c1c952d2 71#ifdef PCI_OS_LINUX
cca2f7c6 72"-p <file>\tLook up kernel modules in a given file instead of default modules.pcimap\n"
c1c952d2 73#endif
cca2f7c6 74"-M\t\tEnable `bus mapping' mode (dangerous; root only)\n"
1b99a704
MM
75"\n"
76"PCI access options:\n"
727ce158
MM
77GENERIC_HELP
78;
98e39e09 79
a387042e 80/*** Our view of the PCI bus ***/
98e39e09 81
c7a34993
MM
82struct pci_access *pacc;
83struct device *first_dev;
934e7e36 84static int seen_errors;
ce22dfec 85static int need_topology;
98e39e09 86
c7a34993 87int
ec25b52d
MM
88config_fetch(struct device *d, unsigned int pos, unsigned int len)
89{
90 unsigned int end = pos+len;
91 int result;
84d437d6
MM
92
93 while (pos < d->config_bufsize && len && d->present[pos])
94 pos++, len--;
95 while (pos+len <= d->config_bufsize && len && d->present[pos+len-1])
96 len--;
97 if (!len)
ec25b52d 98 return 1;
84d437d6 99
ec25b52d
MM
100 if (end > d->config_bufsize)
101 {
84d437d6 102 int orig_size = d->config_bufsize;
ec25b52d
MM
103 while (end > d->config_bufsize)
104 d->config_bufsize *= 2;
105 d->config = xrealloc(d->config, d->config_bufsize);
84d437d6 106 d->present = xrealloc(d->present, d->config_bufsize);
1ac3a99d 107 memset(d->present + orig_size, 0, d->config_bufsize - orig_size);
ec25b52d
MM
108 }
109 result = pci_read_block(d->dev, pos, d->config + pos, len);
84d437d6
MM
110 if (result)
111 memset(d->present + pos, 1, len);
ec25b52d
MM
112 return result;
113}
114
c7a34993 115struct device *
1812a795
MM
116scan_device(struct pci_dev *p)
117{
1812a795
MM
118 struct device *d;
119
a387042e
MM
120 if (p->domain && !opt_domains)
121 opt_domains = 1;
ce22dfec 122 if (!pci_filter_match(&filter, p) && !need_topology)
1812a795
MM
123 return NULL;
124 d = xmalloc(sizeof(struct device));
1ac3a99d 125 memset(d, 0, sizeof(*d));
1812a795 126 d->dev = p;
84d437d6 127 d->config_cached = d->config_bufsize = 64;
ec25b52d 128 d->config = xmalloc(64);
84d437d6
MM
129 d->present = xmalloc(64);
130 memset(d->present, 1, 64);
09817437 131 if (!pci_read_block(p, 0, d->config, 64))
934e7e36
MM
132 {
133 fprintf(stderr, "lspci: Unable to read the standard configuration space header of device %04x:%02x:%02x.%d\n",
134 p->domain, p->bus, p->dev, p->func);
135 seen_errors++;
136 return NULL;
137 }
09817437 138 if ((d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
1812a795 139 {
ec25b52d
MM
140 /* For cardbus bridges, we need to fetch 64 bytes more to get the
141 * full standard header... */
84d437d6
MM
142 if (config_fetch(d, 64, 64))
143 d->config_cached += 64;
1812a795 144 }
84d437d6 145 pci_setup_cache(p, d->config, d->config_cached);
ef6c9ec3 146 pci_fill_info(p, PCI_FILL_IDENT | PCI_FILL_CLASS);
1812a795
MM
147 return d;
148}
149
98e39e09 150static void
727ce158 151scan_devices(void)
98e39e09
MM
152{
153 struct device *d;
727ce158 154 struct pci_dev *p;
98e39e09 155
727ce158 156 pci_scan_bus(pacc);
de7ef8bc 157 for (p=pacc->devices; p; p=p->next)
1812a795
MM
158 if (d = scan_device(p))
159 {
160 d->next = first_dev;
161 first_dev = d;
162 }
98e39e09
MM
163}
164
a387042e 165/*** Config space accesses ***/
98e39e09 166
84d437d6
MM
167static void
168check_conf_range(struct device *d, unsigned int pos, unsigned int len)
169{
170 while (len)
171 if (!d->present[pos])
172 die("Internal bug: Accessing non-read configuration byte at position %x", pos);
173 else
174 pos++, len--;
175}
176
c7a34993 177byte
98e39e09
MM
178get_conf_byte(struct device *d, unsigned int pos)
179{
84d437d6 180 check_conf_range(d, pos, 1);
98e39e09
MM
181 return d->config[pos];
182}
183
c7a34993 184word
98e39e09
MM
185get_conf_word(struct device *d, unsigned int pos)
186{
84d437d6 187 check_conf_range(d, pos, 2);
98e39e09
MM
188 return d->config[pos] | (d->config[pos+1] << 8);
189}
190
c7a34993 191u32
98e39e09
MM
192get_conf_long(struct device *d, unsigned int pos)
193{
84d437d6 194 check_conf_range(d, pos, 4);
98e39e09
MM
195 return d->config[pos] |
196 (d->config[pos+1] << 8) |
197 (d->config[pos+2] << 16) |
198 (d->config[pos+3] << 24);
199}
200
a387042e 201/*** Sorting ***/
98e39e09
MM
202
203static int
204compare_them(const void *A, const void *B)
205{
727ce158
MM
206 const struct pci_dev *a = (*(const struct device **)A)->dev;
207 const struct pci_dev *b = (*(const struct device **)B)->dev;
98e39e09 208
84c8d1bb
MM
209 if (a->domain < b->domain)
210 return -1;
211 if (a->domain > b->domain)
212 return 1;
98e39e09
MM
213 if (a->bus < b->bus)
214 return -1;
215 if (a->bus > b->bus)
216 return 1;
727ce158
MM
217 if (a->dev < b->dev)
218 return -1;
219 if (a->dev > b->dev)
220 return 1;
221 if (a->func < b->func)
98e39e09 222 return -1;
727ce158 223 if (a->func > b->func)
98e39e09
MM
224 return 1;
225 return 0;
226}
227
228static void
229sort_them(void)
230{
727ce158 231 struct device **index, **h, **last_dev;
98e39e09
MM
232 int cnt;
233 struct device *d;
234
c7a34993
MM
235 cnt = 0;
236 for (d=first_dev; d; d=d->next)
237 cnt++;
238 h = index = alloca(sizeof(struct device *) * cnt);
239 for (d=first_dev; d; d=d->next)
240 *h++ = d;
241 qsort(index, cnt, sizeof(struct device *), compare_them);
242 last_dev = &first_dev;
243 h = index;
244 while (cnt--)
245 {
246 *last_dev = *h;
247 last_dev = &(*h)->next;
248 h++;
c1c952d2 249 }
c7a34993 250 *last_dev = NULL;
c1c952d2
MM
251}
252
c7a34993 253/*** Normal output ***/
11339c0d 254
62e78fa6
MM
255static void
256show_slot_path(struct device *d)
257{
258 struct pci_dev *p = d->dev;
259
260 if (opt_path)
261 {
262 struct bus *bus = d->parent_bus;
263 struct bridge *br = bus->parent_bridge;
264
265 if (br && br->br_dev)
266 {
267 show_slot_path(br->br_dev);
268 if (opt_path > 1)
269 printf("/%02x:%02x.%d", p->bus, p->dev, p->func);
270 else
271 printf("/%02x.%d", p->dev, p->func);
272 return;
273 }
274 }
275 printf("%02x:%02x.%d", p->bus, p->dev, p->func);
276}
277
c7a34993
MM
278static void
279show_slot_name(struct device *d)
c1c952d2 280{
c7a34993 281 struct pci_dev *p = d->dev;
c1c952d2 282
c7a34993
MM
283 if (!opt_machine ? opt_domains : (p->domain || opt_domains >= 2))
284 printf("%04x:", p->domain);
62e78fa6 285 show_slot_path(d);
c1c952d2
MM
286}
287
c7a34993
MM
288void
289get_subid(struct device *d, word *subvp, word *subdp)
c1c952d2 290{
c7a34993 291 byte htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
11339c0d 292
c7a34993
MM
293 if (htype == PCI_HEADER_TYPE_NORMAL)
294 {
295 *subvp = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID);
296 *subdp = get_conf_word(d, PCI_SUBSYSTEM_ID);
297 }
298 else if (htype == PCI_HEADER_TYPE_CARDBUS && d->config_cached >= 128)
299 {
300 *subvp = get_conf_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);
301 *subdp = get_conf_word(d, PCI_CB_SUBSYSTEM_ID);
302 }
303 else
304 *subvp = *subdp = 0xffff;
c1c952d2
MM
305}
306
11339c0d 307static void
c7a34993 308show_terse(struct device *d)
11339c0d 309{
c7a34993
MM
310 int c;
311 struct pci_dev *p = d->dev;
312 char classbuf[128], devbuf[128];
11339c0d 313
c7a34993
MM
314 show_slot_name(d);
315 printf(" %s: %s",
316 pci_lookup_name(pacc, classbuf, sizeof(classbuf),
317 PCI_LOOKUP_CLASS,
318 p->device_class),
319 pci_lookup_name(pacc, devbuf, sizeof(devbuf),
320 PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
321 p->vendor_id, p->device_id));
322 if (c = get_conf_byte(d, PCI_REVISION_ID))
323 printf(" (rev %02x)", c);
324 if (verbose)
325 {
326 char *x;
327 c = get_conf_byte(d, PCI_CLASS_PROG);
328 x = pci_lookup_name(pacc, devbuf, sizeof(devbuf),
329 PCI_LOOKUP_PROGIF | PCI_LOOKUP_NO_NUMBERS,
330 p->device_class, c);
331 if (c || x)
332 {
333 printf(" (prog-if %02x", c);
334 if (x)
335 printf(" [%s]", x);
336 putchar(')');
337 }
338 }
339 putchar('\n');
c1c952d2 340
c7a34993
MM
341 if (verbose || opt_kernel)
342 {
343 word subsys_v, subsys_d;
344 char ssnamebuf[256];
c1c952d2 345
2a39bc9e
VP
346 pci_fill_info(p, PCI_FILL_LABEL);
347
aecf5b35
TR
348 if (p->label)
349 printf("\tDeviceName: %s", p->label);
c7a34993
MM
350 get_subid(d, &subsys_v, &subsys_d);
351 if (subsys_v && subsys_v != 0xffff)
352 printf("\tSubsystem: %s\n",
353 pci_lookup_name(pacc, ssnamebuf, sizeof(ssnamebuf),
354 PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
355 p->vendor_id, p->device_id, subsys_v, subsys_d));
356 }
c1c952d2
MM
357}
358
a387042e
MM
359/*** Verbose output ***/
360
361static void
41d883cb 362show_size(u64 x)
a387042e 363{
0188807c 364 static const char suffix[][2] = { "", "K", "M", "G", "T" };
f2f8adaa 365 unsigned i;
a387042e
MM
366 if (!x)
367 return;
f2f8adaa 368 for (i = 0; i < (sizeof(suffix) / sizeof(*suffix) - 1); i++) {
558f736b 369 if (x % 1024)
f2f8adaa
MW
370 break;
371 x /= 1024;
372 }
373 printf(" [size=%u%s]", (unsigned)x, suffix[i]);
a387042e
MM
374}
375
41d883cb
MM
376static void
377show_range(char *prefix, u64 base, u64 limit, int is_64bit)
378{
e6b0b6e1
KS
379 printf("%s:", prefix);
380 if (base <= limit || verbose > 2)
41d883cb 381 {
e6b0b6e1
KS
382 if (is_64bit)
383 printf(" %016" PCI_U64_FMT_X "-%016" PCI_U64_FMT_X, base, limit);
384 else
385 printf(" %08x-%08x", (unsigned) base, (unsigned) limit);
41d883cb 386 }
41d883cb
MM
387 if (base <= limit)
388 show_size(limit - base + 1);
389 else
e6b0b6e1 390 printf(" [disabled]");
41d883cb
MM
391 putchar('\n');
392}
393
a387042e
MM
394static void
395show_bases(struct device *d, int cnt)
396{
397 struct pci_dev *p = d->dev;
398 word cmd = get_conf_word(d, PCI_COMMAND);
399 int i;
659d438b 400 int virtual = 0;
a387042e 401
de7ef8bc 402 for (i=0; i<cnt; i++)
a387042e
MM
403 {
404 pciaddr_t pos = p->base_addr[i];
405 pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->size[i] : 0;
558f736b 406 pciaddr_t ioflg = (p->known_fields & PCI_FILL_IO_FLAGS) ? p->flags[i] : 0;
a387042e 407 u32 flg = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i);
bf72d3e9
MM
408 u32 hw_lower;
409 u32 hw_upper = 0;
410 int broken = 0;
411
a387042e
MM
412 if (flg == 0xffffffff)
413 flg = 0;
414 if (!pos && !flg && !len)
415 continue;
bf72d3e9 416
a387042e
MM
417 if (verbose > 1)
418 printf("\tRegion %d: ", i);
419 else
420 putchar('\t');
bf72d3e9
MM
421
422 /* Read address as seen by the hardware */
423 if (flg & PCI_BASE_ADDRESS_SPACE_IO)
424 hw_lower = flg & PCI_BASE_ADDRESS_IO_MASK;
425 else
426 {
427 hw_lower = flg & PCI_BASE_ADDRESS_MEM_MASK;
428 if ((flg & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
429 {
430 if (i >= cnt - 1)
431 broken = 1;
432 else
433 {
434 i++;
435 hw_upper = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i);
436 }
437 }
438 }
439
440 /* Detect virtual regions, which are reported by the OS, but unassigned in the device */
441 if (pos && !hw_lower && !hw_upper && !(ioflg & PCI_IORESOURCE_PCI_EA_BEI))
a387042e 442 {
a387042e 443 flg = pos;
659d438b 444 virtual = 1;
a387042e 445 }
bf72d3e9
MM
446
447 /* Print base address */
a387042e
MM
448 if (flg & PCI_BASE_ADDRESS_SPACE_IO)
449 {
450 pciaddr_t a = pos & PCI_BASE_ADDRESS_IO_MASK;
451 printf("I/O ports at ");
00bf6625 452 if (a || (cmd & PCI_COMMAND_IO))
a387042e 453 printf(PCIADDR_PORT_FMT, a);
bf72d3e9 454 else if (hw_lower)
a387042e
MM
455 printf("<ignored>");
456 else
457 printf("<unassigned>");
bf72d3e9
MM
458 if (virtual)
459 printf(" [virtual]");
460 else if (!(cmd & PCI_COMMAND_IO))
a387042e
MM
461 printf(" [disabled]");
462 }
463 else
464 {
465 int t = flg & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
466 pciaddr_t a = pos & PCI_ADDR_MEM_MASK;
a387042e
MM
467
468 printf("Memory at ");
bf72d3e9
MM
469 if (broken)
470 printf("<broken-64-bit-slot>");
471 else if (a)
472 printf(PCIADDR_T_FMT, a);
473 else if (hw_lower || hw_upper)
474 printf("<ignored>");
475 else
476 printf("<unassigned>");
a387042e
MM
477 printf(" (%s, %sprefetchable)",
478 (t == PCI_BASE_ADDRESS_MEM_TYPE_32) ? "32-bit" :
479 (t == PCI_BASE_ADDRESS_MEM_TYPE_64) ? "64-bit" :
480 (t == PCI_BASE_ADDRESS_MEM_TYPE_1M) ? "low-1M" : "type 3",
481 (flg & PCI_BASE_ADDRESS_MEM_PREFETCH) ? "" : "non-");
bf72d3e9
MM
482 if (virtual)
483 printf(" [virtual]");
484 else if (!(cmd & PCI_COMMAND_MEMORY))
a387042e
MM
485 printf(" [disabled]");
486 }
bf72d3e9
MM
487
488 if (ioflg & PCI_IORESOURCE_PCI_EA_BEI)
489 printf(" [enhanced]");
490
a387042e
MM
491 show_size(len);
492 putchar('\n');
493 }
494}
495
496static void
497show_rom(struct device *d, int reg)
498{
499 struct pci_dev *p = d->dev;
500 pciaddr_t rom = p->rom_base_addr;
501 pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->rom_size : 0;
558f736b 502 pciaddr_t ioflg = (p->known_fields & PCI_FILL_IO_FLAGS) ? p->rom_flags : 0;
a387042e
MM
503 u32 flg = get_conf_long(d, reg);
504 word cmd = get_conf_word(d, PCI_COMMAND);
659d438b 505 int virtual = 0;
a387042e
MM
506
507 if (!rom && !flg && !len)
508 return;
cb94f26e
MM
509
510 if ((rom & PCI_ROM_ADDRESS_MASK) && !(flg & PCI_ROM_ADDRESS_MASK) && !(ioflg & PCI_IORESOURCE_PCI_EA_BEI))
a387042e 511 {
a387042e 512 flg = rom;
659d438b 513 virtual = 1;
a387042e 514 }
cb94f26e
MM
515
516 printf("\tExpansion ROM at ");
a387042e
MM
517 if (rom & PCI_ROM_ADDRESS_MASK)
518 printf(PCIADDR_T_FMT, rom & PCI_ROM_ADDRESS_MASK);
519 else if (flg & PCI_ROM_ADDRESS_MASK)
520 printf("<ignored>");
521 else
522 printf("<unassigned>");
cb94f26e
MM
523
524 if (virtual)
525 printf(" [virtual]");
526
a387042e
MM
527 if (!(flg & PCI_ROM_ADDRESS_ENABLE))
528 printf(" [disabled]");
659d438b 529 else if (!virtual && !(cmd & PCI_COMMAND_MEMORY))
a387042e 530 printf(" [disabled by cmd]");
cb94f26e
MM
531
532 if (ioflg & PCI_IORESOURCE_PCI_EA_BEI)
533 printf(" [enhanced]");
534
a387042e
MM
535 show_size(len);
536 putchar('\n');
537}
538
e95c8373
MM
539static void
540show_htype0(struct device *d)
541{
542 show_bases(d, 6);
6aa54f1b 543 show_rom(d, PCI_ROM_ADDRESS);
21510591 544 show_caps(d, PCI_CAPABILITY_LIST);
e95c8373
MM
545}
546
98e39e09
MM
547static void
548show_htype1(struct device *d)
549{
550 u32 io_base = get_conf_byte(d, PCI_IO_BASE);
551 u32 io_limit = get_conf_byte(d, PCI_IO_LIMIT);
552 u32 io_type = io_base & PCI_IO_RANGE_TYPE_MASK;
553 u32 mem_base = get_conf_word(d, PCI_MEMORY_BASE);
554 u32 mem_limit = get_conf_word(d, PCI_MEMORY_LIMIT);
555 u32 mem_type = mem_base & PCI_MEMORY_RANGE_TYPE_MASK;
556 u32 pref_base = get_conf_word(d, PCI_PREF_MEMORY_BASE);
557 u32 pref_limit = get_conf_word(d, PCI_PREF_MEMORY_LIMIT);
558 u32 pref_type = pref_base & PCI_PREF_RANGE_TYPE_MASK;
138c0385 559 word sec_stat = get_conf_word(d, PCI_SEC_STATUS);
98e39e09
MM
560 word brc = get_conf_word(d, PCI_BRIDGE_CONTROL);
561
562 show_bases(d, 2);
563 printf("\tBus: primary=%02x, secondary=%02x, subordinate=%02x, sec-latency=%d\n",
564 get_conf_byte(d, PCI_PRIMARY_BUS),
565 get_conf_byte(d, PCI_SECONDARY_BUS),
566 get_conf_byte(d, PCI_SUBORDINATE_BUS),
567 get_conf_byte(d, PCI_SEC_LATENCY_TIMER));
568
569 if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
570 (io_type != PCI_IO_RANGE_TYPE_16 && io_type != PCI_IO_RANGE_TYPE_32))
571 printf("\t!!! Unknown I/O range types %x/%x\n", io_base, io_limit);
572 else
573 {
574 io_base = (io_base & PCI_IO_RANGE_MASK) << 8;
575 io_limit = (io_limit & PCI_IO_RANGE_MASK) << 8;
576 if (io_type == PCI_IO_RANGE_TYPE_32)
577 {
578 io_base |= (get_conf_word(d, PCI_IO_BASE_UPPER16) << 16);
579 io_limit |= (get_conf_word(d, PCI_IO_LIMIT_UPPER16) << 16);
580 }
41d883cb 581 show_range("\tI/O behind bridge", io_base, io_limit+0xfff, 0);
98e39e09
MM
582 }
583
584 if (mem_type != (mem_limit & PCI_MEMORY_RANGE_TYPE_MASK) ||
585 mem_type)
586 printf("\t!!! Unknown memory range types %x/%x\n", mem_base, mem_limit);
e306e911 587 else
98e39e09
MM
588 {
589 mem_base = (mem_base & PCI_MEMORY_RANGE_MASK) << 16;
590 mem_limit = (mem_limit & PCI_MEMORY_RANGE_MASK) << 16;
41d883cb 591 show_range("\tMemory behind bridge", mem_base, mem_limit + 0xfffff, 0);
98e39e09
MM
592 }
593
594 if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
595 (pref_type != PCI_PREF_RANGE_TYPE_32 && pref_type != PCI_PREF_RANGE_TYPE_64))
596 printf("\t!!! Unknown prefetchable memory range types %x/%x\n", pref_base, pref_limit);
e306e911 597 else
98e39e09 598 {
41d883cb
MM
599 u64 pref_base_64 = (pref_base & PCI_PREF_RANGE_MASK) << 16;
600 u64 pref_limit_64 = (pref_limit & PCI_PREF_RANGE_MASK) << 16;
601 if (pref_type == PCI_PREF_RANGE_TYPE_64)
e306e911 602 {
41d883cb
MM
603 pref_base_64 |= (u64) get_conf_long(d, PCI_PREF_BASE_UPPER32) << 32;
604 pref_limit_64 |= (u64) get_conf_long(d, PCI_PREF_LIMIT_UPPER32) << 32;
e306e911 605 }
41d883cb 606 show_range("\tPrefetchable memory behind bridge", pref_base_64, pref_limit_64 + 0xfffff, (pref_type == PCI_PREF_RANGE_TYPE_64));
98e39e09
MM
607 }
608
138c0385 609 if (verbose > 1)
c1c2c30e 610 printf("\tSecondary status: 66MHz%c FastB2B%c ParErr%c DEVSEL=%s >TAbort%c <TAbort%c <MAbort%c <SERR%c <PERR%c\n",
138c0385
MM
611 FLAG(sec_stat, PCI_STATUS_66MHZ),
612 FLAG(sec_stat, PCI_STATUS_FAST_BACK),
613 FLAG(sec_stat, PCI_STATUS_PARITY),
614 ((sec_stat & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) ? "slow" :
615 ((sec_stat & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) ? "medium" :
616 ((sec_stat & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) ? "fast" : "??",
617 FLAG(sec_stat, PCI_STATUS_SIG_TARGET_ABORT),
618 FLAG(sec_stat, PCI_STATUS_REC_TARGET_ABORT),
619 FLAG(sec_stat, PCI_STATUS_REC_MASTER_ABORT),
620 FLAG(sec_stat, PCI_STATUS_SIG_SYSTEM_ERROR),
621 FLAG(sec_stat, PCI_STATUS_DETECTED_PARITY));
98e39e09 622
6aa54f1b 623 show_rom(d, PCI_ROM_ADDRESS1);
98e39e09
MM
624
625 if (verbose > 1)
da322bfb 626 {
b2a45526 627 printf("\tBridgeCtl: Parity%c SERR%c NoISA%c VGA%c VGA16%c MAbort%c >Reset%c FastB2B%c\n",
da322bfb
MM
628 FLAG(brc, PCI_BRIDGE_CTL_PARITY),
629 FLAG(brc, PCI_BRIDGE_CTL_SERR),
630 FLAG(brc, PCI_BRIDGE_CTL_NO_ISA),
631 FLAG(brc, PCI_BRIDGE_CTL_VGA),
b2a45526 632 FLAG(brc, PCI_BRIDGE_CTL_VGA_16BIT),
da322bfb
MM
633 FLAG(brc, PCI_BRIDGE_CTL_MASTER_ABORT),
634 FLAG(brc, PCI_BRIDGE_CTL_BUS_RESET),
635 FLAG(brc, PCI_BRIDGE_CTL_FAST_BACK));
636 printf("\t\tPriDiscTmr%c SecDiscTmr%c DiscTmrStat%c DiscTmrSERREn%c\n",
637 FLAG(brc, PCI_BRIDGE_CTL_PRI_DISCARD_TIMER),
638 FLAG(brc, PCI_BRIDGE_CTL_SEC_DISCARD_TIMER),
639 FLAG(brc, PCI_BRIDGE_CTL_DISCARD_TIMER_STATUS),
640 FLAG(brc, PCI_BRIDGE_CTL_DISCARD_TIMER_SERR_EN));
641 }
e95c8373 642
21510591 643 show_caps(d, PCI_CAPABILITY_LIST);
98e39e09
MM
644}
645
2f48f637
MM
646static void
647show_htype2(struct device *d)
648{
96e4f295
MM
649 int i;
650 word cmd = get_conf_word(d, PCI_COMMAND);
651 word brc = get_conf_word(d, PCI_CB_BRIDGE_CONTROL);
84d437d6 652 word exca;
e306e911 653 int verb = verbose > 2;
96e4f295
MM
654
655 show_bases(d, 1);
656 printf("\tBus: primary=%02x, secondary=%02x, subordinate=%02x, sec-latency=%d\n",
657 get_conf_byte(d, PCI_CB_PRIMARY_BUS),
658 get_conf_byte(d, PCI_CB_CARD_BUS),
659 get_conf_byte(d, PCI_CB_SUBORDINATE_BUS),
660 get_conf_byte(d, PCI_CB_LATENCY_TIMER));
de7ef8bc 661 for (i=0; i<2; i++)
96e4f295
MM
662 {
663 int p = 8*i;
664 u32 base = get_conf_long(d, PCI_CB_MEMORY_BASE_0 + p);
665 u32 limit = get_conf_long(d, PCI_CB_MEMORY_LIMIT_0 + p);
f288d32f
BH
666 limit = limit + 0xfff;
667 if (base <= limit || verb)
81077814 668 printf("\tMemory window %d: %08x-%08x%s%s\n", i, base, limit,
96e4f295
MM
669 (cmd & PCI_COMMAND_MEMORY) ? "" : " [disabled]",
670 (brc & (PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 << i)) ? " (prefetchable)" : "");
671 }
de7ef8bc 672 for (i=0; i<2; i++)
96e4f295
MM
673 {
674 int p = 8*i;
675 u32 base = get_conf_long(d, PCI_CB_IO_BASE_0 + p);
676 u32 limit = get_conf_long(d, PCI_CB_IO_LIMIT_0 + p);
677 if (!(base & PCI_IO_RANGE_TYPE_32))
678 {
679 base &= 0xffff;
680 limit &= 0xffff;
681 }
682 base &= PCI_CB_IO_RANGE_MASK;
96e4f295 683 limit = (limit & PCI_CB_IO_RANGE_MASK) + 3;
e306e911
MM
684 if (base <= limit || verb)
685 printf("\tI/O window %d: %08x-%08x%s\n", i, base, limit,
686 (cmd & PCI_COMMAND_IO) ? "" : " [disabled]");
96e4f295
MM
687 }
688
689 if (get_conf_word(d, PCI_CB_SEC_STATUS) & PCI_STATUS_SIG_SYSTEM_ERROR)
690 printf("\tSecondary status: SERR\n");
691 if (verbose > 1)
692 printf("\tBridgeCtl: Parity%c SERR%c ISA%c VGA%c MAbort%c >Reset%c 16bInt%c PostWrite%c\n",
1c31d620
MM
693 FLAG(brc, PCI_CB_BRIDGE_CTL_PARITY),
694 FLAG(brc, PCI_CB_BRIDGE_CTL_SERR),
695 FLAG(brc, PCI_CB_BRIDGE_CTL_ISA),
696 FLAG(brc, PCI_CB_BRIDGE_CTL_VGA),
697 FLAG(brc, PCI_CB_BRIDGE_CTL_MASTER_ABORT),
698 FLAG(brc, PCI_CB_BRIDGE_CTL_CB_RESET),
699 FLAG(brc, PCI_CB_BRIDGE_CTL_16BIT_INT),
700 FLAG(brc, PCI_CB_BRIDGE_CTL_POST_WRITES));
84d437d6
MM
701
702 if (d->config_cached < 128)
703 {
704 printf("\t<access denied to the rest>\n");
705 return;
706 }
707
708 exca = get_conf_word(d, PCI_CB_LEGACY_MODE_BASE);
96e4f295
MM
709 if (exca)
710 printf("\t16-bit legacy interface ports at %04x\n", exca);
21510591 711 show_caps(d, PCI_CB_CAPABILITY_LIST);
2f48f637
MM
712}
713
98e39e09
MM
714static void
715show_verbose(struct device *d)
716{
727ce158 717 struct pci_dev *p = d->dev;
98e39e09
MM
718 word status = get_conf_word(d, PCI_STATUS);
719 word cmd = get_conf_word(d, PCI_COMMAND);
c2b144ef 720 word class = p->device_class;
98e39e09
MM
721 byte bist = get_conf_byte(d, PCI_BIST);
722 byte htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
723 byte latency = get_conf_byte(d, PCI_LATENCY_TIMER);
724 byte cache_line = get_conf_byte(d, PCI_CACHE_LINE_SIZE);
725 byte max_lat, min_gnt;
726 byte int_pin = get_conf_byte(d, PCI_INTERRUPT_PIN);
ef6c9ec3 727 unsigned int irq;
c02d903c 728 char *dt_node;
98e39e09
MM
729
730 show_terse(d);
731
ef6c9ec3 732 pci_fill_info(p, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES |
6d701ce3 733 PCI_FILL_PHYS_SLOT | PCI_FILL_NUMA_NODE | PCI_FILL_DT_NODE);
ef6c9ec3
MM
734 irq = p->irq;
735
98e39e09
MM
736 switch (htype)
737 {
2f48f637
MM
738 case PCI_HEADER_TYPE_NORMAL:
739 if (class == PCI_CLASS_BRIDGE_PCI)
56164f4f 740 printf("\t!!! Invalid class %04x for header type %02x\n", class, htype);
98e39e09
MM
741 max_lat = get_conf_byte(d, PCI_MAX_LAT);
742 min_gnt = get_conf_byte(d, PCI_MIN_GNT);
98e39e09 743 break;
2f48f637 744 case PCI_HEADER_TYPE_BRIDGE:
cce2caac 745 if ((class >> 8) != PCI_BASE_CLASS_BRIDGE)
56164f4f 746 printf("\t!!! Invalid class %04x for header type %02x\n", class, htype);
001b9ac6 747 min_gnt = max_lat = 0;
2f48f637
MM
748 break;
749 case PCI_HEADER_TYPE_CARDBUS:
750 if ((class >> 8) != PCI_BASE_CLASS_BRIDGE)
56164f4f 751 printf("\t!!! Invalid class %04x for header type %02x\n", class, htype);
96e4f295 752 min_gnt = max_lat = 0;
98e39e09
MM
753 break;
754 default:
755 printf("\t!!! Unknown header type %02x\n", htype);
756 return;
757 }
758
2849a165
AC
759 if (p->phy_slot)
760 printf("\tPhysical Slot: %s\n", p->phy_slot);
761
c02d903c
MM
762 if (dt_node = pci_get_string_property(p, PCI_FILL_DT_NODE))
763 printf("\tDevice tree node: %s\n", dt_node);
764
98e39e09
MM
765 if (verbose > 1)
766 {
da322bfb 767 printf("\tControl: I/O%c Mem%c BusMaster%c SpecCycle%c MemWINV%c VGASnoop%c ParErr%c Stepping%c SERR%c FastB2B%c DisINTx%c\n",
1c31d620
MM
768 FLAG(cmd, PCI_COMMAND_IO),
769 FLAG(cmd, PCI_COMMAND_MEMORY),
770 FLAG(cmd, PCI_COMMAND_MASTER),
771 FLAG(cmd, PCI_COMMAND_SPECIAL),
772 FLAG(cmd, PCI_COMMAND_INVALIDATE),
773 FLAG(cmd, PCI_COMMAND_VGA_PALETTE),
774 FLAG(cmd, PCI_COMMAND_PARITY),
775 FLAG(cmd, PCI_COMMAND_WAIT),
776 FLAG(cmd, PCI_COMMAND_SERR),
da322bfb
MM
777 FLAG(cmd, PCI_COMMAND_FAST_BACK),
778 FLAG(cmd, PCI_COMMAND_DISABLE_INTx));
779 printf("\tStatus: Cap%c 66MHz%c UDF%c FastB2B%c ParErr%c DEVSEL=%s >TAbort%c <TAbort%c <MAbort%c >SERR%c <PERR%c INTx%c\n",
1c31d620
MM
780 FLAG(status, PCI_STATUS_CAP_LIST),
781 FLAG(status, PCI_STATUS_66MHZ),
782 FLAG(status, PCI_STATUS_UDF),
783 FLAG(status, PCI_STATUS_FAST_BACK),
784 FLAG(status, PCI_STATUS_PARITY),
98e39e09
MM
785 ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) ? "slow" :
786 ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) ? "medium" :
787 ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) ? "fast" : "??",
1c31d620
MM
788 FLAG(status, PCI_STATUS_SIG_TARGET_ABORT),
789 FLAG(status, PCI_STATUS_REC_TARGET_ABORT),
790 FLAG(status, PCI_STATUS_REC_MASTER_ABORT),
791 FLAG(status, PCI_STATUS_SIG_SYSTEM_ERROR),
da322bfb
MM
792 FLAG(status, PCI_STATUS_DETECTED_PARITY),
793 FLAG(status, PCI_STATUS_INTx));
98e39e09
MM
794 if (cmd & PCI_COMMAND_MASTER)
795 {
56164f4f
MM
796 printf("\tLatency: %d", latency);
797 if (min_gnt || max_lat)
798 {
799 printf(" (");
800 if (min_gnt)
801 printf("%dns min", min_gnt*250);
802 if (min_gnt && max_lat)
803 printf(", ");
804 if (max_lat)
805 printf("%dns max", max_lat*250);
806 putchar(')');
807 }
98e39e09 808 if (cache_line)
7a61b93c 809 printf(", Cache Line Size: %d bytes", cache_line * 4);
98e39e09
MM
810 putchar('\n');
811 }
727ce158 812 if (int_pin || irq)
9739916e 813 printf("\tInterrupt: pin %c routed to IRQ " PCIIRQ_FMT "\n",
727ce158 814 (int_pin ? 'A' + int_pin - 1 : '?'), irq);
1d9d1a01
MM
815 if (p->numa_node != -1)
816 printf("\tNUMA node: %d\n", p->numa_node);
98e39e09
MM
817 }
818 else
819 {
820 printf("\tFlags: ");
821 if (cmd & PCI_COMMAND_MASTER)
822 printf("bus master, ");
823 if (cmd & PCI_COMMAND_VGA_PALETTE)
824 printf("VGA palette snoop, ");
825 if (cmd & PCI_COMMAND_WAIT)
826 printf("stepping, ");
827 if (cmd & PCI_COMMAND_FAST_BACK)
828 printf("fast Back2Back, ");
829 if (status & PCI_STATUS_66MHZ)
c1c2c30e 830 printf("66MHz, ");
98e39e09
MM
831 if (status & PCI_STATUS_UDF)
832 printf("user-definable features, ");
833 printf("%s devsel",
834 ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) ? "slow" :
835 ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) ? "medium" :
836 ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) ? "fast" : "??");
837 if (cmd & PCI_COMMAND_MASTER)
838 printf(", latency %d", latency);
727ce158 839 if (irq)
9739916e 840 printf(", IRQ " PCIIRQ_FMT, irq);
90ec4a6d
MW
841 if (p->numa_node != -1)
842 printf(", NUMA node %d", p->numa_node);
98e39e09
MM
843 putchar('\n');
844 }
845
846 if (bist & PCI_BIST_CAPABLE)
847 {
848 if (bist & PCI_BIST_START)
849 printf("\tBIST is running\n");
850 else
851 printf("\tBIST result: %02x\n", bist & PCI_BIST_CODE_MASK);
852 }
853
854 switch (htype)
855 {
2f48f637 856 case PCI_HEADER_TYPE_NORMAL:
98e39e09
MM
857 show_htype0(d);
858 break;
2f48f637 859 case PCI_HEADER_TYPE_BRIDGE:
98e39e09
MM
860 show_htype1(d);
861 break;
2f48f637
MM
862 case PCI_HEADER_TYPE_CARDBUS:
863 show_htype2(d);
864 break;
98e39e09
MM
865 }
866}
867
a387042e
MM
868/*** Machine-readable dumps ***/
869
98e39e09
MM
870static void
871show_hex_dump(struct device *d)
872{
09817437 873 unsigned int i, cnt;
98e39e09 874
84d437d6 875 cnt = d->config_cached;
a387042e 876 if (opt_hex >= 3 && config_fetch(d, cnt, 256-cnt))
09817437
MM
877 {
878 cnt = 256;
a387042e 879 if (opt_hex >= 4 && config_fetch(d, 256, 4096-256))
09817437
MM
880 cnt = 4096;
881 }
882
de7ef8bc 883 for (i=0; i<cnt; i++)
98e39e09
MM
884 {
885 if (! (i & 15))
886 printf("%02x:", i);
887 printf(" %02x", get_conf_byte(d, i));
888 if ((i & 15) == 15)
889 putchar('\n');
890 }
891}
892
13081e57
MM
893static void
894print_shell_escaped(char *c)
895{
896 printf(" \"");
897 while (*c)
898 {
899 if (*c == '"' || *c == '\\')
900 putchar('\\');
901 putchar(*c++);
902 }
903 putchar('"');
904}
905
0a33d0ec
MM
906static void
907show_machine(struct device *d)
908{
727ce158 909 struct pci_dev *p = d->dev;
0a33d0ec 910 int c;
c1c952d2 911 word sv_id, sd_id;
727ce158 912 char classbuf[128], vendbuf[128], devbuf[128], svbuf[128], sdbuf[128];
c02d903c 913 char *dt_node;
ce503b7f 914
c1c952d2 915 get_subid(d, &sv_id, &sd_id);
0a33d0ec
MM
916
917 if (verbose)
918 {
6d701ce3 919 pci_fill_info(p, PCI_FILL_PHYS_SLOT | PCI_FILL_NUMA_NODE | PCI_FILL_DT_NODE);
a387042e 920 printf((opt_machine >= 2) ? "Slot:\t" : "Device:\t");
84c8d1bb
MM
921 show_slot_name(d);
922 putchar('\n');
727ce158 923 printf("Class:\t%s\n",
c2b144ef 924 pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, p->device_class));
727ce158 925 printf("Vendor:\t%s\n",
224707ba 926 pci_lookup_name(pacc, vendbuf, sizeof(vendbuf), PCI_LOOKUP_VENDOR, p->vendor_id, p->device_id));
727ce158 927 printf("Device:\t%s\n",
224707ba 928 pci_lookup_name(pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id));
ce503b7f
MM
929 if (sv_id && sv_id != 0xffff)
930 {
727ce158 931 printf("SVendor:\t%s\n",
a99c0d69 932 pci_lookup_name(pacc, svbuf, sizeof(svbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR, sv_id));
727ce158 933 printf("SDevice:\t%s\n",
d4798a32 934 pci_lookup_name(pacc, sdbuf, sizeof(sdbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id, sv_id, sd_id));
ce503b7f 935 }
2849a165
AC
936 if (p->phy_slot)
937 printf("PhySlot:\t%s\n", p->phy_slot);
0a33d0ec
MM
938 if (c = get_conf_byte(d, PCI_REVISION_ID))
939 printf("Rev:\t%02x\n", c);
940 if (c = get_conf_byte(d, PCI_CLASS_PROG))
941 printf("ProgIf:\t%02x\n", c);
11339c0d
MM
942 if (opt_kernel)
943 show_kernel_machine(d);
1d9d1a01
MM
944 if (p->numa_node != -1)
945 printf("NUMANode:\t%d\n", p->numa_node);
c02d903c
MM
946 if (dt_node = pci_get_string_property(p, PCI_FILL_DT_NODE))
947 printf("DTNode:\t%s\n", dt_node);
0a33d0ec
MM
948 }
949 else
950 {
84c8d1bb 951 show_slot_name(d);
13081e57
MM
952 print_shell_escaped(pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, p->device_class));
953 print_shell_escaped(pci_lookup_name(pacc, vendbuf, sizeof(vendbuf), PCI_LOOKUP_VENDOR, p->vendor_id, p->device_id));
954 print_shell_escaped(pci_lookup_name(pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id));
0a33d0ec
MM
955 if (c = get_conf_byte(d, PCI_REVISION_ID))
956 printf(" -r%02x", c);
957 if (c = get_conf_byte(d, PCI_CLASS_PROG))
958 printf(" -p%02x", c);
ce503b7f 959 if (sv_id && sv_id != 0xffff)
13081e57
MM
960 {
961 print_shell_escaped(pci_lookup_name(pacc, svbuf, sizeof(svbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR, sv_id));
962 print_shell_escaped(pci_lookup_name(pacc, sdbuf, sizeof(sdbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id, sv_id, sd_id));
963 }
ce503b7f
MM
964 else
965 printf(" \"\" \"\"");
0a33d0ec
MM
966 putchar('\n');
967 }
968}
969
a387042e
MM
970/*** Main show function ***/
971
c7a34993 972void
1812a795
MM
973show_device(struct device *d)
974{
a387042e 975 if (opt_machine)
1812a795 976 show_machine(d);
1812a795 977 else
11339c0d
MM
978 {
979 if (verbose)
980 show_verbose(d);
981 else
982 show_terse(d);
983 if (opt_kernel || verbose)
984 show_kernel(d);
985 }
a387042e 986 if (opt_hex)
1812a795 987 show_hex_dump(d);
a387042e 988 if (verbose || opt_hex)
1812a795
MM
989 putchar('\n');
990}
991
98e39e09
MM
992static void
993show(void)
994{
995 struct device *d;
996
de7ef8bc 997 for (d=first_dev; d; d=d->next)
ce22dfec
MM
998 if (pci_filter_match(&filter, d->dev))
999 show_device(d);
98e39e09
MM
1000}
1001
1002/* Main */
1003
1004int
1005main(int argc, char **argv)
1006{
1007 int i;
e4842ff3 1008 char *msg;
98e39e09 1009
496d4021
MM
1010 if (argc == 2 && !strcmp(argv[1], "--version"))
1011 {
1012 puts("lspci version " PCIUTILS_VERSION);
1013 return 0;
1014 }
727ce158
MM
1015
1016 pacc = pci_alloc();
1017 pacc->error = die;
1018 pci_filter_init(pacc, &filter);
1019
98e39e09
MM
1020 while ((i = getopt(argc, argv, options)) != -1)
1021 switch (i)
1022 {
1023 case 'n':
bc2eed2d 1024 pacc->numeric_ids++;
98e39e09
MM
1025 break;
1026 case 'v':
1027 verbose++;
1028 break;
1029 case 'b':
727ce158 1030 pacc->buscentric = 1;
98e39e09 1031 break;
e4842ff3 1032 case 's':
727ce158 1033 if (msg = pci_filter_parse_slot(&filter, optarg))
b7fd8e19 1034 die("-s: %s", msg);
ce22dfec 1035 opt_filter = 1;
98e39e09 1036 break;
e4842ff3 1037 case 'd':
727ce158
MM
1038 if (msg = pci_filter_parse_id(&filter, optarg))
1039 die("-d: %s", msg);
ce22dfec 1040 opt_filter = 1;
98e39e09
MM
1041 break;
1042 case 'x':
a387042e 1043 opt_hex++;
98e39e09 1044 break;
62e78fa6
MM
1045 case 'P':
1046 opt_path++;
ce22dfec 1047 need_topology = 1;
62e78fa6 1048 break;
6d0dc0fd 1049 case 't':
a387042e 1050 opt_tree++;
ce22dfec 1051 need_topology = 1;
6d0dc0fd 1052 break;
18928b91 1053 case 'i':
cc062b4a 1054 pci_set_name_list_path(pacc, optarg, 0);
18928b91 1055 break;
0a33d0ec 1056 case 'm':
a387042e 1057 opt_machine++;
0a33d0ec 1058 break;
c1c952d2
MM
1059 case 'p':
1060 opt_pcimap = optarg;
1061 break;
1b99a704 1062#ifdef PCI_OS_LINUX
11339c0d
MM
1063 case 'k':
1064 opt_kernel++;
1065 break;
1b99a704 1066#endif
1812a795 1067 case 'M':
a387042e 1068 opt_map_mode++;
1812a795 1069 break;
af61eb25 1070 case 'D':
a387042e 1071 opt_domains = 2;
af61eb25 1072 break;
e022789d 1073#ifdef PCI_USE_DNS
cca2f7c6
MM
1074 case 'q':
1075 opt_query_dns++;
1076 break;
1077 case 'Q':
1078 opt_query_all = 1;
1079 break;
e022789d
MM
1080#else
1081 case 'q':
1082 case 'Q':
1083 die("DNS queries are not available in this version");
1084#endif
98e39e09 1085 default:
727ce158
MM
1086 if (parse_generic_option(i, pacc, optarg))
1087 break;
98e39e09 1088 bad:
727ce158 1089 fprintf(stderr, help_msg, pacc->id_file_name);
98e39e09
MM
1090 return 1;
1091 }
1092 if (optind < argc)
1093 goto bad;
1094
cca2f7c6
MM
1095 if (opt_query_dns)
1096 {
1097 pacc->id_lookup_mode |= PCI_LOOKUP_NETWORK;
1098 if (opt_query_dns > 1)
1099 pacc->id_lookup_mode |= PCI_LOOKUP_REFRESH_CACHE;
1100 }
1101 if (opt_query_all)
1102 pacc->id_lookup_mode |= PCI_LOOKUP_NETWORK | PCI_LOOKUP_SKIP_LOCAL;
1103
727ce158 1104 pci_init(pacc);
a387042e 1105 if (opt_map_mode)
62e78fa6 1106 {
ce22dfec
MM
1107 if (need_topology)
1108 die("Bus mapping mode does not recognize bus topology");
62e78fa6
MM
1109 map_the_bus();
1110 }
6d0dc0fd 1111 else
1812a795
MM
1112 {
1113 scan_devices();
1114 sort_them();
ce22dfec
MM
1115 if (need_topology)
1116 grow_tree();
a387042e 1117 if (opt_tree)
888ddf0e 1118 show_forest(opt_filter ? &filter : NULL);
1812a795
MM
1119 else
1120 show();
1121 }
17ec7e70 1122 show_kernel_cleanup();
727ce158 1123 pci_cleanup(pacc);
98e39e09 1124
934e7e36 1125 return (seen_errors ? 2 : 0);
98e39e09 1126}