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