From owner-freebsd-mobile Wed Mar 31 22:28:18 1999 Delivered-To: freebsd-mobile@freebsd.org Received: from widefw.csl.sony.co.jp (widefw.csl.sony.co.jp [133.138.1.1]) by hub.freebsd.org (Postfix) with ESMTP id 87336151AF for ; Wed, 31 Mar 1999 22:28:16 -0800 (PST) (envelope-from kjc@csl.sony.co.jp) Received: from hotaka.csl.sony.co.jp (root@hotaka.csl.sony.co.jp [43.27.98.57]) by widefw.csl.sony.co.jp (8.8.8/3.6W) with ESMTP id PAA16114; Wed, 31 Mar 1999 15:24:58 +0900 (JST) Received: from localhost (kjc@[127.0.0.1]) by hotaka.csl.sony.co.jp (8.8.8/3.6W/hotaka/98122515) with ESMTP id PAA00950; Wed, 31 Mar 1999 15:24:57 +0900 (JST) Message-Id: <199903310624.PAA00950@hotaka.csl.sony.co.jp> To: freebsd-mobile@FreeBSD.ORG Cc: Poul-Henning Kamp Subject: timer problem (calcru: negative time) after resume Date: Wed, 31 Mar 1999 15:24:57 +0900 From: Kenjiro Cho Sender: owner-freebsd-mobile@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org 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 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