1 /* 2 * Copyright (c) 1982 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)clock.c 6.3 (Berkeley) 06/08/85 7 */ 8 9 #include "param.h" 10 #include "time.h" 11 #include "kernel.h" 12 13 #include "mtpr.h" 14 #include "clock.h" 15 16 /* 17 * Machine-dependent clock routines. 18 * 19 * Startrtclock restarts the real-time clock, which provides 20 * hardclock interrupts to kern_clock.c. 21 * 22 * Inittodr initializes the time of day hardware which provides 23 * date functions. Its primary function is to use some file 24 * system information in case the hardare clock lost state. 25 * 26 * Resettodr restores the time of day hardware after a time change. 27 */ 28 29 /* 30 * Start the real-time clock. 31 */ 32 startrtclock() 33 { 34 35 mtpr(NICR, -1000000/hz); 36 mtpr(ICCS, ICCS_RUN+ICCS_IE+ICCS_TRANS+ICCS_INT+ICCS_ERR); 37 } 38 39 /* 40 * Initialze the time of day register, based on the time base which is, e.g. 41 * from a filesystem. Base provides the time to within six months, 42 * and the time of year clock provides the rest. 43 */ 44 inittodr(base) 45 time_t base; 46 { 47 register u_int todr = mfpr(TODR); 48 long deltat; 49 int year = YRREF; 50 51 if (base < 5*SECYR) { 52 printf("WARNING: preposterous time in file system"); 53 time.tv_sec = 6*SECYR + 186*SECDAY + SECDAY/2; 54 resettodr(); 55 goto check; 56 } 57 /* 58 * TODRZERO is base used by VMS, which runs on local time. 59 */ 60 if (todr < TODRZERO) { 61 printf("WARNING: todr too small"); 62 time.tv_sec = base; 63 /* 64 * Believe the time in the file system for lack of 65 * anything better, resetting the TODR. 66 */ 67 resettodr(); 68 goto check; 69 } 70 71 /* 72 * Sneak to within 6 month of the time in the filesystem, 73 * by starting with the time of the year suggested by the TODR, 74 * and advancing through succesive years. Adding the number of 75 * seconds in the current year takes us to the end of the current year 76 * and then around into the next year to the same position. 77 */ 78 time.tv_sec = (todr-TODRZERO)/100; 79 while (time.tv_sec < base-SECYR/2) { 80 if (LEAPYEAR(year)) 81 time.tv_sec += SECDAY; 82 year++; 83 time.tv_sec += SECYR; 84 } 85 86 /* 87 * See if we gained/lost two or more days; 88 * if so, assume something is amiss. 89 */ 90 deltat = time.tv_sec - base; 91 if (deltat < 0) 92 deltat = -deltat; 93 if (deltat < 2*SECDAY) 94 return; 95 printf("WARNING: clock %s %d days", 96 time.tv_sec < base ? "lost" : "gained", deltat / SECDAY); 97 check: 98 printf(" -- CHECK AND RESET THE DATE!\n"); 99 } 100 101 /* 102 * Reset the TODR based on the time value; used when the TODR 103 * has a preposterous value and also when the time is reset 104 * by the stime system call. Also called when the TODR goes past 105 * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) 106 * to wrap the TODR around. 107 */ 108 resettodr() 109 { 110 int year = YRREF; 111 u_int secyr; 112 u_int yrtime = time.tv_sec; 113 114 /* 115 * Whittle the time down to an offset in the current year, 116 * by subtracting off whole years as long as possible. 117 */ 118 for (;;) { 119 secyr = SECYR; 120 if (LEAPYEAR(year)) 121 secyr += SECDAY; 122 if (yrtime < secyr) 123 break; 124 yrtime -= secyr; 125 year++; 126 } 127 mtpr(TODR, TODRZERO + yrtime*100); 128 } 129