Return to BSD News archive
Newsgroups: comp.os.386bsd.bugs Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!elroy.jpl.nasa.gov!sdd.hp.com!crash!fpm From: fpm@crash.cts.com (Frank Maclachlan) Subject: [NetBSD-0.8] Patch for kernel DELAY function Organization: CTS Network Services (crash, ctsnet), El Cajon, CA Date: 24 May 93 12:04:02 PDT Message-ID: <1993May24.120402.23222@crash> Keywords: patch NetBSD Lines: 108 I hope that this is the correct group for this. It was pointed out quite a while ago that the 386bsd kernel DELAY() function didn't seem to work properly. In particular, the line highlighted below: /* * Wait "n" microseconds. Relies on timer 0 to have 1Mhz clock, regardless * of processor board speed. Note: timer had better have been programmed * before this is first used! */ DELAY(n) { int tick = getit(0,0) & 1; while (n--) { /* wait approximately 1 micro second */ while (tick == getit(0,0) & 1) ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tick = getit(0,0) & 1; } } should really be: while (tick == (getit(0,0) & 1)) ; This, however, causes the system to lock up when DELAY() is called. The problem is that the processor is not fast enough to poll micro- second events in this fashion. The original DELAY() is highly processor speed dependent (uncalibrated software delay loop). I replaced the DELAY() function in my NetBSD-0.8 system w/ a micro- second delay routine based upon the calibrated spinwait() millisecond delay routine Julian Elischer added to clock.c. The new DELAY() is reasonably accurate and *IS* CPU speed independent. A patch to the NetBSD-0.8 files is included below. The relevant files are in /sys/i386/isa/. ==================== Cut here =================== *** clock.c.ORIG Tue Mar 23 00:12:10 1993 --- clock.c Mon May 24 10:52:10 1993 *************** *** 261,263 **** --- 261,283 ---- ; } + + /* + * Delay approximately `usec' microseconds. Uses delaycount + * variable set up by findcpuspeed(). + */ + DELAY(usec) + int usec; + { + int msec, i; + + /* Use spinwait() if delaying more than a millisecond. */ + msec = usec / 1000; + if (msec > 0) + spinwait(msec); + + /* Now delay for remaining usecs. */ + usec = ((usec % 1000) * delaycount) / 1000; + for (i = 0; i < usec; i++) + ; + } *** isa.c.ORIG Fri Apr 9 09:24:12 1993 --- isa.c Mon May 24 11:01:45 1993 *************** *** 531,560 **** log(LOG_CRIT,"Too many ISA strayintr not logging any more\n"); } - /* - * Wait "n" microseconds. Relies on timer 0 to have 1Mhz clock, regardless - * of processor board speed. Note: timer had better have been programmed - * before this is first used! - */ - DELAY(n) { - int tick = getit(0,0) & 1; - - while (n--) { - /* wait approximately 1 micro second */ - while (tick == getit(0,0) & 1) ; - - tick = getit(0,0) & 1; - } - } - - getit(unit, timer) { - int port = (unit ? IO_TIMER2 : IO_TIMER1) + timer, val; - - val = inb(port); - val = (inb(port) << 8) + val; - return (val); - } - extern int hz; static beeping; --- 531,536 ---- ==================== Cut here =================== -- UUCP: {hplabs!hp-sdd ucsd nosc}!crash!fpm INET: fpm@crash.cts.com