Deleted Added
full compact
clock.c (32052) clock.c (32054)
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

--- 20 unchanged lines hidden (view full) ---

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

--- 20 unchanged lines hidden (view full) ---

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.105 1997/12/26 20:42:05 phk Exp $
37 * $Id: clock.c,v 1.106 1997/12/28 13:36:07 phk Exp $
38 */
39
40/*
41 * Routines to handle clock hardware.
42 */
43
44/*
45 * inittodr, settodr and support routines written

--- 16 unchanged lines hidden (view full) ---

62#include <machine/clock.h>
63#ifdef CLK_CALIBRATION_LOOP
64#include <machine/cons.h>
65#endif
66#include <machine/cputypes.h>
67#include <machine/frame.h>
68#include <machine/ipl.h>
69#include <machine/limits.h>
38 */
39
40/*
41 * Routines to handle clock hardware.
42 */
43
44/*
45 * inittodr, settodr and support routines written

--- 16 unchanged lines hidden (view full) ---

62#include <machine/clock.h>
63#ifdef CLK_CALIBRATION_LOOP
64#include <machine/cons.h>
65#endif
66#include <machine/cputypes.h>
67#include <machine/frame.h>
68#include <machine/ipl.h>
69#include <machine/limits.h>
70#include <machine/md_var.h>
70#ifdef APIC_IO
71#include <machine/segments.h>
72#endif
73#if defined(SMP) || defined(APIC_IO)
74#include <machine/smp.h>
75#endif /* SMP || APIC_IO */
71#ifdef APIC_IO
72#include <machine/segments.h>
73#endif
74#if defined(SMP) || defined(APIC_IO)
75#include <machine/smp.h>
76#endif /* SMP || APIC_IO */
77#include <machine/specialreg.h>
76
77#include <i386/isa/icu.h>
78#include <i386/isa/isa.h>
79#include <i386/isa/rtc.h>
80#include <i386/isa/timerreg.h>
81
82#include <sys/interrupt.h>
83

--- 37 unchanged lines hidden (view full) ---

121#ifdef TIMER_FREQ
122u_int timer_freq = TIMER_FREQ;
123#else
124u_int timer_freq = 1193182;
125#endif
126int timer0_max_count;
127u_int timer0_overflow_threshold;
128u_int timer0_prescaler_count;
78
79#include <i386/isa/icu.h>
80#include <i386/isa/isa.h>
81#include <i386/isa/rtc.h>
82#include <i386/isa/timerreg.h>
83
84#include <sys/interrupt.h>
85

--- 37 unchanged lines hidden (view full) ---

