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>