2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Timer startup and device commands
8 /****************************************************************************************/
10 #include <exec/devices.h>
11 #include <exec/interrupts.h>
12 #include <devices/timer.h>
13 #include <hardware/intbits.h>
14 #include <proto/exec.h>
15 #include <proto/kernel.h>
16 #include <aros/symbolsets.h>
18 #include <aros/debug.h>
22 #define KernelBase LIBBASE->tb_KernelBase
24 /****************************************************************************************/
26 static void TimerInt(struct TimerBase
*TimerBase
, struct ExecBase
*SysBase
)
29 * Sync up with the hardware, we need the proper time value in order to
30 * process our requests correctly.
32 EClockUpdate(TimerBase
);
34 * Process MICROHZ requests.
35 * VBLANK is emulated by us, so we don't check it here. We always
36 * have one active request in this list, which will cause VBLANK checking.
38 handleMicroHZ(TimerBase
, SysBase
);
39 /* Request next interrupt from the hardware */
40 Timer0Setup(TimerBase
);
43 /****************************************************************************************/
45 static int hw_Init(struct TimerBase
*LIBBASE
)
47 /* We must have kernel.resource */
48 D(bug("[Timer] KernelBase = 0x%p\n", KernelBase
));
52 /* Start up the interrupt server. We know that our HW timer is at IRQ 0 */
53 LIBBASE
->tb_TimerIRQHandle
= KrnAddIRQHandler(0, TimerInt
, LIBBASE
, SysBase
);
54 D(bug("[Timer] IRQ handle = 0x%p\n", LIBBASE
->tb_TimerIRQHandle
));
55 if (!LIBBASE
->tb_TimerIRQHandle
)
58 D(bug("[Timer] Initializing hardware...\n"));
60 /* We have fixed EClock rate. VBlank will be emulated at 50Hz, can be changed at runtime. */
61 SysBase
->VBlankFrequency
= 50;
62 SysBase
->ex_EClockFrequency
= 1193180;
63 LIBBASE
->tb_eclock_rate
= 1193180;
64 LIBBASE
->tb_prev_tick
= 0xFFFF;
66 /* Start up the timer. Count the whole range for now. */
67 outb(CH0
|ACCESS_FULL
|MODE_SW_STROBE
, PIT_CONTROL
); /* Software strobe mode, 16-bit access */
68 ch_write(0xFFFF, PIT_CH0
);
72 * FIXME: This is not used by timer.device any more and must be removed.
73 * However PS/2 port driver uses polled microsecond delays via channel 2,
74 * and it relies on it being activated by us. This urgently needs to
77 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
78 outb(0xb4, 0x43); /* Binary mode on Timer2, count mode 2 */
79 outb(0x00, 0x42); /* We're counting whole range */
83 D(bug("[Timer] Starting VBlank emulation (%u Hz)...\n", SysBase
->VBlankFrequency
));
85 LIBBASE
->tb_vblank_timerequest
.tr_node
.io_Command
= TR_ADDREQUEST
;
86 LIBBASE
->tb_vblank_timerequest
.tr_node
.io_Device
= &LIBBASE
->tb_Device
;
87 LIBBASE
->tb_vblank_timerequest
.tr_node
.io_Unit
= (struct Unit
*)UNIT_MICROHZ
;
88 LIBBASE
->tb_vblank_timerequest
.tr_time
.tv_secs
= 0;
89 LIBBASE
->tb_vblank_timerequest
.tr_time
.tv_micro
= 1000000 / SysBase
->VBlankFrequency
;
91 SendIO(&LIBBASE
->tb_vblank_timerequest
.tr_node
);
93 D(bug("[Timer] Done\n"));
98 /****************************************************************************************/
100 static int hw_Expunge(struct TimerBase
*LIBBASE
)
102 KrnRemIRQHandler(LIBBASE
->tb_TimerIRQHandle
);
107 /****************************************************************************************/
109 ADD2INITLIB(hw_Init
, 0)
110 ADD2EXPUNGELIB(hw_Expunge
, 0)