X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lspci.c;h=4e6196e2277332c747d123915011c62098ad6eb0;hb=44c6c7fcfe0f9219447ac78e3f386e3223328149;hp=3aeaf46e4b431a0ea92117520ae392c1cb2d3b19;hpb=41d883cb97f94e844e96b4631a99c3da557cf162;p=pciutils.git diff --git a/lspci.c b/lspci.c index 3aeaf46..4e6196e 100644 --- a/lspci.c +++ b/lspci.c @@ -1,7 +1,7 @@ /* * The PCI Utilities -- List All PCI Devices * - * Copyright (c) 1997--2016 Martin Mares + * Copyright (c) 1997--2020 Martin Mares * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -18,7 +18,9 @@ int verbose; /* Show detailed information */ static int opt_hex; /* Show contents of config space as hexadecimal numbers */ struct pci_filter filter; /* Device filter */ +static int opt_filter; /* Any filter was given */ static int opt_tree; /* Show bus tree */ +static int opt_path; /* Show bridge path */ static int opt_machine; /* Generate machine-readable output */ static int opt_map_mode; /* Bus mapping mode enabled */ static int opt_domains; /* Show domain numbers (0=disabled, 1=auto-detected, 2=requested) */ @@ -29,7 +31,7 @@ char *opt_pcimap; /* Override path to Linux modules.pcimap */ const char program_name[] = "lspci"; -static char options[] = "nvbxs:d:ti:mgp:qkMDQ" GENERIC_OPTIONS ; +static char options[] = "nvbxs:d:tPi:mgp:qkMDQ" GENERIC_OPTIONS ; static char help_msg[] = "Usage: lspci []\n" @@ -39,7 +41,7 @@ static char help_msg[] = "-t\t\tShow bus tree\n" "\n" "Display options:\n" -"-v\t\tBe verbose (-vv for very verbose)\n" +"-v\t\tBe verbose (-vv or -vvv for higher verbosity)\n" #ifdef PCI_OS_LINUX "-k\t\tShow kernel drivers handling each device\n" #endif @@ -48,6 +50,8 @@ static char help_msg[] = "-xxxx\t\tShow hex-dump of the 4096-byte extended config space (root only)\n" "-b\t\tBus-centric view (addresses and IRQ's as seen by the bus)\n" "-D\t\tAlways show domain numbers\n" +"-P\t\tDisplay bridge path in addition to bus and device number\n" +"-PP\t\tDisplay bus path in addition to bus and device number\n" "\n" "Resolving of device ID's to names:\n" "-n\t\tShow numeric ID's\n" @@ -78,6 +82,7 @@ GENERIC_HELP struct pci_access *pacc; struct device *first_dev; static int seen_errors; +static int need_topology; int config_fetch(struct device *d, unsigned int pos, unsigned int len) @@ -114,7 +119,7 @@ scan_device(struct pci_dev *p) if (p->domain && !opt_domains) opt_domains = 1; - if (!pci_filter_match(&filter, p)) + if (!pci_filter_match(&filter, p) && !need_topology) return NULL; d = xmalloc(sizeof(struct device)); memset(d, 0, sizeof(*d)); @@ -247,6 +252,29 @@ sort_them(void) /*** Normal output ***/ +static void +show_slot_path(struct device *d) +{ + struct pci_dev *p = d->dev; + + if (opt_path) + { + struct bus *bus = d->parent_bus; + struct bridge *br = bus->parent_bridge; + + if (br && br->br_dev) + { + show_slot_path(br->br_dev); + if (opt_path > 1) + printf("/%02x:%02x.%d", p->bus, p->dev, p->func); + else + printf("/%02x.%d", p->dev, p->func); + return; + } + } + printf("%02x:%02x.%d", p->bus, p->dev, p->func); +} + static void show_slot_name(struct device *d) { @@ -254,7 +282,7 @@ show_slot_name(struct device *d) if (!opt_machine ? opt_domains : (p->domain || opt_domains >= 2)) printf("%04x:", p->domain); - printf("%02x:%02x.%d", p->bus, p->dev, p->func); + show_slot_path(d); } void @@ -315,6 +343,8 @@ show_terse(struct device *d) word subsys_v, subsys_d; char ssnamebuf[256]; + pci_fill_info(p, PCI_FILL_LABEL); + if (p->label) printf("\tDeviceName: %s", p->label); get_subid(d, &subsys_v, &subsys_d); @@ -346,26 +376,18 @@ show_size(u64 x) static void show_range(char *prefix, u64 base, u64 limit, int is_64bit) { - if (base > limit) + printf("%s:", prefix); + if (base <= limit || verbose > 2) { - if (!verbose) - return; - else if (verbose < 3) - { - printf("%s: None\n", prefix); - return; - } + if (is_64bit) + printf(" %016" PCI_U64_FMT_X "-%016" PCI_U64_FMT_X, base, limit); + else + printf(" %08x-%08x", (unsigned) base, (unsigned) limit); } - - printf("%s: ", prefix); - if (is_64bit) - printf("%016" PCI_U64_FMT "x-%016" PCI_U64_FMT "x", base, limit); - else - printf("%08x-%08x", (unsigned) base, (unsigned) limit); if (base <= limit) show_size(limit - base + 1); else - printf(" [empty]"); + printf(" [disabled]"); putchar('\n'); } @@ -383,71 +405,89 @@ show_bases(struct device *d, int cnt) pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->size[i] : 0; pciaddr_t ioflg = (p->known_fields & PCI_FILL_IO_FLAGS) ? p->flags[i] : 0; u32 flg = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i); + u32 hw_lower; + u32 hw_upper = 0; + int broken = 0; + if (flg == 0xffffffff) flg = 0; if (!pos && !flg && !len) continue; + if (verbose > 1) printf("\tRegion %d: ", i); else putchar('\t'); - if (ioflg & PCI_IORESOURCE_PCI_EA_BEI) - printf("[enhanced] "); - else if (pos && !flg) /* Reported by the OS, but not by the device */ + + /* Read address as seen by the hardware */ + if (flg & PCI_BASE_ADDRESS_SPACE_IO) + hw_lower = flg & PCI_BASE_ADDRESS_IO_MASK; + else + { + hw_lower = flg & PCI_BASE_ADDRESS_MEM_MASK; + if ((flg & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) + { + if (i >= cnt - 1) + broken = 1; + else + { + i++; + hw_upper = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i); + } + } + } + + /* Detect virtual regions, which are reported by the OS, but unassigned in the device */ + if (pos && !hw_lower && !hw_upper && !(ioflg & PCI_IORESOURCE_PCI_EA_BEI)) { - printf("[virtual] "); flg = pos; virtual = 1; } + + /* Print base address */ if (flg & PCI_BASE_ADDRESS_SPACE_IO) { pciaddr_t a = pos & PCI_BASE_ADDRESS_IO_MASK; printf("I/O ports at "); if (a || (cmd & PCI_COMMAND_IO)) printf(PCIADDR_PORT_FMT, a); - else if (flg & PCI_BASE_ADDRESS_IO_MASK) + else if (hw_lower) printf(""); else printf(""); - if (!virtual && !(cmd & PCI_COMMAND_IO)) + if (virtual) + printf(" [virtual]"); + else if (!(cmd & PCI_COMMAND_IO)) printf(" [disabled]"); } else { int t = flg & PCI_BASE_ADDRESS_MEM_TYPE_MASK; pciaddr_t a = pos & PCI_ADDR_MEM_MASK; - int done = 0; - u32 z = 0; printf("Memory at "); - if (t == PCI_BASE_ADDRESS_MEM_TYPE_64) - { - if (i >= cnt - 1) - { - printf(""); - done = 1; - } - else - { - i++; - z = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i); - } - } - if (!done) - { - if (a) - printf(PCIADDR_T_FMT, a); - else - printf(((flg & PCI_BASE_ADDRESS_MEM_MASK) || z) ? "" : ""); - } + if (broken) + printf(""); + else if (a) + printf(PCIADDR_T_FMT, a); + else if (hw_lower || hw_upper) + printf(""); + else + printf(""); printf(" (%s, %sprefetchable)", (t == PCI_BASE_ADDRESS_MEM_TYPE_32) ? "32-bit" : (t == PCI_BASE_ADDRESS_MEM_TYPE_64) ? "64-bit" : (t == PCI_BASE_ADDRESS_MEM_TYPE_1M) ? "low-1M" : "type 3", (flg & PCI_BASE_ADDRESS_MEM_PREFETCH) ? "" : "non-"); - if (!virtual && !(cmd & PCI_COMMAND_MEMORY)) + if (virtual) + printf(" [virtual]"); + else if (!(cmd & PCI_COMMAND_MEMORY)) printf(" [disabled]"); } + + if (ioflg & PCI_IORESOURCE_PCI_EA_BEI) + printf(" [enhanced]"); + show_size(len); putchar('\n'); } @@ -466,26 +506,32 @@ show_rom(struct device *d, int reg) if (!rom && !flg && !len) return; - putchar('\t'); - if (ioflg & PCI_IORESOURCE_PCI_EA_BEI) - printf("[enhanced] "); - else if ((rom & PCI_ROM_ADDRESS_MASK) && !(flg & PCI_ROM_ADDRESS_MASK)) + + if ((rom & PCI_ROM_ADDRESS_MASK) && !(flg & PCI_ROM_ADDRESS_MASK) && !(ioflg & PCI_IORESOURCE_PCI_EA_BEI)) { - printf("[virtual] "); flg = rom; virtual = 1; } - printf("Expansion ROM at "); + + printf("\tExpansion ROM at "); if (rom & PCI_ROM_ADDRESS_MASK) printf(PCIADDR_T_FMT, rom & PCI_ROM_ADDRESS_MASK); else if (flg & PCI_ROM_ADDRESS_MASK) printf(""); else printf(""); + + if (virtual) + printf(" [virtual]"); + if (!(flg & PCI_ROM_ADDRESS_ENABLE)) printf(" [disabled]"); else if (!virtual && !(cmd & PCI_COMMAND_MEMORY)) printf(" [disabled by cmd]"); + + if (ioflg & PCI_IORESOURCE_PCI_EA_BEI) + printf(" [enhanced]"); + show_size(len); putchar('\n'); } @@ -578,11 +624,12 @@ show_htype1(struct device *d) if (verbose > 1) { - printf("\tBridgeCtl: Parity%c SERR%c NoISA%c VGA%c MAbort%c >Reset%c FastB2B%c\n", + printf("\tBridgeCtl: Parity%c SERR%c NoISA%c VGA%c VGA16%c MAbort%c >Reset%c FastB2B%c\n", FLAG(brc, PCI_BRIDGE_CTL_PARITY), FLAG(brc, PCI_BRIDGE_CTL_SERR), FLAG(brc, PCI_BRIDGE_CTL_NO_ISA), FLAG(brc, PCI_BRIDGE_CTL_VGA), + FLAG(brc, PCI_BRIDGE_CTL_VGA_16BIT), FLAG(brc, PCI_BRIDGE_CTL_MASTER_ABORT), FLAG(brc, PCI_BRIDGE_CTL_BUS_RESET), FLAG(brc, PCI_BRIDGE_CTL_FAST_BACK)); @@ -678,11 +725,12 @@ show_verbose(struct device *d) byte max_lat, min_gnt; byte int_pin = get_conf_byte(d, PCI_INTERRUPT_PIN); unsigned int irq; + char *dt_node; show_terse(d); pci_fill_info(p, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES | - PCI_FILL_PHYS_SLOT | PCI_FILL_LABEL | PCI_FILL_NUMA_NODE); + PCI_FILL_PHYS_SLOT | PCI_FILL_NUMA_NODE | PCI_FILL_DT_NODE); irq = p->irq; switch (htype) @@ -711,6 +759,9 @@ show_verbose(struct device *d) if (p->phy_slot) printf("\tPhysical Slot: %s\n", p->phy_slot); + if (dt_node = pci_get_string_property(p, PCI_FILL_DT_NODE)) + printf("\tDevice tree node: %s\n", dt_node); + if (verbose > 1) { 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", @@ -859,12 +910,13 @@ show_machine(struct device *d) int c; word sv_id, sd_id; char classbuf[128], vendbuf[128], devbuf[128], svbuf[128], sdbuf[128]; + char *dt_node; get_subid(d, &sv_id, &sd_id); if (verbose) { - pci_fill_info(p, PCI_FILL_PHYS_SLOT | PCI_FILL_NUMA_NODE); + pci_fill_info(p, PCI_FILL_PHYS_SLOT | PCI_FILL_NUMA_NODE | PCI_FILL_DT_NODE); printf((opt_machine >= 2) ? "Slot:\t" : "Device:\t"); show_slot_name(d); putchar('\n'); @@ -891,6 +943,8 @@ show_machine(struct device *d) show_kernel_machine(d); if (p->numa_node != -1) printf("NUMANode:\t%d\n", p->numa_node); + if (dt_node = pci_get_string_property(p, PCI_FILL_DT_NODE)) + printf("DTNode:\t%s\n", dt_node); } else { @@ -941,7 +995,8 @@ show(void) struct device *d; for (d=first_dev; d; d=d->next) - show_device(d); + if (pci_filter_match(&filter, d->dev)) + show_device(d); } /* Main */ @@ -977,16 +1032,23 @@ main(int argc, char **argv) case 's': if (msg = pci_filter_parse_slot(&filter, optarg)) die("-s: %s", msg); + opt_filter = 1; break; case 'd': if (msg = pci_filter_parse_id(&filter, optarg)) die("-d: %s", msg); + opt_filter = 1; break; case 'x': opt_hex++; break; + case 'P': + opt_path++; + need_topology = 1; + break; case 't': opt_tree++; + need_topology = 1; break; case 'i': pci_set_name_list_path(pacc, optarg, 0); @@ -1041,13 +1103,19 @@ main(int argc, char **argv) pci_init(pacc); if (opt_map_mode) - map_the_bus(); + { + if (need_topology) + die("Bus mapping mode does not recognize bus topology"); + map_the_bus(); + } else { scan_devices(); sort_them(); + if (need_topology) + grow_tree(); if (opt_tree) - show_forest(); + show_forest(opt_filter ? &filter : NULL); else show(); }