Subject: generic todr support for pmax
To: None <port-pmax@netbsd.org>
From: Garrett D'Amore <garrett@damore.org>
List: port-pmax
Date: 09/15/2006 17:51:56
This is a multi-part message in MIME format.
--------------060202010003040503040603
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Here's my swag at generic TODR support for pmax.  Kinda ugly, but
hopefully it will work.  Compile tested only.

    -- Garrett

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

Index: dev/dec/clockvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/dec/clockvar.h,v
retrieving revision 1.8
diff -d -p -u -r1.8 clockvar.h
--- dev/dec/clockvar.h	11 Dec 2005 12:21:20 -0000	1.8
+++ dev/dec/clockvar.h	16 Sep 2006 00:21:47 -0000
@@ -32,22 +32,6 @@
  */
 
 /*
- * clocktime structure:
- *
- * structure passed to TOY clocks when setting them.  broken out this
- * way, so that the time_t -> field conversion can be shared.
- */
-struct clocktime {
-	int	year;			/* year - 1900 */
-	int	mon;			/* month (1 - 12) */
-	int	day;			/* day (1 - 31) */
-	int	hour;			/* hour (0 - 23) */
-	int	min;			/* minute (0 - 59) */
-	int	sec;			/* second (0 - 59) */
-	int	dow;			/* day of week (0 - 6; 0 = Sunday) */
-};
-
-/*
  * clockfns structure:
  *
  * function switch used by chip-independent clock code, to access
@@ -55,8 +39,6 @@ struct clocktime {
  */
 struct clockfns {
 	void	(*cf_init)(struct device *);
-	void	(*cf_get)(struct device *, time_t, struct clocktime *);
-	void	(*cf_set)(struct device *, struct clocktime *);
 };
 
 void clockattach(struct device *, const struct clockfns *);
Index: dev/dec/mcclock.c
===================================================================
RCS file: /cvsroot/src/sys/dev/dec/mcclock.c,v
retrieving revision 1.17
diff -d -p -u -r1.17 mcclock.c
--- dev/dec/mcclock.c	11 Dec 2005 12:21:20 -0000	1.17
+++ dev/dec/mcclock.c	16 Sep 2006 00:21:47 -0000
@@ -34,6 +34,7 @@ __KERNEL_RCSID(0, "$NetBSD: mcclock.c,v 
 #include <sys/kernel.h>
 #include <sys/systm.h>
 #include <sys/device.h>
+#include <dev/clock_subr.h>
 
 #include <dev/dec/clockvar.h>
 #include <dev/dec/mcclockvar.h>
@@ -51,11 +52,11 @@ __KERNEL_RCSID(0, "$NetBSD: mcclock.c,v 
 
 
 void	mcclock_init(struct device *);
-void	mcclock_get(struct device *, time_t, struct clocktime *);
-void	mcclock_set(struct device *, struct clocktime *);
+int	mcclock_get(todr_chip_handle_t, volatile struct timeval *);
+int	mcclock_set(todr_chip_handle_t, volatile struct timeval *);
 
 const struct clockfns mcclock_clockfns = {
-	mcclock_init, mcclock_get, mcclock_set,
+	mcclock_init, 
 };
 
 #define	mc146818_write(dev, reg, datum)					\
@@ -76,7 +77,10 @@ mcclock_attach(sc, busfns)
 	/* Turn interrupts off, just in case. */
 	mc146818_write(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
 
-	clockattach(&sc->sc_dev, &mcclock_clockfns);
+	sc->sc_todr.todr_gettime = mcclock_get;
+	sc->sc_todr.todr_settime = mcclock_set;
+	sc->sc_todr.cookie = sc;
+	todr_attach(&sc->sc_todr);
 }
 
 void
@@ -133,56 +137,107 @@ again:
 }
 
 /*
+ * Experiments (and  passing years) show that Decstation PROMS
+ * assume the kernel uses the clock chip as a time-of-year clock.
+ * The PROM assumes the clock is always set to 1972 or 1973, and contains
+ * time-of-year in seconds.   The PROM checks the clock at boot time,
+ * and if it's outside that range, sets it to 1972-01-01.
+ *
+ * XXX should be at the mc146818 layer?
+*/
+
+/*
  * Get the time of day, based on the clock's value and/or the base value.
  */
-void
-mcclock_get(dev, base, ct)
-	struct device *dev;
-	time_t base;
-	struct clocktime *ct;
+int
+mcclock_get(todr_chip_handle_t tch, volatile struct timeval *tvp)
 {
-	struct mcclock_softc *sc = (struct mcclock_softc *)dev;
+	struct mcclock_softc *sc = (struct mcclock_softc *)tch->cookie;
+	uint32_t yearsecs;
 	mc_todregs regs;
 	int s;
+	struct clock_ymdhms dt;
 
 	s = splclock();
 	MC146818_GETTOD(sc, &regs)
 	splx(s);
 
-	ct->sec = regs[MC_SEC];
-	ct->min = regs[MC_MIN];
-	ct->hour = regs[MC_HOUR];
-	ct->dow = regs[MC_DOW];
-	ct->day = regs[MC_DOM];
-	ct->mon = regs[MC_MONTH];
-	ct->year = regs[MC_YEAR];
+	dt.dt_sec = regs[MC_SEC];
+	dt.dt_min = regs[MC_MIN];
+	dt.dt_hour = regs[MC_HOUR];
+	dt.dt_day = regs[MC_DOM];
+	dt.dt_mon = regs[MC_MONTH];
+	dt.dt_year = 1972;
+
+	yearsecs = clock_ymdhms_to_secs(&dt) - (72 - 70) * SECYR;
+
+	/*
+	 * Take the actual year from the filesystem if possible;
+	 * allow for 2 days of clock loss and 363 days of clock gain.
+	 */
+	dt.dt_year = 1972; /* or MINYEAR or base/SECYR+1970 ... */
+	dt.dt_mon = 1;
+	dt.dt_day = 1;
+	dt.dt_hour = 0;
+	dt.dt_min = 0;
+	dt.dt_sec = 0;
+	for(;;) {
+		tvp->tv_sec = yearsecs + clock_ymdhms_to_secs(&dt);
+		if (tvp->tv_sec > tch->base_time - 2 * SECDAY)
+			break;
+		dt.dt_year++;
+	}
+
+	tvp->tv_usec = 0;
+	return 0;
 }
 
 /*
  * Reset the TODR based on the time value.
  */
-void
-mcclock_set(dev, ct)
-	struct device *dev;
-	struct clocktime *ct;
+int
+mcclock_set(todr_chip_handle_t tch, volatile struct timeval *tvp)
 {
-	struct mcclock_softc *sc = (struct mcclock_softc *)dev;
+	struct mcclock_softc *sc = (struct mcclock_softc *)tch->cookie;
+	struct clock_ymdhms dt;
+	uint32_t yearsecs;
 	mc_todregs regs;
 	int s;
 
+	/*
+	 * calculate seconds relative to this year
+	 */
+	clock_secs_to_ymdhms(tvp->tv_sec, &dt); /* get the year */
+	dt.dt_mon = 1;
+	dt.dt_day = 1;
+	dt.dt_hour = 0;
+	dt.dt_min = 0;
+	dt.dt_sec = 0;
+	yearsecs = tvp->tv_sec - clock_ymdhms_to_secs(&dt);
+
+#define first72 ((72 - 70) * SECYR)
+	clock_secs_to_ymdhms(first72 + yearsecs, &dt);
+
+#ifdef DEBUG
+	if (dt.dt_year != 1972)
+		printf("resettodr: botch (%ld, %ld)\n", yearsecs, time.tv_sec);
+#endif
+
 	s = splclock();
 	MC146818_GETTOD(sc, &regs);
 	splx(s);
 
-	regs[MC_SEC] = ct->sec;
-	regs[MC_MIN] = ct->min;
-	regs[MC_HOUR] = ct->hour;
-	regs[MC_DOW] = ct->dow;
-	regs[MC_DOM] = ct->day;
-	regs[MC_MONTH] = ct->mon;
-	regs[MC_YEAR] = ct->year;
+	regs[MC_SEC] = dt.dt_sec;
+	regs[MC_MIN] = dt.dt_min;
+	regs[MC_HOUR] = dt.dt_hour;
+	regs[MC_DOW] = dt.dt_wday;
+	regs[MC_DOM] = dt.dt_day;
+	regs[MC_MONTH] = dt.dt_mon;
+	regs[MC_YEAR] = dt.dt_year;
 
 	s = splclock();
 	MC146818_PUTTOD(sc, &regs);
 	splx(s);
+
+	return 0;
 }
Index: dev/dec/mcclock_pad32.c
===================================================================
RCS file: /cvsroot/src/sys/dev/dec/mcclock_pad32.c,v
retrieving revision 1.13
diff -d -p -u -r1.13 mcclock_pad32.c
--- dev/dec/mcclock_pad32.c	11 Dec 2005 12:21:20 -0000	1.13
+++ dev/dec/mcclock_pad32.c	16 Sep 2006 00:21:47 -0000
@@ -49,6 +49,7 @@ __KERNEL_RCSID(0, "$NetBSD: mcclock_pad3
 #include <sys/kernel.h>
 #include <sys/systm.h>
 #include <sys/device.h>
+#include <dev/clock_subr.h>
 
 #include <machine/autoconf.h>
 #include <dev/dec/clockvar.h>
Index: dev/dec/mcclockvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/dec/mcclockvar.h,v
retrieving revision 1.6
diff -d -p -u -r1.6 mcclockvar.h
--- dev/dec/mcclockvar.h	11 Dec 2005 12:21:20 -0000	1.6
+++ dev/dec/mcclockvar.h	16 Sep 2006 00:21:47 -0000
@@ -30,6 +30,7 @@
 struct mcclock_softc {
 	struct device sc_dev;
 	const struct mcclock_busfns *sc_busfns;
+	struct todr_chip_handle sc_todr;
 };
 
 struct mcclock_busfns {
Index: arch/pmax/ibus/mcclock_ibus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/pmax/ibus/mcclock_ibus.c,v
retrieving revision 1.12
diff -d -p -u -r1.12 mcclock_ibus.c
--- arch/pmax/ibus/mcclock_ibus.c	2 Oct 2002 04:15:09 -0000	1.12
+++ arch/pmax/ibus/mcclock_ibus.c	16 Sep 2006 00:21:47 -0000
@@ -34,6 +34,7 @@ __KERNEL_RCSID(0, "$NetBSD: mcclock_ibus
 #include <sys/kernel.h>
 #include <sys/device.h>
 #include <sys/systm.h>
+#include <dev/clock_subr.h>
 
 #include <dev/dec/mcclockvar.h>
 #include <dev/dec/mcclock_pad32.h>
Index: arch/pmax/include/types.h
===================================================================
RCS file: /cvsroot/src/sys/arch/pmax/include/types.h,v
retrieving revision 1.21
diff -d -p -u -r1.21 types.h
--- arch/pmax/include/types.h	5 Aug 2002 02:13:15 -0000	1.21
+++ arch/pmax/include/types.h	16 Sep 2006 00:21:47 -0000
@@ -4,6 +4,7 @@
 
 #define	__HAVE_DEVICE_REGISTER
 #define	__HAVE_GENERIC_SOFT_INTERRUPTS
+#define	__HAVE_GENERIC_TODR
 
 /* MIPS specific options */
 #define	__HAVE_BOOTINFO_H
Index: arch/pmax/pmax/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/pmax/pmax/clock.c,v
retrieving revision 1.34
diff -d -p -u -r1.34 clock.c
--- arch/pmax/pmax/clock.c	11 Dec 2005 12:18:39 -0000	1.34
+++ arch/pmax/pmax/clock.c	16 Sep 2006 00:21:47 -0000
@@ -194,160 +194,3 @@ setstatclockrate(newhz)
 	/* nothing we can do */
 }
 
-/*
- * Experiments (and  passing years) show that Decstation PROMS
- * assume the kernel uses the clock chip as a time-of-year clock.
- * The PROM assumes the clock is always set to 1972 or 1973, and contains
- * time-of-year in seconds.   The PROM checks the clock at boot time,
- * and if it's outside that range, sets it to 1972-01-01.
- *
- * XXX should be at the mc146818 layer?
-*/
-
-/*
- * Initialze the time of day register, based on the time base which is, e.g.
- * from a filesystem.  Base provides the time to within six months,
- * and the time of year clock (if any) provides the rest.
- */
-void
-inittodr(base)
-	time_t base;
-{
-	struct clocktime ct;
-	struct clock_ymdhms dt;
-	time_t yearsecs;
-	time_t deltat;
-	int badbase;
-
-	if (base < (MINYEAR-1970)*SECYR) {
-		printf("WARNING: preposterous time in file system");
-		/* read the system clock anyway */
-		base = (MINYEAR-1970)*SECYR;
-		badbase = 1;
-	} else
-		badbase = 0;
-
-	(*clockfns->cf_get)(clockdev, base, &ct);
-#ifdef DEBUG
-	printf("readclock: %d/%d/%d/%d/%d/%d", ct.year, ct.mon, ct.day,
-	       ct.hour, ct.min, ct.sec);
-#endif
-	clockinitted = 1;
-
-	/* simple sanity checks */
-	if (ct.year < 70 || ct.mon < 1 || ct.mon > 12 || ct.day < 1 ||
-	    ct.day > 31 || ct.hour > 23 || ct.min > 59 || ct.sec > 59) {
-		/*
-		 * Believe the time in the file system for lack of
-		 * anything better, resetting the TODR.
-		 */
-		time.tv_sec = base;
-		if (!badbase) {
-			printf("WARNING: preposterous clock chip time\n");
-			resettodr();
-		}
-		goto bad;
-	}
-
-	/*
-	 * The clock lives in 1972 (leapyear!);
-	 * calculate seconds relative to this year.
-	 */
-	dt.dt_year = 1972;
-	dt.dt_mon = ct.mon;
-	dt.dt_day = ct.day;
-	dt.dt_hour = ct.hour;
-	dt.dt_min = ct.min;
-	dt.dt_sec = ct.sec;
-	yearsecs = clock_ymdhms_to_secs(&dt) - (72 - 70) * SECYR;
-
-	/*
-	 * Take the actual year from the filesystem if possible;
-	 * allow for 2 days of clock loss and 363 days of clock gain.
-	 */
-	dt.dt_year = 1972; /* or MINYEAR or base/SECYR+1970 ... */
-	dt.dt_mon = 1;
-	dt.dt_day = 1;
-	dt.dt_hour = 0;
-	dt.dt_min = 0;
-	dt.dt_sec = 0;
-	for(;;) {
-		time.tv_sec = yearsecs + clock_ymdhms_to_secs(&dt);
-		if (badbase || (time.tv_sec > base - 2 * SECDAY))
-			break;
-		dt.dt_year++;
-	}
-#ifdef DEBUG
-	printf("=>%ld (%ld)\n", time.tv_sec, base);
-#endif
-
-	if (!badbase) {
-		/*
-		 * See if we gained/lost two or more days;
-		 * if so, assume something is amiss.
-		 */
-		deltat = time.tv_sec - base;
-		if (deltat < 0)
-			deltat = -deltat;
-		if (deltat < 2 * SECDAY)
-			return;
-		printf("WARNING: clock %s %d days",
-		    time.tv_sec < base ? "lost" : "gained",
-		       (int) (deltat / SECDAY));
-	}
-bad:
-	printf(" -- CHECK AND RESET THE DATE!\n");
-}
-
-/*
- * Reset the TODR based on the time value; used when the TODR
- * has a preposterous value and also when the time is reset
- * by the stime system call.  Also called when the TODR goes past
- * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
- * to wrap the TODR around.
- */
-void
-resettodr()
-{
-	time_t yearsecs;
-	struct clock_ymdhms dt;
-	struct clocktime ct;
-
-	if (!clockinitted)
-		return;
-
-	/*
-	 * calculate seconds relative to this year
-	 */
-	clock_secs_to_ymdhms(time.tv_sec, &dt); /* get the year */
-	dt.dt_mon = 1;
-	dt.dt_day = 1;
-	dt.dt_hour = 0;
-	dt.dt_min = 0;
-	dt.dt_sec = 0;
-	yearsecs = time.tv_sec - clock_ymdhms_to_secs(&dt);
-
-	/*
-	 * The clock lives in 1972 (leapyear!); calc fictious date.
-	 */
-#define first72 ((72 - 70) * SECYR)
-	clock_secs_to_ymdhms(first72 + yearsecs, &dt);
-
-#ifdef DEBUG
-	if (dt.dt_year != 1972)
-		printf("resettodr: botch (%ld, %ld)\n", yearsecs, time.tv_sec);
-#endif
-	ct.year = dt.dt_year % 100; /* rt clock wants 2 digits */
-	ct.mon = dt.dt_mon;
-	ct.day = dt.dt_day;
-	ct.hour = dt.dt_hour;
-	ct.min = dt.dt_min;
-	ct.sec = dt.dt_sec;
-	ct.dow = dt.dt_wday;
-#ifdef DEBUG
-	printf("setclock: %d/%d/%d/%d/%d/%d\n", ct.year, ct.mon, ct.day,
-	       ct.hour, ct.min, ct.sec);
-#endif
-
-	(*clockfns->cf_set)(clockdev, &ct);
-}
Index: arch/pmax/tc/mcclock_ioasic.c
===================================================================
RCS file: /cvsroot/src/sys/arch/pmax/tc/mcclock_ioasic.c,v
retrieving revision 1.18
diff -d -p -u -r1.18 mcclock_ioasic.c
--- arch/pmax/tc/mcclock_ioasic.c	2 Oct 2002 04:15:10 -0000	1.18
+++ arch/pmax/tc/mcclock_ioasic.c	16 Sep 2006 00:21:47 -0000
@@ -33,6 +33,7 @@ __KERNEL_RCSID(0, "$NetBSD: mcclock_ioas
 #include <sys/param.h>
 #include <sys/device.h>
 #include <sys/systm.h>
+#include <dev/clock_subr.h>
 
 #include <dev/dec/mcclockvar.h>
 #include <dev/dec/mcclock_pad32.h>
Index: arch/mips/mips/mips_mcclock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/mips/mips_mcclock.c,v
retrieving revision 1.15
diff -d -p -u -r1.15 mips_mcclock.c
--- arch/mips/mips/mips_mcclock.c	8 Mar 2006 23:46:23 -0000	1.15
+++ arch/mips/mips/mips_mcclock.c	16 Sep 2006 00:21:47 -0000
@@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: mips_mcclock
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/device.h>
+#include <dev/clock_subr.h>
 
 #include <dev/ic/mc146818reg.h>
 #include <dev/dec/mcclockvar.h>

--------------060202010003040503040603--