📄 pci-config.c
字号:
dump_mem_region(config[4 + ((space-1))]); } if (opt_sleep) acpi_sleep(pci_bus, pci_dev_fn, config); if (opt_wake) acpi_wake(pci_bus, pci_dev_fn, config); if (opt_set_WOL) if (pci_id == 0x905510b7) cyclone_WOL(pci_bus, pci_dev_fn, config);}static void show_addr_config(unsigned char pci_bus, unsigned char pci_dev_fn){ int i; unsigned int pciaddr, cdw; for (i = 0; i < 5; i++) { int cfg_i = 0x10 + (i<<2); pcibios_read_config_dword(pci_bus, pci_dev_fn, cfg_i, &pciaddr); pcibios_write_config_dword(pci_bus, pci_dev_fn, cfg_i, 0xffffffff); pcibios_read_config_dword(pci_bus, pci_dev_fn, cfg_i, &cdw); if (cdw == 0) break; printf(" Address %d %s at %8.8x, decoded bits are %8.8x.\n", i, cdw & 1 ? "is I/O" : "memory", pciaddr & ~1, ~cdw); pcibios_write_config_dword(pci_bus, pci_dev_fn, cfg_i, pciaddr); } pcibios_read_config_dword(pci_bus, pci_dev_fn, 0x30, &pciaddr); pcibios_write_config_dword(pci_bus, pci_dev_fn, 0x30, 0xfffffffe); pcibios_read_config_dword(pci_bus, pci_dev_fn, 0x30, &cdw); pcibios_write_config_dword(pci_bus, pci_dev_fn, 0x30, pciaddr); if (cdw) printf(" BIOS ROM at %8.8x, decoded bits are %8.8x.\n", pciaddr, cdw); else printf(" No BIOS extension (boot ROM).\n"); return;}static void show_ext_caps(unsigned int *cfg_space, unsigned char pci_bus, unsigned char pci_dev_fn){ unsigned char *pcfg = (void *)cfg_space; int cap_idx = cfg_space[13] & 0xff; printf(" Extended capabilities, first structure at offset 0x%x.\n", cap_idx); for (; cap_idx; cap_idx = pcfg[cap_idx + 1]) { printf(" Extended PCI capability type %d at 0x%2.2x, next %d.\n", pcfg[cap_idx], cap_idx, pcfg[cap_idx + 1]); if (pcfg[cap_idx] == 1) { printf(" Power management entry ver. %d: Capabilities %2.2x%2.2x" ", Ctrl %2.2x%2.2x, Event %2.2x%2.2x.\n", pcfg[cap_idx + 2] & 7, pcfg[cap_idx + 3], pcfg[cap_idx + 2], pcfg[cap_idx + 5], pcfg[cap_idx + 4], pcfg[cap_idx + 7], pcfg[cap_idx + 6]); printf(" Power state D%d.\n", pcfg[cap_idx + 4] & 3); } }}static int acpi_find(unsigned char pci_bus, unsigned char pci_dev_fn, void *config){ unsigned char *pcfg = (void *)config; if (pcfg[6] & 0x10) { int cap_idx = pcfg[0x34]; printf(" Extended capabilities, first structure at offset 0x%x.\n", cap_idx); for (; cap_idx; cap_idx = pcfg[cap_idx + 1]) { if (pcfg[cap_idx] == 1) return cap_idx; } } return 0;}static void acpi_wake(unsigned char pci_bus, unsigned char pci_dev_fn, void *pci_config_space){ unsigned char *config = pci_config_space; unsigned short *configw = pci_config_space; unsigned int *configdw = pci_config_space; int pwr_idx = acpi_find(pci_bus, pci_dev_fn, config); unsigned short pwr_command = configw[(pwr_idx + 4)>>1]; int i; if (debug) printf("Power index is %#x.\n", pwr_idx); printf(" Waking up an ACPI device. Currently powered %s, " "I/O %#x IRQ %d.\n" " Updating the power state of %4.4x->%4.4x.\n", pwr_command & 3 ? "down" : "up", configdw[0x10>>2], config[0x3c], pwr_command, pwr_command & ~3); pcibios_write_config_word(pci_bus, pci_dev_fn, pwr_idx + 4, pwr_command & ~3); /* Many devices must have their PCI register state restored when changing from D3 state. */ for (i = 0x10; i <= 0x20; i+=4) pcibios_write_config_dword(pci_bus, pci_dev_fn, i, configdw[i >> 2]); /* PCI_ROM_ADDRESS, interrupt line, cache line size, latency timer */ pcibios_write_config_dword(pci_bus, pci_dev_fn, 0x30, configdw[0x30 >> 2]); pcibios_write_config_byte(pci_bus, pci_dev_fn, 0x3c, config[0x3c]); pcibios_write_config_byte(pci_bus, pci_dev_fn, 0x0c, config[0x0c]); pcibios_write_config_byte(pci_bus, pci_dev_fn, 0x0d, config[0x0d]); /* Finally, restore the command register. */ pcibios_write_config_word(pci_bus, pci_dev_fn, 0x04, configw[4>>1]);}static void acpi_sleep(unsigned char bus, unsigned char devfn, void *pci_config_space){ unsigned short *configw = pci_config_space; int pwr_idx = acpi_find(bus, devfn, pci_config_space); unsigned short pwr_command = configw[(pwr_idx + 4)>>1]; pcibios_write_config_word(bus, devfn, pwr_idx + 4, pwr_command | 0x0103);}/* Put the 3Com Cyclone e.g. 3c905B series into Wake On LAN mode. */static void cyclone_WOL(int pci_bus, int pci_dev_fn, void *config){ int pwr_idx = acpi_find(pci_bus, pci_dev_fn, config); unsigned short pwr_command = ((unsigned short *)config)[(pwr_idx + 4)>>1]; long ioaddr = ((int *)config)[0x10]; acpi_wake(pci_bus, pci_dev_fn, config); outw(0x801f, ioaddr + 0x0e); /* Set RxFilter to accept frames. */ outw((1<<11) + 7, ioaddr + 0x0e); outw(7, ioaddr + 0x0c); printf(" Window 7 Power Management Event is %4.4x.\n", inw(ioaddr + 0x0c)); printf(" Changing the power state from %4.4x to 0103.\n", pwr_command); outw(0x2000, ioaddr + 0x0e); /* RxEnable. */ pcibios_write_config_word(pci_bus, pci_dev_fn, 0xe0, pwr_command | 0x8103);}#define PCI_CONFIG_ADDR 0x0cf8#define PCI_CONFIG_DATA 0x0cfcint pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned char *val){ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc), PCI_CONFIG_ADDR); *val = inb(PCI_CONFIG_DATA + (regnum & 3)); return 0;}int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned short *val){ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc), PCI_CONFIG_ADDR); *val = inw(PCI_CONFIG_DATA + (regnum & 2)); return 0;}int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned int *val){ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc), PCI_CONFIG_ADDR); *val = inl(PCI_CONFIG_DATA); return 0;}void pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned char val){ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc), PCI_CONFIG_ADDR); outb(val, PCI_CONFIG_DATA + (regnum & 3)); return;}void pcibios_write_config_word (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned short val){ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc), PCI_CONFIG_ADDR); outw(val, PCI_CONFIG_DATA + (regnum & 2)); return;}void pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, unsigned char regnum, unsigned int val){ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc), PCI_CONFIG_ADDR); outl(val, PCI_CONFIG_DATA); return;}/* Map the board shared memory into our address space -- this code is a good example of non-kernel access to devices on the PCI bus. */static int dump_mem_region(long addr){ unsigned short *shared_mem; int i; int memfd = open("/dev/kmem", O_RDWR); if (memfd < 0) { perror("/dev/kmem (shared memory)"); return 2; } else printf("Opened /dev/kmem for PCI memory.\n"); shared_mem = mmap(0, 0x8000, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, addr); printf("Shared memory at %#lx (%p).\n", (long)addr, shared_mem); for (i = 0; i < 100; i++) printf(" %4.4x", shared_mem[i]); close(memfd); printf(" ...\n"); return 0;}/* * Local variables: * compile-command: "cc -O -Wall -o pci-config pci-config.c" * tab-width: 4 * c-indent-level: 4 * c-basic-offset: 4 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -