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
)
25 asm volatile("movl $0,%%eax; divl %2":"=a"(ret
):"d"(usec
),"m"(TIMER_RPROK
));
29 void EClockUpdate(struct TimerBase
*TimerBase
)
35 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
36 /* Latch the current time value */
39 /* Read out current 16-bit time */
40 time
= inb(0x42) >> 1;
41 time
+= inb(0x42) << 7;
43 diff
= (TimerBase
->tb_prev_tick
- time
);
45 if (time
> TimerBase
->tb_prev_tick
)
48 TimerBase
->tb_prev_tick
= time
;
50 TimerBase
->tb_ticks_total
+= diff
;
51 TimerBase
->tb_ticks_sec
+= diff
;
52 TimerBase
->tb_ticks_elapsed
+= diff
;
54 if (TimerBase
->tb_ticks_sec
>= 1193180) {
55 TimerBase
->tb_ticks_sec
-= 1193180;
56 TimerBase
->tb_CurrentTime
.tv_secs
++;
59 if (TimerBase
->tb_ticks_elapsed
>= 1193180) {
60 TimerBase
->tb_ticks_elapsed
-= 1193180;
61 TimerBase
->tb_Elapsed
.tv_secs
++;
64 TimerBase
->tb_Elapsed
.tv_micro
= tick2usec(TimerBase
->tb_ticks_elapsed
);
65 TimerBase
->tb_CurrentTime
.tv_micro
= tick2usec(TimerBase
->tb_ticks_sec
);
70 void EClockSet(struct TimerBase
*TimerBase
)
74 TimerBase
->tb_ticks_sec
= usec2tick(TimerBase
->tb_CurrentTime
.tv_micro
);
75 TimerBase
->tb_ticks_total
= TimerBase
->tb_ticks_sec
76 + (UQUAD
)TimerBase
->tb_CurrentTime
.tv_secs
* 1193180;
78 /* Latch the current time value */
80 /* Read out current 16-bit time */
81 time
= inb(0x42) >> 1;
82 time
+= inb(0x42) << 7;
83 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
85 TimerBase
->tb_prev_tick
= time
;
88 void Timer0Setup(struct TimerBase
*TimerBase
)
92 struct timerequest
*tr
;
94 tr
= (struct timerequest
*)GetHead(&TimerBase
->tb_Lists
[TL_WAITVBL
]);
98 time
.tv_micro
= tr
->tr_time
.tv_micro
;
99 time
.tv_secs
= tr
->tr_time
.tv_secs
;
101 EClockUpdate(TimerBase
);
102 SubTime(&time
, &TimerBase
->tb_CurrentTime
);
104 if ((LONG
)time
.tv_secs
< 0)
108 else if (time
.tv_secs
== 0)
110 if (time
.tv_micro
< 20000)
112 delay
= usec2tick(time
.tv_micro
);
117 tr
= (struct timerequest
*)GetHead(&TimerBase
->tb_Lists
[TL_VBLANK
]);
121 time
.tv_micro
= tr
->tr_time
.tv_micro
;
122 time
.tv_secs
= tr
->tr_time
.tv_secs
;
124 EClockUpdate(TimerBase
);
125 SubTime(&time
, &TimerBase
->tb_Elapsed
);
127 if ((LONG
)time
.tv_secs
< 0)
131 else if (time
.tv_secs
== 0)
133 if (time
.tv_micro
< 20000)
135 if (delay
> usec2tick(time
.tv_micro
))
136 delay
= usec2tick(time
.tv_micro
);
141 if (delay
< 2) delay
= 2;
143 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
144 outb(0x38, 0x43); /* Binary, mode 4, LSB&MSB */
145 outb(delay
& 0xff, 0x40);
146 outb(delay
>> 8, 0x40);