Fix a few conversion bugs. For example, GLshort->GLfloat conversion
[mesa.git] / src / glut / dos / PC_HW / pc_timer.c
1 /*
2 * PC/HW routine collection v1.5 for DOS/DJGPP
3 *
4 * Copyright (C) 2002 - Daniel Borca
5 * Email : dborca@yahoo.com
6 * Web : http://www.geocities.com/dborca
7 */
8
9
10 #include <pc.h>
11 #include <string.h>
12
13 #include "pc_hw.h"
14
15 #define TIMER_IRQ 0
16
17 #define MAX_TIMERS 8
18
19 #define PIT_FREQ 0x1234DD
20
21 #define ADJUST(timer, basefreq) timer.counter = PIT_FREQ * timer.freq / SQR(basefreq)
22
23 #define unvolatile(__v, __t) __extension__ ({union { volatile __t __cp; __t __p; } __q; __q.__cp = __v; __q.__p;})
24
25 static int timer_installed;
26
27 typedef struct {
28 volatile unsigned int counter, clock_ticks, freq;
29 volatile PFUNC func;
30 volatile void *parm;
31 } TIMER;
32
33 static TIMER timer_main, timer_func[MAX_TIMERS];
34
35
36 /* Desc: main timer callback
37 *
38 * In : -
39 * Out : 0 to bypass BIOS, 1 to chain to BIOS
40 *
41 * Note: -
42 */
43 static int
44 timer ()
45 {
46 int i;
47
48 for (i = 0; i < MAX_TIMERS; i++) {
49 TIMER *t = &timer_func[i];
50 if (t->func) {
51 t->clock_ticks += t->counter;
52 if (t->clock_ticks >= timer_main.counter) {
53 t->clock_ticks -= timer_main.counter;
54 t->func(unvolatile(t->parm, void *));
55 }
56 }
57 }
58
59 timer_main.clock_ticks += timer_main.counter;
60 if (timer_main.clock_ticks >= 0x10000) {
61 timer_main.clock_ticks -= 0x10000;
62 return 1;
63 } else {
64 outportb(0x20, 0x20);
65 return 0;
66 }
67 } ENDOFUNC(timer)
68
69
70 /* Desc: uninstall timer engine
71 *
72 * In : -
73 * Out : -
74 *
75 * Note: -
76 */
77 void
78 pc_remove_timer (void)
79 {
80 if (timer_installed) {
81 timer_installed = FALSE;
82 pc_clexit(pc_remove_timer);
83
84 DISABLE();
85 outportb(0x43, 0x34);
86 outportb(0x40, 0);
87 outportb(0x40, 0);
88 ENABLE();
89
90 pc_remove_irq(TIMER_IRQ);
91 }
92 }
93
94
95 /* Desc: remove timerfunc
96 *
97 * In : timerfunc id
98 * Out : 0 if success
99 *
100 * Note: tries to relax the main timer whenever possible
101 */
102 int
103 pc_remove_int (int fid)
104 {
105 int i;
106 unsigned int freq = 0;
107
108 /* are we installed? */
109 if (!timer_installed) {
110 return -1;
111 }
112
113 /* sanity check */
114 if ((fid < 0) || (fid >= MAX_TIMERS) || (timer_func[fid].func == NULL)) {
115 return -1;
116 }
117 timer_func[fid].func = NULL;
118
119 /* scan for maximum frequency */
120 for (i = 0; i < MAX_TIMERS; i++) {
121 TIMER *t = &timer_func[i];
122 if (t->func) {
123 if (freq < t->freq) {
124 freq = t->freq;
125 }
126 }
127 }
128
129 /* if there are no callbacks left, cleanup */
130 if (!freq) {
131 pc_remove_timer();
132 return 0;
133 }
134
135 /* if we just lowered the maximum frequency, try to relax the timer engine */
136 if (freq < timer_main.freq) {
137 unsigned int new_counter = PIT_FREQ / freq;
138
139 DISABLE();
140
141 for (i = 0; i < MAX_TIMERS; i++) {
142 if (timer_func[i].func) {
143 ADJUST(timer_func[i], freq);
144 }
145 }
146
147 outportb(0x43, 0x34);
148 outportb(0x40, (unsigned char)new_counter);
149 outportb(0x40, (unsigned char)(new_counter>>8));
150 timer_main.clock_ticks = 0;
151 timer_main.counter = new_counter;
152 timer_main.freq = freq;
153
154 ENABLE();
155 }
156
157 return 0;
158 } ENDOFUNC(pc_remove_int)
159
160
161 /* Desc: adjust timerfunc
162 *
163 * In : timerfunc id, new frequency (Hz)
164 * Out : 0 if success
165 *
166 * Note: might change the main timer frequency
167 */
168 int
169 pc_adjust_int (int fid, unsigned int freq)
170 {
171 int i;
172
173 /* are we installed? */
174 if (!timer_installed) {
175 return -1;
176 }
177
178 /* sanity check */
179 if ((fid < 0) || (fid >= MAX_TIMERS) || (timer_func[fid].func == NULL)) {
180 return -1;
181 }
182 timer_func[fid].freq = freq;
183
184 /* scan for maximum frequency */
185 freq = 0;
186 for (i = 0; i < MAX_TIMERS; i++) {
187 TIMER *t = &timer_func[i];
188 if (t->func) {
189 if (freq < t->freq) {
190 freq = t->freq;
191 }
192 }
193 }
194
195 /* update main timer / sons to match highest frequency */
196 DISABLE();
197
198 /* using '>' is correct still (and avoids updating
199 * the HW timer too often), but doesn't relax the timer!
200 */
201 if (freq != timer_main.freq) {
202 unsigned int new_counter = PIT_FREQ / freq;
203
204 for (i = 0; i < MAX_TIMERS; i++) {
205 if (timer_func[i].func) {
206 ADJUST(timer_func[i], freq);
207 }
208 }
209
210 outportb(0x43, 0x34);
211 outportb(0x40, (unsigned char)new_counter);
212 outportb(0x40, (unsigned char)(new_counter>>8));
213 timer_main.clock_ticks = 0;
214 timer_main.counter = new_counter;
215 timer_main.freq = freq;
216 } else {
217 ADJUST(timer_func[fid], timer_main.freq);
218 }
219
220 ENABLE();
221
222 return 0;
223 } ENDOFUNC(pc_adjust_int)
224
225
226 /* Desc: install timer engine
227 *
228 * In : -
229 * Out : 0 for success
230 *
231 * Note: initial frequency is 18.2 Hz
232 */
233 static int
234 install_timer (void)
235 {
236 if (timer_installed || pc_install_irq(TIMER_IRQ, timer)) {
237 return -1;
238 } else {
239 memset(timer_func, 0, sizeof(timer_func));
240
241 LOCKDATA(timer_func);
242 LOCKDATA(timer_main);
243 LOCKFUNC(timer);
244 LOCKFUNC(pc_adjust_int);
245 LOCKFUNC(pc_remove_int);
246
247 timer_main.counter = 0x10000;
248
249 DISABLE();
250 outportb(0x43, 0x34);
251 outportb(0x40, 0);
252 outportb(0x40, 0);
253 timer_main.clock_ticks = 0;
254 ENABLE();
255
256 pc_atexit(pc_remove_timer);
257 timer_installed = TRUE;
258 return 0;
259 }
260 }
261
262
263 /* Desc: install timerfunc
264 *
265 * In : callback function, opaque pointer to be passed to callee, freq (Hz)
266 * Out : timerfunc id (0 .. MAX_TIMERS-1)
267 *
268 * Note: returns -1 if error
269 */
270 int
271 pc_install_int (PFUNC func, void *parm, unsigned int freq)
272 {
273 int i;
274 TIMER *t = NULL;
275
276 /* ensure the timer engine is set up */
277 if (!timer_installed) {
278 if (install_timer()) {
279 return -1;
280 }
281 }
282
283 /* find an empty slot */
284 for (i = 0; i < MAX_TIMERS; i++) {
285 if (!timer_func[i].func) {
286 t = &timer_func[i];
287 break;
288 }
289 }
290 if (t == NULL) {
291 return -1;
292 }
293
294 DISABLE();
295
296 t->func = func;
297 t->parm = parm;
298 t->freq = freq;
299 t->clock_ticks = 0;
300
301 /* update main timer / sons to match highest frequency */
302 if (freq > timer_main.freq) {
303 unsigned int new_counter = PIT_FREQ / freq;
304
305 for (i = 0; i < MAX_TIMERS; i++) {
306 if (timer_func[i].func) {
307 ADJUST(timer_func[i], freq);
308 }
309 }
310
311 outportb(0x43, 0x34);
312 outportb(0x40, (unsigned char)new_counter);
313 outportb(0x40, (unsigned char)(new_counter>>8));
314 timer_main.clock_ticks = 0;
315 timer_main.counter = new_counter;
316 timer_main.freq = freq;
317 } else {
318 /* t == &timer_func[i] */
319 ADJUST(timer_func[i], timer_main.freq);
320 }
321
322 i = t - timer_func;
323
324 ENABLE();
325
326 return i;
327 }