Deleted Added
full compact
pcrtc.c (24700) pcrtc.c (25195)
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.18 1997/03/05 16:19:48 kato Exp $
37 * $Id: clock.c,v 1.19 1997/04/07 10:53:14 kato Exp $
38 */
39
40/*
41 * Routines to handle clock hardware.
42 */
43
44/*
45 * inittodr, settodr and support routines written
46 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
47 *
48 * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
49 */
50
51/*
52 * modified for PC98 by Kakefuda
53 */
54
55#include "opt_clock.h"
38 */
39
40/*
41 * Routines to handle clock hardware.
42 */
43
44/*
45 * inittodr, settodr and support routines written
46 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
47 *
48 * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
49 */
50
51/*
52 * modified for PC98 by Kakefuda
53 */
54
55#include "opt_clock.h"
56#include "opt_smp.h"
56#include "opt_cpu.h"
57
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/time.h>
61#include <sys/kernel.h>
62#include <sys/sysctl.h>
63

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

105 * value than TIMER0_LATCH_COUNT so that we don't have to worry about
106 * underflow in the calculation of timer0_overflow_threshold.
107 */
108#define TIMER0_MAX_FREQ 20000
109
110int adjkerntz; /* local offset from GMT in seconds */
111int disable_rtc_set; /* disable resettodr() if != 0 */
112u_int idelayed;
57#include "opt_cpu.h"
58
59#include <sys/param.h>
60#include <sys/systm.h>
61#include <sys/time.h>
62#include <sys/kernel.h>
63#include <sys/sysctl.h>
64

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

106 * value than TIMER0_LATCH_COUNT so that we don't have to worry about
107 * underflow in the calculation of timer0_overflow_threshold.
108 */
109#define TIMER0_MAX_FREQ 20000
110
111int adjkerntz; /* local offset from GMT in seconds */
112int disable_rtc_set; /* disable resettodr() if != 0 */
113u_int idelayed;
113#if defined(I586_CPU) || defined(I686_CPU)
114#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
114u_int i586_ctr_bias;
115u_int i586_ctr_comultiplier;
116u_int i586_ctr_freq;
117u_int i586_ctr_multiplier;
118#endif
119int statclock_disable;
120u_int stat_imask = SWI_CLOCK_MASK;
121#ifdef TIMER_FREQ

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

171static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
172#ifdef PC98
173static void rtc_serialcombit __P((int));
174static void rtc_serialcom __P((int));
175static int rtc_inb __P((void));
176static void rtc_outb __P((int));
177#endif
178
115u_int i586_ctr_bias;
116u_int i586_ctr_comultiplier;
117u_int i586_ctr_freq;
118u_int i586_ctr_multiplier;
119#endif
120int statclock_disable;
121u_int stat_imask = SWI_CLOCK_MASK;
122#ifdef TIMER_FREQ

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

