Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
56 pj 1
/*
2
 * PC/HW routine collection v1.0 for DOS/DJGPP
3
 *
4
 *  Copyright (C) 2002 - Borca Daniel
5
 *  Email : dborca@yahoo.com
6
 *  Web   : http://www.geocities.com/dborca
7
 */
8
 
9
 
10
#include <pc.h>
11
 
12
#include "pc_hw.h"
13
 
14
#define TIMER_IRQ 0
15
 
16
#define MAX_TIMERS 8
17
 
18
#define PIT_FREQ 0x1234DD
19
 
20
#define unvolatile(__v, __t) __extension__ ({union { volatile __t __cp; __t __p; } __q; __q.__cp = __v; __q.__p;})
21
 
22
static int timer_installed;
23
 
24
typedef struct {
25
        volatile unsigned int counter, clock_ticks, freq;
26
        volatile PFUNC func;
27
        volatile void *parm;
28
} TIMER;
29
 
30
TIMER timer_main, timer_func[MAX_TIMERS];
31
 
32
static int timer ()
33
{
34
 int i;
35
 
36
 for (i=0;i<MAX_TIMERS;i++) {
37
     TIMER *t = &timer_func[i];
38
     if (t->func) {
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 *));
43
        }
44
     }
45
 }
46
 
47
 timer_main.clock_ticks += timer_main.counter;
48
 if (timer_main.clock_ticks>=0x10000) {
49
    timer_main.clock_ticks -= 0x10000;
50
    return 1;
51
 } else {
52
    outportb(0x20, 0x20);
53
    return 0;
54
 }
55
} ENDOFUNC(timer)
56
 
57
void pc_remove_timer (void)
58
{
59
 if (timer_installed) {
60
    timer_installed = FALSE;
61
    pc_clexit(pc_remove_timer);
62
 
63
    DISABLE();
64
    outportb(0x43, 0x34);
65
    outportb(0x40, 0);
66
    outportb(0x40, 0);
67
    ENABLE();
68
 
69
    pc_remove_irq(TIMER_IRQ);
70
 }
71
}
72
 
73
static int install_timer (void)
74
{
75
 if (timer_installed||pc_install_irq(TIMER_IRQ, timer)) {
76
    return -1;
77
 } else {
78
    LOCKDATA(timer_func);
79
    LOCKDATA(timer_main);
80
    LOCKFUNC(timer);
81
 
82
    timer_main.counter = 0x10000;
83
 
84
    DISABLE();
85
    outportb(0x43, 0x34);
86
    outportb(0x40, 0);
87
    outportb(0x40, 0);
88
    timer_main.clock_ticks = 0;
89
    ENABLE();
90
 
91
    pc_atexit(pc_remove_timer);
92
    timer_installed = TRUE;
93
    return 0;
94
 }
95
}
96
 
97
static TIMER *find_slot (PFUNC func)
98
{
99
 int i;
100
 
101
 for (i=0;i<MAX_TIMERS;i++) {
102
     if (timer_func[i].func==func) {
103
        return &timer_func[i];
104
     }
105
 }
106
 for (i=0;i<MAX_TIMERS;i++) {
107
     if (!timer_func[i].func) {
108
        return &timer_func[i];
109
     }
110
 }
111
 
112
 return NULL;
113
}
114
 
115
int pc_install_int (PFUNC func, void *parm, unsigned int freq)
116
{
117
 int i;
118
 TIMER *t;
119
 
120
 if (!timer_installed) {
121
    if (install_timer()) {
122
       return -1;
123
    }
124
 }
125
 
126
 if ((t=find_slot(func))!=NULL) {
127
    unsigned int new_counter = PIT_FREQ / freq;
128
 
129
    DISABLE();
130
 
131
    t->func = func;
132
    t->parm = parm;
133
    t->freq = freq;
134
    t->clock_ticks = 0;
135
 
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;
140
           }
141
       }
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;
148
    } else {
149
       t->counter = PIT_FREQ * freq / (timer_main.freq * timer_main.freq);
150
    }
151
 
152
    ENABLE();
153
 
154
    return 0;
155
 }
156
 
157
 return -1;
158
}