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