Hi there,
After I wrote a number of small utilities a while back to dump the several memory mapped and io mapped registers of the Intel northbridges and southbridges, the number of these utilities became a bit overwhelming, while each utility was very limited.
So I joined my utility collection and made one bigger tool out of it: inteltool
inteltool dumps all registers of a typical intel system that I ran into so far. This includes GPIOs, RCBA, Egress Ports BAR, PMBASE, MCHBAR, DMIBAR, PCIEXBAR as well as an extended number of system MSRs.
The tool also has a cleaner way of distinguishing between different Intel northbridges and southbridges now. Though only i945 and ICH7 are implemented and tested. It should be fairly easy to add other chips.
I suggest dropping my first attempt in utils/inteltools and take this much better utility instead in utils/inteltool.
Signed-off-by: Stefan Reinauer stepan@coresystems.de
Attached as single files, as a patch does not make much sense
Best wishes,
Stefan
# # Makefile for inteltool utility # # Copyright (C) 2008 by coresystems GmbH # written by Stefan Reinauer stepan@coresystems.de # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
PROGRAM = inteltool
CC = gcc INSTALL = /usr/bin/install PREFIX = /usr/local CFLAGS = -O2 -g -Wall -W LDFLAGS = -lpci -lz
OBJS = inteltool.o
all: pciutils dep $(PROGRAM)
$(PROGRAM): $(OBJS) $(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
clean: rm -f *.o *~
distclean: clean rm -f $(PROGRAM) .dependencies dep: @$(CC) -MM *.c > .dependencies
pciutils: @echo; echo -n "Checking for pciutils and zlib... " @$(shell ( echo "#include <pci/pci.h>"; \ echo "struct pci_access *pacc;"; \ echo "int main(int argc, char **argv)"; \ echo "{ pacc = pci_alloc(); return 0; }"; ) > .test.c ) @$(CC) $(CFLAGS) .test.c -o .test $(LDFLAGS) &>/dev/null && \ echo "found." || ( echo "not found."; echo; \ echo "Please install pciutils-devel and zlib-devel."; \ echo "See README for more information."; echo; \ rm -f .test.c .test; exit 1) @rm -f .test.c .test
install: $(PROGRAM) $(INSTALL) $(PROGRAM) $(PREFIX)/sbin mkdir -p $(PREFIX)/share/man/man8 $(INSTALL) $(PROGRAM).8 $(PREFIX)/share/man/man8
.PHONY: all clean distclean dep pciutils
-include .dependencies
/* * inteltool - dump all registers on an Intel CPU + chipset based system. * * Copyright (C) 2008 by coresystems GmbH * written by Stefan Reinauer stepan@coresystems.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <errno.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdint.h> #include <getopt.h> #include <sys/mman.h> #include <sys/io.h> #include <pci/pci.h>
#define INTELTOOL_VERSION "1.0"
#define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
typedef struct { uint32_t hi, lo; } msr_t;
int fd_mem; int fd_msr;
typedef struct { uint16_t addr; int size; char *name; } io_register_t;
int print_gpios(struct pci_dev *sb) { int i; uint16_t gpiobase;
io_register_t ich7_gpio_registers[] = { { 0x00, 4, "GPIO_USE_SEL" }, { 0x04, 4, "GP_IO_SEL" }, { 0x08, 4, "RESERVED" }, { 0x0c, 4, "GP_LVL" }, { 0x10, 4, "RESERVED" }, { 0x14, 4, "RESERVED" }, { 0x18, 4, "GPO_BLINK" }, { 0x1c, 4, "RESERVED" }, { 0x20, 4, "RESERVED" }, { 0x24, 4, "RESERVED" }, { 0x28, 4, "RESERVED" }, { 0x2c, 4, "GPI_INV" }, { 0x30, 4, "GPIO_USE_SEL2" }, { 0x34, 4, "GP_IO_SEL2" }, { 0x38, 4, "GP_LVL2" }, { 0x3C, 4, "RESERVED" } };
printf("\n============= GPIOS =============\n\n");
switch (sb->device_id) { case 0x27b8: // ICH7 gpiobase = pci_read_word(sb, 0x48) & 0xfffc; break; case 0x1234: // Dummy for non-existent functionality printf("Error: This southbridge does not have GPIOBASE.\n"); return 1; default: printf("Error: Dumping GPIOs on this southbridge is not (yet) supported.\n"); return 1; }
printf("GPIOBASE = 0x%04x (IO)\n\n", gpiobase);
for (i=0; i<ARRAY_SIZE(ich7_gpio_registers); i++) { switch (ich7_gpio_registers[i].size) { case 4: printf("gpiobase+0x%04x: 0x%08x (%s)\n", ich7_gpio_registers[i].addr, inl(gpiobase+ich7_gpio_registers[i].addr), ich7_gpio_registers[i].name); break; case 2: printf("gpiobase+0x%04x: 0x%04x (%s)\n", ich7_gpio_registers[i].addr, inw(gpiobase+ich7_gpio_registers[i].addr), ich7_gpio_registers[i].name); break; case 1: printf("gpiobase+0x%04x: 0x%02x (%s)\n", ich7_gpio_registers[i].addr, inb(gpiobase+ich7_gpio_registers[i].addr), ich7_gpio_registers[i].name); break; } }
return 0; }
int print_rcba(struct pci_dev *sb) { int i, size=0x4000; volatile uint8_t *rcba; uint32_t rcba_phys;
printf("\n============= RCBA ==============\n\n");
switch (sb->device_id) { case 0x27b8: // ICH7 rcba_phys = pci_read_long(sb, 0xf0) & 0xfffffffe; break; case 0x1234: // Dummy for non-existent functionality printf("Error: This southbridge does not have RCBA.\n"); return 1; default: printf("Error: Dumping RCBA on this southbridge is not (yet) supported.\n"); return 1; }
rcba = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd_mem, (off_t) rcba_phys); if (rcba == MAP_FAILED) { perror("Error mapping RCBA"); exit(1); }
printf("RCBA = 0x%08x (MEM)\n\n", rcba_phys);
for (i=0; i<size; i+=4) { if(*(uint32_t *)(rcba+i)) printf("0x%04x: 0x%08x\n", i, *(uint32_t *)(rcba+i)); }
munmap((void *) rcba, size); return 0; }
int print_pmbase(struct pci_dev *sb) { int i, size=0x80; uint16_t pmbase;
printf("\n============= PMBASE ============\n\n");
switch (sb->device_id) { case 0x27b8: // ICH7 pmbase = pci_read_word(sb, 0x40) & 0xfffc; break; case 0x1234: // Dummy for non-existent functionality printf("Error: This southbridge does not have PMBASE.\n"); return 1; default: printf("Error: Dumping PMBASE on this southbridge is not (yet) supported.\n"); return 1; }
printf("PMBASE = 0x%04x (IO)\n\n", pmbase);
for (i=0; i<size; i+=4) { printf("pmbase+0x%04x: 0x%08x\n", i, inl(pmbase+i)); }
return 0; }
/* * (G)MCH MMIO Config Space */
int print_mchbar(struct pci_dev *nb) { int i, size=(16*1024); volatile uint8_t *mchbar; uint32_t mchbar_phys;
printf("\n============= MCHBAR ============\n\n");
switch (nb->device_id) { case 0x27a0: // i945 mchbar_phys = pci_read_long(nb, 0x44) & 0xfffffffe; break; case 0x1234: // Dummy for non-existent functionality printf("Error: This northbrigde does not have MCHBAR.\n"); return 1; default: printf("Error: Dumping MCHBAR on this northbridge is not (yet) supported.\n"); return 1; }
mchbar = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd_mem, (off_t) mchbar_phys ); if (mchbar == MAP_FAILED) { perror("Error mapping MCHBAR"); exit(1); }
printf("MCHBAR = 0x%08x (MEM)\n\n", mchbar_phys);
for (i=0; i<size; i+=4) { if(*(uint32_t *)(mchbar+i)) printf("0x%04x: 0x%08x\n", i, *(uint32_t *)(mchbar+i)); }
munmap((void *) mchbar, size); return 0; }
/* * Egress Port Root Complex MMIO configuration space */ int print_epbar(struct pci_dev *nb) { int i, size=4096; volatile uint8_t *epbar; uint32_t epbar_phys;
printf("\n============= EPBAR =============\n\n");
switch (nb->device_id) { case 0x27a0: // i945 epbar_phys = pci_read_long(nb, 0x40) & 0xfffffffe; break; case 0x1234: // Dummy for non-existent functionality printf("Error: This northbrigde does not have EPBAR.\n"); return 1; default: printf("Error: Dumping EPBAR on this northbridge is not (yet) supported.\n"); return 1; }
epbar = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd_mem, (off_t) epbar_phys ); if (epbar == MAP_FAILED) { perror("Error mapping EPBAR"); exit(1); }
printf("EPBAR = 0x%08x (MEM)\n\n", epbar_phys); for (i=0; i<size; i+=4) { if(*(uint32_t *)(epbar+i)) printf("0x%04x: 0x%08x\n", i, *(uint32_t *)(epbar+i)); }
munmap((void *) epbar, size); return 0; }
/* * MCH-ICH Serial Interconnect Ingress Root Complex MMIO configuration space */ int print_dmibar(struct pci_dev *nb) { int i, size=4096; volatile uint8_t *dmibar; uint32_t dmibar_phys;
printf("\n============= DMIBAR ============\n\n");
switch (nb->device_id) { case 0x27a0: // i945 dmibar_phys = pci_read_long(nb, 0x4c) & 0xfffffffe; break; case 0x1234: // Dummy for non-existent functionality printf("Error: This northbrigde does not have DMIBAR.\n"); return 1; default: printf("Error: Dumping DMIBAR on this northbridge is not (yet) supported.\n"); return 1; }
dmibar = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd_mem, (off_t) dmibar_phys ); if (dmibar == MAP_FAILED) { perror("Error mapping DMIBAR"); exit(1); }
printf("DMIBAR = 0x%08x (MEM)\n\n", dmibar_phys); for (i=0; i<size; i+=4) { if(*(uint32_t *)(dmibar+i)) printf("0x%04x: 0x%08x\n", i, *(uint32_t *)(dmibar+i)); }
munmap((void *) dmibar, size); return 0; }
/* * PCIe MMIO configuration space */ int print_pciexbar(struct pci_dev *nb) { uint32_t pciexbar_reg; uint32_t pciexbar_phys; volatile uint8_t *pciexbar; int max_busses, devbase, i; int bus, dev, fn;
printf("========= PCIEXBAR ========\n\n");
switch (nb->device_id) { case 0x27a0: // i945 pciexbar_reg = pci_read_long(nb, 0x48); break; case 0x1234: // Dummy for non-existent functionality printf("Error: This northbrigde does not have PCIEXBAR.\n"); return 1; default: printf("Error: Dumping PCIEXBAR on this northbridge is not (yet) supported.\n"); return 1; }
if( !(pciexbar_reg & (1 << 0))) { printf("PCIEXBAR register is disabled.\n"); return 0; }
switch ((pciexbar_reg >> 1) & 3) { case 0: // 256MB pciexbar_phys = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)); max_busses = 256; break; case 1: // 128M pciexbar_phys = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)); max_busses = 128; break; case 2: // 64M pciexbar_phys = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)); max_busses = 64; break; default: // RSVD printf("Undefined Address base. Bailing out\n"); return 1; }
printf("PCIEXBAR: 0x%08x\n", pciexbar_phys);
pciexbar = mmap(0, (max_busses * 1024 * 1024), PROT_WRITE | PROT_READ, MAP_SHARED, fd_mem, (off_t) pciexbar_phys ); if (pciexbar == MAP_FAILED) { perror("Error mapping PCIEXBAR"); exit(1); } for (bus = 0; bus < max_busses; bus++) { for (dev = 0; dev < 32; dev++) { for (fn = 0; fn < 8; fn++) { devbase = (bus * 1024 * 1024) + (dev * 32 * 1024) + (fn * 4 * 1024);
if (*(uint16_t *)(pciexbar + devbase) == 0xffff) continue; /* This is a heuristics. Anyone got a better check? */ if( (*(uint32_t *)(pciexbar + devbase + 256) == 0xffffffff) && (*(uint32_t *)(pciexbar + devbase + 512) == 0xffffffff) ) { #if DEBUG printf("Skipped non-PCIe device %02x:%02x.%01x\n", bus, dev, fn); #endif continue; }
printf("\nPCIe %02x:%02x.%01x extended config space:", bus, dev, fn); for (i=0; i<4096; i++) { if((i % 0x10) == 0) printf("\n%04x:", i); printf(" %02x", *(pciexbar+devbase+i)); } printf("\n"); } } }
munmap((void *) pciexbar, (max_busses * 1024 * 1024));
return 0; }
int msr_readerror = 0;
msr_t rdmsr(int addr) { unsigned char buf[8]; msr_t msr = { 0xffffffff, 0xffffffff };
if (lseek(fd_msr, (off_t) addr, SEEK_SET) == -1) { perror("Could not lseek() to MSR"); close(fd_msr); exit(1); }
if (read(fd_msr, buf, 8) == 8) { msr.lo = *(uint32_t *)buf; msr.hi = *(uint32_t *)(buf+4);
return msr; }
if (errno == 5) { printf(" (*)"); // Not all bits of the MSR could be read msr_readerror = 1; } else { // A severe error. perror("Could not read() MSR"); close(fd_msr); exit(1); }
return msr; }
int print_intel_core_msrs(void) { unsigned int i, core; msr_t msr;
#define IA32_PLATFORM_ID 0x0017 #define EBL_CR_POWERON 0x002a #define FSB_CLK_STS 0x00cd #define IA32_TIME_STAMP_COUNTER 0x0010 #define IA32_APIC_BASE 0x001b
typedef struct { int number; char *name; } msr_entry_t;
msr_entry_t global_msrs[] = { { 0x0017, "IA32_PLATFORM_ID" }, { 0x002a, "EBL_CR_POWERON" }, { 0x00cd, "FSB_CLOCK_STS" }, { 0x00ce, "FSB_CLOCK_VCC" }, { 0x00e2, "CLOCK_CST_CONFIG_CONTROL" }, { 0x00e3, "PMG_IO_BASE_ADDR" }, { 0x00e4, "PMG_IO_CAPTURE_ADDR" }, { 0x00ee, "EXT_CONFIG" }, { 0x011e, "BBL_CR_CTL3" }, { 0x0194, "CLOCK_FLEX_MAX" }, { 0x0198, "IA32_PERF_STATUS" }, { 0x01a0, "IA32_MISC_ENABLES" }, { 0x01aa, "PIC_SENS_CFG" }, { 0x0400, "IA32_MC0_CTL" }, { 0x0401, "IA32_MC0_STATUS" }, { 0x0402, "IA32_MC0_ADDR" }, //{ 0x0403, "IA32_MC0_MISC" }, // Seems to be RO { 0x040c, "IA32_MC4_CTL" }, { 0x040d, "IA32_MC4_STATUS" }, { 0x040e, "IA32_MC4_ADDR" }, //{ 0x040f, "IA32_MC4_MISC" } // Seems to be RO };
msr_entry_t per_core_msrs[] = { { 0x0010, "IA32_TIME_STAMP_COUNTER" }, { 0x001b, "IA32_APIC_BASE" }, { 0x003a, "IA32_FEATURE_CONTROL" }, { 0x003f, "IA32_TEMPERATURE_OFFSET" }, //{ 0x0079, "IA32_BIOS_UPDT_TRIG" }, // Seems to be RO { 0x008b, "IA32_BIOS_SIGN_ID" }, { 0x00e7, "IA32_MPERF" }, { 0x00e8, "IA32_APERF" }, { 0x00fe, "IA32_MTRRCAP" }, { 0x015f, "DTS_CAL_CTRL" }, { 0x0179, "IA32_MCG_CAP" }, { 0x017a, "IA32_MCG_STATUS" }, { 0x0199, "IA32_PERF_CONTROL" }, { 0x019a, "IA32_CLOCK_MODULATION" }, { 0x019b, "IA32_THERM_INTERRUPT" }, { 0x019c, "IA32_THERM_STATUS" }, { 0x019d, "GV_THERM" }, { 0x01d9, "IA32_DEBUGCTL" }, { 0x0200, "IA32_MTRR_PHYSBASE0" }, { 0x0201, "IA32_MTRR_PHYSMASK0" }, { 0x0202, "IA32_MTRR_PHYSBASE1" }, { 0x0203, "IA32_MTRR_PHYSMASK1" }, { 0x0204, "IA32_MTRR_PHYSBASE2" }, { 0x0205, "IA32_MTRR_PHYSMASK2" }, { 0x0206, "IA32_MTRR_PHYSBASE3" }, { 0x0207, "IA32_MTRR_PHYSMASK3" }, { 0x0208, "IA32_MTRR_PHYSBASE4" }, { 0x0209, "IA32_MTRR_PHYSMASK4" }, { 0x020a, "IA32_MTRR_PHYSBASE5" }, { 0x020b, "IA32_MTRR_PHYSMASK5" }, { 0x020c, "IA32_MTRR_PHYSBASE6" }, { 0x020d, "IA32_MTRR_PHYSMASK6" }, { 0x020e, "IA32_MTRR_PHYSBASE7" }, { 0x020f, "IA32_MTRR_PHYSMASK7" }, { 0x0250, "IA32_MTRR_FIX64K_00000" }, { 0x0258, "IA32_MTRR_FIX16K_80000" }, { 0x0259, "IA32_MTRR_FIX16K_A0000" }, { 0x0268, "IA32_MTRR_FIX4K_C0000" }, { 0x0269, "IA32_MTRR_FIX4K_C8000" }, { 0x026a, "IA32_MTRR_FIX4K_D0000" }, { 0x026b, "IA32_MTRR_FIX4K_D8000" }, { 0x026c, "IA32_MTRR_FIX4K_E0000" }, { 0x026d, "IA32_MTRR_FIX4K_E8000" }, { 0x026e, "IA32_MTRR_FIX4K_F0000" }, { 0x026f, "IA32_MTRR_FIX4K_F8000" }, { 0x02ff, "IA32_MTRR_DEF_TYPE" }, //{ 0x00c000080, "IA32_CR_EFER" }, // Seems to be RO };
fd_msr = open("/dev/cpu/0/msr", O_RDWR); if (fd_msr<0) { perror("Error while opening /dev/cpu/0/msr"); printf("Did you run 'modprobe msr'?\n"); return -1; }
printf("\n===================== SHARED MSRs (All Cores) =====================\n");
for (i = 0; i < ARRAY_SIZE(global_msrs); i++) { msr = rdmsr(global_msrs[i].number); printf(" MSR 0x%08X = 0x%08X:0x%08X (%s)\n", global_msrs[i].number, msr.hi, msr.lo, global_msrs[i].name); }
close(fd_msr); for (core=0; core < 8; core++) { char msrfilename[64]; memset(msrfilename, 0, 64); sprintf(msrfilename, "/dev/cpu/%d/msr", core);
fd_msr = open(msrfilename, O_RDWR); if (fd_msr<0) { /* If the file is not there, we're probably through. * No error, since we successfully opened /dev/cpu/0/msr before */ break; }
printf("\n====================== UNIQUE MSRs (core %d) ======================\n", core);
for (i = 0; i < ARRAY_SIZE(per_core_msrs); i++) { msr = rdmsr(per_core_msrs[i].number); printf(" MSR 0x%08X = 0x%08X:0x%08X (%s)\n", per_core_msrs[i].number, msr.hi, msr.lo, per_core_msrs[i].name); }
close(fd_msr); }
if (msr_readerror) printf("\n(*) Some MSRs could not be read. The marked values are unreliable.\n");
return 0; }
void print_version(void) { printf("inteltool v%s -- ", INTELTOOL_VERSION); printf("Copyright (C) 2008 coresystems GmbH\n\n"); printf( "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, version 2 of the License.\n\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see http://www.gnu.org/licenses/.\n\n"); }
void print_usage(const char *name) { printf("usage: %s [-vh?grpmedPM]\n", name); printf("\n" " -v | --version: print the version\n" " -h | --help: print this help\n\n" " -g | --gpio: dump soutbridge GPIO registers\n" " -r | --rcba: dump soutbridge RCBA registers\n" " -p | --pmbase: dump soutbridge Power Management registers\n\n" " -m | --mchbar: dump northbridge Memory Controller registers\n" " -e | --epbar: dump northbridge EPBAR registers\n" " -d | --dmibar: dump northbridge DMIBAR registers\n" " -P | --pciexpress: dump northbridge PCIEXBAR registers\n\n" " -M | --msrs: dump CPU MSRs\n" "\n"); exit(1); }
int main(int argc, char *argv[]) { struct pci_access *pacc; struct pci_dev *sb, *nb; int opt; int option_index = 0;
char *sbname, *nbname;
int dump_gpios=0, dump_mchbar=0, dump_rcba=0; int dump_pmbase=0, dump_epbar=0, dump_dmibar=0; int dump_pciexbar=0, dump_coremsrs=0;
static struct option long_options[] = { {"version", 0, 0, 'v'}, {"help", 0, 0, 'h'}, {"gpios", 0, 0, 'g'}, {"mchbar", 0, 0, 'm'}, {"rcba", 0, 0, 'r'}, {"pmbase", 0, 0, 'p'}, {"epbar", 0, 0, 'e'}, {"dmibar", 0, 0, 'd'}, {"pciexpress", 0, 0, 'P'}, {"msrs", 0, 0, 'M'}, {"all", 0, 0, 'a'}, {0, 0, 0, 0} };
while ((opt = getopt_long(argc, argv, "vh?gmrpedPca", long_options, &option_index)) != EOF) { switch (opt) { case 'v': print_version(); exit(0); break; case 'g': dump_gpios = 1; break; case 'm': dump_mchbar = 1; break; case 'r': dump_rcba = 1; break; case 'p': dump_pmbase = 1; break; case 'e': dump_epbar = 1; break; case 'd': dump_dmibar = 1; break; case 'P': dump_pciexbar = 1; break; case 'M': dump_coremsrs = 1; break; case 'a': dump_gpios = 1; dump_mchbar = 1; dump_rcba = 1; dump_pmbase = 1; dump_epbar = 1; dump_dmibar = 1; dump_pciexbar = 1; dump_coremsrs = 1; break; case 'h': case '?': default: print_usage(argv[0]); exit(0); break; } }
if (iopl(3)) { printf("You need to be root.\n"); exit(1); }
if ((fd_mem = open("/dev/mem", O_RDWR)) < 0) { perror("Can not open /dev/mem"); exit(1); }
pacc = pci_alloc(); pci_init(pacc); pci_scan_bus(pacc);
/* Find the required devices */
sb = pci_get_dev(pacc, 0, 0, 0x1f, 0); if (!sb) { printf("No southbridge found.\n"); exit(1); }
pci_fill_info(sb, PCI_FILL_IDENT|PCI_FILL_BASES|PCI_FILL_SIZES|PCI_FILL_CLASS);
if (sb->vendor_id != 0x8086) { printf("Not an Intel(R) southbridge.\n"); exit(1); }
nb = pci_get_dev(pacc, 0, 0, 0x00, 0); if (!nb) { printf("No northbridge found.\n"); exit(1); }
pci_fill_info(nb, PCI_FILL_IDENT|PCI_FILL_BASES|PCI_FILL_SIZES|PCI_FILL_CLASS);
if (nb->vendor_id != 0x8086) { printf("Not an Intel(R) northbridge.\n"); exit(1); }
/* TODO check cpuid, too */
/* Determine names */ switch(nb->device_id) { case 0x27a0: nbname="i945"; break; default: nbname="unknown"; }
switch(sb->device_id) { case 0x27b8: sbname="ICH7"; break; default: sbname="unknown"; }
printf("Intel Northbridge: %04x:%04x (%s)\n", nb->vendor_id, nb->device_id, nbname);
printf("Intel Southbridge: %04x:%04x (%s)\n", sb->vendor_id, sb->device_id, sbname);
/* Now do the deed */
if (dump_gpios) { print_gpios(sb); printf("\n\n"); }
if (dump_rcba) { print_rcba(sb); printf("\n\n"); }
if (dump_pmbase) { print_pmbase(sb); printf("\n\n"); }
if (dump_mchbar) { print_mchbar(nb); printf("\n\n"); }
if (dump_epbar) { print_epbar(nb); printf("\n\n"); }
if (dump_dmibar) { print_dmibar(nb); printf("\n\n"); }
if (dump_pciexbar) { print_pciexbar(nb); printf("\n\n"); }
if (dump_coremsrs) { print_intel_core_msrs(); printf("\n\n"); }
/* Clean up */
pci_free_dev(nb); pci_free_dev(sb); pci_cleanup(pacc);
return 0; }
.TH INTELTOOL 8 "May 12, 2008" .SH NAME inteltool - a tool for dumping Intel(R) CPU / chipset configuration parameters .SH SYNOPSIS .B inteltool \fR[\fB-vh?grpmedPM\fR] .SH DESCRIPTION .B inteltool is a handy little tool for dumping the configuration space of Intel(R) CPUs, northbridges and southbridges.
This tool has been developed for the coreboot project (see .B http://www.coreboot.org/ for details on coreboot). .SH OPTIONS .TP .B "-h, --help" Show a help text and exit. .TP .B "-v, --version" Show version information and exit. .TP .B "-a, --all" Dump all known I/O Controller Hub (ICH) southbridge, Intel(R) northbridge and Intel(R) Core CPU MSRs. .TP .B "-g, --gpio" Dump I/O Controller Hub (ICH) southbridge GPIO registers .TP .B "-r, --rcba" Dump I/O Controller Hub (ICH) southbridge RCBA registers .TP .B "-p, --pmbase" Dump I/O Controller Hub (ICH) southbridge pmbase registers .TP .B "-m, --mchbar" Dump Intel(R) northbridge MCHBAR registers .TP .B "-e, --epbar" Dump Intel(R) northbridge EPBAR registers .TP .B "-d, --dmibar" Dump Intel(R) northbridge DMIBAR registers .TP .B "-P, --pciexbar" Dump Intel(R) northbridge PCIEXBAR registers .TP .B "-M, --msrs" Dump Intel(R) CPU MSRs .SH BUGS Please report any bugs at .BR http://tracker.coreboot.org/trac/coreboot/newticket "," or on the coreboot mailing list .RB "(" http://coreboot.org/Mailinglist ")." .SH LICENCE .B inteltool is covered by the GNU General Public License (GPL), version 2 or later. .SH COPYRIGHT (C) 2008 coresystems GmbH .SH AUTHORS Stefan Reinauer stepan@coresystems.de .PP This manual page was written by Stefan Reinauer stepan@coresystems.de. It is licensed under the terms of the GNU GPL (version 2).
Intel(R) is a registered trademark of Intel Corporation. Other product and/or company names mentioned herein may be trademarks or registered trademarks of their respective owners.
I like it. I am afraid to ack because others do better reviews. but if it takes too long to get an ack let me know :-)
I might just try this on my laptop.
ron
On Tue, May 13, 2008 at 07:06:01PM +0200, Stefan Reinauer wrote:
So I joined my utility collection and made one bigger tool out of it: inteltool
Great idea.
I suggest dropping my first attempt in utils/inteltools and take this much better utility instead in utils/inteltool.
Signed-off-by: Stefan Reinauer stepan@coresystems.de
I like that suggestion.
io_register_t ich7_gpio_registers[] = { { 0x00, 4, "GPIO_USE_SEL" }, { 0x04, 4, "GP_IO_SEL" }, { 0x08, 4, "RESERVED" }, { 0x0c, 4, "GP_LVL" }, { 0x10, 4, "RESERVED" }, { 0x14, 4, "RESERVED" }, { 0x18, 4, "GPO_BLINK" }, { 0x1c, 4, "RESERVED" }, { 0x20, 4, "RESERVED" }, { 0x24, 4, "RESERVED" }, { 0x28, 4, "RESERVED" }, { 0x2c, 4, "GPI_INV" }, { 0x30, 4, "GPIO_USE_SEL2" }, { 0x34, 4, "GP_IO_SEL2" }, { 0x38, 4, "GP_LVL2" }, { 0x3C, 4, "RESERVED" } };
..
switch (sb->device_id) { case 0x27b8: // ICH7 gpiobase = pci_read_word(sb, 0x48) & 0xfffc; break; case 0x1234: // Dummy for non-existent functionality printf("Error: This southbridge does not have GPIOBASE.\n"); return 1;
Maybe device ID #defines would be nice?
case 0x27b8: // ICH7 case 0x27b8: // ICH7 case 0x27a0: // i945 case 0x27a0: // i945 case 0x27a0: // i945 case 0x27a0: // i945 if (sb->vendor_id != 0x8086) { if (nb->vendor_id != 0x8086) {
These IDs are after all in a few places.
/* Determine names */ switch(nb->device_id) { case 0x27a0: nbname="i945"; break; default: nbname="unknown"; }
switch(sb->device_id) { case 0x27b8: sbname="ICH7"; break; default: sbname="unknown"; }
I'd prefer to have a table for this, maybe the same one that has register definitions?
Nice tool!
On Tue, May 13, 2008 at 10:08:16AM -0700, ron minnich wrote:
I like it. I am afraid to ack because others do better reviews. but if it takes too long to get an ack let me know :-)
You could ack with reservation. :)
No ack from me yet, but next time, Gadget!
//Peter
* Peter Stuge peter@stuge.se [080513 21:35]:
On Tue, May 13, 2008 at 07:06:01PM +0200, Stefan Reinauer wrote:
So I joined my utility collection and made one bigger tool out of it: inteltool
Great idea.
case 0x27b8: // ICH7 gpiobase = pci_read_word(sb, 0x48) & 0xfffc; break; case 0x1234: // Dummy for non-existent functionality printf("Error: This southbridge does not have GPIOBASE.\n"); return 1;
Maybe device ID #defines would be nice?
done.
/* Determine names */ switch(nb->device_id) { case 0x27a0: nbname="i945"; break; default: nbname="unknown"; }
switch(sb->device_id) { case 0x27b8: sbname="ICH7"; break; default: sbname="unknown"; }
I'd prefer to have a table for this, maybe the same one that has register definitions?
done.
It's not in the register definitions though. If you have an idea how to do this nicely, I suggest we integrate this in other patches. Also, we might want to see how other intel chipsets come in over time to see what is beneficial and what is not.
No ack from me yet, but next time, Gadget!
Ok, 'nother try:
Signed-off-by: Stefan Reinauer stepan@coresystems.de
This time only inteltool.c is attached, the rest staid unchanged.
On Tue, May 13, 2008 at 11:47:19PM +0200, Stefan Reinauer wrote:
case 0x27a0: nbname="i945"; break;
I'd prefer to have a table for this, maybe the same one that has register definitions?
done.
It's not in the register definitions though. If you have an idea how to do this nicely, I suggest we integrate this in other patches. Also, we might want to see how other intel chipsets come in over time to see what is beneficial and what is not.
*nods*
No ack from me yet, but next time, Gadget!
Ok, 'nother try:
Signed-off-by: Stefan Reinauer stepan@coresystems.de
Acked-by: Peter Stuge peter@stuge.se
On Wed, May 14, 2008 at 12:05:24AM +0200, Peter Stuge wrote:
On Tue, May 13, 2008 at 11:47:19PM +0200, Stefan Reinauer wrote:
case 0x27a0: nbname="i945"; break;
I'd prefer to have a table for this, maybe the same one that has register definitions?
done.
It's not in the register definitions though. If you have an idea how to do this nicely, I suggest we integrate this in other patches. Also, we might want to see how other intel chipsets come in over time to see what is beneficial and what is not.
*nods*
No ack from me yet, but next time, Gadget!
Ok, 'nother try:
Signed-off-by: Stefan Reinauer stepan@coresystems.de
Acked-by: Peter Stuge peter@stuge.se
For the records -- this was r3304.
Uwe.
Dump support for ICH5's GPIO and Power Management registers (inteltool -g -p), detection for ICH5 and i865G (printing the real name instead of "unknown"). See attached patch.
~/coreboot/coreboot-svn/coreboot-util-svn $ svn diff inteltool inteltool-ich5 > coreboot-v2-i865-ich5_gpio_pmbase_dump.svndiff
Dump support for ICH5's GPIO and Power Management registers (inteltool -g -p), detection for ICH5 and i865G (printing the real name instead of "unknown"). See attached patch.
~/coreboot/coreboot-svn/coreboot-util-svn $ svn diff inteltool inteltool-ich5 > coreboot-v2-i865-ich5_gpio_pmbase_dump.svndiff
---
Repost: Signed-off-by: idwer_
On Sat, 17 May 2008 00:46:02 +0200, "Idwer Vollering" vidwer@gmail.com wrote:
Dump support for ICH5's GPIO and Power Management registers (inteltool -g -p), detection for ICH5 and i865G (printing the real name instead of "unknown"). See attached patch.
~/coreboot/coreboot-svn/coreboot-util-svn $ svn diff inteltool inteltool-ich5 > coreboot-v2-i865-ich5_gpio_pmbase_dump.svndiff
Repost: Signed-off-by: idwer_
Good Job. I don't think your Signed-off-by: is the correct format though. Can you post the output results?