From owner-FreeBSD-users-jp@jp.freebsd.org  Wed Dec 11 14:17:05 1996
Received: by jaz.jp.freebsd.org (8.8.3+2.6Wbeta9/8.7.3) id OAA28003
	Wed, 11 Dec 1996 14:17:05 +0900 (JST)
Received: by jaz.jp.freebsd.org (8.8.3+2.6Wbeta9/8.7.3) with ESMTP id OAA27998
	for <FreeBSD-users-jp@jp.freebsd.org>; Wed, 11 Dec 1996 14:17:04 +0900 (JST)
Received: (from ohashi@localhost) by atohasi.mickey.ai.kyutech.ac.jp (8.8.2/3.4Wbeta6) id OAA01883; Wed, 11 Dec 1996 14:16:53 +0900 (JST)
Date: Wed, 11 Dec 1996 14:16:53 +0900 (JST)
Message-Id: <199612110516.OAA01883@atohasi.mickey.ai.kyutech.ac.jp>
To: FreeBSD-users-jp@jp.freebsd.org
In-Reply-To: Your message of Wed, 11 Dec 1996 11:54:19 +0900.
	<199612110254.LAA00054@adam.dsp.cl.nec.co.jp>
From: ohashi@mickey.ai.kyutech.ac.jp (Takeshi OHASHI)
X-Mailer: mnews [version 1.19PL2] 1996-01/26(Fri)
Reply-To: FreeBSD-users-jp@jp.freebsd.org
X-Distribute: distribute [version 2.1 (Alpha) patchlevel=19]
X-Sequence: FreeBSD-users-jp 7398
Subject: [FreeBSD-users-jp 7398] DELAY()
Errors-To: owner-FreeBSD-users-jp@jp.freebsd.org
Sender: owner-FreeBSD-users-jp@jp.freebsd.org

