Deleted Added
full compact
clock.c (13000) clock.c (13228)
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz and Don Ahn.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: @(#)clock.c 7.2 (Berkeley) 5/12/91
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz and Don Ahn.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: @(#)clock.c 7.2 (Berkeley) 5/12/91
37 * $Id: clock.c,v 1.42 1995/12/20 20:57:33 wollman Exp $
37 * $Id: clock.c,v 1.43 1995/12/24 08:10:52 davidg Exp $
38 */
39
40/*
41 * inittodr, settodr and support routines written
42 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
43 *
44 * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
45 */
46
47/*
48 * Primitive clock interrupt routines.
49 */
38 */
39
40/*
41 * inittodr, settodr and support routines written
42 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
43 *
44 * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
45 */
46
47/*
48 * Primitive clock interrupt routines.
49 */
50#include "opt_ddb.h"
51
50#include <sys/param.h>
51#include <sys/systm.h>
52#include <sys/time.h>
53#include <sys/kernel.h>
54#include <machine/clock.h>
55#include <machine/frame.h>
56#include <i386/isa/icu.h>
57#include <i386/isa/isa.h>
58#include <i386/isa/isa_device.h>
59#include <i386/isa/rtc.h>
60#include <i386/isa/timerreg.h>
61
62/*
63 * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
64 * can use a simple formula for leap years.
65 */
66#define LEAPYEAR(y) ((u_int)(y) % 4 == 0)
67#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31)
68
69/* X-tals being what they are, it's nice to be able to fudge this one... */
70#ifndef TIMER_FREQ
71#define TIMER_FREQ 1193182 /* XXX - should be in isa.h */
72#endif
73#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
74
75/*
76 * Time in timer cycles that it takes for microtime() to disable interrupts
77 * and latch the count. microtime() currently uses "cli; outb ..." so it
78 * normally takes less than 2 timer cycles. Add a few for cache misses.
79 * Add a few more to allow for latency in bogus calls to microtime() with
80 * interrupts already disabled.
81 */
82#define TIMER0_LATCH_COUNT 20
83
84/*
85 * Minimum maximum count that we are willing to program into timer0.
86 * Must be large enough to guarantee that the timer interrupt handler
87 * returns before the next timer interrupt. Must be larger than
88 * TIMER0_LATCH_COUNT so that we don't have to worry about underflow in
89 * the calculation of timer0_overflow_threshold.
90 */
91#define TIMER0_MIN_MAX_COUNT TIMER_DIV(20000)
92
93int adjkerntz = 0; /* offset from CMOS clock */
94int disable_rtc_set = 0; /* disable resettodr() if != 0 */
95u_int idelayed;
96#if defined(I586_CPU) || defined(I686_CPU)
97unsigned i586_ctr_rate;
98long long i586_ctr_bias;
99long long i586_last_tick;
100#endif
101u_int stat_imask = SWI_CLOCK_MASK;
102int timer0_max_count;
103u_int timer0_overflow_threshold;
104u_int timer0_prescaler_count;
105
106static int beeping = 0;
107static u_int clk_imask = HWI_MASK | SWI_MASK;
108static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
109static u_int hardclock_max_count;
110/*
111 * XXX new_function and timer_func should not handle clockframes, but
112 * timer_func currently needs to hold hardclock to handle the
113 * timer0_state == 0 case. We should use register_intr()/unregister_intr()
114 * to switch between clkintr() and a slightly different timerintr().
115 * This will require locking when acquiring and releasing timer0 - the
116 * current (nonexistent) locking doesn't seem to be adequate even now.
117 */
118static void (*new_function) __P((struct clockframe *frame));
119static u_int new_rate;
120static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
121static char timer0_state = 0;
122static char timer2_state = 0;
123static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
124
125#if 0
126void
127clkintr(struct clockframe frame)
128{
129 hardclock(&frame);
130 setdelayed();
131}
132#else
133static void
134clkintr(struct clockframe frame)
135{
136 timer_func(&frame);
137 switch (timer0_state) {
138 case 0:
139 setdelayed();
140 break;
141 case 1:
142 if ((timer0_prescaler_count += timer0_max_count)
143 >= hardclock_max_count) {
144 hardclock(&frame);
145 setdelayed();
146 timer0_prescaler_count -= hardclock_max_count;
147 }
148 break;
149 case 2:
150 setdelayed();
151 timer0_max_count = TIMER_DIV(new_rate);
152 timer0_overflow_threshold =
153 timer0_max_count - TIMER0_LATCH_COUNT;
154 disable_intr();
155 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
156 outb(TIMER_CNTR0, timer0_max_count & 0xff);
157 outb(TIMER_CNTR0, timer0_max_count >> 8);
158 enable_intr();
159 timer0_prescaler_count = 0;
160 timer_func = new_function;
161 timer0_state = 1;
162 break;
163 case 3:
164 if ((timer0_prescaler_count += timer0_max_count)
165 >= hardclock_max_count) {
166 hardclock(&frame);
167 setdelayed();
168 timer0_max_count = hardclock_max_count;
169 timer0_overflow_threshold =
170 timer0_max_count - TIMER0_LATCH_COUNT;
171 disable_intr();
172 outb(TIMER_MODE,
173 TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
174 outb(TIMER_CNTR0, timer0_max_count & 0xff);
175 outb(TIMER_CNTR0, timer0_max_count >> 8);
176 enable_intr();
177 /*
178 * See microtime.s for this magic.
179 */
180 time.tv_usec += (27645 *
181 (timer0_prescaler_count - hardclock_max_count))
182 >> 15;
183 if (time.tv_usec >= 1000000)
184 time.tv_usec -= 1000000;
185 timer0_prescaler_count = 0;
186 timer_func = hardclock;;
187 timer0_state = 0;
188 }
189 break;
190 }
191}
192#endif
193
194int
195acquire_timer0(int rate, void (*function) __P((struct clockframe *frame)))
196{
197 if (timer0_state || TIMER_DIV(rate) < TIMER0_MIN_MAX_COUNT ||
198 !function)
199 return -1;
200 new_function = function;
201 new_rate = rate;
202 timer0_state = 2;
203 return 0;
204}
205
206int
207acquire_timer2(int mode)
208{
209 if (timer2_state)
210 return -1;
211 timer2_state = 1;
212 outb(TIMER_MODE, TIMER_SEL2 | (mode &0x3f));
213 return 0;
214}
215
216int
217release_timer0()
218{
219 if (!timer0_state)
220 return -1;
221 timer0_state = 3;
222 return 0;
223}
224
225int
226release_timer2()
227{
228 if (!timer2_state)
229 return -1;
230 timer2_state = 0;
231 outb(TIMER_MODE, TIMER_SEL2|TIMER_SQWAVE|TIMER_16BIT);
232 return 0;
233}
234
235/*
236 * This routine receives statistical clock interrupts from the RTC.
237 * As explained above, these occur at 128 interrupts per second.
238 * When profiling, we receive interrupts at a rate of 1024 Hz.
239 *
240 * This does not actually add as much overhead as it sounds, because
241 * when the statistical clock is active, the hardclock driver no longer
242 * needs to keep (inaccurate) statistics on its own. This decouples
243 * statistics gathering from scheduling interrupts.
244 *
245 * The RTC chip requires that we read status register C (RTC_INTR)
246 * to acknowledge an interrupt, before it will generate the next one.
247 */
248static void
249rtcintr(struct clockframe frame)
250{
251 u_char stat;
252 stat = rtcin(RTC_INTR);
253 if(stat & RTCIR_PERIOD) {
254 statclock(&frame);
255 }
256}
257
258#ifdef DDB
259static void
260DDB_printrtc(void)
261{
262 printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n",
263 rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY),
264 rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC),
265 rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR));
266}
267#endif
268
269static int
270getit(void)
271{
272 int high, low;
273
274 disable_intr();
275 /* select timer0 and latch counter value */
276 outb(TIMER_MODE, TIMER_SEL0);
277 low = inb(TIMER_CNTR0);
278 high = inb(TIMER_CNTR0);
279 enable_intr();
280 return ((high << 8) | low);
281}
282
283#if defined(I586_CPU) || defined(I686_CPU)
284/*
285 * Figure out how fast the cyclecounter runs. This must be run with
286 * clock interrupts disabled, but with the timer/counter programmed
287 * and running.
288 */
289void
290calibrate_cyclecounter(void)
291{
292 /*
293 * Don't need volatile; should always use unsigned if 2's
294 * complement arithmetic is desired.
295 */
296 unsigned long long count;
297
298#define howlong 131072UL
299 __asm __volatile(".byte 0x0f, 0x30" : : "A"(0LL), "c" (0x10));
300 DELAY(howlong);
301 __asm __volatile(".byte 0xf,0x31" : "=A" (count));
302
303 i586_ctr_rate = (count << I586_CTR_RATE_SHIFT) / howlong;
304#undef howlong
305}
306#endif
307
308/*
309 * Wait "n" microseconds.
310 * Relies on timer 1 counting down from (TIMER_FREQ / hz)
311 * Note: timer had better have been programmed before this is first used!
312 */
313void
314DELAY(int n)
315{
316 int prev_tick, tick, ticks_left, sec, usec;
317
318#ifdef DELAYDEBUG
319 int getit_calls = 1;
320 int n1;
321 static int state = 0;
322
323 if (state == 0) {
324 state = 1;
325 for (n1 = 1; n1 <= 10000000; n1 *= 10)
326 DELAY(n1);
327 state = 2;
328 }
329 if (state == 1)
330 printf("DELAY(%d)...", n);
331#endif
332 /*
333 * Read the counter first, so that the rest of the setup overhead is
334 * counted. Guess the initial overhead is 20 usec (on most systems it
335 * takes about 1.5 usec for each of the i/o's in getit(). The loop
336 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The
337 * multiplications and divisions to scale the count take a while).
338 */
339 prev_tick = getit();
340 n -= 20;
341 /*
342 * Calculate (n * (TIMER_FREQ / 1e6)) without using floating point
343 * and without any avoidable overflows.
344 */
345 sec = n / 1000000;
346 usec = n - sec * 1000000;
347 ticks_left = sec * TIMER_FREQ
348 + usec * (TIMER_FREQ / 1000000)
349 + usec * ((TIMER_FREQ % 1000000) / 1000) / 1000
350 + usec * (TIMER_FREQ % 1000) / 1000000;
351
352 while (ticks_left > 0) {
353 tick = getit();
354#ifdef DELAYDEBUG
355 ++getit_calls;
356#endif
357 if (tick > prev_tick)
358 ticks_left -= prev_tick - (tick - timer0_max_count);
359 else
360 ticks_left -= prev_tick - tick;
361 prev_tick = tick;
362 }
363#ifdef DELAYDEBUG
364 if (state == 1)
365 printf(" %d calls to getit() at %d usec each\n",
366 getit_calls, (n + 5) / getit_calls);
367#endif
368}
369
370static void
371sysbeepstop(void *chan)
372{
373 outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */
374 release_timer2();
375 beeping = 0;
376}
377
378int
379sysbeep(int pitch, int period)
380{
381
382 if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT))
383 return -1;
384 disable_intr();
385 outb(TIMER_CNTR2, pitch);
386 outb(TIMER_CNTR2, (pitch>>8));
387 enable_intr();
388 if (!beeping) {
389 outb(IO_PPI, inb(IO_PPI) | 3); /* enable counter2 output to speaker */
390 beeping = period;
391 timeout(sysbeepstop, (void *)NULL, period);
392 }
393 return 0;
394}
395
396/*
397 * RTC support routines
398 */
399static int
400bcd2int(int bcd)
401{
402 return(bcd/16 * 10 + bcd%16);
403}
404
405static int
406int2bcd(int dez)
407{
408 return(dez/10 * 16 + dez%10);
409}
410
411static inline void
412writertc(u_char reg, u_char val)
413{
414 outb(IO_RTC, reg);
415 outb(IO_RTC + 1, val);
416}
417
418static int
419readrtc(int port)
420{
421 return(bcd2int(rtcin(port)));
422}
423
424/*
425 * Initialize 8253 timer 0 early so that it can be used in DELAY().
426 * XXX initialization of other timers is unintentionally left blank.
427 */
428void
429startrtclock()
430{
431 timer0_max_count = hardclock_max_count = TIMER_DIV(hz);
432 timer0_overflow_threshold = timer0_max_count - TIMER0_LATCH_COUNT;
433 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
434 outb(TIMER_CNTR0, timer0_max_count & 0xff);
435 outb(TIMER_CNTR0, timer0_max_count >> 8);
436}
437
438/*
439 * Initialize the time of day register, based on the time base which is, e.g.
440 * from a filesystem.
441 */
442void
443inittodr(time_t base)
444{
445 unsigned long sec, days;
446 int yd;
447 int year, month;
448 int y, m, s;
449
450 s = splclock();
451 time.tv_sec = base;
452 time.tv_usec = 0;
453 splx(s);
454
455 /* Look if we have a RTC present and the time is valid */
456 if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
457 goto wrong_time;
458
459 /* wait for time update to complete */
460 /* If RTCSA_TUP is zero, we have at least 244us before next update */
461 while (rtcin(RTC_STATUSA) & RTCSA_TUP);
462
463 days = 0;
464#ifdef USE_RTC_CENTURY
465 year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100;
466#else
467 year = readrtc(RTC_YEAR) + 1900;
468 if (year < 1970)
469 year += 100;
470#endif
471 if (year < 1970)
472 goto wrong_time;
473 month = readrtc(RTC_MONTH);
474 for (m = 1; m < month; m++)
475 days += daysinmonth[m-1];
476 if ((month > 2) && LEAPYEAR(year))
477 days ++;
478 days += readrtc(RTC_DAY) - 1;
479 yd = days;
480 for (y = 1970; y < year; y++)
481 days += DAYSPERYEAR + LEAPYEAR(y);
482 sec = ((( days * 24 +
483 readrtc(RTC_HRS)) * 60 +
484 readrtc(RTC_MIN)) * 60 +
485 readrtc(RTC_SEC));
486 /* sec now contains the number of seconds, since Jan 1 1970,
487 in the local time zone */
488
489 sec += tz.tz_minuteswest * 60 + adjkerntz;
490
491 s = splclock();
492 time.tv_sec = sec;
493 splx(s);
494 return;
495
496wrong_time:
497 printf("Invalid time in real time clock.\n");
498 printf("Check and reset the date immediately!\n");
499}
500
501/*
502 * Write system time back to RTC
503 */
504void
505resettodr()
506{
507 unsigned long tm;
508 int y, m, s;
509
510 if (disable_rtc_set)
511 return;
512
513 s = splclock();
514 tm = time.tv_sec;
515 splx(s);
516
517 /* Disable RTC updates and interrupts. */
518 writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
519
520 /* Calculate local time to put in RTC */
521
522 tm -= tz.tz_minuteswest * 60 + adjkerntz;
523
524 writertc(RTC_SEC, int2bcd(tm%60)); tm /= 60; /* Write back Seconds */
525 writertc(RTC_MIN, int2bcd(tm%60)); tm /= 60; /* Write back Minutes */
526 writertc(RTC_HRS, int2bcd(tm%24)); tm /= 24; /* Write back Hours */
527
528 /* We have now the days since 01-01-1970 in tm */
529 writertc(RTC_WDAY, (tm+4)%7); /* Write back Weekday */
530 for (y=1970;; y++)
531 if ((tm - DAYSPERYEAR - LEAPYEAR(y)) > tm)
532 break;
533 else
534 tm -= DAYSPERYEAR + LEAPYEAR(y);
535
536 /* Now we have the years in y and the day-of-the-year in tm */
537 writertc(RTC_YEAR, int2bcd(y%100)); /* Write back Year */
538#ifdef USE_RTC_CENTURY
539 writertc(RTC_CENTURY, int2bcd(y/100)); /* ... and Century */
540#endif
541 if (LEAPYEAR(y) && (tm >= 31+29))
542 tm--; /* Subtract Feb-29 */
543 for (m=1;; m++)
544 if (tm - daysinmonth[m-1] > tm)
545 break;
546 else
547 tm -= daysinmonth[m-1];
548
549 writertc(RTC_MONTH, int2bcd(m)); /* Write back Month */
550 writertc(RTC_DAY, int2bcd(tm+1)); /* Write back Day */
551
552 /* Reenable RTC updates and interrupts. */
553 writertc(RTC_STATUSB, RTCSB_24HR | RTCSB_PINTR);
554}
555
556/*
557 * Start both clocks running.
558 */
559void
560cpu_initclocks()
561{
562 int diag;
563
564 stathz = RTC_NOPROFRATE;
565 profhz = RTC_PROFRATE;
566
567 /* Finish initializing 8253 timer 0. */
568 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
569 /* XXX */ (inthand2_t *)clkintr, &clk_imask,
570 /* unit */ 0);
571 INTREN(IRQ0);
572#if defined(I586_CPU) || defined(I686_CPU)
573 /*
574 * Finish setting up anti-jitter measures.
575 */
576 if (i586_ctr_rate) {
577 I586_CYCLECTR(i586_last_tick);
578 i586_ctr_bias = i586_last_tick;
579 }
580#endif
581
582 /* Initialize RTC. */
583 writertc(RTC_STATUSA, rtc_statusa);
584 writertc(RTC_STATUSB, RTCSB_24HR);
585 diag = rtcin(RTC_DIAG);
586 if (diag != 0)
587 printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
588 register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
589 /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
590 /* unit */ 0);
591 INTREN(IRQ8);
592 writertc(RTC_STATUSB, RTCSB_24HR | RTCSB_PINTR);
593}
594
595void
596setstatclockrate(int newhz)
597{
598 if (newhz == RTC_PROFRATE)
599 rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
600 else
601 rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
602 writertc(RTC_STATUSA, rtc_statusa);
603}
52#include <sys/param.h>
53#include <sys/systm.h>
54#include <sys/time.h>
55#include <sys/kernel.h>
56#include <machine/clock.h>
57#include <machine/frame.h>
58#include <i386/isa/icu.h>
59#include <i386/isa/isa.h>
60#include <i386/isa/isa_device.h>
61#include <i386/isa/rtc.h>
62#include <i386/isa/timerreg.h>
63
64/*
65 * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
66 * can use a simple formula for leap years.
67 */
68#define LEAPYEAR(y) ((u_int)(y) % 4 == 0)
69#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31)
70
71/* X-tals being what they are, it's nice to be able to fudge this one... */
72#ifndef TIMER_FREQ
73#define TIMER_FREQ 1193182 /* XXX - should be in isa.h */
74#endif
75#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
76
77/*
78 * Time in timer cycles that it takes for microtime() to disable interrupts
79 * and latch the count. microtime() currently uses "cli; outb ..." so it
80 * normally takes less than 2 timer cycles. Add a few for cache misses.
81 * Add a few more to allow for latency in bogus calls to microtime() with
82 * interrupts already disabled.
83 */
84#define TIMER0_LATCH_COUNT 20
85
86/*
87 * Minimum maximum count that we are willing to program into timer0.
88 * Must be large enough to guarantee that the timer interrupt handler
89 * returns before the next timer interrupt. Must be larger than
90 * TIMER0_LATCH_COUNT so that we don't have to worry about underflow in
91 * the calculation of timer0_overflow_threshold.
92 */
93#define TIMER0_MIN_MAX_COUNT TIMER_DIV(20000)
94
95int adjkerntz = 0; /* offset from CMOS clock */
96int disable_rtc_set = 0; /* disable resettodr() if != 0 */
97u_int idelayed;
98#if defined(I586_CPU) || defined(I686_CPU)
99unsigned i586_ctr_rate;
100long long i586_ctr_bias;
101long long i586_last_tick;
102#endif
103u_int stat_imask = SWI_CLOCK_MASK;
104int timer0_max_count;
105u_int timer0_overflow_threshold;
106u_int timer0_prescaler_count;
107
108static int beeping = 0;
109static u_int clk_imask = HWI_MASK | SWI_MASK;
110static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
111static u_int hardclock_max_count;
112/*
113 * XXX new_function and timer_func should not handle clockframes, but
114 * timer_func currently needs to hold hardclock to handle the
115 * timer0_state == 0 case. We should use register_intr()/unregister_intr()
116 * to switch between clkintr() and a slightly different timerintr().
117 * This will require locking when acquiring and releasing timer0 - the
118 * current (nonexistent) locking doesn't seem to be adequate even now.
119 */
120static void (*new_function) __P((struct clockframe *frame));
121static u_int new_rate;
122static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
123static char timer0_state = 0;
124static char timer2_state = 0;
125static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
126
127#if 0
128void
129clkintr(struct clockframe frame)
130{
131 hardclock(&frame);
132 setdelayed();
133}
134#else
135static void
136clkintr(struct clockframe frame)
137{
138 timer_func(&frame);
139 switch (timer0_state) {
140 case 0:
141 setdelayed();
142 break;
143 case 1:
144 if ((timer0_prescaler_count += timer0_max_count)
145 >= hardclock_max_count) {
146 hardclock(&frame);
147 setdelayed();
148 timer0_prescaler_count -= hardclock_max_count;
149 }
150 break;
151 case 2:
152 setdelayed();
153 timer0_max_count = TIMER_DIV(new_rate);
154 timer0_overflow_threshold =
155 timer0_max_count - TIMER0_LATCH_COUNT;
156 disable_intr();
157 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
158 outb(TIMER_CNTR0, timer0_max_count & 0xff);
159 outb(TIMER_CNTR0, timer0_max_count >> 8);
160 enable_intr();
161 timer0_prescaler_count = 0;
162 timer_func = new_function;
163 timer0_state = 1;
164 break;
165 case 3:
166 if ((timer0_prescaler_count += timer0_max_count)
167 >= hardclock_max_count) {
168 hardclock(&frame);
169 setdelayed();
170 timer0_max_count = hardclock_max_count;
171 timer0_overflow_threshold =
172 timer0_max_count - TIMER0_LATCH_COUNT;
173 disable_intr();
174 outb(TIMER_MODE,
175 TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
176 outb(TIMER_CNTR0, timer0_max_count & 0xff);
177 outb(TIMER_CNTR0, timer0_max_count >> 8);
178 enable_intr();
179 /*
180 * See microtime.s for this magic.
181 */
182 time.tv_usec += (27645 *
183 (timer0_prescaler_count - hardclock_max_count))
184 >> 15;
185 if (time.tv_usec >= 1000000)
186 time.tv_usec -= 1000000;
187 timer0_prescaler_count = 0;
188 timer_func = hardclock;;
189 timer0_state = 0;
190 }
191 break;
192 }
193}
194#endif
195
196int
197acquire_timer0(int rate, void (*function) __P((struct clockframe *frame)))
198{
199 if (timer0_state || TIMER_DIV(rate) < TIMER0_MIN_MAX_COUNT ||
200 !function)
201 return -1;
202 new_function = function;
203 new_rate = rate;
204 timer0_state = 2;
205 return 0;
206}
207
208int
209acquire_timer2(int mode)
210{
211 if (timer2_state)
212 return -1;
213 timer2_state = 1;
214 outb(TIMER_MODE, TIMER_SEL2 | (mode &0x3f));
215 return 0;
216}
217
218int
219release_timer0()
220{
221 if (!timer0_state)
222 return -1;
223 timer0_state = 3;
224 return 0;
225}
226
227int
228release_timer2()
229{
230 if (!timer2_state)
231 return -1;
232 timer2_state = 0;
233 outb(TIMER_MODE, TIMER_SEL2|TIMER_SQWAVE|TIMER_16BIT);
234 return 0;
235}
236
237/*
238 * This routine receives statistical clock interrupts from the RTC.
239 * As explained above, these occur at 128 interrupts per second.
240 * When profiling, we receive interrupts at a rate of 1024 Hz.
241 *
242 * This does not actually add as much overhead as it sounds, because
243 * when the statistical clock is active, the hardclock driver no longer
244 * needs to keep (inaccurate) statistics on its own. This decouples
245 * statistics gathering from scheduling interrupts.
246 *
247 * The RTC chip requires that we read status register C (RTC_INTR)
248 * to acknowledge an interrupt, before it will generate the next one.
249 */
250static void
251rtcintr(struct clockframe frame)
252{
253 u_char stat;
254 stat = rtcin(RTC_INTR);
255 if(stat & RTCIR_PERIOD) {
256 statclock(&frame);
257 }
258}
259
260#ifdef DDB
261static void
262DDB_printrtc(void)
263{
264 printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n",
265 rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY),
266 rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC),
267 rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR));
268}
269#endif
270
271static int
272getit(void)
273{
274 int high, low;
275
276 disable_intr();
277 /* select timer0 and latch counter value */
278 outb(TIMER_MODE, TIMER_SEL0);
279 low = inb(TIMER_CNTR0);
280 high = inb(TIMER_CNTR0);
281 enable_intr();
282 return ((high << 8) | low);
283}
284
285#if defined(I586_CPU) || defined(I686_CPU)
286/*
287 * Figure out how fast the cyclecounter runs. This must be run with
288 * clock interrupts disabled, but with the timer/counter programmed
289 * and running.
290 */
291void
292calibrate_cyclecounter(void)
293{
294 /*
295 * Don't need volatile; should always use unsigned if 2's
296 * complement arithmetic is desired.
297 */
298 unsigned long long count;
299
300#define howlong 131072UL
301 __asm __volatile(".byte 0x0f, 0x30" : : "A"(0LL), "c" (0x10));
302 DELAY(howlong);
303 __asm __volatile(".byte 0xf,0x31" : "=A" (count));
304
305 i586_ctr_rate = (count << I586_CTR_RATE_SHIFT) / howlong;
306#undef howlong
307}
308#endif
309
310/*
311 * Wait "n" microseconds.
312 * Relies on timer 1 counting down from (TIMER_FREQ / hz)
313 * Note: timer had better have been programmed before this is first used!
314 */
315void
316DELAY(int n)
317{
318 int prev_tick, tick, ticks_left, sec, usec;
319
320#ifdef DELAYDEBUG
321 int getit_calls = 1;
322 int n1;
323 static int state = 0;
324
325 if (state == 0) {
326 state = 1;
327 for (n1 = 1; n1 <= 10000000; n1 *= 10)
328 DELAY(n1);
329 state = 2;
330 }
331 if (state == 1)
332 printf("DELAY(%d)...", n);
333#endif
334 /*
335 * Read the counter first, so that the rest of the setup overhead is
336 * counted. Guess the initial overhead is 20 usec (on most systems it
337 * takes about 1.5 usec for each of the i/o's in getit(). The loop
338 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The
339 * multiplications and divisions to scale the count take a while).
340 */
341 prev_tick = getit();
342 n -= 20;
343 /*
344 * Calculate (n * (TIMER_FREQ / 1e6)) without using floating point
345 * and without any avoidable overflows.
346 */
347 sec = n / 1000000;
348 usec = n - sec * 1000000;
349 ticks_left = sec * TIMER_FREQ
350 + usec * (TIMER_FREQ / 1000000)
351 + usec * ((TIMER_FREQ % 1000000) / 1000) / 1000
352 + usec * (TIMER_FREQ % 1000) / 1000000;
353
354 while (ticks_left > 0) {
355 tick = getit();
356#ifdef DELAYDEBUG
357 ++getit_calls;
358#endif
359 if (tick > prev_tick)
360 ticks_left -= prev_tick - (tick - timer0_max_count);
361 else
362 ticks_left -= prev_tick - tick;
363 prev_tick = tick;
364 }
365#ifdef DELAYDEBUG
366 if (state == 1)
367 printf(" %d calls to getit() at %d usec each\n",
368 getit_calls, (n + 5) / getit_calls);
369#endif
370}
371
372static void
373sysbeepstop(void *chan)
374{
375 outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */
376 release_timer2();
377 beeping = 0;
378}
379
380int
381sysbeep(int pitch, int period)
382{
383
384 if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT))
385 return -1;
386 disable_intr();
387 outb(TIMER_CNTR2, pitch);
388 outb(TIMER_CNTR2, (pitch>>8));
389 enable_intr();
390 if (!beeping) {
391 outb(IO_PPI, inb(IO_PPI) | 3); /* enable counter2 output to speaker */
392 beeping = period;
393 timeout(sysbeepstop, (void *)NULL, period);
394 }
395 return 0;
396}
397
398/*
399 * RTC support routines
400 */
401static int
402bcd2int(int bcd)
403{
404 return(bcd/16 * 10 + bcd%16);
405}
406
407static int
408int2bcd(int dez)
409{
410 return(dez/10 * 16 + dez%10);
411}
412
413static inline void
414writertc(u_char reg, u_char val)
415{
416 outb(IO_RTC, reg);
417 outb(IO_RTC + 1, val);
418}
419
420static int
421readrtc(int port)
422{
423 return(bcd2int(rtcin(port)));
424}
425
426/*
427 * Initialize 8253 timer 0 early so that it can be used in DELAY().
428 * XXX initialization of other timers is unintentionally left blank.
429 */
430void
431startrtclock()
432{
433 timer0_max_count = hardclock_max_count = TIMER_DIV(hz);
434 timer0_overflow_threshold = timer0_max_count - TIMER0_LATCH_COUNT;
435 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
436 outb(TIMER_CNTR0, timer0_max_count & 0xff);
437 outb(TIMER_CNTR0, timer0_max_count >> 8);
438}
439
440/*
441 * Initialize the time of day register, based on the time base which is, e.g.
442 * from a filesystem.
443 */
444void
445inittodr(time_t base)
446{
447 unsigned long sec, days;
448 int yd;
449 int year, month;
450 int y, m, s;
451
452 s = splclock();
453 time.tv_sec = base;
454 time.tv_usec = 0;
455 splx(s);
456
457 /* Look if we have a RTC present and the time is valid */
458 if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
459 goto wrong_time;
460
461 /* wait for time update to complete */
462 /* If RTCSA_TUP is zero, we have at least 244us before next update */
463 while (rtcin(RTC_STATUSA) & RTCSA_TUP);
464
465 days = 0;
466#ifdef USE_RTC_CENTURY
467 year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100;
468#else
469 year = readrtc(RTC_YEAR) + 1900;
470 if (year < 1970)
471 year += 100;
472#endif
473 if (year < 1970)
474 goto wrong_time;
475 month = readrtc(RTC_MONTH);
476 for (m = 1; m < month; m++)
477 days += daysinmonth[m-1];
478 if ((month > 2) && LEAPYEAR(year))
479 days ++;
480 days += readrtc(RTC_DAY) - 1;
481 yd = days;
482 for (y = 1970; y < year; y++)
483 days += DAYSPERYEAR + LEAPYEAR(y);
484 sec = ((( days * 24 +
485 readrtc(RTC_HRS)) * 60 +
486 readrtc(RTC_MIN)) * 60 +
487 readrtc(RTC_SEC));
488 /* sec now contains the number of seconds, since Jan 1 1970,
489 in the local time zone */
490
491 sec += tz.tz_minuteswest * 60 + adjkerntz;
492
493 s = splclock();
494 time.tv_sec = sec;
495 splx(s);
496 return;
497
498wrong_time:
499 printf("Invalid time in real time clock.\n");
500 printf("Check and reset the date immediately!\n");
501}
502
503/*
504 * Write system time back to RTC
505 */
506void
507resettodr()
508{
509 unsigned long tm;
510 int y, m, s;
511
512 if (disable_rtc_set)
513 return;
514
515 s = splclock();
516 tm = time.tv_sec;
517 splx(s);
518
519 /* Disable RTC updates and interrupts. */
520 writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
521
522 /* Calculate local time to put in RTC */
523
524 tm -= tz.tz_minuteswest * 60 + adjkerntz;
525
526 writertc(RTC_SEC, int2bcd(tm%60)); tm /= 60; /* Write back Seconds */
527 writertc(RTC_MIN, int2bcd(tm%60)); tm /= 60; /* Write back Minutes */
528 writertc(RTC_HRS, int2bcd(tm%24)); tm /= 24; /* Write back Hours */
529
530 /* We have now the days since 01-01-1970 in tm */
531 writertc(RTC_WDAY, (tm+4)%7); /* Write back Weekday */
532 for (y=1970;; y++)
533 if ((tm - DAYSPERYEAR - LEAPYEAR(y)) > tm)
534 break;
535 else
536 tm -= DAYSPERYEAR + LEAPYEAR(y);
537
538 /* Now we have the years in y and the day-of-the-year in tm */
539 writertc(RTC_YEAR, int2bcd(y%100)); /* Write back Year */
540#ifdef USE_RTC_CENTURY
541 writertc(RTC_CENTURY, int2bcd(y/100)); /* ... and Century */
542#endif
543 if (LEAPYEAR(y) && (tm >= 31+29))
544 tm--; /* Subtract Feb-29 */
545 for (m=1;; m++)
546 if (tm - daysinmonth[m-1] > tm)
547 break;
548 else
549 tm -= daysinmonth[m-1];
550
551 writertc(RTC_MONTH, int2bcd(m)); /* Write back Month */
552 writertc(RTC_DAY, int2bcd(tm+1)); /* Write back Day */
553
554 /* Reenable RTC updates and interrupts. */
555 writertc(RTC_STATUSB, RTCSB_24HR | RTCSB_PINTR);
556}
557
558/*
559 * Start both clocks running.
560 */
561void
562cpu_initclocks()
563{
564 int diag;
565
566 stathz = RTC_NOPROFRATE;
567 profhz = RTC_PROFRATE;
568
569 /* Finish initializing 8253 timer 0. */
570 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
571 /* XXX */ (inthand2_t *)clkintr, &clk_imask,
572 /* unit */ 0);
573 INTREN(IRQ0);
574#if defined(I586_CPU) || defined(I686_CPU)
575 /*
576 * Finish setting up anti-jitter measures.
577 */
578 if (i586_ctr_rate) {
579 I586_CYCLECTR(i586_last_tick);
580 i586_ctr_bias = i586_last_tick;
581 }
582#endif
583
584 /* Initialize RTC. */
585 writertc(RTC_STATUSA, rtc_statusa);
586 writertc(RTC_STATUSB, RTCSB_24HR);
587 diag = rtcin(RTC_DIAG);
588 if (diag != 0)
589 printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
590 register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
591 /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
592 /* unit */ 0);
593 INTREN(IRQ8);
594 writertc(RTC_STATUSB, RTCSB_24HR | RTCSB_PINTR);
595}
596
597void
598setstatclockrate(int newhz)
599{
600 if (newhz == RTC_PROFRATE)
601 rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
602 else
603 rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
604 writertc(RTC_STATUSA, rtc_statusa);
605}