summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>1999-10-30 14:56:01 +0000
committeriwasaki <iwasaki@FreeBSD.org>1999-10-30 14:56:01 +0000
commit945a25b48913c2f1a8b8f0aadcb902c3189ed927 (patch)
tree44779f7a28dcd79760060b54d492be07d1a097e2
parent437d3feb752ab5ec3128771f54f8a684bf186e02 (diff)
downloadFreeBSD-src-945a25b48913c2f1a8b8f0aadcb902c3189ed927.zip
FreeBSD-src-945a25b48913c2f1a8b8f0aadcb902c3189ed927.tar.gz
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. Submitted by: kjc, iwasaki Reviewed by: Steve O'Hara-Smith <steveo@eircom.net> and committers. Obtained from: PAO3
-rw-r--r--sys/amd64/amd64/tsc.c22
-rw-r--r--sys/amd64/include/clock.h1
-rw-r--r--sys/amd64/isa/clock.c22
-rw-r--r--sys/i386/apm/apm.c1
-rw-r--r--sys/i386/bios/apm.c1
-rw-r--r--sys/i386/i386/tsc.c22
-rw-r--r--sys/i386/include/clock.h1
-rw-r--r--sys/i386/isa/clock.c22
-rw-r--r--sys/isa/atrtc.c22
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.
*/
OpenPOWER on IntegriCloud