Merge branch 'master' of github.com:thepowersgang/acess2
[tpg/acess2.git] / KernelLand / Kernel / arch / x86_64 / time.c
1 /*
2  * Acess2 Kernel
3  * Timekeeping
4  * arch/x86_64/time.c
5  */
6 #include <acess.h>
7 #include <arch_config.h>
8
9 // === MACROS ===
10 #define TIMER_QUANTUM   100
11 #define TIMER_FREQ      PIT_TIMER_BASE_N/(PIT_TIMER_BASE_D*PIT_TIMER_DIVISOR)
12 #define MS_PER_TICK_WHOLE       (1000*(PIT_TIMER_BASE_D*PIT_TIMER_DIVISOR)/PIT_TIMER_BASE_N)
13 #define MS_PER_TICK_FRACT       ((0x80000000ULL*1000ULL*PIT_TIMER_BASE_D*PIT_TIMER_DIVISOR/PIT_TIMER_BASE_N)&0x7FFFFFFF)
14
15 // === IMPORTS ===
16 extern volatile Sint64  giTimestamp;
17 extern volatile Uint64  giTicks;
18 extern volatile Uint64  giPartMiliseconds;
19 extern void     Timer_CallTimers(void);
20
21 // === GLOBALS ===
22 volatile Uint64 giTime_TSCAtLastTick = 0;
23 volatile Uint64 giTime_TSCPerTick = 0;
24
25 // === PROTOTYPES ===
26 //Sint64        now(void);
27  int    Time_Setup(void);
28 void    Time_UpdateTimestamp(void);
29 Uint64  Time_ReadTSC(void);
30
31 // === CODE ===
32 /**
33  * \fn Sint64 now()
34  * \brief Return the current timestamp
35  */
36 Sint64 now(void)
37 {
38         Uint64  tsc = Time_ReadTSC();
39         tsc -= giTime_TSCAtLastTick;
40         tsc *= MS_PER_TICK_WHOLE;
41         if( giTime_TSCPerTick ) {
42                 tsc /= giTime_TSCPerTick;
43         }
44         else
45                 tsc = 0;
46         return giTimestamp + tsc;
47 }
48
49 /**
50  * \fn int Time_Setup(void)
51  * \brief Sets the system time from the Realtime-Clock
52  */
53 int Time_Setup(void)
54 {
55         Log_Log("Timer", "PIT Timer firing at %iHz, %i.0x%08x miliseconds per tick",
56                 TIMER_FREQ, MS_PER_TICK_WHOLE, MS_PER_TICK_FRACT);
57
58         // TODO: Read time from RTC
59         
60         return 0;
61 }
62
63 /**
64  * \brief Called on the timekeeping IRQ
65  */
66 void Time_UpdateTimestamp(void)
67 {
68         Uint64  curTSC = Time_ReadTSC();
69         
70         if( giTime_TSCAtLastTick )
71         {
72                 giTime_TSCPerTick = curTSC - giTime_TSCAtLastTick;
73         }
74         giTime_TSCAtLastTick = curTSC;
75         
76         giTicks ++;
77         giTimestamp += MS_PER_TICK_WHOLE;
78         giPartMiliseconds += MS_PER_TICK_FRACT;
79         if(giPartMiliseconds > 0x80000000) {
80                 giTimestamp ++;
81                 giPartMiliseconds -= 0x80000000;
82         }
83         
84         Timer_CallTimers();
85 }
86
87 #if 0
88 /**
89  * \fn void Time_TimerThread(void)
90  */
91 void Time_TimerThread(void)
92 {
93         Sint64  next;
94         Threads_SetName("TIMER");
95         
96         next = giTimestamp + TIMER_QUANTUM;
97         for(;;)
98         {
99                 while(giTimestamp < next)       Threads_Yield();
100                 next = giTimestamp + TIMER_QUANTUM;     
101                 Timer_CallTimers();
102         }
103 }
104 #endif
105
106 Uint64 Time_ReadTSC(void)
107 {
108         Uint32  a, d;
109         __asm__ __volatile__ ("rdtsc" : "=a" (a), "=d" (d));
110         return ((Uint64)d << 32) | a;
111 }

UCC git Repository :: git.ucc.asn.au