|
|
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.