root/headers/private/kernel/arch/x86/arch_hpet.h
/*
 * Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
 * Distributed under the terms of the MIT License.
 */
#ifndef _KERNEL_ARCH_x86_HPET_H
#define _KERNEL_ARCH_x86_HPET_H

#include <acpi.h>

/* All masks are 32 bits wide to represent relative bit locations */
/* Doing it this way is Required since the HPET only supports 32/64-bit aligned reads. */

/* Global Capability Register Masks */
#define HPET_CAP_MASK_REVID                     0x00000000000000FFULL
#define HPET_CAP_MASK_NUMTIMERS                 0x0000000000001F00ULL
#define HPET_CAP_MASK_WIDTH                     0x0000000000002000ULL
#define HPET_CAP_MASK_LEGACY                    0x0000000000008000ULL
#define HPET_CAP_MASK_VENDOR_ID                 0x00000000FFFF0000ULL
#define HPET_CAP_MASK_PERIOD                    0xFFFFFFFF00000000ULL

/* Retrieve Global Capabilities */
#define HPET_GET_REVID(regs)            ((regs)->capabilities & HPET_CAP_MASK_REVID)
#define HPET_GET_NUM_TIMERS(regs)       (((regs)->capabilities & HPET_CAP_MASK_NUMTIMERS) >> 8)
#define HPET_IS_64BIT(regs)             (((regs)->capabilities & HPET_CAP_MASK_WIDTH) >> 13)
#define HPET_IS_LEGACY_CAPABLE(regs)    (((regs)->capabilities & HPET_CAP_MASK_LEGACY) >> 15)
#define HPET_GET_VENDOR_ID(regs)        (((regs)->capabilities & HPET_CAP_MASK_VENDOR_ID) >> 16)
#define HPET_GET_PERIOD(regs)           (((regs)->capabilities & HPET_CAP_MASK_PERIOD) >> 32)

/* Global Config Register Masks */
#define HPET_CONF_MASK_ENABLED                  0x00000001
#define HPET_CONF_MASK_LEGACY                   0x00000002

/* Retrieve Global Configuration */
#define HPET_IS_ENABLED(regs)           ((regs)->config & HPET_CONF_MASK_ENABLED)
#define HPET_IS_LEGACY(regs)            (((regs)->config & HPET_CONF_MASK_LEGACY) >> 1)

/* Timer Configuration and Capabilities*/
#define HPET_CAP_TIMER_MASK                     0xFFFFFFFF00000000ULL
#define HPET_CONF_TIMER_INT_ROUTE_MASK          0x3e00UL
#define HPET_CONF_TIMER_INT_ROUTE_SHIFT         9       
#define HPET_CONF_TIMER_INT_TYPE                0x00000002UL
#define HPET_CONF_TIMER_INT_ENABLE              0x00000004UL
#define HPET_CONF_TIMER_TYPE                    0x00000008UL
#define HPET_CONF_TIMER_VAL_SET                 0x00000040UL
#define HPET_CONF_TIMER_32MODE                  0x00000100UL
#define HPET_CONF_TIMER_FSB_ENABLE              0x00004000UL
#define HPET_CAP_TIMER_PER_INT                  0x00000010UL
#define HPET_CAP_TIMER_SIZE                     0x00000020UL
#define HPET_CAP_TIMER_FSB_INT_DEL              0x00008000UL

#define HPET_GET_CAP_TIMER_ROUTE(timer)         (((timer)->config & HPET_CAP_TIMER_MASK) >> 32)
#define HPET_GET_CONF_TIMER_INT_ROUTE(timer)    (((timer)->config & HPET_CONF_TIMER_INT_ROUTE_MASK) >> HPET_CONF_TIMER_INT_ROUTE_SHIFT)

#define ACPI_HPET_SIGNATURE                     "HPET"

struct hpet_timer {
        /* Timer Configuration/Capability bits, Reversed because x86 is LSB */  
        volatile uint64 config;
                                        /* R/W: Each bit represents one allowed interrupt for this timer. */
                                        /* If interrupt 16 is allowed, bit 16 will be 1. */
        union { 
                volatile uint64 comparator64;   /* R/W: Comparator value */
                volatile uint32 comparator32;   
        } u0;                           /* non-periodic mode: fires once when main counter = this comparator */
                                        /* periodic mode: fires when timer reaches this value, is increased by the original value */
        
        volatile uint64 fsb_route[2];   /* R/W: FSB Interrupt Route values */
};


struct hpet_regs {
        volatile uint64 capabilities;           /* Read Only */ 
        
        volatile uint64 reserved1;

        volatile uint64 config;                 /* R/W: Config Bits */

        volatile uint64 reserved2;

        /* Interrupt Status bits */
        volatile uint64 interrupt_status;       /* Interrupt Config bits for timers 0-31 */
                                                /* Level Tigger: 0 = off, 1 = set by hardware, timer is active */
                                                /* Edge Trigger: ignored */
                                                /* Writing 0 will not clear these. Must write 1 again. */
        volatile uint64 reserved3[25];

        union {
                volatile uint64 counter64;      /* R/W */
                volatile uint32 counter32;
        } u0;

        volatile uint64 reserved4;

        volatile struct hpet_timer timer[1];
};


typedef struct acpi_hpet_addr {
        uint8   address_space;
        uint8   register_width;
        uint8   register_offset;
        uint8   reserved;
        uint64  address;
} _PACKED acpi_hpet_addr;


typedef struct acpi_hpet {
        acpi_descriptor_header  header; /* "HPET" signature and acpi header */
        uint8   hw_revision;
        uint8   comparators : 5;
        uint8   countersize : 1;
        uint8   reserved1 : 1;
        uint8   legacy_capable : 1;
        uint16  vendor_id;
        acpi_hpet_addr hpet_address;
        uint8   number;
        uint16  min_tick;
} _PACKED acpi_hpet;

#endif