$BBg66!w6e9)Bg$G$9!%(B

  $B0JA0$+$iLdBj$H$J$C$F$$$?!"(Bclock.c$BCf$N(BDELAY()$B$G$9$,!"(Bcurrent@freebsd.org
$B$KEj$2$F(BBruce Evans$B$5$s$+%3%a%s%H$rD:$$$F!"$`$i$?7/$H:n$jD>$7$^$7$?$N(B
$B$G%F%9%H$7$F$_$F$/$@$5$$!%(B

$B0JA0$+$i$NJQ99E@(B

1. calibrate_delay_offset()$B$rJ,N%$7$?!%(B
2. $B7WB,Cf$O3d$j9~$_$r6X;_$7$?!%(B
3. $B5/F0;~$N(Bcalibrte_timer()$BCf$H(B10ms$B$h$jBg$-$$(BDELAY()$B$N$H$-$K(Boffset$B$r:F(B
   $BD4@0$9$k$h$&$K$7$?!%(B

$B$3$l$K$h$j(BTURBO$B%9%$%C%A$r@Z$C$F5/F0$7$F!"$=$N8e(BTURBO$B%9%$%C%A$rF~$l$F$b(B
$BBg>fIW$J$O$:$G$9!%(Bapm$B$,8z$$$F(Bclock$B$rJQ99$7$F$b$"$kDxEYBP=h$G$-$^$9!%(B

$BJ}?K$O!"4QB,$G$-$kCY1d$,:G>.!"$D$^$j(Bclock$B$,0lHVB.$$$H$-$K9g$;$k$h$&$K(B
$B$7$^$7$?!%CY$/$J$C$?$H$-$OCY1d$,B?$a$KF~$k$@$1$G$=$l$[$ICWL?E*$G$"$j$^(B
$B$;$s$,!"5U$OCWL?E*$@$+$i$G$9!%(B

# $B?H6a$G3NG'$G$-$k5!3#$,$J$$$N$G3NG'$G$-$kJ}$*4j$$$7$^$9!%(B

$B?H6a$K$"$k(B 2.2-ALPHA$B$d(Bcurrent$B$G$O!"0J2<$N$h$&$J7k2L$K$J$j!"(B20us$B$HHf$Y(B
$B$k$H$d$C$Q$jCY1d$,>.$5$$$G$9!%(B

Pentium Pro 200 4us
Pentium 133	3us
AMD DX4/75	12us

# $B$J$<(B FMV-6200T4(P6-200)$B$O$N(BGateway2000(P5-133)$B$h$jCY$$$N$+$J(B?
# $B$^$?!"(Bpatch$BCf$N(Bif$BJ8$,@5$7$/F0$+$J$/$F!"(B3$B9`1i;;;R$K$7$F$k$N$G$9$,!"$3(B
# $B$l$O(B gcc-2.7.2.1$B$N%P%0$J$N$G$7$g$&$+(B?
--
$B$*$*$O$7(B

/usr/src/sys/i386/isa $B$GEv$F$F$/$@$5$$!%(B
PAO$B$N?M$O!"(Bsysbeep_cancel()$B$KCm0U$7$F$/$@$5$$!%(B

--- clock.c.orig	Sat Oct 26 09:11:57 1996
+++ clock.c	Sat Dec  7 18:39:19 1996
@@ -133,6 +133,8 @@
 static	u_char	rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
 static	u_char	rtc_statusb = RTCSB_24HR | RTCSB_PINTR;
 
+static	u_int	delay_offset = 20;	/* It should be calibrated */
+
 /* Values for timerX_state: */
 #define	RELEASED	0
 #define	RELEASE_PENDING	1
@@ -354,6 +356,55 @@
 }
 
 /*
+ * calibrate delay_offset for DELAY()
+ * This is called from calibrate_clock() and DELAY().
+ */
+static int
+calibrate_delay_offset(void)
+{
+	int i, start_tick, end_tick, min_ticks;
+	u_int delta_ticks, delay_offset_old, delay_offset_tmp;
+	u_long ef;
+	const int loops = 100; 
+	const int delay = 10; 
+
+	delay_offset_old = delay_offset;
+	delay_offset = 0;
+	min_ticks = INT_MAX;
+	for (i = 0; i < loops; i++) {
+		ef = read_eflags();
+		start_tick = getit();
+		DELAY(delay);
+		end_tick = getit();
+		write_eflags(ef);
+		delta_ticks = start_tick - end_tick;
+		if (min_ticks > delta_ticks)
+			min_ticks = delta_ticks;
+	}
+	if (min_ticks == INT_MAX) {
+		printf("warning: cannot calibrate delay offset\n");
+		delay_offset = delay_offset_tmp = 20;
+	} else {
+		delay_offset_tmp = min_ticks * 1000000LL / timer_freq - delay;
+/* Why does not it work right?
+		if (delay_offset_tmp < delay_offset_old)
+			delay_offset = delay_offset_tmp;
+*/
+		delay_offset = (delay_offset_tmp < delay_offset_old) ?
+				delay_offset_tmp : delay_offset_old;
+#define DELAYOFFSETDEBUG
+#ifdef DELAYOFFSETDEBUG
+		if (delay_offset != delay_offset_old) {
+			printf("DELAY offset: %u usec\n", delay_offset);
+		}
+#endif
+		if (!(0 <= delay_offset || delay_offset <= 20))
+			delay_offset = 20;
+	}
+	return ((delay_offset_tmp + delay) * loops);
+}
+
+/*
  * Wait "n" microseconds.
  * Relies on timer 1 counting down from (timer_freq / hz)
  * Note: timer had better have been programmed before this is first used!
@@ -384,8 +435,11 @@
 	 * takes about 6 usec on a 486/33 and 13 usec on a 386/20.  The
 	 * multiplications and divisions to scale the count take a while).
 	 */
+	if (n > 10000) {
+		n -= calibrate_delay_offset();
+	}
 	prev_tick = getit();
-	n -= 20;
+	n = (n <= delay_offset) ? 1 : (n - delay_offset);
 	/*
 	 * Calculate (n * (timer_freq / 1e6)) without using floating point
 	 * and without any avoidable overflows.
@@ -564,6 +618,9 @@
 #endif
 
 	printf("i8254 clock: %u Hz\n", tot_count);
+
+	calibrate_delay_offset();
+
 	return (tot_count);
 
 fail:
