Subversion Repositories shark

Rev

Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/* Project:     OSLib
2
 * Description: The OS Construction Kit
3
 * Date:                1.6.2000
4
 * Idea by:             Luca Abeni & Gerardo Lamastra
5
 *
6
 * OSLib is an SO project aimed at developing a common, easy-to-use
7
 * low-level infrastructure for developing OS kernels and Embedded
8
 * Applications; it partially derives from the HARTIK project but it
9
 * currently is independently developed.
10
 *
11
 * OSLib is distributed under GPL License, and some of its code has
12
 * been derived from the Linux kernel source; also some important
13
 * ideas come from studying the DJGPP go32 extender.
14
 *
15
 * We acknowledge the Linux Community, Free Software Foundation,
16
 * D.J. Delorie and all the other developers who believe in the
17
 * freedom of software and ideas.
18
 *
19
 * For legalese, check out the included GPL license.
20
 */
21
 
22
/*      Time Event routines     */
23
 
24
#include <ll/i386/stdlib.h>
25
#include <ll/i386/mem.h>
26
#include <ll/i386/error.h>
27
#include <ll/i386/hw-arch.h>
40 pj 28
#include <ll/i386/pic.h>
2 pj 29
#include <ll/i386/pit.h>
30
#include <ll/sys/ll/ll-data.h>
31
#include <ll/sys/ll/ll-instr.h>
32
#include <ll/sys/ll/time.h>
33
#include <ll/sys/ll/event.h>
34
 
35
FILE(Event);
36
 
37
extern LL_ARCH ll_arch;
38
 
39
BYTE frc;
40
 
41
/* Timer 0 usec base tick */
42
DWORD ticksize;
43
 
44
/* Timer 0 loaded time constant (= ticksize * 1.197) */
45
WORD pit_time_const;
46
DWORD timermode;
47
 
48
static DWORD nts;               /* System tick in nanoSeconds... */
49
struct timespec actTime;        /* Time (in nanosecs)... */
50
extern int activeInt;
51
 
52
WORD lastTime;
53
struct pitspec globalCounter;
54
 
55
struct event eventlist[MAX_EVENT];
56
 
57
struct event *freeevents;
58
struct event *firstevent;
59
 
60
extern void *last_handler;
61
extern void (*evt_prol) (void);
62
extern void (*evt_epil) (void);
63
 
40 pj 64
void event_setlasthandler(void *p)
65
{
66
    last_handler = p;
67
}                                                                              
2 pj 68
 
69
void event_setprologue(void *p)
70
{
71
    evt_prol = p;
72
}
73
 
74
void event_setepilogue(void *p)
75
{
76
    evt_epil = p;
77
}
78
 
79
/* Switched to timespec */
80
int periodic_event_post(struct timespec time, void (*handler) (void *p),
81
                        void *par)
82
{
83
    struct event *p;
84
    struct event *p1, *t;
85
 
86
    if (!freeevents) {
87
        return -1;
88
    }
89
 
90
    /* Extract from the ``free events'' queue */
91
    p = freeevents;
92
    freeevents = p->next;
93
 
94
    /* Fill the event fields */
95
    p->handler = handler;
96
    TIMESPEC_ASSIGN(&(p->time), &time);
97
    p->par = par;
98
 
99
    /* ...And insert it in the event queue!!! */
100
 
101
    t = NULL;
102
    /* walk through list, finding spot, adjusting ticks parameter */
103
    for (p1 = firstevent; p1; p1 = t->next) {
104
/*
105
                SUBTIMESPEC(&time, &(p1->time), &tmp);
106
                if ((tmp.tv_sec > 0) && (tmp.tv_nsec > 0)) {
107
*/
108
        if (TIMESPEC_A_GT_B(&time, &p1->time))
109
            t = p1;
110
        else
111
            break;
112
    }
113
 
114
    /* adjust next entry */
115
    if (t) {
116
        t->next = p;
117
    } else {
118
        firstevent = p;
119
    }
120
    p->next = p1;
121
 
122
    return p->index;
123
}
124
 
125
int periodic_event_delete(int index)
126
{
127
    struct event *p1, *t;
128
 
129
    t = NULL;
130
    /* walk through list, finding spot, adjusting ticks parameter */
131
    for (p1 = firstevent; (p1) && (index != p1->index); p1 = t->next) {
132
        t = p1;
133
    }
134
 
135
    if (p1 == NULL) {
136
        return -1;
137
    }
138
 
139
    if (t == NULL) {
140
        firstevent = p1->next;
141
    } else {
142
        t->next = p1->next;
143
    }
144
    p1->next = freeevents;
145
    freeevents = p1;
146
 
147
    return 1;
148
}
149
 
