ia64/linux-2.6.18-xen.hg

annotate Documentation/hpet.txt @ 524:7f8b544237bf

netfront: Allow netfront in domain 0.

This is useful if your physical network device is in a utility domain.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Apr 15 15:18:58 2008 +0100 (2008-04-15)
parents 831230e53067
children
rev   line source
ian@0 1 High Precision Event Timer Driver for Linux
ian@0 2
ian@0 3 The High Precision Event Timer (HPET) hardware is the future replacement
ian@0 4 for the 8254 and Real Time Clock (RTC) periodic timer functionality.
ian@0 5 Each HPET can have up to 32 timers. It is possible to configure the
ian@0 6 first two timers as legacy replacements for 8254 and RTC periodic timers.
ian@0 7 A specification done by Intel and Microsoft can be found at
ian@0 8 <http://www.intel.com/hardwaredesign/hpetspec.htm>.
ian@0 9
ian@0 10 The driver supports detection of HPET driver allocation and initialization
ian@0 11 of the HPET before the driver module_init routine is called. This enables
ian@0 12 platform code which uses timer 0 or 1 as the main timer to intercept HPET
ian@0 13 initialization. An example of this initialization can be found in
ian@0 14 arch/i386/kernel/time_hpet.c.
ian@0 15
ian@0 16 The driver provides two APIs which are very similar to the API found in
ian@0 17 the rtc.c driver. There is a user space API and a kernel space API.
ian@0 18 An example user space program is provided below.
ian@0 19
ian@0 20 #include <stdio.h>
ian@0 21 #include <stdlib.h>
ian@0 22 #include <unistd.h>
ian@0 23 #include <fcntl.h>
ian@0 24 #include <string.h>
ian@0 25 #include <memory.h>
ian@0 26 #include <malloc.h>
ian@0 27 #include <time.h>
ian@0 28 #include <ctype.h>
ian@0 29 #include <sys/types.h>
ian@0 30 #include <sys/wait.h>
ian@0 31 #include <signal.h>
ian@0 32 #include <fcntl.h>
ian@0 33 #include <errno.h>
ian@0 34 #include <sys/time.h>
ian@0 35 #include <linux/hpet.h>
ian@0 36
ian@0 37
ian@0 38 extern void hpet_open_close(int, const char **);
ian@0 39 extern void hpet_info(int, const char **);
ian@0 40 extern void hpet_poll(int, const char **);
ian@0 41 extern void hpet_fasync(int, const char **);
ian@0 42 extern void hpet_read(int, const char **);
ian@0 43
ian@0 44 #include <sys/poll.h>
ian@0 45 #include <sys/ioctl.h>
ian@0 46 #include <signal.h>
ian@0 47
ian@0 48 struct hpet_command {
ian@0 49 char *command;
ian@0 50 void (*func)(int argc, const char ** argv);
ian@0 51 } hpet_command[] = {
ian@0 52 {
ian@0 53 "open-close",
ian@0 54 hpet_open_close
ian@0 55 },
ian@0 56 {
ian@0 57 "info",
ian@0 58 hpet_info
ian@0 59 },
ian@0 60 {
ian@0 61 "poll",
ian@0 62 hpet_poll
ian@0 63 },
ian@0 64 {
ian@0 65 "fasync",
ian@0 66 hpet_fasync
ian@0 67 },
ian@0 68 };
ian@0 69
ian@0 70 int
ian@0 71 main(int argc, const char ** argv)
ian@0 72 {
ian@0 73 int i;
ian@0 74
ian@0 75 argc--;
ian@0 76 argv++;
ian@0 77
ian@0 78 if (!argc) {
ian@0 79 fprintf(stderr, "-hpet: requires command\n");
ian@0 80 return -1;
ian@0 81 }
ian@0 82
ian@0 83
ian@0 84 for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
ian@0 85 if (!strcmp(argv[0], hpet_command[i].command)) {
ian@0 86 argc--;
ian@0 87 argv++;
ian@0 88 fprintf(stderr, "-hpet: executing %s\n",
ian@0 89 hpet_command[i].command);
ian@0 90 hpet_command[i].func(argc, argv);
ian@0 91 return 0;
ian@0 92 }
ian@0 93
ian@0 94 fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
ian@0 95
ian@0 96 return -1;
ian@0 97 }
ian@0 98
ian@0 99 void
ian@0 100 hpet_open_close(int argc, const char **argv)
ian@0 101 {
ian@0 102 int fd;
ian@0 103
ian@0 104 if (argc != 1) {
ian@0 105 fprintf(stderr, "hpet_open_close: device-name\n");
ian@0 106 return;
ian@0 107 }
ian@0 108
ian@0 109 fd = open(argv[0], O_RDONLY);
ian@0 110 if (fd < 0)
ian@0 111 fprintf(stderr, "hpet_open_close: open failed\n");
ian@0 112 else
ian@0 113 close(fd);
ian@0 114
ian@0 115 return;
ian@0 116 }
ian@0 117
ian@0 118 void
ian@0 119 hpet_info(int argc, const char **argv)
ian@0 120 {
ian@0 121 }
ian@0 122
ian@0 123 void
ian@0 124 hpet_poll(int argc, const char **argv)
ian@0 125 {
ian@0 126 unsigned long freq;
ian@0 127 int iterations, i, fd;
ian@0 128 struct pollfd pfd;
ian@0 129 struct hpet_info info;
ian@0 130 struct timeval stv, etv;
ian@0 131 struct timezone tz;
ian@0 132 long usec;
ian@0 133
ian@0 134 if (argc != 3) {
ian@0 135 fprintf(stderr, "hpet_poll: device-name freq iterations\n");
ian@0 136 return;
ian@0 137 }
ian@0 138
ian@0 139 freq = atoi(argv[1]);
ian@0 140 iterations = atoi(argv[2]);
ian@0 141
ian@0 142 fd = open(argv[0], O_RDONLY);
ian@0 143
ian@0 144 if (fd < 0) {
ian@0 145 fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
ian@0 146 return;
ian@0 147 }
ian@0 148
ian@0 149 if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
ian@0 150 fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
ian@0 151 goto out;
ian@0 152 }
ian@0 153
ian@0 154 if (ioctl(fd, HPET_INFO, &info) < 0) {
ian@0 155 fprintf(stderr, "hpet_poll: failed to get info\n");
ian@0 156 goto out;
ian@0 157 }
ian@0 158
ian@0 159 fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
ian@0 160
ian@0 161 if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
ian@0 162 fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
ian@0 163 goto out;
ian@0 164 }
ian@0 165
ian@0 166 if (ioctl(fd, HPET_IE_ON, 0) < 0) {
ian@0 167 fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
ian@0 168 goto out;
ian@0 169 }
ian@0 170
ian@0 171 pfd.fd = fd;
ian@0 172 pfd.events = POLLIN;
ian@0 173
ian@0 174 for (i = 0; i < iterations; i++) {
ian@0 175 pfd.revents = 0;
ian@0 176 gettimeofday(&stv, &tz);
ian@0 177 if (poll(&pfd, 1, -1) < 0)
ian@0 178 fprintf(stderr, "hpet_poll: poll failed\n");
ian@0 179 else {
ian@0 180 long data;
ian@0 181
ian@0 182 gettimeofday(&etv, &tz);
ian@0 183 usec = stv.tv_sec * 1000000 + stv.tv_usec;
ian@0 184 usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
ian@0 185
ian@0 186 fprintf(stderr,
ian@0 187 "hpet_poll: expired time = 0x%lx\n", usec);
ian@0 188
ian@0 189 fprintf(stderr, "hpet_poll: revents = 0x%x\n",
ian@0 190 pfd.revents);
ian@0 191
ian@0 192 if (read(fd, &data, sizeof(data)) != sizeof(data)) {
ian@0 193 fprintf(stderr, "hpet_poll: read failed\n");
ian@0 194 }
ian@0 195 else
ian@0 196 fprintf(stderr, "hpet_poll: data 0x%lx\n",
ian@0 197 data);
ian@0 198 }
ian@0 199 }
ian@0 200
ian@0 201 out:
ian@0 202 close(fd);
ian@0 203 return;
ian@0 204 }
ian@0 205
ian@0 206 static int hpet_sigio_count;
ian@0 207
ian@0 208 static void
ian@0 209 hpet_sigio(int val)
ian@0 210 {
ian@0 211 fprintf(stderr, "hpet_sigio: called\n");
ian@0 212 hpet_sigio_count++;
ian@0 213 }
ian@0 214
ian@0 215 void
ian@0 216 hpet_fasync(int argc, const char **argv)
ian@0 217 {
ian@0 218 unsigned long freq;
ian@0 219 int iterations, i, fd, value;
ian@0 220 sig_t oldsig;
ian@0 221 struct hpet_info info;
ian@0 222
ian@0 223 hpet_sigio_count = 0;
ian@0 224 fd = -1;
ian@0 225
ian@0 226 if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
ian@0 227 fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
ian@0 228 return;
ian@0 229 }
ian@0 230
ian@0 231 if (argc != 3) {
ian@0 232 fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
ian@0 233 goto out;
ian@0 234 }
ian@0 235
ian@0 236 fd = open(argv[0], O_RDONLY);
ian@0 237
ian@0 238 if (fd < 0) {
ian@0 239 fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
ian@0 240 return;
ian@0 241 }
ian@0 242
ian@0 243
ian@0 244 if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
ian@0 245 ((value = fcntl(fd, F_GETFL)) == 1) ||
ian@0 246 (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
ian@0 247 fprintf(stderr, "hpet_fasync: fcntl failed\n");
ian@0 248 goto out;
ian@0 249 }
ian@0 250
ian@0 251 freq = atoi(argv[1]);
ian@0 252 iterations = atoi(argv[2]);
ian@0 253
ian@0 254 if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
ian@0 255 fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
ian@0 256 goto out;
ian@0 257 }
ian@0 258
ian@0 259 if (ioctl(fd, HPET_INFO, &info) < 0) {
ian@0 260 fprintf(stderr, "hpet_fasync: failed to get info\n");
ian@0 261 goto out;
ian@0 262 }
ian@0 263
ian@0 264 fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
ian@0 265
ian@0 266 if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
ian@0 267 fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
ian@0 268 goto out;
ian@0 269 }
ian@0 270
ian@0 271 if (ioctl(fd, HPET_IE_ON, 0) < 0) {
ian@0 272 fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
ian@0 273 goto out;
ian@0 274 }
ian@0 275
ian@0 276 for (i = 0; i < iterations; i++) {
ian@0 277 (void) pause();
ian@0 278 fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
ian@0 279 }
ian@0 280
ian@0 281 out:
ian@0 282 signal(SIGIO, oldsig);
ian@0 283
ian@0 284 if (fd >= 0)
ian@0 285 close(fd);
ian@0 286
ian@0 287 return;
ian@0 288 }
ian@0 289
ian@0 290 The kernel API has three interfaces exported from the driver:
ian@0 291
ian@0 292 hpet_register(struct hpet_task *tp, int periodic)
ian@0 293 hpet_unregister(struct hpet_task *tp)
ian@0 294 hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
ian@0 295
ian@0 296 The kernel module using this interface fills in the ht_func and ht_data
ian@0 297 members of the hpet_task structure before calling hpet_register.
ian@0 298 hpet_control simply vectors to the hpet_ioctl routine and has the same
ian@0 299 commands and respective arguments as the user API. hpet_unregister
ian@0 300 is used to terminate usage of the HPET timer reserved by hpet_register.