|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988 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.3 (Berkeley) 7/9/88 ! 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: ! 36: (*cpuops->cpu_clock->clkstartrt)(); ! 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 (if any) provides the rest. ! 43: */ ! 44: inittodr(base) ! 45: time_t base; ! 46: { ! 47: long deltat, badbase = 0; ! 48: ! 49: if (base < 5*SECYR) { ! 50: printf("WARNING: preposterous time in file system\n"); ! 51: /* read the system clock anyway */ ! 52: base = 6*SECYR + 186*SECDAY + SECDAY/2; ! 53: badbase = 1; ! 54: } ! 55: switch ((*cpuops->cpu_clock->clkread)(base)) { ! 56: ! 57: case CLKREAD_BAD: ! 58: /* ! 59: * Believe the time in the file system for lack of ! 60: * anything better, resetting the TODR. ! 61: */ ! 62: time.tv_sec = base; ! 63: if (!badbase) ! 64: resettodr(); ! 65: break; ! 66: ! 67: case CLKREAD_WARN: ! 68: break; ! 69: ! 70: case CLKREAD_OK: ! 71: if (badbase) ! 72: break; ! 73: /* ! 74: * See if we gained/lost two or more days; ! 75: * if so, assume something is amiss. ! 76: */ ! 77: deltat = time.tv_sec - base; ! 78: if (deltat < 0) ! 79: deltat = -deltat; ! 80: if (deltat < 2 * SECDAY) ! 81: return; ! 82: printf("WARNING: clock %s %d days", ! 83: time.tv_sec < base ? "lost" : "gained", deltat / SECDAY); ! 84: break; ! 85: ! 86: default: ! 87: panic("inittodr"); ! 88: /* NOTREACHED */ ! 89: } ! 90: printf(" -- CHECK AND RESET THE DATE!\n"); ! 91: } ! 92: ! 93: /* ! 94: * Reset the TODR based on the time value; used when the TODR ! 95: * has a preposterous value and also when the time is reset ! 96: * by the stime system call. Also called when the TODR goes past ! 97: * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) ! 98: * to wrap the TODR around. ! 99: */ ! 100: resettodr() ! 101: { ! 102: ! 103: (*cpuops->cpu_clock->clkwrite)(); ! 104: } ! 105: ! 106: /* ! 107: * ``Standard'' VAX clock routines. ! 108: */ ! 109: #if VAX8600 || VAX8200 || VAX780 || VAX750 || VAX730 ! 110: vaxstd_clkstartrt() ! 111: { ! 112: ! 113: mtpr(NICR, -1000000/hz); ! 114: mtpr(ICCS, ICCS_RUN+ICCS_IE+ICCS_TRANS+ICCS_INT+ICCS_ERR); ! 115: } ! 116: #endif ! 117: ! 118: #if VAX8600 || VAX780 || VAX750 || VAX730 ! 119: vaxstd_clkread(base) ! 120: time_t base; ! 121: { ! 122: register u_int todr = mfpr(TODR); ! 123: int year; ! 124: ! 125: /* ! 126: * TODRZERO is base used by VMS, which runs on local time. ! 127: */ ! 128: if (todr < TODRZERO) { ! 129: printf("WARNING: todr too small"); ! 130: return (CLKREAD_BAD); ! 131: } ! 132: ! 133: /* ! 134: * Sneak to within 6 months of the time in the filesystem, ! 135: * by starting with the time of the year suggested by the TODR, ! 136: * and advancing through succesive years. Adding the number of ! 137: * seconds in the current year takes us to the end of the current year ! 138: * and then around into the next year to the same position. ! 139: */ ! 140: time.tv_sec = (todr - TODRZERO) / 100; ! 141: year = YRREF; ! 142: while (time.tv_sec < base - SECYR/2) { ! 143: if (LEAPYEAR(year)) ! 144: time.tv_sec += SECDAY; ! 145: year++; ! 146: time.tv_sec += SECYR; ! 147: } ! 148: ! 149: return (CLKREAD_OK); ! 150: } ! 151: ! 152: vaxstd_clkwrite() ! 153: { ! 154: int year = YRREF; ! 155: u_int secyr; ! 156: u_int yrtime = time.tv_sec; ! 157: ! 158: /* ! 159: * Whittle the time down to an offset in the current year, ! 160: * by subtracting off whole years as long as possible. ! 161: */ ! 162: for (;;) { ! 163: secyr = SECYR; ! 164: if (LEAPYEAR(year)) ! 165: secyr += SECDAY; ! 166: if (yrtime < secyr) ! 167: break; ! 168: yrtime -= secyr; ! 169: year++; ! 170: } ! 171: mtpr(TODR, TODRZERO + yrtime*100); ! 172: } ! 173: #endif ! 174: ! 175: #if VAX8200 || VAX630 ! 176: /* ! 177: * This code is defunct after 2099. ! 178: * Will Unix still be here then?? ! 179: */ ! 180: short dayyr[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; ! 181: ! 182: chiptotime(c) ! 183: register struct chiptime *c; ! 184: { ! 185: register int days, yr; ! 186: ! 187: /* simple sanity checks */ ! 188: if (c->year < 70 || c->mon < 1 || c->mon > 12 || ! 189: c->day < 1 || c->day > 31) { ! 190: printf("WARNING: preposterous clock chip time"); ! 191: return (0); ! 192: } ! 193: days = 0; ! 194: for (yr = 70; yr < c->year; yr++) ! 195: days += LEAPYEAR(yr) ? 366 : 365; ! 196: days += dayyr[c->mon - 1] + c->day - 1; ! 197: if (LEAPYEAR(yr) && c->mon > 2) ! 198: days++; ! 199: /* now have days since Jan 1, 1970; the rest is easy... */ ! 200: return (days * SECDAY + c->hour * 3600 + c->min * 60 + c->sec); ! 201: } ! 202: ! 203: timetochip(c) ! 204: register struct chiptime *c; ! 205: { ! 206: register int t, t2, t3; ! 207: ! 208: /* compute the year */ ! 209: t2 = time.tv_sec / SECDAY; ! 210: t = 69; ! 211: while (t2 >= 0) { /* whittle off years */ ! 212: t3 = t2; ! 213: t++; ! 214: t2 -= LEAPYEAR(t) ? 366 : 365; ! 215: } ! 216: c->year = t; ! 217: ! 218: /* t3 = month + day; separate */ ! 219: t = LEAPYEAR(t); ! 220: for (t2 = 1; t2 < 12; t2++) ! 221: if (t3 < dayyr[t2] + (t && t2 > 1)) ! 222: break; ! 223: ! 224: /* t2 is month */ ! 225: c->mon = t2; ! 226: c->day = t3 - dayyr[t2 - 1] + 1; ! 227: if (t && t2 > 2) ! 228: c->day--; ! 229: ! 230: /* the rest is easy */ ! 231: t = time.tv_sec % SECDAY; ! 232: c->hour = t / 3600; ! 233: t %= 3600; ! 234: c->min = t / 60; ! 235: c->sec = t % 60; ! 236: } ! 237: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.