|
|
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.