diff options
-rw-r--r-- | sys/amd64/amd64/tsc.c | 22 | ||||
-rw-r--r-- | sys/amd64/include/clock.h | 1 | ||||
-rw-r--r-- | sys/amd64/isa/clock.c | 22 | ||||
-rw-r--r-- | sys/i386/apm/apm.c | 1 | ||||
-rw-r--r-- | sys/i386/bios/apm.c | 1 | ||||
-rw-r--r-- | sys/i386/i386/tsc.c | 22 | ||||
-rw-r--r-- | sys/i386/include/clock.h | 1 | ||||
-rw-r--r-- | sys/i386/isa/clock.c | 22 | ||||
-rw-r--r-- | sys/isa/atrtc.c | 22 |
9 files changed, 114 insertions, 0 deletions
diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c index c659741..4d393b0 100644 --- a/sys/amd64/amd64/tsc.c +++ b/sys/amd64/amd64/tsc.c @@ -691,6 +691,28 @@ set_timer_freq(u_int freq, int intr_freq) } /* + * i8254_restore is called from apm_default_resume() to reload + * the countdown register. + * this should not be necessary but there are broken laptops that + * do not restore the countdown register on resume. + * when it happnes, it messes up the hardclock interval and system clock, + * which leads to the infamous "calcru: negative time" problem. + */ +void +i8254_restore(void) +{ + u_long ef; + + ef = read_eflags(); + disable_intr(); + 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); +} + +/* * Initialize 8254 timer 0 early so that it can be used in DELAY(). * XXX initialization of other timers is unintentionally left blank. */ diff --git a/sys/amd64/include/clock.h b/sys/amd64/include/clock.h index f5c654a..8d0e2d3 100644 --- a/sys/amd64/include/clock.h +++ b/sys/amd64/include/clock.h @@ -44,6 +44,7 @@ int acquire_timer1 __P((int mode)); int release_timer1 __P((void)); #endif int sysbeep __P((int pitch, int period)); +void i8254_restore __P((void)); #endif /* KERNEL */ diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c index c659741..4d393b0 100644 --- a/sys/amd64/isa/clock.c +++ b/sys/amd64/isa/clock.c @@ -691,6 +691,28 @@ set_timer_freq(u_int freq, int intr_freq) } /* + * i8254_restore is called from apm_default_resume() to reload + * the countdown register. + * this should not be necessary but there are broken laptops that + * do not restore the countdown register on resume. + * when it happnes, it messes up the hardclock interval and system clock, + * which leads to the infamous "calcru: negative time" problem. + */ +void +i8254_restore(void) +{ + u_long ef; + + ef = read_eflags(); + disable_intr(); + 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); +} + +/* * Initialize 8254 timer 0 early so that it can be used in DELAY(). * XXX initialization of other timers is unintentionally left blank. */ diff --git a/sys/i386/apm/apm.c b/sys/i386/apm/apm.c index 96860f6..9630f02 100644 --- a/sys/i386/apm/apm.c +++ b/sys/i386/apm/apm.c @@ -404,6 +404,7 @@ apm_default_resume(void *arg) /* modified for adjkerntz */ pl = splsoftclock(); + i8254_restore(); /* restore timer_freq and hz */ inittodr(0); /* adjust time to RTC */ microtime(&resume_time); getmicrotime(&tmp_time); diff --git a/sys/i386/bios/apm.c b/sys/i386/bios/apm.c index 96860f6..9630f02 100644 --- a/sys/i386/bios/apm.c +++ b/sys/i386/bios/apm.c @@ -404,6 +404,7 @@ apm_default_resume(void *arg) /* modified for adjkerntz */ pl = splsoftclock(); + i8254_restore(); /* restore timer_freq and hz */ inittodr(0); /* adjust time to RTC */ microtime(&resume_time); getmicrotime(&tmp_time); diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c index c659741..4d393b0 100644 --- a/sys/i386/i386/tsc.c +++ b/sys/i386/i386/tsc.c @@ -691,6 +691,28 @@ set_timer_freq(u_int freq, int intr_freq) } /* + * i8254_restore is called from apm_default_resume() to reload + * the countdown register. + * this should not be necessary but there are broken laptops that + * do not restore the countdown register on resume. + * when it happnes, it messes up the hardclock interval and system clock, + * which leads to the infamous "calcru: negative time" problem. + */ +void +i8254_restore(void) +{ + u_long ef; + + ef = read_eflags(); + disable_intr(); + 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); +} + +/* * Initialize 8254 timer 0 early so that it can be used in DELAY(). * XXX initialization of other timers is unintentionally left blank. */ diff --git a/sys/i386/include/clock.h b/sys/i386/include/clock.h index f5c654a..8d0e2d3 100644 --- a/sys/i386/include/clock.h +++ b/sys/i386/include/clock.h @@ -44,6 +44,7 @@ int acquire_timer1 __P((int mode)); int release_timer1 __P((void)); #endif int sysbeep __P((int pitch, int period)); +void i8254_restore __P((void)); #endif /* KERNEL */ diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index c659741..4d393b0 100644 --- a/sys/i386/isa/clock.c +++ b/sys/i386/isa/clock.c @@ -691,6 +691,28 @@ set_timer_freq(u_int freq, int intr_freq) } /* + * i8254_restore is called from apm_default_resume() to reload + * the countdown register. + * this should not be necessary but there are broken laptops that + * do not restore the countdown register on resume. + * when it happnes, it messes up the hardclock interval and system clock, + * which leads to the infamous "calcru: negative time" problem. + */ +void +i8254_restore(void) +{ + u_long ef; + + ef = read_eflags(); + disable_intr(); + 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); +} + +/* * Initialize 8254 timer 0 early so that it can be used in DELAY(). * XXX initialization of other timers is unintentionally left blank. */ diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c index c659741..4d393b0 100644 --- a/sys/isa/atrtc.c +++ b/sys/isa/atrtc.c @@ -691,6 +691,28 @@ set_timer_freq(u_int freq, int intr_freq) } /* + * i8254_restore is called from apm_default_resume() to reload + * the countdown register. + * this should not be necessary but there are broken laptops that + * do not restore the countdown register on resume. + * when it happnes, it messes up the hardclock interval and system clock, + * which leads to the infamous "calcru: negative time" problem. + */ +void +i8254_restore(void) +{ + u_long ef; + + ef = read_eflags(); + disable_intr(); + 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); +} + +/* * Initialize 8254 timer 0 early so that it can be used in DELAY(). * XXX initialization of other timers is unintentionally left blank. */ |