150
void periodic_wake_up(void)
151
{                               /* CHANGE the NAME, please... */
152
    struct event *p, *pp;
153
    WORD tmp;
154
 
155
    tmp = pit_read(frc);
156
    ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter);
157
    lastTime = tmp;
158
 
159
    activeInt++;
160
    if (activeInt == 1 && evt_prol != NULL) {
161
        evt_prol();
162
    }
163
 
164
    ADDNANO2TIMESPEC(nts, &actTime);
165
 
166
    for (p = firstevent; p != NULL; p = pp) {
167
/*
168
                SUBTIMESPEC(&(p->time), &actTime, &tmp);
169
                if ((tmp.tv_sec > 0) && (tmp.tv_nsec > 0)) {
170
                        break;
171
                } */
172
        if ((p->time.tv_sec > actTime.tv_sec) ||
173
            ((p->time.tv_sec == actTime.tv_sec)
174
             && (p->time.tv_nsec > actTime.tv_nsec))) {
175
            break;
176
        }
177
        pp = p->next;
178
        p->next = freeevents;
179
        freeevents = p;
180
        firstevent = pp;
181
        p->handler(p->par);
182
    }
183
 
184
    if (activeInt == 1 && evt_epil != NULL) {
185
        evt_epil();
186
    }
187
    activeInt--;
188
}
189
 
190
void event_init(struct ll_initparms *l)
191
{
192
    extern void ll_timer(void);
193
    int i;
194
    BYTE mask;
195
    TIME t;
196
 
40 pj 197
    IDT_place(0x40,ll_timer);
2 pj 198
 
199
    if (l->mode != LL_PERIODIC) {
40 pj 200
        error("Trying one-shot!!!");
2 pj 201
        t = 0;
202
        /* Mode: Binary/Mode 4/16 bit Time_const/Counter 0 */
203
        pit_init(0, TMR_MD4, 0xFFFF);   /* Timer 0, Mode 4, constant 0xFFFF */
204
    } else {
205
        t = l->tick;
206
        /* Translate the tick value in usec into a suitable time constant   */
207
        /* for 8254 timer chip; the chip is driven with a 1.19718 MHz       */
208
        /* frequency; then the effective frequency is given by the base     */
209
        /* frequency divided for the time constant; the tick is the inverse */
210
        /* of this effective frequency (in usec!)                           */
211
        /* Time-Constant = f_base (MHz) * tick (usec)                       */
212
        /* If T-C == 0 -> T-C = 65536 (Max available)                       */
213
        ticksize = t;
214
        t = t * 1197;
215
        t = t / 1000;
216
        /* Only for security! This should cause timer overrun */
217
        /* While 0 would set maximum period on timer          */
218
        if (t == 0)
219
            t = 1;
220
        pit_time_const = (WORD) (t & 0xFFFF);
221
        /* Mode: Binary/Mode 2/16 bit Time_const/Counter 0 */
222
        pit_init(0, TMR_MD2, t);        /* Timer 0, Mode 2, Time constant t */
223
 
224
 
225
    }
226
    timermode = l->mode;
40 pj 227
 
228
    if (ll_arch.x86.cpu > 4) {
2 pj 229
        /* Timer1: mode 0, time const 0... */
230
        pit_init(1, TMR_MD0, 0);
231
        frc = 1;
232
    } else {
233
        frc = 2;
234
        pit_init(2, TMR_MD0, 0);
40 pj 235
         outp(0x61, 3);
2 pj 236
    }
237
 
238
    mask = ll_in(0x21);
239
    mask &= 0xFE;               /* 0xFE = ~0x01 */
240
    ll_out(0x21, mask);
241
 
242
 
243
    /* Init the event list... */
244
    for (i = 0; i < MAX_EVENT; i++) {
245
        if (i < MAX_EVENT - 1) {
246
            eventlist[i].next = &(eventlist[i + 1]);
247
        }
248
        eventlist[i].index = i;
249
    }
250
    eventlist[MAX_EVENT - 1].next = NULL;
251
    freeevents = &(eventlist[0]);
252
 
253
    evt_prol = NULL;
254
    evt_epil = NULL;
255
 
256
    /* Initialization of the time variables for periodic mode */
257
    nts = ticksize * 1000;
258
    NULL_TIMESPEC(&actTime);
259
 
260
    /* Initialization of the general time variables */
261
    NULLPITSPEC(&globalCounter);
262
    lastTime = 0;
263
 
264
    if (timermode == LL_PERIODIC) {
265
        event_post = periodic_event_post;
266
        event_delete = periodic_event_delete;
267
    } else {
268
        event_post = oneshot_event_post;
269
        event_delete = oneshot_event_delete;
270
    }
40 pj 271
 
272
    /* Last but not least... */
273
    irq_unmask(0);
2 pj 274
}