From owner-FreeBSD-users-jp@jp.freebsd.org  Tue Mar 14 02:01:01 2000
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id CAA79563;
	Tue, 14 Mar 2000 02:01:01 +0900 (JST)
	(envelope-from owner-FreeBSD-users-jp@jp.FreeBSD.org)
Received: from tama5.ecl.ntt.co.jp (tama5.ecl.ntt.co.jp [129.60.39.102])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP id CAA79558
	for <FreeBSD-users-jp@jp.FreeBSD.org>; Tue, 14 Mar 2000 02:01:00 +0900 (JST)
	(envelope-from kihara@isl.ntt.co.jp)
Received: from nttmail3.ecl.ntt.co.jp (nttmail3.ecl.ntt.co.jp [129.60.39.100])
	by tama5.ecl.ntt.co.jp (8.9.3+3.2W/3.7W/01/21/00) with ESMTP id CAA29780;
	Tue, 14 Mar 2000 02:00:58 +0900 (JST)
	(envelope-from kihara@isl.ntt.co.jp)
Received: from qlair.isl.ntt.co.jp
	by nttmail3.ecl.ntt.co.jp (8.9.3+3.2W/3.7W/01/18/00) with ESMTP id CAA20282;
	Tue, 14 Mar 2000 02:00:53 +0900 (JST)
	(envelope-from kihara@isl.ntt.co.jp)
Received: from qlair.isl.ntt.co.jp (kihara@localhost [127.0.0.1])
	by qlair.isl.ntt.co.jp (8.8.8/3.7W+isl1.3) with ESMTP id CAA18289;
	Tue, 14 Mar 2000 02:00:51 +0900 (JST)
	(envelope-from kihara@isl.ntt.co.jp)
Date: Tue, 14 Mar 2000 02:00:50 +0900
Message-ID: <14541.7874.582119.72159A@qlair.isl.ntt.co.jp>
From: Seiji Kihara <kihara@isl.ntt.co.jp>
To: FreeBSD-users-jp@jp.FreeBSD.org, bsd-nomads@clave.gr.jp
User-Agent: Wanderlust/1.0.3 (Notorious) SEMI/1.13.4 (Terai) FLIM/1.12.7
 (=?ISO-8859-4?Q?Y=FEzaki?=) MULE/2.3 (SUETSUMUHANA) (based on Emacs 19.34)
MIME-Version: 1.0 (generated by SEMI 1.13.4 - "Terai")
Content-Type: text/plain; charset=ISO-2022-JP
Reply-To: FreeBSD-users-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+990727
X-Sequence: FreeBSD-users-jp 50505
Subject: [FreeBSD-users-jp 50505] MediaGX clock patch
Errors-To: owner-FreeBSD-users-jp@jp.freebsd.org
Sender: owner-FreeBSD-users-jp@jp.freebsd.org
X-Originator: kihara@isl.ntt.co.jp

