X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lspci.c;h=071cc117bc682c11917e57d6392a987c6a50d528;hb=7d23054d18402b1891343f090d3cd37d7e83c82f;hp=95a1318e5e80eceb0b5272645545d971ff0bddd4;hpb=72cabfbb12ad48bd4cdd5ecbe72f882197e2dac6;p=pciutils.git diff --git a/lspci.c b/lspci.c index 95a1318..071cc11 100644 --- a/lspci.c +++ b/lspci.c @@ -3,7 +3,9 @@ * * Copyright (c) 1997--2020 Martin Mares * - * Can be freely distributed and used under the terms of the GNU GPL. + * Can be freely distributed and used under the terms of the GNU GPL v2+. + * + * SPDX-License-Identifier: GPL-2.0-or-later */ #include @@ -105,6 +107,7 @@ config_fetch(struct device *d, unsigned int pos, unsigned int len) d->config = xrealloc(d->config, d->config_bufsize); d->present = xrealloc(d->present, d->config_bufsize); memset(d->present + orig_size, 0, d->config_bufsize - orig_size); + pci_setup_cache(d->dev, d->config, d->dev->cache_len); } result = pci_read_block(d->dev, pos, d->config + pos, len); if (result) @@ -124,18 +127,18 @@ scan_device(struct pci_dev *p) d = xmalloc(sizeof(struct device)); memset(d, 0, sizeof(*d)); d->dev = p; + d->no_config_access = p->no_config_access; d->config_cached = d->config_bufsize = 64; d->config = xmalloc(64); d->present = xmalloc(64); memset(d->present, 1, 64); - if (!pci_read_block(p, 0, d->config, 64)) + if (!d->no_config_access && !pci_read_block(p, 0, d->config, 64)) { - fprintf(stderr, "lspci: Unable to read the standard configuration space header of device %04x:%02x:%02x.%d\n", - p->domain, p->bus, p->dev, p->func); - seen_errors++; - return NULL; + d->no_config_access = 1; + d->config_cached = d->config_bufsize = 0; + memset(d->present, 0, 64); } - if ((d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS) + if (!d->no_config_access && (d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS) { /* For cardbus bridges, we need to fetch 64 bytes more to get the * full standard header... */ @@ -290,7 +293,7 @@ show_terse(struct device *d) { int c; struct pci_dev *p = d->dev; - char classbuf[128], devbuf[128]; + char classbuf[256], devbuf[256]; show_slot_name(d); printf(" %s: %s", @@ -397,17 +400,17 @@ show_bases(struct device *d, int cnt, int without_config_data) struct pci_dev *p = d->dev; word cmd = without_config_data ? (PCI_COMMAND_IO | PCI_COMMAND_MEMORY) : get_conf_word(d, PCI_COMMAND); int i; - int virtual = 0; for (i=0; ibase_addr[i]; 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 = without_config_data ? ioflg_to_pciflg(ioflg) : get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i); - u32 hw_lower; + u32 flg = (p->known_fields & PCI_FILL_IO_FLAGS) ? ioflg_to_pciflg(ioflg) : without_config_data ? 0 : get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i); + u32 hw_lower = 0; u32 hw_upper = 0; int broken = 0; + int virtual = 0; if (flg == 0xffffffff) flg = 0; @@ -419,32 +422,26 @@ show_bases(struct device *d, int cnt, int without_config_data) else putchar('\t'); - /* Read address as seen by the hardware */ - if (flg & PCI_BASE_ADDRESS_SPACE_IO) - hw_lower = flg & PCI_BASE_ADDRESS_IO_MASK; - else + /* Detect virtual regions, which are reported by the OS, but unassigned in the device */ + if ((p->known_fields & PCI_FILL_IO_FLAGS) && !without_config_data) { - hw_lower = flg & PCI_BASE_ADDRESS_MEM_MASK; - if ((flg & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) + /* Read address as seen by the hardware */ + hw_lower = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i); + if ((hw_lower & PCI_BASE_ADDRESS_SPACE) == (ioflg_to_pciflg(ioflg) & PCI_BASE_ADDRESS_SPACE)) { - if (i >= cnt - 1) - broken = 1; - else - { - i++; - if (!without_config_data) - hw_upper = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i); + if ((ioflg & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_MEM && + (hw_lower & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) + { + if (i >= cnt - 1) + broken = 1; + else + hw_upper = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i + 1); } + if (pos && !hw_lower && !hw_upper && !(ioflg & PCI_IORESOURCE_PCI_EA_BEI)) + virtual = 1; } } - /* Detect virtual regions, which are reported by the OS, but unassigned in the device */ - if (!without_config_data && pos && !hw_lower && !hw_upper && !(ioflg & PCI_IORESOURCE_PCI_EA_BEI)) - { - flg = pos; - virtual = 1; - } - /* Print base address */ if (flg & PCI_BASE_ADDRESS_SPACE_IO) { @@ -799,7 +796,7 @@ show_verbose(struct device *d) struct pci_dev *p = d->dev; int unknown_config_data = 0; word class = p->device_class; - byte htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f; + byte htype = d->no_config_access ? -1 : (get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f); byte bist; byte max_lat, min_gnt; char *dt_node, *iommu_group; @@ -832,6 +829,7 @@ show_verbose(struct device *d) min_gnt = max_lat = 0; break; default: + if (!d->no_config_access) printf("\t!!! Unknown header type %02x\n", htype); bist = 0; min_gnt = max_lat = 0; @@ -973,6 +971,12 @@ show_hex_dump(struct device *d) { unsigned int i, cnt; + if (d->no_config_access) + { + printf("WARNING: Cannot show hex-dump of the config space\n"); + return; + } + cnt = d->config_cached; if (opt_hex >= 3 && config_fetch(d, cnt, 256-cnt)) { @@ -1008,7 +1012,7 @@ static void show_machine(struct device *d) { struct pci_dev *p = d->dev; - char classbuf[128], vendbuf[128], devbuf[128], svbuf[128], sdbuf[128]; + char classbuf[256], vendbuf[256], devbuf[256], svbuf[256], sdbuf[256]; char *dt_node, *iommu_group; if (verbose)