From 6aa54f1bd8c734ee8f6399945f353f9ba1dc9677 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Fri, 13 Aug 2004 19:51:05 +0000 Subject: [PATCH] Fixed bugs in reading and interpreting of base addresses. git-archimport-id: mj@ucw.cz--public/pciutils--main--2.2--patch-58 --- ChangeLog | 17 +++++++++++++++++ lib/generic.c | 45 ++++++++++++++++++--------------------------- lib/pci.h | 2 +- lspci.c | 24 ++++++++++++++++++------ 4 files changed, 54 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 86f8d91..1fc2e74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2004-08-13 Martin Mares + + * lspci.c (show_rom): Use the same logic for printing disabled + or unassigned ROM's as we do in show_bases() for the other BAR's. + + * lib/generic.c (pci_generic_fill_info): Better reaction to + invalid 64-bit addresses. Also d->hdrtype should not include + bit 7, which caused mysterious errors on multi-function devices. + + * lib/generic.c (pci_generic_fill_info): Fill in base addresses + even if the regions are known to be disabled. It is the client's + job to interpret them. (And it is not a trivial job if you want + to do it correctly, since you need to check I/O and memory enables + on all upstream bridges, too.) However, it could be interesting to + introduce functions for interpreting the addresses and even for + mapping the regions and doing I/O on them. + 2004-07-30 Martin Mares * lspci.c: HyperTransport improvements from Maciej. diff --git a/lib/generic.c b/lib/generic.c index 25d3faa..0402ad1 100644 --- a/lib/generic.c +++ b/lib/generic.c @@ -80,7 +80,7 @@ pci_generic_fill_info(struct pci_dev *d, int flags) struct pci_access *a = d->access; if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) && d->hdrtype < 0) - d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE); + d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f; if (flags & PCI_FILL_IDENT) { d->vendor_id = pci_read_word(d, PCI_VENDOR_ID); @@ -106,41 +106,32 @@ pci_generic_fill_info(struct pci_dev *d, int flags) } if (cnt) { - u16 cmd = pci_read_word(d, PCI_COMMAND); for(i=0; ibase_addr[i] = x; - if (x & PCI_BASE_ADDRESS_SPACE_IO) - { - if (!a->buscentric && !(cmd & PCI_COMMAND_IO)) - d->base_addr[i] = 0; - } - else if (a->buscentric || (cmd & PCI_COMMAND_MEMORY)) + if ((x & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) + d->base_addr[i] = x; + else { - if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) + if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != PCI_BASE_ADDRESS_MEM_TYPE_64) + d->base_addr[i] = x; + else if (i >= cnt-1) + a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen for BAR %d.", d->domain, d->bus, d->dev, d->func, i); + else { - if (i >= cnt-1) - a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen.", d->domain, d->bus, d->dev, d->func); - else - { - u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4); + u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4); #ifdef HAVE_64BIT_ADDRESS - d->base_addr[i-1] |= ((pciaddr_t) y) << 32; + d->base_addr[i-1] = x | (((pciaddr_t) y) << 32); #else - if (y) - { - a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.", d->domain, d->bus, d->dev, d->func); - d->base_addr[i-1] = 0; - } + if (y) + a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.", d->domain, d->bus, d->dev, d->func); + else + d->base_addr[i-1] = x; #endif - } } } - else - d->base_addr[i] = 0; } } } @@ -159,9 +150,9 @@ pci_generic_fill_info(struct pci_dev *d, int flags) } if (reg) { - u32 a = pci_read_long(d, reg); - if (a & PCI_ROM_ADDRESS_ENABLE) - d->rom_base_addr = a; + u32 u = pci_read_long(d, reg); + if (u != 0xffffffff) + d->rom_base_addr = u; } } return flags & ~PCI_FILL_SIZES; diff --git a/lib/pci.h b/lib/pci.h index 188f2e5..1083cb7 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -140,7 +140,7 @@ struct pci_dev { struct pci_methods *methods; byte *cache; /* Cached config registers */ int cache_len; - int hdrtype; /* Cached header type, -1 if unknown */ + int hdrtype; /* Cached low 7 bits of header type, -1 if unknown */ void *aux; /* Auxillary data */ }; diff --git a/lspci.c b/lspci.c index aa6b37a..943c1cd 100644 --- a/lspci.c +++ b/lspci.c @@ -916,21 +916,33 @@ show_ht(struct device *d, int where, int cmd) } static void -show_rom(struct device *d) +show_rom(struct device *d, int reg) { struct pci_dev *p = d->dev; pciaddr_t rom = p->rom_base_addr; pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->rom_size : 0; + u32 flg = get_conf_long(d, reg); + word cmd = get_conf_word(d, PCI_COMMAND); - if (!rom && !len) + if (!rom && !flg && !len) return; - printf("\tExpansion ROM at "); + putchar('\t'); + if ((rom & PCI_ROM_ADDRESS_MASK) && !(flg & PCI_ROM_ADDRESS_MASK)) + { + printf("[virtual] "); + flg = rom; + } + printf("Expansion 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 (!(rom & PCI_ROM_ADDRESS_ENABLE)) + if (!(flg & PCI_ROM_ADDRESS_ENABLE)) printf(" [disabled]"); + else if (!(cmd & PCI_COMMAND_MEMORY)) + printf(" [disabled by cmd]"); show_size(len); putchar('\n'); } @@ -1363,7 +1375,7 @@ static void show_htype0(struct device *d) { show_bases(d, 6); - show_rom(d); + show_rom(d, PCI_ROM_ADDRESS); show_caps(d); } @@ -1451,7 +1463,7 @@ show_htype1(struct device *d) FLAG(sec_stat, PCI_STATUS_SIG_SYSTEM_ERROR), FLAG(sec_stat, PCI_STATUS_DETECTED_PARITY)); - show_rom(d); + show_rom(d, PCI_ROM_ADDRESS1); if (verbose > 1) printf("\tBridgeCtl: Parity%c SERR%c NoISA%c VGA%c MAbort%c >Reset%c FastB2B%c\n", -- 2.39.2