aboutsummaryrefslogtreecommitdiffstats
path: root/src/glut/dos/PC_HW
diff options
context:
space:
mode:
Diffstat (limited to 'src/glut/dos/PC_HW')
-rw-r--r--src/glut/dos/PC_HW/pc_hw.h6
-rw-r--r--src/glut/dos/PC_HW/pc_timer.c247
2 files changed, 211 insertions, 42 deletions
diff --git a/src/glut/dos/PC_HW/pc_hw.h b/src/glut/dos/PC_HW/pc_hw.h
index 26bb8ba17df..bd2293eb29d 100644
--- a/src/glut/dos/PC_HW/pc_hw.h
+++ b/src/glut/dos/PC_HW/pc_hw.h
@@ -1,5 +1,5 @@
/*
- * PC/HW routine collection v1.3 for DOS/DJGPP
+ * PC/HW routine collection v1.4 for DOS/DJGPP
*
* Copyright (C) 2002 - Borca Daniel
@@ -19,6 +19,8 @@
#define FALSE 0
#define TRUE !FALSE
+#define SQR(x) ((x) * (x))
+
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
#define MID(x,y,z) MAX((x), MIN((y), (z)))
@@ -201,6 +203,8 @@ int pc_keyshifts (void);
* timer
*/
int pc_install_int (PFUNC func, void *parm, unsigned int freq);
+int pc_remove_int (int fid);
+int pc_adjust_int (int fid, unsigned int freq);
void pc_remove_timer (void);
/*
diff --git a/src/glut/dos/PC_HW/pc_timer.c b/src/glut/dos/PC_HW/pc_timer.c
index bf39bd0a4c0..f11917db1aa 100644
--- a/src/glut/dos/PC_HW/pc_timer.c
+++ b/src/glut/dos/PC_HW/pc_timer.c
@@ -1,5 +1,5 @@
/*
- * PC/HW routine collection v1.3 for DOS/DJGPP
+ * PC/HW routine collection v1.4 for DOS/DJGPP
*
* Copyright (C) 2002 - Borca Daniel
@@ -8,6 +8,7 @@
#include <pc.h>
+#include <string.h>
#include "pc_hw.h"
@@ -17,6 +18,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;
@@ -29,15 +32,24 @@ typedef struct {
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++) {
+ 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) {
+ if (t->clock_ticks >= timer_main.counter) {
t->clock_ticks -= timer_main.counter;
t->func(unvolatile(t->parm, void *));
}
@@ -45,7 +57,7 @@ static int timer ()
}
timer_main.clock_ticks += timer_main.counter;
- if (timer_main.clock_ticks>=0x10000) {
+ if (timer_main.clock_ticks >= 0x10000) {
timer_main.clock_ticks -= 0x10000;
return 1;
} else {
@@ -54,6 +66,15 @@ static int timer ()
}
} ENDOFUNC(timer)
+
+
+/* Desc: uninstall timer engine
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: -
+ */
void pc_remove_timer (void)
{
if (timer_installed) {
@@ -70,11 +91,22 @@ void pc_remove_timer (void)
}
}
+
+
+/* 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)) {
+ 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);
@@ -94,65 +126,198 @@ static int install_timer (void)
}
}
-static TIMER *find_slot (PFUNC func)
+
+
+/* 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;
- for (i=0;i<MAX_TIMERS;i++) {
- if (timer_func[i].func==func) {
- return &timer_func[i];
- }
+ /* ensure the timer engine is set up */
+ if (!timer_installed) {
+ if (install_timer()) {
+ return -1;
+ }
}
- for (i=0;i<MAX_TIMERS;i++) {
+
+ /* find an empty slot */
+ for (i = 0; i < MAX_TIMERS; i++) {
if (!timer_func[i].func) {
- return &timer_func[i];
+ 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);
+ }
+ }
- return NULL;
+ 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);
+ }
+
+ ENABLE();
+
+ return t - timer_func;
}
-int pc_install_int (PFUNC func, void *parm, unsigned int freq)
+
+
+/* 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;
- TIMER *t;
+ unsigned int freq = 0;
+ /* are we installed? */
if (!timer_installed) {
- if (install_timer()) {
- return -1;
- }
+ return -1;
}
- if ((t=find_slot(func))!=NULL) {
+ /* 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();
- t->func = func;
- t->parm = parm;
- t->freq = freq;
- t->clock_ticks = 0;
-
- if (new_counter < timer_main.counter) {
- for (i=0;i<MAX_TIMERS;i++) {
- if (timer_func[i].func) {
- timer_func[i].counter = new_counter * timer_func[i].freq / 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->counter = PIT_FREQ * freq / (timer_main.freq * timer_main.freq);
+ for (i = 0; i < MAX_TIMERS; i++) {
+ if (timer_func[i].func) {
+ ADJUST(timer_func[i], freq);
+ }
}
- ENABLE();
+ 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;
- return 0;
+ ENABLE();
}
- return -1;
+ return 0;
+}
+
+
+
+/* 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;
}