[haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- From: "Dustin Howett" <alaricx@xxxxxxxxx>
- To: haiku-gsoc@xxxxxxxxxxxxx
- Date: Fri, 4 Jul 2008 13:29:36 -0400
On Fri, Jul 4, 2008 at 1:25 PM, Dustin Howett <alaricx@xxxxxxxxx> wrote:
>
> Here's the patch for that. Rev. 10 :)
>
Last try. The original patch was malformed because I attempted to
correct it in nano and didn't fix the line numbers.
- Dustin
Index: src/system/kernel/arch/x86/arch_timer.c
===================================================================
--- src/system/kernel/arch/x86/arch_timer.c (revision 26244)
+++ src/system/kernel/arch/x86/arch_timer.c (working copy)
@@ -32,60 +32,24 @@
# define TRACE(x) ;
#endif
+extern timer_info gPITTimer;
+extern timer_info gAPICTimer;
+extern timer_info gHPETTimer;
-#define PIT_CLOCK_RATE 1193180
-#define PIT_MAX_TIMER_INTERVAL (0xffff * 1000000ll / PIT_CLOCK_RATE)
+static timer_info *sTimers[] = {
+ &gPITTimer,
+ &gAPICTimer,
+ &gHPETTimer,
+ NULL
+};
+static timer_info *sTimer = NULL;
-static void
-set_isa_hardware_timer(bigtime_t relative_timeout)
-{
- uint16 next_event_clocks;
-
- if (relative_timeout <= 0)
- next_event_clocks = 2;
- else if (relative_timeout < PIT_MAX_TIMER_INTERVAL)
- next_event_clocks = relative_timeout * PIT_CLOCK_RATE / 1000000;
- else
- next_event_clocks = 0xffff;
-
- out8(0x30, 0x43);
- out8(next_event_clocks & 0xff, 0x40);
- out8((next_event_clocks >> 8) & 0xff, 0x40);
-
- arch_int_enable_io_interrupt(0);
-}
-
-
-static void
-clear_isa_hardware_timer(void)
-{
- // mask out the timer
- arch_int_disable_io_interrupt(0);
-}
-
-
-static int32
-isa_timer_interrupt(void *data)
-{
- return timer_interrupt();
-}
-
-
-int
-apic_timer_interrupt(void)
-{
- return timer_interrupt();
-}
-
-
void
arch_timer_set_hardware_timer(bigtime_t timeout)
{
TRACE(("arch_timer_set_hardware_timer: timeout %lld\n", timeout));
- // try the apic timer first
- if (arch_smp_set_apic_timer(timeout) != B_OK)
- set_isa_hardware_timer(timeout);
+ sTimer->set_hardware_timer(timeout);
}
@@ -93,21 +57,42 @@
arch_timer_clear_hardware_timer(void)
{
TRACE(("arch_timer_clear_hardware_timer\n"));
- if (arch_smp_clear_apic_timer() != B_OK)
- clear_isa_hardware_timer();
+ sTimer->clear_hardware_timer();
}
int
arch_init_timer(kernel_args *args)
{
- //dprintf("arch_init_timer: entry\n");
+ int i = 0;
+ int bestPriority = -1;
+ timer_info *timer = NULL;
+ cpu_status state = disable_interrupts();
- install_io_interrupt_handler(0, &isa_timer_interrupt, NULL, 0);
- clear_isa_hardware_timer();
+ for (i = 0; (timer = sTimers[i]) != NULL; i++) {
+ int priority;
+ if (timer->init(args) != B_OK) {
+ TRACE(("arch_init_timer: %s failed init. Skipping.\n",
timer->name));
+ continue;
+ }
- // apic timer interrupt set up by smp code
+ priority = timer->get_priority();
+ if (priority > bestPriority) {
+ bestPriority = priority;
+ sTimer = timer;
+ TRACE(("arch_init_timer: %s is now best timer module
with prio %d.\n", timer->name, bestPriority));
+ }
+ }
+
+ if (sTimer != NULL) {
+ dprintf("arch_init_timer: using %s timer.\n", sTimer->name);
+ } else {
+ panic("No system timers were found usable.\n");
+ }
+
+ restore_interrupts(state);
+
return 0;
}
Index: src/system/kernel/arch/x86/timers/pit.h
===================================================================
--- src/system/kernel/arch/x86/timers/pit.h (revision 0)
+++ src/system/kernel/arch/x86/timers/pit.h (revision 0)
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2008, Dustin Howett, dustin.howett@xxxxxxxxxx All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _KERNEL_ARCH_x86_TIMERS_PIT_H
+#define _KERNEL_ARCH_x86_TIMERS_PIT_H
+
+#include <SupportDefs.h>
+
+/* Method Prototypes */
+static int pit_get_prio(void);
+static status_t pit_set_hardware_timer(bigtime_t relativeTimeout);
+static status_t pit_clear_hardware_timer(void);
+static status_t pit_init(struct kernel_args *args);
+
+#endif /* _KERNEL_ARCH_x86_TIMERS_PIT_H */
Index: src/system/kernel/arch/x86/timers/x86_pit.c
===================================================================
--- src/system/kernel/arch/x86/timers/x86_pit.c (revision 0)
+++ src/system/kernel/arch/x86/timers/x86_pit.c (revision 0)
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2008, Dustin Howett, dustin.howett@xxxxxxxxxx All rights reserved.
+ * Copyright 2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx 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 <timer.h>
+#include <arch/x86/timer.h>
+
+#include <arch/int.h>
+#include <arch/cpu.h>
+
+#include "pit.h"
+
+#define PIT_CLOCK_RATE 1193180
+#define PIT_MAX_TIMER_INTERVAL (0xffff * 1000000ll / PIT_CLOCK_RATE)
+
+static bool sPITTimerInitialized = false;
+
+struct timer_info gPITTimer = {
+ "PIT",
+ &pit_get_prio,
+ &pit_set_hardware_timer,
+ &pit_clear_hardware_timer,
+ &pit_init
+};
+
+
+static int
+pit_get_prio(void)
+{
+ return 1;
+}
+
+
+static int32
+pit_timer_interrupt(void *data)
+{
+ return timer_interrupt();
+}
+
+
+static status_t
+pit_set_hardware_timer(bigtime_t relativeTimeout)
+{
+ uint16 nextEventClocks;
+
+ if (relativeTimeout <= 0)
+ nextEventClocks = 2;
+ else if (relativeTimeout < PIT_MAX_TIMER_INTERVAL)
+ nextEventClocks = relativeTimeout * PIT_CLOCK_RATE / 1000000;
+ else
+ nextEventClocks = 0xffff;
+
+ out8(0x30, 0x43);
+ out8(nextEventClocks & 0xff, 0x40);
+ out8((nextEventClocks >> 8) & 0xff, 0x40);
+
+ arch_int_enable_io_interrupt(0);
+ return B_OK;
+}
+
+
+static status_t
+pit_clear_hardware_timer(void)
+{
+ arch_int_disable_io_interrupt(0);
+ return B_OK;
+}
+
+
+static status_t
+pit_init(struct kernel_args *args)
+{
+ if (sPITTimerInitialized) {
+ return B_OK;
+ }
+
+ install_io_interrupt_handler(0, &pit_timer_interrupt, NULL, 0);
+ pit_clear_hardware_timer();
+
+ sPITTimerInitialized = true;
+
+ return B_OK;
+}
Index: src/system/kernel/arch/x86/timers/apic.h
===================================================================
--- src/system/kernel/arch/x86/timers/apic.h (revision 0)
+++ src/system/kernel/arch/x86/timers/apic.h (revision 0)
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2008, Dustin Howett, dustin.howett@xxxxxxxxxx All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _KERNEL_ARCH_x86_TIMERS_APIC_H
+#define _KERNEL_ARCH_x86_TIMERS_APIC_H
+
+#include <SupportDefs.h>
+
+/* Method Prototypes */
+static int apic_get_prio(void);
+static status_t apic_set_hardware_timer(bigtime_t relativeTimeout);
+static status_t apic_clear_hardware_timer(void);
+static status_t apic_init(struct kernel_args *args);
+status_t apic_smp_init_timer(struct kernel_args *args, int32 cpu);
+
+#endif /* _KERNEL_ARCH_x86_TIMERS_APIC_H */
Index: src/system/kernel/arch/x86/timers/x86_apic.c
===================================================================
--- src/system/kernel/arch/x86/timers/x86_apic.c (revision 0)
+++ src/system/kernel/arch/x86/timers/x86_apic.c (revision 0)
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2008, Dustin Howett, dustin.howett@xxxxxxxxxx All rights reserved.
+ * Copyright 2002-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights
reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
+ * Distributed under the terms of the NewOS License.
+ */
+
+#include <timer.h>
+#include <arch/x86/timer.h>
+
+#include <int.h>
+#include <arch/x86/smp_apic.h>
+
+#include <arch/cpu.h>
+#include <arch/smp.h>
+
+#include "apic.h"
+
+static void *sApicPtr = NULL;
+static uint32 sApicTicsPerSec = 0;
+
+struct timer_info gAPICTimer = {
+ "APIC",
+ &apic_get_prio,
+ &apic_set_hardware_timer,
+ &apic_clear_hardware_timer,
+ &apic_init
+};
+
+
+static int
+apic_get_prio(void)
+{
+ return 2;
+}
+
+
+static uint32
+_apic_read(uint32 offset)
+{
+ return *(volatile uint32 *)((char *)sApicPtr + offset);
+}
+
+
+static void
+_apic_write(uint32 offset, uint32 data)
+{
+ *(volatile uint32 *)((char *)sApicPtr + offset) = data;
+}
+
+
+static void
+_apic_acknowledge_interrupt(void)
+{
+ _apic_write(APIC_EOI, 0);
+}
+
+
+static int32
+apic_timer_interrupt(void *data)
+{
+ _apic_acknowledge_interrupt();
+ return timer_interrupt();
+}
+
+
+#define MIN_TIMEOUT 1000
+
+static status_t
+apic_set_hardware_timer(bigtime_t relativeTimeout)
+{
+ cpu_status state;
+ uint32 config;
+ uint32 ticks;
+
+ if (sApicPtr == NULL)
+ return B_ERROR;
+
+ if (relativeTimeout < MIN_TIMEOUT)
+ relativeTimeout = MIN_TIMEOUT;
+
+ // calculation should be ok, since it's going to be 64-bit
+ ticks = ((relativeTimeout * sApicTicsPerSec) / 1000000);
+
+ state = disable_interrupts();
+
+ config = _apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; // mask the timer
+ _apic_write(APIC_LVT_TIMER, config);
+
+ _apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer
+
+ config = _apic_read(APIC_LVT_TIMER) & ~APIC_LVT_MASKED; // unmask the
timer
+ _apic_write(APIC_LVT_TIMER, config);
+
+ //TRACE_TIMER(("arch_smp_set_apic_timer: config 0x%lx, timeout %Ld,
tics/sec %lu, tics %lu\n",
+ // config, relativeTimeout, sApicTicsPerSec, ticks));
+
+ _apic_write(APIC_INITIAL_TIMER_COUNT, ticks); // start it up
+
+ restore_interrupts(state);
+
+ return B_OK;
+}
+
+
+static status_t
+apic_clear_hardware_timer(void)
+{
+ cpu_status state;
+ uint32 config;
+
+ if (sApicPtr == NULL)
+ return B_ERROR;
+
+ state = disable_interrupts();
+
+ config = _apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; // mask the timer
+ _apic_write(APIC_LVT_TIMER, config);
+
+ _apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer
+
+ restore_interrupts(state);
+ return B_OK;
+}
+
+
+static status_t
+apic_init(struct kernel_args *args)
+{
+ /* If we're in this method, arch_smp called the special init function.
+ Therefore, if we got here with sApicPtr NULL, there is no APIC! */
+ if (sApicPtr == NULL)
+ return B_ERROR;
+
+ return B_OK;
+}
+
+
+status_t
+apic_smp_init_timer(struct kernel_args *args, int32 cpu)
+{
+ uint32 config;
+
+ if (args->arch_args.apic == NULL) {
+ return B_ERROR;
+ }
+
+ /* This is in place of apic_preinit; if we're not already initialized,
+ register the interrupt handler and set the pointers */
+ if (sApicPtr == NULL) {
+ sApicPtr = (void *)args->arch_args.apic;
+ sApicTicsPerSec = args->arch_args.apic_time_cv_factor;
+ install_io_interrupt_handler(0xfb - ARCH_INTERRUPT_BASE,
&apic_timer_interrupt, NULL, B_NO_LOCK_VECTOR);
+ }
+
+ /* setup timer */
+ config = _apic_read(APIC_LVT_TIMER) & APIC_LVT_TIMER_MASK;
+ config |= 0xfb | APIC_LVT_MASKED; // vector 0xfb, timer masked
+ _apic_write(APIC_LVT_TIMER, config);
+
+ _apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the clock
+
+ config = _apic_read(APIC_TIMER_DIVIDE_CONFIG) & 0xfffffff0;
+ config |= APIC_TIMER_DIVIDE_CONFIG_1; // clock division by 1
+ _apic_write(APIC_TIMER_DIVIDE_CONFIG, config);
+
+ return B_OK;
+}
Index: src/system/kernel/arch/x86/timers/hpet.h
===================================================================
--- src/system/kernel/arch/x86/timers/hpet.h (revision 0)
+++ src/system/kernel/arch/x86/timers/hpet.h (revision 0)
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008, Dustin Howett, dustin.howett@xxxxxxxxxx All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _KERNEL_ARCH_x86_TIMERS_HPET_H
+#define _KERNEL_ARCH_x86_TIMERS_HPET_H
+
+#include <SupportDefs.h>
+
+/* 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);
+static status_t hpet_clear_hardware_timer(void);
+static status_t hpet_init(struct kernel_args *args);
+
+#endif /* _KERNEL_ARCH_x86_TIMERS_HPET_H */
Index: src/system/kernel/arch/x86/timers/x86_hpet.c
===================================================================
--- src/system/kernel/arch/x86/timers/x86_hpet.c (revision 0)
+++ src/system/kernel/arch/x86/timers/x86_hpet.c (revision 0)
@@ -0,0 +1,89 @@
+
+/*
+ * Copyright 2008, Dustin Howett, dustin.howett@xxxxxxxxxx All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+
+#include <timer.h>
+#include <arch/x86/timer.h>
+
+#include "hpet.h"
+
+static int32 sHPETAddr;
+static struct hpet_regs *sHPETRegs;
+
+struct timer_info gHPETTimer = {
+ "HPET",
+ &hpet_get_prio,
+ &hpet_set_hardware_timer,
+ &hpet_clear_hardware_timer,
+ &hpet_init
+};
+
+
+static int
+hpet_get_prio(void)
+{
+ return 3;
+}
+
+
+/* TODO: Implement something similar to smp_acpi_probe from boot/.../smp.cpp-
+ we need to get the hpet base address without talking to the acpi module,
+ because there's no guarantee that it's actually present at this early
point. */
+
+static int
+hpet_set_enabled(struct hpet_regs *regs, bool enabled)
+{
+ if (enabled)
+ regs->config |= HPET_CONF_MASK_ENABLED;
+ else
+ regs->config &= ~HPET_CONF_MASK_ENABLED;
+ return B_OK;
+}
+
+
+static int
+hpet_set_legacy(struct hpet_regs *regs, bool enabled)
+{
+ if (!HPET_IS_LEGACY_CAPABLE(regs))
+ return B_NOT_SUPPORTED;
+
+ if (enabled)
+ regs->config |= HPET_CONF_MASK_LEGACY;
+ else
+ regs->config &= ~HPET_CONF_MASK_LEGACY;
+ return B_OK;
+}
+
+
+static int32
+hpet_timer_interrupt(void *data)
+{
+ return timer_interrupt();
+}
+
+
+static status_t
+hpet_set_hardware_timer(bigtime_t relative_timeout)
+{
+ return B_ERROR;
+}
+
+
+static status_t
+hpet_clear_hardware_timer(void)
+{
+ return B_ERROR;
+}
+
+
+static status_t
+hpet_init(struct kernel_args *args)
+{
+ /* hpet_acpi_probe() through a similar "scan spots" table to that of
smp.cpp.
+ Seems to be the most elegant solution right now. */
+
+ /* There is no hpet support proper, so error out on init */
+ return B_ERROR;
+}
Index: src/system/kernel/arch/x86/Jamfile
===================================================================
--- src/system/kernel/arch/x86/Jamfile (revision 26244)
+++ src/system/kernel/arch/x86/Jamfile (working copy)
@@ -4,18 +4,20 @@
# for syscall_numbers.h
SubDirHdrs $(HAIKU_TOP) src add-ons kernel bus_managers ps2 ;
SubDirHdrs $(SUBDIR) $(DOTDOT) generic ;
+SubDirHdrs $(SUBDIR) timers ;
UsePrivateKernelHeaders ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
+SEARCH_SOURCE += [ FDirName $(SUBDIR) timers ] ;
+
KernelMergeObject kernel_arch_x86.o :
arch_commpage.cpp
arch_cpu.c
arch_debug.cpp
arch_debug_console.c
arch_elf.c
- arch_hpet.c
arch_int.c
arch_platform.c
# arch_selector.c
@@ -35,6 +37,10 @@
cpuid.S
syscall.S
vm86.cpp
+
+ x86_pit.c
+ x86_apic.c
+ x86_hpet.c
generic_vm_physical_page_mapper.cpp
:
Index: src/system/kernel/arch/x86/arch_smp.c
===================================================================
--- src/system/kernel/arch/x86/arch_smp.c (revision 26244)
+++ src/system/kernel/arch/x86/arch_smp.c (working copy)
@@ -17,6 +17,8 @@
#include <arch/vm.h>
#include <arch/smp.h>
+#include <timer.h>
+
#include <arch/x86/smp_priv.h>
#include <arch/x86/smp_apic.h>
#include <arch/x86/timer.h>
@@ -39,25 +41,15 @@
# define TRACE_TIMER(x) ;
#endif
+extern timer_info gAPICTimer;
static void *apic = NULL;
static uint32 cpu_apic_id[B_MAX_CPU_COUNT] = {0, 0};
static uint32 cpu_os_id[B_MAX_CPU_COUNT] = {0, 0};
static uint32 cpu_apic_version[B_MAX_CPU_COUNT] = {0, 0};
static void *ioapic = NULL;
-static uint32 apic_timer_tics_per_sec = 0;
-
static int32
-i386_timer_interrupt(void *data)
-{
- arch_smp_ack_interrupt();
-
- return apic_timer_interrupt();
-}
-
-
-static int32
i386_ici_interrupt(void *data)
{
// genuine inter-cpu interrupt
@@ -147,17 +139,8 @@
}
#endif
- /* setup timer */
- config = apic_read(APIC_LVT_TIMER) & APIC_LVT_TIMER_MASK;
- config |= 0xfb | APIC_LVT_MASKED; // vector 0xfb, timer masked
- apic_write(APIC_LVT_TIMER, config);
+ apic_smp_init_timer(args, cpu);
- apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the clock
-
- config = apic_read(APIC_TIMER_DIVIDE_CONFIG) & 0xfffffff0;
- config |= APIC_TIMER_DIVIDE_CONFIG_1; // clock division by 1
- apic_write(APIC_TIMER_DIVIDE_CONFIG, config);
-
/* setup error vector to 0xfe */
config = (apic_read(APIC_LVT_ERROR) & 0xffffff00) | 0xfe;
apic_write(APIC_LVT_ERROR, config);
@@ -185,7 +168,6 @@
memcpy(cpu_apic_id, args->arch_args.cpu_apic_id,
sizeof(args->arch_args.cpu_apic_id));
memcpy(cpu_os_id, args->arch_args.cpu_os_id,
sizeof(args->arch_args.cpu_os_id));
memcpy(cpu_apic_version, args->arch_args.cpu_apic_version,
sizeof(args->arch_args.cpu_apic_version));
- apic_timer_tics_per_sec = args->arch_args.apic_time_cv_factor;
// setup regions that represent the apic & ioapic
map_physical_memory("local apic", (void
*)args->arch_args.apic_phys, B_PAGE_SIZE,
@@ -197,7 +179,6 @@
arch_smp_per_cpu_init(args, 0);
// I/O interrupts start at ARCH_INTERRUPT_BASE, so all
interrupts are shifted
- install_io_interrupt_handler(0xfb - ARCH_INTERRUPT_BASE,
&i386_timer_interrupt, NULL, B_NO_LOCK_VECTOR);
install_io_interrupt_handler(0xfd - ARCH_INTERRUPT_BASE,
&i386_ici_interrupt, NULL, B_NO_LOCK_VECTOR);
install_io_interrupt_handler(0xfe - ARCH_INTERRUPT_BASE,
&i386_smp_error_interrupt, NULL, B_NO_LOCK_VECTOR);
install_io_interrupt_handler(0xff - ARCH_INTERRUPT_BASE,
&i386_spurious_interrupt, NULL, B_NO_LOCK_VECTOR);
@@ -268,63 +249,3 @@
{
apic_write(APIC_EOI, 0);
}
-
-#define MIN_TIMEOUT 1000
-
-status_t
-arch_smp_set_apic_timer(bigtime_t relativeTimeout)
-{
- cpu_status state;
- uint32 config;
- uint32 ticks;
-
- if (apic == NULL)
- return B_ERROR;
-
- if (relativeTimeout < MIN_TIMEOUT)
- relativeTimeout = MIN_TIMEOUT;
-
- // calculation should be ok, since it's going to be 64-bit
- ticks = ((relativeTimeout * apic_timer_tics_per_sec) / 1000000);
-
- state = disable_interrupts();
-
- config = apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; // mask the timer
- apic_write(APIC_LVT_TIMER, config);
-
- apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer
-
- config = apic_read(APIC_LVT_TIMER) & ~APIC_LVT_MASKED; // unmask the
timer
- apic_write(APIC_LVT_TIMER, config);
-
- TRACE_TIMER(("arch_smp_set_apic_timer: config 0x%lx, timeout %Ld,
tics/sec %lu, tics %lu\n",
- config, relativeTimeout, apic_timer_tics_per_sec, ticks));
-
- apic_write(APIC_INITIAL_TIMER_COUNT, ticks); // start it up
-
- restore_interrupts(state);
-
- return B_OK;
-}
-
-
-status_t
-arch_smp_clear_apic_timer(void)
-{
- cpu_status state;
- uint32 config;
-
- if (apic == NULL)
- return B_ERROR;
-
- state = disable_interrupts();
-
- config = apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; // mask the timer
- apic_write(APIC_LVT_TIMER, config);
-
- apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer
-
- restore_interrupts(state);
- return B_OK;
-}
-
Index: src/system/kernel/arch/x86/arch_hpet.c
===================================================================
--- src/system/kernel/arch/x86/arch_hpet.c (working copy)
+++ src/system/kernel/arch/x86/arch_hpet.c (working copy)
@@ -1,6 +0,0 @@
-/*
- * Copyright 2008, Dustin Howett, dustin.howett@xxxxxxxxxx All rights reserved.
- * Distributed under the terms of the MIT License.
- */
-
-#include <arch/x86/arch_hpet.h>
Index: headers/private/kernel/arch/x86/arch_hpet.h
===================================================================
--- headers/private/kernel/arch/x86/arch_hpet.h (working copy)
+++ headers/private/kernel/arch/x86/arch_hpet.h (working copy)
@@ -1,49 +0,0 @@
-/*
- * Copyright 2008, Dustin Howett, dustin.howett@xxxxxxxxxx All rights reserved.
- * Distributed under the terms of the MIT License.
- */
-#ifndef _KERNEL_ARCH_x86_HPET_H
-#define _KERNEL_ARCH_x86_HPET_H
-
-#include <types.h>
-
-/* 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
-
-/* Retrieve Global Capabilities */
-#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)
-
-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 */
-};
-
-#endif
Index: headers/private/kernel/arch/x86/timer.h
===================================================================
--- headers/private/kernel/arch/x86/timer.h (revision 26244)
+++ headers/private/kernel/arch/x86/timer.h (working copy)
@@ -2,10 +2,12 @@
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
-#ifndef _NEWOS_KERNEL_ARCH_I386_TIMER
-#define _NEWOS_KERNEL_ARCH_I386_TIMER
+#ifndef _KERNEL_ARCH_X86_TIMER
+#define _KERNEL_ARCH_X86_TIMER
-int apic_timer_interrupt(void);
+#define ISA_TIMER_MODULE_NAME "timers/x86/isa/v1"
+#define APIC_TIMER_MODULE_NAME "timers/x86/apic/v1"
+#define HPET_TIMER_MODULE_NAME "timers/x86/hpet/v1"
#endif
Index: headers/private/kernel/timer.h
===================================================================
--- headers/private/kernel/timer.h (revision 26244)
+++ headers/private/kernel/timer.h (working copy)
@@ -18,6 +18,18 @@
#define B_TIMER_ACQUIRE_THREAD_LOCK 0x8000
#define B_TIMER_FLAGS B_TIMER_ACQUIRE_THREAD_LOCK
+/* Timer info structure */
+struct timer_info {
+ char *name;
+ int (*get_priority)(void);
+ status_t (*set_hardware_timer)(bigtime_t timeout);
+ status_t (*clear_hardware_timer)(void);
+ status_t (*init)(struct kernel_args *args);
+};
+
+typedef struct timer_info timer_info;
+
+
/* kernel functions */
status_t timer_init(struct kernel_args *);
int32 timer_interrupt(void);
- References:
- [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- From: Dustin Howett
- [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- From: Axel Dörfler
- [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- From: Dustin Howett
- [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- From: Dustin Howett
Other related posts:
- » [haiku-gsoc] New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- » [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- From: Dustin Howett
- [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- From: Axel Dörfler
- [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- From: Dustin Howett
- [haiku-gsoc] Re: New timer patch (again) (Was: Re: First timer.diff (from private e-mails))
- From: Dustin Howett