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