Annotation of sys/arch/mac68k/mac68k/clock.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: clock.c,v 1.24 2007/07/14 19:06:48 miod Exp $ */
2: /* $NetBSD: clock.c,v 1.39 1999/11/05 19:14:56 scottr Exp $ */
3:
4: /*
5: * Copyright (c) 1988 University of Utah.
6: * Copyright (c) 1982, 1990 The Regents of the University of California.
7: * All rights reserved.
8: *
9: * This code is derived from software contributed to Berkeley by
10: * the Systems Programming Group of the University of Utah Computer
11: * Science Department.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: */
37: /*-
38: * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
39: * Michael L. Finch, Bradley A. Grantham, and
40: * Lawrence A. Kesteloot
41: * All rights reserved.
42: *
43: * Redistribution and use in source and binary forms, with or without
44: * modification, are permitted provided that the following conditions
45: * are met:
46: * 1. Redistributions of source code must retain the above copyright
47: * notice, this list of conditions and the following disclaimer.
48: * 2. Redistributions in binary form must reproduce the above copyright
49: * notice, this list of conditions and the following disclaimer in the
50: * documentation and/or other materials provided with the distribution.
51: * 3. All advertising materials mentioning features or use of this software
52: * must display the following acknowledgement:
53: * This product includes software developed by the Alice Group.
54: * 4. The names of the Alice Group or any of its members may not be used
55: * to endorse or promote products derived from this software without
56: * specific prior written permission.
57: *
58: * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
59: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61: * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
62: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
67: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68: *
69: */
70: /*
71: *
72: * from: Utah $Hdr: clock.c 1.18 91/01/21$
73: *
74: * @(#)clock.c 7.6 (Berkeley) 5/7/91
75: */
76:
77: /*
78: * Mac II machine-dependent clock routines.
79: */
80:
81: #include <sys/param.h>
82: #include <sys/device.h>
83: #include <sys/limits.h>
84: #include <sys/kernel.h>
85: #include <sys/systm.h>
86:
87: #include <machine/autoconf.h>
88: #include <machine/psl.h>
89: #include <machine/cpu.h>
90:
91: #include <mac68k/mac68k/pram.h>
92: #include <machine/viareg.h>
93:
94: #include <dev/clock_subr.h>
95:
96: #ifdef DEBUG
97: int clock_debug = 0;
98: #endif
99:
100: int rtclock_intr(void *);
101:
102: u_int clk_interval;
103: u_int8_t clk_inth, clk_intl;
104:
105: #define DIFF19041970 2082844800
106:
107: /*
108: * The Macintosh timers decrement once every 1.2766 microseconds.
109: * MGFH2, p. 180
110: */
111: #define CLK_RATE 12766
112:
113: /*
114: * Start the real-time clock; i.e. set timer latches and boot timer.
115: *
116: * We use VIA1 timer 1.
117: */
118: void
119: startrtclock()
120: {
121: #ifndef HZ
122: /*
123: * By default, if HZ is not specified, use 60 Hz, unless we are
124: * using A/UX style interrupts. We then need to readjust values
125: * based on a 100Hz value in param.c.
126: */
127: if (mac68k_machine.aux_interrupts == 0) {
128: #define HZ_60 60
129: hz = HZ_60;
130: tick = 1000000 / HZ_60;
131: tickadj = 240000 / (60 * HZ_60);/* can adjust 240ms in 60s */
132: }
133: #endif
134:
135: /*
136: * Calculate clocks needed to hit hz ticks/sec.
137: *
138: * The VIA clock speed is 1.2766us, so the timer value needed is:
139: *
140: * 1 1,000,000us 1
141: * CLK_INTERVAL = -------- * ----------- * ------
142: e 1.2766us 1s hz
143: *
144: * While it may be tempting to simplify the following further,
145: * we can run into integer overflow problems.
146: * Also note: do *not* define HZ to be less than 12; overflow
147: * will occur, yielding invalid results.
148: */
149: clk_interval = ((100000000UL / hz) * 100) / 12766;
150: clk_inth = ((clk_interval >> 8) & 0xff);
151: clk_intl = (clk_interval & 0xff);
152:
153: /* be certain clock interrupts are off */
154: via_reg(VIA1, vIER) = V1IF_T1;
155:
156: /* set timer latch */
157: via_reg(VIA1, vACR) |= ACR_T1LATCH;
158:
159: /* set VIA timer 1 latch to ``hz'' Hz */
160: via_reg(VIA1, vT1L) = clk_intl;
161: via_reg(VIA1, vT1LH) = clk_inth;
162:
163: /* set VIA timer 1 counter started for ``hz'' Hz */
164: via_reg(VIA1, vT1C) = clk_intl;
165: via_reg(VIA1, vT1CH) = clk_inth;
166: }
167:
168: void
169: cpu_initclocks()
170: {
171: tickfix = 1000000 - (hz * tick);
172: if (tickfix != 0) {
173: int ftp;
174:
175: ftp = min(ffs(tickfix), ffs(hz));
176: tickfix >>= (ftp - 1);
177: tickfixinterval = hz >> (ftp - 1);
178: }
179:
180: /* clear then enable clock interrupt. */
181: via_reg(VIA1, vIFR) |= V1IF_T1;
182: via_reg(VIA1, vIER) = 0x80 | V1IF_T1;
183: }
184:
185: void
186: setstatclockrate(rateinhz)
187: int rateinhz;
188: {
189: }
190:
191: /*
192: * Returns number of usec since last clock tick/interrupt.
193: *
194: * Check high byte twice to prevent missing a roll-over.
195: * (race condition?)
196: */
197: u_long
198: clkread()
199: {
200: int high, high2, low;
201:
202: high = via_reg(VIA1, vT1CH);
203: low = via_reg(VIA1, vT1C);
204:
205: high2 = via_reg(VIA1, vT1CH);
206: if (high != high2)
207: high = high2;
208:
209: /* return count left in timer / 1.27 */
210: return ((clk_interval - (high << 8) - low) * 10000 / CLK_RATE);
211: }
212:
213: static u_long ugmt_2_pramt(u_long);
214: static u_long pramt_2_ugmt(u_long);
215:
216: /*
217: * Convert GMT to Mac PRAM time, using rtc_offset
218: * GMT bias adjustment is done elsewhere.
219: */
220: static u_long
221: ugmt_2_pramt(t)
222: u_long t;
223: {
224: /* don't know how to open a file properly. */
225: /* assume compiled timezone is correct. */
226:
227: return (t + DIFF19041970 - 60 * tz.tz_minuteswest);
228: }
229:
230: /*
231: * Convert a Mac PRAM time value to GMT, using rtc_offset
232: * GMT bias adjustment is done elsewhere.
233: */
234: static u_long
235: pramt_2_ugmt(t)
236: u_long t;
237: {
238: return (t - DIFF19041970 + 60 * tz.tz_minuteswest);
239: }
240:
241: /*
242: * Time from the booter.
243: */
244: u_long macos_boottime;
245:
246: /*
247: * Bias in minutes east from GMT (also from booter).
248: */
249: long macos_gmtbias;
250:
251: /*
252: * Flag for whether or not we can trust the PRAM. If we don't
253: * trust it, we don't write to it, and we take the MacOS value
254: * that is passed from the booter (which will only be a second
255: * or two off by now).
256: */
257: int mac68k_trust_pram = 1;
258:
259: /*
260: * Set global GMT time register, using a file system time base for comparison
261: * and sanity checking.
262: */
263: void
264: inittodr(base)
265: time_t base;
266: {
267: u_long timbuf;
268:
269: timbuf = pram_readtime();
270: if (timbuf == 0) {
271: /* We don't know how to access PRAM on this hardware. */
272: timbuf = macos_boottime;
273: mac68k_trust_pram = 0;
274: } else {
275: timbuf = pramt_2_ugmt(pram_readtime());
276: if ((timbuf - (macos_boottime + 60 * tz.tz_minuteswest)) >
277: 10 * 60) {
278: #ifdef DIAGNOSTIC
279: printf("PRAM time does not appear"
280: " to have been read correctly.\n");
281: printf("PRAM: 0x%lx, macos_boottime: 0x%lx.\n",
282: timbuf, macos_boottime + 60 * tz.tz_minuteswest);
283: #endif
284: timbuf = macos_boottime;
285: mac68k_trust_pram = 0;
286: }
287: #ifdef DEBUG
288: else
289: printf("PRAM: 0x%lx, macos_boottime: 0x%lx.\n",
290: timbuf, macos_boottime);
291: #endif
292: }
293:
294: /*
295: * GMT bias is passed in from Booter
296: * To get GMT, *subtract* GMTBIAS from *our* time
297: * (gmtbias is in minutes, mult by 60)
298: */
299: timbuf -= macos_gmtbias * 60;
300:
301: if (base < 5 * SECYR) {
302: printf("WARNING: file system time earlier than 1975\n");
303: printf(" -- CHECK AND RESET THE DATE!\n");
304: base = 36 * SECYR; /* Last update here in 2006... */
305: }
306: if (timbuf < base) {
307: printf(
308: "WARNING: Battery clock has earlier time than UNIX fs.\n");
309: timbuf = base;
310: }
311: time.tv_sec = timbuf;
312: time.tv_usec = 0;
313: }
314:
315: /*
316: * Set battery backed clock to a new time, presumably after someone has
317: * changed system time.
318: */
319: void
320: resettodr()
321: {
322: if (mac68k_trust_pram)
323: /*
324: * GMT bias is passed in from the Booter.
325: * To get *our* time, add GMTBIAS to GMT.
326: * (gmtbias is in minutes, multiply by 60).
327: */
328: pram_settime(ugmt_2_pramt(time.tv_sec + macos_gmtbias * 60));
329: }
330:
331: #define DELAY_CALIBRATE (0xffffff << 7) /* Large value for calibration */
332:
333: u_int delay_factor = DELAY_CALIBRATE;
334: volatile int delay_flag = 1;
335:
336: int _delay(u_int);
337: static int delay_timer1_irq(void *);
338:
339: static int
340: delay_timer1_irq(dummy)
341: void *dummy;
342: {
343: delay_flag = 0;
344: return (1);
345: }
346:
347: /*
348: * Calibrate delay_factor with VIA1 timer T1.
349: */
350: void
351: mac68k_calibrate_delay()
352: {
353: u_int sum, n;
354:
355: /* Disable VIA1 timer 1 interrupts and set up service routine */
356: via_reg(VIA1, vIER) = V1IF_T1;
357: via1_register_irq(VIA1_T1, delay_timer1_irq, NULL, NULL);
358:
359: /* Set the timer for one-shot mode, then clear and enable interrupts */
360: via_reg(VIA1, vACR) &= ~ACR_T1LATCH;
361: via_reg(VIA1, vIFR) = V1IF_T1; /* (this is needed for IIsi) */
362: via_reg(VIA1, vIER) = 0x80 | V1IF_T1;
363:
364: #ifdef DEBUG
365: if (clock_debug)
366: printf("mac68k_calibrate_delay(): entering timing loop\n");
367: #endif
368:
369: (void)_spl(IPLTOPSL(mac68k_machine.via1_ipl) - 1);
370:
371: for (sum = 0, n = 8; n > 0; n--) {
372: delay_flag = 1;
373: via_reg(VIA1, vT1C) = 0; /* 1024 clock ticks */
374: via_reg(VIA1, vT1CH) = 4; /* (approx 1.3 msec) */
375: sum += ((delay_factor >> 7) - _delay(1));
376: }
377:
378: (void)splhigh();
379:
380: /* Disable timer interrupts and reset service routine */
381: via_reg(VIA1, vIER) = V1IF_T1;
382: via1_register_irq(VIA1_T1, rtclock_intr, NULL, NULL);
383:
384: /*
385: * If this weren't integer math, the following would look
386: * a lot prettier. It should really be something like
387: * this:
388: * delay_factor = ((sum / 8) / (1024 * 1.2766)) * 128;
389: * That is, average the sum, divide by the number of usec,
390: * and multiply by a scale factor of 128.
391: *
392: * We can accomplish the same thing by simplifying and using
393: * shifts, being careful to avoid as much loss of precision
394: * as possible. (If the sum exceeds UINT_MAX/10000, we need
395: * to rearrange the calculation slightly to do this.)
396: */
397: if (sum > (UINT_MAX / 10000)) /* This is a _fast_ machine! */
398: delay_factor = (((sum >> 3) * 10000) / CLK_RATE) >> 3;
399: else
400: delay_factor = (((sum * 10000) >> 3) / CLK_RATE) >> 3;
401:
402: /* Reset the delay_flag for normal use */
403: delay_flag = 1;
404:
405: #ifdef DEBUG
406: if (clock_debug)
407: printf("mac68k_calibrate_delay(): delay_factor calibrated\n");
408: #endif
409: }
CVSweb