diff options
Diffstat (limited to 'nx-X11/extras/Mesa_6.4.1/src/glut/dos/PC_HW/pc_timer.c')
-rw-r--r-- | nx-X11/extras/Mesa_6.4.1/src/glut/dos/PC_HW/pc_timer.c | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/nx-X11/extras/Mesa_6.4.1/src/glut/dos/PC_HW/pc_timer.c b/nx-X11/extras/Mesa_6.4.1/src/glut/dos/PC_HW/pc_timer.c new file mode 100644 index 000000000..e7cbe70a1 --- /dev/null +++ b/nx-X11/extras/Mesa_6.4.1/src/glut/dos/PC_HW/pc_timer.c @@ -0,0 +1,327 @@ +/* + * PC/HW routine collection v1.5 for DOS/DJGPP + * + * Copyright (C) 2002 - Daniel Borca + * Email : dborca@yahoo.com + * Web : http://www.geocities.com/dborca + */ + + +#include <pc.h> +#include <string.h> + +#include "pc_hw.h" + +#define TIMER_IRQ 0 + +#define MAX_TIMERS 8 + +#define PIT_FREQ 0x1234DD + +#define ADJUST(timer, basefreq) timer.counter = PIT_FREQ * timer.freq / SQR(basefreq) + +#define unvolatile(__v, __t) __extension__ ({union { volatile __t __cp; __t __p; } __q; __q.__cp = __v; __q.__p;}) + +static int timer_installed; + +typedef struct { + volatile unsigned int counter, clock_ticks, freq; + volatile PFUNC func; + volatile void *parm; +} TIMER; + +static TIMER timer_main, timer_func[MAX_TIMERS]; + + +/* Desc: main timer callback + * + * In : - + * Out : 0 to bypass BIOS, 1 to chain to BIOS + * + * Note: - + */ +static int +timer () +{ + int i; + + for (i = 0; i < MAX_TIMERS; i++) { + TIMER *t = &timer_func[i]; + if (t->func) { + t->clock_ticks += t->counter; + if (t->clock_ticks >= timer_main.counter) { + t->clock_ticks -= timer_main.counter; + t->func(unvolatile(t->parm, void *)); + } + } + } + + timer_main.clock_ticks += timer_main.counter; + if (timer_main.clock_ticks >= 0x10000) { + timer_main.clock_ticks -= 0x10000; + return 1; + } else { + outportb(0x20, 0x20); + return 0; + } +} ENDOFUNC(timer) + + +/* Desc: uninstall timer engine + * + * In : - + * Out : - + * + * Note: - + */ +void +pc_remove_timer (void) +{ + if (timer_installed) { + timer_installed = FALSE; + pc_clexit(pc_remove_timer); + + DISABLE(); + outportb(0x43, 0x34); + outportb(0x40, 0); + outportb(0x40, 0); + ENABLE(); + + pc_remove_irq(TIMER_IRQ); + } +} + + +/* Desc: remove timerfunc + * + * In : timerfunc id + * Out : 0 if success + * + * Note: tries to relax the main timer whenever possible + */ +int +pc_remove_int (int fid) +{ + int i; + unsigned int freq = 0; + + /* are we installed? */ + if (!timer_installed) { + return -1; + } + + /* sanity check */ + if ((fid < 0) || (fid >= MAX_TIMERS) || (timer_func[fid].func == NULL)) { + return -1; + } + timer_func[fid].func = NULL; + + /* scan for maximum frequency */ + for (i = 0; i < MAX_TIMERS; i++) { + TIMER *t = &timer_func[i]; + if (t->func) { + if (freq < t->freq) { + freq = t->freq; + } + } + } + + /* if there are no callbacks left, cleanup */ + if (!freq) { + pc_remove_timer(); + return 0; + } + + /* if we just lowered the maximum frequency, try to relax the timer engine */ + if (freq < timer_main.freq) { + unsigned int new_counter = PIT_FREQ / freq; + + DISABLE(); + + for (i = 0; i < MAX_TIMERS; i++) { + if (timer_func[i].func) { + ADJUST(timer_func[i], freq); + } + } + + outportb(0x43, 0x34); + outportb(0x40, (unsigned char)new_counter); + outportb(0x40, (unsigned char)(new_counter>>8)); + timer_main.clock_ticks = 0; + timer_main.counter = new_counter; + timer_main.freq = freq; + + ENABLE(); + } + + return 0; +} ENDOFUNC(pc_remove_int) + + +/* Desc: adjust timerfunc + * + * In : timerfunc id, new frequency (Hz) + * Out : 0 if success + * + * Note: might change the main timer frequency + */ +int +pc_adjust_int (int fid, unsigned int freq) +{ + int i; + + /* are we installed? */ + if (!timer_installed) { + return -1; + } + + /* sanity check */ + if ((fid < 0) || (fid >= MAX_TIMERS) || (timer_func[fid].func == NULL)) { + return -1; + } + timer_func[fid].freq = freq; + + /* scan for maximum frequency */ + freq = 0; + for (i = 0; i < MAX_TIMERS; i++) { + TIMER *t = &timer_func[i]; + if (t->func) { + if (freq < t->freq) { + freq = t->freq; + } + } + } + + /* update main timer / sons to match highest frequency */ + DISABLE(); + + /* using '>' is correct still (and avoids updating + * the HW timer too often), but doesn't relax the timer! + */ + if (freq != timer_main.freq) { + unsigned int new_counter = PIT_FREQ / freq; + + for (i = 0; i < MAX_TIMERS; i++) { + if (timer_func[i].func) { + ADJUST(timer_func[i], freq); + } + } + + outportb(0x43, 0x34); + outportb(0x40, (unsigned char)new_counter); + outportb(0x40, (unsigned char)(new_counter>>8)); + timer_main.clock_ticks = 0; + timer_main.counter = new_counter; + timer_main.freq = freq; + } else { + ADJUST(timer_func[fid], timer_main.freq); + } + + ENABLE(); + + return 0; +} ENDOFUNC(pc_adjust_int) + + +/* Desc: install timer engine + * + * In : - + * Out : 0 for success + * + * Note: initial frequency is 18.2 Hz + */ +static int +install_timer (void) +{ + if (timer_installed || pc_install_irq(TIMER_IRQ, timer)) { + return -1; + } else { + memset(timer_func, 0, sizeof(timer_func)); + + LOCKDATA(timer_func); + LOCKDATA(timer_main); + LOCKFUNC(timer); + LOCKFUNC(pc_adjust_int); + LOCKFUNC(pc_remove_int); + + timer_main.counter = 0x10000; + + DISABLE(); + outportb(0x43, 0x34); + outportb(0x40, 0); + outportb(0x40, 0); + timer_main.clock_ticks = 0; + ENABLE(); + + pc_atexit(pc_remove_timer); + timer_installed = TRUE; + return 0; + } +} + + +/* Desc: install timerfunc + * + * In : callback function, opaque pointer to be passed to callee, freq (Hz) + * Out : timerfunc id (0 .. MAX_TIMERS-1) + * + * Note: returns -1 if error + */ +int +pc_install_int (PFUNC func, void *parm, unsigned int freq) +{ + int i; + TIMER *t = NULL; + + /* ensure the timer engine is set up */ + if (!timer_installed) { + if (install_timer()) { + return -1; + } + } + + /* find an empty slot */ + for (i = 0; i < MAX_TIMERS; i++) { + if (!timer_func[i].func) { + t = &timer_func[i]; + break; + } + } + if (t == NULL) { + return -1; + } + + DISABLE(); + + t->func = func; + t->parm = parm; + t->freq = freq; + t->clock_ticks = 0; + + /* update main timer / sons to match highest frequency */ + if (freq > timer_main.freq) { + unsigned int new_counter = PIT_FREQ / freq; + + for (i = 0; i < MAX_TIMERS; i++) { + if (timer_func[i].func) { + ADJUST(timer_func[i], freq); + } + } + + outportb(0x43, 0x34); + outportb(0x40, (unsigned char)new_counter); + outportb(0x40, (unsigned char)(new_counter>>8)); + timer_main.clock_ticks = 0; + timer_main.counter = new_counter; + timer_main.freq = freq; + } else { + /* t == &timer_func[i] */ + ADJUST(timer_func[i], timer_main.freq); + } + + i = t - timer_func; + + ENABLE(); + + return i; +} |