4b2e0678453e1c88bd89f947422eff11c92077b7
[tpg/acess2.git] / 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), 15: 1HZ, 5: 1024Hz, 2: 8192Hz
11 #define TIMER_RATE      12      // (Max: 15, Min: 2) - 15 = 1Hz, 13 = 4Hz, 12 = 8Hz, 11 = 16Hz 10 = 32Hz, 2
12 #define TIMER_FREQ      (0x8000>>TIMER_RATE)    //Hz
13 #define MS_PER_TICK_WHOLE       (1000/(TIMER_FREQ))
14 #define MS_PER_TICK_FRACT       ((Uint64)(1000*TIMER_FREQ-((Uint64)MS_PER_TICK_WHOLE)*0x80000000/TIMER_FREQ))
15
16 // === IMPORTS ===
17 extern Sint64   giTimestamp;
18 extern Uint64   giTicks;
19 extern Uint64   giPartMiliseconds;
20
21 // === PROTOTYPES ===
22 void    Time_Interrupt();
23
24 // === CODE ===
25 /**
26  * \fn int Time_Setup()
27  * \brief Sets the system time from the Realtime-Clock
28  */
29 int Time_Setup()
30 {
31         Uint8   val;
32         
33         outb(0x70, inb(0x70)&0x7F);     // Disable NMIs
34         __asm__ __volatile__ ("cli");   // Disable normal interrupts
35         
36         // Set IRQ8 firing rate
37         outb(0x70, 0x0A);       // Set the index to register A
38         val = inb(0x71); // Get the current value of register A
39         outb(0x70, 0x0A); // Reset index to A
40         val &= 0xF0;
41         val |= TIMER_RATE;
42         outb(0x71, val);        // Update the timer rate
43                 
44         // Enable IRQ8
45         outb(0x70, 0x0B);       // Set the index to register B
46         val = inb(0x71);        // Read the current value of register B
47         outb(0x70, 0x0B);       // Set the index again (a read will reset the index to register D)
48         outb(0x71, val | 0x40); // Write the previous value or'd with 0x40. This turns on bit 6 of register D
49         
50         __asm__ __volatile__ ("sti");   // Disable normal interrupts
51         outb(0x70, inb(0x70)|0x80);     // Disable NMIs
52         
53         // Install IRQ Handler
54         IRQ_AddHandler(8, Time_Interrupt);
55         return 0;
56 }
57
58 /**
59  * \fn void Time_Interrupt()
60  * \brief Called on the timekeeping IRQ
61  */
62 void Time_Interrupt()
63 {
64         giTicks ++;
65         giTimestamp += MS_PER_TICK_WHOLE;
66         giPartMiliseconds += MS_PER_TICK_FRACT;
67         if(giPartMiliseconds > 0x80000000) {
68                 giTimestamp ++;
69                 giPartMiliseconds -= 0x80000000;
70         }
71         
72         Timer_CallTimers();
73
74         // Make sure the RTC Fires again
75         outb(0x70, 0x0C); // Select register C
76         inb(0x71);      // Just throw away contents.
77 }
78
79 #if 0
80 /**
81  * \fn void Time_TimerThread()
82  */
83 void Time_TimerThread()
84 {
85         Sint64  next;
86         Threads_SetName("TIMER");
87         
88         next = giTimestamp + TIMER_QUANTUM;
89         for(;;)
90         {
91                 while(giTimestamp < next)       Threads_Yield();
92                 next = giTimestamp + TIMER_QUANTUM;     
93                 Timer_CallTimers();
94         }
95 }
96 #endif

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