2 * Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
3 * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
4 * Distributed under the terms of the MIT License.
6 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
7 * Distributed under the terms of the NewOS License.
11 #include <arch/x86/timer.h>
14 #include <arch/x86/apic.h>
18 #include "apic_timer.h"
21 /* Method Prototypes */
22 static int apic_timer_get_priority();
23 static status_t
apic_timer_set_hardware_timer(bigtime_t relativeTimeout
);
24 static status_t
apic_timer_clear_hardware_timer();
25 static status_t
apic_timer_init(struct kernel_args
*args
);
27 static uint32 sApicTicsPerSec
= 0;
29 struct timer_info gAPICTimer
= {
31 &apic_timer_get_priority
,
32 &apic_timer_set_hardware_timer
,
33 &apic_timer_clear_hardware_timer
,
39 apic_timer_get_priority()
46 apic_timer_interrupt(void *data
)
48 return timer_interrupt();
55 apic_timer_set_hardware_timer(bigtime_t relativeTimeout
)
57 if (relativeTimeout
< MIN_TIMEOUT
)
58 relativeTimeout
= MIN_TIMEOUT
;
60 // calculation should be ok, since it's going to be 64-bit
61 uint32 ticks
= ((relativeTimeout
* sApicTicsPerSec
) / 1000000);
63 cpu_status state
= disable_interrupts();
65 uint32 config
= apic_lvt_timer() | APIC_LVT_MASKED
; // mask the timer
66 apic_set_lvt_timer(config
);
68 apic_set_lvt_initial_timer_count(0); // zero out the timer
70 config
= apic_lvt_timer() & ~APIC_LVT_MASKED
; // unmask the timer
71 apic_set_lvt_timer(config
);
73 //TRACE_TIMER(("arch_smp_set_apic_timer: config 0x%lx, timeout %Ld, tics/sec %lu, tics %lu\n",
74 // config, relativeTimeout, sApicTicsPerSec, ticks));
76 apic_set_lvt_initial_timer_count(ticks
); // start it up
78 restore_interrupts(state
);
85 apic_timer_clear_hardware_timer()
87 cpu_status state
= disable_interrupts();
89 uint32 config
= apic_lvt_timer() | APIC_LVT_MASKED
;
91 apic_set_lvt_timer(config
);
93 apic_set_lvt_initial_timer_count(0); // zero out the timer
95 restore_interrupts(state
);
101 apic_timer_init(struct kernel_args
*args
)
103 if (!apic_available())
106 sApicTicsPerSec
= args
->arch_args
.apic_time_cv_factor
;
108 reserve_io_interrupt_vectors(1, 0xfb - ARCH_INTERRUPT_BASE
,
109 INTERRUPT_TYPE_LOCAL_IRQ
);
110 install_io_interrupt_handler(0xfb - ARCH_INTERRUPT_BASE
,
111 &apic_timer_interrupt
, NULL
, B_NO_LOCK_VECTOR
);
118 apic_timer_per_cpu_init(struct kernel_args
*args
, int32 cpu
)
121 uint32 config
= apic_lvt_timer() & APIC_LVT_TIMER_MASK
;
122 config
|= 0xfb | APIC_LVT_MASKED
; // vector 0xfb, timer masked
123 apic_set_lvt_timer(config
);
125 apic_set_lvt_initial_timer_count(0); // zero out the clock
127 config
= apic_lvt_timer_divide_config() & 0xfffffff0;
128 config
|= APIC_TIMER_DIVIDE_CONFIG_1
; // clock division by 1
129 apic_set_lvt_timer_divide_config(config
);