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.
This commit is contained in:
Bruce Evans 1998-02-13 06:33:16 +00:00
parent 9f449d2aa2
commit 1d804e7925
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=33309
5 changed files with 110 additions and 75 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}