From 1d804e792535903a0526853d678bfee403ac9309 Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Fri, 13 Feb 1998 06:33:16 +0000 Subject: [PATCH] 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. --- sys/amd64/amd64/tsc.c | 37 ++++++++++++++++++++++--------------- sys/amd64/isa/clock.c | 37 ++++++++++++++++++++++--------------- sys/i386/i386/tsc.c | 37 ++++++++++++++++++++++--------------- sys/i386/isa/clock.c | 37 ++++++++++++++++++++++--------------- sys/isa/atrtc.c | 37 ++++++++++++++++++++++--------------- 5 files changed, 110 insertions(+), 75 deletions(-) diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c index 0732bd16c1a1..2fb46cb67c92 100644 --- a/sys/amd64/amd64/tsc.c +++ b/sys/amd64/amd64/tsc.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); } diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c index 0732bd16c1a1..2fb46cb67c92 100644 --- a/sys/amd64/isa/clock.c +++ b/sys/amd64/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); } diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c index 0732bd16c1a1..2fb46cb67c92 100644 --- a/sys/i386/i386/tsc.c +++ b/sys/i386/i386/tsc.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); } diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index 0732bd16c1a1..2fb46cb67c92 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); } diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c index 0732bd16c1a1..2fb46cb67c92 100644 --- a/sys/isa/atrtc.c +++ b/sys/isa/atrtc.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); }