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