Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 31 Mar 1999 15:24:57 +0900
From:      Kenjiro Cho <kjc@csl.sony.co.jp>
To:        freebsd-mobile@FreeBSD.ORG
Cc:        Poul-Henning Kamp <phk@critter.freebsd.dk>
Subject:   timer problem (calcru: negative time) after resume
Message-ID:  <199903310624.PAA00950@hotaka.csl.sony.co.jp>

next in thread | raw e-mail | index | archive | help

Some laptop machines running 3.x/4.x exhibit the "calcru: negative time"
problem after resume.  
At least, the following machines appear to have this problem.
 - ThinkPad 235 (Chandra II)
 - MITSUBISHI Pedion M3041
 - Sharp Mebius MN-5400D

Iwasaki-san <iwasaki@jp.FreeBSD.org> and I were working on this back
in February.  (We should've reported this earlier...)

It turns out that the countdown register of i8254 timer is destroyed
after resume.  The counter value becomes more than
"timer0_max_count", which spoils the hardclock interval and
timecounter badly.

It seems that, though bios should restore the i8254 registers, it is
safer to restore the register value on resume since the "calcru"
problem is hard to track down.
The patch below has been tested for a while among the PAO users.

--Kenjiro

--- i386/apm/apm.c	Fri Feb 19 04:20:13 1999
+++ /sys/i386/apm/apm.c	Sun Feb 28 03:43:40 1999
@@ -471,6 +471,7 @@
 	else {
 		/* 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 -ru i386/include/clock.h /sys/i386/include/clock.h
--- i386/include/clock.h	Fri Nov  6 15:33:23 1998
+++ /sys/i386/include/clock.h	Sat Feb 27 16:03:28 1999
@@ -44,6 +44,7 @@
 #endif
 int	sysbeep __P((int pitch, int period));
 int	sysbeep_cancel __P((void));
+void	i8254_restore __P((void));
 
 #endif /* KERNEL */
 
diff -ru i386/isa/clock.c /sys/i386/isa/clock.c
--- i386/isa/clock.c	Fri Feb 19 04:21:19 1999
+++ /sys/i386/isa/clock.c	Sat Feb 27 16:23:19 1999
@@ -744,6 +744,28 @@
 #endif /* ncv port */
 
 /*
+ * 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.
  */




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-mobile" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199903310624.PAA00950>