📄 pci-config.c
字号:
/* pci-config-space.c: Read the PCI configuration space. Read the PCI configuration space using the Intel bus-bridge interface registers. This bypasses the BIOS32 entry, and thus we are not assured of working on all systems. Copyright 1998-2003 by Donald Becker. This software may be used and distributed according to the terms of the GNU General Public License (GPL), incorporated herein by reference. Contact the author for use under other terms. The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation 914 Bay Ridge Road, Suite 220 Annapolis MD 21403 Support and updates available at http://www.scyld.com/diag/index.html Common-sense licensing statement: Using any portion of this program in your own program means that you must give credit to the original author and release the resulting code under the GPL. */static char *version_msg ="pci-config.c:v2.04a 8/14/2003 Donald Becker (becker@scyld.com)\n"" http://www.scyld.com/diag/index.html\n";static char *usage_msg ="Usage: pci-config [-aDfSvVW] [-# <device_index>]\n";static char *long_usage_msg =" This program shows the contents of PCI configuration space. It reads the hardware registers, and thus must be run as 'root'. Running this program with no options shows the installed PCI devices. Each line is prefixed by its index which may be used with -#<index> e.g. \"pci-config -#3\" to specify the device to operate on. Commonly use options are -# <device-index> Operate only on DEVICE-INDEX e.g -#3 The operations on the selected device are -a --show-addresses Show PCI address registers. -S --sleep Put device to sleep (ACPI D3 state) -W --wake Wake a sleeping device (ACPI D0 state) Less commonly used options are -B <bus> --bus <bus> Show only devices on BUS. -A <addr> --set-addresses Set PCI address register 1 to the ADDR. -D --debug Show details of operations -f --force Override checks and perform the operation -u --usage Show this long usage message -v --verbose Verbose mode -V --version Display this program's version information";#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <getopt.h>#if defined(__linux__) && __GNU_LIBRARY__ == 1#include <asm/io.h> /* Newer libraries use <sys/io.h> instead. */#else#include <sys/io.h>#endif#if !defined(__OPTIMIZE__)#error You must compile this driver with "-O"!#endifstruct option longopts[] = { {"show-addresses", 0, 0, 'a'}, /* Show PCI address registers. */ {"set-addresses", 1, 0, 'A'}, /* Show PCI address registers. */ {"bus", 1, 0, 'B'}, /* Show only devices on BUS. */ {"debug", 0, 0, 'D'}, /* Increase debug level. */ {"force", 0, 0, 'f'}, /* Force operation. */ {"set-WOL", 0, 0, 'M'}, /* Set to Wake-On-LAN mode. */ {"sleep", 0, 0, 'S'}, /* Put device to sleep (ACPI D3 state). */ {"usage", 0, 0, 'u'}, /* Show the long usage message. */ {"verbose", 0, 0, 'v'}, /* Verbose mode */ {"version", 0, 0, 'V'}, /* Display version number */ {"wake-on-lan", 0, 0, 'W'}, /* Wake (set to D0 state) the device. */ {"device-index", 1, 0, '#'}, /* Operate only on device INDEX. */ { 0, 0, 0, 0 }};static int verbose=1, opt_a=0, opt_f=0, opt_wake=0, opt_set_WOL=0, debug=0;static int opt_sleep = 0;static long set_address = -1;static void show_addr_config(unsigned char pci_bus, unsigned char pci_dev_fn);static void show_ext_caps(unsigned int *cfg_space, unsigned char pci_bus, unsigned char pci_dev_fn);static void show_one_device(unsigned char pci_bus, unsigned char pci_dev_fn, int dev_num);static void cyclone_WOL(int pci_bus, int pci_dev_fn, void *pci_config_space);static void acpi_wake(unsigned char pci_bus, unsigned char pci_dev_fn, void *config);static void acpi_sleep(unsigned char bus, unsigned char devfn, void *pci_cfg);static int dump_mem_region(long addr);extern int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn, unsigned char where, unsigned char *val);int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned short *val);extern int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned int *val);void pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned char val);void pcibios_write_config_word (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned short val);void pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned int val);int main(int argc, char **argv){ int pci_bus = 0, pci_dev_fn; int errflag = 0, show_version = 0; int c, longind, card_num = 0; int dev_num = 0; while ((c = getopt_long(argc, argv, "#:aA:b:B:DfMSuvVW", longopts, &longind)) != -1) switch (c) { case 'a': opt_a++; break; case 'A': set_address = strtol(optarg, NULL, 16); break; case 'b': printf("Setting bus to %s.\n", optarg); case 'B': pci_bus = strtol(optarg, NULL, 0); break; case 'D': debug++; break; case 'f': opt_f++; break; case 'M': opt_set_WOL++; break; case 'S': opt_sleep++; break; case 'u': printf("%s%s", usage_msg, long_usage_msg); return 0; case 'v': verbose++; break; case 'V': show_version++; break; case 'W': opt_wake++; break; case '#': card_num = atoi(optarg); break; case '?': errflag++; } if (errflag) { fprintf(stderr, "%s%s", usage_msg, " Use -u for more information.\n"); return 3; } if (verbose) printf(version_msg); /* Get access to all of I/O space. */ if (iopl(3) < 0) { perror("pci-config: iopl()"); fprintf(stderr, "This program must be run as root.\n"); return 2; } for (pci_dev_fn = 0; pci_dev_fn < 256; pci_dev_fn++) { /*unsigned char cb;*/ unsigned int pci_id; /* Read the PCI ID from offset 0. */ pcibios_read_config_dword(pci_bus, pci_dev_fn, 0, &pci_id); if (pci_id == 0xffffffff) continue; dev_num++; if (card_num == 0) { printf("Device #%d at bus %d device/function %d/%d, %8.8x.\n", dev_num, pci_bus, pci_dev_fn>>3, pci_dev_fn&7, pci_id); } else if (card_num == dev_num) { show_one_device(pci_bus, pci_dev_fn, dev_num); } /* Skip fn1-fn7 if this is not a multi-function device. */ if ((pci_dev_fn & 7) == 0) { unsigned int cdw; pcibios_read_config_dword(pci_bus, pci_dev_fn, 3*4, &cdw); if ((cdw & 0x00800000) == 0) pci_dev_fn += 7; } } return 0;}static void show_one_device(unsigned char pci_bus, unsigned char pci_dev_fn, int dev_num){ unsigned int config[64]; int i; int pci_id; printf("Device #%d at bus %d device/function %d/%d.", dev_num, pci_bus, pci_dev_fn>>3, pci_dev_fn&7); for (i = 0; i < 64; i++) { pcibios_read_config_dword(pci_bus, pci_dev_fn, i<<2, &config[i]); printf("%s%8.8x", i % 8 == 0 ? "\n " : " ", config[i]); } printf("\n"); for (i = 0; i < 5; i++) { unsigned int pciaddr = config[4 + i]; if (pciaddr) printf(" Base Address %d: %s at %8.8x.\n", i, pciaddr & 1 ? "I/O" : "Memory", pciaddr & ~1); } if (set_address >= 0) { fprintf(stderr, "Setting PCI address register 1 to 0x%lx.\n", set_address); pcibios_write_config_dword(pci_bus, pci_dev_fn, 0x14, set_address); pcibios_write_config_dword(pci_bus, pci_dev_fn, 0x04, config[1] | 3); } if (opt_a) show_addr_config(pci_bus, pci_dev_fn); pci_id = config[0]; if (config[1] & 0x00100000) show_ext_caps(config, pci_bus, pci_dev_fn); if (config[10]) { char *cis_addr_space[] = {"PCI configuration space", "BAR 0", "BAR 1", "BAR 2", "BAR 3", }; int space = config[10] & 7; printf(" CardBus CIS pointer 0x%4.4x (%s), address %x.\n", config[10], cis_addr_space[space], config[4 + (space-1)]); if (space > 0 && space < 4)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -