Subject: generic todr and timecounter support for next68k
To: None <port-next68k@netbsd.org>
From: Garrett D'Amore <garrett_damore@tadpole.com>
List: port-next68k
Date: 09/08/2006 19:16:55
This is a multi-part message in MIME format.
--------------070204050501070102030902
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

timecounters & todr patch.

The following patch addresses support for NeXT 68k platforms for
timecounters and generic time-of-day support.  I've only compile tested
at this point, but it should work.

If someone can test, and let me know, or even better, if the
port-maintainer could do so, that would be great.

Once it is known to work, it can be committed.

-- 
Garrett D'Amore, Principal Software Engineer
Tadpole Computer / Computing Technologies Division,
General Dynamics C4 Systems
http://www.tadpolecomputer.com/
Phone: 951 325-2134  Fax: 951 325-2191


--------------070204050501070102030902
Content-Type: text/x-patch;
 name="next68k.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="next68k.diff"

Index: sys/arch/next68k/include/types.h
===================================================================
RCS file: /cvsroot/src/sys/arch/next68k/include/types.h,v
retrieving revision 1.1.1.1
diff -d -p -u -r1.1.1.1 types.h
--- sys/arch/next68k/include/types.h	9 Jun 1998 07:53:05 -0000	1.1.1.1
+++ sys/arch/next68k/include/types.h	9 Sep 2006 02:14:41 -0000
@@ -1,3 +1,6 @@
 /*	$NetBSD: types.h,v 1.1.1.1 1998/06/09 07:53:05 dbj Exp $	*/
 
 #include <m68k/types.h>
+
+#define __HAVE_TIMECOUNTER
+#define	__HAVE_GENERIC_TODR
Index: sys/arch/next68k/next68k/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/next68k/next68k/clock.c,v
retrieving revision 1.10
diff -d -p -u -r1.10 clock.c
--- sys/arch/next68k/next68k/clock.c	4 Aug 2006 02:07:59 -0000	1.10
+++ sys/arch/next68k/next68k/clock.c	9 Sep 2006 02:14:41 -0000
@@ -85,52 +85,6 @@ next68k_calibrate_delay(void)
 	cpuspeed = 2048 / delay_divisor;
 }
 
