summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/clock.c
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1998-02-13 06:33:16 +0000
committerbde <bde@FreeBSD.org>1998-02-13 06:33:16 +0000
commitc0758a12df13db5ca34c99e7facb377ddf0fa69a (patch)
tree6c9b88dc5bd9c030811253123bcce20f1c0c3e82 /sys/i386/isa/clock.c
parent793b3fcc96da24432a08fc9c09fd7753c2f7a229 (diff)
downloadFreeBSD-src-c0758a12df13db5ca34c99e7facb377ddf0fa69a.zip
FreeBSD-src-c0758a12df13db5ca34c99e7facb377ddf0fa69a.tar.gz
Update timer0_prescaler_count before calling hardclock() while timer0
is "acquired". This fixes a TSC biasing error of about 10 msec when pcaudio is active. Update `time' before calling hardclock() when timer0 is being released. This is not known to be important. Added some delays in writertc(). Efficiency is not critical here, unlike in rtcin(), and we already use conservative delays there. Don't touch the hardware when machdep.i8254_freq is being changed but the maximum count wouldn't change. This fixes jitter of up to 10 msec for most small adjustments to machdep.i8254_freq. When the maximum count needs to change, the hardware should be adjusted more carefully.
Diffstat (limited to 'sys/i386/isa/clock.c')
-rw-r--r--sys/i386/isa/clock.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c
index 0732bd1..2fb46cb 100644
--- a/sys/i386/isa/clock.c
+++ b/sys/i386/isa/clock.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
- * $Id: clock.c,v 1.108 1998/01/28 10:41:33 phk Exp $
+ * $Id: clock.c,v 1.109 1998/02/09 06:08:26 eivind Exp $
*/
/*
@@ -176,9 +176,9 @@ clkintr(struct clockframe frame)
case ACQUIRED:
if ((timer0_prescaler_count += timer0_max_count)
>= hardclock_max_count) {
+ timer0_prescaler_count -= hardclock_max_count;
hardclock(&frame);
setdelayed();
- timer0_prescaler_count -= hardclock_max_count;
}
break;
@@ -200,6 +200,13 @@ clkintr(struct clockframe frame)
case RELEASE_PENDING:
if ((timer0_prescaler_count += timer0_max_count)
>= hardclock_max_count) {
+ timer0_prescaler_count -= hardclock_max_count;
+ /*
+ * See microtime.s for this magic.
+ */
+ time.tv_usec += (27465 * timer0_prescaler_count) >> 15;
+ if (time.tv_usec >= 1000000)
+ time.tv_usec -= 1000000;
hardclock(&frame);
setdelayed();
timer0_max_count = hardclock_max_count;
@@ -211,14 +218,6 @@ clkintr(struct clockframe frame)
outb(TIMER_CNTR0, timer0_max_count & 0xff);
outb(TIMER_CNTR0, timer0_max_count >> 8);
enable_intr();
- /*
- * See microtime.s for this magic.
- */
- time.tv_usec += (27465 *
- (timer0_prescaler_count - hardclock_max_count))
- >> 15;
- if (time.tv_usec >= 1000000)
- time.tv_usec -= 1000000;
timer0_prescaler_count = 0;
timer_func = hardclock;
timer0_state = RELEASED;
@@ -519,8 +518,11 @@ rtcin(reg)
static __inline void
writertc(u_char reg, u_char val)
{
+ inb(0x84);
outb(IO_RTC, reg);
+ inb(0x84);
outb(IO_RTC + 1, val);
+ inb(0x84); /* XXX work around wrong order in rtcin() */
}
static __inline int
@@ -625,15 +627,20 @@ static void
set_timer_freq(u_int freq, int intr_freq)
{
u_long ef;
+ int new_timer0_max_count;
ef = read_eflags();
disable_intr();
timer_freq = freq;
- timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq);
- timer0_overflow_threshold = timer0_max_count - TIMER0_LATCH_COUNT;
- outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
- outb(TIMER_CNTR0, timer0_max_count & 0xff);
- outb(TIMER_CNTR0, timer0_max_count >> 8);
+ new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq);
+ if (new_timer0_max_count != timer0_max_count) {
+ timer0_max_count = new_timer0_max_count;
+ timer0_overflow_threshold = timer0_max_count -
+ TIMER0_LATCH_COUNT;
+ outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
+ outb(TIMER_CNTR0, timer0_max_count & 0xff);
+ outb(TIMER_CNTR0, timer0_max_count >> 8);
+ }
CLOCK_UNLOCK();
write_eflags(ef);
}
OpenPOWER on IntegriCloud