3 //#include <aros/debug.h>
4 #include <exec/types.h>
5 #include <proto/exec.h>
8 #include <proto/timer.h>
12 const ULONG TIMER_RPROK
= 3599597124UL;
14 ULONG
tick2usec(ULONG tick
)
17 asm volatile("mull %3":"=d"(ret
),"=a"(rest
):"a"(TIMER_RPROK
),"m"(tick
));
22 ULONG
usec2tick(ULONG usec
)
26 // gcc 4.3.1 with -O2: Following doesn't work properly, probably because it
27 // doesn't tell about edx trashing.
29 // asm volatile("movl $0,%%eax; divl %2":"=a"(ret):"d"(usec),"m"(TIMER_RPROK));
31 asm volatile("movl $0,%%eax; divl %2":"=a"(ret
),"+d"(usec
):"m"(TIMER_RPROK
));
35 void EClockUpdate(struct TimerBase
*TimerBase
)
41 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
42 /* Latch the current time value */
45 /* Read out current 16-bit time */
46 time
= inb(0x42) >> 1;
47 time
+= inb(0x42) << 7;
49 diff
= (TimerBase
->tb_prev_tick
- time
);
51 if (time
> TimerBase
->tb_prev_tick
)
54 TimerBase
->tb_prev_tick
= time
;
56 TimerBase
->tb_ticks_total
+= diff
;
57 TimerBase
->tb_ticks_sec
+= diff
;
58 TimerBase
->tb_ticks_elapsed
+= diff
;
60 if (TimerBase
->tb_ticks_sec
>= 1193180) {
61 TimerBase
->tb_ticks_sec
-= 1193180;
62 TimerBase
->tb_CurrentTime
.tv_secs
++;
65 if (TimerBase
->tb_ticks_elapsed
>= 1193180) {
66 TimerBase
->tb_ticks_elapsed
-= 1193180;
67 TimerBase
->tb_Elapsed
.tv_secs
++;
70 TimerBase
->tb_Elapsed
.tv_micro
= tick2usec(TimerBase
->tb_ticks_elapsed
);
71 TimerBase
->tb_CurrentTime
.tv_micro
= tick2usec(TimerBase
->tb_ticks_sec
);
76 void EClockSet(struct TimerBase
*TimerBase
)
80 TimerBase
->tb_ticks_sec
= usec2tick(TimerBase
->tb_CurrentTime
.tv_micro
);
81 TimerBase
->tb_ticks_total
= TimerBase
->tb_ticks_sec
82 + (UQUAD
)TimerBase
->tb_CurrentTime
.tv_secs
* 1193180;
84 /* Latch the current time value */
86 /* Read out current 16-bit time */
87 time
= inb(0x42) >> 1;
88 time
+= inb(0x42) << 7;
89 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
91 TimerBase
->tb_prev_tick
= time
;
94 void Timer0Setup(struct TimerBase
*TimerBase
)
98 struct timerequest
*tr
;
100 tr
= (struct timerequest
*)GetHead(&TimerBase
->tb_Lists
[TL_WAITVBL
]);
104 time
.tv_micro
= tr
->tr_time
.tv_micro
;
105 time
.tv_secs
= tr
->tr_time
.tv_secs
;
107 EClockUpdate(TimerBase
);
108 SubTime(&time
, &TimerBase
->tb_CurrentTime
);
110 if ((LONG
)time
.tv_secs
< 0)
114 else if (time
.tv_secs
== 0)
116 if (time
.tv_micro
< 20000)
118 delay
= usec2tick(time
.tv_micro
);
123 tr
= (struct timerequest
*)GetHead(&TimerBase
->tb_Lists
[TL_VBLANK
]);
127 time
.tv_micro
= tr
->tr_time
.tv_micro
;
128 time
.tv_secs
= tr
->tr_time
.tv_secs
;
130 EClockUpdate(TimerBase
);
131 SubTime(&time
, &TimerBase
->tb_Elapsed
);
133 if ((LONG
)time
.tv_secs
< 0)
137 else if (time
.tv_secs
== 0)
139 if (time
.tv_micro
< 20000)
141 if (delay
> usec2tick(time
.tv_micro
))
142 delay
= usec2tick(time
.tv_micro
);
147 if (delay
< 2) delay
= 2;
149 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
150 outb(0x30, 0x43); /* Binary, mode 0, LSB&MSB */
151 outb(delay
& 0xff, 0x40);
152 outb(delay
>> 8, 0x40);