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

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