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