diff options
-rw-r--r-- | sys/arch/mips64/mips64/mips64_machdep.c | 293 |
1 files changed, 158 insertions, 135 deletions
diff --git a/sys/arch/mips64/mips64/mips64_machdep.c b/sys/arch/mips64/mips64/mips64_machdep.c index 97d0325ef5d..e1bbbf80d8a 100644 --- a/sys/arch/mips64/mips64/mips64_machdep.c +++ b/sys/arch/mips64/mips64/mips64_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mips64_machdep.c,v 1.26 2018/06/13 14:38:42 visa Exp $ */ +/* $OpenBSD: mips64_machdep.c,v 1.27 2020/05/09 22:12:18 kettenis Exp $ */ /* * Copyright (c) 2009, 2010, 2012 Miodrag Vallat. @@ -58,6 +58,7 @@ #include <uvm/uvm_extern.h> #include <mips64/dev/clockvar.h> +#include <dev/clock_subr.h> /* * Build a tlb trampoline @@ -240,6 +241,68 @@ tlb_asid_wrap(struct cpu_info *ci) struct tod_desc sys_tod; void (*md_startclock)(struct cpu_info *); +extern todr_chip_handle_t todr_handle; +struct todr_chip_handle rtc_todr; + +int +rtc_gettime(struct todr_chip_handle *handle, struct timeval *tv) +{ + struct tod_desc *cd = &sys_tod; + struct clock_ymdhms dt; + struct tod_time c; + time_t base; + + KASSERT(cd->tod_get); + + /* + * Set base to a random time in this century just in case one + * of the supported RTCs uses it to determine the current + * century. + */ + base = 1234567890; + + /* + * Read RTC chip registers NOTE: Read routines are responsible + * for sanity checking clock. Dates after 19991231 should be + * returned as year >= 100. + */ + (*cd->tod_get)(cd->tod_cookie, base, &c); + + dt.dt_sec = c.sec; + dt.dt_min = c.min; + dt.dt_hour = c.hour; + dt.dt_day = c.day; + dt.dt_mon = c.mon; + dt.dt_year = c.year + 1900; + + tv->tv_sec = clock_ymdhms_to_secs(&dt); + tv->tv_usec = 0; + return 0; +} + +int +rtc_settime(struct todr_chip_handle *handle, struct timeval *tv) +{ + struct tod_desc *cd = &sys_tod; + struct clock_ymdhms dt; + struct tod_time c; + + KASSERT(cd->tod_set); + + clock_secs_to_ymdhms(tv->tv_sec, &dt); + + c.sec = dt.dt_sec; + c.min = dt.dt_min; + c.hour = dt.dt_hour; + c.day = dt.dt_day; + c.mon = dt.dt_mon; + c.year = dt.dt_year - 1900; + c.dow = dt.dt_wday + 1; + + (*cd->tod_set)(cd->tod_cookie, &c); + return 0; +} + /* * Wait "n" microseconds. */ @@ -323,6 +386,13 @@ void cpu_initclocks() { struct cpu_info *ci = curcpu(); + struct tod_desc *cd = &sys_tod; + + if (todr_handle == NULL && cd->tod_get) { + rtc_todr.todr_gettime = rtc_gettime; + rtc_todr.todr_settime = rtc_settime; + todr_handle = &rtc_todr; + } profhz = hz; @@ -356,140 +426,6 @@ setstatclockrate(int newhz) { } -/* XXX switch to kern/clock_subr.c routines */ -/* - * This code is defunct after 2099. Will Unix still be here then?? - */ -static short dayyr[12] = { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 -}; - -#define SECMIN (60) /* seconds per minute */ -#define SECHOUR (60*SECMIN) /* seconds per hour */ - -#define YEARDAYS(year) (((((year) + 1900) % 4) == 0 && \ - ((((year) + 1900) % 100) != 0 || \ - (((year) + 1900) % 400) == 0)) ? 366 : 365) - -/* - * Initialize the time of day register, based on the time base which - * is, e.g. from a filesystem. - */ -void -inittodr(time_t base) -{ - struct timespec ts; - struct tod_time c; - struct tod_desc *cd = &sys_tod; - int days, yr; - - ts.tv_nsec = 0; - - if (base < 35 * SECYR) { - printf("WARNING: preposterous time in file system"); - /* read the system clock anyway */ - base = 40 * SECYR; /* 2010 */ - } - - /* - * Read RTC chip registers NOTE: Read routines are responsible - * for sanity checking clock. Dates after 19991231 should be - * returned as year >= 100. - */ - if (cd->tod_get) { - (*cd->tod_get)(cd->tod_cookie, base, &c); - } else { - printf("WARNING: No TOD clock, believing file system.\n"); - goto bad; - } - - days = 0; - for (yr = 70; yr < c.year; yr++) { - days += YEARDAYS(yr); - } - - days += dayyr[c.mon - 1] + c.day - 1; - if (YEARDAYS(c.year) == 366 && c.mon > 2) { - days++; - } - - /* now have days since Jan 1, 1970; the rest is easy... */ - ts.tv_sec = days * SECDAY + c.hour * 3600 + c.min * 60 + c.sec; - - /* - * See if we gained/lost time. - */ - if (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"); - } else { - tc_setclock(&ts); - cd->tod_valid = 1; - return; - } - -bad: - ts.tv_sec = base; - tc_setclock(&ts); - cd->tod_valid = 1; - printf("WARNING: CHECK AND RESET THE DATE!\n"); -} - -/* - * Reset the TOD clock. This is done when the system is halted or - * when the time is reset by the stime system call. - */ -void -resettodr() -{ - struct tod_time c; - struct tod_desc *cd = &sys_tod; - int t, t2; - - /* - * Don't reset TOD if time has not been set! - */ - if (!cd->tod_valid) - return; - - /* compute the day of week. 1 is Sunday*/ - t2 = time_second / SECDAY; - c.dow = (t2 + 5) % 7 + 1; /* 1/1/1970 was thursday */ - - /* compute the year */ - t = 0; - t2 = time_second / SECDAY; - c.year = 69; - while (t2 >= 0) { /* whittle off years */ - t = t2; - c.year++; - t2 -= YEARDAYS(c.year); - } - - /* t = month + day; separate */ - t2 = YEARDAYS(c.year); - for (c.mon = 1; c.mon < 12; c.mon++) { - if (t < dayyr[c.mon] + (t2 == 366 && c.mon > 1)) - break; - } - - c.day = t - dayyr[c.mon - 1] + 1; - if (t2 == 366 && c.mon > 2) { - c.day--; - } - - t = time_second % SECDAY; - c.hour = t / 3600; - t %= 3600; - c.min = t / 60; - c.sec = t % 60; - - if (cd->tod_set) - (*cd->tod_set)(cd->tod_cookie, &c); -} - /* * Decode instruction and figure out type. */ @@ -562,3 +498,90 @@ unmap_startup(void) while (word < endboot) *word++ = 0x00000034u; /* TEQ zero, zero */ } + + +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"); +} |