linux/Documentation/timers/hpet.txt
<<
>>
Prefs
   1                High Precision Event Timer Driver for Linux
   2
   3The High Precision Event Timer (HPET) hardware follows a specification
   4by Intel and Microsoft which can be found at
   5
   6        http://www.intel.com/technology/architecture/hpetspec.htm
   7
   8Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision")
   9and up to 32 comparators.  Normally three or more comparators are provided,
  10each of which can generate oneshot interupts and at least one of which has
  11additional hardware to support periodic interrupts.  The comparators are
  12also called "timers", which can be misleading since usually timers are
  13independent of each other ... these share a counter, complicating resets.
  14
  15HPET devices can support two interrupt routing modes.  In one mode, the
  16comparators are additional interrupt sources with no particular system
  17role.  Many x86 BIOS writers don't route HPET interrupts at all, which
  18prevents use of that mode.  They support the other "legacy replacement"
  19mode where the first two comparators block interrupts from 8254 timers
  20and from the RTC.
  21
  22The driver supports detection of HPET driver allocation and initialization
  23of the HPET before the driver module_init routine is called.  This enables
  24platform code which uses timer 0 or 1 as the main timer to intercept HPET
  25initialization.  An example of this initialization can be found in
  26arch/x86/kernel/hpet.c.
  27
  28The driver provides a userspace API which resembles the API found in the
  29RTC driver framework.  An example user space program is provided below.
  30
  31#include <stdio.h>
  32#include <stdlib.h>
  33#include <unistd.h>
  34#include <fcntl.h>
  35#include <string.h>
  36#include <memory.h>
  37#include <malloc.h>
  38#include <time.h>
  39#include <ctype.h>
  40#include <sys/types.h>
  41#include <sys/wait.h>
  42#include <signal.h>
  43#include <fcntl.h>
  44#include <errno.h>
  45#include <sys/time.h>
  46#include <linux/hpet.h>
  47
  48
  49extern void hpet_open_close(int, const char **);
  50extern void hpet_info(int, const char **);
  51extern void hpet_poll(int, const char **);
  52extern void hpet_fasync(int, const char **);
  53extern void hpet_read(int, const char **);
  54
  55#include <sys/poll.h>
  56#include <sys/ioctl.h>
  57#include <signal.h>
  58
  59struct hpet_command {
  60        char            *command;
  61        void            (*func)(int argc, const char ** argv);
  62} hpet_command[] = {
  63        {
  64                "open-close",
  65                hpet_open_close
  66        },
  67        {
  68                "info",
  69                hpet_info
  70        },
  71        {
  72                "poll",
  73                hpet_poll
  74        },
  75        {
  76                "fasync",
  77                hpet_fasync
  78        },
  79};
  80
  81int
  82main(int argc, const char ** argv)
  83{
  84        int     i;
  85
  86        argc--;
  87        argv++;
  88
  89        if (!argc) {
  90                fprintf(stderr, "-hpet: requires command\n");
  91                return -1;
  92        }
  93
  94
  95        for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
  96                if (!strcmp(argv[0], hpet_command[i].command)) {
  97                        argc--;
  98                        argv++;
  99                        fprintf(stderr, "-hpet: executing %s\n",
 100                                hpet_command[i].command);
 101                        hpet_command[i].func(argc, argv);
 102                        return 0;
 103                }
 104
 105        fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
 106
 107        return -1;
 108}
 109
 110void
 111hpet_open_close(int argc, const char **argv)
 112{
 113        int     fd;
 114
 115        if (argc != 1) {
 116                fprintf(stderr, "hpet_open_close: device-name\n");
 117                return;
 118        }
 119
 120        fd = open(argv[0], O_RDONLY);
 121        if (fd < 0)
 122                fprintf(stderr, "hpet_open_close: open failed\n");
 123        else
 124                close(fd);
 125
 126        return;
 127}
 128
 129void
 130hpet_info(int argc, const char **argv)
 131{
 132}
 133
 134void
 135hpet_poll(int argc, const char **argv)
 136{
 137        unsigned long           freq;
 138        int                     iterations, i, fd;
 139        struct pollfd           pfd;
 140        struct hpet_info        info;
 141        struct timeval          stv, etv;
 142        struct timezone         tz;
 143        long                    usec;
 144
 145        if (argc != 3) {
 146                fprintf(stderr, "hpet_poll: device-name freq iterations\n");
 147                return;
 148        }
 149
 150        freq = atoi(argv[1]);
 151        iterations = atoi(argv[2]);
 152
 153        fd = open(argv[0], O_RDONLY);
 154
 155        if (fd < 0) {
 156                fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
 157                return;
 158        }
 159
 160        if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
 161                fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
 162                goto out;
 163        }
 164
 165        if (ioctl(fd, HPET_INFO, &info) < 0) {
 166                fprintf(stderr, "hpet_poll: failed to get info\n");
 167                goto out;
 168        }
 169
 170        fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
 171
 172        if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
 173                fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
 174                goto out;
 175        }
 176
 177        if (ioctl(fd, HPET_IE_ON, 0) < 0) {
 178                fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
 179                goto out;
 180        }
 181
 182        pfd.fd = fd;
 183        pfd.events = POLLIN;
 184
 185        for (i = 0; i < iterations; i++) {
 186                pfd.revents = 0;
 187                gettimeofday(&stv, &tz);
 188                if (poll(&pfd, 1, -1) < 0)
 189                        fprintf(stderr, "hpet_poll: poll failed\n");
 190                else {
 191                        long    data;
 192
 193                        gettimeofday(&etv, &tz);
 194                        usec = stv.tv_sec * 1000000 + stv.tv_usec;
 195                        usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
 196
 197                        fprintf(stderr,
 198                                "hpet_poll: expired time = 0x%lx\n", usec);
 199
 200                        fprintf(stderr, "hpet_poll: revents = 0x%x\n",
 201                                pfd.revents);
 202
 203                        if (read(fd, &data, sizeof(data)) != sizeof(data)) {
 204                                fprintf(stderr, "hpet_poll: read failed\n");
 205                        }
 206                        else
 207                                fprintf(stderr, "hpet_poll: data 0x%lx\n",
 208                                        data);
 209                }
 210        }
 211
 212out:
 213        close(fd);
 214        return;
 215}
 216
 217static int hpet_sigio_count;
 218
 219static void
 220hpet_sigio(int val)
 221{
 222        fprintf(stderr, "hpet_sigio: called\n");
 223        hpet_sigio_count++;
 224}
 225
 226void
 227hpet_fasync(int argc, const char **argv)
 228{
 229        unsigned long           freq;
 230        int                     iterations, i, fd, value;
 231        sig_t                   oldsig;
 232        struct hpet_info        info;
 233
 234        hpet_sigio_count = 0;
 235        fd = -1;
 236
 237        if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
 238                fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
 239                return;
 240        }
 241
 242        if (argc != 3) {
 243                fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
 244                goto out;
 245        }
 246
 247        fd = open(argv[0], O_RDONLY);
 248
 249        if (fd < 0) {
 250                fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
 251                return;
 252        }
 253
 254
 255        if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
 256                ((value = fcntl(fd, F_GETFL)) == 1) ||
 257                (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
 258                fprintf(stderr, "hpet_fasync: fcntl failed\n");
 259                goto out;
 260        }
 261
 262        freq = atoi(argv[1]);
 263        iterations = atoi(argv[2]);
 264
 265        if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
 266                fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
 267                goto out;
 268        }
 269
 270        if (ioctl(fd, HPET_INFO, &info) < 0) {
 271                fprintf(stderr, "hpet_fasync: failed to get info\n");
 272                goto out;
 273        }
 274
 275        fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
 276
 277        if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
 278                fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
 279                goto out;
 280        }
 281
 282        if (ioctl(fd, HPET_IE_ON, 0) < 0) {
 283                fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
 284                goto out;
 285        }
 286
 287        for (i = 0; i < iterations; i++) {
 288                (void) pause();
 289                fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
 290        }
 291
 292out:
 293        signal(SIGIO, oldsig);
 294
 295        if (fd >= 0)
 296                close(fd);
 297
 298        return;
 299}
 300