~mmach/netext73/lm-sensors

« back to all changes in this revision

Viewing changes to prog/dump/isaset.c

  • Committer: mmach
  • Date: 2020-02-05 20:28:34 UTC
  • Revision ID: netbit73@gmail.com-20200205202834-zc3sla47j9e700w5
3.6

Show diffs side-by-side

added added

removed removed

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