Commit | Line | Data |
---|---|---|
af5295ff KM |
1 | /* |
2 | * Copyright (c) 1988 University of Utah. | |
ad787160 C |
3 | * Copyright (c) 1992, 1993 |
4 | * The Regents of the University of California. All rights reserved. | |
af5295ff KM |
5 | * |
6 | * This code is derived from software contributed to Berkeley by | |
7 | * the Systems Programming Group of the University of Utah Computer | |
8 | * Science Department, Ralph Campbell, and Kazumasa Utashiro of | |
9 | * Software Research Associates, Inc. | |
10 | * | |
ad787160 C |
11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions and the following disclaimer. | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in the | |
18 | * documentation and/or other materials provided with the distribution. | |
19 | * 3. All advertising materials mentioning features or use of this software | |
20 | * must display the following acknowledgement: | |
21 | * This product includes software developed by the University of | |
22 | * California, Berkeley and its contributors. | |
23 | * 4. Neither the name of the University nor the names of its contributors | |
24 | * may be used to endorse or promote products derived from this software | |
25 | * without specific prior written permission. | |
26 | * | |
27 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
29 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
30 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
33 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
36 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
37 | * SUCH DAMAGE. | |
af5295ff KM |
38 | * |
39 | * from: Utah $Hdr: clock.c 1.18 91/01/21$ | |
40 | * | |
ad787160 | 41 | * @(#)clock.c 8.1 (Berkeley) 6/11/93 |
af5295ff KM |
42 | */ |
43 | ||
f5e2c85d | 44 | #include <machine/adrsmap.h> |
af5295ff | 45 | |
f5e2c85d KU |
46 | #include <sys/param.h> |
47 | #include <sys/kernel.h> | |
af5295ff | 48 | |
f5e2c85d | 49 | #include <news3400/news3400/clockreg.h> |
af5295ff KM |
50 | |
51 | /* | |
52 | * Machine-dependent clock routines. | |
53 | * | |
54 | * Startrtclock restarts the real-time clock, which provides | |
55 | * hardclock interrupts to kern_clock.c. | |
56 | * | |
57 | * Inittodr initializes the time of day hardware which provides | |
58 | * date functions. Its primary function is to use some file | |
59 | * system information in case the hardare clock lost state. | |
60 | * | |
61 | * Resettodr restores the time of day hardware after a time change. | |
62 | */ | |
63 | ||
6d429c8e KB |
64 | /* |
65 | * We assume newhz is either stathz or profhz, and that neither will | |
66 | * change after being set up above. Could recalculate intervals here | |
67 | * but that would be a drag. | |
68 | */ | |
69 | void | |
70 | setstatclockrate(newhz) | |
71 | int newhz; | |
72 | { | |
73 | ||
74 | /* KU:XXX do something! */ | |
75 | } | |
76 | ||
679d1338 KU |
77 | /* |
78 | * Set up the real-time and statistics clocks. Leave stathz 0 only if | |
79 | * no alternative timer is available. | |
679d1338 KU |
80 | */ |
81 | cpu_initclocks() | |
82 | { | |
83 | ||
92daa486 KU |
84 | /* |
85 | * Start the real-time clock. | |
86 | */ | |
87 | *(char *)ITIMER = IOCLOCK / 6144 / 100 - 1; | |
88 | ||
89 | /* | |
90 | * Enable the real-time clock. | |
91 | */ | |
92 | *(char *)INTEN0 |= (char)INTEN0_TIMINT; | |
679d1338 KU |
93 | } |
94 | ||
af5295ff KM |
95 | /* |
96 | * This code is defunct after 2099. | |
97 | * Will Unix still be here then?? | |
98 | */ | |
99 | static short dayyr[12] = { | |
100 | 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 | |
101 | }; | |
102 | ||
f8bea1d3 | 103 | #define bcd_to_int(BCD) (i = BCD, (((i) >> 4) & 0xf) * 10 + ((i) & 0xf)) |
af5295ff KM |
104 | #define int_to_bcd(INT) (i = INT, ((((i) / 10) % 10) << 4) + (i) % 10) |
105 | ||
106 | /* | |
107 | * Initialze the time of day register, based on the time base which is, e.g. | |
108 | * from a filesystem. Base provides the time to within six months, | |
109 | * and the time of year clock (if any) provides the rest. | |
110 | */ | |
111 | inittodr(base) | |
112 | time_t base; | |
113 | { | |
114 | register volatile u_char *rtc_port = (u_char *)RTC_PORT; | |
115 | register volatile u_char *rtc_data = (u_char *)DATA_PORT; | |
116 | register int days, yr; | |
117 | int sec, min, hour, week, day, mon, year; | |
118 | long deltat, badbase = 0; | |
f8bea1d3 | 119 | register u_int i; |
af5295ff KM |
120 | |
121 | if (base < 5*SECYR) { | |
122 | printf("WARNING: preposterous time in file system\n"); | |
123 | /* read the system clock anyway */ | |
124 | base = 6*SECYR + 186*SECDAY + SECDAY/2; | |
125 | badbase = 1; | |
126 | } | |
127 | ||
128 | *rtc_port = READ_CLOCK; | |
129 | sec = bcd_to_int(*rtc_data++); | |
130 | min = bcd_to_int(*rtc_data++); | |
131 | hour = bcd_to_int(*rtc_data++); | |
132 | week = bcd_to_int(*rtc_data++); | |
133 | day = bcd_to_int(*rtc_data++); | |
134 | mon = bcd_to_int(*rtc_data++); | |
135 | year = bcd_to_int(*rtc_data++); | |
136 | *rtc_port = 0; | |
137 | ||
138 | /* simple sanity checks */ | |
139 | if (year < 70 || mon < 1 || mon > 12 || day < 1 || day > 31 || | |
140 | hour > 23 || min > 59 || sec > 59) { | |
f8bea1d3 | 141 | printf("WARNING: preposterous clock chip time\n"); |
af5295ff KM |
142 | /* |
143 | * Believe the time in the file system for lack of | |
144 | * anything better, resetting the TODR. | |
145 | */ | |
146 | time.tv_sec = base; | |
147 | if (!badbase) | |
148 | resettodr(); | |
149 | return (0); | |
150 | } | |
151 | days = 0; | |
152 | for (yr = 70; yr < year; yr++) | |
153 | days += LEAPYEAR(yr) ? 366 : 365; | |
154 | days += dayyr[mon - 1] + day - 1; | |
155 | if (LEAPYEAR(yr) && mon > 2) | |
156 | days++; | |
157 | /* now have days since Jan 1, 1970; the rest is easy... */ | |
158 | time.tv_sec = days * SECDAY + hour * 3600 + min * 60 + sec; | |
159 | ||
160 | if (!badbase) { | |
161 | /* | |
162 | * See if we gained/lost two or more days; | |
163 | * if so, assume something is amiss. | |
164 | */ | |
165 | deltat = time.tv_sec - base; | |
166 | if (deltat < 0) | |
167 | deltat = -deltat; | |
168 | if (deltat < 2 * SECDAY) | |
169 | return; | |
170 | printf("WARNING: clock %s %d days", | |
171 | time.tv_sec < base ? "lost" : "gained", deltat / SECDAY); | |
172 | } | |
173 | printf(" -- CHECK AND RESET THE DATE!\n"); | |
174 | } | |
175 | ||
176 | /* | |
177 | * Reset the TODR based on the time value; used when the TODR | |
178 | * has a preposterous value and also when the time is reset | |
179 | * by the stime system call. Also called when the TODR goes past | |
180 | * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) | |
181 | * to wrap the TODR around. | |
182 | */ | |
183 | resettodr() | |
184 | { | |
185 | register volatile u_char *rtc_port = (u_char *)RTC_PORT; | |
186 | register volatile u_char *rtc_data = (u_char *)DATA_PORT; | |
187 | int sec, min, hour, week, day, mon, year; | |
188 | register int t, t2, t3; | |
189 | register int i; | |
190 | ||
191 | /* compute the year */ | |
192 | t2 = time.tv_sec / SECDAY; | |
193 | t = 69; | |
194 | while (t2 >= 0) { /* whittle off years */ | |
195 | t3 = t2; | |
196 | t++; | |
197 | t2 -= LEAPYEAR(t) ? 366 : 365; | |
198 | } | |
199 | ||
200 | year = t; | |
201 | ||
202 | /* t3 = month + day; separate */ | |
203 | t = LEAPYEAR(t); | |
204 | for (t2 = 1; t2 < 12; t2++) | |
205 | if (t3 < dayyr[t2] + (t && t2 > 1)) | |
206 | break; | |
207 | ||
208 | /* t2 is month */ | |
209 | mon = t2; | |
210 | t3 = t3 - dayyr[t2 - 1] + 1; | |
211 | if (t && t2 > 2) | |
212 | t3--; | |
213 | day = t3; | |
214 | ||
215 | week = 0; | |
216 | ||
217 | /* the rest is easy */ | |
218 | t = time.tv_sec % SECDAY; | |
219 | hour = t / 3600; | |
220 | t %= 3600; | |
221 | min = t / 60; | |
222 | sec = t % 60; | |
223 | ||
224 | *rtc_port = SET_CLOCK; | |
225 | *rtc_data++ = int_to_bcd(sec); | |
226 | *rtc_data++ = int_to_bcd(min); | |
227 | *rtc_data++ = int_to_bcd(hour); | |
228 | *rtc_data++ = int_to_bcd(week); | |
229 | *rtc_data++ = int_to_bcd(day); | |
230 | *rtc_data++ = int_to_bcd(mon); | |
231 | *rtc_data = int_to_bcd(year); | |
232 | *rtc_port = 0; | |
233 | } |