/* clock.c 4.1 83/02/10 */ #include "../h/param.h" #include "../h/time.h" #include "../h/kernel.h" #include "../vax/mtpr.h" #include "../vax/clock.h" /* * Machine-dependent clock routines. * * Startrtclock restarts the real-time clock, which provides * hardclock interrupts to kern_clock.c. * * Inittodr initializes the time of day hardware which provides * date functions. Its primary function is to use some file * system information in case the hardare clock lost state. * * Resettodr restores the time of day hardware after a time change. */ /* * Start the real-time clock. */ startrtclock() { mtpr(NICR, -1000000/hz); mtpr(ICCS, ICCS_RUN+ICCS_IE+ICCS_TRANS+ICCS_INT+ICCS_ERR); } /* * 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 provides the rest. */ inittodr(base) time_t base; { register u_int todr = mfpr(TODR); long deltat; int year = YRREF; if (base < 5*SECYR) { printf("WARNING: preposterous time in file system"); time.tv_sec = 6*SECYR + 186*SECDAY + SECDAY/2; resettodr(); goto check; } /* * TODRZERO is base used by VMS, which runs on local time. */ if (todr < TODRZERO) { printf("WARNING: todr too small"); time.tv_sec = base; /* * Believe the time in the file system for lack of * anything better, resetting the TODR. */ resettodr(); goto check; } /* * Sneak to within 6 month of the time in the filesystem, * by starting with the time of the year suggested by the TODR, * and advancing through succesive years. Adding the number of * seconds in the current year takes us to the end of the current year * and then around into the next year to the same position. */ time.tv_sec = (todr-TODRZERO)/100; while (time.tv_sec < base-SECYR/2) { if (LEAPYEAR(year)) time.tv_sec += SECDAY; year++; time.tv_sec += SECYR; } /* * 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", deltat / SECDAY); check: 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. */ resettodr() { int year = YRREF; u_int secyr; u_int yrtime = time.tv_sec; /* * Whittle the time down to an offset in the current year, * by subtracting off whole years as long as possible. */ for (;;) { secyr = SECYR; if (LEAPYEAR(year)) secyr += SECDAY; if (yrtime < secyr) break; yrtime -= secyr; year++; } mtpr(TODR, TODRZERO + yrtime*100); }