Subversion Repositories shark

Rev

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