2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
7 * Windows-hosted timer driver.
9 * In Windows kernel we have two statically allocated timers.
10 * Timer 0 is used by kernel for VBlank interrupts, timer 1 is our one.
12 * Our VBlank unit is driven by exec interrupt.
14 * TODO: Rewrite this implementation to use variable time intervals.
17 #include <aros/bootloader.h>
18 #include <aros/debug.h>
19 #include <aros/symbolsets.h>
20 #include <exec/execbase.h>
21 #include <exec/interrupts.h>
22 #include <hardware/intbits.h>
23 #include <proto/arossupport.h>
24 #include <proto/bootloader.h>
25 #include <proto/exec.h>
26 #include <proto/hostlib.h>
27 #include <proto/kernel.h>
29 #include "timer_intern.h"
30 #include "timer_macros.h"
31 #include "timervblank.h"
36 /* Timer 1 (EClock) interrupt handler */
37 static void TimerTick(struct TimerBase
*TimerBase
, struct ExecBase
*SysBase
)
39 /* Increment EClock value and process microhz requests */
40 ADDTIME(&TimerBase
->tb_CurrentTime
, &TimerBase
->tb_Platform
.tb_VBlankTime
);
41 ADDTIME(&TimerBase
->tb_Elapsed
, &TimerBase
->tb_Platform
.tb_VBlankTime
);
42 TimerBase
->tb_ticks_total
++;
44 handleMicroHZ(TimerBase
, SysBase
);
47 /****************************************************************************************/
49 #define KernelBase TimerBase->tb_KernelBase
51 static int Timer_Init(struct TimerBase
*TimerBase
)
56 HostLibBase
= OpenResource("hostlib.resource");
60 TimerBase
->tb_Platform
.kernelHandle
= HostLib_Open("Libs\\Host\\kernel.dll", NULL
);
61 if (!TimerBase
->tb_Platform
.kernelHandle
)
64 TimerBase
->tb_Platform
.StartClock
= HostLib_GetPointer(TimerBase
->tb_Platform
.kernelHandle
, "StartClock", NULL
);
65 if (!TimerBase
->tb_Platform
.StartClock
)
68 /* Install timer IRQ handler */
69 TimerBase
->tb_TimerIRQHandle
= KrnAddIRQHandler(1, TimerTick
, TimerBase
, SysBase
);
70 if (!TimerBase
->tb_TimerIRQHandle
)
73 /* Set up VBlank handler */
74 vblank_Init(TimerBase
);
76 /* By default we want 100 Hz EClock */
77 TimerBase
->tb_eclock_rate
= 100;
80 * Since we are software-driven, we can just ask the user which
81 * frequencies he wishes to use.
83 BootLoaderBase
= OpenResource("bootloader.resource");
86 struct List
*args
= GetBootInfo(BL_Args
);
92 for (node
= args
->lh_Head
; node
->ln_Succ
; node
= node
->ln_Succ
)
94 if (strncasecmp(node
->ln_Name
, "eclock=", 7) == 0)
96 TimerBase
->tb_eclock_rate
= atoi(&node
->ln_Name
[7]);
103 /* Set ExecBase public field. */
104 SysBase
->ex_EClockFrequency
= TimerBase
->tb_eclock_rate
;
105 D(bug("[Timer_Init] Timer frequency is %d\n", TimerBase
->tb_eclock_rate
));
107 /* Calculate timer period in us */
108 TimerBase
->tb_Platform
.tb_VBlankTime
.tv_secs
= 0;
109 TimerBase
->tb_Platform
.tb_VBlankTime
.tv_micro
= 1000000 / TimerBase
->tb_eclock_rate
;
111 /* Start up timer 1 */
113 ret
= TimerBase
->tb_Platform
.StartClock(1, TimerBase
->tb_eclock_rate
);
116 D(bug("[Timer_Init] StartClock() returned %d\n", ret
));
120 static int Timer_Expunge(struct TimerBase
*TimerBase
)
125 if (TimerBase
->tb_TimerIRQHandle
)
126 KrnRemIRQHandler(TimerBase
->tb_TimerIRQHandle
);
128 if (TimerBase
->tb_Platform
.kernelHandle
)
129 HostLib_Close(TimerBase
->tb_Platform
.kernelHandle
, NULL
);
134 ADD2INITLIB(Timer_Init
, 0)
135 ADD2EXPUNGELIB(Timer_Expunge
, 0)