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) */ |