summaryrefslogtreecommitdiff
path: root/sys/dev/dec
diff options
context:
space:
mode:
authorjoerg <joerg@NetBSD.org>2008-01-03 23:02:24 +0000
committerjoerg <joerg@NetBSD.org>2008-01-03 23:02:24 +0000
commit28b31e738fa993dd2cbd87e89978a6c5f199897e (patch)
treefec1eb6a54cb3615a33b330929c022bcde7aa7e0 /sys/dev/dec
parent26ecc8b33ad5f179433c5efb59ecaca3f174e4c7 (diff)
Timecounter and generic todr support for pmax. From Garret D'Amore.
Diffstat (limited to 'sys/dev/dec')
-rw-r--r--sys/dev/dec/clockvar.h20
-rw-r--r--sys/dev/dec/mcclock.c119
-rw-r--r--sys/dev/dec/mcclock_pad32.c5
-rw-r--r--sys/dev/dec/mcclockvar.h3
4 files changed, 94 insertions, 53 deletions
diff --git a/sys/dev/dec/clockvar.h b/sys/dev/dec/clockvar.h
index 331a56a26fd..e43b5e3741b 100644
--- a/sys/dev/dec/clockvar.h
+++ b/sys/dev/dec/clockvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: clockvar.h,v 1.8 2005/12/11 12:21:20 christos Exp $ */
+/* $NetBSD: clockvar.h,v 1.9 2008/01/03 23:02:25 joerg Exp $ */
/*
* Copyright (c) 1994, 1995 Carnegie-Mellon University.
@@ -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 *);
diff --git a/sys/dev/dec/mcclock.c b/sys/dev/dec/mcclock.c
index 7e2ee64dd54..cb424c68763 100644
--- a/sys/dev/dec/mcclock.c
+++ b/sys/dev/dec/mcclock.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mcclock.c,v 1.17 2005/12/11 12:21:20 christos Exp $ */
+/* $NetBSD: mcclock.c,v 1.18 2008/01/03 23:02:25 joerg Exp $ */
/*
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -28,12 +28,13 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mcclock.c,v 1.17 2005/12/11 12:21:20 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mcclock.c,v 1.18 2008/01/03 23:02:25 joerg Exp $");
#include <sys/param.h>
#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 1.17 2005/12/11 12:21:20 christos Exp $"
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) \
@@ -69,7 +70,7 @@ mcclock_attach(sc, busfns)
const struct mcclock_busfns *busfns;
{
- printf(": mc146818 or compatible");
+ printf(": mc146818 or compatible\n");
sc->sc_busfns = busfns;
@@ -77,6 +78,11 @@ mcclock_attach(sc, busfns)
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 +139,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;
}
diff --git a/sys/dev/dec/mcclock_pad32.c b/sys/dev/dec/mcclock_pad32.c
index d7ea12311f0..c2319df1f13 100644
--- a/sys/dev/dec/mcclock_pad32.c
+++ b/sys/dev/dec/mcclock_pad32.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mcclock_pad32.c,v 1.13 2005/12/11 12:21:20 christos Exp $ */
+/* $NetBSD: mcclock_pad32.c,v 1.14 2008/01/03 23:02:25 joerg Exp $ */
/*
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mcclock_pad32.c,v 1.13 2005/12/11 12:21:20 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mcclock_pad32.c,v 1.14 2008/01/03 23:02:25 joerg Exp $");
/*
@@ -49,6 +49,7 @@ __KERNEL_RCSID(0, "$NetBSD: mcclock_pad32.c,v 1.13 2005/12/11 12:21:20 christos
#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>
diff --git a/sys/dev/dec/mcclockvar.h b/sys/dev/dec/mcclockvar.h
index 1fa5abba443..f7e3f63107a 100644
--- a/sys/dev/dec/mcclockvar.h
+++ b/sys/dev/dec/mcclockvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: mcclockvar.h,v 1.6 2005/12/11 12:21:20 christos Exp $ */
+/* $NetBSD: mcclockvar.h,v 1.7 2008/01/03 23:02:25 joerg Exp $ */
/*
* Copyright (c) 1996 Carnegie-Mellon University.
@@ -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 {