-#define	SECDAY		(24 * 60 * 60)
-#define	SECYR		(SECDAY * 365)
-
-/*
- * Set up the system's time, given a `reasonable' time value.
- */
-void
-inittodr(time_t base)
-{
-	int badbase = 0;
-
-	if (base < 5*SECYR) {
-		printf("WARNING: preposterous time in file system");
-		base = 6*SECYR + 186*SECDAY + SECDAY/2;
-		badbase = 1;
-	}
-
-	if ((time.tv_sec = getsecs()) == 0) {
-		printf("WARNING: bad date in battery clock");
-
-		/*
-		 * Believe the time in the file system for lack of
-		 * anything better, resetting the clock.
-		 */
-
-		time.tv_sec = base;
-		if (!badbase)
-			resettodr();
-	} else {
-		int deltat = time.tv_sec - base;
-
-		if (deltat < 0)
-			deltat = -deltat;
-		if (deltat < 2 * SECDAY)
-			return;
-		printf("WARNING: clock %s %d days\n",
-		       time.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
-	}
-}
-
-void
-resettodr(void)
-{
-	setsecs(time.tv_sec);
-}
-
 int clock_intr(void *);
 
 int
@@ -199,39 +153,7 @@ setstatclockrate(int newhz)
 
 /* @@@ update this to use the usec timer 
  * Darrin B Jewell <jewell@mit.edu>  Sun Feb  8 05:01:02 1998
+ * XXX: Well, there is no more microtime.  But if there is a hardware
+ * timer of any sort, it could be added.   ENODOCS.  gdamore.
  */
 
-
-/*
- * Return the best possible estimate of the time in the timeval
- * to which tvp points.  We do this by returning the current time
- * plus the amount of time since the last clock interrupt (clock.c:clkread).
- *
- * Check that this time is no less than any previously-reported time,
- * which could happen around the time of a clock adjustment.  Just for fun,
- * we guarantee that the time will be greater than the value obtained by a
- * previous call.
- */
-
-void
-microtime(struct timeval *tvp)
-{
-	int s;
-	static struct timeval lasttime;
-
-	s = splhigh();
-	*tvp = time;
-	tvp->tv_usec++;
-	while (tvp->tv_usec >= 1000000) {
-		tvp->tv_sec++;
-		tvp->tv_usec -= 1000000;
-	}
-	if (tvp->tv_sec == lasttime.tv_sec &&
-	    tvp->tv_usec <= lasttime.tv_usec &&
-	    (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
-		tvp->tv_sec++;
-		tvp->tv_usec -= 1000000;
-	}
-	lasttime = *tvp;
-	splx(s);
-}
Index: sys/arch/next68k/next68k/rtc.c
===================================================================
RCS file: /cvsroot/src/sys/arch/next68k/next68k/rtc.c,v
retrieving revision 1.13
diff -d -p -u -r1.13 rtc.c
--- sys/arch/next68k/next68k/rtc.c	15 Mar 2006 15:39:26 -0000	1.13
+++ sys/arch/next68k/next68k/rtc.c	9 Sep 2006 02:14:41 -0000
@@ -59,9 +59,20 @@ __KERNEL_RCSID(0, "$NetBSD: rtc.c,v 1.13
 u_char new_clock;
 volatile u_int *scr2 = (u_int *)NEXT_P_SCR2; /* will get memory mapped in rtc_init */
 
+static int gettime_old(todr_chip_handle_t, struct clock_ymdhms *);
+static int settime_old(todr_chip_handle_t, struct clock_ymdhms *);
+static int gettime_new(todr_chip_handle_t, volatile struct timeval *);
+static int settime_new(todr_chip_handle_t, volatile struct timeval *);
+
+/*
+ * NB: This code should probably be converted to a _true_ device, then this
+ * initialization could happen in attach.  The printf could get fixed then,
+ * too.
+ */
 void
 rtc_init(void)
 {
+	static struct todr_chip_handle tch;
 	u_char val;
 	
 	scr2 = (u_int *)IIOV(NEXT_P_SCR2);
@@ -76,6 +87,21 @@ rtc_init(void)
 #ifdef RTC_DEBUG
 	rtc_print();
 #endif
+
+	if (new_clock) {
+		tch.todr_gettime = gettime_new;
+		tch.todr_settime = settime_new;
+		tch.todr_gettime_ymdhms = NULL;
+		tch.todr_settime_ymdhms = NULL;
+	} else {
+		tch.todr_gettime_ymdhms = gettime_old;
+		tch.todr_settime_ymdhms = settime_old;
+		tch.todr_gettime = NULL;
+		tch.todr_settime = NULL;
+	}
+	tch.todr_setwen = NULL;
+
+	todr_attach(&tch);
 }
 
 void
@@ -241,56 +267,45 @@ poweroff(void)
 }
 
 
-time_t
-getsecs(void)
+int
+gettime_old(todr_chip_handle_t tch, struct clock_ymdhms *dt)
 {
-	u_int secs = 0;
+	u_char h, y;
 	
-	if (new_clock) {
-		secs = rtc_read(RTC_CNTR0) << 24 |
-				rtc_read(RTC_CNTR1) << 16 |
-				rtc_read(RTC_CNTR2) << 8	 |
-				rtc_read(RTC_CNTR3);
+	struct clock_ymdhms val;
+	y = FROMBCD(rtc_read(RTC_YR));
+	if (y >= 69) {
+		dt->dt_year = 1900+y;
 	} else {
-		struct clock_ymdhms val;
-		{
-			u_char y;
-			y = FROMBCD(rtc_read(RTC_YR));
-			if (y >= 69) {
-				val.dt_year = 1900+y;
-			} else {
-				val.dt_year = 2000+y;
-			}
-		}
-		val.dt_mon	= FROMBCD(rtc_read(RTC_MON)&0x1f);
-		val.dt_day	= FROMBCD(rtc_read(RTC_DATE)&0x3f);
-		val.dt_wday = FROMBCD(rtc_read(RTC_DAY)&0x7);
-		{
-			u_char h;
-			h = rtc_read(RTC_HRS);
-			if (h & 0x80) {					/* time is am/pm format */
-				val.dt_hour = FROMBCD(h&0x1f);
-				if (h & 0x20) { /* pm */
-					if (val.dt_hour < 12) val.dt_hour += 12;
-				} else {  /* am */
-					if (val.dt_hour == 12) val.dt_hour = 0;
-				}
-			} else {								/* time is 24 hour format */
-				val.dt_hour = FROMBCD(h & 0x3f);
-			}
-		}
-		val.dt_min	= FROMBCD(rtc_read(RTC_MIN)&0x7f);
-		val.dt_sec	= FROMBCD(rtc_read(RTC_SEC)&0x7f);
+		dt->dt_year = 2000+y;
+	}
 
-		secs = clock_ymdhms_to_secs(&val);
+	dt->dt_mon	= FROMBCD(rtc_read(RTC_MON)&0x1f);
+	dt->dt_day	= FROMBCD(rtc_read(RTC_DATE)&0x3f);
+	dt->dt_wday = FROMBCD(rtc_read(RTC_DAY)&0x7);
+
+	h = rtc_read(RTC_HRS);
+	if (h & 0x80) {			/* time is am/pm format */
+		dt->dt_hour = FROMBCD(h&0x1f);
+		if (h & 0x20) { /* pm */
+			if (dt->dt_hour < 12) dt->dt_hour += 12;
+		} else {  /* am */
+			if (dt->dt_hour == 12) dt->dt_hour = 0;
+		}
+	} else {	/* time is 24 hour format */
+		val.dt_hour = FROMBCD(h & 0x3f);
 	}
 
-	return secs;
+	dt->dt_min	= FROMBCD(rtc_read(RTC_MIN)&0x7f);
+	dt->dt_sec	= FROMBCD(rtc_read(RTC_SEC)&0x7f);
+
+	return 0;
 }
 
-void
-setsecs(time_t secs)
+int
+settime_old(todr_chip_handle_t tcr, struct clock_ymdhms *dt)
 {
+	u_char h;
 
 	/* Stop the clock */
 	rtc_write(RTC_CONTROL,rtc_read(RTC_CONTROL) & ~RTC_START);
@@ -300,39 +315,62 @@ setsecs(time_t secs)
 	rtc_print();
 #endif
 
-	if (new_clock) {
-		rtc_write(RTC_CNTR0, (secs >> 24) & 0xff);
-		rtc_write(RTC_CNTR1, (secs >> 16) & 0xff);
-		rtc_write(RTC_CNTR2, (secs >> 8) & 0xff);
-		rtc_write(RTC_CNTR3, (secs) & 0xff);
-
-	} else {
-		struct clock_ymdhms val;
-		clock_secs_to_ymdhms(secs,&val);
-		rtc_write(RTC_SEC,TOBCD(val.dt_sec));
-		rtc_write(RTC_MIN,TOBCD(val.dt_min));
-		{
-			u_char h;
-			h = rtc_read(RTC_HRS);
-			if (h & 0x80) {						/* time is am/pm format */
-				if (val.dt_hour == 0) {
-					rtc_write(RTC_HRS,TOBCD(12)|0x80);
-				} else if (val.dt_hour < 12) {	/* am */
-					rtc_write(RTC_HRS,TOBCD(val.dt_hour)|0x80);
-				} else if (val.dt_hour == 12) {
-						rtc_write(RTC_HRS,TOBCD(12)|0x80|0x20);
-				} else {								/* pm */
-					rtc_write(RTC_HRS,TOBCD(val.dt_hour-12)|0x80|0x20);
-				}
-			} else {									/* time is 24 hour format */
-				rtc_write(RTC_HRS,TOBCD(val.dt_hour));
-			}
-		}
-		rtc_write(RTC_DAY,TOBCD(val.dt_wday));
-		rtc_write(RTC_DATE,TOBCD(val.dt_day));
-		rtc_write(RTC_MON,TOBCD(val.dt_mon));
-		rtc_write(RTC_YR,TOBCD(val.dt_year%100));
+	rtc_write(RTC_SEC,TOBCD(dt->dt_sec));
+	rtc_write(RTC_MIN,TOBCD(dt->dt_min));
+	h = rtc_read(RTC_HRS);
+	if (h & 0x80) {		/* time is am/pm format */
+		if (dt->dt_hour == 0) {
+			rtc_write(RTC_HRS,TOBCD(12)|0x80);
+		} else if (dt->dt_hour < 12) {	/* am */
+			rtc_write(RTC_HRS,TOBCD(dt->dt_hour)|0x80);
+		} else if (dt->dt_hour == 12) {
+				rtc_write(RTC_HRS,TOBCD(12)|0x80|0x20);
+		} else 		/* pm */
+			rtc_write(RTC_HRS,TOBCD(dt->dt_hour-12)|0x80|0x20);
+	} else {	/* time is 24 hour format */
+			rtc_write(RTC_HRS,TOBCD(dt->dt_hour));
 	}
+	rtc_write(RTC_DAY,TOBCD(dt->dt_wday));
+	rtc_write(RTC_DATE,TOBCD(dt->dt_day));
+	rtc_write(RTC_MON,TOBCD(dt->dt_mon));
+	rtc_write(RTC_YR,TOBCD(dt->dt_year%100));
+
+#ifdef RTC_DEBUG
+	printf("Regs after:\n",secs);
+	rtc_print();
+#endif
+
+	/* restart the clock */
+	rtc_write(RTC_CONTROL,rtc_read(RTC_CONTROL) | RTC_START);
+	return 0;
+}
+
+int
+gettime_new(todr_chip_handle_t tch, volatile struct timeval *tvp)
+{
+	tvp->tv_sec = rtc_read(RTC_CNTR0) << 24 |
+			rtc_read(RTC_CNTR1) << 16 |
+			rtc_read(RTC_CNTR2) << 8	 |
+			rtc_read(RTC_CNTR3);
+	return 0;
+}
+
+int
+settime_new(todr_chip_handle_t tch, volatile struct timeval *tvp)
+{
+
+	/* Stop the clock */
+	rtc_write(RTC_CONTROL,rtc_read(RTC_CONTROL) & ~RTC_START);
+
+#ifdef RTC_DEBUG
+	printf("Setting RTC to 0x%08x.  Regs before:\n",tvp->tv_sec);
+	rtc_print();
+#endif
+
+	rtc_write(RTC_CNTR0, (tvp->tv_sec >> 24) & 0xff);
+	rtc_write(RTC_CNTR1, (tvp->tv_sec >> 16) & 0xff);
+	rtc_write(RTC_CNTR2, (tvp->tv_sec >> 8) & 0xff);
+	rtc_write(RTC_CNTR3, (tvp->tv_sec) & 0xff);
 
 #ifdef RTC_DEBUG
 	printf("Regs after:\n",secs);
@@ -342,4 +380,5 @@ setsecs(time_t secs)
 	/* restart the clock */
 	rtc_write(RTC_CONTROL,rtc_read(RTC_CONTROL) | RTC_START);
 
+	return 0;
 }
Index: sys/arch/next68k/next68k/rtc.h
===================================================================
RCS file: /cvsroot/src/sys/arch/next68k/next68k/rtc.h,v
retrieving revision 1.3
diff -d -p -u -r1.3 rtc.h
--- sys/arch/next68k/next68k/rtc.h	19 Jan 2005 01:58:21 -0000	1.3
+++ sys/arch/next68k/next68k/rtc.h	9 Sep 2006 02:14:41 -0000
@@ -39,5 +39,3 @@ void rtc_init(void);
 u_char rtc_read(u_char);
 void rtc_write(u_char, u_char);
 void rtc_print(void);
-time_t getsecs(void);
-void setsecs(time_t);

--------------070204050501070102030902--