Add support for microvax 3000.
[unix-history] / usr / src / sys / vax / vax / clock.c
CommitLineData
802ae52e 1
da7c5cc6 2/*
3907f97a 3 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
da7c5cc6
KM
4 * All rights reserved. The Berkeley software License Agreement
5 * specifies the terms and conditions for redistribution.
6 *
802ae52e 7 * @(#)clock.c 7.4 (Berkeley) %G%
da7c5cc6 8 */
fdbdc7ae 9
1884f3f6
JB
10#include "param.h"
11#include "time.h"
12#include "kernel.h"
fdbdc7ae 13
1884f3f6
JB
14#include "mtpr.h"
15#include "clock.h"
90dc7048 16#include "cpu.h"
fdbdc7ae
SL
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 */
34startrtclock()
35{
9a0de372
MK
36
37 (*cpuops->cpu_clock->clkstartrt)();
fdbdc7ae
SL
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,
9a0de372 43 * and the time of year clock (if any) provides the rest.
fdbdc7ae
SL
44 */
45inittodr(base)
46 time_t base;
47{
9a0de372
MK
48 long deltat, badbase = 0;
49
fdbdc7ae 50 if (base < 5*SECYR) {
9a0de372
MK
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;
fdbdc7ae 55 }
9a0de372
MK
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 and also when the time is reset
97 * by the stime system call. Also called when the TODR goes past
98 * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
99 * to wrap the TODR around.
100 */
101resettodr()
102{
103
104 (*cpuops->cpu_clock->clkwrite)();
105}
106
107/*
108 * ``Standard'' VAX clock routines.
109 */
110#if VAX8600 || VAX8200 || VAX780 || VAX750 || VAX730
111vaxstd_clkstartrt()
112{
113
114 mtpr(NICR, -1000000/hz);
115 mtpr(ICCS, ICCS_RUN+ICCS_IE+ICCS_TRANS+ICCS_INT+ICCS_ERR);
116}
117#endif
118
802ae52e 119#if VAX8600 || VAX780 || VAX750 || VAX730 || VAX650
9a0de372
MK
120vaxstd_clkread(base)
121 time_t base;
122{
123 register u_int todr = mfpr(TODR);
124 int year;
125
fdbdc7ae
SL
126 /*
127 * TODRZERO is base used by VMS, which runs on local time.
128 */
129 if (todr < TODRZERO) {
130 printf("WARNING: todr too small");
9a0de372 131 return (CLKREAD_BAD);
fdbdc7ae
SL
132 }
133
134 /*
3907f97a 135 * Sneak to within 6 months of the time in the filesystem,
fdbdc7ae
SL
136 * by starting with the time of the year suggested by the TODR,
137 * and advancing through succesive years. Adding the number of
138 * seconds in the current year takes us to the end of the current year
139 * and then around into the next year to the same position.
140 */
9a0de372
MK
141 time.tv_sec = (todr - TODRZERO) / 100;
142 year = YRREF;
143 while (time.tv_sec < base - SECYR/2) {
fdbdc7ae
SL
144 if (LEAPYEAR(year))
145 time.tv_sec += SECDAY;
146 year++;
147 time.tv_sec += SECYR;
148 }
149
9a0de372 150 return (CLKREAD_OK);
fdbdc7ae
SL
151}
152
9a0de372 153vaxstd_clkwrite()
fdbdc7ae
SL
154{
155 int year = YRREF;
156 u_int secyr;
157 u_int yrtime = time.tv_sec;
158
159 /*
160 * Whittle the time down to an offset in the current year,
161 * by subtracting off whole years as long as possible.
162 */
163 for (;;) {
164 secyr = SECYR;
165 if (LEAPYEAR(year))
166 secyr += SECDAY;
167 if (yrtime < secyr)
168 break;
169 yrtime -= secyr;
170 year++;
171 }
172 mtpr(TODR, TODRZERO + yrtime*100);
173}
9a0de372
MK
174#endif
175
176#if VAX8200 || VAX630
177/*
178 * This code is defunct after 2099.
179 * Will Unix still be here then??
180 */
181short dayyr[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
182
183chiptotime(c)
184 register struct chiptime *c;
185{
186 register int days, yr;
187
188 /* simple sanity checks */
189 if (c->year < 70 || c->mon < 1 || c->mon > 12 ||
190 c->day < 1 || c->day > 31) {
191 printf("WARNING: preposterous clock chip time");
192 return (0);
193 }
194 days = 0;
195 for (yr = 70; yr < c->year; yr++)
196 days += LEAPYEAR(yr) ? 366 : 365;
197 days += dayyr[c->mon - 1] + c->day - 1;
198 if (LEAPYEAR(yr) && c->mon > 2)
199 days++;
200 /* now have days since Jan 1, 1970; the rest is easy... */
201 return (days * SECDAY + c->hour * 3600 + c->min * 60 + c->sec);
202}
203
204timetochip(c)
205 register struct chiptime *c;
206{
207 register int t, t2, t3;
208
209 /* compute the year */
210 t2 = time.tv_sec / SECDAY;
211 t = 69;
212 while (t2 >= 0) { /* whittle off years */
213 t3 = t2;
214 t++;
215 t2 -= LEAPYEAR(t) ? 366 : 365;
216 }
217 c->year = t;
218
219 /* t3 = month + day; separate */
220 t = LEAPYEAR(t);
221 for (t2 = 1; t2 < 12; t2++)
222 if (t3 < dayyr[t2] + (t && t2 > 1))
223 break;
224
225 /* t2 is month */
226 c->mon = t2;
227 c->day = t3 - dayyr[t2 - 1] + 1;
228 if (t && t2 > 2)
229 c->day--;
230
231 /* the rest is easy */
232 t = time.tv_sec % SECDAY;
233 c->hour = t / 3600;
234 t %= 3600;
235 c->min = t / 60;
236 c->sec = t % 60;
237}
238#endif