X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lspci.c;h=14825a8969cab5f8ed2363082df57d1be71dc308;hb=579b19ffe582dca15d89da7f6198edb15eb1e357;hp=14c943d2670384b4baf0dff3e0b9af5c1b909eca;hpb=8d047897623f2e14aaa4ada0400adeb5271460b1;p=pciutils.git diff --git a/lspci.c b/lspci.c index 14c943d..14825a8 100644 --- a/lspci.c +++ b/lspci.c @@ -1,9 +1,9 @@ /* - * $Id: lspci.c,v 1.31 1999/11/03 09:30:11 mj Exp $ + * $Id: lspci.c,v 1.43 2002/12/26 20:24:50 mj Exp $ * * Linux PCI Utilities -- List All PCI Devices * - * Copyright (c) 1997--1999 Martin Mares + * Copyright (c) 1997--2002 Martin Mares * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -34,7 +34,8 @@ Usage: lspci []\n\ -v\t\tBe verbose\n\ -n\t\tShow numeric ID's\n\ -b\t\tBus-centric view (PCI addresses and IRQ's instead of those seen by the CPU)\n\ --x\t\tShow hex-dump of config space\n\ +-x\t\tShow hex-dump of the standard portion of config space\n\ +-xxx\t\tShow hex-dump of the whole config space (dangerous; root only)\n\ -s [[]:][][.[]]\tShow only devices in selected slots\n\ -d []:[]\tShow only selected devices\n\ -t\t\tShow bus tree\n\ @@ -68,12 +69,22 @@ static struct pci_access *pacc; #ifdef ARCH_SPARC64 #define IO_FORMAT "%016Lx" -#elif defined(HAVE_64BIT_ADDRESS) +#elif defined(HAVE_LONG_ADDRESS) #define IO_FORMAT "%04Lx" #else #define IO_FORMAT "%04lx" #endif +/* + * If we aren't being compiled by GCC, use malloc() instead of alloca(). + * This increases our memory footprint, but only slightly since we don't + * use alloca() much. + */ + +#ifndef __GNUC__ +#define alloca malloc +#endif + /* Our view of the PCI bus */ struct device { @@ -101,7 +112,7 @@ scan_device(struct pci_dev *p) if (how_much < 128 && (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... */ - if (!pci_read_block(p, 0, d->config+64, 64)) + if (!pci_read_block(p, 64, d->config+64, 64)) die("Unable to read cardbus bridge extension data."); how_much = 128; } @@ -365,57 +376,181 @@ show_bases(struct device *d, int cnt) static void show_pm(struct device *d, int where, int cap) { - int t; + int t, b; + static int pm_aux_current[8] = { 0, 55, 100, 160, 220, 270, 320, 375 }; printf("Power Management version %d\n", cap & PCI_PM_CAP_VER_MASK); if (verbose < 2) return; - printf("\t\tFlags: PMEClk%c AuxPwr%c DSI%c D1%c D2%c PME%c\n", + printf("\t\tFlags: PMEClk%c DSI%c D1%c D2%c AuxCurrent=%dmA PME(D0%c,D1%c,D2%c,D3hot%c,D3cold%c)\n", FLAG(cap, PCI_PM_CAP_PME_CLOCK), - FLAG(cap, PCI_PM_CAP_AUX_POWER), FLAG(cap, PCI_PM_CAP_DSI), FLAG(cap, PCI_PM_CAP_D1), FLAG(cap, PCI_PM_CAP_D2), - FLAG(cap, PCI_PM_CAP_PME)); + pm_aux_current[(cap >> 6) & 7], + FLAG(cap, PCI_PM_CAP_PME_D0), + FLAG(cap, PCI_PM_CAP_PME_D1), + FLAG(cap, PCI_PM_CAP_PME_D2), + FLAG(cap, PCI_PM_CAP_PME_D3_HOT), + FLAG(cap, PCI_PM_CAP_PME_D3_COLD)); config_fetch(d, where + PCI_PM_CTRL, PCI_PM_SIZEOF - PCI_PM_CTRL); t = get_conf_word(d, where + PCI_PM_CTRL); - printf("\t\tStatus: D%d PME-Enable%c DSel=%x DScale=%x PME%c\n", + printf("\t\tStatus: D%d PME-Enable%c DSel=%d DScale=%d PME%c\n", t & PCI_PM_CTRL_STATE_MASK, FLAG(t, PCI_PM_CTRL_PME_ENABLE), (t & PCI_PM_CTRL_DATA_SEL_MASK) >> 9, (t & PCI_PM_CTRL_DATA_SCALE_MASK) >> 13, FLAG(t, PCI_PM_CTRL_PME_STATUS)); + b = get_conf_byte(d, where + PCI_PM_PPB_EXTENSIONS); + if (b) + printf("\t\tBridge: PM%c B3%c\n", + FLAG(t, PCI_PM_BPCC_ENABLE), + FLAG(~t, PCI_PM_PPB_B2_B3)); +} + +static void +format_agp_rate(int rate, char *buf, int agp3) +{ + char *c = buf; + int i; + + for(i=0; i<=2; i++) + if (rate & (1 << i)) + { + if (c != buf) + *c++ = ','; + *c++ = 'x'; + *c++ = '0' + (1 << (i + 2*agp3)); + } + if (c != buf) + *c = 0; + else + strcpy(buf, ""); } static void show_agp(struct device *d, int where, int cap) { u32 t; + char rate[8]; + int ver, rev; + int agp3 = 0; - t = cap & 0xff; - printf("AGP version %x.%x\n", cap/16, cap%16); + ver = (cap >> 4) & 0x0f; + rev = cap & 0x0f; + printf("AGP version %x.%x\n", ver, rev); if (verbose < 2) return; config_fetch(d, where + PCI_AGP_STATUS, PCI_AGP_SIZEOF - PCI_AGP_STATUS); t = get_conf_long(d, where + PCI_AGP_STATUS); - printf("\t\tStatus: RQ=%d SBA%c 64bit%c FW%c Rate=%s%s%s\n", - (t & PCI_AGP_STATUS_RQ_MASK) >> 24U, + if (ver >= 3 && (t & PCI_AGP_STATUS_AGP3)) + agp3 = 1; + format_agp_rate(t & 7, rate, agp3); + printf("\t\tStatus: RQ=%d Iso%c ArqSz=%d Cal=%d SBA%c ITACoh%c GART64%c HTrans%c 64bit%c FW%c AGP3%c Rate=%s\n", + ((t & PCI_AGP_STATUS_RQ_MASK) >> 24U) + 1, + FLAG(t, PCI_AGP_STATUS_ISOCH), + ((t & PCI_AGP_STATUS_ARQSZ_MASK) >> 13), + ((t & PCI_AGP_STATUS_CAL_MASK) >> 10), FLAG(t, PCI_AGP_STATUS_SBA), + FLAG(t, PCI_AGP_STATUS_ITA_COH), + FLAG(t, PCI_AGP_STATUS_GART64), + FLAG(t, PCI_AGP_STATUS_HTRANS), FLAG(t, PCI_AGP_STATUS_64BIT), FLAG(t, PCI_AGP_STATUS_FW), - (t & PCI_AGP_STATUS_RATE4) ? "4" : "", - (t & PCI_AGP_STATUS_RATE2) ? "2" : "", - (t & PCI_AGP_STATUS_RATE1) ? "1" : ""); + FLAG(t, PCI_AGP_STATUS_AGP3), + rate); t = get_conf_long(d, where + PCI_AGP_COMMAND); - printf("\t\tCommand: RQ=%d SBA%c AGP%c 64bit%c FW%c Rate=%s%s%s\n", - (t & PCI_AGP_COMMAND_RQ_MASK) >> 24U, + format_agp_rate(t & 7, rate, agp3); + printf("\t\tCommand: RQ=%d ArqSz=%d Cal=%d SBA%c AGP%c GART64%c 64bit%c FW%c Rate=%s\n", + ((t & PCI_AGP_COMMAND_RQ_MASK) >> 24U) + 1, + ((t & PCI_AGP_COMMAND_ARQSZ_MASK) >> 13), + ((t & PCI_AGP_COMMAND_CAL_MASK) >> 10), FLAG(t, PCI_AGP_COMMAND_SBA), FLAG(t, PCI_AGP_COMMAND_AGP), + FLAG(t, PCI_AGP_COMMAND_GART64), FLAG(t, PCI_AGP_COMMAND_64BIT), FLAG(t, PCI_AGP_COMMAND_FW), - (t & PCI_AGP_COMMAND_RATE4) ? "4" : "", - (t & PCI_AGP_COMMAND_RATE2) ? "2" : "", - (t & PCI_AGP_COMMAND_RATE1) ? "1" : ""); + rate); +} + +static void +show_pcix_nobridge(struct device *d, int where) +{ + u16 command = get_conf_word(d, where + PCI_PCIX_COMMAND); + u32 status = get_conf_long(d, where + PCI_PCIX_STATUS); + printf("PCI-X non-bridge device.\n"); + if (verbose < 2) + return; + printf("\t\tCommand: DPERE%c ERO%c RBC=%d OST=%d\n", + FLAG(command, PCI_PCIX_COMMAND_DPERE), + FLAG(command, PCI_PCIX_COMMAND_ERO), + ((command & PCI_PCIX_COMMAND_MAX_MEM_READ_BYTE_COUNT) >> 2U), + ((command & PCI_PCIX_COMMAND_MAX_OUTSTANDING_SPLIT_TRANS) >> 4U)); + printf("\t\tStatus: Bus=%u Dev=%u Func=%u 64bit%c 133MHz%c SCD%c USC%c, DC=%s, DMMRBC=%u, DMOST=%u, DMCRS=%u, RSCEM%c", + ((status >> 8) & 0xffU), // bus + ((status >> 3) & 0x1fU), // dev + (status & PCI_PCIX_BRIDGE_STATUS_FUNCTION), // function + FLAG(status, PCI_PCIX_STATUS_64BIT), + FLAG(status, PCI_PCIX_STATUS_133MHZ), + FLAG(status, PCI_PCIX_STATUS_SC_DISCARDED), + FLAG(status, PCI_PCIX_STATUS_UNEXPECTED_SC), + ((status & PCI_PCIX_STATUS_DEVICE_COMPLEXITY) ? "bridge" : "simple"), + ((status >> 21) & 3U), + ((status >> 23) & 7U), + ((status >> 26) & 7U), + FLAG(status, PCI_PCIX_STATUS_RCVD_SC_ERR_MESS)); +} + +static void +show_pcix_bridge(struct device *d, int where) +{ + u16 secstatus; + u32 status, upstcr, downstcr; + printf("PCI-X bridge device.\n"); + if (verbose < 2) + return; + secstatus = get_conf_word(d, where + PCI_PCIX_BRIDGE_SEC_STATUS); + printf("\t\tSecondary Status: 64bit%c, 133MHz%c, SCD%c, USC%c, SCO%c, SRD%c Freq=%d\n", + FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_64BIT), + FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_133MHZ), + FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_SC_DISCARDED), + FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_UNEXPECTED_SC), + FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_SC_OVERRUN), + FLAG(secstatus, PCI_PCIX_BRIDGE_SEC_STATUS_SPLIT_REQUEST_DELAYED), + ((secstatus >> 6) & 7)); + status = get_conf_long(d, where + PCI_PCIX_BRIDGE_STATUS); + printf("\t\tStatus: Bus=%u Dev=%u Func=%u 64bit%c 133MHz%c SCD%c USC%c, SCO%c, SRD%c\n", + ((status >> 8) & 0xff), // bus + ((status >> 3) & 0x1f), // dev + (status & PCI_PCIX_BRIDGE_STATUS_FUNCTION), // function + FLAG(status, PCI_PCIX_BRIDGE_STATUS_64BIT), + FLAG(status, PCI_PCIX_BRIDGE_STATUS_133MHZ), + FLAG(status, PCI_PCIX_BRIDGE_STATUS_SC_DISCARDED), + FLAG(status, PCI_PCIX_BRIDGE_STATUS_UNEXPECTED_SC), + FLAG(status, PCI_PCIX_BRIDGE_STATUS_SC_OVERRUN), + FLAG(status, PCI_PCIX_BRIDGE_STATUS_SPLIT_REQUEST_DELAYED)); + upstcr = get_conf_long(d, where + PCI_PCIX_BRIDGE_UPSTREAM_SPLIT_TRANS_CTRL); + printf("\t\t: Upstream: Capacity=%u, Commitment Limit=%u\n", + (upstcr & PCI_PCIX_BRIDGE_STR_CAPACITY), + (upstcr >> 16) & 0xffff); + downstcr = get_conf_long(d, where + PCI_PCIX_BRIDGE_DOWNSTREAM_SPLIT_TRANS_CTRL); + printf("\t\t: Downstream: Capacity=%u, Commitment Limit=%u\n", + (downstcr & PCI_PCIX_BRIDGE_STR_CAPACITY), + (downstcr >> 16) & 0xffff); +} + +static void +show_pcix(struct device *d, int where) +{ + switch (d->dev->hdrtype) + { + case PCI_HEADER_TYPE_NORMAL: + show_pcix_nobridge(d, where); + break; + case PCI_HEADER_TYPE_BRIDGE: + show_pcix_bridge(d, where); + break; + } } static void @@ -520,6 +655,9 @@ show_caps(struct device *d) case PCI_CAP_ID_MSI: show_msi(d, where, cap); break; + case PCI_CAP_ID_PCIX: + show_pcix(d, where); + break; default: printf("#%02x [%04x]\n", id, cap); } @@ -644,7 +782,7 @@ show_htype2(struct device *d) u32 base = get_conf_long(d, PCI_CB_MEMORY_BASE_0 + p); u32 limit = get_conf_long(d, PCI_CB_MEMORY_LIMIT_0 + p); if (limit > base || verb) - printf("Memory window %d: %08x-%08x%s%s\n", i, base, limit, + printf("\tMemory window %d: %08x-%08x%s%s\n", i, base, limit, (cmd & PCI_COMMAND_MEMORY) ? "" : " [disabled]", (brc & (PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 << i)) ? " (prefetchable)" : ""); } @@ -704,11 +842,7 @@ show_verbose(struct device *d) { case PCI_HEADER_TYPE_NORMAL: if (class == PCI_CLASS_BRIDGE_PCI) - { - badhdr: - printf("\t!!! Header type %02x doesn't match class code %04x\n", htype, class); - return; - } + printf("\t!!! Invalid class %04x for header type %02x\n", class, htype); max_lat = get_conf_byte(d, PCI_MAX_LAT); min_gnt = get_conf_byte(d, PCI_MIN_GNT); subsys_v = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID); @@ -716,13 +850,13 @@ show_verbose(struct device *d) break; case PCI_HEADER_TYPE_BRIDGE: if (class != PCI_CLASS_BRIDGE_PCI) - goto badhdr; + printf("\t!!! Invalid class %04x for header type %02x\n", class, htype); irq = int_pin = min_gnt = max_lat = 0; subsys_v = subsys_d = 0; break; case PCI_HEADER_TYPE_CARDBUS: if ((class >> 8) != PCI_BASE_CLASS_BRIDGE) - goto badhdr; + printf("\t!!! Invalid class %04x for header type %02x\n", class, htype); min_gnt = max_lat = 0; subsys_v = get_conf_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID); subsys_d = get_conf_word(d, PCI_CB_SUBSYSTEM_ID); @@ -767,12 +901,18 @@ show_verbose(struct device *d) FLAG(status, PCI_STATUS_DETECTED_PARITY)); if (cmd & PCI_COMMAND_MASTER) { - printf("\tLatency: "); - if (min_gnt) - printf("%d min, ", min_gnt); - if (max_lat) - printf("%d max, ", max_lat); - printf("%d set", latency); + printf("\tLatency: %d", latency); + if (min_gnt || max_lat) + { + printf(" ("); + if (min_gnt) + printf("%dns min", min_gnt*250); + if (min_gnt && max_lat) + printf(", "); + if (max_lat) + printf("%dns max", max_lat*250); + putchar(')'); + } if (cache_line) printf(", cache line size %02x", cache_line); putchar('\n'); @@ -987,7 +1127,10 @@ insert_dev(struct device *d, struct bridge *b) struct bridge *c; for(c=b->child; c; c=c->next) if (c->secondary <= p->bus && p->bus <= c->subordinate) - return insert_dev(d, c); + { + insert_dev(d, c); + return; + } bus = new_bus(b, p->bus); } /* Simple insertion at the end _does_ guarantee the correct order as the