includes: AROS_UFIxx -> AROS_INTxx change
[AROS.git] / arch / m68k-amiga / timer / timer_init.c
blob40dec3bbb8022b761dfb61ec91cfc09cbcd94d3e
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Timer startup and device commands
6 */
8 /****************************************************************************************/
12 implementation notes:
14 - CIAA-A: normal timer jobs (microhz/e-clock)
15 - CIAA-B: E-clock counter
16 - vblank interrupt used for vblank timer unit
18 Unit conversions and misuse of tv_sec/tv_usec fields probably looks strange..
21 #define DEBUG 0
22 #include <aros/debug.h>
24 #include <aros/kernel.h>
25 #include <exec/types.h>
26 #include <exec/io.h>
27 #include <exec/errors.h>
28 #include <exec/devices.h>
29 #include <exec/alerts.h>
30 #include <exec/initializers.h>
31 #include <devices/timer.h>
32 #include <hardware/intbits.h>
33 #include <hardware/cia.h>
34 #include <graphics/gfxbase.h>
36 #include <proto/exec.h>
37 #include <proto/kernel.h>
38 #include <proto/timer.h>
39 #include <proto/cia.h>
40 #include <proto/battclock.h>
42 #include <aros/symbolsets.h>
44 #include LC_LIBDEFS_FILE
46 #include <timer_intern.h>
47 #include <timer_platform.h>
49 AROS_INTP(ciab_eclock);
50 AROS_INTP(ciaint_timer);
51 AROS_INTP(cia_vbint);
53 /****************************************************************************************/
55 static int GM_UNIQUENAME(Init)(LIBBASETYPEPTR LIBBASE)
57 struct Interrupt *inter;
58 struct BattClockBase *BattClockBase;
59 struct GfxBase *GfxBase;
61 GfxBase = TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS);
63 InitCustom(GfxBase);
65 LIBBASE->tb_eclock_rate = (GfxBase->DisplayFlags & REALLY_PAL) ? 709379 : 715909;
66 LIBBASE->tb_vblank_rate = (GfxBase->DisplayFlags & PAL) ? 50 : 60;
67 LIBBASE->tb_vblank_micros = 1000000 / LIBBASE->tb_vblank_rate;
68 SysBase->ex_EClockFrequency = LIBBASE->tb_eclock_rate;
69 LIBBASE->tb_eclock_micro_mult = (GfxBase->DisplayFlags & REALLY_PAL) ? 92385 : 91542;
70 LIBBASE->tb_micro_eclock_mult = (GfxBase->DisplayFlags & REALLY_PAL) ? 23245 : 23459;
72 CloseLibrary((struct Library*)GfxBase);
74 BattClockBase = OpenResource("battclock.resource");
75 if (BattClockBase)
76 LIBBASE->tb_CurrentTime.tv_secs = ReadBattClock();
78 /* Initialise the lists */
79 NEWLIST(&LIBBASE->tb_Lists[UNIT_VBLANK]);
80 NEWLIST(&LIBBASE->tb_Lists[UNIT_MICROHZ]);
82 inter = &LIBBASE->tb_vbint;
83 inter->is_Code = (APTR)cia_vbint;
84 inter->is_Data = LIBBASE;
85 inter->is_Node.ln_Name = "timer.device VBlank";
86 inter->is_Node.ln_Pri = 20;
87 inter->is_Node.ln_Type = NT_INTERRUPT;
88 AddIntServer(INTB_VERTB, inter);
90 /* CIA-A timer A = microhz */
91 LIBBASE->tb_micro_cia = (struct CIA*)0xbfe001;
92 LIBBASE->tb_micro_cr = (UBYTE*)LIBBASE->tb_micro_cia + 0xe00;
93 LIBBASE->tb_micro_lo = (UBYTE*)LIBBASE->tb_micro_cia + 0x400;
94 LIBBASE->tb_micro_hi = (UBYTE*)LIBBASE->tb_micro_cia + 0x500;
95 LIBBASE->tb_micro_intbit = 0;
96 if (!(LIBBASE->tb_micro_res = OpenResource("ciaa.resource")))
97 Alert(AT_DeadEnd | AG_OpenRes | AO_CIARsrc);
99 inter = &LIBBASE->tb_ciaint_timer;
100 inter->is_Node.ln_Pri = 0;
101 inter->is_Node.ln_Type = NT_INTERRUPT;
102 inter->is_Node.ln_Name = "timer.device microhz";
103 inter->is_Code = (APTR)ciaint_timer;
104 inter->is_Data = LIBBASE;
106 Disable();
107 if (AddICRVector(LIBBASE->tb_micro_res, LIBBASE->tb_micro_intbit, inter))
108 Alert(AT_DeadEnd | AG_NoMemory | AO_CIARsrc);
109 *LIBBASE->tb_micro_cr = 0x08; // one-shot
110 SetICR(LIBBASE->tb_micro_res, 1 << LIBBASE->tb_micro_intbit);
111 Enable();
113 /* CIA-A timer B = E-Clock */
114 LIBBASE->tb_eclock_cia = (struct CIA*)0xbfe001;
115 LIBBASE->tb_eclock_cr = (UBYTE*)LIBBASE->tb_eclock_cia + 0xf00;
116 LIBBASE->tb_eclock_lo = (UBYTE*)LIBBASE->tb_eclock_cia + 0x600;
117 LIBBASE->tb_eclock_hi = (UBYTE*)LIBBASE->tb_eclock_cia + 0x700;
118 LIBBASE->tb_eclock_intbit = 1;
119 if (!(LIBBASE->tb_eclock_res = OpenResource("ciaa.resource")))
120 Alert(AT_DeadEnd | AG_OpenRes | AO_CIARsrc);
122 inter = &LIBBASE->tb_ciaint_eclock;
123 inter->is_Node.ln_Pri = 0;
124 inter->is_Node.ln_Type = NT_INTERRUPT;
125 inter->is_Node.ln_Name = "timer.device eclock";
126 inter->is_Code = (APTR)ciab_eclock;
127 inter->is_Data = LIBBASE;
129 Disable();
130 if (AddICRVector(LIBBASE->tb_eclock_res, LIBBASE->tb_eclock_intbit, inter))
131 Alert(AT_DeadEnd | AG_NoMemory | AO_CIARsrc);
132 *LIBBASE->tb_eclock_cr = 0x00;
133 // start timer in continuous mode
134 *LIBBASE->tb_eclock_lo = 0xff;
135 *LIBBASE->tb_eclock_hi = 0xff;
136 *LIBBASE->tb_eclock_cr |= 0x10;
137 *LIBBASE->tb_eclock_cr |= 0x01;
138 Enable();
140 D(bug("timer.device init\n"));
142 return TRUE;
145 /****************************************************************************************/
147 static int GM_UNIQUENAME(Open)
149 LIBBASETYPEPTR LIBBASE,
150 struct timerequest *tr,
151 ULONG unitNum,
152 ULONG flags
155 switch(unitNum)
157 case UNIT_VBLANK:
158 case UNIT_WAITUNTIL:
159 case UNIT_MICROHZ:
160 case UNIT_ECLOCK:
161 case UNIT_WAITECLOCK:
162 tr->tr_node.io_Error = 0;
163 tr->tr_node.io_Unit = (struct Unit *)unitNum;
164 tr->tr_node.io_Device = (struct Device *)LIBBASE;
165 break;
167 default:
168 tr->tr_node.io_Error = IOERR_OPENFAIL;
171 return TRUE;
174 /****************************************************************************************/
176 static int GM_UNIQUENAME(Expunge)(LIBBASETYPEPTR LIBBASE)
178 Disable();
179 RemIntServer(INTB_VERTB, &LIBBASE->tb_vbint);
180 RemICRVector(LIBBASE->tb_micro_res, LIBBASE->tb_micro_intbit, &LIBBASE->tb_ciaint_timer);
181 RemICRVector(LIBBASE->tb_eclock_res, LIBBASE->tb_eclock_intbit, &LIBBASE->tb_ciaint_eclock);
182 Enable();
183 return TRUE;
186 /****************************************************************************************/
188 ADD2INITLIB(GM_UNIQUENAME(Init), 0)
189 ADD2OPENDEV(GM_UNIQUENAME(Open), 0)
190 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge), 0)