diff --git a/headers/private/kernel/arch/x86/arch_hpet.h b/headers/private/kernel/arch/x86/arch_hpet.h new file mode 100644 index 0000000000..b06cfecb2e --- /dev/null +++ b/headers/private/kernel/arch/x86/arch_hpet.h @@ -0,0 +1,104 @@ +/* + * 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 + +/* 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_ID 0x000000FF +#define HPET_CAP_MASK_NUMTIMERS 0x00001F00 +#define HPET_CAP_MASK_WIDTH 0x00002000 +#define HPET_CAP_MASK_LEGACY 0x00008000 +#define HPET_CAP_MASK_VENDOR_ID 0xFFFF0000 + +/* Retrieve Global Capabilities */ +#define HPET_GET_ID(regs) ((regs)->capability & HPET_CAP_MASK_ID) +#define HPET_GET_NUM_TIMERS(regs) (((regs)->capability & HPET_CAP_MASK_NUMTIMERS) >> 8) +#define HPET_IS_64BIT(regs) (((regs)->capability & HPET_CAP_MASK_WIDTH) >> 13) +#define HPET_IS_LEGACY_CAPABLE(regs) (((regs)->capability & HPET_CAP_MASK_LEGACY) >> 15) +#define HPET_GET_VENDOR_ID(regs) (((regs)->capability & HPET_CAP_MASK_VENDOR_ID) >> 16) + +/* 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) + +#define ACPI_HPET_SIGNATURE "HPET" + +struct hpet_timer { + /* Timer Configuration/Capability bits, Reversed because x86 is LSB */ + volatile uint32 config; + volatile uint32 interrupts; /* Each bit represents one allowed interrupt for this timer. */ + /* Read Only. If interrupt 16 is allowed, bit 16 will be 1. */ + + volatile uint64 comparator; /* Comparator value */ + /* non-periodic mode: fires once when main counter = this comparator */ + /* periodic mode: fires when timer reaches this value, is increased by the original value */ + + /* FSB Interrupt Route values */ + volatile uint32 fsb_value; + volatile uint32 fsb_addr; /* Where fsb_value should be written */ + + volatile uint64 reserved; +}; + + +struct hpet_regs { + /* Capability bits */ + volatile uint32 period; + volatile uint32 capability; /* Capabilities */ + + volatile uint64 reserved1; + + /* Config Bits */ + volatile uint64 config; + + volatile uint64 reserved2; + + /* Interrupt Status bits */ + volatile uint64 timer_interrupts; /* 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 uint8 reserved3[200]; + + volatile uint64 counter; + + volatile uint64 reserved4; + + volatile struct hpet_timer timer0; + volatile struct hpet_timer timer1; + volatile struct hpet_timer timer2; +}; + + +typedef struct acpi_hpet { + acpi_descriptor_header header; /* "HPET" signature and acpi header */ + uint16 vendor_id; + uint8 legacy_capable : 1; + uint8 reserved1 : 1; + uint8 countersize : 1; + uint8 comparators : 5; + uint8 hw_revision; + struct hpet_addr { + uint8 address_space; + uint8 register_width; + uint8 register_offset; + uint8 reserved; + uint64 address; + } hpet_address; + uint8 number; + uint16 min_tick; +} _PACKED acpi_hpet; + +#endif diff --git a/src/system/boot/platform/bios_ia32/Jamfile b/src/system/boot/platform/bios_ia32/Jamfile index a60f82c1f1..889458ed8c 100644 --- a/src/system/boot/platform/bios_ia32/Jamfile +++ b/src/system/boot/platform/bios_ia32/Jamfile @@ -35,6 +35,7 @@ KernelMergeObject boot_platform_bios_ia32.o : support.S video.cpp apm.cpp + hpet.cpp # generic text_menu.cpp diff --git a/src/system/boot/platform/bios_ia32/hpet.cpp b/src/system/boot/platform/bios_ia32/hpet.cpp new file mode 100644 index 0000000000..42568d214b --- /dev/null +++ b/src/system/boot/platform/bios_ia32/hpet.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. +*/ + + +#include "mmu.h" +#include "acpi.h" +#include "hpet.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define TRACE_HPET +#ifdef TRACE_HPET +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + +void +hpet_init(void) +{ + // Try to find the HPET ACPI table. + TRACE(("hpet_init: Looking for HPET...\n")); + acpi_hpet *hpet = (acpi_hpet *)acpi_find_table(ACPI_HPET_SIGNATURE); + + if (hpet == NULL) { + // No HPET table in the RSDT. + // Since there are no other methods for finding it, + // assume we don't have one. + TRACE(("hpet_init: HPET not found.\n")); + gKernelArgs.arch_args.hpet_phys = 0; + gKernelArgs.arch_args.hpet = NULL; + return; + } + + TRACE(("hpet_init: found HPET at %x.\n", hpet->hpet_address.address)); + gKernelArgs.arch_args.hpet_phys = hpet->hpet_address.address; + gKernelArgs.arch_args.hpet = (uint32 *)mmu_map_physical_memory( + gKernelArgs.arch_args.hpet_phys, B_PAGE_SIZE, kDefaultPageFlags); +} diff --git a/src/system/boot/platform/bios_ia32/hpet.h b/src/system/boot/platform/bios_ia32/hpet.h new file mode 100644 index 0000000000..124eef7fc8 --- /dev/null +++ b/src/system/boot/platform/bios_ia32/hpet.h @@ -0,0 +1,21 @@ +/* + * Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef HPET_H +#define HPET_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void hpet_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* HPET_H */ diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index 650925691a..4f59a9dfec 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -11,6 +11,7 @@ #include "smp.h" #include "mmu.h" #include "acpi.h" +#include "hpet.h" #include diff --git a/src/system/boot/platform/bios_ia32/start.c b/src/system/boot/platform/bios_ia32/start.c index d1c28599c5..85fa14b75f 100644 --- a/src/system/boot/platform/bios_ia32/start.c +++ b/src/system/boot/platform/bios_ia32/start.c @@ -138,6 +138,7 @@ _start(void) apm_init(); acpi_init(); smp_init(); + //hpet_init(); // TODO: Not yet main(&args); } diff --git a/src/system/kernel/arch/x86/timers/hpet.h b/src/system/kernel/arch/x86/timers/hpet.h index ff49700a2e..f7fe1bef7f 100644 --- a/src/system/kernel/arch/x86/timers/hpet.h +++ b/src/system/kernel/arch/x86/timers/hpet.h @@ -7,53 +7,6 @@ #include -/* All masks are 64 bits wide to represent bit locations; - the HPET registers are 64 bits wide. */ - -/* Global Capability Register Masks */ -#define HPET_CAP_MASK_ID 0x00000000000000FF -#define HPET_CAP_MASK_NUMTIMERS 0x0000000000001F00 -#define HPET_CAP_MASK_WIDTH 0x0000000000002000 -#define HPET_CAP_MASK_LEGACY 0x0000000000008000 -#define HPET_CAP_MASK_VENDOR_ID 0x00000000FFFF0000 -#define HPET_CAP_MASK_PERIOD 0xFFFFFFFF00000000 - -/* Convenience macros for Capability masks */ -#define HPET_GET_ID(regs) ((regs)->caps & HPET_CAP_MASK_ID) -#define HPET_GET_NUM_TIMERS(regs) (((regs)->caps & HPET_CAP_MASK_NUMTIMERS) >> 8) -#define HPET_IS_64BIT_CAPABLE(regs) (((regs)->caps & HPET_CAP_MASK_WIDTH) >> 13) -#define HPET_IS_LEGACY_CAPABLE(regs) (((regs)->caps & HPET_CAP_MASK_LEGACY) >> 15) -#define HPET_GET_VENDOR_ID(regs) (((regs)->caps & HPET_CAP_MASK_VENDOR_ID) >> 16) -#define HPET_GET_PERIOD(regs) (((regs)->caps & HPET_CAP_MASK_PERIOD) >> 32) - -/* Global Configuration Masks */ -#define HPET_CONF_MASK_ENABLED 0x0000000000000001 -#define HPET_CONF_MASK_LEGACY 0x0000000000000002 - -/* Convenience macros for Config masks */ -#define HPET_IS_ENABLED(regs) ((regs)->config & HPET_CONF_MASK_ENABLED) -#define HPET_IS_LEGACY(regs) (((regs)->config & HPET_CONF_MASK_LEGACY) >> 1) - -struct hpet_timer { - uint64 config; /* Timer configuration and capabilities */ - uint64 comparator; /* Comparator value */ - uint64 introute; /* FSB Interrupt Routing */ - uint64 reserved; -}; - - -struct hpet_regs { - uint64 caps; /* HPET Capabilities and ID */ - uint64 reserved1; - uint64 config; /* General Configuration */ - uint64 reserved2; - uint64 intstatus; /* General Interrupt Status */ - uint8 reserved3[200]; - uint64 mainvalue; /* Main Counter Value */ - uint64 reserved4; - struct hpet_timer timers[1]; /* Timers */ -}; - /* Method prototypes */ static int hpet_get_prio(void); static status_t hpet_set_hardware_timer(bigtime_t relativeTimeout);