xref: /netbsd-src/sys/arch/vax/vax/clock.c (revision 07bae7edddbb1ce4c926b2e8db425804589074c9)
1 /*	$NetBSD: clock.c,v 1.7 1995/04/12 15:34:44 ragge Exp $	*/
2 /*
3  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *     This product includes software developed at Ludd, University of Lule}.
17  * 4. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32  /* All bugs are subject to removal without further notice */
33 
34 
35 
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 
39 #include "machine/mtpr.h"
40 #include "machine/sid.h"
41 
42 #define SEC_PER_DAY (60*60*24)
43 
44 extern int todrstopped;
45 
46 static unsigned long year;     /*  start of current year in seconds */
47 static unsigned long year_len; /* length of current year in 100th of seconds */
48 
49 /*
50  * microtime() should return number of usecs in struct timeval.
51  * We may get wrap-arounds, but that will be fixed with lasttime
52  * check. This may fault within 10 msecs.
53  */
54 void
55 microtime(tvp)
56 	register struct timeval *tvp;
57 {
58 	int s,i;
59 	u_int int_time,tmp_year;
60 	static struct timeval lasttime;
61 
62 	s = splhigh();
63 	int_time=mfpr(PR_TODR);
64 	bcopy(&time,tvp,sizeof(struct timeval));
65 	i=mfpr(PR_ICR)+tick; /* Get current interval count */
66 	tvp->tv_usec += i;
67 	while (tvp->tv_usec > 1000000) {
68 		tvp->tv_sec++;
69 		tvp->tv_usec -= 1000000;
70 	}
71 	if (tvp->tv_sec == lasttime.tv_sec &&
72 	    tvp->tv_usec <= lasttime.tv_usec &&
73 	    (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
74 		tvp->tv_sec++;
75 		tvp->tv_usec -= 1000000;
76 	}
77 	bcopy(tvp,&lasttime,sizeof(struct timeval));
78 	if(int_time>year_len) {
79 		mtpr(mfpr(PR_TODR)-year_len, PR_TODR);
80 		year+=year_len/100;
81 		tmp_year=year/SEC_PER_DAY/365+2;
82 		year_len=100*SEC_PER_DAY*((tmp_year%4&&tmp_year!=32)?365:366);
83 	}
84 	splx(s);
85 }
86 
87 /*
88  * Sets year to the year in fs_time and then calculates the number of
89  * 100th of seconds in the current year and saves that info in year_len.
90  * fs_time contains the time set in the superblock in the root filesystem.
91  * If the clock is started, it then checks if the time is valid
92  * compared with the time in fs_time. If the clock is stopped, an
93  * alert is printed and the time is temporary set to the time in fs_time.
94  */
95 
96 void
97 inittodr(fs_time)
98 	time_t fs_time;
99 {
100 
101 	unsigned long tmp_year,sluttid,year_ticks;
102 	int clock_stopped;
103 
104 	sluttid=fs_time;
105 	year=(fs_time/SEC_PER_DAY/365)*365*SEC_PER_DAY;
106 	tmp_year=year/SEC_PER_DAY/365+2;
107 	year_len=100*SEC_PER_DAY*((tmp_year%4&&tmp_year!=32)?365:366);
108 
109 	switch (cpunumber) {
110 #if VAX750
111 	case VAX_750:
112 		year_ticks = mfpr(PR_TODR);
113 		clock_stopped = todrstopped;
114 		break;
115 #endif
116 #if VAX630 || VAX410
117 	case VAX_78032:
118 		year_ticks = uvaxII_gettodr(&clock_stopped);
119 		break;
120 #endif
121 	default:
122 		year_ticks = 0;
123 		clock_stopped = 1;
124 	};
125 
126 	if(clock_stopped){
127 		printf(
128 	"Internal clock not started. Using time from file system.\n");
129 		switch (cpunumber) {
130 #if VAX750
131 		case VAX_750:
132 			/*+1 so the clock won't be stopped */
133 			mtpr((fs_time-year)*100+1, PR_TODR);
134 			break;
135 #endif
136 #if VAX630 || VAX410
137 		case VAX_78032:
138 			uvaxII_settodr((fs_time-year)*100+1);
139 			break;
140 #endif
141 		};
142 		todrstopped=0;
143 	} else if(year_ticks/100>fs_time-year+SEC_PER_DAY*3) {
144 		printf(
145 	"WARNING: Clock has gained %d days - CHECK AND RESET THE DATE.\n",
146 		    (year_ticks/100-(fs_time-year))/SEC_PER_DAY);
147 		sluttid=year+(year_ticks/100);
148 	} else if(year_ticks/100<fs_time-year) {
149 		printf(
150 		"WARNING: Clock has lost time - CHECK AND RESET THE DATE.\n");
151 	} else sluttid=year+(year_ticks/100);
152 	time.tv_sec=sluttid;
153 }
154 
155 /*
156  * Resettodr restores the time of day hardware after a time change.
157  */
158 
159 void
160 resettodr()
161 {
162 
163 	unsigned long tmp_year;
164 
165 	year=(time.tv_sec/SEC_PER_DAY/365)*365*SEC_PER_DAY;
166 	tmp_year=year/SEC_PER_DAY/365+2;
167 	year_len=100*SEC_PER_DAY*((tmp_year%4&&tmp_year!=32)?365:366);
168 	switch (cpunumber) {
169 #if VAX750
170 	case VAX_750:
171 		mtpr((time.tv_sec-year)*100+1, PR_TODR);
172 		break;
173 #endif
174 #if VAX630 || VAX410
175 	case VAX_78032:
176 		uvaxII_settodr((time.tv_sec-year)*100+1);
177 		break;
178 #endif
179 	};
180 	todrstopped=0;
181 }
182 
183 /*
184  * Unfortunately the 78032 cpu chip (MicroVAXII cpu) does not have a functional
185  * todr register, so this function is necessary.
186  * (the x and y variables are used to confuse the optimizer enough to ensure
187  *  that the code actually loops:-)
188  */
189 int
190 todr()
191 {
192       int delaycnt, x = 4, y = 4;
193       static int todr_val;
194 
195       if (cpunumber != VAX_78032)
196 	      return (mfpr(PR_TODR));
197 
198       /*
199        * Loop for approximately 10msec and then return todr_val + 1.
200        */
201       delaycnt = 5000;
202       while (delaycnt > 0)
203 	      delaycnt = delaycnt - x + 3 + y - 4;
204       return (++todr_val);
205 }
206