diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-04-28 12:58:29 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-04-28 12:58:29 +0000 |
commit | 24ee44d5c45a34741b11031b1bc91780b2dcbf50 (patch) | |
tree | b19ba67f2ac16694b2da626250ccf27bc69fc9c3 | |
parent | 6887b193b9ca540f1400351cad1d1dbf7dca36b2 (diff) |
Use the same inittodr()/resettodr() implementation as on arm64/armv7/sparc64
and move it to the end of machdep.c. Rework the actual implementation
for te MC14818 compatible RTC into something that can be used as a todr_handle.
ok mpi@
-rw-r--r-- | sys/arch/amd64/amd64/machdep.c | 92 | ||||
-rw-r--r-- | sys/arch/amd64/include/cpu.h | 3 | ||||
-rw-r--r-- | sys/arch/amd64/isa/clock.c | 97 |
3 files changed, 121 insertions, 71 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 21c88098743..ddb7315a03d 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.261 2020/01/24 05:27:31 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.262 2020/04/28 12:58:27 kettenis Exp $ */ /* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */ /*- @@ -277,6 +277,7 @@ cpu_startup(void) printf("%s", version); startclocks(); + rtcinit(); printf("real mem = %lu (%luMB)\n", ptoa((psize_t)physmem), ptoa((psize_t)physmem)/1024/1024); @@ -2066,3 +2067,92 @@ check_context(const struct reg *regs, struct trapframe *tf) return 0; } + +#include <sys/timetc.h> +#include <dev/clock_subr.h> + +todr_chip_handle_t todr_handle; + +#define MINYEAR ((OpenBSD / 100) - 1) /* minimum plausible year */ + +/* + * inittodr: + * + * Initialize time from the time-of-day register. + */ +void +inittodr(time_t base) +{ + time_t deltat; + struct timeval rtctime; + struct timespec ts; + int badbase; + + if (base < (MINYEAR - 1970) * SECYR) { + printf("WARNING: preposterous time in file system\n"); + /* read the system clock anyway */ + base = (MINYEAR - 1970) * SECYR; + badbase = 1; + } else + badbase = 0; + + if (todr_handle == NULL || + todr_gettime(todr_handle, &rtctime) != 0 || + rtctime.tv_sec < (MINYEAR - 1970) * SECYR) { + /* + * Believe the time in the file system for lack of + * anything better, resetting the TODR. + */ + rtctime.tv_sec = base; + rtctime.tv_usec = 0; + if (todr_handle != NULL && !badbase) + printf("WARNING: bad clock chip time\n"); + ts.tv_sec = rtctime.tv_sec; + ts.tv_nsec = rtctime.tv_usec * 1000; + tc_setclock(&ts); + goto bad; + } else { + ts.tv_sec = rtctime.tv_sec; + ts.tv_nsec = rtctime.tv_usec * 1000; + tc_setclock(&ts); + } + + if (!badbase) { + /* + * See if we gained/lost two or more days; if + * so, assume something is amiss. + */ + deltat = rtctime.tv_sec - base; + if (deltat < 0) + deltat = -deltat; + if (deltat < 2 * SECDAY) + return; /* all is well */ +#ifndef SMALL_KERNEL + printf("WARNING: clock %s %lld days\n", + rtctime.tv_sec < base ? "lost" : "gained", + (long long)(deltat / SECDAY)); +#endif + } + bad: + printf("WARNING: CHECK AND RESET THE DATE!\n"); +} + +/* + * resettodr: + * + * Reset the time-of-day register with the current time. + */ +void +resettodr(void) +{ + struct timeval rtctime; + + if (time_second == 1) + return; + + microtime(&rtctime); + + if (todr_handle != NULL && + todr_settime(todr_handle, &rtctime) != 0) + printf("WARNING: can't update clock chip time\n"); +} diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h index df98aafcc3b..0c96b8abde8 100644 --- a/sys/arch/amd64/include/cpu.h +++ b/sys/arch/amd64/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.134 2020/04/15 16:38:24 kettenis Exp $ */ +/* $OpenBSD: cpu.h,v 1.135 2020/04/28 12:58:28 kettenis Exp $ */ /* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */ /*- @@ -390,6 +390,7 @@ void proc_trampoline(void); /* clock.c */ extern void (*initclock_func)(void); void startclocks(void); +void rtcinit(void); void rtcstart(void); void rtcstop(void); void i8254_delay(int); diff --git a/sys/arch/amd64/isa/clock.c b/sys/arch/amd64/isa/clock.c index b80bcf7c647..a93b1a160f0 100644 --- a/sys/arch/amd64/isa/clock.c +++ b/sys/arch/amd64/isa/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.31 2019/08/21 20:44:09 cheloha Exp $ */ +/* $OpenBSD: clock.c,v 1.32 2020/04/28 12:58:28 kettenis Exp $ */ /* $NetBSD: clock.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */ /*- @@ -86,8 +86,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * Primitive clock interrupt routines. */ -/* #define CLOCKDEBUG */ -/* #define CLOCK_PARANOIA */ +/* #define CLOCK_DEBUG */ #include <sys/param.h> #include <sys/systm.h> @@ -101,6 +100,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include <machine/pio.h> #include <machine/cpufunc.h> +#include <dev/clock_subr.h> #include <dev/isa/isareg.h> #include <dev/isa/isavar.h> #include <dev/ic/mc146818reg.h> @@ -344,8 +344,6 @@ bintobcd(int n) return ((u_char)(((n / 10) << 4) & 0xf0) | ((n % 10) & 0x0f)); } -static int timeset; - /* * check whether the CMOS layout is "standard"-like (ie, not PS/2-like), * to be called at splclock() @@ -422,47 +420,21 @@ clock_expandyear(int clockyear) return (clockyear); } -/* - * Initialize the time of day register, based on the time base which is, e.g. - * from a filesystem. - */ -void -inittodr(time_t base) +int +rtcgettime(struct todr_chip_handle *handle, struct timeval *tv) { - struct timespec ts; mc_todregs rtclk; struct clock_ymdhms dt; int s; - - ts.tv_nsec = 0; - - /* - * We mostly ignore the suggested time (which comes from the - * file system) and go for the RTC clock time stored in the - * CMOS RAM. If the time can't be obtained from the CMOS, or - * if the time obtained from the CMOS is 5 or more years less - * than the suggested time, we used the suggested time. (In - * the latter case, it's likely that the CMOS battery has - * died.) - */ - - /* - * if the file system time is more than a year older than the - * kernel, warn and then set the base time to the CONFIG_TIME. - */ - if (base < 30*SECYR) { /* if before 2000, something's odd... */ - printf("WARNING: preposterous time in file system\n"); - base = 30*SECYR; - } - + s = splclock(); if (rtcget(&rtclk)) { splx(s); - printf("WARNING: invalid time in clock chip\n"); - goto fstime; + return EINVAL; } splx(s); -#ifdef DEBUG_CLOCK + +#ifdef CLOCK_DEBUG printf("readclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR], rtclk[MC_MONTH], rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN], rtclk[MC_SEC]); @@ -475,44 +447,18 @@ inittodr(time_t base) dt.dt_mon = bcdtobin(rtclk[MC_MONTH]); dt.dt_year = clock_expandyear(bcdtobin(rtclk[MC_YEAR])); - ts.tv_sec = clock_ymdhms_to_secs(&dt) - utc_offset; - - if (base != 0 && base < ts.tv_sec - 5*SECYR) - printf("WARNING: file system time much less than clock time\n"); - else if (base > ts.tv_sec + 5*SECYR) { - printf("WARNING: clock time much less than file system time\n"); - printf("WARNING: using file system time\n"); - goto fstime; - } - - tc_setclock(&ts); - timeset = 1; - return; - -fstime: - ts.tv_sec = base; - tc_setclock(&ts); - timeset = 1; - printf("WARNING: CHECK AND RESET THE DATE!\n"); + tv->tv_sec = clock_ymdhms_to_secs(&dt) - utc_offset; + tv->tv_usec = 0; + return 0; } -/* - * Reset the clock. - */ -void -resettodr(void) +int +rtcsettime(struct todr_chip_handle *handle, struct timeval *tv) { mc_todregs rtclk; struct clock_ymdhms dt; int century, s; - /* - * We might have been called by boot() due to a crash early - * on. Don't reset the clock chip in this case. - */ - if (!timeset) - return; - s = splclock(); if (rtcget(&rtclk)) memset(&rtclk, 0, sizeof(rtclk)); @@ -528,10 +474,11 @@ resettodr(void) rtclk[MC_MONTH] = bintobcd(dt.dt_mon); rtclk[MC_DOM] = bintobcd(dt.dt_day); -#ifdef DEBUG_CLOCK +#ifdef CLOCK_DEBUG printf("setclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR], rtclk[MC_MONTH], rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN], rtclk[MC_SEC]); #endif + s = splclock(); rtcput(&rtclk); if (rtc_update_century > 0) { @@ -539,6 +486,18 @@ resettodr(void) mc146818_write(NULL, centb, century); /* XXX softc */ } splx(s); + return 0; +} + +extern todr_chip_handle_t todr_handle; +struct todr_chip_handle rtc_todr; + +void +rtcinit(void) +{ + rtc_todr.todr_gettime = rtcgettime; + rtc_todr.todr_settime = rtcsettime; + todr_handle = &rtc_todr; } void |