2 * PC/HW routine collection v1.0 for DOS/DJGPP
4 * Copyright (C) 2002 - Borca Daniel
5 * Email : dborca@yahoo.com
6 * Web : http://www.geocities.com/dborca
18 #define PIT_FREQ 0x1234DD
20 #define unvolatile(__v, __t) __extension__ ({union { volatile __t __cp; __t __p; } __q; __q.__cp = __v; __q.__p;})
22 static int timer_installed
;
25 volatile unsigned int counter
, clock_ticks
, freq
;
30 TIMER timer_main
, timer_func
[MAX_TIMERS
];
36 for (i
=0;i
<MAX_TIMERS
;i
++) {
37 TIMER
*t
= &timer_func
[i
];
39 t
->clock_ticks
+= t
->counter
;
40 if (t
->clock_ticks
>=timer_main
.counter
) {
41 t
->clock_ticks
-= timer_main
.counter
;
42 t
->func(unvolatile(t
->parm
, void *));
47 timer_main
.clock_ticks
+= timer_main
.counter
;
48 if (timer_main
.clock_ticks
>=0x10000) {
49 timer_main
.clock_ticks
-= 0x10000;
57 void pc_remove_timer (void)
59 if (timer_installed
) {
60 timer_installed
= FALSE
;
61 pc_clexit(pc_remove_timer
);
69 pc_remove_irq(TIMER_IRQ
);
73 static int install_timer (void)
75 if (timer_installed
||pc_install_irq(TIMER_IRQ
, timer
)) {
82 timer_main
.counter
= 0x10000;
88 timer_main
.clock_ticks
= 0;
91 pc_atexit(pc_remove_timer
);
92 timer_installed
= TRUE
;
97 static TIMER
*find_slot (PFUNC func
)
101 for (i
=0;i
<MAX_TIMERS
;i
++) {
102 if (timer_func
[i
].func
==func
) {
103 return &timer_func
[i
];
106 for (i
=0;i
<MAX_TIMERS
;i
++) {
107 if (!timer_func
[i
].func
) {
108 return &timer_func
[i
];
115 int pc_install_int (PFUNC func
, void *parm
, unsigned int freq
)
120 if (!timer_installed
) {
121 if (install_timer()) {
126 if ((t
=find_slot(func
))!=NULL
) {
127 unsigned int new_counter
= PIT_FREQ
/ freq
;
136 if (new_counter
< timer_main
.counter
) {
137 for (i
=0;i
<MAX_TIMERS
;i
++) {
138 if (timer_func
[i
].func
) {
139 timer_func
[i
].counter
= new_counter
* timer_func
[i
].freq
/ freq
;
142 outportb(0x43, 0x34);
143 outportb(0x40, (unsigned char)new_counter
);
144 outportb(0x40, (unsigned char)(new_counter
>>8));
145 timer_main
.clock_ticks
= 0;
146 timer_main
.counter
= new_counter
;
147 timer_main
.freq
= freq
;
149 t
->counter
= PIT_FREQ
* freq
/ (timer_main
.freq
* timer_main
.freq
);