Kernel/x86 - Added USE_ACPICA makefile variable to easily enable/disable
[tpg/acess2.git] / KernelLand / Kernel / arch / x86 / time.c
1 /*
2  * Acess2 Kernel
3  * Timekeeping
4  * arch/x86/time.c
5  */
6 #include <acess.h>
7
8 // === MACROS ===
9 #define TIMER_QUANTUM   100
10 // 2^(15-rate), 14: 2Hz, 5: 1024Hz, 2: 8192Hz
11 // (Max: 14, Min: 2) - 14 = 2Hz, 13 = 4Hz, 12 = 8Hz, 11 = 16Hz 10 = 32Hz, 2 = 8192Hz
12 //#define TIMER_RATE    10      // 32 Hz
13 //#define TIMER_RATE    12      // 8 Hz
14 #define TIMER_RATE      14      // 2 Hz - Lowest
15 #define TIMER_FREQ      (0x8000>>TIMER_RATE)    //Hz
16 #define MS_PER_TICK_WHOLE       (1000/(TIMER_FREQ))
17 #define MS_PER_TICK_FRACT       ((0x80000000*(1000%TIMER_FREQ))/TIMER_FREQ)
18
19 // === IMPORTS ===
20 extern volatile Sint64  giTimestamp;
21 extern volatile Uint64  giTicks;
22 extern volatile Uint64  giPartMiliseconds;
23 extern void     Timer_CallTimers(void);
24
25 // === GLOBALS ===
26 volatile Uint64 giTime_TSCAtLastTick = 0;
27 volatile Uint64 giTime_TSCPerTick = 0;
28
29 // === PROTOTYPES ===
30 //Sint64        now(void);
31  int    Time_Setup(void);
32 void    Time_Interrupt(int IRQ, void *Ptr);
33 Uint64  Time_ReadTSC(void);
34
35 // === CODE ===
36 /**
37  * \fn Sint64 now()
38  * \brief Return the current timestamp
39  */
40 Sint64 now(void)
41 {
42         Uint64  tsc = Time_ReadTSC();
43         tsc -= giTime_TSCAtLastTick;
44         tsc *= MS_PER_TICK_WHOLE;
45         if( giTime_TSCPerTick ) {
46                 tsc /= giTime_TSCPerTick;
47         }
48         else
49                 tsc = 0;
50         return giTimestamp + tsc;
51 }
52
53 /**
54  * \fn int Time_Setup(void)
55  * \brief Sets the system time from the Realtime-Clock
56  */
57 int Time_Setup(void)
58 {
59         Uint8   val;
60         
61         Log_Log("Timer", "RTC Timer firing at %iHz (%i divisor), %i.0x%08x",
62                 TIMER_FREQ, TIMER_RATE, MS_PER_TICK_WHOLE, MS_PER_TICK_FRACT);
63         
64         outb(0x70, inb(0x70)&0x7F);     // Disable NMIs
65         __asm__ __volatile__ ("cli");   // Disable normal interrupts
66         
67         // Set IRQ8 firing rate
68         outb(0x70, 0x0A);       // Set the index to register A
69         val = inb(0x71); // Get the current value of register A
70         val &= 0xF0;
71         val |= TIMER_RATE+1;
72         outb(0x70, 0x0A); // Reset index to A
73         outb(0x71, val);        // Update the timer rate
74                 
75         // Enable IRQ8
76         outb(0x70, 0x0B);       // Set the index to register B
77         val = inb(0x71);        // Read the current value of register B
78         outb(0x70, 0x0B);       // Set the index again (a read will reset the index to register D)
79         outb(0x71, val | 0x40); // Write the previous value or'd with 0x40. This turns on bit 6 of register D
80         
81         __asm__ __volatile__ ("sti");   // Re-enable normal interrupts
82         outb(0x70, inb(0x70)|0x80);     // Re-enable NMIs
83         
84         // Install IRQ Handler
85         IRQ_AddHandler(8, Time_Interrupt, NULL);
86         
87         // Make sure the RTC actually fires
88         outb(0x70, 0x0C); // Select register C
89         inb(0x71);      // Just throw away contents.
90         
91         return 0;
92 }
93
94 /**
95  * \brief Called on the timekeeping IRQ
96  */
97 void Time_Interrupt(int IRQ, void *Ptr)
98 {
99         Uint64  curTSC = Time_ReadTSC();
100         
101         if( giTime_TSCAtLastTick )
102         {
103                 giTime_TSCPerTick = curTSC - giTime_TSCAtLastTick;
104         }
105         giTime_TSCAtLastTick = curTSC;
106         
107         giTicks ++;
108         giTimestamp += MS_PER_TICK_WHOLE;
109         giPartMiliseconds += MS_PER_TICK_FRACT;
110         if(giPartMiliseconds > 0x80000000) {
111                 giTimestamp ++;
112                 giPartMiliseconds -= 0x80000000;
113         }
114         
115         Timer_CallTimers();
116
117         // Make sure the RTC Fires again
118         outb(0x70, 0x0C); // Select register C
119         inb(0x71);      // Just throw away contents.
120 }
121
122 Uint64 Time_ReadTSC(void)
123 {
124         Uint32  a, d;
125         __asm__ __volatile__ ("rdtsc" : "=a" (a), "=d" (d));
126         return ((Uint64)d << 32) | a;
127 }

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