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