unbroke sparc front-end server protocol
[akaros.git] / kern / arch / sparc / timer.c
1 #include <arch/timer.h>
2 #include <arch/types.h>
3 #include <arch/trap.h>
4 #include <arch/arch.h>
5 #include <stdio.h>
6 #include <assert.h>
7
8 system_timing_t system_timing = {0};
9 volatile uint32_t timer_ticks = 0;
10
11 asm (
12 ".global handle_timer_interrupt         \n\t"
13 "handle_timer_interrupt:                \n\t"
14 "       mov     " XSTR(CORE_ID_REG) ",%l3       \n\t"
15 "       mov     %psr,%l4                        \n\t"
16 "       cmp     %l3,0                           \n\t"
17 "       bne     1f                              \n\t"
18 "        mov    %l4,%psr                        \n\t"
19 "       sethi   %hi(timer_ticks),%l4            \n\t"
20 "       ld      [%l4+%lo(timer_ticks)],%l5      \n\t"
21 "       inc     %l5                             \n\t"
22 "       st      %l5,[%l4+%lo(timer_ticks)]      \n\t"
23 "1:     jmp     %l1                             \n\t"
24 "        rett   %l2                             \n\t" );
25
26 void
27 timer_init(void)
28 {
29         uint32_t ticks = timer_ticks;
30         uint64_t tsc_ticks;
31
32         while(ticks == timer_ticks) ;
33
34         ticks = timer_ticks;
35         tsc_ticks = read_tsc();
36
37         while(ticks == timer_ticks) ;
38
39         system_timing.tsc_freq = (read_tsc() - tsc_ticks)*INTERRUPT_TIMER_HZ;
40
41         cprintf("TSC Frequency: %llu\n", system_timing.tsc_freq);
42 }
43
44 void
45 udelay(uint64_t usec)
46 {
47         if (system_timing.tsc_freq != 0)
48         {
49                 uint64_t start, end, now;
50         
51                 start = read_tsc();
52                 end = start + (system_timing.tsc_freq * usec) / 1000000;
53
54                 do
55                 {
56                         cpu_relax();
57                         now = read_tsc();
58                 } while (now < end || (now > start && end < start));
59         }
60         else panic("udelay() was called before timer_init(), moron!");
61 }