Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / tools / power / acpi / tools / ec / ec_access.c
1 /*
2  * ec_access.c
3  *
4  * Copyright (C) 2010 SUSE Linux Products GmbH
5  * Author:
6  *      Thomas Renninger <trenn@suse.de>
7  *
8  * This work is licensed under the terms of the GNU GPL, version 2.
9  */
10
11 #include <fcntl.h>
12 #include <err.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <libgen.h>
16 #include <unistd.h>
17 #include <getopt.h>
18 #include <stdint.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21
22
23 #define EC_SPACE_SIZE 256
24 #define SYSFS_PATH "/sys/kernel/debug/ec/ec0/io"
25
26 /* TBD/Enhancements:
27    - Provide param for accessing different ECs (not supported by kernel yet)
28 */
29
30 static int read_mode = -1;
31 static int sleep_time;
32 static int write_byte_offset = -1;
33 static int read_byte_offset = -1;
34 static uint8_t write_value = -1;
35
36 void usage(char progname[], int exit_status)
37 {
38         printf("Usage:\n");
39         printf("1) %s -r [-s sleep]\n", basename(progname));
40         printf("2) %s -b byte_offset\n", basename(progname));
41         printf("3) %s -w byte_offset -v value\n\n", basename(progname));
42
43         puts("\t-r [-s sleep]      : Dump EC registers");
44         puts("\t                     If sleep is given, sleep x seconds,");
45         puts("\t                     re-read EC registers and show changes");
46         puts("\t-b offset          : Read value at byte_offset (in hex)");
47         puts("\t-w offset -v value : Write value at byte_offset");
48         puts("\t-h                 : Print this help\n\n");
49         puts("Offsets and values are in hexadecimal number sytem.");
50         puts("The offset and value must be between 0 and 0xff.");
51         exit(exit_status);
52 }
53
54 void parse_opts(int argc, char *argv[])
55 {
56         int c;
57
58         while ((c = getopt(argc, argv, "rs:b:w:v:h")) != -1) {
59
60                 switch (c) {
61                 case 'r':
62                         if (read_mode != -1)
63                                 usage(argv[0], EXIT_FAILURE);
64                         read_mode = 1;
65                         break;
66                 case 's':
67                         if (read_mode != -1 && read_mode != 1)
68                                 usage(argv[0], EXIT_FAILURE);
69
70                         sleep_time = atoi(optarg);
71                         if (sleep_time <= 0) {
72                                 sleep_time = 0;
73                                 usage(argv[0], EXIT_FAILURE);
74                                 printf("Bad sleep time: %s\n", optarg);
75                         }
76                         break;
77                 case 'b':
78                         if (read_mode != -1)
79                                 usage(argv[0], EXIT_FAILURE);
80                         read_mode = 1;
81                         read_byte_offset = strtoul(optarg, NULL, 16);
82                         break;
83                 case 'w':
84                         if (read_mode != -1)
85                                 usage(argv[0], EXIT_FAILURE);
86                         read_mode = 0;
87                         write_byte_offset = strtoul(optarg, NULL, 16);
88                         break;
89                 case 'v':
90                         write_value = strtoul(optarg, NULL, 16);
91                         break;
92                 case 'h':
93                         usage(argv[0], EXIT_SUCCESS);
94                 default:
95                         fprintf(stderr, "Unknown option!\n");
96                         usage(argv[0], EXIT_FAILURE);
97                 }
98         }
99         if (read_mode == 0) {
100                 if (write_byte_offset < 0 ||
101                     write_byte_offset >= EC_SPACE_SIZE) {
102                         fprintf(stderr, "Wrong byte offset 0x%.2x, valid: "
103                                 "[0-0x%.2x]\n",
104                                 write_byte_offset, EC_SPACE_SIZE - 1);
105                         usage(argv[0], EXIT_FAILURE);
106                 }
107                 if (write_value < 0 ||
108                     write_value >= 255) {
109                         fprintf(stderr, "Wrong byte offset 0x%.2x, valid:"
110                                 "[0-0xff]\n", write_byte_offset);
111                         usage(argv[0], EXIT_FAILURE);
112                 }
113         }
114         if (read_mode == 1 && read_byte_offset != -1) {
115                 if (read_byte_offset < -1 ||
116                     read_byte_offset >= EC_SPACE_SIZE) {
117                         fprintf(stderr, "Wrong byte offset 0x%.2x, valid: "
118                                 "[0-0x%.2x]\n",
119                                 read_byte_offset, EC_SPACE_SIZE - 1);
120                         usage(argv[0], EXIT_FAILURE);
121                 }
122         }
123         /* Add additional parameter checks here */
124 }
125
126 void dump_ec(int fd)
127 {
128         char buf[EC_SPACE_SIZE];
129         char buf2[EC_SPACE_SIZE];
130         int byte_off, bytes_read;
131
132         bytes_read = read(fd, buf, EC_SPACE_SIZE);
133
134         if (bytes_read == -1)
135                 err(EXIT_FAILURE, "Could not read from %s\n", SYSFS_PATH);
136
137         if (bytes_read != EC_SPACE_SIZE)
138                 fprintf(stderr, "Could only read %d bytes\n", bytes_read);
139
140         printf("     00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F");
141         for (byte_off = 0; byte_off < bytes_read; byte_off++) {
142                 if ((byte_off % 16) == 0)
143                         printf("\n%.2X: ", byte_off);
144                 printf(" %.2x ", (uint8_t)buf[byte_off]);
145         }
146         printf("\n");
147
148         if (!sleep_time)
149                 return;
150
151         printf("\n");
152         lseek(fd, 0, SEEK_SET);
153         sleep(sleep_time);
154
155         bytes_read = read(fd, buf2, EC_SPACE_SIZE);
156
157         if (bytes_read == -1)
158                 err(EXIT_FAILURE, "Could not read from %s\n", SYSFS_PATH);
159
160         if (bytes_read != EC_SPACE_SIZE)
161                 fprintf(stderr, "Could only read %d bytes\n", bytes_read);
162
163         printf("     00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F");
164         for (byte_off = 0; byte_off < bytes_read; byte_off++) {
165                 if ((byte_off % 16) == 0)
166                         printf("\n%.2X: ", byte_off);
167
168                 if (buf[byte_off] == buf2[byte_off])
169                         printf(" %.2x ", (uint8_t)buf2[byte_off]);
170                 else
171                         printf("*%.2x ", (uint8_t)buf2[byte_off]);
172         }
173         printf("\n");
174 }
175
176 void read_ec_val(int fd, int byte_offset)
177 {
178         uint8_t buf;
179         int error;
180
181         error = lseek(fd, byte_offset, SEEK_SET);
182         if (error != byte_offset)
183                 err(EXIT_FAILURE, "Cannot set offset to 0x%.2x", byte_offset);
184
185         error = read(fd, &buf, 1);
186         if (error != 1)
187                 err(EXIT_FAILURE, "Could not read byte 0x%.2x from %s\n",
188                     byte_offset, SYSFS_PATH);
189         printf("0x%.2x\n", buf);
190         return;
191 }
192
193 void write_ec_val(int fd, int byte_offset, uint8_t value)
194 {
195         int error;
196
197         error = lseek(fd, byte_offset, SEEK_SET);
198         if (error != byte_offset)
199                 err(EXIT_FAILURE, "Cannot set offset to 0x%.2x", byte_offset);
200
201         error = write(fd, &value, 1);
202         if (error != 1)
203                 err(EXIT_FAILURE, "Cannot write value 0x%.2x to offset 0x%.2x",
204                     value, byte_offset);
205 }
206
207 int main(int argc, char *argv[])
208 {
209         int file_mode = O_RDONLY;
210         int fd;
211
212         parse_opts(argc, argv);
213
214         if (read_mode == 0)
215                 file_mode = O_WRONLY;
216         else if (read_mode == 1)
217                 file_mode = O_RDONLY;
218         else
219                 usage(argv[0], EXIT_FAILURE);
220
221         fd = open(SYSFS_PATH, file_mode);
222         if (fd == -1)
223                 err(EXIT_FAILURE, "%s", SYSFS_PATH);
224
225         if (read_mode)
226                 if (read_byte_offset == -1)
227                         dump_ec(fd);
228                 else if (read_byte_offset < 0 ||
229                          read_byte_offset >= EC_SPACE_SIZE)
230                         usage(argv[0], EXIT_FAILURE);
231                 else
232                         read_ec_val(fd, read_byte_offset);
233         else
234                 write_ec_val(fd, write_byte_offset, write_value);
235         close(fd);
236
237         exit(EXIT_SUCCESS);
238 }