Mercurial > ~darius > hgwebdir.cgi > hwmon
comparison pcmon/pcmonhelper.c @ 0:c34b37680055 default tip
Inital commit of random SuperIO code.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Thu, 20 Oct 2011 16:48:24 +1030 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c34b37680055 |
---|---|
1 #define _WITH_GETLINE | |
2 | |
3 #include <stdio.h> | |
4 #include <errno.h> | |
5 #include <string.h> | |
6 #include <fcntl.h> | |
7 #include <stdlib.h> | |
8 #include <sys/types.h> | |
9 #include <machine/cpufunc.h> | |
10 #include <unistd.h> | |
11 | |
12 /* Prototypes */ | |
13 void ec_outb(uint16_t base, uint8_t adr, uint8_t val); | |
14 uint8_t ec_inb(uint16_t base, uint8_t adr); | |
15 void ec_run(uint16_t base); | |
16 void freeargs(char **args, size_t nargs); | |
17 void splitline(char *line, char ***args, size_t *nargs); | |
18 void superio_enter(uint16_t base, char type); | |
19 void superio_exit(uint16_t base, char type); | |
20 uint8_t superio_inb(uint8_t base, uint8_t adr); | |
21 void superio_outb(uint16_t base, uint8_t adr, uint8_t val); | |
22 void usage(char *name); | |
23 | |
24 void | |
25 usage(char *name) { | |
26 fprintf(stderr, | |
27 "Bad usage\n" | |
28 "\t%s [-b base] [-t type]\n" | |
29 "\n" | |
30 "Read/write registers in the EC function of Winbond/ITE parts\n" | |
31 "base is the base address for the chip (default: 0x2e)\n" | |
32 "type is the chip type (i = ITE, w = WinBond)\n", name); | |
33 exit(1); | |
34 } | |
35 | |
36 int | |
37 main(int argc, char **argv) { | |
38 int fd, base, ch, ecbase, devid; | |
39 char *progname, type; | |
40 | |
41 type = 'w'; | |
42 base = 0x2e; | |
43 | |
44 progname = argv[0]; | |
45 | |
46 while ((ch = getopt(argc, argv, "b:t:")) != -1) { | |
47 switch (ch) { | |
48 case 'b': | |
49 base = strtol(optarg, NULL, 0) & 0xffff; | |
50 break; | |
51 | |
52 case 't': | |
53 if (optarg[0] != 'w' && optarg[0] != 'i') { | |
54 fprintf(stderr, "type must be w or i\n\n"); | |
55 usage(progname); | |
56 } | |
57 | |
58 type = optarg[0]; | |
59 break; | |
60 | |
61 default: | |
62 usage(progname); | |
63 break; | |
64 } | |
65 } | |
66 argc -= optind; | |
67 argv += optind; | |
68 | |
69 if (argc != 0) | |
70 usage(progname); | |
71 | |
72 if ((fd = open("/dev/io", O_RDWR)) == -1) { | |
73 fprintf(stderr, "Can't open /dev/io: %s\n", strerror(errno)); | |
74 exit(1); | |
75 } | |
76 | |
77 /* Enter extended function mode */ | |
78 superio_enter(base, type); | |
79 | |
80 /* Check device ID */ | |
81 devid = superio_inb(base, 0x20) << 8 | superio_inb(base, 0x21); | |
82 printf("Device ID = 0x%04x\n", devid); | |
83 if (devid != 0x8720) { | |
84 fprintf(stderr, "Device ID mismatch\n"); | |
85 superio_exit(base, type); | |
86 exit(1); | |
87 } | |
88 | |
89 /* Select EC config registers */ | |
90 superio_outb(base, 0x7, 4); | |
91 | |
92 /* Determine EC base address */ | |
93 ecbase = superio_inb(base, 0x60) << 8; | |
94 ecbase |= superio_inb(base, 0x61); | |
95 | |
96 /* Exit extended function mode */ | |
97 superio_exit(base, type); | |
98 | |
99 ec_run(ecbase); | |
100 exit(0); | |
101 } | |
102 | |
103 /* Enter extended function mode */ | |
104 void | |
105 superio_enter(uint16_t base, char type) { | |
106 if (type == 'w') { | |
107 outb(base, 0x87); | |
108 outb(base, 0x87); | |
109 } else { | |
110 outb(base, 0x87); | |
111 outb(base, 0x01); | |
112 outb(base, 0x55); | |
113 outb(base, 0x55); | |
114 } | |
115 } | |
116 | |
117 /* Exit extended function mode */ | |
118 void | |
119 superio_exit(uint16_t base, char type) { | |
120 if (type == 'w') { | |
121 outb(base, 0xaa); | |
122 outb(base, 0xaa); | |
123 } else { | |
124 outb(base, 0x02); | |
125 outb(base, 0x02); | |
126 } | |
127 } | |
128 | |
129 void | |
130 superio_outb(uint16_t base, uint8_t adr, uint8_t val) { | |
131 outb(base, adr); | |
132 outb(base + 1, val); | |
133 } | |
134 | |
135 uint8_t | |
136 superio_inb(uint8_t base, uint8_t adr) { | |
137 outb(base, adr); | |
138 return(inb(base + 1)); | |
139 } | |
140 | |
141 void | |
142 ec_outb(uint16_t base, uint8_t adr, uint8_t val) { | |
143 outb(base + 5, adr); | |
144 outb(base + 6, val); | |
145 } | |
146 | |
147 uint8_t | |
148 ec_inb(uint16_t base, uint8_t adr) { | |
149 outb(base + 5, adr); | |
150 return(inb(base + 6)); | |
151 } | |
152 | |
153 void | |
154 ec_run(uint16_t base) { | |
155 char *line = NULL, **args = NULL, *p; | |
156 size_t llen = 0, nargs; | |
157 long tmp; | |
158 uint8_t adr, val; | |
159 | |
160 printf("EC base address = 0x%04x\n", base); | |
161 printf("EC Vendor ID = 0x%02x\n", ec_inb(base, 0x58)); | |
162 printf("EC Core ID = 0x%02x\n", ec_inb(base, 0x5b)); | |
163 | |
164 while (1) { | |
165 if (getline(&line, &llen, stdin) == -1) | |
166 break; | |
167 | |
168 /* Snip trailing new line*/ | |
169 *rindex(line, '\n')= '\0'; | |
170 | |
171 splitline(line, &args, &nargs); | |
172 | |
173 if (nargs != 2 && nargs != 3) { | |
174 printf("Unable to parse line\n"); | |
175 continue; | |
176 } | |
177 | |
178 tmp = strtol(args[1], &p, 0); | |
179 if (p == args[1]) { | |
180 printf("Unable to parse address\n"); | |
181 continue; | |
182 } | |
183 if (tmp < 0 || tmp > 255) { | |
184 printf("Address out of range\n"); | |
185 continue; | |
186 } | |
187 adr = tmp; | |
188 | |
189 if (!strcmp("read", args[0])) { | |
190 if (nargs != 2) { | |
191 printf("Bad usage of read command\n"); | |
192 continue; | |
193 } | |
194 | |
195 printf("0x%02x -> 0x%02x\n", adr, ec_inb(base, adr)); | |
196 } else if (!strcmp("write", args[0])) { | |
197 if (nargs != 3) { | |
198 printf("Bad usage of write command\n"); | |
199 continue; | |
200 } | |
201 tmp = strtol(args[2], &p, 0); | |
202 if (p == args[1]) { | |
203 printf("Unable to parse value\n"); | |
204 continue; | |
205 } | |
206 if (tmp < 0 || tmp > 255) { | |
207 printf("Value out of range\n"); | |
208 continue; | |
209 } | |
210 val = tmp; | |
211 ec_outb(base, adr, val); | |
212 printf("0x%02x <- 0x%02x\n", adr, val); | |
213 } else { | |
214 printf("Unable to parse line\n"); | |
215 } | |
216 } | |
217 free(line); | |
218 } | |
219 | |
220 void | |
221 splitline(char *line, char ***args, size_t *nargs) { | |
222 char *token; | |
223 | |
224 freeargs(*args, *nargs); | |
225 *args = NULL; | |
226 *nargs = 0; | |
227 | |
228 while ((token = strsep(&line, " ")) != NULL) { | |
229 *args = realloc(*args, sizeof(char *) * (*nargs + 1)); | |
230 if (args == NULL) { | |
231 fprintf(stderr, "Unable to allocate memory\n"); | |
232 exit(1); | |
233 } | |
234 | |
235 (*args)[*nargs] = malloc(strlen(token) + 1); | |
236 strcpy((*args)[*nargs], token); | |
237 | |
238 (*nargs)++; | |
239 } | |
240 } | |
241 | |
242 void | |
243 freeargs(char **args, size_t nargs) { | |
244 int i; | |
245 | |
246 if (args != NULL) { | |
247 for (i = 0; i < nargs; i++) | |
248 free(args[i]); | |
249 free(args); | |
250 } | |
251 } | |
252 |