X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Ftime.c;h=abdbb118e6f88488e8d6c7e01da876e6d69aa0de;hb=1e7db40300bc594cf708bb6082a6e05a268da946;hp=3a13904f819d0776793194cee9f37f7c474166de;hpb=8bc40333b1401d7616b225945fee53d972c2f418;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/time.c b/Kernel/arch/x86/time.c index 3a13904f..abdbb118 100644 --- a/Kernel/arch/x86/time.c +++ b/Kernel/arch/x86/time.c @@ -6,17 +6,29 @@ #include // === MACROS === -#define TIMER_FREQ 1024 //Hz +#define NUM_TIMERS 8 +#define TIMER_QUANTUM 100 +#define TIMER_RATE 13 // (Max: 15, Min: 2) - 15 = 1Hz, 13 = 4Hz, 10 = 1024Hz +#define TIMER_FREQ (32768>>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)) +// === TYPEDEFS === +typedef struct sTimer { + int FiresAfter; + void (*Callback)(void*); + void *Argument; +} tTimer; + // === PROTOTYPES === void Time_Interrupt(); +void Timer_CallTimers(); // === GLOBALS === Uint64 giTicks = 0; Sint64 giTimestamp = 0; Uint64 giPartMiliseconds = 0; +tTimer gTimers[NUM_TIMERS]; // === CODE === /** @@ -30,6 +42,14 @@ int Time_Setup() 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 @@ -57,8 +77,35 @@ void Time_Interrupt() giTimestamp ++; giPartMiliseconds -= 0x80000000; } + + //Log("giTimestamp = %lli", giTimestamp); + + Timer_CallTimers(); + + // Make sure the RTC Fires again + outb(0x70, 0x0C); // Select register C + inb(0x71); // Just throw away contents. } +#if 0 +/** + * \fn void Time_TimerThread() + */ +void Time_TimerThread() +{ + Sint64 next; + Threads_SetName("TIMER"); + + next = giTimestamp + TIMER_QUANTUM; + for(;;) + { + while(giTimestamp < next) Threads_Yield(); + next = giTimestamp + TIMER_QUANTUM; + Timer_CallTimers(); + } +} +#endif + /** * \fn Sint64 now() * \brief Return the current timestamp @@ -67,3 +114,72 @@ Sint64 now() { return giTimestamp; } + +/** + * \fn void Timer_CallTimers() + */ +void Timer_CallTimers() +{ + int i; + void (*callback)(void *); + + for(i = 0; + i < NUM_TIMERS; + i ++) + { + if(gTimers[i].Callback == NULL) continue; + 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) +{ + Sint64 dest = giTimestamp + Delay; + while(dest < giTimestamp) Threads_Yield(); +} + +// === EXPORTS === +EXPORT(now); +EXPORT(Time_CreateTimer); +EXPORT(Time_RemoveTimer); +EXPORT(Time_Delay);