Subversion Repositories shark

Rev

Rev 303 | Rev 305 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
40 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
 
40 pj 29
/*      Time Event routines     (one shot mode) */
30
 
31
#include <ll/i386/stdlib.h>
32
#include <ll/i386/mem.h>
33
#include <ll/i386/pit.h>
299 giacomo 34
#include <ll/i386/apic.h>
131 giacomo 35
#include <ll/i386/advtimer.h>
304 giacomo 36
#include <ll/i386/error.h>
131 giacomo 37
 
40 pj 38
#include <ll/sys/ll/ll-data.h>
304 giacomo 39
#include <ll/sys/ll/ll-func.h>
40 pj 40
#include <ll/sys/ll/time.h>
41
#include <ll/sys/ll/event.h>
42
 
43
FILE(EventOneShot);
44
 
45
extern int activeInt;
46
int activeEvent;
47
 
48
extern BYTE frc;
49
 
50
extern struct event eventlist[MAX_EVENT];
51
extern WORD lastTime;
52
extern struct pitspec globalCounter;
53
 
54
extern struct event *freeevents;
55
extern struct event *firstevent;
56
 
57
extern void (*evt_prol) (void);
58
extern void (*evt_epil) (void);
59
 
120 giacomo 60
extern unsigned char use_tsc;
304 giacomo 61
extern unsigned char use_apic;
62
extern unsigned long long apic_clk_per_msec;
120 giacomo 63
 
304 giacomo 64
#define barrier() __asm__ __volatile__("" ::: "memory");
40 pj 65
 
66
/* Switched to timespec */
67
int oneshot_event_post(struct timespec time, void (*handler) (void *p),
68
                       void *par)
69
{
70
    struct event *p;
71
    struct event *p1, *t;
72
    struct timespec now, tmp;
73
    int done;
74
    DWORD tnext;
75
 
76
    if (!freeevents) {
304 giacomo 77
        message("NO FREE EVENTS !\n");
78
        ll_abort(20);
40 pj 79
        return -1;
80
    }
81
    /* Extract from the ``free events'' queue */
82
    p = freeevents;
83
    freeevents = p->next;
84
 
85
    /* Fill the event fields */
86
    p->handler = handler;
87
    TIMESPEC_ASSIGN(&(p->time), &time);
88
    p->par = par;
89
 
90
    /* ...And insert it in the event queue!!! */
91
 
92
    t = NULL;
93
    done = 0;
94
    /* walk through list, finding spot, adjusting ticks parameter */
95
    for (p1 = firstevent; p1; p1 = t->next) {
96
        if (TIMESPEC_A_GT_B((&time), (&p1->time))) {
97
            t = p1;
98
        } else
99
            break;
100
    }
101
 
102
    /* adjust next entry */
103
    if (t) {
104
        t->next = p;
105
    } else {
106
        firstevent = p;
107
        if (!activeEvent) {
108
          ll_gettime(TIME_NEW, &now);
109
          if (TIMESPEC_A_GT_B(&now, &(firstevent->time))) {
110
            NULL_TIMESPEC(&tmp);
111
          } else {
112
            SUBTIMESPEC(&(firstevent->time), &now, &tmp);
113
          }
114
          tnext = TIMESPEC2USEC(&tmp);
299 giacomo 115
          if (!use_apic) {
116
            tnext = (signed long long)(tnext) * 1193182 / 1000000;
117
            pit_setconstant(0, tnext);
118
          } else {
119
            tnext = (signed long long)(tnext) * apic_clk_per_msec / 1000;
303 giacomo 120
            set_APIC_timer(tnext);
299 giacomo 121
          }
40 pj 122
        }
123
    }
124
    p->next = p1;
125
 
126
    return p->index;
127
}
128
 
129
 
130
 
131
void oneshot_wake_up(void)
132
{                               /* CHANGE the NAME, please... */
133
    struct event *p = NULL, *pp;
134
    struct timespec now, ttmp;
135
    WORD tmp;
136
    DWORD tnext;
137
 
120 giacomo 138
    if (!use_tsc) {
139
 
140
        tmp = pit_read(frc);
141
        ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter);
142
        lastTime = tmp;
40 pj 143
 
120 giacomo 144
        PITSPEC2TIMESPEC(&globalCounter, &now);
40 pj 145
 
120 giacomo 146
    } else {
147
 
131 giacomo 148
        ll_read_timespec(&now);
120 giacomo 149
 
150
    }
151
 
