revert commit 56204.
[AROS.git] / arch / all-pc / timer / timer_init.c
blobbe5dd5c03b2cc5b7d5eb7aa8bcd61dc26d8a77f0
1 /*
2 Copyright © 1995-2018, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Timer startup and device commands
6 */
8 #define DEBUG 0
9 #include <aros/debug.h>
11 /****************************************************************************************/
13 #include <aros/config.h>
14 #include <exec/devices.h>
15 #include <exec/interrupts.h>
16 #include <devices/timer.h>
17 #include <hardware/intbits.h>
18 #include <proto/exec.h>
19 #include <proto/execlock.h>
20 #include <proto/kernel.h>
21 #include <aros/symbolsets.h>
22 #include <asm/io.h>
24 #include "ticks.h"
26 #define KernelBase LIBBASE->tb_KernelBase
28 /****************************************************************************************/
30 static void TimerInt(struct TimerBase *TimerBase, struct ExecBase *SysBase)
33 * Sync up with the hardware, we need the proper time value in order to
34 * process our requests correctly.
36 EClockUpdate(TimerBase);
38 * Process MICROHZ requests.
39 * VBLANK is emulated by us, so we don't check it here. We always
40 * have one active request in this list, which will cause VBLANK checking.
42 handleMicroHZ(TimerBase, SysBase);
43 /* Request next interrupt from the hardware */
44 Timer0Setup(TimerBase);
47 /****************************************************************************************/
49 static AROS_INTH1(ResetHandler, struct TimerBase *, LIBBASE)
51 AROS_INTFUNC_INIT
53 /* Set a mode that won't generate interrupts */
54 outb(CH0|ACCESS_FULL|MODE_ONESHOT, PIT_CONTROL);
56 return 0;
58 AROS_INTFUNC_EXIT
61 /****************************************************************************************/
63 static int hw_Init(struct TimerBase *LIBBASE)
65 #if defined(__AROSEXEC_SMP__)
66 struct ExecLockBase *ExecLockBase;
67 if ((ExecLockBase = OpenResource("execlock.resource")) != NULL)
69 LIBBASE->tb_ExecLockBase = ExecLockBase;
70 LIBBASE->tb_ListLock = AllocLock();
72 #endif
74 /* We must have kernel.resource */
75 D(bug("[Timer] KernelBase = 0x%p\n", KernelBase));
76 if (!KernelBase)
77 return FALSE;
79 /* Start up the interrupt server. We know that our HW timer is at IRQ 0 */
80 LIBBASE->tb_TimerIRQHandle = KrnAddIRQHandler(0, TimerInt, LIBBASE, SysBase);
81 D(bug("[Timer] IRQ handle = 0x%p\n", LIBBASE->tb_TimerIRQHandle));
82 if (!LIBBASE->tb_TimerIRQHandle)
83 return FALSE;
85 /* Install a reset handler */
86 LIBBASE->tb_ResetHandler.is_Node.ln_Name =
87 LIBBASE->tb_Device.dd_Library.lib_Node.ln_Name;
88 LIBBASE->tb_ResetHandler.is_Code = (VOID_FUNC)ResetHandler;
89 LIBBASE->tb_ResetHandler.is_Data = LIBBASE;
90 AddResetCallback(&LIBBASE->tb_ResetHandler);
92 D(bug("[Timer] Initializing hardware...\n"));
94 /* We have fixed EClock rate. VBlank will be emulated at 50Hz, can be changed at runtime. */
95 SysBase->VBlankFrequency = 50;
96 SysBase->ex_EClockFrequency = 1193180;
97 LIBBASE->tb_eclock_rate = 1193180;
98 LIBBASE->tb_prev_tick = 0xFFFF;
100 /* Start up the timer. Count the whole range for now. */
101 outb(CH0|ACCESS_FULL|MODE_SW_STROBE, PIT_CONTROL); /* Software strobe mode, 16-bit access */
102 ch_write(0xFFFF, PIT_CH0);
105 * Start the timer2.
106 * FIXME: This is not used by timer.device any more and must be removed.
107 * However PS/2 port driver uses polled microsecond delays via channel 2,
108 * and it relies on it being activated by us. This urgently needs to
109 * be fixed!
111 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
112 outb(0xb4, 0x43); /* Binary mode on Timer2, count mode 2 */
113 outb(0x00, 0x42); /* We're counting whole range */
114 outb(0x00, 0x42);
116 /* Own VBlank EMU */
117 D(bug("[Timer] Starting VBlank emulation (%u Hz)...\n", SysBase->VBlankFrequency));
119 LIBBASE->tb_vblank_timerequest.tr_node.io_Command = TR_ADDREQUEST;
120 LIBBASE->tb_vblank_timerequest.tr_node.io_Device = &LIBBASE->tb_Device;
121 LIBBASE->tb_vblank_timerequest.tr_node.io_Unit = (struct Unit *)UNIT_MICROHZ;
122 LIBBASE->tb_vblank_timerequest.tr_time.tv_secs = 0;
123 LIBBASE->tb_vblank_timerequest.tr_time.tv_micro = 1000000 / SysBase->VBlankFrequency;
125 SendIO(&LIBBASE->tb_vblank_timerequest.tr_node);
127 D(bug("[Timer] Done\n"));
129 return TRUE;
132 /****************************************************************************************/
134 static int hw_Expunge(struct TimerBase *LIBBASE)
136 KrnRemIRQHandler(LIBBASE->tb_TimerIRQHandle);
137 RemResetCallback(&LIBBASE->tb_ResetHandler);
139 return TRUE;
142 /****************************************************************************************/
144 ADD2INITLIB(hw_Init, 0)
145 ADD2EXPUNGELIB(hw_Expunge, 0)