From ed@hoeg.nl  Sun Jun 10 20:18:14 2007
Return-Path: <ed@hoeg.nl>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 8E66916A46F
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 10 Jun 2007 20:18:14 +0000 (UTC)
	(envelope-from ed@hoeg.nl)
Received: from palm.hoeg.nl (mx0.hoeg.nl [83.98.131.211])
	by mx1.freebsd.org (Postfix) with ESMTP id 5C1A013C45E
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 10 Jun 2007 20:18:14 +0000 (UTC)
	(envelope-from ed@hoeg.nl)
Received: by palm.hoeg.nl (Postfix, from userid 1000)
	id B11831CCB7; Sun, 10 Jun 2007 22:18:13 +0200 (CEST)
Message-Id: <20070610201813.B11831CCB7@palm.hoeg.nl>
Date: Sun, 10 Jun 2007 22:18:13 +0200 (CEST)
From: Ed Schouten <ed@fxq.nl>
Reply-To: Ed Schouten <ed@fxq.nl>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: decrease i8254 calibration precision to make it work with Xbox, remove warnings
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         113540
>Category:       i386
>Synopsis:       [i386] [patch] decrease i8254 calibration precision to make it work with Xbox, remove warnings
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    rink
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jun 10 20:20:02 GMT 2007
>Closed-Date:    Mon Feb 11 14:33:55 UTC 2008
>Last-Modified:  Mon Feb 11 14:33:55 UTC 2008
>Originator:     Ed Schouten
>Release:        FreeBSD 6.2-STABLE i386
>Organization:
>Environment:
System: FreeBSD palm.hoeg.nl 6.2-STABLE FreeBSD 6.2-STABLE #0: Fri Apr 20 13:44:49 CEST 2007 root@palm.hoeg.nl:/usr/obj/usr/src/sys/PALM i386
>Description:
For some reason, the timers in the Microsoft Xbox aren't as sane as on
PC's; it has two issues:

- The frequency of the i8254 timer is 1125000 Hz instead of 1193182 Hz.
  The Microsoft Xbox port currently solves this by hardcoding TIMER_FREQ
  in the config file.
- The diagnostic and status registers of the RTC contain invalid data,
  which causes FreeBSD to assume the RTC is broken. This causes a lot of
  spurious messages in the dmesg.
>How-To-Repeat:
>Fix:
I've been using the following patch on my Xbox for a long time now; it
essentially does the following things:

- It changes the rtcin() routine to return fake values for the diagnose
  and status registers, which forces FreeBSD to properly use theh RTC.
- It decreases the precision of the timer (by default disabled) timer
  calibration code from 1% to 10%; this is needed because the Xbox clock
  is 6% off.
- It removes the hardcoded Xbox timer value from the Xbox configuration
  file and enables timer calibration.

The reason why we want to do such a thing is because we could then
compile kernels that run on Xbox'es and PC's without a clock drift on
one of those systems.

--- src/sys/i386/isa/clock.c	Tue Jan 23 19:18:32 2007
+++ src/sys/i386/isa/clock.c	Thu Feb  8 18:07:28 2007
@@ -94,6 +94,10 @@
 #include <i386/bios/mca_machdep.h>
 #endif
 
+#ifdef XBOX
+#include <machine/xbox.h>
+#endif
+
 #define	TIMER_DIV(x) ((timer_freq + (x) / 2) / (x))
 
 int	clkintr_pending;
