Subversion Repositories shark

Rev

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