172static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
173#ifdef PC98
174static void rtc_serialcombit __P((int));
175static void rtc_serialcom __P((int));
176static int rtc_inb __P((void));
177static void rtc_outb __P((int));
178#endif
179
179#if defined(I586_CPU) || defined(I686_CPU)
180#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
180static void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq);
181#endif
182static void set_timer_freq(u_int freq, int intr_freq);
183
184static void
185clkintr(struct clockframe frame)
186{
187 timer_func(&frame);

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

689 }
690
691 /* Start keeping track of the i8254 counter. */
692 prev_count = getit();
693 if (prev_count == 0 || prev_count > timer0_max_count)
694 goto fail;
695 tot_count = 0;
696
181static void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq);
182#endif
183static void set_timer_freq(u_int freq, int intr_freq);
184
185static void
186clkintr(struct clockframe frame)
187{
188 timer_func(&frame);

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

690 }
691
692 /* Start keeping track of the i8254 counter. */
693 prev_count = getit();
694 if (prev_count == 0 || prev_count > timer0_max_count)
695 goto fail;
696 tot_count = 0;
697
697#if defined(I586_CPU) || defined(I686_CPU)
698#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
698 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
699 wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
700#endif
701
702 /*
703 * Wait for the mc146818A seconds counter to change. Read the i8254
704 * counter for each iteration since this is convenient and only
705 * costs a few usec of inaccuracy. The timing of the final reads

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

722 tot_count += prev_count - count;
723 prev_count = count;
724 if (sec != start_sec)
725 break;
726 if (--timeout == 0)
727 goto fail;
728 }
729
699 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
700 wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
701#endif
702
703 /*
704 * Wait for the mc146818A seconds counter to change. Read the i8254
705 * counter for each iteration since this is convenient and only
706 * costs a few usec of inaccuracy. The timing of the final reads

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

723 tot_count += prev_count - count;
724 prev_count = count;
725 if (sec != start_sec)
726 break;
727 if (--timeout == 0)
728 goto fail;
729 }
730
730#if defined(I586_CPU) || defined(I686_CPU)
731#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
731 /*
732 * Read the cpu cycle counter. The timing considerations are
733 * similar to those for the i8254 clock.
734 */
735 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) {
736 set_i586_ctr_freq((u_int)rdtsc(), tot_count);
737 if (bootverbose)
738 printf("i586 clock: %u Hz, ", i586_ctr_freq);

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

827 freq = timer_freq;
828#endif
829 timer_freq = freq;
830 } else {
831 if (bootverbose)
832 printf(
833 "%d Hz differs from default of %d Hz by more than 1%%\n",
834 freq, timer_freq);
732 /*
733 * Read the cpu cycle counter. The timing considerations are
734 * similar to those for the i8254 clock.
735 */
736 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) {
737 set_i586_ctr_freq((u_int)rdtsc(), tot_count);
738 if (bootverbose)
739 printf("i586 clock: %u Hz, ", i586_ctr_freq);

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

828 freq = timer_freq;
829#endif
830 timer_freq = freq;
831 } else {
832 if (bootverbose)
833 printf(
834 "%d Hz differs from default of %d Hz by more than 1%%\n",
835 freq, timer_freq);
835#if defined(I586_CPU) || defined(I686_CPU)
836#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
836 i586_ctr_freq = 0;
837#endif
838 }
839#endif
840
841 set_timer_freq(timer_freq, hz);
842
837 i586_ctr_freq = 0;
838#endif
839 }
840#endif
841
842 set_timer_freq(timer_freq, hz);
843
843#if defined(I586_CPU) || defined(I686_CPU)
844#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
844#ifndef CLK_USE_I586_CALIBRATION
845 if (i586_ctr_freq != 0) {
846 if (bootverbose)
847 printf(
848"CLK_USE_I586_CALIBRATION not specified - using old calibration method\n");
849 i586_ctr_freq = 0;
850 }
851#endif

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

1118 writertc(RTC_MONTH, bin2bcd(m + 1)); /* Write back Month */
1119 writertc(RTC_DAY, bin2bcd(tm + 1)); /* Write back Month Day */
1120
1121 /* Reenable RTC updates and interrupts. */
1122 writertc(RTC_STATUSB, rtc_statusb);
1123#endif
1124}
1125
845#ifndef CLK_USE_I586_CALIBRATION
846 if (i586_ctr_freq != 0) {
847 if (bootverbose)
848 printf(
849"CLK_USE_I586_CALIBRATION not specified - using old calibration method\n");
850 i586_ctr_freq = 0;
851 }
852#endif

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

