Decouple the ITE code from fintek.c, it doesn't belong there.
[coreboot.git] / util / superiotool / superiotool.c
1 /*
2  * This file is part of the LinuxBIOS project.
3  *
4  * Copyright (C) 2006 Ronald Minnich <rminnich@gmail.com>
5  * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
6  * Copyright (C) 2007 Carl-Daniel Hailfinger
7  *
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
23 #include "superiotool.h"
24
25 /* Command line options. */
26 int dump = 0, verbose = 0;
27
28 uint8_t regval(uint16_t port, uint8_t reg)
29 {
30         outb(reg, port);
31         return inb(port + 1);
32 }
33
34 void regwrite(uint16_t port, uint8_t reg, uint8_t val)
35 {
36         outb(reg, port);
37         outb(val, port + 1);
38 }
39
40 void enter_conf_mode_winbond_fintek_ite_8787(uint16_t port)
41 {
42         outb(0x87, port);
43         outb(0x87, port);
44 }
45
46 void exit_conf_mode_winbond_fintek_ite_8787(uint16_t port)
47 {
48         outb(0xaa, port);               /* Fintek, Winbond */
49         regwrite(port, 0x02, 0x02);     /* ITE */
50 }
51
52 int superio_unknown(const struct superio_registers reg_table[], uint16_t id)
53 {
54         return !strncmp(get_superio_name(reg_table, id), "<unknown>", 9);
55 }
56
57 const char *get_superio_name(const struct superio_registers reg_table[],
58                              uint16_t id)
59 {
60         int i;
61
62         for (i = 0; /* Nothing */; i++) {
63                 if (reg_table[i].superio_id == EOT)
64                         break;
65
66                 if ((uint16_t)reg_table[i].superio_id != id)
67                         continue;
68
69                 return reg_table[i].name;
70         }
71
72         return "<unknown>";
73 }
74
75 static void dump_regs(const struct superio_registers reg_table[],
76                       int i, int j, uint16_t port)
77 {
78         int k, *idx;
79
80         if (reg_table[i].ldn[j].ldn != NOLDN) {
81                 printf("LDN 0x%02x ", reg_table[i].ldn[j].ldn);
82                 if (reg_table[i].ldn[j].name != NULL)
83                         printf("(%s)", reg_table[i].ldn[j].name);
84                 regwrite(port, 0x07, reg_table[i].ldn[j].ldn);
85         } else {
86                 printf("Register dump:");
87         }
88
89         idx = reg_table[i].ldn[j].idx;
90
91         printf("\nidx ");
92         for (k = 0; /* Nothing */; k++) {
93                 if (idx[k] == EOT)
94                         break;
95                 printf("%02x ", idx[k]);
96         }
97
98         printf("\nval ");
99         for (k = 0; /* Nothing */; k++) {
100                 if (idx[k] == EOT)
101                         break;
102                 printf("%02x ", regval(port, idx[k]));
103         }
104
105         printf("\ndef ");
106         idx = reg_table[i].ldn[j].def;
107         for (k = 0; /* Nothing */; k++) {
108                 if (idx[k] == EOT)
109                         break;
110                 else if (idx[k] == NANA)
111                         printf("NA ");
112                 else if (idx[k] == RSVD)
113                         printf("RR ");
114                 else if (idx[k] == MISC)        /* TODO */
115                         printf("MM ");
116                 else
117                         printf("%02x ", idx[k]);
118         }
119         printf("\n");
120 }
121
122 void dump_superio(const char *vendor,
123                   const struct superio_registers reg_table[],
124                   uint16_t port, uint16_t id)
125 {
126         int i, j, no_dump_available = 1;
127
128         if (!dump)
129                 return;
130
131         for (i = 0; /* Nothing */; i++) {
132                 if (reg_table[i].superio_id == EOT)
133                         break;
134
135                 if ((uint16_t)reg_table[i].superio_id != id)
136                         continue;
137
138                 for (j = 0; /* Nothing */; j++) {
139                         if (reg_table[i].ldn[j].ldn == EOT)
140                                 break;
141                         no_dump_available = 0;
142                         dump_regs(reg_table, i, j, port);
143                 }
144
145                 if (no_dump_available)
146                         printf("No dump available for this Super I/O\n");
147         }
148 }
149
150 void no_superio_found(uint16_t port)
151 {
152         if (!verbose)
153                 return;
154
155         if (inb(port) == 0xff)
156                 printf("No Super I/O chip found at 0x%04x\n", port);
157         else
158                 printf("Probing 0x%04x, failed (0x%02x), data returns 0x%02x\n",
159                        port, inb(port), inb(port + 1));
160 }
161
162 int main(int argc, char *argv[])
163 {
164         int i, j, opt, option_index;
165
166         const static struct option long_options[] = {
167                 {"dump",        no_argument, NULL, 'd'},
168                 {"verbose",     no_argument, NULL, 'V'},
169                 {"version",     no_argument, NULL, 'v'},
170                 {"help",        no_argument, NULL, 'h'},
171                 {0, 0, 0, 0}
172         };
173
174         while ((opt = getopt_long(argc, argv, "dVvh",
175                                   long_options, &option_index)) != EOF) {
176                 switch (opt) {
177                 case 'd':
178                         dump = 1;
179                         break;
180                 case 'V':
181                         verbose = 1;
182                         break;
183                 case 'v':
184                         printf("superiotool %s\n", SUPERIOTOOL_VERSION);
185                         exit(0);
186                         break;
187                 case 'h':
188                         printf(USAGE);
189                         exit(0);
190                         break;
191                 default:
192                         /* Unknown option. */
193                         exit(1);
194                         break;
195                 }
196         }
197
198         if (iopl(3) < 0) {
199                 perror("iopl");
200                 printf("Superiotool must be run as root.\n");
201                 exit(1);
202         }
203
204         for (i = 0; i < ARRAY_SIZE(superio_ports_table); i++) {
205                 for (j = 0; superio_ports_table[i].ports[j] != EOT; j++)
206                         superio_ports_table[i].probe_idregs(
207                                 superio_ports_table[i].ports[j]);
208         }
209
210         return 0;
211 }