Annotation of src/sys/arch/alpha/alpha/clock.c, Revision 1.3
1.3 ! cgd 1: /* $NetBSD: clock.c,v 1.2 1995/03/03 01:35:21 cgd Exp $ */
1.1 cgd 2:
3: /*
4: * Copyright (c) 1988 University of Utah.
5: * Copyright (c) 1992, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley by
9: * the Systems Programming Group of the University of Utah Computer
10: * Science Department and Ralph Campbell.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the University of
23: * California, Berkeley and its contributors.
24: * 4. Neither the name of the University nor the names of its contributors
25: * may be used to endorse or promote products derived from this software
26: * without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38: * SUCH DAMAGE.
39: *
40: * from: Utah Hdr: clock.c 1.18 91/01/21
41: *
42: * @(#)clock.c 8.1 (Berkeley) 6/10/93
43: */
44:
45: #include <sys/param.h>
46: #include <sys/kernel.h>
47: #include <sys/systm.h>
48: #include <sys/device.h>
49:
50: #include <machine/autoconf.h>
51: #include <machine/rpb.h>
52:
1.3 ! cgd 53: #include <alpha/alpha/clockvar.h>
! 54: #include <alpha/tc/asic.h> /* XXX */
! 55: #include <dev/isa/isavar.h> /* XXX */
1.1 cgd 56:
57: /* Definition of the driver for autoconfig. */
58: static int clockmatch __P((struct device *, void *, void *));
59: static void clockattach __P((struct device *, struct device *, void *));
60: struct cfdriver clockcd =
1.3 ! cgd 61: { NULL, "clock", clockmatch, clockattach, DV_DULL,
! 62: sizeof(struct clock_softc) };
1.1 cgd 63:
1.3 ! cgd 64: #if defined(DEC_3000_500) || defined(DEC_3000_300) || \
! 65: defined(DEC_2000_300) || defined(DEC_2100_A50)
! 66: void mcclock_attach __P((struct device *parent,
! 67: struct device *self, void *aux));
! 68: #endif
! 69:
! 70: #define SECMIN ((unsigned)60) /* seconds per minute */
! 71: #define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */
! 72: #define SECDAY ((unsigned)(24*SECHOUR)) /* seconds per day */
! 73: #define SECYR ((unsigned)(365*SECDAY)) /* seconds per common year */
1.1 cgd 74:
1.3 ! cgd 75: #define LEAPYEAR(year) (((year) % 4) == 0)
1.1 cgd 76:
77: static int
78: clockmatch(parent, cfdata, aux)
79: struct device *parent;
80: void *cfdata;
81: void *aux;
82: {
83: struct cfdata *cf = cfdata;
84: struct confargs *ca = aux;
85:
86: /* See how many clocks this system has */
87: switch (hwrpb->rpb_type) {
1.3 ! cgd 88: #if defined(DEC_3000_500) || defined(DEC_3000_300)
! 89:
! 90: #if defined(DEC_3000_500)
1.1 cgd 91: case ST_DEC_3000_500:
1.3 ! cgd 92: #endif
! 93: #if defined(DEC_3000_300)
1.1 cgd 94: case ST_DEC_3000_300:
1.3 ! cgd 95: #endif
! 96: /* make sure that we're looking for this type of device. */
! 97: if (!BUS_MATCHNAME(ca, "dallas_rtc"))
! 98: return (0);
! 99:
! 100: if (cf->cf_unit >= 1)
! 101: return (0);
! 102:
! 103: break;
! 104: #endif
! 105:
! 106: #if defined(DEC_2100_A50)
! 107: case ST_DEC_2100_A50:
! 108: /* Just say yes. XXX */
! 109:
! 110: if (cf->cf_unit >= 1)
! 111: return 0;
! 112:
! 113: /* XXX XXX XXX */
! 114: {
! 115: struct isa_attach_args *ia = aux;
! 116:
! 117: if (ia->ia_iobase != 0x70 && /* XXX */
! 118: ia->ia_iobase != -1) /* XXX */
! 119: return (0);
! 120:
! 121: ia->ia_iobase = 0x70; /* XXX */
! 122: ia->ia_iosize = 2; /* XXX */
! 123: ia->ia_msize = 0;
! 124: }
! 125:
1.1 cgd 126: break;
1.3 ! cgd 127: #endif
! 128:
! 129: #if defined(DEC_2000_300)
! 130: case ST_DEC_2000_300:
! 131: panic("clockmatch on jensen");
! 132: #endif
! 133:
1.1 cgd 134: default:
1.3 ! cgd 135: panic("unknown CPU");
1.1 cgd 136: }
137:
138: return (1);
139: }
140:
141: static void
142: clockattach(parent, self, aux)
143: struct device *parent;
144: struct device *self;
145: void *aux;
146: {
147:
1.3 ! cgd 148: switch (hwrpb->rpb_type) {
! 149: #if defined(DEC_3000_500) || defined(DEC_3000_300) || \
! 150: defined(DEC_2000_300) || defined(DEC_2100_A50)
! 151: #if defined(DEC_3000_500)
! 152: case ST_DEC_3000_500:
! 153: #endif
! 154: #if defined(DEC_2000_300)
! 155: case ST_DEC_2000_300:
! 156: #endif
! 157: #if defined(DEC_3000_300)
! 158: case ST_DEC_3000_300:
! 159: #endif
! 160: #if defined(DEC_2100_A50)
! 161: case ST_DEC_2100_A50:
! 162: #endif
! 163: mcclock_attach(parent, self, aux);
! 164: break;
! 165: #endif /* defined(at least one of lots of system types) */
! 166:
! 167: default:
! 168: panic("clockattach: it didn't get here. really.");
! 169: }
1.1 cgd 170:
171:
1.3 ! cgd 172: /*
! 173: * establish the clock interrupt; it's a special case
! 174: */
! 175: set_clockintr(hardclock);
1.1 cgd 176:
1.3 ! cgd 177: printf("\n");
1.1 cgd 178: }
179:
180: /*
181: * Machine-dependent clock routines.
182: *
183: * Startrtclock restarts the real-time clock, which provides
184: * hardclock interrupts to kern_clock.c.
185: *
186: * Inittodr initializes the time of day hardware which provides
187: * date functions. Its primary function is to use some file
188: * system information in case the hardare clock lost state.
189: *
190: * Resettodr restores the time of day hardware after a time change.
191: */
192:
193: /*
194: * Start the real-time and statistics clocks. Leave stathz 0 since there
195: * are no other timers available.
196: */
197: cpu_initclocks()
198: {
199: extern int tickadj;
1.3 ! cgd 200: struct clock_softc *csc = (struct clock_softc *)clockcd.cd_devs[0];
1.2 cgd 201: int fractick;
1.1 cgd 202:
1.2 cgd 203: hz = 1024; /* 1024 Hz clock */
204: tick = 1000000 / hz; /* number of microseconds between interrupts */
205: tickfix = 1000000 - (hz * tick);
206: if (tickfix) {
207: int ftp;
208:
209: ftp = min(ffs(tickfix), ffs(hz));
210: tickfix >>= (ftp - 1);
211: tickfixinterval = hz >> (ftp - 1);
212: }
1.1 cgd 213:
1.3 ! cgd 214: /*
! 215: * Get the clock started.
! 216: */
! 217: (*csc->sc_init)(csc);
1.1 cgd 218: }
219:
220: /*
221: * We assume newhz is either stathz or profhz, and that neither will
222: * change after being set up above. Could recalculate intervals here
223: * but that would be a drag.
224: */
225: void
226: setstatclockrate(newhz)
227: int newhz;
228: {
1.3 ! cgd 229:
1.1 cgd 230: /* nothing we can do */
231: }
232:
233: /*
234: * This code is defunct after 2099.
235: * Will Unix still be here then??
236: */
237: static short dayyr[12] = {
238: 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
239: };
240:
241: /*
242: * Initialze the time of day register, based on the time base which is, e.g.
243: * from a filesystem. Base provides the time to within six months,
244: * and the time of year clock (if any) provides the rest.
245: */
246: void
247: inittodr(base)
248: time_t base;
249: {
1.3 ! cgd 250: struct clock_softc *csc = (struct clock_softc *)clockcd.cd_devs[0];
1.1 cgd 251: register int days, yr;
1.3 ! cgd 252: struct clocktime ct;
1.1 cgd 253: long deltat;
254: int badbase, s;
255:
256: if (base < 5*SECYR) {
257: printf("WARNING: preposterous time in file system");
258: /* read the system clock anyway */
259: base = 6*SECYR + 186*SECDAY + SECDAY/2;
260: badbase = 1;
261: } else
262: badbase = 0;
263:
1.3 ! cgd 264: (*csc->sc_get)(csc, base, &ct);
! 265:
! 266: csc->sc_initted = 1;
1.1 cgd 267:
268: /* simple sanity checks */
1.3 ! cgd 269: if (ct.year < 70 || ct.mon < 1 || ct.mon > 12 || ct.day < 1 ||
! 270: ct.day > 31 || ct.hour > 23 || ct.min > 59 || ct.sec > 59) {
1.1 cgd 271: /*
272: * Believe the time in the file system for lack of
273: * anything better, resetting the TODR.
274: */
275: time.tv_sec = base;
276: if (!badbase) {
277: printf("WARNING: preposterous clock chip time\n");
278: resettodr();
279: }
280: goto bad;
281: }
282: days = 0;
1.3 ! cgd 283: for (yr = 70; yr < ct.year; yr++)
1.1 cgd 284: days += LEAPYEAR(yr) ? 366 : 365;
1.3 ! cgd 285: days += dayyr[ct.mon - 1] + ct.day - 1;
! 286: if (LEAPYEAR(yr) && ct.mon > 2)
1.1 cgd 287: days++;
288: /* now have days since Jan 1, 1970; the rest is easy... */
1.3 ! cgd 289: time.tv_sec =
! 290: days * SECDAY + ct.hour * SECHOUR + ct.min * SECMIN + ct.sec;
1.1 cgd 291:
292: if (!badbase) {
293: /*
294: * See if we gained/lost two or more days;
295: * if so, assume something is amiss.
296: */
297: deltat = time.tv_sec - base;
298: if (deltat < 0)
299: deltat = -deltat;
300: if (deltat < 2 * SECDAY)
301: return;
302: printf("WARNING: clock %s %d days",
303: time.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
304: }
305: bad:
306: printf(" -- CHECK AND RESET THE DATE!\n");
307: }
308:
309: /*
310: * Reset the TODR based on the time value; used when the TODR
311: * has a preposterous value and also when the time is reset
312: * by the stime system call. Also called when the TODR goes past
313: * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
314: * to wrap the TODR around.
315: */
316: resettodr()
317: {
1.3 ! cgd 318: struct clock_softc *csc = (struct clock_softc *)clockcd.cd_devs[0];
1.1 cgd 319: register int t, t2;
1.3 ! cgd 320: struct clocktime ct;
1.1 cgd 321: int s;
322:
1.3 ! cgd 323: if (!csc->sc_initted)
! 324: return;
! 325:
! 326: /* compute the day of week. */
! 327: t2 = time.tv_sec / SECDAY;
! 328: ct.dow = (t2 + 4) % 7; /* 1/1/1970 was thursday */
! 329:
1.1 cgd 330: /* compute the year */
1.3 ! cgd 331: ct.year = 69;
1.1 cgd 332: while (t2 >= 0) { /* whittle off years */
333: t = t2;
1.3 ! cgd 334: ct.year++;
! 335: t2 -= LEAPYEAR(ct.year) ? 366 : 365;
1.1 cgd 336: }
337:
338: /* t = month + day; separate */
1.3 ! cgd 339: t2 = LEAPYEAR(ct.year);
! 340: for (ct.mon = 1; ct.mon < 12; ct.mon++)
! 341: if (t < dayyr[ct.mon] + (t2 && ct.mon > 1))
1.1 cgd 342: break;
343:
1.3 ! cgd 344: ct.day = t - dayyr[ct.mon - 1] + 1;
! 345: if (t2 && ct.mon > 2)
! 346: ct.day--;
1.1 cgd 347:
348: /* the rest is easy */
349: t = time.tv_sec % SECDAY;
1.3 ! cgd 350: ct.hour = t / SECHOUR;
1.1 cgd 351: t %= 3600;
1.3 ! cgd 352: ct.min = t / SECMIN;
! 353: ct.sec = t % SECMIN;
1.1 cgd 354:
1.3 ! cgd 355: (*csc->sc_set)(csc, &ct);
1.1 cgd 356: }
357:
358: /*
1.3 ! cgd 359: * Wait "n" microseconds. This doesn't belong here. XXX.
1.1 cgd 360: */
361: void
362: delay(n)
363: int n;
364: {
365: DELAY(n);
366: }
CVSweb <webmaster@jp.NetBSD.org>