2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
5 Desc: Timer startup and device commands
8 /****************************************************************************************/
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..
22 #include <aros/debug.h>
24 #include <aros/kernel.h>
25 #include <exec/types.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
);
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
);
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");
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
;
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
);
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
;
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;
140 D(bug("timer.device init\n"));
145 /****************************************************************************************/
147 static int GM_UNIQUENAME(Open
)
149 LIBBASETYPEPTR LIBBASE
,
150 struct timerequest
*tr
,
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
;
168 tr
->tr_node
.io_Error
= IOERR_OPENFAIL
;
174 /****************************************************************************************/
176 static int GM_UNIQUENAME(Expunge
)(LIBBASETYPEPTR LIBBASE
)
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
);
186 /****************************************************************************************/
188 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
189 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
190 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge
), 0)