blob: de512486e608ba202faeaea7c2b7a68e30dea860 [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 Hermann3acf31e2007-09-19 01:55:35 +000040const char *get_superio_name(const struct superio_registers reg_table[],
41 uint16_t id)
42{
43 int i;
44
45 for (i = 0; /* Nothing */; i++) {
46 if (reg_table[i].superio_id == EOT)
47 break;
48
49 if ((uint16_t)reg_table[i].superio_id != id)
50 continue;
51
52 return reg_table[i].name;
53 }
54
55 return "<unknown>";
56}
57
Uwe Hermann25a6c0f2007-09-19 00:48:42 +000058void dump_superio(const char *vendor, const struct superio_registers reg_table[],
Uwe Hermannde24a0e2007-09-19 00:03:14 +000059 uint16_t port, uint16_t id)
Uwe Hermann519419b2007-09-16 20:59:01 +000060{
Uwe Hermann25a6c0f2007-09-19 00:48:42 +000061 int i, j, k, nodump;
Uwe Hermannde24a0e2007-09-19 00:03:14 +000062 int *idx;
Uwe Hermann519419b2007-09-16 20:59:01 +000063
Uwe Hermann519419b2007-09-16 20:59:01 +000064 for (i = 0; /* Nothing */; i++) {
65 if (reg_table[i].superio_id == EOT)
66 break;
67
Uwe Hermannde24a0e2007-09-19 00:03:14 +000068 if ((uint16_t)reg_table[i].superio_id != id)
Uwe Hermann519419b2007-09-16 20:59:01 +000069 continue;
70
Uwe Hermann25a6c0f2007-09-19 00:48:42 +000071 nodump = 1;
Uwe Hermann519419b2007-09-16 20:59:01 +000072
Uwe Hermannde24a0e2007-09-19 00:03:14 +000073 for (j = 0; /* Nothing */; j++) {
Uwe Hermann519419b2007-09-16 20:59:01 +000074 if (reg_table[i].ldn[j].ldn == EOT)
75 break;
76
Uwe Hermann25a6c0f2007-09-19 00:48:42 +000077 nodump = 0;
78
Uwe Hermann519419b2007-09-16 20:59:01 +000079 if (reg_table[i].ldn[j].ldn != NOLDN) {
Uwe Hermannde24a0e2007-09-19 00:03:14 +000080 printf("Switching to LDN 0x%02x\n",
Uwe Hermann519419b2007-09-16 20:59:01 +000081 reg_table[i].ldn[j].ldn);
Uwe Hermannde24a0e2007-09-19 00:03:14 +000082 regwrite(port, 0x07, reg_table[i].ldn[j].ldn);
Uwe Hermann519419b2007-09-16 20:59:01 +000083 }
84
85 idx = reg_table[i].ldn[j].idx;
86
87 printf("idx ");
Uwe Hermannde24a0e2007-09-19 00:03:14 +000088 for (k = 0; /* Nothing */; k++) {
Uwe Hermann519419b2007-09-16 20:59:01 +000089 if (idx[k] == EOT)
90 break;
91 printf("%02x ", idx[k]);
92 }
93
94 printf("\nval ");
Uwe Hermannde24a0e2007-09-19 00:03:14 +000095 for (k = 0; /* Nothing */; k++) {
Uwe Hermann519419b2007-09-16 20:59:01 +000096 if (idx[k] == EOT)
97 break;
98 printf("%02x ", regval(port, idx[k]));
99 }
100
101 printf("\ndef ");
102 idx = reg_table[i].ldn[j].def;
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;
Uwe Hermann6ff6af72007-09-18 22:24:34 +0000106 else if (idx[k] == NANA)
Uwe Hermann519419b2007-09-16 20:59:01 +0000107 printf("NA ");
Uwe Hermann6ff6af72007-09-18 22:24:34 +0000108 else if (idx[k] == RSVD)
109 printf("RR ");
Uwe Hermann519419b2007-09-16 20:59:01 +0000110 else
111 printf("%02x ", idx[k]);
112 }
113 printf("\n");
114 }
Uwe Hermann25a6c0f2007-09-19 00:48:42 +0000115
116 if (nodump)
117 printf("No dump for %s %s\n", vendor, reg_table[i].name);
Uwe Hermann519419b2007-09-16 20:59:01 +0000118 }
119}
120
Uwe Hermann3acf31e2007-09-19 01:55:35 +0000121void no_superio_found(uint16_t port) {
122 if (!verbose)
123 return;
124
125 if (inb(port) == 0xff)
126 printf("No Super I/O chip found at 0x%04x\n", port);
127 else
128 printf("Probing 0x%04x, failed (0x%02x), data returns 0x%02x\n", port, inb(port), inb(port + 1));
129}
130
Uwe Hermann2046ff92007-09-01 21:02:44 +0000131int main(int argc, char *argv[])
Stefan Reinauer6a5bc462007-01-17 10:57:42 +0000132{
Uwe Hermann3acf31e2007-09-19 01:55:35 +0000133 int i, j, opt, option_index;
134
135 const static struct option long_options[] = {
136 {"dump", no_argument, NULL, 'd'},
137 {"verbose", no_argument, NULL, 'V'},
138 {"version", no_argument, NULL, 'v'},
139 {"help", no_argument, NULL, 'h'},
140 {0, 0, 0, 0}
141 };
142
143 while ((opt = getopt_long(argc, argv, "dVvh",
144 long_options, &option_index)) != EOF) {
145 switch (opt) {
146 case 'd':
147 dump = 1;
148 break;
149 case 'V':
150 verbose = 1;
151 break;
152 case 'v':
153 printf("superiotool %s\n", SUPERIOTOOL_VERSION);
154 exit(0);
155 break;
156 case 'h':
157 printf("Usage: superiotool [-d] [-V] [-v] [-h]\n");
158 exit(0);
159 break;
160 default:
161 /* Unknown option. */
162 exit(1);
163 break;
164 }
165 }
Uwe Hermannd754d2c2007-09-18 23:30:24 +0000166
Ronald G. Minnich394e7c42006-02-22 22:12:21 +0000167 if (iopl(3) < 0) {
168 perror("iopl");
169 exit(1);
170 }
171
Uwe Hermannd754d2c2007-09-18 23:30:24 +0000172 for (i = 0; i < ARRAY_SIZE(superio_ports_table); i++) {
173 for (j = 0; superio_ports_table[i].ports[j] != EOT; j++)
174 superio_ports_table[i].probe_idregs(
175 superio_ports_table[i].ports[j]);
176 }
Stefan Reinauer6a5bc462007-01-17 10:57:42 +0000177
178 return 0;
Ronald G. Minnich394e7c42006-02-22 22:12:21 +0000179}