|
|
1.1 root 1: /*
2: * Copyright (c) 1999 University of Utah and the Flux Group.
3: * All rights reserved.
4: *
5: * This file is part of the Flux OSKit. The OSKit is free software, also known
6: * as "open source;" you can redistribute it and/or modify it under the terms
7: * of the GNU General Public License (GPL), version 2, as published by the Free
8: * Software Foundation (FSF). To explore alternate licensing terms, contact
9: * the University of Utah at [email protected] or +1-801-585-3271.
10: *
11: * The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
12: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13: * FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have
14: * received a copy of the GPL along with the OSKit; see the file COPYING. If
15: * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
16: */
17: /*
18: * Timer interrupt support.
19: */
20:
21: #include <oskit/dev/dev.h>
22:
23: #include <oskit/machine/pc/pit.h>
24:
25: #include <machine/mach_param.h> /* HZ */
26: #include <machine/spl.h>
27:
28: #include "../ds_oskit.h"
29:
30:
31: #define NTIMERS 4
32: #define TIMER_FREQ HZ
33: #define TIMER_VALUE (PIT_HZ / TIMER_FREQ)
34:
35: struct timer_handler {
36: void (*func)(void);
37: struct timer_handler *next;
38: };
39:
40: static struct timer_handler *timer_head, *timer_free;
41: static struct timer_handler timer_data[NTIMERS];
42:
43:
44: /*
45: * This is called on every Mach clock tick, at splsoftclock.
46: * These handlers want to be called with interrupts disabled,
47: * but then reenable and redisable them before returning.
48: */
49: void
50: softclock_oskit (void)
51: {
52: struct timer_handler *th;
53: osenv_intr_disable();
54: for (th = timer_head; th; th = th->next)
55: (*th->func)();
56: osenv_intr_enable();
57:
58: oskit_softint();
59: }
60:
61: /*
62: * Initialize timers.
63: */
64: void
65: osenv_timer_init()
66: {
67: static int initialized = 0; /* guard against multiple invocations */
68: int i;
69:
70: if (initialized)
71: return;
72:
73: initialized = 1;
74:
75: for (i = 0; i < NTIMERS; i++)
76: timer_data[i].next = &timer_data[i + 1];
77: timer_data[NTIMERS - 1].next = 0;
78: timer_free = &timer_data[0];
79: }
80:
81: /*
82: * Turn all timers off.
83: */
84: void
85: osenv_timer_shutdown()
86: {
87: osenv_log(OSENV_LOG_DEBUG, "Shutting down timer\n");
88: osenv_timer_pit_shutdown();
89: }
90:
91: /*
92: * Register a timer handler to be called at the specified frequency.
93: */
94: void
95: osenv_timer_register(void (*func)(void), int freq)
96: {
97: struct timer_handler *th;
98: spl_t s;
99:
100: /* XXX */
101: osenv_timer_init();
102:
103: if (timer_free == 0)
104: osenv_panic("%s:%d: ran out of entries", __FILE__, __LINE__);
105: /*
106: * XXX
107: */
108: if (freq != TIMER_FREQ)
109: osenv_panic("%s:%d: bad freq", __FILE__, __LINE__);
110: if (func == 0)
111: osenv_panic("%s:%d: null function", __FILE__, __LINE__);
112:
113: s = splio ();
114:
115: th = timer_free;
116: timer_free = th->next;
117: th->next = timer_head;
118: timer_head = th;
119: th->func = func;
120:
121: splx (s);
122: }
123:
124:
125: /*
126: * Frequency and function address uniquely identify which to remove since
127: * equal values are equivelent.
128: */
129: void
130: osenv_timer_unregister(void (*func)(void), int freq)
131: {
132: spl_t s;
133: struct timer_handler *th, **prev;
134:
135: if (freq != TIMER_FREQ)
136: osenv_panic("%s:%d: bad freq", __FILE__, __LINE__);
137:
138: s = splio ();
139:
140: /* move the timer from the run-queue to the unused-queue */
141: prev = &timer_head;
142: th = timer_head;
143:
144: while (th && (th->func != func)) {
145: prev = &th->next;
146: th = th->next;
147: }
148: if (!th) {
149: osenv_log(OSENV_LOG_WARNING, "Timer handler not found\n");
150: } else {
151: /* have the active list skip over it */
152: *prev = th->next;
153:
154: /* place in inactive queue */
155: th->next = timer_free;
156: timer_free = th;
157: }
158:
159: splx (s);
160: }
161:
162:
163: /*
164: * Spin for a small amount of time, specified in nanoseconds,
165: * without blocking or enabling interrupts.
166: */
167: void
168: osenv_timer_spin(long nanosec)
169: {
170: int prev_val = osenv_timer_pit_read();
171:
172: while (nanosec > 0) {
173: int val = osenv_timer_pit_read();
174: if (val > prev_val)
175: prev_val += TIMER_VALUE;
176: nanosec -= (prev_val - val) * PIT_NS;
177: prev_val = val;
178: }
179: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.