1119 writertc(RTC_MONTH, bin2bcd(m + 1)); /* Write back Month */
1120 writertc(RTC_DAY, bin2bcd(tm + 1)); /* Write back Month Day */
1121
1122 /* Reenable RTC updates and interrupts. */
1123 writertc(RTC_STATUSB, rtc_statusb);
1124#endif
1125}
1126
1127#if defined(APIC_IO)
1128
1129/* from icu.s: */
1130extern u_int hwisrs[];
1131extern void vec8254 __P((void));
1132extern void vecRTC __P((void));
1133extern u_int ivectors[];
1134extern u_int Xintr8254;
1135extern u_int XintrRTC;
1136extern u_int mask8254;
1137extern u_int maskRTC;
1138
1139#endif /* APIC_IO */
1140
1126/*
1127 * Start both clocks running.
1128 */
1129void
1130cpu_initclocks()
1131{
1141/*
1142 * Start both clocks running.
1143 */
1144void
1145cpu_initclocks()
1146{
1147#if defined(APIC_IO)
1148 int x;
1149#endif /* APIC_IO */
1132#ifndef PC98
1133 int diag;
1134
1135 if (statclock_disable) {
1136 /*
1137 * The stat interrupt mask is different without the
1138 * statistics clock. Also, don't set the interrupt
1139 * flag which would normally cause the RTC to generate

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

1144 } else {
1145 /* Setting stathz to nonzero early helps avoid races. */
1146 stathz = RTC_NOPROFRATE;
1147 profhz = RTC_PROFRATE;
1148 }
1149#endif
1150
1151 /* Finish initializing 8253 timer 0. */
1150#ifndef PC98
1151 int diag;
1152
1153 if (statclock_disable) {
1154 /*
1155 * The stat interrupt mask is different without the
1156 * statistics clock. Also, don't set the interrupt
1157 * flag which would normally cause the RTC to generate

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

1162 } else {
1163 /* Setting stathz to nonzero early helps avoid races. */
1164 stathz = RTC_NOPROFRATE;
1165 profhz = RTC_PROFRATE;
1166 }
1167#endif
1168
1169 /* Finish initializing 8253 timer 0. */
1170#if defined(APIC_IO)
1171 /* 8254 is traditionally on ISA IRQ0 */
1172 if ((x = get_isa_apic_irq(0)) < 0) {
1173 /*
1174 * bummer, this mb doesn't have the 8254 on ISA irq0,
1175 * perhaps it's on the EISA bus...
1176 */
1177 if ((x = get_eisa_apic_irq(0)) < 0) {
1178 /* double bummer, attempt to redirect thru the 8259 */
1179 if (bootverbose)
1180 printf("APIC missing 8254 connection\n");
1181
1182 /* allow 8254 timer to INTerrupt 8259 */
1183#if !defined(IO_ICU1)
1184#ifdef PC98
1185#define IO_ICU1 0x00
1186#else
1187#define IO_ICU1 0x20
1188#endif
1189#endif
1190 x = inb(IO_ICU1 + 1); /* current mask in 8259 */
1191 x &= ~1; /* clear 8254 timer mask */
1192 outb(IO_ICU1 + 1, x); /* write new mask */
1193
1194 /* program IO APIC for type 3 INT on INT0 */
1195 if (ext_int_setup(0, 0) < 0)
1196 panic("8254 redirect impossible!");
1197 x = 0; /* 8259 is on 0 */
1198 }
1199 }
1200
1201 hwisrs[x] = (u_int)vec8254;
1202 Xintr8254 = (u_int)ivectors[x]; /* XXX might need Xfastintr# */
1203 mask8254 = (1 << x);
1204 register_intr(/* irq */ x, /* XXX id */ 0, /* flags */ 0,
1205 /* XXX */ (inthand2_t *)clkintr, &clk_imask,
1206 /* unit */ 0);
1207 INTREN(mask8254);
1208#else
1152 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
1153 /* XXX */ (inthand2_t *)clkintr, &clk_imask,
1154 /* unit */ 0);
1155 INTREN(IRQ0);
1209 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
1210 /* XXX */ (inthand2_t *)clkintr, &clk_imask,
1211 /* unit */ 0);
1212 INTREN(IRQ0);
1156#if defined(I586_CPU) || defined(I686_CPU)
1213#endif /* APIC_IO */
1214#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
1157 /*
1158 * Finish setting up anti-jitter measures.
1159 */
1160 if (i586_ctr_freq != 0)
1161 i586_ctr_bias = rdtsc();
1162#endif
1163
1164#ifndef PC98
1165 /* Initialize RTC. */
1166 writertc(RTC_STATUSA, rtc_statusa);
1167 writertc(RTC_STATUSB, RTCSB_24HR);
1168
1169 /* Don't bother enabling the statistics clock. */
1170 if (statclock_disable)
1171 return;
1172 diag = rtcin(RTC_DIAG);
1173 if (diag != 0)
1174 printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
1215 /*
1216 * Finish setting up anti-jitter measures.
1217 */
1218 if (i586_ctr_freq != 0)
1219 i586_ctr_bias = rdtsc();
1220#endif
1221
1222#ifndef PC98
1223 /* Initialize RTC. */
1224 writertc(RTC_STATUSA, rtc_statusa);
1225 writertc(RTC_STATUSB, RTCSB_24HR);
1226
1227 /* Don't bother enabling the statistics clock. */
1228 if (statclock_disable)
1229 return;
1230 diag = rtcin(RTC_DIAG);
1231 if (diag != 0)
1232 printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
1233#if defined(APIC_IO)
1234 /* RTC is traditionally on ISA IRQ8 */
1235 if ((x = get_isa_apic_irq(8)) < 0) {
1236 if ((x = get_eisa_apic_irq(8)) < 0) {
1237 panic("APIC missing RTC connection");
1238 }
1239 }
1240
1241 hwisrs[x] = (u_int)vecRTC;
1242 XintrRTC = (u_int)ivectors[x]; /* XXX might need Xfastintr# */
1243 maskRTC = (1 << x);
1244 register_intr(/* irq */ x, /* XXX id */ 1, /* flags */ 0,
1245 /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
1246 /* unit */ 0);
1247 INTREN(maskRTC);
1248#else
1175 register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
1176 /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
1177 /* unit */ 0);
1178 INTREN(IRQ8);
1249 register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
1250 /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
1251 /* unit */ 0);
1252 INTREN(IRQ8);
1253#endif /* APIC_IO */
1179 writertc(RTC_STATUSB, rtc_statusb);
1180#endif
1254 writertc(RTC_STATUSB, rtc_statusb);
1255#endif
1256
1257#if defined(APIC_IO)
1258 printf("Enabled INTs: ");
1259 for (x = 0; x < 24; ++x)
1260 if ((imen & (1 << x)) == 0)
1261 printf("%d, ", x);
1262 printf("imen: 0x%08x\n", imen);
1263#endif /* APIC_IO */
1181}
1182
1183void
1184setstatclockrate(int newhz)
1185{
1186#ifndef PC98
1187 if (newhz == RTC_PROFRATE)
1188 rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;

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

1203 * is is too generic. Should use it everywhere.
1204 */
1205 freq = timer_freq;
1206 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
1207 if (error == 0 && req->newptr != NULL) {
1208 if (timer0_state != 0)
1209 return (EBUSY); /* too much trouble to handle */
1210 set_timer_freq(freq, hz);
1264}
1265
1266void
1267setstatclockrate(int newhz)
1268{
1269#ifndef PC98
1270 if (newhz == RTC_PROFRATE)
1271 rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;

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

1286 * is is too generic. Should use it everywhere.
1287 */
1288 freq = timer_freq;
1289 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
1290 if (error == 0 && req->newptr != NULL) {
1291 if (timer0_state != 0)
1292 return (EBUSY); /* too much trouble to handle */
1293 set_timer_freq(freq, hz);
1211#if defined(I586_CPU) || defined(I686_CPU)
1294#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
1212 set_i586_ctr_freq(i586_ctr_freq, timer_freq);
1213#endif
1214 }
1215 return (error);
1216}
1217
1218SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
1219 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
1220
1295 set_i586_ctr_freq(i586_ctr_freq, timer_freq);
1296#endif
1297 }
1298 return (error);
1299}
1300
1301SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
1302 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
1303
1221#if defined(I586_CPU) || defined(I686_CPU)
1304#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
1222static void
1223set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq)
1224{
1225 u_int comultiplier, multiplier;
1226 u_long ef;
1227
1228 if (i586_freq == 0) {
1229 i586_ctr_freq = i586_freq;

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

1252 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
1253 if (error == 0 && req->newptr != NULL)
1254 set_i586_ctr_freq(freq, timer_freq);
1255 return (error);
1256}
1257
1258SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
1259 0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
1305static void
1306set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq)
1307{
1308 u_int comultiplier, multiplier;
1309 u_long ef;
1310
1311 if (i586_freq == 0) {
1312 i586_ctr_freq = i586_freq;

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

1335 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
1336 if (error == 0 && req->newptr != NULL)
1337 set_i586_ctr_freq(freq, timer_freq);
1338 return (error);
1339}
1340
1341SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
1342 0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
1260#endif /* defined(I586_CPU) || defined(I686_CPU) */
1343#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */