blob: 2ff56fb5c08420347127767ffde4103103ff03f0 [file] [log] [blame]
Stefan Reinauer6a5bc462007-01-17 10:57:42 +00001/*
2 * This file is part of the LinuxBIOS project.
3 *
4 * Copyright (C) 2006 Ronald Minnich <rminnich@gmail.com>
Uwe Hermannbd263922007-09-01 19:42:42 +00005 * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
Uwe Hermann519419b2007-09-16 20:59:01 +00006 * Copyright (C) 2007 Carl-Daniel Hailfinger
Stefan Reinauer6a5bc462007-01-17 10:57:42 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
Uwe Hermann0120e1a2007-09-16 18:11:03 +000023#include "superiotool.h"
Ronald G. Minnich394e7c42006-02-22 22:12:21 +000024
Uwe Hermann3acf31e2007-09-19 01:55:35 +000025/* Command line options. */
26int dump = 0, verbose = 0;
27
Uwe Hermannde24a0e2007-09-19 00:03:14 +000028uint8_t regval(uint16_t port, uint8_t reg)
Uwe Hermann2046ff92007-09-01 21:02:44 +000029{
Ronald G. Minnich394e7c42006-02-22 22:12:21 +000030 outb(reg, port);
Carl-Daniel Hailfingerb1786c22007-08-28 10:43:57 +000031 return inb(port + 1);
Ronald G. Minnich394e7c42006-02-22 22:12:21 +000032}
33
Uwe Hermannde24a0e2007-09-19 00:03:14 +000034void regwrite(uint16_t port, uint8_t reg, uint8_t val)
Uwe Hermann2046ff92007-09-01 21:02:44 +000035{
Carl-Daniel Hailfinger7a7890a2007-08-27 07:28:28 +000036 outb(reg, port);
Carl-Daniel Hailfingerb1786c22007-08-28 10:43:57 +000037 outb(val, port + 1);
Carl-Daniel Hailfinger7a7890a2007-08-27 07:28:28 +000038}
39
Uwe Hermann7e7e9ac2007-09-19 15:52:23 +000040int superio_unknown(const struct superio_registers reg_table[], uint16_t id)
41{
42 return !strncmp(get_superio_name(reg_table, id), "<unknown>", 9);
43}
44
Uwe Hermann3acf31e2007-09-19 01:55:35 +000045const char *get_superio_name(const struct superio_registers reg_table[],
46 uint16_t id)
47{
48 int i;
49
50 for (i = 0; /* Nothing */; i++) {
51 if (reg_table[i].superio_id == EOT)
52 break;
53
54 if ((uint16_t)reg_table[i].superio_id != id)
55 continue;
56
57 return reg_table[i].name;
58 }
59
60 return "<unknown>";
61}
62
Uwe Hermann25a6c0f2007-09-19 00:48:42 +000063void dump_superio(const char *vendor, const struct superio_registers reg_table[],
Uwe Hermannde24a0e2007-09-19 00:03:14 +000064 uint16_t port, uint16_t id)
Uwe Hermann519419b2007-09-16 20:59:01 +000065{
Uwe Hermann25a6c0f2007-09-19 00:48:42 +000066 int i, j, k, nodump;
Uwe Hermannde24a0e2007-09-19 00:03:14 +000067 int *idx;
Uwe Hermann519419b2007-09-16 20:59:01 +000068
Uwe Hermann7e7e9ac2007-09-19 15:52:23 +000069 if (!dump)
70 return;
71
Uwe Hermann519419b2007-09-16 20:59:01 +000072 for (i = 0; /* Nothing */; i++) {
73 if (reg_table[i].superio_id == EOT)
74 break;
75
Uwe Hermannde24a0e2007-09-19 00:03:14 +000076 if ((uint16_t)reg_table[i].superio_id != id)
Uwe Hermann519419b2007-09-16 20:59:01 +000077 continue;
78
Uwe Hermann25a6c0f2007-09-19 00:48:42 +000079 nodump = 1;
Uwe Hermann519419b2007-09-16 20:59:01 +000080
Uwe Hermannde24a0e2007-09-19 00:03:14 +000081 for (j = 0; /* Nothing */; j++) {
Uwe Hermann519419b2007-09-16 20:59:01 +000082 if (reg_table[i].ldn[j].ldn == EOT)
83 break;
84
Uwe Hermann25a6c0f2007-09-19 00:48:42 +000085 nodump = 0;
86
Uwe Hermann519419b2007-09-16 20:59:01 +000087 if (reg_table[i].ldn[j].ldn != NOLDN) {
Uwe Hermannde24a0e2007-09-19 00:03:14 +000088 printf("Switching to LDN 0x%02x\n",
Uwe Hermann519419b2007-09-16 20:59:01 +000089 reg_table[i].ldn[j].ldn);
Uwe Hermannde24a0e2007-09-19 00:03:14 +000090 regwrite(port, 0x07, reg_table[i].ldn[j].ldn);
Uwe Hermann519419b2007-09-16 20:59:01 +000091 }
92
93 idx = reg_table[i].ldn[j].idx;
94
95 printf("idx ");
Uwe Hermannde24a0e2007-09-19 00:03:14 +000096 for (k = 0; /* Nothing */; k++) {
Uwe Hermann519419b2007-09-16 20:59:01 +000097 if (idx[k] == EOT)
98 break;
99 printf("%02x ", idx[k]);
100 }
101
102 printf("\nval ");
Uwe Hermannde24a0e2007-09-19 00:03:14 +0000103 for (k = 0; /* Nothing */; k++) {
Uwe Hermann519419b2007-09-16 20:59:01 +0000104 if (idx[k] == EOT)
105 break;
106 printf("%02x ", regval(port, idx[k]));
107 }
108
109 printf("\ndef ");
110 idx = reg_table[i].ldn[j].def;
Uwe Hermannde24a0e2007-09-19 00:03:14 +0000111 for (k = 0; /* Nothing */; k++) {
Uwe Hermann519419b2007-09-16 20:59:01 +0000112 if (idx[k] == EOT)
113 break;
Uwe Hermann6ff6af72007-09-18 22:24:34 +0000114 else if (idx[k] == NANA)
Uwe Hermann519419b2007-09-16 20:59:01 +0000115 printf("NA ");
Uwe Hermann6ff6af72007-09-18 22:24:34 +0000116 else if (idx[k] == RSVD)
117 printf("RR ");
Uwe Hermann7e7e9ac2007-09-19 15:52:23 +0000118 else if (idx[k] == MISC) /* TODO */
119 printf("MM ");
Uwe Hermann519419b2007-09-16 20:59:01 +0000120 else
121 printf("%02x ", idx[k]);
122 }
123 printf("\n");
124 }
Uwe Hermann25a6c0f2007-09-19 00:48:42 +0000125
126 if (nodump)
127 printf("No dump for %s %s\n", vendor, reg_table[i].name);
Uwe Hermann519419b2007-09-16 20:59:01 +0000128 }
129}
130
Uwe Hermann3acf31e2007-09-19 01:55:35 +0000131void no_superio_found(uint16_t port) {
132 if (!verbose)
133 return;
134
135 if (inb(port) == 0xff)
136 printf("No Super I/O chip found at 0x%04x\n", port);
137 else
138 printf("Probing 0x%04x, failed (0x%02x), data returns 0x%02x\n", port, inb(port), inb(port + 1));
139}
140
Uwe Hermann2046ff92007-09-01 21:02:44 +0000141int main(int argc, char *argv[])
Stefan Reinauer6a5bc462007-01-17 10:57:42 +0000142{
Uwe Hermann3acf31e2007-09-19 01:55:35 +0000143 int i, j, opt, option_index;
144
145 const static struct option long_options[] = {
146 {"dump", no_argument, NULL, 'd'},
147 {"verbose", no_argument, NULL, 'V'},
148 {"version", no_argument, NULL, 'v'},
149 {"help", no_argument, NULL, 'h'},
150 {0, 0, 0, 0}
151 };
152
153 while ((opt = getopt_long(argc, argv, "dVvh",
154 long_options, &option_index)) != EOF) {
155 switch (opt) {
156 case 'd':
157 dump = 1;
158 break;
159 case 'V':
160 verbose = 1;
161 break;
162 case 'v':
163 printf("superiotool %s\n", SUPERIOTOOL_VERSION);
164 exit(0);
165 break;
166 case 'h':
167 printf("Usage: superiotool [-d] [-V] [-v] [-h]\n");
168 exit(0);
169 break;
170 default:
171 /* Unknown option. */
172 exit(1);
173 break;
174 }
175 }
Uwe Hermannd754d2c2007-09-18 23:30:24 +0000176
Ronald G. Minnich394e7c42006-02-22 22:12:21 +0000177 if (iopl(3) < 0) {
178 perror("iopl");
Uwe Hermann7e7e9ac2007-09-19 15:52:23 +0000179 printf("Superiotool must be run as root.\n");
Ronald G. Minnich394e7c42006-02-22 22:12:21 +0000180 exit(1);
181 }
182
Uwe Hermannd754d2c2007-09-18 23:30:24 +0000183 for (i = 0; i < ARRAY_SIZE(superio_ports_table); i++) {
184 for (j = 0; superio_ports_table[i].ports[j] != EOT; j++)
185 superio_ports_table[i].probe_idregs(
186 superio_ports_table[i].ports[j]);
187 }
Stefan Reinauer6a5bc462007-01-17 10:57:42 +0000188
189 return 0;
Ronald G. Minnich394e7c42006-02-22 22:12:21 +0000190}