40 pj 152
    if (firstevent != NULL) {
153
        activeEvent = 1;
154
        if (TIMESPEC_A_GT_B(&now, &(firstevent->time))) {
155
            if (!activeInt && evt_prol != NULL) {
156
                evt_prol();
157
            }
158
            activeInt++;
159
 
160
            for (p = firstevent; p != NULL; p = pp) {
161
                if ((p->time.tv_sec > now.tv_sec) ||
162
                    ((p->time.tv_sec == now.tv_sec)
163
                     && (p->time.tv_nsec > now.tv_nsec))) {
164
                    break;
165
                }
166
                pp = p->next;
167
                p->next = freeevents;
168
                freeevents = p;
169
                firstevent = pp;
170
                p->handler(p->par);
171
            }
172
 
173
            if (activeInt == 1 && evt_epil != NULL) {
174
                evt_epil();
175
            }
176
            activeInt--;
177
        }
178
 
304 giacomo 179
        barrier();
180
 
120 giacomo 181
        if (!use_tsc) {
182
 
183
            tmp = pit_read(frc);
184
            ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter);
185
            lastTime = tmp;
40 pj 186
 
120 giacomo 187
            PITSPEC2TIMESPEC(&globalCounter, &now);
40 pj 188
 
120 giacomo 189
        } else {
190
 
131 giacomo 191
            ll_read_timespec(&now);
120 giacomo 192
 
193
        }
194
 
195
 
40 pj 196
        if (TIMESPEC_A_GT_B(&now, &(firstevent->time))) {
197
            NULL_TIMESPEC(&ttmp);
198
        } else {
199
            SUBTIMESPEC(&(firstevent->time), &now, &ttmp);
200
        }
201
        /*  SUBTIMESPEC(&(firstevent->time), &now, &ttmp); */
202
        tnext = TIMESPEC2USEC(&ttmp);
299 giacomo 203
        if (!use_apic) {
204
          tnext = (signed long long)(tnext) * 1193182 / 1000000;
205
          pit_setconstant(0, tnext);
206
        } else {
207
          tnext = (signed long long)(tnext) * apic_clk_per_msec / 1000;
303 giacomo 208
          set_APIC_timer(tnext);
299 giacomo 209
        }
40 pj 210
        activeEvent = 0;
211
    } else {
299 giacomo 212
        if (!use_apic) {
213
          pit_setconstant(0, 0xFFFF);
214
        } else {
303 giacomo 215
          set_APIC_timer(0xFFFFFFFF);
299 giacomo 216
        }
40 pj 217
    }
304 giacomo 218
 
40 pj 219
}
220
 
221
int oneshot_event_delete(int index)
222
{
223
    struct event *p1, *t;
224
    struct timespec tmp, now;
225
    DWORD tnext;
226
    int firstdeleted = FALSE;
227
 
228
    t = NULL;
229
    /* walk through list, finding spot, adjusting ticks parameter */
230
 
231
    for (p1 = firstevent; (p1) && (index != p1->index); p1 = t->next) {
232
        t = p1;
233
    }
234
 
235
    if (p1 == NULL) {
236
        return -1;
237
    }
238
    if (t == NULL) {
239
        firstevent = p1->next;
240
        firstdeleted = TRUE;
241
    } else {
242
        t->next = p1->next;
243
    }
244
 
245
    p1->next = freeevents;
246
    freeevents = p1;
247
 
248
    if (!activeEvent) {
249
      if (firstevent == NULL) {
299 giacomo 250
        if (!use_apic) {
251
          pit_setconstant(0, 0xFFFF);
252
        } else {
303 giacomo 253
          set_APIC_timer(0xFFFFFFFF);
299 giacomo 254
        }
40 pj 255
      } else {
256
        if (firstdeleted) {
257
          ll_gettime(TIME_NEW, &now);
258
          if (TIMESPEC_A_GT_B(&now, &(firstevent->time))) {
259
            NULL_TIMESPEC(&tmp);
260
          } else {
261
            SUBTIMESPEC(&(firstevent->time), &now, &tmp);
262
          }
263
          /*SUBTIMESPEC(&now, &(firstevent->time), &tmp); */
264
          tnext = TIMESPEC2USEC(&tmp);
299 giacomo 265
          if (!use_apic) {
266
            tnext = (signed long long)(tnext) * 1193182 / 1000000;
267
            pit_setconstant(0, tnext);
268
          } else {
269
            tnext = (signed long long)(tnext) * apic_clk_per_msec / 1000;
303 giacomo 270
            set_APIC_timer(tnext);
299 giacomo 271
          }
40 pj 272
        }
273
      }
274
    }
275
    return 1;
276
}