Subversion Repositories shark

Rev

Rev 120 | 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
 
120 giacomo 22
/* Added Advanced Timer Code
23
 *
24
 * Date:   8.4.2003
25
 * Author: Giacomo Guidi <giacomo@gandalf.sssup.it>
26
 *
27
 */
28
 
2 pj 29
/*      Time Event routines     */
30
 
31
#include <ll/i386/stdlib.h>
32
#include <ll/i386/mem.h>
33
#include <ll/i386/error.h>
34
#include <ll/i386/hw-arch.h>
40 pj 35
#include <ll/i386/pic.h>
2 pj 36
#include <ll/i386/pit.h>
131 giacomo 37
#include <ll/i386/advtimer.h>
38
 
2 pj 39
#include <ll/sys/ll/ll-data.h>
40
#include <ll/sys/ll/ll-instr.h>
41
#include <ll/sys/ll/time.h>
42
#include <ll/sys/ll/event.h>
43
 
44
FILE(Event);
45
 
46
extern LL_ARCH ll_arch;
47
 
48
BYTE frc;
49
 
50
/* Timer 0 usec base tick */
51
DWORD ticksize;
52
 
53
/* Timer 0 loaded time constant (= ticksize * 1.197) */
54
WORD pit_time_const;
55
DWORD timermode;
56
 
57
static DWORD nts;               /* System tick in nanoSeconds... */
58
struct timespec actTime;        /* Time (in nanosecs)... */
59
extern int activeInt;
60
 
61
WORD lastTime;
62
struct pitspec globalCounter;
63
 
64
struct event eventlist[MAX_EVENT];
65
 
66
struct event *freeevents;
67
struct event *firstevent;
68
 
69
extern void *last_handler;
70
extern void (*evt_prol) (void);
71
extern void (*evt_epil) (void);
72
 
120 giacomo 73
extern unsigned char use_tsc;
74
 
40 pj 75
void event_setlasthandler(void *p)
76
{
77
    last_handler = p;
78
}                                                                              
2 pj 79
 
80
void event_setprologue(void *p)
81
{
82
    evt_prol = p;
83
}
84
 
85
void event_setepilogue(void *p)
86
{
87
    evt_epil = p;
88
}
89
 
90
/* Switched to timespec */
91
int periodic_event_post(struct timespec time, void (*handler) (void *p),
92
                        void *par)
93
{
94
    struct event *p;
95
    struct event *p1, *t;
96
 
97
    if (!freeevents) {
98
        return -1;
99
    }
100
 
101
    /* Extract from the ``free events'' queue */
102
    p = freeevents;
103
    freeevents = p->next;
104
 
105
    /* Fill the event fields */
106
    p->handler = handler;
107
    TIMESPEC_ASSIGN(&(p->time), &time);
108
    p->par = par;
109
 
110
    /* ...And insert it in the event queue!!! */
111
 
112
    t = NULL;
113
    /* walk through list, finding spot, adjusting ticks parameter */
114
    for (p1 = firstevent; p1; p1 = t->next) {
115
/*
116
                SUBTIMESPEC(&time, &(p1->time), &tmp);
117
                if ((tmp.tv_sec > 0) && (tmp.tv_nsec > 0)) {
118
*/
119
        if (TIMESPEC_A_GT_B(&time, &p1->time))
120
            t = p1;
121
        else
122
            break;
123
    }
124
 
125
    /* adjust next entry */
126
    if (t) {
127
        t->next = p;
128
    } else {
129
        firstevent = p;
130
    }
131
    p->next = p1;
132
 
133
    return p->index;
134
}
135
 
136
int periodic_event_delete(int index)
137
{
138
    struct event *p1, *t;
139
 
140
    t = NULL;
141
    /* walk through list, finding spot, adjusting ticks parameter */
142
    for (p1 = firstevent; (p1) && (index != p1->index); p1 = t->next) {
143
        t = p1;
144
    }
145
 
146
    if (p1 == NULL) {
147
        return -1;
148
    }
149
 
150
    if (t == NULL) {
151
        firstevent = p1->next;
152
    } else {
153
        t->next = p1->next;
154
    }
155
    p1->next = freeevents;
156
    freeevents = p1;
157
 
158
    return 1;
159
}
160
 
161
void periodic_wake_up(void)
162
{                               /* CHANGE the NAME, please... */
163
    struct event *p, *pp;
164
    WORD tmp;
165
 
120 giacomo 166
    if(!use_tsc) {
167
        tmp = pit_read(frc);
168
        ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter);
169
        lastTime = tmp;
170
    }
171
 
2 pj 172
    activeInt++;
173
    if (activeInt == 1 && evt_prol != NULL) {
174
        evt_prol();
175
    }
