Subject: new pc532 NetBSD kernel microtime() function
To: None <port-pc532@NetBSD.ORG>
From: Phil Budne <budd@cs.bu.edu>
List: port-pc532
Date: 05/31/1996 03:41:09
While trying to characterize the software interrupt latency I'm seeing
in my pc532 serial driver, I decided to hack at the microtime function
(used for gettimeofday) to get better resolution.  It turns out that
the ICU counter ticks almost every microsecond.  Here are my diffs
thus far.  I'm sure it can be improved.

*** /netbsd/usr/src/sys/arch/pc532/pc532/machdep.c	Sat May  4 07:48:43 1996
--- ./machdep.c	Fri May 31 03:27:11 1996
***************
*** 84,93 ****
--- 84,94 ----
  #include <machine/cpu.h>
  #include <machine/cpufunc.h>
  #include <machine/psl.h>
  #include <machine/fpu.h>
  #include <machine/pmap.h>
+ #include <machine/icu.h>
  
  /*
   * Support for VERY low debugging ... in case we get NO output.
   * e.g. in case pmap does not work and can't do regular mapped
   * output. In this case use umprintf to display debug messages.
***************
*** 739,760 ****
  	}
  	printf("\n\n");
  	DELAY(5000000);		/* 5 seconds */
  }
  
  void
  microtime(tvp)
  	register struct timeval *tvp;
  {
! 	int s = splhigh();
  
  	*tvp = time;
! 	tvp->tv_usec += tick;
! 	splx(s);
! 	while (tvp->tv_usec > 1000000) {
! 		tvp->tv_sec++;
  		tvp->tv_usec -= 1000000;
  	}
  }
  
  /*
   * Clear registers on exec
--- 740,787 ----
  	}
  	printf("\n\n");
  	DELAY(5000000);		/* 5 seconds */
  }
  
+ /*
+  * new version 5/96 -phil budne
+  * + do direct sets of MCTL?
+  * + ipend set when delta 9999??
+  * + recode in asm??
+  */
+ 
  void
  microtime(tvp)
  	register struct timeval *tvp;
  {
! 	u_short count, delta, ipend;
  
+ 	di();
+ 	ICUB(MCTL) |= 0x88;		/* freeze HCCV, IPND */
+ 	count = ICUW(HCCV);
+ 	ipend = ICUW(IPND);
  	*tvp = time;
! 	ICUB(MCTL) &= 0x77;		/* thaw ICU regs */
! 	ei();
! 
! 	/* yields value 0..9999 */
! #if defined(HZ) && HZ != 100
! 	/* suspect: should work for default, but doesn't? */
! 	delta = (((ICU_CLK_HZ/HZ)-count) * (4096*1000000UL/ICU_CLK_HZ)) >> 12;
! #else
! 	delta = ((9216-count) * 4444L) >> 12;
! #endif
! 
! 	tvp->tv_usec += delta;
! 
! 	/* check for timer overflow (ie; clock int disabled) */
! 	if (ipend & (1<<IR_CLK)) {
! 	    tvp->tv_usec += tick;
! 	    if (tvp->tv_usec > 1000000) {
  		tvp->tv_usec -= 1000000;
+ 		tvp->tv_sec++;
+ 	    }
  	}
  }
  
  /*
   * Clear registers on exec