tsc.c (1407) | tsc.c (1442) |
---|---|
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.7 1994/04/21 14:19:16 sos Exp $ | 37 * $Id: clock.c,v 1.6 1994/02/06 22:48:13 davidg Exp $ |
38 */ 39 40/* 41 * Primitive clock interrupt routines. 42 */ 43#include "param.h" 44#include "systm.h" 45#include "time.h" --- 8 unchanged lines hidden (view full) --- 54/* X-tals being what they are, it's nice to be able to fudge this one... */ 55/* Note, the name changed here from XTALSPEED to TIMER_FREQ rgrimes 4/26/93 */ 56#ifndef TIMER_FREQ 57#define TIMER_FREQ 1193182 /* XXX - should be in isa.h */ 58#endif 59#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 60 61void hardclock(); | 38 */ 39 40/* 41 * Primitive clock interrupt routines. 42 */ 43#include "param.h" 44#include "systm.h" 45#include "time.h" --- 8 unchanged lines hidden (view full) --- 54/* X-tals being what they are, it's nice to be able to fudge this one... */ 55/* Note, the name changed here from XTALSPEED to TIMER_FREQ rgrimes 4/26/93 */ 56#ifndef TIMER_FREQ 57#define TIMER_FREQ 1193182 /* XXX - should be in isa.h */ 58#endif 59#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 60 61void hardclock(); |
62static void findcpuspeed(void); | 62static int beeping; 63int timer0_divisor = TIMER_DIV(100); /* XXX should be hz */ 64u_int timer0_prescale; 65static char timer0_state = 0, timer2_state = 0; 66static char timer0_reprogram = 0; 67static void (*timer_func)() = hardclock; 68static void (*new_function)(); 69static u_int new_rate; 70static u_int hardclock_divisor; |
63 | 71 |
64static char timer0_in_use = 0, timer2_in_use = 0; 65static int timer0_rate = 100; /* XXX should be hz */ 66static void (*timer_func)() = hardclock; 67static unsigned int prescale = 0; 68static unsigned int hardclock_prescale; 69static int beeping; 70unsigned int delaycount; /* calibrated loop variable (1 millisecond) */ | |
71 | 72 |
72 | |
73void 74timerintr(struct intrframe frame) 75{ 76 timer_func(frame); | 73void 74timerintr(struct intrframe frame) 75{ 76 timer_func(frame); |
77 if (timer0_in_use) 78 if (prescale++ >= hardclock_prescale) { | 77 switch (timer0_state) { 78 case 0: 79 break; 80 case 1: 81 if ((timer0_prescale+=timer0_divisor) >= hardclock_divisor) { |
79 hardclock(frame); | 82 hardclock(frame); |
80 prescale = 0; | 83 timer0_prescale = 0; |
81 } | 84 } |
85 break; 86 case 2: 87 disable_intr(); 88 outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); 89 outb(TIMER_CNTR0, TIMER_DIV(new_rate)%256); 90 outb(TIMER_CNTR0, TIMER_DIV(new_rate)/256); 91 enable_intr(); 92 timer0_divisor = TIMER_DIV(new_rate); 93 timer0_prescale = 0; 94 timer_func = new_function; 95 timer0_state = 1; 96 break; 97 case 3: 98 if ((timer0_prescale+=timer0_divisor) >= hardclock_divisor) { 99 hardclock(frame); 100 disable_intr(); 101 outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); 102 outb(TIMER_CNTR0, TIMER_DIV(hz)%256); 103 outb(TIMER_CNTR0, TIMER_DIV(hz)/256); 104 enable_intr(); 105 timer0_divisor = TIMER_DIV(hz); 106 timer0_prescale = 0; 107 timer_func = hardclock;; 108 timer0_state = 0; 109 } 110 break; 111 } |
|
82} 83 84 85int 86acquire_timer0(int rate, void (*function)() ) 87{ | 112} 113 114 115int 116acquire_timer0(int rate, void (*function)() ) 117{ |
88#ifndef INACCURATE_MICROTIME_IS_OK 89 return -1; 90#else 91 if (timer0_in_use) /* XXX || (rate < 20000 && rate % hz)) */ | 118 if (timer0_state || !function) |
92 return -1; | 119 return -1; |
93 timer0_in_use = 1; 94 timer0_rate = rate; 95 prescale = 0; 96 hardclock_prescale = rate/hz; 97 outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); 98 outb(TIMER_CNTR0, TIMER_DIV(rate)%256); 99 outb(TIMER_CNTR0, TIMER_DIV(rate)/256); 100 if (function) 101 timer_func = function; | 120 121 new_function = function; 122 new_rate = rate; 123 timer0_state = 2; |
102 return 0; | 124 return 0; |
103#endif | |
104} 105 106 107int 108acquire_timer2(int mode) 109{ | 125} 126 127 128int 129acquire_timer2(int mode) 130{ |
110 if (timer2_in_use) | 131 if (timer2_state) |
111 return -1; | 132 return -1; |
112 timer2_in_use = 1; | 133 timer2_state = 1; |
113 outb(TIMER_MODE, TIMER_SEL2 | (mode &0x3f)); 114 return 0; 115} 116 117 118int 119release_timer0() 120{ | 134 outb(TIMER_MODE, TIMER_SEL2 | (mode &0x3f)); 135 return 0; 136} 137 138 139int 140release_timer0() 141{ |
121 if (!timer0_in_use) | 142 if (!timer0_state) |
122 return -1; | 143 return -1; |
123 timer0_in_use = 0; 124 timer0_rate = hz; 125 outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); 126 outb(TIMER_CNTR0, TIMER_DIV(hz)%256); 127 outb(TIMER_CNTR0, TIMER_DIV(hz)/256); 128 timer_func = hardclock; | 144 timer0_state = 3; |
129 return 0; 130} 131 132 133int 134release_timer2() 135{ | 145 return 0; 146} 147 148 149int 150release_timer2() 151{ |
136 if (!timer2_in_use) | 152 if (!timer2_state) |
137 return -1; | 153 return -1; |
138 timer2_in_use = 0; | 154 timer2_state = 0; |
139 outb(TIMER_MODE, TIMER_SEL2|TIMER_SQWAVE|TIMER_16BIT); 140 return 0; 141} 142 143 144static int 145getit() 146{ 147 int high, low; 148 149 disable_intr(); | 155 outb(TIMER_MODE, TIMER_SEL2|TIMER_SQWAVE|TIMER_16BIT); 156 return 0; 157} 158 159 160static int 161getit() 162{ 163 int high, low; 164 165 disable_intr(); |
150 | |
151 /* select timer0 and latch counter value */ 152 outb(TIMER_MODE, TIMER_SEL0); 153 low = inb(TIMER_CNTR0); 154 high = inb(TIMER_CNTR0); 155 enable_intr(); 156 return ((high << 8) | low); 157} 158 --- 37 unchanged lines hidden (view full) --- 196 */ 197 sec = n / 1000000; 198 usec = n - sec * 1000000; 199 ticks_left = sec * TIMER_FREQ 200 + usec * (TIMER_FREQ / 1000000) 201 + usec * ((TIMER_FREQ % 1000000) / 1000) / 1000 202 + usec * (TIMER_FREQ % 1000) / 1000000; 203 | 166 /* select timer0 and latch counter value */ 167 outb(TIMER_MODE, TIMER_SEL0); 168 low = inb(TIMER_CNTR0); 169 high = inb(TIMER_CNTR0); 170 enable_intr(); 171 return ((high << 8) | low); 172} 173 --- 37 unchanged lines hidden (view full) --- 211 */ 212 sec = n / 1000000; 213 usec = n - sec * 1000000; 214 ticks_left = sec * TIMER_FREQ 215 + usec * (TIMER_FREQ / 1000000) 216 + usec * ((TIMER_FREQ % 1000000) / 1000) / 1000 217 + usec * (TIMER_FREQ % 1000) / 1000000; 218 |
204 counter_limit = TIMER_FREQ/timer0_rate; | |
205 while (ticks_left > 0) { 206 tick = getit(0, 0); 207#ifdef DELAYDEBUG 208 ++getit_calls; 209#endif 210 if (tick > prev_tick) | 219 while (ticks_left > 0) { 220 tick = getit(0, 0); 221#ifdef DELAYDEBUG 222 ++getit_calls; 223#endif 224 if (tick > prev_tick) |
211 ticks_left -= prev_tick - (tick - counter_limit); | 225 ticks_left -= prev_tick - (tick - timer0_divisor); |
212 else 213 ticks_left -= prev_tick - tick; 214 prev_tick = tick; 215 } 216#ifdef DELAYDEBUG 217 if (state == 1) 218 printf(" %d calls to getit() at %d usec each\n", 219 getit_calls, (n + 5) / getit_calls); 220#endif 221} 222 223 224static void | 226 else 227 ticks_left -= prev_tick - tick; 228 prev_tick = tick; 229 } 230#ifdef DELAYDEBUG 231 if (state == 1) 232 printf(" %d calls to getit() at %d usec each\n", 233 getit_calls, (n + 5) / getit_calls); 234#endif 235} 236 237 238static void |
225sysbeepstop() /* SOS XXX dummy is not needed */ | 239sysbeepstop() |
226{ 227 outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ 228 release_timer2(); 229 beeping = 0; 230} 231 232 233int 234sysbeep(int pitch, int period) 235{ 236 237 if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) 238 return -1; | 240{ 241 outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ 242 release_timer2(); 243 beeping = 0; 244} 245 246 247int 248sysbeep(int pitch, int period) 249{ 250 251 if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) 252 return -1; |
253 disable_intr(); |
|
239 outb(TIMER_CNTR2, pitch); 240 outb(TIMER_CNTR2, (pitch>>8)); | 254 outb(TIMER_CNTR2, pitch); 255 outb(TIMER_CNTR2, (pitch>>8)); |
256 enable_intr(); |
|
241 if (!beeping) { 242 outb(IO_PPI, inb(IO_PPI) | 3); /* enable counter2 output to speaker */ 243 beeping = period; 244 timeout(sysbeepstop, 0, period); 245 } 246 return 0; 247} 248 249 250void 251startrtclock() 252{ 253 int s; 254 | 257 if (!beeping) { 258 outb(IO_PPI, inb(IO_PPI) | 3); /* enable counter2 output to speaker */ 259 beeping = period; 260 timeout(sysbeepstop, 0, period); 261 } 262 return 0; 263} 264 265 266void 267startrtclock() 268{ 269 int s; 270 |
255 findcpuspeed(); /* use the clock (while it's free) 256 to find the cpu speed */ | |
257 /* initialize 8253 clock */ 258 outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); 259 260 /* Correct rounding will buy us a better precision in timekeeping */ 261 outb (IO_TIMER1, TIMER_DIV(hz)%256); 262 outb (IO_TIMER1, TIMER_DIV(hz)/256); | 271 /* initialize 8253 clock */ 272 outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); 273 274 /* Correct rounding will buy us a better precision in timekeeping */ 275 outb (IO_TIMER1, TIMER_DIV(hz)%256); 276 outb (IO_TIMER1, TIMER_DIV(hz)/256); |
263 timer0_rate = hz; | 277 timer0_divisor = hardclock_divisor = TIMER_DIV(hz); |
264 265 /* initialize brain-dead battery powered clock */ 266 outb (IO_RTC, RTC_STATUSA); 267 outb (IO_RTC+1, 0x26); 268 outb (IO_RTC, RTC_STATUSB); 269 outb (IO_RTC+1, 2); 270 271 outb (IO_RTC, RTC_DIAG); 272 if (s = inb (IO_RTC+1)) 273 printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); 274} 275 276 | 278 279 /* initialize brain-dead battery powered clock */ 280 outb (IO_RTC, RTC_STATUSA); 281 outb (IO_RTC+1, 0x26); 282 outb (IO_RTC, RTC_STATUSB); 283 outb (IO_RTC+1, 2); 284 285 outb (IO_RTC, RTC_DIAG); 286 if (s = inb (IO_RTC+1)) 287 printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); 288} 289 290 |
277#define FIRST_GUESS 0x2000 278static void 279findcpuspeed() 280{ 281 unsigned char low; 282 unsigned int remainder; 283 284 /* Put counter in count down mode */ 285 outb(TIMER_MODE, TIMER_16BIT|TIMER_RATEGEN); 286 outb(IO_TIMER1, 0xff); 287 outb(IO_TIMER1, 0xff); 288 delaycount = FIRST_GUESS; 289 spinwait(1); 290 /* Read the value left in the counter */ 291 low = inb(IO_TIMER1); /* least siginifcant */ 292 remainder = inb(IO_TIMER1); /* most significant */ 293 remainder = (remainder<<8) + low ; 294 /* Formula for delaycount is : 295 * (loopcount * timer clock speed)/ (counter ticks * 1000) 296 */ 297 delaycount = (FIRST_GUESS * (TIMER_FREQ/1000)) / (0xffff-remainder); 298} 299 300 | |
301/* convert 2 digit BCD number */ 302int 303bcd(int i) 304{ 305 return ((i/16)*10 + (i%16)); 306} 307 308 --- 54 unchanged lines hidden (view full) --- 363 /* ready for a read? */ 364 while ((sa&RTCSA_TUP) == RTCSA_TUP) 365 sa = rtcin(RTC_STATUSA); 366 367 sec = bcd(rtcin(RTC_YEAR)) + 1900; 368 if (sec < 1970) 369 sec += 100; 370 | 291/* convert 2 digit BCD number */ 292int 293bcd(int i) 294{ 295 return ((i/16)*10 + (i%16)); 296} 297 298 --- 54 unchanged lines hidden (view full) --- 353 /* ready for a read? */ 354 while ((sa&RTCSA_TUP) == RTCSA_TUP) 355 sa = rtcin(RTC_STATUSA); 356 357 sec = bcd(rtcin(RTC_YEAR)) + 1900; 358 if (sec < 1970) 359 sec += 100; 360 |
371 leap = !(sec % 4); sec = ytos(sec); /* year */ | 361 leap = !(sec % 4); sec = ytos(sec); /* year */ |
372 yd = mtos(bcd(rtcin(RTC_MONTH)),leap); sec+=yd; /* month */ 373 t = (bcd(rtcin(RTC_DAY))-1) * 24*60*60; sec+=t; yd+=t; /* date */ 374 day_week = rtcin(RTC_WDAY); /* day */ 375 sec += bcd(rtcin(RTC_HRS)) * 60*60; /* hour */ 376 sec += bcd(rtcin(RTC_MIN)) * 60; /* minutes */ 377 sec += bcd(rtcin(RTC_SEC)); /* seconds */ 378 sec += tz.tz_minuteswest * 60; 379 time.tv_sec = sec; --- 61 unchanged lines hidden --- | 362 yd = mtos(bcd(rtcin(RTC_MONTH)),leap); sec+=yd; /* month */ 363 t = (bcd(rtcin(RTC_DAY))-1) * 24*60*60; sec+=t; yd+=t; /* date */ 364 day_week = rtcin(RTC_WDAY); /* day */ 365 sec += bcd(rtcin(RTC_HRS)) * 60*60; /* hour */ 366 sec += bcd(rtcin(RTC_MIN)) * 60; /* minutes */ 367 sec += bcd(rtcin(RTC_SEC)); /* seconds */ 368 sec += tz.tz_minuteswest * 60; 369 time.tv_sec = sec; --- 61 unchanged lines hidden --- |