$BLZ86(B@NTT$B$G$9!#(B

Cassiopeia FIVA MPC-101(CPU: Cyrix MediaGX 200MHz)$B$K$F(B
FreeBSD 3.4$B$r;H$C$F$$$^$9!#2a5n$KOCBj$K$J$C$F$$$kDL$j!"(B
$B%/%m%C%/<~$j$KLdBj$,$"$j!"(BPS/2$B%^%&%9$,;H$($^$;$s!#(B
USB$B%^%&%9$r;H$($P$"$^$jLdBj$O$J$$$N$G$9$,!"$d$C$Q$j(B
$B;}$AJb$/;~$KITJX$J$N$H!"(Bcalcru$B$N%a%C%;!<%8$,5$$K$J$k$N$H!"(B
CPU$B$,(B16MHz$B$J$s$F8@$o$l$?$j$9$k$N$,5$$K$J$C$?$j$9$k$N$H$G!"(B

http://home.jp.FreeBSD.ORG/cgi-bin/showmail/bsd-nomads/12160

$B$K$F>R2p$5$l$F$$$k(BNetBSD$BMQ$N%Q%C%A$r<j$GEv$F$F$_$^$7$?!#(B
CLOCKDEBUG$B$H$+(BCLOCK_PARANOIA$B$OL5;k$7$F$$$^$9!#(B
$B$b$7;H$o$l$kJ}$,$$$i$C$7$c$$$^$7$?$i!"$H;W$$$^$7$F!"(B
$B%Q%C%A$K$7$F8e$m$KIU$1$^$7$?!#(B

$B$J$*!"$3$N%Q%C%A$O(BFreeBSD 3.4-RELEASE$B$N%=!<%9$KBP$9$k(B
$B$b$N$G$9$,!"$3$l$r(Bpatch$B%3%^%s%I$K$F(B3.4-RELEASE+PAO$B$N(B
$B%+!<%M%k%=!<%9$KEv$F$F;H$($F$$$^$9!#(B
-- 
$BLZ86(B $B@?;J(B
NTT$B%5!<%S%9%$%s%F%0%l!<%7%g%s4pHW8&5f=j(B($B2#?\2l(B)


--- /usr/src/sys/i386/isa/clock.c.orig	Sun Oct 31 15:04:52 1999
+++ /usr/src/sys/i386/isa/clock.c	Mon Mar 13 23:52:22 2000
@@ -101,6 +101,11 @@
 #endif
 #endif /* SMP */
 
+#ifndef NO_CHECK_CLOCK
+static void check_clock_bug __P((void));
+static __inline int getit_broken_latch __P((void));
+#endif /* NO_CHECK_CLOCK */
+
 /*
  * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
  * can use a simple formula for leap years.
@@ -196,6 +201,91 @@
 SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, 
 	&i8254_timecounter, sizeof(i8254_timecounter), "S,timecounter", "");
 
+#ifndef NO_CHECK_CLOCK
+static int clock_broken_latch = 0;
+
+/*
+ * check i8254 latch routine:
+ *	set the variable 'clock_broken_latch'
+ *	XXX check only cpu_id
+ */
+static void
+check_clock_bug()
+{
+	/* extern int cpu_id; */
+
+	switch (cpu_id & 0xff0) {
+	case 0x440:     /* Cyrix MediaGX */
+	case 0x540:     /* GXm */
+		clock_broken_latch = 1;
+		break;
+	default:
+		clock_broken_latch = 0;
+		break;
+	}
+}
+
+int
+getit_broken_latch()
+{
+	u_long ef;
+	int v1, v2, v3;
+	int w1, w2, w3;
+
+	/* Don't want someone screwing with the counter
+	   while we're here. */
+	ef = read_eflags();
+	disable_intr();
+
+	v1 = inb(TIMER_CNTR0);
+	v1 |= inb(TIMER_CNTR0) << 8;
+	v2 = inb(TIMER_CNTR0);
+	v2 |= inb(TIMER_CNTR0) << 8;
+	v3 = inb(TIMER_CNTR0);
+	v3 |= inb(TIMER_CNTR0) << 8;
+
+	write_eflags(ef);
+
+	if (v1 >= v2 && v2 >= v3 && v1 - v3 < 0x200)
+		return (v2);
+
+#define _swap_val(a, b) do { \
+	int c = a; \
+	a = b; \
+	b = c; \
+} while (0)
+
+	/*
+	 * sort v1 v2 v3
+	 */
+	if (v1 < v2)
+		_swap_val(v1, v2);
+	if (v2 < v3)
+		_swap_val(v2, v3);
+	if (v1 < v2)
+		_swap_val(v1, v2);
+
+	/*
+	 * compute the middle value
+	 */
+
+	if (v1 - v3 < 0x200)
+		return (v2);
+
+	w1 = v2 - v3;
+	w2 = v3 - v1 + timer0_max_count;
+	w3 = v1 - v2;
+	if (w1 >= w2) {
+		if (w1 >= w3)
+			return (v1);
+	} else {
+		if (w2 >= w3)
+			return (v2);
+	}
+	return (v3);
+}
+#endif /* NO_CHECK_CLOCK */
+
 static void
 clkintr(struct clockframe frame)
 {
@@ -418,6 +508,11 @@
 	u_long ef;
 	int high, low;
 
+#ifndef NO_CHECK_CLOCK
+	if (clock_broken_latch)
+		return (getit_broken_latch());
+#endif /* NO_CHECK_CLOCK */
+
 	ef = read_eflags();
 	disable_intr();
 
@@ -732,6 +827,10 @@
 startrtclock()
 {
 	u_int delta, freq;
+
+#ifndef NO_CHECK_CLOCK
+	check_clock_bug();
+#endif /* NO_CHECK_CLOCK */
 
 	if (cpu_feature & CPUID_TSC)
 		tsc_present = 1;
