X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=util%2Fsuperiotool%2Fsuperiotool.c;h=293aaa617d018ef156abe976668616fab4d50862;hb=28f6a43755246641186f2c436b158d2dab4243a5;hp=9bde779a81aee8becd240b9bb8f6b85d4f0891f0;hpb=afe83092020d37d1b8629b3b92f9179e925e72fe;p=coreboot.git diff --git a/util/superiotool/superiotool.c b/util/superiotool/superiotool.c index 9bde779a8..293aaa617 100644 --- a/util/superiotool/superiotool.c +++ b/util/superiotool/superiotool.c @@ -4,6 +4,7 @@ * Copyright (C) 2006 Ronald Minnich * Copyright (C) 2007 Uwe Hermann * Copyright (C) 2007 Carl-Daniel Hailfinger + * Copyright (C) 2008 Robinson P. Tryon * * 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 @@ -22,38 +23,58 @@ #include "superiotool.h" +#if defined(__FreeBSD__) +#include +#include +#endif + /* Command line options. */ -int dump = 0, dump_readable = 0, verbose = 0; +int dump = 0, verbose = 0, extra_dump = 0; + +/* Global flag which indicates whether a chip was detected at all. */ +int chip_found = 0; uint8_t regval(uint16_t port, uint8_t reg) { - outb(reg, port); - return inb(port + 1); + OUTB(reg, port); + return INB(port + ((port == 0x3bd) ? 2 : 1)); /* 0x3bd is special. */ } void regwrite(uint16_t port, uint8_t reg, uint8_t val) { - outb(reg, port); - outb(val, port + 1); + OUTB(reg, port); + OUTB(val, port + 1); } void enter_conf_mode_winbond_fintek_ite_8787(uint16_t port) { - outb(0x87, port); - outb(0x87, port); + OUTB(0x87, port); + OUTB(0x87, port); } void exit_conf_mode_winbond_fintek_ite_8787(uint16_t port) { - outb(0xaa, port); /* Fintek, Winbond */ + OUTB(0xaa, port); /* Fintek, Winbond */ regwrite(port, 0x02, 0x02); /* ITE */ } +void enter_conf_mode_fintek_7777(uint16_t port) +{ + OUTB(0x77, port); + OUTB(0x77, port); +} + +void exit_conf_mode_fintek_7777(uint16_t port) +{ + OUTB(0xaa, port); /* Fintek */ +} + int superio_unknown(const struct superio_registers reg_table[], uint16_t id) { return !strncmp(get_superio_name(reg_table, id), "", 9); } + const char *get_superio_name(const struct superio_registers reg_table[], uint16_t id) { @@ -73,56 +94,59 @@ const char *get_superio_name(const struct superio_registers reg_table[], } static void dump_regs(const struct superio_registers reg_table[], - int i, int j, uint16_t port) + int i, int j, uint16_t port, uint8_t ldn_sel) { int k; - const int *idx; + const int16_t *idx; if (reg_table[i].ldn[j].ldn != NOLDN) { - printf("LDN 0x%02x ", reg_table[i].ldn[j].ldn); + printf("LDN 0x%02x", reg_table[i].ldn[j].ldn); if (reg_table[i].ldn[j].name != NULL) - printf("(%s)", reg_table[i].ldn[j].name); - regwrite(port, 0x07, reg_table[i].ldn[j].ldn); + printf(" (%s)", reg_table[i].ldn[j].name); + regwrite(port, ldn_sel, reg_table[i].ldn[j].ldn); } else { - printf("Register dump:"); + if (reg_table[i].ldn[j].name == NULL) + printf("Register dump:"); + else + printf("(%s)", reg_table[i].ldn[j].name); } idx = reg_table[i].ldn[j].idx; - printf("\nidx "); - for (k = 0; /* Nothing */; k++) { - if (idx[k] == EOT) - break; - printf("%02x ", idx[k]); + printf("\nidx"); + for (k = 0; idx[k] != EOT; k++) { + if (k && !(k % 8)) + putchar(' '); + printf(" %02x", idx[k]); } - printf("\nval "); - for (k = 0; /* Nothing */; k++) { - if (idx[k] == EOT) - break; - printf("%02x ", regval(port, idx[k])); + printf("\nval"); + for (k = 0; idx[k] != EOT; k++) { + if (k && !(k % 8)) + putchar(' '); + printf(" %02x", regval(port, idx[k])); } - printf("\ndef "); + printf("\ndef"); idx = reg_table[i].ldn[j].def; - for (k = 0; /* Nothing */; k++) { - if (idx[k] == EOT) - break; - else if (idx[k] == NANA) - printf("NA "); + for (k = 0; idx[k] != EOT; k++) { + if (k && !(k % 8)) + putchar(' '); + if (idx[k] == NANA) + printf(" NA"); else if (idx[k] == RSVD) - printf("RR "); - else if (idx[k] == MISC) /* TODO */ - printf("MM "); + printf(" RR"); + else if (idx[k] == MISC) + printf(" MM"); else - printf("%02x ", idx[k]); + printf(" %02x", idx[k]); } printf("\n"); } void dump_superio(const char *vendor, const struct superio_registers reg_table[], - uint16_t port, uint16_t id) + uint16_t port, uint16_t id, uint8_t ldn_sel) { int i, j, no_dump_available = 1; @@ -140,7 +164,7 @@ void dump_superio(const char *vendor, if (reg_table[i].ldn[j].ldn == EOT) break; no_dump_available = 0; - dump_regs(reg_table, i, j, port); + dump_regs(reg_table, i, j, port, ldn_sel); } if (no_dump_available) @@ -148,58 +172,109 @@ void dump_superio(const char *vendor, } } -void dump_superio_readable(uint16_t port) +void dump_io(uint16_t iobase, uint16_t length) { - /* TODO */ - if (dump_readable) - printf("No human-readable dump available for this Super I/O\n"); + uint16_t i; + + printf("Dumping %d I/O mapped registers at base 0x%04x:\n", + length, iobase); + for (i = 0; i < length; i++) + printf("%02x ", i); + printf("\n"); + for (i = 0; i < length; i++) + printf("%02x ", INB(iobase + i)); + printf("\n"); } -void no_superio_found(const char *vendor, const char *info, uint16_t port) +void probing_for(const char *vendor, const char *info, uint16_t port) { if (!verbose) return; - if (inb(port) == 0xff) - /* Yes, there's no space between '%s' and 'at'! */ - printf("Probing for %s Super I/O %sat 0x%x... failed\n", - vendor, info, port); - else - printf("Probing 0x%x, failed (0x%02x), data returns 0x%02x\n", - port, inb(port), inb(port + 1)); + /* Yes, there's no space between '%s' and 'at'! */ + printf("Probing for %s Super I/O %sat 0x%x...\n", vendor, info, port); +} + +/** Print a list of all supported chips from the given vendor. */ +void print_vendor_chips(const char *vendor, + const struct superio_registers reg_table[]) +{ + int i; + + for (i = 0; reg_table[i].superio_id != EOT; i++) { + printf("%s %s", vendor, reg_table[i].name); + + /* Unless the ldn is empty, assume this chip has a dump. */ + if (reg_table[i].ldn[0].ldn != EOT) + printf(" (dump available)"); + + printf("\n"); + } + + /* If we printed any chips for this vendor, put in a blank line. */ + if (i != 0) + printf("\n"); +} + +/** Print a list of all chips supported by superiotool. */ +void print_list_of_supported_chips(void) +{ + int i; + + printf("Supported Super I/O chips:\n\n"); + + for (i = 0; i < ARRAY_SIZE(vendor_print_functions); i++) + vendor_print_functions[i].print_list(); + + printf("See " + "for more information.\n"); +} + +static void print_version(void) +{ + printf("superiotool r%s\n", SUPERIOTOOL_VERSION); } int main(int argc, char *argv[]) { int i, j, opt, option_index; +#if defined(__FreeBSD__) + int io_fd; +#endif - const static struct option long_options[] = { + static const struct option long_options[] = { {"dump", no_argument, NULL, 'd'}, - {"dump-readable", no_argument, NULL, 'D'}, + {"extra-dump", no_argument, NULL, 'e'}, + {"list-supported", no_argument, NULL, 'l'}, {"verbose", no_argument, NULL, 'V'}, {"version", no_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "dDVvh", + while ((opt = getopt_long(argc, argv, "delVvh", long_options, &option_index)) != EOF) { switch (opt) { case 'd': dump = 1; break; - case 'D': - dump_readable = 1; + case 'e': + extra_dump = 1; + break; + case 'l': + print_list_of_supported_chips(); + exit(0); break; case 'V': verbose = 1; break; case 'v': - printf("superiotool %s\n", SUPERIOTOOL_VERSION); + print_version(); exit(0); break; case 'h': printf(USAGE); + printf(USAGE_INFO); exit(0); break; default: @@ -209,17 +284,37 @@ int main(int argc, char *argv[]) } } +#if defined(__FreeBSD__) + if ((io_fd = open("/dev/io", O_RDWR)) < 0) { + perror("/dev/io"); +#else if (iopl(3) < 0) { perror("iopl"); +#endif printf("Superiotool must be run as root.\n"); exit(1); } + print_version(); + +#ifdef PCI_SUPPORT + /* Do some basic libpci init. */ + pacc = pci_alloc(); + pci_init(pacc); + pci_scan_bus(pacc); +#endif + for (i = 0; i < ARRAY_SIZE(superio_ports_table); i++) { for (j = 0; superio_ports_table[i].ports[j] != EOT; j++) superio_ports_table[i].probe_idregs( superio_ports_table[i].ports[j]); } + if (!chip_found) + printf("No Super I/O found\n"); + +#if defined(__FreeBSD__) + close(io_fd); +#endif return 0; }