123#ifdef TIMER_FREQ
124u_int timer_freq = TIMER_FREQ;
125#else
126u_int timer_freq = 1193182;
127#endif
128int timer0_max_count;
129u_int timer0_overflow_threshold;
130u_int timer0_prescaler_count;
129#if defined(I586_CPU) || defined(I686_CPU)
130#ifndef SMP
131u_int tsc_bias;
132u_int tsc_comultiplier;
131u_int tsc_bias;
132u_int tsc_comultiplier;
133#endif
134u_int tsc_freq;
133u_int tsc_freq;
135#ifndef SMP
136u_int tsc_multiplier;
134u_int tsc_multiplier;
137#endif
138#endif
135u_int tsc_present;
139int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
140
141static int beeping = 0;
142static u_int clk_imask = HWI_MASK | SWI_MASK;
143static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
144static u_int hardclock_max_count;
145/*
146 * XXX new_function and timer_func should not handle clockframes, but

--- 11 unchanged lines hidden (view full) ---

158#define RELEASE_PENDING 1
159#define ACQUIRED 2
160#define ACQUIRE_PENDING 3
161
162static u_char timer0_state;
163static u_char timer2_state;
164static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
165
136int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
137
138static int beeping = 0;
139static u_int clk_imask = HWI_MASK | SWI_MASK;
140static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
141static u_int hardclock_max_count;
142/*
143 * XXX new_function and timer_func should not handle clockframes, but

--- 11 unchanged lines hidden (view full) ---

155#define RELEASE_PENDING 1
156#define ACQUIRED 2
157#define ACQUIRE_PENDING 3
158
159static u_char timer0_state;
160static u_char timer2_state;
161static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
162
166#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
167static void set_tsc_freq(u_int i586_freq, u_int i8254_freq);
168#endif
163static void set_tsc_freq(u_int tsc_count, u_int i8254_freq);
169static void set_timer_freq(u_int freq, int intr_freq);
170
171static void
172clkintr(struct clockframe frame)
173{
174 timer_func(&frame);
175 switch (timer0_state) {
176

--- 392 unchanged lines hidden (view full) ---

569 }
570
571 /* Start keeping track of the i8254 counter. */
572 prev_count = getit();
573 if (prev_count == 0 || prev_count > timer0_max_count)
574 goto fail;
575 tot_count = 0;
576
164static void set_timer_freq(u_int freq, int intr_freq);
165
166static void
167clkintr(struct clockframe frame)
168{
169 timer_func(&frame);
170 switch (timer0_state) {
171

--- 392 unchanged lines hidden (view full) ---

564 }
565
566 /* Start keeping track of the i8254 counter. */
567 prev_count = getit();
568 if (prev_count == 0 || prev_count > timer0_max_count)
569 goto fail;
570 tot_count = 0;
571
577#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
578 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
572 if (tsc_present)
579 wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
573 wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
580#endif
581
582 /*
583 * Wait for the mc146818A seconds counter to change. Read the i8254
584 * counter for each iteration since this is convenient and only
585 * costs a few usec of inaccuracy. The timing of the final reads
586 * of the counters almost matches the timing of the initial reads,
587 * so the main cause of inaccuracy is the varying latency from
588 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the

--- 13 unchanged lines hidden (view full) ---

602 tot_count += prev_count - count;
603 prev_count = count;
604 if (sec != start_sec)
605 break;
606 if (--timeout == 0)
607 goto fail;
608 }
609
574
575 /*
576 * Wait for the mc146818A seconds counter to change. Read the i8254
577 * counter for each iteration since this is convenient and only
578 * costs a few usec of inaccuracy. The timing of the final reads
579 * of the counters almost matches the timing of the initial reads,
580 * so the main cause of inaccuracy is the varying latency from
581 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the

--- 13 unchanged lines hidden (view full) ---

595 tot_count += prev_count - count;
596 prev_count = count;
597 if (sec != start_sec)
598 break;
599 if (--timeout == 0)
600 goto fail;
601 }
602
610#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
611 /*
612 * Read the cpu cycle counter. The timing considerations are
613 * similar to those for the i8254 clock.
614 */
603 /*
604 * Read the cpu cycle counter. The timing considerations are
605 * similar to those for the i8254 clock.
606 */
615 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) {
607 if (tsc_present) {
616 set_tsc_freq((u_int)rdtsc(), tot_count);
617 if (bootverbose)
618 printf("TSC clock: %u Hz, ", tsc_freq);
619 }
608 set_tsc_freq((u_int)rdtsc(), tot_count);
609 if (bootverbose)
610 printf("TSC clock: %u Hz, ", tsc_freq);
611 }
620#endif
621
622 if (bootverbose)
623 printf("i8254 clock: %u Hz\n", tot_count);
624 return (tot_count);
625
626fail:
627 if (bootverbose)
628 printf("failed, using default i8254 clock of %u Hz\n",

--- 22 unchanged lines hidden (view full) ---

651 * Initialize 8253 timer 0 early so that it can be used in DELAY().
652 * XXX initialization of other timers is unintentionally left blank.
653 */
654void
655startrtclock()
656{
657 u_int delta, freq;
658
612
613 if (bootverbose)
614 printf("i8254 clock: %u Hz\n", tot_count);
615 return (tot_count);
616
617fail:
618 if (bootverbose)
619 printf("failed, using default i8254 clock of %u Hz\n",

--- 22 unchanged lines hidden (view full) ---

642 * Initialize 8253 timer 0 early so that it can be used in DELAY().
643 * XXX initialization of other timers is unintentionally left blank.
644 */
645void
646startrtclock()
647{
648 u_int delta, freq;
649
650 if (cpu_feature & CPUID_TSC)
651 tsc_present = 1;
652 else
653 tsc_present = 0;
654
655#ifdef SMP
656 tsc_present = 0;
657#endif
658
659 writertc(RTC_STATUSA, rtc_statusa);
660 writertc(RTC_STATUSB, RTCSB_24HR);
661
662 set_timer_freq(timer_freq, hz);
663 freq = calibrate_clocks();
664#ifdef CLK_CALIBRATION_LOOP
665 if (bootverbose) {
666 printf(

--- 17 unchanged lines hidden (view full) ---

684 freq = timer_freq;
685#endif
686 timer_freq = freq;
687 } else {
688 if (bootverbose)
689 printf(
690 "%d Hz differs from default of %d Hz by more than 1%%\n",
691 freq, timer_freq);
659 writertc(RTC_STATUSA, rtc_statusa);
660 writertc(RTC_STATUSB, RTCSB_24HR);
661
662 set_timer_freq(timer_freq, hz);
663 freq = calibrate_clocks();
664#ifdef CLK_CALIBRATION_LOOP
665 if (bootverbose) {
666 printf(

--- 17 unchanged lines hidden (view full) ---

684 freq = timer_freq;
685#endif
686 timer_freq = freq;
687 } else {
688 if (bootverbose)
689 printf(
690 "%d Hz differs from default of %d Hz by more than 1%%\n",
691 freq, timer_freq);
692#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
693 tsc_freq = 0;
692 tsc_freq = 0;
694#endif
695 }
696
697 set_timer_freq(timer_freq, hz);
698
693 }
694
695 set_timer_freq(timer_freq, hz);
696
699#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
700#ifndef CLK_USE_TSC_CALIBRATION
701 if (tsc_freq != 0) {
702 if (bootverbose)
703 printf(
704"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
705 tsc_freq = 0;
706 }
707#endif
697#ifndef CLK_USE_TSC_CALIBRATION
698 if (tsc_freq != 0) {
699 if (bootverbose)
700 printf(
701"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
702 tsc_freq = 0;
703 }
704#endif
708 if (tsc_freq == 0 &&
709 (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) {
705 if (tsc_present && tsc_freq == 0) {
710 /*
711 * Calibration of the i586 clock relative to the mc146818A
712 * clock failed. Do a less accurate calibration relative
713 * to the i8254 clock.
714 */
715 wrmsr(0x10, 0LL); /* XXX */
716 DELAY(1000000);
717 set_tsc_freq((u_int)rdtsc(), timer_freq);
706 /*
707 * Calibration of the i586 clock relative to the mc146818A
708 * clock failed. Do a less accurate calibration relative
709 * to the i8254 clock.
710 */
711 wrmsr(0x10, 0LL); /* XXX */
712 DELAY(1000000);
713 set_tsc_freq((u_int)rdtsc(), timer_freq);
718#ifdef CLK_USE_I586_CALIBRATION
714#ifdef CLK_USE_TSC_CALIBRATION
719 if (bootverbose)
720 printf("TSC clock: %u Hz\n", tsc_freq);
721#endif
722 }
715 if (bootverbose)
716 printf("TSC clock: %u Hz\n", tsc_freq);
717#endif
718 }
723#endif
724}
725
726/*
727 * Initialize the time of day register, based on the time base which is, e.g.
728 * from a filesystem.
729 */
730void
731inittodr(time_t base)

--- 188 unchanged lines hidden (view full) ---

920
921 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
922 /* XXX */ (inthand2_t *)clkintr, &clk_imask,
923 /* unit */ 0);
924 INTREN(IRQ0);
925
926#endif /* APIC_IO */
927
719}
720
721/*
722 * Initialize the time of day register, based on the time base which is, e.g.
723 * from a filesystem.
724 */
725void
726inittodr(time_t base)

--- 188 unchanged lines hidden (view full) ---

915
916 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
917 /* XXX */ (inthand2_t *)clkintr, &clk_imask,
918 /* unit */ 0);
919 INTREN(IRQ0);
920
921#endif /* APIC_IO */
922
928#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
929 /*
930 * Finish setting up anti-jitter measures.
931 */
932 if (tsc_freq != 0)
933 tsc_bias = rdtsc();
923 /*
924 * Finish setting up anti-jitter measures.
925 */
926 if (tsc_freq != 0)
927 tsc_bias = rdtsc();
934#endif
935
936 /* Initialize RTC. */
937 writertc(RTC_STATUSA, rtc_statusa);
938 writertc(RTC_STATUSB, RTCSB_24HR);
939
940 /* Don't bother enabling the statistics clock. */
941 if (statclock_disable)
942 return;

--- 40 unchanged lines hidden (view full) ---

983 * is is too generic. Should use it everywhere.
984 */
985 freq = timer_freq;
986 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
987 if (error == 0 && req->newptr != NULL) {
988 if (timer0_state != 0)
989 return (EBUSY); /* too much trouble to handle */
990 set_timer_freq(freq, hz);
928
929 /* Initialize RTC. */
930 writertc(RTC_STATUSA, rtc_statusa);
931 writertc(RTC_STATUSB, RTCSB_24HR);
932
933 /* Don't bother enabling the statistics clock. */
934 if (statclock_disable)
935 return;

--- 40 unchanged lines hidden (view full) ---

976 * is is too generic. Should use it everywhere.
977 */
978 freq = timer_freq;
979 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
980 if (error == 0 && req->newptr != NULL) {
981 if (timer0_state != 0)
982 return (EBUSY); /* too much trouble to handle */
983 set_timer_freq(freq, hz);
991#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
992 set_tsc_freq(tsc_freq, timer_freq);
993#endif
984 if (tsc_present)
985 set_tsc_freq(tsc_freq, timer_freq);
994 }
995 return (error);
996}
997
998SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
999 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
1000
986 }
987 return (error);
988}
989
990SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
991 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
992
1001#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
1002static void
993static void
1003set_tsc_freq(u_int i586_freq, u_int i8254_freq)
994set_tsc_freq(u_int tsc_count, u_int i8254_freq)
1004{
1005 u_int comultiplier, multiplier;
1006 u_long ef;
1007
995{
996 u_int comultiplier, multiplier;
997 u_long ef;
998
1008 if (i586_freq == 0) {
1009 tsc_freq = i586_freq;
999 if (tsc_count == 0) {
1000 tsc_freq = tsc_count;
1010 return;
1011 }
1001 return;
1002 }
1012 comultiplier = ((unsigned long long)i586_freq
1003 comultiplier = ((unsigned long long)tsc_count
1013 << TSC_COMULTIPLIER_SHIFT) / i8254_freq;
1004 << TSC_COMULTIPLIER_SHIFT) / i8254_freq;
1014 multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / i586_freq;
1005 multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / tsc_count;
1015 ef = read_eflags();
1016 disable_intr();
1006 ef = read_eflags();
1007 disable_intr();
1017 tsc_freq = i586_freq;
1008 tsc_freq = tsc_count;
1018 tsc_comultiplier = comultiplier;
1019 tsc_multiplier = multiplier;
1020 CLOCK_UNLOCK();
1021 write_eflags(ef);
1022}
1023
1024static int
1009 tsc_comultiplier = comultiplier;
1010 tsc_multiplier = multiplier;
1011 CLOCK_UNLOCK();
1012 write_eflags(ef);
1013}
1014
1015static int
1025sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
1016sysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS
1026{
1027 int error;
1028 u_int freq;
1029
1017{
1018 int error;
1019 u_int freq;
1020
1030 if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686)
1021 if (!tsc_present)
1031 return (EOPNOTSUPP);
1032 freq = tsc_freq;
1033 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
1034 if (error == 0 && req->newptr != NULL)
1035 set_tsc_freq(freq, timer_freq);
1036 return (error);
1037}
1038
1022 return (EOPNOTSUPP);
1023 freq = tsc_freq;
1024 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
1025 if (error == 0 && req->newptr != NULL)
1026 set_tsc_freq(freq, timer_freq);
1027 return (error);
1028}
1029
1039SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
1040 0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
1041#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */
1030SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW,
1031 0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", "");