root/lm-sensors/trunk/prog/dump/isadump.c @ 2661

Revision 2661, 6.2 KB (checked in by khali, 9 years ago)

Mass coding-style update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    isadump.c - isadump, a user-space program to dump ISA registers
3    Copyright (C) 2000  Frodo Looijaard <frodol@dds.nl>, and
4                        Mark D. Studebaker <mdsxyz123@yahoo.com>
5    Copyright (C) 2004  The lm_sensors group
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22/*
23        Typical usage:
24        isadump 0x295 0x296             Basic winbond dump using address/data registers
25        isadump 0x295 0x296 2           Winbond dump, bank 2
26        isadump 0x2e 0x2f 0x09          Super-I/O, logical device 9
27        isadump -f 0x5000               Flat address space dump like for Via 686a
28        isadump -f 0xecf0 0x10 1        PC87366, temperature channel 2
29*/
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <unistd.h>
34#include <string.h>
35
36
37/* To keep glibc2 happy */
38#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ >= 0
39#include <sys/io.h>
40#else
41#include <asm/io.h>
42#endif
43
44#ifdef __powerpc__
45unsigned long isa_io_base = 0; /* XXX for now */
46#endif /* __powerpc__ */
47
48char hexchar(int i)
49{
50        if ((i >= 0) && (i <= 9))
51                return '0' + i;
52        else if (i <= 15)
53                return 'a' - 10 + i;
54        else
55                return 'X';
56}
57
58void help(void)
59{
60        fprintf(stderr,
61                "Syntax for I2C-like access:\n"
62                "  isadump ADDRREG DATAREG [BANK [BANKREG]]\n"
63                "Syntax for flat address space:\n"
64                "  isadump -f ADDRESS [RANGE [BANK [BANKREG]]]\n");
65}
66
67int default_bankreg(int flat, int addrreg, int datareg)
68{
69        if (flat) {
70                return 0x09; /* Works for National Semiconductor
71                                Super-IO chips */
72        }
73
74        if ((addrreg == 0x2e && datareg == 0x2f)
75         || (addrreg == 0x4e && datareg == 0x4f)) {
76                return 0x07; /* Works for all Super-I/O chips */
77        }
78       
79        return 0x4e; /* Works for Winbond ISA chips, default */
80}
81
82int set_bank(int flat, int addrreg, int datareg, int bank, int bankreg)
83{
84        int oldbank;
85
86        if (flat) {
87                oldbank = inb(addrreg+bankreg);
88                outb(bank, addrreg+bankreg);
89        } else {
90                outb(bankreg, addrreg);
91                oldbank = inb(datareg);
92                outb(bank, datareg);
93        }
94
95        return oldbank;
96}
97
98int main(int argc, char *argv[])
99{
100        int addrreg;        /* address in flat mode */
101        int datareg = 0;    /* unused in flat mode */
102        int range = 256;    /* can be changed only in flat mode */
103        int bank = -1;      /* -1 means no bank operation */
104        int bankreg;
105        int oldbank = 0;
106        int i, j, res;
107        int flat = 0;
108        char *end;
109
110        if (argc < 3) {
111                help();
112                exit(1);
113        }
114
115        if (!strcmp(argv[1], "-f")) {
116                flat = 1;
117        }
118
119        addrreg = strtol(argv[1+flat], &end, 0);
120        if (*end) {
121                fprintf(stderr, "Error: Invalid address!\n");
122                help();
123                exit(1);
124        }
125        if (addrreg < 0 || addrreg > (flat?0xffff:0x3fff)) {
126                fprintf(stderr, "Error: Address out of range "
127                        "(0x0000-0x%04x)!\n", flat?0xffff:0x3fff);
128                help();
129                exit(1);
130        }
131
132        if (flat) {
133                if (argc > 3) {
134                        range = strtol(argv[3], &end, 0);
135                        if (*end || range <= 0 || range > 0x100
136                         || range & 0xf) {
137                                fprintf(stderr, "Error: Invalid range!\n"
138                                        "Hint: Must be a multiple of 16 no "
139                                        "greater than 256.\n");
140                                help();
141                                exit(1);
142                        }
143                } else {
144                        addrreg &= 0xff00; /* Force alignment */
145                }
146        } else {
147                datareg = strtol(argv[2], &end, 0);
148                if (*end) {
149                        fprintf(stderr, "Error: Invalid data register!\n");
150                        help();
151                        exit(1);
152                }
153                if (datareg < 0 || datareg > 0x3fff) {
154                        fprintf(stderr, "Error: Data register out of range "
155                                "(0x0000-0x3fff)!\n");
156                        help();
157                        exit(1);
158                }
159        }
160
161        bankreg = default_bankreg(flat, addrreg, datareg);
162
163        if (argc > 3+flat) {
164                bank = strtol(argv[3+flat], &end, 0);
165                if (*end) {
166                        fprintf(stderr, "Error: Invalid bank number!\n");
167                        help();
168                        exit(1);
169                }
170                if ((bank < 0) || (bank > 15)) {
171                        fprintf(stderr, "Error: bank out of range (0-15)!\n");
172                        help();
173                        exit(1);
174                }
175
176                if (argc > 4+flat) {
177                        bankreg = strtol(argv[4+flat], &end, 0);
178                        if (*end) {
179                                fprintf(stderr, "Error: Invalid bank "
180                                        "register!\n");
181                                help();
182                                exit(1);
183                        }
184                        if (bankreg < 0 || bankreg >= range) {
185                                fprintf(stderr, "Error: bank out of range "
186                                        "(0x00-0x%02x)!\n", range-1);
187                                help();
188                                exit(1);
189                        }
190                }
191        }
192
193        if (getuid()) {
194                fprintf(stderr, "Error: Can only be run as root (or make it "
195                        "suid root)\n");
196                exit(1);
197        }
198
199        fprintf(stderr, "WARNING! Running this program can cause system "
200                "crashes, data loss and worse!\n");
201        if (flat)
202                fprintf(stderr, "I will probe address range 0x%04x to "
203                        "0x%04x.\n", addrreg, addrreg + range - 1);
204        else
205                fprintf(stderr, "I will probe address register 0x%04x and "
206                        "data register 0x%04x.\n", addrreg, datareg);
207        if (bank>=0)   
208                fprintf(stderr, "Probing bank %d using bank register "
209                        "0x%02x.\n", bank, bankreg);
210        fprintf(stderr, "You have five seconds to reconsider and press "
211                "CTRL-C!\n\n");
212        sleep(5);
213
214#ifndef __powerpc__
215        if ((datareg < 0x400) && (addrreg < 0x400) && !flat) {
216                if (ioperm(datareg, 1, 1)) {
217                        fprintf(stderr, "Error: Could not ioperm() data "
218                                "register!\n");
219                        exit(1);
220                }
221                if (ioperm(addrreg, 1, 1)) {
222                        fprintf(stderr, "Error: Could not ioperm() address "
223                                "register!\n");
224                        exit(1);
225                }
226        } else {
227                if (iopl(3)) {
228                        fprintf(stderr, "Error: Could not do iopl(3)!\n");
229                        exit(1);
230                }
231        }
232#endif
233
234        if (bank >= 0)
235                oldbank = set_bank(flat, addrreg, datareg, bank, bankreg);
236
237        printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
238        for (i = 0; i < range; i += 16) {
239                printf("%c0: ", hexchar(i/16));
240                for (j = 0; j < 16; j++) {
241                        if (flat) {
242                                res = inb(addrreg + i + j);
243                        } else {       
244                                outb(i+j, addrreg);
245                                res = inb(datareg);
246                        }
247                        printf("%c%c ", hexchar(res/16), hexchar(res%16));
248                }
249                printf("\n");
250        }
251
252        /* Restore the original bank value */
253        if (bank >= 0)
254                set_bank(flat, addrreg, datareg, oldbank, bankreg);
255
256        exit(0);
257}
Note: See TracBrowser for help on using the browser.