📄 lspci.c
字号:
break; header = get_conf_long(d, where); if (!header) break; id = header & 0xffff; printf("\tCapabilities: [%03x] ", where); if (been_there[where]++) { printf("<chain looped>\n"); break; } switch (id) { case PCI_EXT_CAP_ID_AER: printf("Advanced Error Reporting <?>\n"); break; case PCI_EXT_CAP_ID_VC: printf("Virtual Channel <?>\n"); break; case PCI_EXT_CAP_ID_DSN: cap_dsn(d, where); break; case PCI_EXT_CAP_ID_PB: printf("Power Budgeting <?>\n"); break; case PCI_EXT_CAP_ID_RCLINK: printf("Root Complex Link <?>\n"); break; case PCI_EXT_CAP_ID_RCILINK: printf("Root Complex Internal Link <?>\n"); break; case PCI_EXT_CAP_ID_RCECOLL: printf("Root Complex Event Collector <?>\n"); break; case PCI_EXT_CAP_ID_MFVC: printf("Multi-Function Virtual Channel <?>\n"); break; case PCI_EXT_CAP_ID_RBCB: printf("Root Bridge Control Block <?>\n"); break; case PCI_EXT_CAP_ID_VNDR: printf("Vendor Specific Information <?>\n"); break; case PCI_EXT_CAP_ID_ACS: printf("Access Controls <?>\n"); break; default: printf("#%02x\n", id); break; } where = header >> 20; } while (where);}static voidshow_caps(struct device *d){ int can_have_ext_caps = 0; if (get_conf_word(d, PCI_STATUS) & PCI_STATUS_CAP_LIST) { int where = get_conf_byte(d, PCI_CAPABILITY_LIST) & ~3; byte been_there[256]; memset(been_there, 0, 256); while (where) { int id, next, cap; printf("\tCapabilities: "); if (!config_fetch(d, where, 4)) { puts("<access denied>"); break; } id = get_conf_byte(d, where + PCI_CAP_LIST_ID); next = get_conf_byte(d, where + PCI_CAP_LIST_NEXT) & ~3; cap = get_conf_word(d, where + PCI_CAP_FLAGS); printf("[%02x] ", where); if (been_there[where]++) { printf("<chain looped>\n"); break; } if (id == 0xff) { printf("<chain broken>\n"); break; } switch (id) { case PCI_CAP_ID_PM: cap_pm(d, where, cap); break; case PCI_CAP_ID_AGP: cap_agp(d, where, cap); break; case PCI_CAP_ID_VPD: printf("Vital Product Data <?>\n"); break; case PCI_CAP_ID_SLOTID: cap_slotid(cap); break; case PCI_CAP_ID_MSI: cap_msi(d, where, cap); break; case PCI_CAP_ID_CHSWP: printf("CompactPCI hot-swap <?>\n"); break; case PCI_CAP_ID_PCIX: cap_pcix(d, where); can_have_ext_caps = 1; break; case PCI_CAP_ID_HT: cap_ht(d, where, cap); break; case PCI_CAP_ID_VNDR: printf("Vendor Specific Information <?>\n"); break; case PCI_CAP_ID_DBG: cap_debug_port(cap); break; case PCI_CAP_ID_CCRC: printf("CompactPCI central resource control <?>\n"); break; case PCI_CAP_ID_HOTPLUG: printf("Hot-plug capable\n"); break; case PCI_CAP_ID_SSVID: cap_ssvid(d, where); break; case PCI_CAP_ID_AGP3: printf("AGP3 <?>\n"); break; case PCI_CAP_ID_SECURE: printf("Secure device <?>\n"); break; case PCI_CAP_ID_EXP: cap_express(d, where, cap); can_have_ext_caps = 1; break; case PCI_CAP_ID_MSIX: cap_msix(d, where, cap); break; case PCI_CAP_ID_SATA: printf("SATA HBA <?>\n"); break; case PCI_CAP_ID_AF: printf("PCIe advanced features <?>\n"); break; default: printf("#%02x [%04x]\n", id, cap); } where = next; } } if (can_have_ext_caps) show_ext_caps(d);}/*** Verbose output ***/static voidshow_size(pciaddr_t x){ if (!x) return; printf(" [size="); if (x < 1024) printf("%d", (int) x); else if (x < 1048576) printf("%dK", (int)(x / 1024)); else if (x < 0x80000000) printf("%dM", (int)(x / 1048576)); else printf(PCIADDR_T_FMT, x); putchar(']');}static voidshow_bases(struct device *d, int cnt){ struct pci_dev *p = d->dev; word cmd = get_conf_word(d, PCI_COMMAND); int i; for(i=0; i<cnt; i++) { pciaddr_t pos = p->base_addr[i]; pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->size[i] : 0; u32 flg = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i); if (flg == 0xffffffff) flg = 0; if (!pos && !flg && !len) continue; if (verbose > 1) printf("\tRegion %d: ", i); else putchar('\t'); if (pos && !flg) /* Reported by the OS, but not by the device */ { printf("[virtual] "); flg = pos; } if (flg & PCI_BASE_ADDRESS_SPACE_IO) { pciaddr_t a = pos & PCI_BASE_ADDRESS_IO_MASK; printf("I/O ports at "); if (a) printf(PCIADDR_PORT_FMT, a); else if (flg & PCI_BASE_ADDRESS_IO_MASK) printf("<ignored>"); else printf("<unassigned>"); 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("<invalid-64bit-slot>"); done = 1; } else { i++; z = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i); if (opt_buscentric) { u32 y = a & 0xffffffff; if (a || z) printf("%08x%08x", z, y); else printf("<unassigned>"); done = 1; } } } if (!done) { if (a) printf(PCIADDR_T_FMT, a); else printf(((flg & PCI_BASE_ADDRESS_MEM_MASK) || z) ? "<ignored>" : "<unassigned>"); } 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 (!(cmd & PCI_COMMAND_MEMORY)) printf(" [disabled]"); } show_size(len); putchar('\n'); }}static voidshow_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 && !flg && !len) return; 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("<ignored>"); else printf("<unassigned>"); if (!(flg & PCI_ROM_ADDRESS_ENABLE)) printf(" [disabled]"); else if (!(cmd & PCI_COMMAND_MEMORY)) printf(" [disabled by cmd]"); show_size(len); putchar('\n');}static voidshow_htype0(struct device *d){ show_bases(d, 6); show_rom(d, PCI_ROM_ADDRESS); show_caps(d);}static voidshow_htype1(struct device *d){ u32 io_base = get_conf_byte(d, PCI_IO_BASE); u32 io_limit = get_conf_byte(d, PCI_IO_LIMIT); u32 io_type = io_base & PCI_IO_RANGE_TYPE_MASK; u32 mem_base = get_conf_word(d, PCI_MEMORY_BASE); u32 mem_limit = get_conf_word(d, PCI_MEMORY_LIMIT); u32 mem_type = mem_base & PCI_MEMORY_RANGE_TYPE_MASK; u32 pref_base = get_conf_word(d, PCI_PREF_MEMORY_BASE); u32 pref_limit = get_conf_word(d, PCI_PREF_MEMORY_LIMIT); u32 pref_type = pref_base & PCI_PREF_RANGE_TYPE_MASK; word sec_stat = get_conf_word(d, PCI_SEC_STATUS); word brc = get_conf_word(d, PCI_BRIDGE_CONTROL); int verb = verbose > 2; show_bases(d, 2); printf("\tBus: primary=%02x, secondary=%02x, subordinate=%02x, sec-latency=%d\n", get_conf_byte(d, PCI_PRIMARY_BUS), get_conf_byte(d, PCI_SECONDARY_BUS), get_conf_byte(d, PCI_SUBORDINATE_BUS), get_conf_byte(d, PCI_SEC_LATENCY_TIMER)); if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) || (io_type != PCI_IO_RANGE_TYPE_16 && io_type != PCI_IO_RANGE_TYPE_32)) printf("\t!!! Unknown I/O range types %x/%x\n", io_base, io_limit); else { io_base = (io_base & PCI_IO_RANGE_MASK) << 8; io_limit = (io_limit & PCI_IO_RANGE_MASK) << 8; if (io_type == PCI_IO_RANGE_TYPE_32) { io_base |= (get_conf_word(d, PCI_IO_BASE_UPPER16) << 16); io_limit |= (get_conf_word(d, PCI_IO_LIMIT_UPPER16) << 16); } if (io_base <= io_limit || verb) printf("\tI/O behind bridge: %08x-%08x\n", io_base, io_limit+0xfff); } if (mem_type != (mem_limit & PCI_MEMORY_RANGE_TYPE_MASK) || mem_type) printf("\t!!! Unknown memory range types %x/%x\n", mem_base, mem_limit); else { mem_base = (mem_base & PCI_MEMORY_RANGE_MASK) << 16; mem_limit = (mem_limit & PCI_MEMORY_RANGE_MASK) << 16; if (mem_base <= mem_limit || verb) printf("\tMemory behind bridge: %08x-%08x\n", mem_base, mem_limit + 0xfffff); } if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) || (pref_type != PCI_PREF_RANGE_TYPE_32 && pref_type != PCI_PREF_RANGE_TYPE_64)) printf("\t!!! Unknown prefetchable memory range types %x/%x\n", pref_base, pref_limit); else { pref_base = (pref_base & PCI_PREF_RANGE_MASK) << 16; pref_limit = (pref_limit & PCI_PREF_RANGE_MASK) << 16; if (pref_base <= pref_limit || verb) { if (pref_type == PCI_PREF_RANGE_TYPE_32) printf("\tPrefetchable memory behind bridge: %08x-%08x\n", pref_base, pref_limit + 0xfffff); else printf("\tPrefetchable memory behind bridge: %08x%08x-%08x%08x\n", get_conf_long(d, PCI_PREF_BASE_UPPER32), pref_base, get_conf_long(d, PCI_PREF_LIMIT_UPPER32), pref_limit + 0xfffff); } } if (verbose > 1) printf("\tSecondary status: 66MHz%c FastB2B%c ParErr%c DEVSEL=%s >TAbort%c <TAbort%c <MAbort%c <SERR%c <PERR%c\n", FLAG(sec_stat, PCI_STATUS_66MHZ), FLAG(sec_stat, PCI_STATUS_FAST_BACK), FLAG(sec_stat, PCI_STATUS_PARITY), ((sec_stat & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) ? "slow" : ((sec_stat & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) ? "medium" : ((sec_stat & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) ? "fast" : "??", FLAG(sec_stat, PCI_STATUS_SIG_TARGET_ABORT), FLAG(sec_stat, PCI_STATUS_REC_TARGET_ABORT), FLAG(sec_stat, PCI_STATUS_REC_MASTER_ABORT), FLAG(sec_stat, PCI_STATUS_SIG_SYSTEM_ERROR), FLAG(sec_stat, PCI_STATUS_DETECTED_PARITY)); 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", 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_MASTER_ABORT), FLAG(brc, PCI_BRIDGE_CTL_BUS_RESET), FLAG(brc, PCI_BRIDGE_CTL_FAST_BACK)); printf("\t\tPriDiscTmr%c SecDiscTmr%c DiscTmrStat%c DiscTmrSERREn%c\n", FLAG(brc, PCI_BRIDGE_CTL_PRI_DISCARD_TIMER), FLAG(brc, PCI_BRIDGE_CTL_SEC_DISCARD_TIMER), FLAG(brc, PCI_BRIDGE_CTL_DISCARD_TIMER_STATUS), FLAG(brc, PCI_BRIDGE_CTL_DISCARD_TIMER_SERR_EN)); } show_caps(d);}static voidshow_htype2(struct device *d){ int i; word cmd = get_conf_word(d, PCI_COMMAND); word brc = get_conf_word(d, PCI_CB_BRIDGE_CONTROL); word exca; int verb = verbose > 2; show_bases(d, 1); printf("\tBus: primary=%02x, secondary=%02x, subordinate=%02x, sec-latency=%d\n", get_conf_byte(d, PCI_CB_PRIMARY_BUS), get_conf_byte(d, PCI_CB_CARD_BUS), get_conf_byte(d, PCI_CB_SUBORDINATE_BUS), get_conf_byte(d, PCI_CB_LATENCY_TIMER)); for(i=0; i<2; i++) { int p = 8*i; 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -