xref: /original-bsd/sys/vax/vax/clock.c (revision ec7df300)
1 /*
2  * Copyright (c) 1982 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	6.3 (Berkeley) 06/08/85
7  */
8 
9 #include "param.h"
10 #include "time.h"
11 #include "kernel.h"
12 
13 #include "mtpr.h"
14 #include "clock.h"
15 
16 /*
17  * Machine-dependent clock routines.
18  *
19  * Startrtclock restarts the real-time clock, which provides
20  * hardclock interrupts to kern_clock.c.
21  *
22  * Inittodr initializes the time of day hardware which provides
23  * date functions.  Its primary function is to use some file
24  * system information in case the hardare clock lost state.
25  *
26  * Resettodr restores the time of day hardware after a time change.
27  */
28 
29 /*
30  * Start the real-time clock.
31  */
32 startrtclock()
33 {
34 
35 	mtpr(NICR, -1000000/hz);
36 	mtpr(ICCS, ICCS_RUN+ICCS_IE+ICCS_TRANS+ICCS_INT+ICCS_ERR);
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 provides the rest.
43  */
44 inittodr(base)
45 	time_t base;
46 {
47 	register u_int todr = mfpr(TODR);
48 	long deltat;
49 	int year = YRREF;
50 
51 	if (base < 5*SECYR) {
52 		printf("WARNING: preposterous time in file system");
53 		time.tv_sec = 6*SECYR + 186*SECDAY + SECDAY/2;
54 		resettodr();
55 		goto check;
56 	}
57 	/*
58 	 * TODRZERO is base used by VMS, which runs on local time.
59 	 */
60 	if (todr < TODRZERO) {
61 		printf("WARNING: todr too small");
62 		time.tv_sec = base;
63 		/*
64 		 * Believe the time in the file system for lack of
65 		 * anything better, resetting the TODR.
66 		 */
67 		resettodr();
68 		goto check;
69 	}
70 
71 	/*
72 	 * Sneak to within 6 month of the time in the filesystem,
73 	 * by starting with the time of the year suggested by the TODR,
74 	 * and advancing through succesive years.  Adding the number of
75 	 * seconds in the current year takes us to the end of the current year
76 	 * and then around into the next year to the same position.
77 	 */
78 	time.tv_sec = (todr-TODRZERO)/100;
79 	while (time.tv_sec < base-SECYR/2) {
80 		if (LEAPYEAR(year))
81 			time.tv_sec += SECDAY;
82 		year++;
83 		time.tv_sec += SECYR;
84 	}
85 
86 	/*
87 	 * See if we gained/lost two or more days;
88 	 * if so, assume something is amiss.
89 	 */
90 	deltat = time.tv_sec - base;
91 	if (deltat < 0)
92 		deltat = -deltat;
93 	if (deltat < 2*SECDAY)
94 		return;
95 	printf("WARNING: clock %s %d days",
96 	    time.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
97 check:
98 	printf(" -- CHECK AND RESET THE DATE!\n");
99 }
100 
101 /*
102  * Reset the TODR based on the time value; used when the TODR
103  * has a preposterous value and also when the time is reset
104  * by the stime system call.  Also called when the TODR goes past
105  * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
106  * to wrap the TODR around.
107  */
108 resettodr()
109 {
110 	int year = YRREF;
111 	u_int secyr;
112 	u_int yrtime = time.tv_sec;
113 
114 	/*
115 	 * Whittle the time down to an offset in the current year,
116 	 * by subtracting off whole years as long as possible.
117 	 */
118 	for (;;) {
119 		secyr = SECYR;
120 		if (LEAPYEAR(year))
121 			secyr += SECDAY;
122 		if (yrtime < secyr)
123 			break;
124 		yrtime -= secyr;
125 		year++;
126 	}
127 	mtpr(TODR, TODRZERO + yrtime*100);
128 }
129