/*- * Copyright (c) 2011 Jung-uk Kim * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include static __inline uint32_t read32(caddr_t addr, u_int reg) { return (*(volatile uint32_t *)(addr + reg)); } static __inline uint64_t read64(caddr_t addr, u_int reg) { #ifdef __i386__ uint32_t high, low; do { high = read32(addr, reg + 4); low = read32(addr, reg); } while (high != read32(addr, reg + 4)); return (((uint64_t)high << 32) | low); #else return (*(volatile uint64_t *)(addr + reg)); #endif } int main(void) { uint64_t hpet64[10]; uint32_t hpet32[10]; caddr_t addr; uint32_t cap, cfg, prd; int fd, i; fd = open("/dev/hpet", O_RDONLY); if (fd < 0) { perror("open()"); exit (1); } addr = mmap(NULL, HPET_MEM_WIDTH, PROT_READ, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { perror("mmap()"); exit (1); } cap = read32(addr, HPET_CAPABILITIES); printf("HPET capabilities:\t0x%08x\n", cap); printf("\tVendor ID:\t0x%04x\n", (cap & HPET_CAP_VENDOR_ID) >> 16); printf("\tLegacy Route:\t%s\n", (cap & HPET_CAP_LEG_RT) != 0 ? "yes" : "no"); printf("\tCounter Width:\t%s-bit\n", (cap & HPET_CAP_COUNT_SIZE) != 0 ? "64" : "32"); printf("\tNo. of Timers:\t%u\n", ((cap & HPET_CAP_NUM_TIM) >> 8) + 1); printf("\tRevision ID:\t%u\n", cap & HPET_CAP_REV_ID); printf("\n"); prd = read32(addr, HPET_PERIOD); printf("HPET period:\t\t0x%08x\n", prd); printf("\tFrequency:\t%llu Hz\n", (1000000000000000ULL + prd / 2) / prd); printf("\n"); cfg = read32(addr, HPET_CONFIG); printf("HPET configuration:\t0x%08x\n", cfg); printf("\tLegacy Route:\t%s\n", (cfg & HPET_CNF_LEG_RT) != 0 ? "yes" : "no"); printf("\tHPET Enabled:\t%s\n", (cfg & HPET_CNF_ENABLE) != 0 ? "yes" : "no"); printf("\n"); printf("HPET main counter (32 bits):\n"); for (i = 0; i < 10; i++) hpet32[i] = read32(addr, HPET_MAIN_COUNTER); printf("\t0x%08x\n", hpet32[0]); for (i = 1; i < 10; i++) printf("\t0x%08x (offset %d)\n", hpet32[i], i > 0 ? hpet32[i] - hpet32[i - 1] : 0); printf("\n"); printf("HPET main counter (64 bits):\n"); for (i = 0; i < 10; i++) hpet64[i] = read64(addr, HPET_MAIN_COUNTER); printf("\t0x%016jx\n", (uintmax_t)hpet64[0]); for (i = 1; i < 10; i++) printf("\t0x%016jx (offset %jd)\n", (uintmax_t)hpet64[i], i > 0 ? (uintmax_t)(hpet64[i] - hpet64[i - 1]) : 0); munmap(addr, HPET_MEM_WIDTH); close(fd); return (0); }