coreboot-kgpe-d16/util/superiotool/superiotool.c

321 lines
7.0 KiB
C
Raw Normal View History

/*
* This file is part of the superiotool project.
*
* Copyright (C) 2006 Ronald Minnich <rminnich@gmail.com>
Add support for the ITE IT8708F. Here's a dump from my test system which has an IT8708F: No SuperI/O chip found at 0x002e probing 0x002e, failed (0x87), data returns 0x87 SuperI/O found at 0x2e: id=0x8708, chipver=0x0 ITE IT8708 idx 07 20 21 22 23 24 25 26 27 28 29 2a 2e 2f val 02 87 08 00 00 00 00 00 03 01 01 00 00 00 def NA 87 08 00 00 NA 3f 00 ff ff ff ff 00 00 switching to LDN 0x0 idx 30 60 61 70 74 f0 f1 val 01 03 f0 06 02 00 80 def 00 03 f0 06 02 00 00 switching to LDN 0x1 idx 30 60 61 70 f0 val 01 03 f8 04 00 def 00 03 f8 04 00 switching to LDN 0x2 idx 30 60 61 70 f0 f1 f2 f3 val 01 02 f8 03 00 50 01 7f def 00 02 f8 03 00 50 00 7f switching to LDN 0x3 idx 30 60 61 62 63 64 65 70 74 f0 val 01 03 78 07 78 00 80 07 03 0b def 00 03 78 07 78 00 80 07 03 03 switching to LDN 0x4 idx e0 e1 e2 e3 e4 e5 e6 e7 f0 f1 f2 f3 f4 f5 f6 val 80 61 00 00 00 00 00 00 80 00 30 00 80 00 de def NA NA 00 00 00 00 00 00 00 00 00 00 00 NA NA switching to LDN 0x5 idx 30 60 61 62 63 70 71 f0 val 01 00 60 00 64 01 02 0c def 01 00 60 00 64 01 02 00 switching to LDN 0x6 idx 30 70 71 f0 val 01 0c 02 00 def 00 0c 02 00 switching to LDN 0x7 idx 70 b0 b1 b2 b3 b4 b5 b8 b9 ba bb bc bd c0 c1 c2 c3 c4 c5 c8 c9 ca cb cc cd d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc val 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 01 01 00 00 00 03 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 7f 20 51 00 0e 00 00 00 00 00 00 00 def 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 NA NA NA NA NA NA 00 00 00 00 00 00 00 00 00 00 00 NA 00 switching to LDN 0x8 idx 30 60 61 val 00 02 01 def 00 02 01 switching to LDN 0x9 idx 30 60 61 70 f0 val 00 03 10 0b 06 def 00 03 10 0b 00 switching to LDN 0xa idx 30 60 61 70 f0 val 00 03 00 0a 40 def 00 03 00 0a 00 No SuperI/O chip found at 0x004e No SuperIO chip found at 0x004e No SuperIO chip found at 0x004e Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de> Acked-by: Uwe Hermann <uwe@hermann-uwe.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2757 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
2007-09-01 21:42:42 +02:00
* Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2007 Carl-Daniel Hailfinger
* Copyright (C) 2008 Robinson P. Tryon <bishop.robinson@gmail.com>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "superiotool.h"
#if defined(__FreeBSD__)
#include <fcntl.h>
#include <unistd.h>
#endif
/* Command line options. */
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 + ((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);
}
void enter_conf_mode_winbond_fintek_ite_8787(uint16_t port)
{
OUTB(0x87, port);
OUTB(0x87, port);
}
void exit_conf_mode_winbond_fintek_ite_8787(uint16_t port)
{
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), "<unknown>", 9);
}
const char *get_superio_name(const struct superio_registers reg_table[],
uint16_t id)
{
int i;
for (i = 0; /* Nothing */; i++) {
if (reg_table[i].superio_id == EOT)
break;
if ((uint16_t)reg_table[i].superio_id != id)
continue;
return reg_table[i].name;
}
return "<unknown>";
}
static void dump_regs(const struct superio_registers reg_table[],
int i, int j, uint16_t port, uint8_t ldn_sel)
{
int k;
const int16_t *idx;
if (reg_table[i].ldn[j].ldn != NOLDN) {
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, ldn_sel, reg_table[i].ldn[j].ldn);
} else {
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; idx[k] != EOT; k++) {
if (k && !(k % 8))
putchar(' ');
printf(" %02x", idx[k]);
}
printf("\nval");
for (k = 0; idx[k] != EOT; k++) {
if (k && !(k % 8))
putchar(' ');
printf(" %02x", regval(port, idx[k]));
}
printf("\ndef");
idx = reg_table[i].ldn[j].def;
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)
printf(" MM");
else
printf(" %02x", idx[k]);
}
printf("\n");
}
void dump_superio(const char *vendor,
const struct superio_registers reg_table[],
uint16_t port, uint16_t id, uint8_t ldn_sel)
{
int i, j, no_dump_available = 1;
if (!dump)
return;
for (i = 0; /* Nothing */; i++) {
if (reg_table[i].superio_id == EOT)
break;
if ((uint16_t)reg_table[i].superio_id != id)
continue;
for (j = 0; /* Nothing */; j++) {
if (reg_table[i].ldn[j].ldn == EOT)
break;
no_dump_available = 0;
dump_regs(reg_table, i, j, port, ldn_sel);
}
if (no_dump_available)
printf("No dump available for this Super I/O\n");
}
}
void dump_io(uint16_t iobase, uint16_t length)
{
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 probing_for(const char *vendor, const char *info, uint16_t port)
{
if (!verbose)
return;
/* 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 <http://coreboot.org/Superiotool#Supported_devices> "
"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
static const struct option long_options[] = {
{"dump", 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, "delVvh",
long_options, &option_index)) != EOF) {
switch (opt) {
case 'd':
dump = 1;
break;
case 'e':
extra_dump = 1;
break;
case 'l':
print_list_of_supported_chips();
exit(0);
break;
case 'V':
verbose = 1;
break;
case 'v':
print_version();
exit(0);
break;
case 'h':
printf(USAGE);
printf(USAGE_INFO);
exit(0);
break;
default:
/* Unknown option. */
exit(1);
break;
}
}
#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;
}