176
 
120 giacomo 177
    if (!use_tsc) {
178
            ADDNANO2TIMESPEC(nts, &actTime);
179
    } else {
131 giacomo 180
            ll_read_timespec(&actTime);
120 giacomo 181
    }
182
 
2 pj 183
    for (p = firstevent; p != NULL; p = pp) {
184
/*
185
                SUBTIMESPEC(&(p->time), &actTime, &tmp);
186
                if ((tmp.tv_sec > 0) && (tmp.tv_nsec > 0)) {
187
                        break;
188
                } */
189
        if ((p->time.tv_sec > actTime.tv_sec) ||
190
            ((p->time.tv_sec == actTime.tv_sec)
191
             && (p->time.tv_nsec > actTime.tv_nsec))) {
192
            break;
193
        }
194
        pp = p->next;
195
        p->next = freeevents;
196
        freeevents = p;
197
        firstevent = pp;
198
        p->handler(p->par);
199
    }
200
 
201
    if (activeInt == 1 && evt_epil != NULL) {
202
        evt_epil();
203
    }
204
    activeInt--;
205
}
206
 
207
void event_init(struct ll_initparms *l)
208
{
209
    extern void ll_timer(void);
210
    int i;
211
    BYTE mask;
212
    TIME t;
213
 
40 pj 214
    IDT_place(0x40,ll_timer);
2 pj 215
 
216
    if (l->mode != LL_PERIODIC) {
120 giacomo 217
        message("One-shot mode\n");
2 pj 218
        t = 0;
219
        /* Mode: Binary/Mode 4/16 bit Time_const/Counter 0 */
220
        pit_init(0, TMR_MD4, 0xFFFF);   /* Timer 0, Mode 4, constant 0xFFFF */
221
    } else {
222
        t = l->tick;
223
        /* Translate the tick value in usec into a suitable time constant   */
224
        /* for 8254 timer chip; the chip is driven with a 1.19718 MHz       */
225
        /* frequency; then the effective frequency is given by the base     */
226
        /* frequency divided for the time constant; the tick is the inverse */
227
        /* of this effective frequency (in usec!)                           */
228
        /* Time-Constant = f_base (MHz) * tick (usec)                       */
229
        /* If T-C == 0 -> T-C = 65536 (Max available)                       */
230
        ticksize = t;
231
        t = t * 1197;
232
        t = t / 1000;
233
        /* Only for security! This should cause timer overrun */
234
        /* While 0 would set maximum period on timer          */
235
        if (t == 0)
236
            t = 1;
237
        pit_time_const = (WORD) (t & 0xFFFF);
238
        /* Mode: Binary/Mode 2/16 bit Time_const/Counter 0 */
239
        pit_init(0, TMR_MD2, t);        /* Timer 0, Mode 2, Time constant t */
240
 
241
 
242
    }
243
    timermode = l->mode;
40 pj 244
 
245
    if (ll_arch.x86.cpu > 4) {
2 pj 246
        /* Timer1: mode 0, time const 0... */
247
        pit_init(1, TMR_MD0, 0);
248
        frc = 1;
249
    } else {
250
        frc = 2;
251
        pit_init(2, TMR_MD0, 0);
40 pj 252
         outp(0x61, 3);
2 pj 253
    }
254
 
255
    mask = ll_in(0x21);
256
    mask &= 0xFE;               /* 0xFE = ~0x01 */
257
    ll_out(0x21, mask);
258
 
259
 
260
    /* Init the event list... */
261
    for (i = 0; i < MAX_EVENT; i++) {
262
        if (i < MAX_EVENT - 1) {
263
            eventlist[i].next = &(eventlist[i + 1]);
264
        }
265
        eventlist[i].index = i;
266
    }
267
    eventlist[MAX_EVENT - 1].next = NULL;
268
    freeevents = &(eventlist[0]);
269
 
270
    evt_prol = NULL;
271
    evt_epil = NULL;
272
 
273
    /* Initialization of the time variables for periodic mode */
274
    nts = ticksize * 1000;
275
    NULL_TIMESPEC(&actTime);
120 giacomo 276
 
277
    if (use_tsc) ll_init_advtimer();
2 pj 278
 
279
    /* Initialization of the general time variables */
280
    NULLPITSPEC(&globalCounter);
281
    lastTime = 0;
282
 
283
    if (timermode == LL_PERIODIC) {
284
        event_post = periodic_event_post;
285
        event_delete = periodic_event_delete;
286
    } else {
287
        event_post = oneshot_event_post;
288
        event_delete = oneshot_event_delete;
289
    }
40 pj 290
 
291
    /* Last but not least... */
292
    irq_unmask(0);
2 pj 293
}