1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <stdio.h>
3*4882a593Smuzhiyun #include <stdlib.h>
4*4882a593Smuzhiyun #include <unistd.h>
5*4882a593Smuzhiyun #include <fcntl.h>
6*4882a593Smuzhiyun #include <string.h>
7*4882a593Smuzhiyun #include <memory.h>
8*4882a593Smuzhiyun #include <malloc.h>
9*4882a593Smuzhiyun #include <time.h>
10*4882a593Smuzhiyun #include <ctype.h>
11*4882a593Smuzhiyun #include <sys/types.h>
12*4882a593Smuzhiyun #include <sys/wait.h>
13*4882a593Smuzhiyun #include <signal.h>
14*4882a593Smuzhiyun #include <errno.h>
15*4882a593Smuzhiyun #include <sys/time.h>
16*4882a593Smuzhiyun #include <linux/hpet.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun extern void hpet_open_close(int, const char **);
20*4882a593Smuzhiyun extern void hpet_info(int, const char **);
21*4882a593Smuzhiyun extern void hpet_poll(int, const char **);
22*4882a593Smuzhiyun extern void hpet_fasync(int, const char **);
23*4882a593Smuzhiyun extern void hpet_read(int, const char **);
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <sys/poll.h>
26*4882a593Smuzhiyun #include <sys/ioctl.h>
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun struct hpet_command {
29*4882a593Smuzhiyun char *command;
30*4882a593Smuzhiyun void (*func)(int argc, const char ** argv);
31*4882a593Smuzhiyun } hpet_command[] = {
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun "open-close",
34*4882a593Smuzhiyun hpet_open_close
35*4882a593Smuzhiyun },
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun "info",
38*4882a593Smuzhiyun hpet_info
39*4882a593Smuzhiyun },
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun "poll",
42*4882a593Smuzhiyun hpet_poll
43*4882a593Smuzhiyun },
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun "fasync",
46*4882a593Smuzhiyun hpet_fasync
47*4882a593Smuzhiyun },
48*4882a593Smuzhiyun };
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun int
main(int argc,const char ** argv)51*4882a593Smuzhiyun main(int argc, const char ** argv)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun unsigned int i;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun argc--;
56*4882a593Smuzhiyun argv++;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun if (!argc) {
59*4882a593Smuzhiyun fprintf(stderr, "-hpet: requires command\n");
60*4882a593Smuzhiyun return -1;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
65*4882a593Smuzhiyun if (!strcmp(argv[0], hpet_command[i].command)) {
66*4882a593Smuzhiyun argc--;
67*4882a593Smuzhiyun argv++;
68*4882a593Smuzhiyun fprintf(stderr, "-hpet: executing %s\n",
69*4882a593Smuzhiyun hpet_command[i].command);
70*4882a593Smuzhiyun hpet_command[i].func(argc, argv);
71*4882a593Smuzhiyun return 0;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun return -1;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun void
hpet_open_close(int argc,const char ** argv)80*4882a593Smuzhiyun hpet_open_close(int argc, const char **argv)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun int fd;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun if (argc != 1) {
85*4882a593Smuzhiyun fprintf(stderr, "hpet_open_close: device-name\n");
86*4882a593Smuzhiyun return;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun fd = open(argv[0], O_RDONLY);
90*4882a593Smuzhiyun if (fd < 0)
91*4882a593Smuzhiyun fprintf(stderr, "hpet_open_close: open failed\n");
92*4882a593Smuzhiyun else
93*4882a593Smuzhiyun close(fd);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun return;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun void
hpet_info(int argc,const char ** argv)99*4882a593Smuzhiyun hpet_info(int argc, const char **argv)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun struct hpet_info info;
102*4882a593Smuzhiyun int fd;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun if (argc != 1) {
105*4882a593Smuzhiyun fprintf(stderr, "hpet_info: device-name\n");
106*4882a593Smuzhiyun return;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun fd = open(argv[0], O_RDONLY);
110*4882a593Smuzhiyun if (fd < 0) {
111*4882a593Smuzhiyun fprintf(stderr, "hpet_info: open of %s failed\n", argv[0]);
112*4882a593Smuzhiyun return;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun if (ioctl(fd, HPET_INFO, &info) < 0) {
116*4882a593Smuzhiyun fprintf(stderr, "hpet_info: failed to get info\n");
117*4882a593Smuzhiyun goto out;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun fprintf(stderr, "hpet_info: hi_irqfreq 0x%lx hi_flags 0x%lx ",
121*4882a593Smuzhiyun info.hi_ireqfreq, info.hi_flags);
122*4882a593Smuzhiyun fprintf(stderr, "hi_hpet %d hi_timer %d\n",
123*4882a593Smuzhiyun info.hi_hpet, info.hi_timer);
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun out:
126*4882a593Smuzhiyun close(fd);
127*4882a593Smuzhiyun return;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun void
hpet_poll(int argc,const char ** argv)131*4882a593Smuzhiyun hpet_poll(int argc, const char **argv)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun unsigned long freq;
134*4882a593Smuzhiyun int iterations, i, fd;
135*4882a593Smuzhiyun struct pollfd pfd;
136*4882a593Smuzhiyun struct hpet_info info;
137*4882a593Smuzhiyun struct timeval stv, etv;
138*4882a593Smuzhiyun struct timezone tz;
139*4882a593Smuzhiyun long usec;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun if (argc != 3) {
142*4882a593Smuzhiyun fprintf(stderr, "hpet_poll: device-name freq iterations\n");
143*4882a593Smuzhiyun return;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun freq = atoi(argv[1]);
147*4882a593Smuzhiyun iterations = atoi(argv[2]);
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun fd = open(argv[0], O_RDONLY);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if (fd < 0) {
152*4882a593Smuzhiyun fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
153*4882a593Smuzhiyun return;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
157*4882a593Smuzhiyun fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
158*4882a593Smuzhiyun goto out;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun if (ioctl(fd, HPET_INFO, &info) < 0) {
162*4882a593Smuzhiyun fprintf(stderr, "hpet_poll: failed to get info\n");
163*4882a593Smuzhiyun goto out;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
169*4882a593Smuzhiyun fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
170*4882a593Smuzhiyun goto out;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun if (ioctl(fd, HPET_IE_ON, 0) < 0) {
174*4882a593Smuzhiyun fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
175*4882a593Smuzhiyun goto out;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun pfd.fd = fd;
179*4882a593Smuzhiyun pfd.events = POLLIN;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun for (i = 0; i < iterations; i++) {
182*4882a593Smuzhiyun pfd.revents = 0;
183*4882a593Smuzhiyun gettimeofday(&stv, &tz);
184*4882a593Smuzhiyun if (poll(&pfd, 1, -1) < 0)
185*4882a593Smuzhiyun fprintf(stderr, "hpet_poll: poll failed\n");
186*4882a593Smuzhiyun else {
187*4882a593Smuzhiyun long data;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun gettimeofday(&etv, &tz);
190*4882a593Smuzhiyun usec = stv.tv_sec * 1000000 + stv.tv_usec;
191*4882a593Smuzhiyun usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun fprintf(stderr,
194*4882a593Smuzhiyun "hpet_poll: expired time = 0x%lx\n", usec);
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun fprintf(stderr, "hpet_poll: revents = 0x%x\n",
197*4882a593Smuzhiyun pfd.revents);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun if (read(fd, &data, sizeof(data)) != sizeof(data)) {
200*4882a593Smuzhiyun fprintf(stderr, "hpet_poll: read failed\n");
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun else
203*4882a593Smuzhiyun fprintf(stderr, "hpet_poll: data 0x%lx\n",
204*4882a593Smuzhiyun data);
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun out:
209*4882a593Smuzhiyun close(fd);
210*4882a593Smuzhiyun return;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun static int hpet_sigio_count;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun static void
hpet_sigio(int val)216*4882a593Smuzhiyun hpet_sigio(int val)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun fprintf(stderr, "hpet_sigio: called\n");
219*4882a593Smuzhiyun hpet_sigio_count++;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun void
hpet_fasync(int argc,const char ** argv)223*4882a593Smuzhiyun hpet_fasync(int argc, const char **argv)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun unsigned long freq;
226*4882a593Smuzhiyun int iterations, i, fd, value;
227*4882a593Smuzhiyun sig_t oldsig;
228*4882a593Smuzhiyun struct hpet_info info;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun hpet_sigio_count = 0;
231*4882a593Smuzhiyun fd = -1;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
234*4882a593Smuzhiyun fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
235*4882a593Smuzhiyun return;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun if (argc != 3) {
239*4882a593Smuzhiyun fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
240*4882a593Smuzhiyun goto out;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun fd = open(argv[0], O_RDONLY);
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (fd < 0) {
246*4882a593Smuzhiyun fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
247*4882a593Smuzhiyun return;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
252*4882a593Smuzhiyun ((value = fcntl(fd, F_GETFL)) == 1) ||
253*4882a593Smuzhiyun (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
254*4882a593Smuzhiyun fprintf(stderr, "hpet_fasync: fcntl failed\n");
255*4882a593Smuzhiyun goto out;
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun freq = atoi(argv[1]);
259*4882a593Smuzhiyun iterations = atoi(argv[2]);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
262*4882a593Smuzhiyun fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
263*4882a593Smuzhiyun goto out;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun if (ioctl(fd, HPET_INFO, &info) < 0) {
267*4882a593Smuzhiyun fprintf(stderr, "hpet_fasync: failed to get info\n");
268*4882a593Smuzhiyun goto out;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
274*4882a593Smuzhiyun fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
275*4882a593Smuzhiyun goto out;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun if (ioctl(fd, HPET_IE_ON, 0) < 0) {
279*4882a593Smuzhiyun fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
280*4882a593Smuzhiyun goto out;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun for (i = 0; i < iterations; i++) {
284*4882a593Smuzhiyun (void) pause();
285*4882a593Smuzhiyun fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun out:
289*4882a593Smuzhiyun signal(SIGIO, oldsig);
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (fd >= 0)
292*4882a593Smuzhiyun close(fd);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun return;
295*4882a593Smuzhiyun }
296