Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 06 Apr 2000 17:11:26 +0200
From:      "Jose M. Alcaide" <jose@we.lc.ehu.es>
To:        freebsd-hackers@FreeBSD.org
Cc:        freebsd-mobile@FreeBSD.org
Subject:   proposal of a better solution for "statclock broken" laptops
Message-ID:  <38ECA91E.F98AE48@we.lc.ehu.es>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------F056678DFC8CD17B1088D5B8
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Let's begin exposing the background:

Some laptops suffer of the "statclock broken" problem: APM suspend
does not work while the RTC is generating periodic interrupts (which
are used for the statistical clock). Currently, the "solution" consists
of setting the 0x20 flag for the apm(4) driver. If this flag is set,
the cpu_initclocks() routine in sys/i386/isa/clock.c does not
initialize the statclok at all. As a consequence, the functionality
of the statclock is lost.

I tried another solution which seems to work for my laptop (a Dell I3.7k).
I added two small routines to clock.c, named statclock_stop() and
statclock_restart(). The first one simply disables the periodic
interrupts from the MC146818A RTC; the second one re-enables those
interrupts. Then, I modified apm_default_suspend() and apm_default_resume()
(in sys/i386/apm/apm.c) for respectively stopping and restarting the
statclock if the 0x20 flag is set. With these small modifications,
now I can suspend and resume my laptop while retaining the statclock
functionality.

I attach a patchfile (against 4.0-RELEASE) to this message. It's
possible that my solution needs to be reworked in order to make
it SMP-safe or something. I would love to hear any comments.

Saludos,
-- JMA
-----------------------------------------------------------------------
José Mª Alcaide                         | mailto:jose@we.lc.ehu.es
Universidad del País Vasco              | mailto:jmas@FreeBSD.org
Dpto. de Electricidad y Electrónica     | http://www.we.lc.ehu.es/~jose
Facultad de Ciencias - Campus de Lejona | Tel.:  +34-946012479
48940 Lejona (Vizcaya) - SPAIN          | Fax:   +34-946013071
-----------------------------------------------------------------------
 "Beware of Programmers who carry screwdrivers"  --  Leonard Brandwein
--------------F056678DFC8CD17B1088D5B8
Content-Type: text/plain; charset=us-ascii;
 name="statclock.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="statclock.patch"

--- sys/i386/isa/clock.c.orig	Tue Jan  4 23:24:59 2000
+++ sys/i386/isa/clock.c	Thu Apr  6 17:05:26 2000
@@ -132,7 +132,6 @@
 int	clkintr_pending;
 int	disable_rtc_set;	/* disable resettodr() if != 0 */
 volatile u_int	idelayed;
-int	statclock_disable;
 u_int	stat_imask = SWI_CLOCK_MASK;
 #ifndef TIMER_FREQ
 #define TIMER_FREQ   1193182
@@ -827,6 +826,28 @@
 #endif /* !defined(SMP) */
 }
 
+/* The following two functions are used in apm.c for stopping and
+ * restarting the statclock interrupts from the RTC, if the apm's
+ * broken_statclock flag is active (some laptops don't enter suspend
+ * mode while the RTC is generating interrupts) */
+
+void
+statclock_stop(void)
+{
+	/* disable RTC interrupts and clear any pending one */
+	writertc(RTC_STATUSB, RTCSB_24HR);
+	rtcin(RTC_INTR);
+}
+
+void
+statclock_restart(void)
+{
+	/* don't trust the APM BIOS (paranoia?) */
+	rtcin(RTC_INTR);
+	/* re-enable periodic interrupts */
+	writertc(RTC_STATUSB, rtc_statusb);
+}
+
 /*
  * Initialize the time of day register, based on the time base which is, e.g.
  * from a filesystem.
@@ -975,20 +996,9 @@
 	struct intrec *clkdesc;
 #endif /* APIC_IO */
 
-	if (statclock_disable) {
-		/*
-		 * The stat interrupt mask is different without the
-		 * statistics clock.  Also, don't set the interrupt
-		 * flag which would normally cause the RTC to generate
-		 * interrupts.
-		 */
-		stat_imask = HWI_MASK | SWI_MASK;
-		rtc_statusb = RTCSB_24HR;
-	} else {
-	        /* Setting stathz to nonzero early helps avoid races. */
-		stathz = RTC_NOPROFRATE;
-		profhz = RTC_PROFRATE;
-        }
+	/* Setting stathz to nonzero early helps avoid races. */
+	stathz = RTC_NOPROFRATE;
+	profhz = RTC_PROFRATE;
 
 	/* Finish initializing 8253 timer 0. */
 #ifdef APIC_IO
@@ -1023,9 +1033,6 @@
 	writertc(RTC_STATUSA, rtc_statusa);
 	writertc(RTC_STATUSB, RTCSB_24HR);
 
-	/* Don't bother enabling the statistics clock. */
-	if (statclock_disable)
-		return;
 	diag = rtcin(RTC_DIAG);
 	if (diag != 0)
 		printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
--- sys/i386/include/clock.h.orig	Wed Dec 29 05:32:58 1999
+++ sys/i386/include/clock.h	Thu Apr  6 17:00:42 2000
@@ -16,7 +16,6 @@
  */
 extern int	adjkerntz;
 extern int	disable_rtc_set;
-extern int	statclock_disable;
 extern u_int	timer_freq;
 extern int	timer0_max_count;
 extern u_int	tsc_freq;
@@ -45,6 +44,8 @@
 #endif
 int	sysbeep __P((int pitch, int period));
 void	i8254_restore __P((void));
+void	statclock_stop __P((void));
+void	statclock_restart __P((void));
 
 #endif /* _KERNEL */
 
--- sys/i386/apm/apm.c.orig	Sun Feb  6 15:57:05 2000
+++ sys/i386/apm/apm.c	Thu Apr  6 17:01:58 2000
@@ -56,6 +56,8 @@
 
 static u_long	apm_version;
 
+static int broken_statclock = 0;
+
 int	apm_evindex;
 
 #define	SCFLAG_ONORMAL	0x0000001
@@ -402,6 +404,10 @@
 	u_int second, minute, hour;
 	struct timeval resume_time, tmp_time;
 
+	/* re-enable statclock if it's broken */
+	if (broken_statclock)
+		statclock_restart();
+
 	/* modified for adjkerntz */
 	pl = splsoftclock();
 	i8254_restore();		/* restore timer_freq and hz */
@@ -451,6 +457,11 @@
 	microtime(&suspend_time);
 	timevalsub(&diff_time, &suspend_time);
 	splx(pl);
+
+	/* stop statclock if it's broken */
+	if (broken_statclock)
+		statclock_stop();
+
 	return 0;
 }
 
@@ -1003,7 +1014,7 @@
 		flags = 0;
 
 	if (flags & 0x20)
-		statclock_disable = 1;
+		broken_statclock = 1;
 
 	sc->initialized = 0;
 

--------------F056678DFC8CD17B1088D5B8--



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




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