X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Ftime.c;h=37cc5e359208208f5513510f9610c2719dcc8d18;hb=09e044c2338f194d0f179aff6358bf9fd0739768;hp=adc2d13331122b0ccbd2d5f9d7fd9b7263289076;hpb=1ca0233bb1e142c536d09c35ce8dcdb209a2938b;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/time.c b/Kernel/arch/x86/time.c index adc2d133..37cc5e35 100644 --- a/Kernel/arch/x86/time.c +++ b/Kernel/arch/x86/time.c @@ -3,64 +3,111 @@ * Timekeeping * arch/x86/time.c */ -#include +#include // === MACROS === -#define NUM_TIMERS 8 #define TIMER_QUANTUM 100 -#define TIMER_FREQ 1024 //Hz +// 2^(15-rate), 15: 1HZ, 5: 1024Hz, 2: 8192Hz +// (Max: 15, Min: 2) - 15 = 1Hz, 13 = 4Hz, 12 = 8Hz, 11 = 16Hz 10 = 32Hz, 2 = 8192Hz +//#define TIMER_RATE 10 // 32 Hz +//#define TIMER_RATE 12 // 8 Hz +#define TIMER_RATE 14 // 2Hz +//#define TIMER_RATE 15 // 1HZ +#define TIMER_FREQ (0x8000>>TIMER_RATE) //Hz #define MS_PER_TICK_WHOLE (1000/(TIMER_FREQ)) -#define MS_PER_TICK_FRACT ((Uint64)(1000*TIMER_FREQ-((Uint64)MS_PER_TICK_WHOLE)*0x80000000/TIMER_FREQ)) +#define MS_PER_TICK_FRACT ((0x80000000*(1000%TIMER_FREQ))/TIMER_FREQ) -// === TYPEDEFS === -typedef struct sTimer { - int FiresAfter; - void (*Callback)(void*); - void *Argument; -} tTimer; - -// === PROTOTYPES === -void Time_Interrupt(); -void Timer_CallTimers(); +// === IMPORTS === +extern volatile Sint64 giTimestamp; +extern volatile Uint64 giTicks; +extern volatile Uint64 giPartMiliseconds; +extern void Timer_CallTimers(void); // === GLOBALS === -Uint64 giTicks = 0; -Sint64 giTimestamp = 0; -Uint64 giPartMiliseconds = 0; -tTimer gTimers[NUM_TIMERS]; +volatile Uint64 giTime_TSCAtLastTick = 0; +volatile Uint64 giTime_TSCPerTick = 0; + +// === PROTOTYPES === +Sint64 now(void); + int Time_Setup(void); +void Time_Interrupt(int); +Uint64 Time_ReadTSC(void); // === CODE === /** - * \fn int Time_Setup() + * \fn Sint64 now() + * \brief Return the current timestamp + */ +Sint64 now(void) +{ + Uint64 tsc = Time_ReadTSC(); + tsc -= giTime_TSCAtLastTick; + tsc *= MS_PER_TICK_WHOLE; + if( giTime_TSCPerTick ) { + tsc /= giTime_TSCPerTick; + } + else + tsc = 0; + return giTimestamp + tsc; +} + +/** + * \fn int Time_Setup(void) * \brief Sets the system time from the Realtime-Clock */ -int Time_Setup() +int Time_Setup(void) { Uint8 val; + Log_Log("Timer", "RTC Timer firing at %iHz (%i divisor), %i.0x%08x", + TIMER_FREQ, TIMER_RATE, MS_PER_TICK_WHOLE, MS_PER_TICK_FRACT); + outb(0x70, inb(0x70)&0x7F); // Disable NMIs __asm__ __volatile__ ("cli"); // Disable normal interrupts + // Set IRQ8 firing rate + outb(0x70, 0x0A); // Set the index to register A + val = inb(0x71); // Get the current value of register A + outb(0x70, 0x0A); // Reset index to A + val &= 0xF0; + val |= TIMER_RATE; + outb(0x71, val); // Update the timer rate + // Enable IRQ8 outb(0x70, 0x0B); // Set the index to register B val = inb(0x71); // Read the current value of register B outb(0x70, 0x0B); // Set the index again (a read will reset the index to register D) outb(0x71, val | 0x40); // Write the previous value or'd with 0x40. This turns on bit 6 of register D - __asm__ __volatile__ ("sti"); // Disable normal interrupts - outb(0x70, inb(0x70)|0x80); // Disable NMIs + __asm__ __volatile__ ("sti"); // Re-enable normal interrupts + outb(0x70, inb(0x70)|0x80); // Re-enable NMIs // Install IRQ Handler - //IRQ_AddHandler(8, Time_Interrupt); + IRQ_AddHandler(8, Time_Interrupt); + + // Make sure the RTC actually fires + outb(0x70, 0x0C); // Select register C + inb(0x71); // Just throw away contents. + return 0; } /** - * \fn void Time_Interrupt() * \brief Called on the timekeeping IRQ + * \param irq IRQ number (unused) */ -void Time_Interrupt() +void Time_Interrupt(int irq) { + //Log("RTC Tick"); + Uint64 curTSC = Time_ReadTSC(); + + if( giTime_TSCAtLastTick ) + { + giTime_TSCPerTick = curTSC - giTime_TSCAtLastTick; + //Log("curTSC = %lli, giTime_TSCPerTick = %lli", curTSC, giTime_TSCPerTick); + } + giTime_TSCAtLastTick = curTSC; + giTicks ++; giTimestamp += MS_PER_TICK_WHOLE; giPartMiliseconds += MS_PER_TICK_FRACT; @@ -69,8 +116,6 @@ void Time_Interrupt() giPartMiliseconds -= 0x80000000; } - //Log("giTimestamp = %lli", giTimestamp); - Timer_CallTimers(); // Make sure the RTC Fires again @@ -78,11 +123,11 @@ void Time_Interrupt() inb(0x71); // Just throw away contents. } +#if 0 /** - * \fn void Time_TimerThread() + * \fn void Time_TimerThread(void) */ -#if 0 -void Time_TimerThread() +void Time_TimerThread(void) { Sint64 next; Threads_SetName("TIMER"); @@ -97,76 +142,9 @@ void Time_TimerThread() } #endif -/** - * \fn Sint64 now() - * \brief Return the current timestamp - */ -Sint64 now() -{ - return giTimestamp; -} - -/** - * \fn void Timer_CallTimers() - */ -void Timer_CallTimers() -{ - int i; - void (*callback)(void *); - - for(i = 0; - i < NUM_TIMERS; - i ++) - { - //Log("Timer %i", i); - if(gTimers[i].Callback == NULL) continue; - Log("%i - %lli < %lli", i, giTimestamp, gTimers[i].FiresAfter); - if(giTimestamp < gTimers[i].FiresAfter) continue; - callback = gTimers[i].Callback; - gTimers[i].Callback = NULL; - callback(gTimers[i].Argument); - } -} - -/** - * \fn int Time_CreateTimer(int Delta, void *Callback, void *Argument) - */ -int Time_CreateTimer(int Delta, void *Callback, void *Argument) -{ - int ret; - - if(Callback == NULL) return -1; - - for(ret = 0; - ret < NUM_TIMERS; - ret++) - { - if(gTimers[ret].Callback != NULL) continue; - gTimers[ret].Callback = Callback; - gTimers[ret].FiresAfter = giTimestamp + Delta; - gTimers[ret].Argument = Argument; - Log("Callback = %p", Callback); - Log("Timer %i fires at %lli", ret, gTimers[ret].FiresAfter); - return ret; - } - return -1; -} - -/** - * \fn void Time_RemoveTimer(int ID) - */ -void Time_RemoveTimer(int ID) -{ - if(ID < 0 || ID >= NUM_TIMERS) return; - gTimers[ID].Callback = NULL; -} - -/** - * \fn void Time_Delay(int Delay) - * \brief Delay for a small ammount of time - */ -void Time_Delay(int Delay) +Uint64 Time_ReadTSC(void) { - Sint64 dest = giTimestamp + Delay; - while(dest < giTimestamp) Threads_Yield(); + Uint32 a, d; + __asm__ __volatile__ ("rdtsc" : "=a" (a), "=d" (d)); + return ((Uint64)d << 32) | a; }