1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2155fe001SShuah Khan #include <stdio.h>
3155fe001SShuah Khan #include <stdlib.h>
4155fe001SShuah Khan #include <unistd.h>
5155fe001SShuah Khan #include <fcntl.h>
6155fe001SShuah Khan #include <string.h>
7155fe001SShuah Khan #include <memory.h>
8155fe001SShuah Khan #include <malloc.h>
9155fe001SShuah Khan #include <time.h>
10155fe001SShuah Khan #include <ctype.h>
11155fe001SShuah Khan #include <sys/types.h>
12155fe001SShuah Khan #include <sys/wait.h>
13155fe001SShuah Khan #include <signal.h>
14155fe001SShuah Khan #include <errno.h>
15155fe001SShuah Khan #include <sys/time.h>
16155fe001SShuah Khan #include <linux/hpet.h>
17155fe001SShuah Khan
18155fe001SShuah Khan
19155fe001SShuah Khan extern void hpet_open_close(int, const char **);
20155fe001SShuah Khan extern void hpet_info(int, const char **);
21155fe001SShuah Khan extern void hpet_poll(int, const char **);
22155fe001SShuah Khan extern void hpet_fasync(int, const char **);
23155fe001SShuah Khan extern void hpet_read(int, const char **);
24155fe001SShuah Khan
25155fe001SShuah Khan #include <sys/poll.h>
26155fe001SShuah Khan #include <sys/ioctl.h>
27155fe001SShuah Khan
28155fe001SShuah Khan struct hpet_command {
29155fe001SShuah Khan char *command;
30155fe001SShuah Khan void (*func)(int argc, const char ** argv);
31155fe001SShuah Khan } hpet_command[] = {
32155fe001SShuah Khan {
33155fe001SShuah Khan "open-close",
34155fe001SShuah Khan hpet_open_close
35155fe001SShuah Khan },
36155fe001SShuah Khan {
37155fe001SShuah Khan "info",
38155fe001SShuah Khan hpet_info
39155fe001SShuah Khan },
40155fe001SShuah Khan {
41155fe001SShuah Khan "poll",
42155fe001SShuah Khan hpet_poll
43155fe001SShuah Khan },
44155fe001SShuah Khan {
45155fe001SShuah Khan "fasync",
46155fe001SShuah Khan hpet_fasync
47155fe001SShuah Khan },
48155fe001SShuah Khan };
49155fe001SShuah Khan
50155fe001SShuah Khan int
main(int argc,const char ** argv)51155fe001SShuah Khan main(int argc, const char ** argv)
52155fe001SShuah Khan {
53155fe001SShuah Khan unsigned int i;
54155fe001SShuah Khan
55155fe001SShuah Khan argc--;
56155fe001SShuah Khan argv++;
57155fe001SShuah Khan
58155fe001SShuah Khan if (!argc) {
59155fe001SShuah Khan fprintf(stderr, "-hpet: requires command\n");
60155fe001SShuah Khan return -1;
61155fe001SShuah Khan }
62155fe001SShuah Khan
63155fe001SShuah Khan
64155fe001SShuah Khan for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
65155fe001SShuah Khan if (!strcmp(argv[0], hpet_command[i].command)) {
66155fe001SShuah Khan argc--;
67155fe001SShuah Khan argv++;
68155fe001SShuah Khan fprintf(stderr, "-hpet: executing %s\n",
69155fe001SShuah Khan hpet_command[i].command);
70155fe001SShuah Khan hpet_command[i].func(argc, argv);
71155fe001SShuah Khan return 0;
72155fe001SShuah Khan }
73155fe001SShuah Khan
74155fe001SShuah Khan fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
75155fe001SShuah Khan
76155fe001SShuah Khan return -1;
77155fe001SShuah Khan }
78155fe001SShuah Khan
79155fe001SShuah Khan void
hpet_open_close(int argc,const char ** argv)80155fe001SShuah Khan hpet_open_close(int argc, const char **argv)
81155fe001SShuah Khan {
82155fe001SShuah Khan int fd;
83155fe001SShuah Khan
84155fe001SShuah Khan if (argc != 1) {
85155fe001SShuah Khan fprintf(stderr, "hpet_open_close: device-name\n");
86155fe001SShuah Khan return;
87155fe001SShuah Khan }
88155fe001SShuah Khan
89155fe001SShuah Khan fd = open(argv[0], O_RDONLY);
90155fe001SShuah Khan if (fd < 0)
91155fe001SShuah Khan fprintf(stderr, "hpet_open_close: open failed\n");
92155fe001SShuah Khan else
93155fe001SShuah Khan close(fd);
94155fe001SShuah Khan
95155fe001SShuah Khan return;
96155fe001SShuah Khan }
97155fe001SShuah Khan
98155fe001SShuah Khan void
hpet_info(int argc,const char ** argv)99155fe001SShuah Khan hpet_info(int argc, const char **argv)
100155fe001SShuah Khan {
101155fe001SShuah Khan struct hpet_info info;
102155fe001SShuah Khan int fd;
103155fe001SShuah Khan
104155fe001SShuah Khan if (argc != 1) {
105155fe001SShuah Khan fprintf(stderr, "hpet_info: device-name\n");
106155fe001SShuah Khan return;
107155fe001SShuah Khan }
108155fe001SShuah Khan
109155fe001SShuah Khan fd = open(argv[0], O_RDONLY);
110155fe001SShuah Khan if (fd < 0) {
111155fe001SShuah Khan fprintf(stderr, "hpet_info: open of %s failed\n", argv[0]);
112155fe001SShuah Khan return;
113155fe001SShuah Khan }
114155fe001SShuah Khan
115155fe001SShuah Khan if (ioctl(fd, HPET_INFO, &info) < 0) {
116155fe001SShuah Khan fprintf(stderr, "hpet_info: failed to get info\n");
117155fe001SShuah Khan goto out;
118155fe001SShuah Khan }
119155fe001SShuah Khan
120155fe001SShuah Khan fprintf(stderr, "hpet_info: hi_irqfreq 0x%lx hi_flags 0x%lx ",
121155fe001SShuah Khan info.hi_ireqfreq, info.hi_flags);
122155fe001SShuah Khan fprintf(stderr, "hi_hpet %d hi_timer %d\n",
123155fe001SShuah Khan info.hi_hpet, info.hi_timer);
124155fe001SShuah Khan
125155fe001SShuah Khan out:
126155fe001SShuah Khan close(fd);
127155fe001SShuah Khan return;
128155fe001SShuah Khan }
129155fe001SShuah Khan
130155fe001SShuah Khan void
hpet_poll(int argc,const char ** argv)131155fe001SShuah Khan hpet_poll(int argc, const char **argv)
132155fe001SShuah Khan {
133155fe001SShuah Khan unsigned long freq;
134155fe001SShuah Khan int iterations, i, fd;
135155fe001SShuah Khan struct pollfd pfd;
136155fe001SShuah Khan struct hpet_info info;
137155fe001SShuah Khan struct timeval stv, etv;
138155fe001SShuah Khan struct timezone tz;
139155fe001SShuah Khan long usec;
140155fe001SShuah Khan
141155fe001SShuah Khan if (argc != 3) {
142155fe001SShuah Khan fprintf(stderr, "hpet_poll: device-name freq iterations\n");
143155fe001SShuah Khan return;
144155fe001SShuah Khan }
145155fe001SShuah Khan
146155fe001SShuah Khan freq = atoi(argv[1]);
147155fe001SShuah Khan iterations = atoi(argv[2]);
148155fe001SShuah Khan
149155fe001SShuah Khan fd = open(argv[0], O_RDONLY);
150155fe001SShuah Khan
151155fe001SShuah Khan if (fd < 0) {
152155fe001SShuah Khan fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
153155fe001SShuah Khan return;
154155fe001SShuah Khan }
155155fe001SShuah Khan
156155fe001SShuah Khan if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
157155fe001SShuah Khan fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
158155fe001SShuah Khan goto out;
159155fe001SShuah Khan }
160155fe001SShuah Khan
161155fe001SShuah Khan if (ioctl(fd, HPET_INFO, &info) < 0) {
162155fe001SShuah Khan fprintf(stderr, "hpet_poll: failed to get info\n");
163155fe001SShuah Khan goto out;
164155fe001SShuah Khan }
165155fe001SShuah Khan
166155fe001SShuah Khan fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
167155fe001SShuah Khan
168155fe001SShuah Khan if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
169155fe001SShuah Khan fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
170155fe001SShuah Khan goto out;
171155fe001SShuah Khan }
172155fe001SShuah Khan
173155fe001SShuah Khan if (ioctl(fd, HPET_IE_ON, 0) < 0) {
174155fe001SShuah Khan fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
175155fe001SShuah Khan goto out;
176155fe001SShuah Khan }
177155fe001SShuah Khan
178155fe001SShuah Khan pfd.fd = fd;
179155fe001SShuah Khan pfd.events = POLLIN;
180155fe001SShuah Khan
181155fe001SShuah Khan for (i = 0; i < iterations; i++) {
182155fe001SShuah Khan pfd.revents = 0;
183155fe001SShuah Khan gettimeofday(&stv, &tz);
184155fe001SShuah Khan if (poll(&pfd, 1, -1) < 0)
185155fe001SShuah Khan fprintf(stderr, "hpet_poll: poll failed\n");
186155fe001SShuah Khan else {
187155fe001SShuah Khan long data;
188155fe001SShuah Khan
189155fe001SShuah Khan gettimeofday(&etv, &tz);
190155fe001SShuah Khan usec = stv.tv_sec * 1000000 + stv.tv_usec;
191155fe001SShuah Khan usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
192155fe001SShuah Khan
193155fe001SShuah Khan fprintf(stderr,
194155fe001SShuah Khan "hpet_poll: expired time = 0x%lx\n", usec);
195155fe001SShuah Khan
196155fe001SShuah Khan fprintf(stderr, "hpet_poll: revents = 0x%x\n",
197155fe001SShuah Khan pfd.revents);
198155fe001SShuah Khan
199155fe001SShuah Khan if (read(fd, &data, sizeof(data)) != sizeof(data)) {
200155fe001SShuah Khan fprintf(stderr, "hpet_poll: read failed\n");
201155fe001SShuah Khan }
202155fe001SShuah Khan else
203155fe001SShuah Khan fprintf(stderr, "hpet_poll: data 0x%lx\n",
204155fe001SShuah Khan data);
205155fe001SShuah Khan }
206155fe001SShuah Khan }
207155fe001SShuah Khan
208155fe001SShuah Khan out:
209155fe001SShuah Khan close(fd);
210155fe001SShuah Khan return;
211155fe001SShuah Khan }
212155fe001SShuah Khan
213155fe001SShuah Khan static int hpet_sigio_count;
214155fe001SShuah Khan
215155fe001SShuah Khan static void
hpet_sigio(int val)216155fe001SShuah Khan hpet_sigio(int val)
217155fe001SShuah Khan {
218155fe001SShuah Khan fprintf(stderr, "hpet_sigio: called\n");
219155fe001SShuah Khan hpet_sigio_count++;
220155fe001SShuah Khan }
221155fe001SShuah Khan
222155fe001SShuah Khan void
hpet_fasync(int argc,const char ** argv)223155fe001SShuah Khan hpet_fasync(int argc, const char **argv)
224155fe001SShuah Khan {
225155fe001SShuah Khan unsigned long freq;
226155fe001SShuah Khan int iterations, i, fd, value;
227155fe001SShuah Khan sig_t oldsig;
228155fe001SShuah Khan struct hpet_info info;
229155fe001SShuah Khan
230155fe001SShuah Khan hpet_sigio_count = 0;
231155fe001SShuah Khan fd = -1;
232155fe001SShuah Khan
233155fe001SShuah Khan if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
234155fe001SShuah Khan fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
235155fe001SShuah Khan return;
236155fe001SShuah Khan }
237155fe001SShuah Khan
238155fe001SShuah Khan if (argc != 3) {
239155fe001SShuah Khan fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
240155fe001SShuah Khan goto out;
241155fe001SShuah Khan }
242155fe001SShuah Khan
243155fe001SShuah Khan fd = open(argv[0], O_RDONLY);
244155fe001SShuah Khan
245155fe001SShuah Khan if (fd < 0) {
246155fe001SShuah Khan fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
247155fe001SShuah Khan return;
248155fe001SShuah Khan }
249155fe001SShuah Khan
250155fe001SShuah Khan
251155fe001SShuah Khan if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
252155fe001SShuah Khan ((value = fcntl(fd, F_GETFL)) == 1) ||
253155fe001SShuah Khan (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
254155fe001SShuah Khan fprintf(stderr, "hpet_fasync: fcntl failed\n");
255155fe001SShuah Khan goto out;
256155fe001SShuah Khan }
257155fe001SShuah Khan
258155fe001SShuah Khan freq = atoi(argv[1]);
259155fe001SShuah Khan iterations = atoi(argv[2]);
260155fe001SShuah Khan
261155fe001SShuah Khan if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
262155fe001SShuah Khan fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
263155fe001SShuah Khan goto out;
264155fe001SShuah Khan }
265155fe001SShuah Khan
266155fe001SShuah Khan if (ioctl(fd, HPET_INFO, &info) < 0) {
267155fe001SShuah Khan fprintf(stderr, "hpet_fasync: failed to get info\n");
268155fe001SShuah Khan goto out;
269155fe001SShuah Khan }
270155fe001SShuah Khan
271155fe001SShuah Khan fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
272155fe001SShuah Khan
273155fe001SShuah Khan if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
274155fe001SShuah Khan fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
275155fe001SShuah Khan goto out;
276155fe001SShuah Khan }
277155fe001SShuah Khan
278155fe001SShuah Khan if (ioctl(fd, HPET_IE_ON, 0) < 0) {
279155fe001SShuah Khan fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
280155fe001SShuah Khan goto out;
281155fe001SShuah Khan }
282155fe001SShuah Khan
283155fe001SShuah Khan for (i = 0; i < iterations; i++) {
284155fe001SShuah Khan (void) pause();
285155fe001SShuah Khan fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
286155fe001SShuah Khan }
287155fe001SShuah Khan
288155fe001SShuah Khan out:
289155fe001SShuah Khan signal(SIGIO, oldsig);
290155fe001SShuah Khan
291155fe001SShuah Khan if (fd >= 0)
292155fe001SShuah Khan close(fd);
293155fe001SShuah Khan
294155fe001SShuah Khan return;
295155fe001SShuah Khan }
296