git://scm.lunaixsky.com
/
lunaix-os.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Unifying External Interrupt System (#51)
[lunaix-os.git]
/
lunaix-os
/
arch
/
x86
/
hal
/
apic_timer.c
diff --git
a/lunaix-os/arch/x86/hal/apic_timer.c
b/lunaix-os/arch/x86/hal/apic_timer.c
index eae4c3feb76391ff1bf518520cc865ac9b0f9228..178928cae3f205d51599d1a788a4fcf2d0883a18 100644
(file)
--- a/
lunaix-os/arch/x86/hal/apic_timer.c
+++ b/
lunaix-os/arch/x86/hal/apic_timer.c
@@
-1,85
+1,57
@@
#include "apic_timer.h"
#include <hal/hwtimer.h>
#include "apic_timer.h"
#include <hal/hwtimer.h>
+#include <hal/irq.h>
#include <lunaix/clock.h>
#include <lunaix/compiler.h>
#include <lunaix/clock.h>
#include <lunaix/compiler.h>
-#include <asm-generic/isrm.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
#include "asm/soc/apic.h"
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
#include "asm/soc/apic.h"
-LOG_MODULE("
APIC_TIMER
")
+LOG_MODULE("
timer(apic)
")
#define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector)
#define APIC_BASETICKS 0x100000
#define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector)
#define APIC_BASETICKS 0x100000
-// Don't optimize them! Took me an half hour to figure that out...
-
-static volatile u8_t apic_timer_done = 0;
-static volatile ticks_t base_freq = 0;
-static volatile ticks_t systicks = 0;
-
-static timer_tick_cb tick_cb = NULL;
-
-static void
-temp_intr_routine_apic_timer(const struct hart_state* state)
-{
- apic_timer_done = 1;
-}
-
static void
static void
-apic_timer_
tick_isr(
const struct hart_state* state)
+apic_timer_
count_stop(irq_t irq,
const struct hart_state* state)
{
{
- s
ysticks++
;
+ s
truct hwtimer_pot* pot
;
- if (likely((ptr_t)tick_cb)) {
- tick_cb();
- }
+ pot = irq_payload(irq, struct hwtimer_pot);
+ pot->systick_raw = (ticks_t)-1;
}
}
-static
int
-apic_timer_
check(struct hwtimer* hwt
)
+static
void
+apic_timer_
tick_isr(irq_t irq, const struct hart_state* state
)
{
{
- // TODO check whether apic timer is supported
- return 1;
-}
+ struct hwtimer_pot* pot;
-static ticks_t
-apic_get_systicks()
-{
- return systicks;
-}
+ pot = irq_payload(irq, struct hwtimer_pot);
+ pot->systick_raw++;
-static ticks_t
-apic_get_base_freq()
-{
- return base_freq;
+ if (likely(__ptr(pot->callback))) {
+ pot->callback();
+ }
}
}
-void
-
apic_timer_init(struct hwtimer* timer, u32_t hertz, timer_tick_cb timer_cb
)
+
static
void
+
__apic_timer_calibrate(struct hwtimer_pot* pot, u32_t hertz
)
{
{
-
ticks_t frequency = hertz
;
- tick
_cb = timer_cb
;
+
irq_t irq
;
+ tick
s_t base_freq = 0
;
cpu_disable_interrupt();
cpu_disable_interrupt();
- // Setup APIC timer
-
- // Remap the IRQ 8 (rtc timer's vector) to RTC_TIMER_IV in ioapic
- // (Remarks IRQ 8 is pin INTIN8)
- // See IBM PC/AT Technical Reference 1-10 for old RTC IRQ
- // See Intel's Multiprocessor Specification for IRQ - IOAPIC INTIN
- // mapping config.
-
- // grab ourselves these irq numbers
- u32_t iv_timer = isrm_ivexalloc(temp_intr_routine_apic_timer);
+ irq = irq_declare_direct(apic_timer_count_stop);
+ irq_set_payload(irq, pot);
+ irq_assign(irq_get_default_domain(), irq, NULL);
// Setup a one-shot timer, we will use this to measure the bus speed. So we
// can then calibrate apic timer to work at *nearly* accurate hz
apic_write_reg(APIC_TIMER_LVT,
// Setup a one-shot timer, we will use this to measure the bus speed. So we
// can then calibrate apic timer to work at *nearly* accurate hz
apic_write_reg(APIC_TIMER_LVT,
- LVT_ENTRY_TIMER(i
v_time
r, LVT_TIMER_ONESHOT));
+ LVT_ENTRY_TIMER(i
rq->vecto
r, LVT_TIMER_ONESHOT));
// Set divider to 64
apic_write_reg(APIC_TIMER_DCR, APIC_TIMER_DIV64);
// Set divider to 64
apic_write_reg(APIC_TIMER_DCR, APIC_TIMER_DIV64);
@@
-107,55
+79,56
@@
apic_timer_init(struct hwtimer* timer, u32_t hertz, timer_tick_cb timer_cb)
*/
*/
-#ifdef __LUNAIXOS_DEBUG__
- if (frequency < 1000) {
- WARN("Frequency too low. Millisecond timer might be dodgy.");
- }
-#endif
-
- apic_timer_done = 0;
-
- sysrtc->cls_mask(sysrtc);
+ sysrtc->ops->set_proactive(sysrtc, true);
apic_write_reg(APIC_TIMER_ICR, APIC_BASETICKS); // start APIC timer
apic_write_reg(APIC_TIMER_ICR, APIC_BASETICKS); // start APIC timer
- // enable interrupt, just for our RTC start ticking!
+ pot->systick_raw = 0;
cpu_enable_interrupt();
cpu_enable_interrupt();
- wait_until(
apic_timer_done
);
+ wait_until(
!(pot->systick_raw + 1)
);
cpu_disable_interrupt();
cpu_disable_interrupt();
- sysrtc->
set_mask(sysrtc
);
-
- base_freq = sysrtc->
get_counts(sysrtc)
;
+ sysrtc->
ops->set_proactive(sysrtc, false
);
+
+ base_freq = sysrtc->
live
;
base_freq = APIC_BASETICKS / base_freq * sysrtc->base_freq;
base_freq = APIC_BASETICKS / base_freq * sysrtc->base_freq;
+ pot->base_freq = base_freq;
+ pot->systick_raw = 0;
assert_msg(base_freq, "Fail to initialize timer (NOFREQ)");
assert_msg(base_freq, "Fail to initialize timer (NOFREQ)");
+ INFO("hw: %u Hz; os: %u Hz", base_freq, hertz);
- kprintf("hw: %u Hz; os: %u Hz", base_freq, frequency);
-
- // cleanup
- isrm_ivfree(iv_timer);
-
- ticks_t tphz = base_freq / frequency;
- timer->base_freq = base_freq;
- apic_write_reg(APIC_TIMER_ICR, tphz);
+ irq_set_servant(irq, apic_timer_tick_isr);
+ apic_write_reg(APIC_TIMER_ICR, base_freq / hertz);
apic_write_reg(
apic_write_reg(
- APIC_TIMER_LVT,
-
LVT_ENTRY_TIMER(isrm_ivexalloc(apic_timer_tick_isr)
, LVT_TIMER_PERIODIC));
+
APIC_TIMER_LVT,
+
LVT_ENTRY_TIMER(irq->vector
, LVT_TIMER_PERIODIC));
}
}
-struct hwtimer*
-apic_hwtimer_context()
+static struct hwtimer_pot_ops potops = {
+ .calibrate = __apic_timer_calibrate,
+};
+
+static int
+__apic_timer_load(struct device_def* def)
{
{
- static struct hwtimer apic_hwt = {
- .name = "apic_timer",
- .class = DEVCLASSV(DEVIF_SOC, DEVFN_TIME, DEV_TIMER, DEV_TIMER_APIC),
- .init = apic_timer_init,
- .supported = apic_timer_check,
- .systicks = apic_get_systicks
- };
-
- return &apic_hwt;
+ struct device* timer;
+
+ timer = device_allocsys(NULL, NULL);
+
+ hwtimer_attach_potens(timer, HWTIMER_MAX_PRECEDENCE, &potops);
+ register_device_var(timer, &def->class, "apic-timer");
+ return 0;
}
}
+
+
+static struct device_def x86_apic_timer =
+{
+ def_device_class(INTEL, TIME, TIMER_APIC),
+ def_device_name("Intel APIC Timer"),
+
+ def_on_load(__apic_timer_load)
+};
+EXPORT_DEVICE(apic_timer, &x86_apic_timer, load_sysconf);