root/lm-sensors/trunk/prog/dump/isaset.c

Revision 5962, 6.5 KB (checked in by khali, 10 months ago)

isaset: Add support for word (16-bit) and long (32-bit) writes

Sometimes the hardware expects 16-bit or 32-bit writes rather than byte
writes. Add support to isaset so that the user can ask for such writes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    isaset.c - isaset, a user-space program to write ISA registers
3    Copyright (C) 2000  Frodo Looijaard <frodol@dds.nl>, and
4                        Mark D. Studebaker <mdsxyz123@yahoo.com>
5    Copyright (C) 2004-2011  Jean Delvare <khali@linux-fr.org>
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., 51 Franklin Street, Fifth Floor, Boston,
20    MA 02110-1301 USA.
21*/
22
23/*
24        Typical usage:
25        isaset 0x295 0x296 0x10 0x12    Write 0x12 to address 0x10 using address/data registers
26        isaset -f 0x5010 0x12           Write 0x12 to location 0x5010
27*/
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include "util.h"
34
35
36/* To keep glibc2 happy */
37#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ >= 0
38#include <sys/io.h>
39#else
40#include <asm/io.h>
41#endif
42
43#ifdef __powerpc__
44unsigned long isa_io_base = 0; /* XXX for now */
45#endif /* __powerpc__ */
46
47static void help(void)
48{
49        fprintf(stderr,
50                "Syntax for I2C-like access:\n"
51                "  isaset [OPTIONS] ADDRREG DATAREG ADDRESS VALUE [MASK]\n"
52                "Syntax for flat address space:\n"
53                "  isaset -f [OPTIONS] ADDRESS VALUE [MASK]\n"
54                "Options:\n"
55                "  -f   Enable flat address space mode\n"
56                "  -y   Assume affirmative answer to all questions\n"
57                "  -W   Write a word (16-bit) value\n"
58                "  -L   Write a long (32-bit) value\n");
59}
60
61int main(int argc, char *argv[])
62{
63        int addrreg, datareg = 0, addr = 0;
64        unsigned long value, vmask = 0, maxval = 0xff, res;
65        int flags = 0;
66        int flat = 0, yes = 0, width = 1;
67        char *end;
68
69        /* handle (optional) flags first */
70        while (1+flags < argc && argv[1+flags][0] == '-') {
71                switch (argv[1+flags][1]) {
72                case 'f': flat = 1; break;
73                case 'y': yes = 1; break;
74                case 'W': width = 2; maxval = 0xffff; break;
75                case 'L': width = 4; maxval = 0xffffffff; break;
76                default:
77                        fprintf(stderr, "Warning: Unsupported flag "
78                                "\"-%c\"!\n", argv[1+flags][1]);
79                        help();
80                        exit(1);
81                }
82                flags++;
83        }
84
85        /* verify that the argument count is correct */
86        if ((!flat && (argc < 1+flags+4 || argc > 1+flags+5))
87         || (flat && (argc < 1+flags+2 || argc > 1+flags+3))) {
88                help();
89                exit(1);
90        }
91
92        addrreg = strtol(argv[1+flags], &end, 0);
93        if (*end) {
94                fprintf(stderr, "Error: Invalid address!\n");
95                help();
96                exit(1);
97        }
98        if (addrreg < 0 || addrreg > (flat?0xffff:0x3fff)) {
99                fprintf(stderr,
100                        "Error: Address out of range (0x0000-0x%04x)!\n",
101                        flat?0xffff:0x3fff);
102                help();
103                exit(1);
104        }
105
106        if (!flat) {
107                datareg = strtol(argv[1+flags+1], &end, 0);
108                if (*end) {
109                        fprintf(stderr, "Error: Invalid data register!\n");
110                        help();
111                        exit(1);
112                }
113                if (datareg < 0 || datareg > 0x3fff) {
114                        fprintf(stderr, "Error: Data register out of range "
115                                "(0x0000-0x3fff)!\n");
116                        help();
117                        exit(1);
118                }
119
120                addr = strtol(argv[1+flags+2], &end, 0);
121                if (*end) {
122                        fprintf(stderr, "Error: Invalid address!\n");
123                        help();
124                        exit(1);
125                }
126                if (addr < 0 || addr > 0xff) {
127                        fprintf(stderr, "Error: Address out of range "
128                                "(0x00-0xff)!\n");
129                        help();
130                        exit(1);
131                }
132        }
133
134        /* rest is the same for both modes so we cheat on flags */
135        if (!flat)
136                flags += 2;
137
138        value = strtoul(argv[flags+2], &end, 0);
139        if (*end) {
140                fprintf(stderr, "Error: Invalid value!\n");
141                help();
142                exit(1);
143        }
144        if (value > maxval) {
145                fprintf(stderr, "Error: Value out of range "
146                        "(0x%0*u-%0*lu)!\n", width * 2, 0, width * 2, maxval);
147                help();
148                exit(1);
149        }
150
151        if (flags+3 < argc) {
152                vmask = strtoul(argv[flags+3], &end, 0);
153                if (*end) {
154                        fprintf(stderr, "Error: Invalid mask!\n");
155                        help();
156                        exit(1);
157                }
158                if (vmask > maxval) {
159                        fprintf(stderr, "Error: Mask out of range "
160                                "(0x%0*u-%0*lu)!\n", width * 2, 0,
161                                width * 2, maxval);
162                        help();
163                        exit(1);
164                }
165        }
166
167        if (geteuid()) {
168                fprintf(stderr, "Error: Can only be run as root "
169                        "(or make it suid root)\n");
170                exit(1);
171        }
172
173        if (!yes) {
174                fprintf(stderr, "WARNING! Running this program can cause "
175                        "system crashes, data loss and worse!\n");
176
177                if (flat)
178                        fprintf(stderr,
179                                "I will write value 0x%0*lx%s to address "
180                                "0x%x.\n", width * 2, value,
181                                vmask ? " (masked)" : "", addrreg);
182                else
183                        fprintf(stderr,
184                                "I will write value 0x%0*lx%s to address "
185                                "0x%02x of chip with address register 0x%x\n"
186                                "and data register 0x%x.\n", width * 2,
187                                value, vmask ? " (masked)" : "", addr,
188                                addrreg, datareg);
189
190                fprintf(stderr, "Continue? [Y/n] ");
191                fflush(stderr);
192                if (!user_ack(1)) {
193                        fprintf(stderr, "Aborting on user request.\n");
194                        exit(0);
195                }
196        }
197
198#ifndef __powerpc__
199        if (!flat && datareg < 0x400 && addrreg < 0x400) {
200                if (ioperm(datareg, 1, 1)) {
201                        fprintf(stderr, "Error: Could not ioperm() data "
202                                "register!\n");
203                        exit(1);
204                }
205                if (ioperm(addrreg, 1, 1)) {
206                        fprintf(stderr, "Error: Could not ioperm() address "
207                                "register!\n");
208                        exit(1);
209                }
210        } else {
211                if (iopl(3)) {
212                        fprintf(stderr, "Error: Could not do iopl(3)!\n");
213                        exit(1);
214                }
215        }
216#endif
217
218        if (vmask) {
219                unsigned long oldvalue;
220
221                if (flat) {
222                        oldvalue = inx(addrreg, width);
223                } else {       
224                        outb(addr, addrreg);
225                        oldvalue = inx(datareg, width);
226                }
227
228                value = (value & vmask) | (oldvalue & ~vmask);
229
230                if (!yes) {
231                        fprintf(stderr, "Old value 0x%0*lx, write mask "
232                                "0x%0*lx: Will write 0x%0*lx to %s "
233                                "0x%02x\n", width * 2, oldvalue,
234                                width * 2, vmask, width * 2, value,
235                                flat ? "address" : "register",
236                                flat ? addrreg : addr);
237
238                        fprintf(stderr, "Continue? [Y/n] ");
239                        fflush(stderr);
240                        if (!user_ack(1)) {
241                                fprintf(stderr, "Aborting on user request.\n");
242                                exit(0);
243                        }
244                }
245        }
246
247        /* do the real thing */
248        if (flat) {
249                /* write */
250                outx(value, addrreg, width);
251                /* readback */
252                res = inx(addrreg, width);
253        } else {       
254                /* write */
255                outb(addr, addrreg);
256                outx(value, datareg, width);
257                /* readback */
258                res = inx(datareg, width);
259        }
260
261        if (res != value) {
262                fprintf(stderr, "Data mismatch, wrote 0x%0*lx, "
263                        "read 0x%0*lx back.\n", width * 2, value,
264                        width * 2, res);
265        }
266
267        exit(0);
268}
Note: See TracBrowser for help on using the browser.