/* * Copyright 2010 Stefan Lankes, Chair for Operating Systems, * RWTH Aachen University * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of MetalSVM. */ #include #include #include #include #include #include #include /* * This will keep track of how many ticks that the system * has been running for */ static volatile uint64_t timer_ticks = 0; static unsigned int curr_timer_freq = 18; void schedule_entry(void); /* * Handles the timer. In this case, it's very simple: We * increment the 'timer_ticks' variable every time the * timer fires. */ static void timer_handler(struct regs *r) { //unsigned int tmp; /* Increment our 'tick counter' */ timer_ticks++; /* * Every TIMER_FREQ clocks (approximately 1 second), we will * display a message on the screen */ /*tmp = (unsigned int) (timer_ticks & 0xFFFFFFFF); if (tmp % TIMER_FREQ == 0) { kputs("One second has passed\n"); }*/ if (current_task && !(current_task->ip)) { current_task->ip = r->eip; r->eip = (unsigned int) schedule_entry; } } /* * This will continuously loop until the given time has * been reached */ void timer_wait(unsigned int ticks) { uint64_t eticks = timer_ticks + ticks; while (timer_ticks < eticks) schedule(); } /* * Sets up the system clock by installing the timer handler * into IRQ0 */ int timer_init(void) { /* Installs 'timer_handler' to IRQ0 */ irq_install_handler(0, timer_handler); return 0; } #define LATCH ((CLOCK_TICK_RATE + TIMER_FREQ/2) / TIMER_FREQ) int timer_set_frequency(unsigned int freq) { irq_disable(); /* set the timer frequency */ outportb(0x43, 0x34); udelay(10); outportb(0x40, LATCH & 0xFF); /* low byte */ udelay(10); outportb(0x40, LATCH >> 8); /* high byte */ curr_timer_freq = freq; irq_enable(); return 0; } unsigned int timer_get_frequency(void) { return curr_timer_freq; }