@@ -421,6 +425,23 @@
 {
 	u_char val;
 
+#ifdef XBOX
+	/*
+	 * The RTC in the Microsoft Xbox always reports errors,
+	 * including power problems, though it's functioning correctly.
+	 * We want to use the RTC to calibrate the timer, because its
+	 * frequency isn't the same as a regular PC.
+	 */
+	if (arch_i386_is_xbox) {
+		switch (reg) {
+		case RTC_DIAG:
+			return (0);
+		case RTC_STATUSD:
+			return (RTCSD_PWR);
+		}
+	}
+#endif
+
 	RTC_LOCK;
 	if (rtc_reg != reg) {
 		inb(0x84);
@@ -631,7 +652,7 @@
 	 * frequency.
 	 */
 	delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq;
-	if (delta < timer_freq / 100) {
+	if (delta < timer_freq / 10) {
 #ifndef CLK_USE_I8254_CALIBRATION
 		if (bootverbose)
 			printf(
@@ -642,7 +663,7 @@
 	} else {
 		if (bootverbose)
 			printf(
-		    "%d Hz differs from default of %d Hz by more than 1%%\n",
+		    "%d Hz differs from default of %d Hz by more than 10%%\n",
 			       freq, timer_freq);
 	}
 
--- src/sys/i386/conf/XBOX	Mon Feb  5 16:50:16 2007
+++ src/sys/i386/conf/XBOX	Mon Feb  5 17:36:12 2007
@@ -42,8 +42,7 @@
 #options 	_KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
 #options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
 options 	ADAPTIVE_GIANT		# Giant mutex is adaptive.
-# Xbox has a non-standard default timer frequency
-options 	TIMER_FREQ=1125000	# Gives ~733.34MHz CPU
+options 	CLK_USE_I8254_CALIBRATION # Timer has non-standard frequency
 
 #device		apic			# I/O APIC
 
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-i386->rink 
Responsible-Changed-By: rink 
Responsible-Changed-When: Sun Jun 10 20:21:51 UTC 2007 
Responsible-Changed-Why:  
I'l deal with this. 


http://www.freebsd.org/cgi/query-pr.cgi?pr=113540 

From: Ed Schouten <ed@fxq.nl>
To: Bruce Evans <brde@optusnet.com.au>
Cc: FreeBSD-gnats-submit@FreeBSD.org, freebsd-i386@FreeBSD.org
Subject: Re: i386/113540: decrease i8254 calibration precision to make it
	work with Xbox, remove warnings
Date: Mon, 11 Jun 2007 10:37:45 +0200

 --UK1lfQXsnwKrySH9
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 Hello Bruce,
 
 * Bruce Evans <brde@optusnet.com.au> wrote:
 >  On Sun, 10 Jun 2007, Ed Schouten wrote:
 > [...]
 > > - It decreases the precision of the timer (by default disabled) timer
 > >  calibration code from 1% to 10%; this is needed because the Xbox clock
 > >  is 6% off.
 >=20
 >  Is it only 6% off because the default is 6% off?  The error margin is
 >  supposed to be just a sanity check, but if the i8254 clock frequency is
 >  not required to be nearly 1193182 then this frequency can be almost
 >  anything in theory and no sanity check works.
 
 On all Xboxes it's 6% off.
 
 > > - It removes the hardcoded Xbox timer value from the Xbox configuration
 > >  file and enables timer calibration.
 >=20
 >  I hope to remove the timer calibration.  It was mainly for RTC calibrati=
 on,
 >  but that most important part of it has been axed.  In practice, the i8254
 >  has always been nearly 1193182 until now, with an error of about the same
 >  as for the RTC, so it doesn't matter which of these is used as a referen=
 ce.
 >  What I do now is not worry much about initial calibration; then fix up
 >  the frequencies of all timecounters in /etc/rc.local, using the results
 >  of more accurate calibrations previously done in userland.  Unfortunatel=
 y,
 >  this requires a lot of setup (ntpd might be able to do it automatically
 >  but might take years to stabilize if the initial frequencies are very
 >  inaccurate).
 
 So what do you think about this patch:
 
 	http://g-rave.nl/junk/freebsd-xbox-clock.diff
 
 We don't depend on the calibration code anymore, but just set the new
 standard timer frequency in i8254_init(). It doesn't touch any existing
 code outside ifdef's.
 
 > [...]
 >=20
 >  Does XBOX have any other timers/timecounters that might give a more
 >  suitable reference?
 
 As far as I know, they don't. Xbox'es don't have ACPI, so that means we
 can't use things like the HPET. The only two counters that show up are:
 
 | Timecounter "i8254" frequency 1124993 Hz quality 0
 | Timecounter "TSC" frequency 733333526 Hz quality 800
 
 Yours,
 --=20
  Ed Schouten <ed@fxq.nl>
  WWW: http://g-rave.nl/
 
 --UK1lfQXsnwKrySH9
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.7 (FreeBSD)
 
 iD8DBQFGbQnZ52SDGA2eCwURAjusAJ40D7F3tPhMxF1ni5h5T+/Klmj+VQCfdfPp
 WD/ujL8P1cNxUZxUHI6ThM4=
 =ndy0
 -----END PGP SIGNATURE-----
 
 --UK1lfQXsnwKrySH9--

From: Bruce Evans <brde@optusnet.com.au>
To: Ed Schouten <ed@fxq.nl>
Cc: Bruce Evans <brde@optusnet.com.au>, FreeBSD-gnats-submit@FreeBSD.org,
        freebsd-i386@FreeBSD.org
Subject: Re: i386/113540: decrease i8254 calibration precision to make it
 work with Xbox, remove warnings
Date: Mon, 11 Jun 2007 22:13:26 +1000 (EST)

 On Mon, 11 Jun 2007, Ed Schouten wrote:
 
 > * Bruce Evans <brde@optusnet.com.au> wrote:
 >>  On Sun, 10 Jun 2007, Ed Schouten wrote:
 >> [...]
 >>> - It decreases the precision of the timer (by default disabled) timer
 >>>  calibration code from 1% to 10%; this is needed because the Xbox clock
 >>>  is 6% off.
 >>
 >>  Is it only 6% off because the default is 6% off?  The error margin is
 >>  supposed to be just a sanity check, but if the i8254 clock frequency is
 >>  not required to be nearly 1193182 then this frequency can be almost
 >>  anything in theory and no sanity check works.
 >
 > On all Xboxes it's 6% off.
 
 I mean, is it always different from the current default of 1193182 by about
 -6%.  A 6% difference depending on the machine sub-type would be surprising.
 
 >>> - It removes the hardcoded Xbox timer value from the Xbox configuration
 >>>  file and enables timer calibration.
 >>
 >>  I hope to remove the timer calibration.  It was mainly for RTC calibration,
 >>  ...
 >
 > So what do you think about this patch:
 >
 > 	http://g-rave.nl/junk/freebsd-xbox-clock.diff
 >
 > We don't depend on the calibration code anymore, but just set the new
 > standard timer frequency in i8254_init(). It doesn't touch any existing
 > code outside ifdef's.
 
 That's much simpler.
 
 Grep for TIMER_FREQ and values like 119 and 149 in the kernel and in
 utilities like kbdcontrol and you will find a few more problems.  The
 variable is supposed to be used, but some places use the macro or
 worse.  The spkr driver seems to do everything correctly, but everything
 else has messes converting from "pitch"es to periods in i8254 timer
 ticks.  The magic numbers here are:
 
 - 119 = first few digits of 1193182.
    1193182 may be found in kbdcontrol.c.
 - 149 = first few digits of 1491 = the period in 1193182-Hz timer ticks for
          the intended syscons default bell frequncy of BELL_PITCH = 800 Hz
        = the frequency that results from not converting BELL_PITCH to
  	1193182-Hz timer ticks.
    1491 may be found miscalculated as 1493 in the dead pcvt driver.
 
 Bruce

From: Bruce Evans <brde@optusnet.com.au>
To: Ed Schouten <ed@fxq.nl>
Cc: FreeBSD-gnats-submit@freebsd.org, freebsd-i386@freebsd.org
Subject: Re: i386/113540: decrease i8254 calibration precision to make it
 work with Xbox, remove warnings
Date: Mon, 11 Jun 2007 13:58:23 +1000 (EST)

 On Sun, 10 Jun 2007, Ed Schouten wrote:
 
 >> Description:
 > For some reason, the timers in the Microsoft Xbox aren't as sane as on
 > PC's; it has two issues:
 >
 > - The frequency of the i8254 timer is 1125000 Hz instead of 1193182 Hz.
 >  The Microsoft Xbox port currently solves this by hardcoding TIMER_FREQ
 >  in the config file.
 > - The diagnostic and status registers of the RTC contain invalid data,
 >  which causes FreeBSD to assume the RTC is broken. This causes a lot of
 >  spurious messages in the dmesg.
 >> How-To-Repeat:
 >> Fix:
 > I've been using the following patch on my Xbox for a long time now; it
 > essentially does the following things:
 >
 > - It changes the rtcin() routine to return fake values for the diagnose
 >  and status registers, which forces FreeBSD to properly use theh RTC.
 > - It decreases the precision of the timer (by default disabled) timer
 >  calibration code from 1% to 10%; this is needed because the Xbox clock
 >  is 6% off.
 
 Is it only 6% off because the default is 6% off?  The error margin is
 supposed to be just a sanity check, but if the i8254 clock frequency is
 not required to be nearly 1193182 then this frequency can be almost
 anything in theory and no sanity check works.
 
 > - It removes the hardcoded Xbox timer value from the Xbox configuration
 >  file and enables timer calibration.
 
 I hope to remove the timer calibration.  It was mainly for RTC calibration,
 but that most important part of it has been axed.  In practice, the i8254
 has always been nearly 1193182 until now, with an error of about the same
 as for the RTC, so it doesn't matter which of these is used as a reference.
 What I do now is not worry much about initial calibration; then fix up
 the frequencies of all timecounters in /etc/rc.local, using the results
 of more accurate calibrations previously done in userland.  Unfortunately,
 this requires a lot of setup (ntpd might be able to do it automatically
 but might take years to stabilize if the initial frequencies are very
 inaccurate).
 
 > The reason why we want to do such a thing is because we could then
 > compile kernels that run on Xbox'es and PC's without a clock drift on
 > one of those systems.
 
 You could make the frequency a tunable.  This would minimize clock drift
 before the frequency can be fixed up in /etc/rc, but still requires
 pre-calibration and storing the result somewhere.
 
 Does XBOX have any other timers/timecounters that might give a more
 suitable reference?
 
 Bruce
State-Changed-From-To: open->closed 
State-Changed-By: rink 
State-Changed-When: Mon Feb 11 14:31:22 UTC 2008 
State-Changed-Why:  
From the discussion, I think we are better off by just forcing the frequency 
on the XBOX. I fear applying the patch may cause issues on older systems, and 
I don't think this issue is important enough to make XBOX-only (the hard-coded 
value is good enough there) 

http://www.freebsd.org/cgi/query-pr.cgi?pr=113540 
>Unformatted:
