X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fclock.c;h=fcdc698bb15b8c9a0cad8a950312fa1b3b35e965;hb=c973788346e984a3d91f443008fdd613c30e3185;hp=e32bf1b717a51a77c2bfb918368f6f4d47d2e59d;hpb=1ca05b0f393c0201c0e8efe87831edddb6a53532;p=seabios.git diff --git a/src/clock.c b/src/clock.c index e32bf1b..fcdc698 100644 --- a/src/clock.c +++ b/src/clock.c @@ -1,6 +1,6 @@ // 16bit code to handle system clocks. // -// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2008-2010 Kevin O'Connor // Copyright (C) 2002 MandrakeSoft S.A. // // This file may be distributed under the terms of the GNU LGPLv3 license. @@ -12,7 +12,7 @@ #include "pic.h" // eoi_pic1 #include "bregs.h" // struct bregs #include "biosvar.h" // GET_GLOBAL -#include "usb-hid.h" // usb_check_key +#include "usb-hid.h" // usb_check_event // RTC register flags #define RTC_A_UIP 0x80 @@ -54,9 +54,6 @@ * TSC timer ****************************************************************/ -#define PIT_TICK_RATE 1193180 // Underlying HZ of PIT -#define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer -#define TICKS_PER_DAY (u32)((u64)60*60*24*PIT_TICK_RATE / PIT_TICK_INTERVAL) #define CALIBRATE_COUNT 0x800 // Approx 1.7ms u32 cpu_khz VAR16VISIBLE; @@ -97,7 +94,7 @@ tscdelay(u64 diff) { u64 start = rdtscll(); u64 end = start + diff; - while (!check_time(end)) + while (!check_tsc(end)) cpu_relax(); } @@ -106,7 +103,7 @@ tscsleep(u64 diff) { u64 start = rdtscll(); u64 end = start + diff; - while (!check_time(end)) + while (!check_tsc(end)) yield(); } @@ -158,18 +155,19 @@ rtc_updating(void) // to 0, and will return 0 if such a transition occurs. A -1 // is returned only after timing out. The maximum period // that this bit should be set is constrained to (1984+244) - // useconds, so we wait for 3 msec max. + // useconds, but we wait for longer just to be sure. if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0) return 0; - u64 end = calc_future_tsc(3); - do { + u64 end = calc_future_tsc(15); + for (;;) { if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0) return 0; - } while (!check_time(end)); - - // update-in-progress never transitioned to 0 - return -1; + if (check_tsc(end)) + // update-in-progress never transitioned to 0 + return -1; + yield(); + } } static void @@ -213,10 +211,9 @@ timer_setup(void) u32 ticks = (hours * 60 + minutes) * 60 + seconds; ticks = ((u64)ticks * PIT_TICK_RATE) / PIT_TICK_INTERVAL; SET_BDA(timer_counter, ticks); - SET_BDA(timer_rollover, 0); - enable_hwirq(0, entry_08); - enable_hwirq(8, entry_70); + enable_hwirq(0, FUNC16(entry_08)); + enable_hwirq(8, FUNC16(entry_70)); } @@ -224,10 +221,40 @@ timer_setup(void) * Standard clock functions ****************************************************************/ +#define TICKS_PER_DAY (u32)((u64)60*60*24*PIT_TICK_RATE / PIT_TICK_INTERVAL) + +// Calculate the timer value at 'count' number of full timer ticks in +// the future. +u32 +calc_future_timer_ticks(u32 count) +{ + return (GET_BDA(timer_counter) + count + 1) % TICKS_PER_DAY; +} + +// Return the timer value that is 'msecs' time in the future. +u32 +calc_future_timer(u32 msecs) +{ + if (!msecs) + return GET_BDA(timer_counter); + u32 kticks = DIV_ROUND_UP((u64)msecs * PIT_TICK_RATE, PIT_TICK_INTERVAL); + u32 ticks = DIV_ROUND_UP(kticks, 1000); + return calc_future_timer_ticks(ticks); +} + +// Check if the given timer value has passed. +int +check_timer(u32 end) +{ + return (((GET_BDA(timer_counter) + TICKS_PER_DAY - end) % TICKS_PER_DAY) + < (TICKS_PER_DAY/2)); +} + // get current clock count static void handle_1a00(struct bregs *regs) { + yield(); u32 ticks = GET_BDA(timer_counter); regs->cx = ticks >> 16; regs->dx = ticks; @@ -452,7 +479,7 @@ handle_08(void) SET_BDA(timer_counter, counter); - usb_check_key(); + usb_check_event(); // chain to user timer tick INT #0x1c u32 eax=0, flags;