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