Subject: timecounters for shark
To: None <port-shark@netbsd.org>
From: Garrett D'Amore <garrett_damore@tadpole.com>
List: port-arm
Date: 09/12/2006 10:54:00
This is a multi-part message in MIME format.
--------------010602090705070208040709
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
The following patch converts shark to use the i8253 timer as a
timecounter. I'd appreciate a quick review. It was tested by pooka@,
and seems to work.
I've not included the change to types.h to add #define
__HAVE_TIMECOUNTER, but you need that, too. (Mostly not here because my
kernel includes _both_ that and the __HAVE_GENERIC_TODR from the
time-of-day changes I posted earlier. :-)
Once someone gives me the go-ahead, I'll commit. Hopefully it won't
take too long for someone to just bless these changes.
--
Garrett D'Amore, Principal Software Engineer
Tadpole Computer / Computing Technologies Division,
General Dynamics C4 Systems
http://www.tadpolecomputer.com/
Phone: 951 325-2134 Fax: 951 325-2191
--------------010602090705070208040709
Content-Type: text/x-patch;
name="shark_clock.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="shark_clock.diff"
Index: sys/arch/shark/isa/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/shark/isa/clock.c,v
retrieving revision 1.12
diff -d -p -u -r1.12 clock.c
--- sys/arch/shark/isa/clock.c 12 Sep 2006 17:07:14 -0000 1.12
+++ sys/arch/shark/isa/clock.c 12 Sep 2006 17:52:06 -0000
@@ -159,6 +159,7 @@ __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/time.h>
+#include <sys/timetc.h>
#include <sys/kernel.h>
#include <sys/device.h>
@@ -181,10 +182,10 @@ void rtcinit(void);
int timer_hz_to_count(int);
static void findcpuspeed(void);
-static void init_isa_timer_tables(void);
static void delayloop(int);
static int clockintr(void *);
static int gettick(void);
+static void tc_init_i8253(void);
void startrtclock(void);
@@ -222,7 +223,6 @@ unsigned int count1024usec; /* calibrate
* time.tv_usec += isa_timer_msb_table[cnt_msb] + isa_timer_lsb_table[cnt_lsb];
*/
-u_short isa_timer_msb_table[256]; /* timer->usec MSB */
u_short isa_timer_lsb_table[256]; /* timer->usec conversion for LSB */
/* 64 bit counts from timer 0 */
@@ -273,8 +273,6 @@ startrtclock(void)
findcpuspeed(); /* use the clock (while it's free) to
find the CPU speed */
- init_isa_timer_tables();
-
timer0count.lo = 0;
timer0count.hi = 0;
timer0_at_last_clockintr.lo = 0;
@@ -293,38 +291,6 @@ startrtclock(void)
#endif
}
-static void
-init_isa_timer_tables(void)
-{
- int s;
- u_long t, msbmillion, quotient, remainder;
-
- for (s = 0; s < 256; s++) {
- /* LSB table is easy, just divide and round */
- t = ((u_long) s * 1000000 * 2) / TIMER_FREQ;
- isa_timer_lsb_table[s] = (u_short) ((t / 2) + (t & 0x1));
-
- msbmillion = s * 1000000;
- quotient = msbmillion / TIMER_FREQ;
- remainder = msbmillion % TIMER_FREQ;
- t = (remainder * 256 * 2) / TIMER_FREQ;
- isa_timer_msb_table[s] =
- (u_short)((t / 2) + (t & 1) + (quotient * 256));
-
-#ifdef DIAGNOSTIC
- if ((s > 0) &&
- (isa_timer_msb_table[s] <
- (isa_timer_msb_table[s - 1] + isa_timer_lsb_table[0xFF])))
- panic ("time tables not monotonic %d: %d < (%d + %d) = %d\n",
- s, isa_timer_msb_table[s],
- isa_timer_msb_table[s - 1],
- isa_timer_lsb_table[0xFF],
- isa_timer_msb_table[s - 1] +
- isa_timer_lsb_table[0xFF]);
-#endif
- } /* END for */
-}
-
int
timer_hz_to_count(int timer_hz)
{
@@ -555,16 +521,6 @@ cpu_initclocks(void)
(void)isa_intr_establish(NULL, IRQ_RTC, IST_LEVEL, IPL_CLOCK,
clockintr, 0);
- /* code for values of hz that don't divide 1000000 exactly */
- tickfix = 1000000 - (hz * tick);
- if (tickfix) {
- int ftp;
-
- ftp = min(ffs(tickfix), ffs(hz));
- tickfix >>= (ftp - 1);
- tickfixinterval = hz >> (ftp - 1);
- }
-
/* set up periodic interrupt @ hz
this is the subset of hz values in kern_clock.c that are
supported by the ISA RTC */
@@ -592,6 +548,8 @@ cpu_initclocks(void)
/* enable periodic interrupt */
mc146818_write(NULL, MC_REGB,
mc146818_read(NULL, MC_REGB) | MC_REGB_PIE);
+
+ tc_init_i8253();
}
void
@@ -613,78 +571,24 @@ setstatclockrate(int arg)
{
}
-/*
- * void microtime(struct timeval *tvp)
- *
- * Fill in the specified timeval struct with the current time
- * accurate to the microsecond.
- */
+static uint32_t
+i8253_get_timecount(struct timecounter *tc)
+{
+ return (TIMER0_ROLLOVER - gettick());
+}
void
-microtime(struct timeval *tvp)
+tc_init_i8253(void)
{
- int s;
- unsigned lsb, msb;
- int tm;
- static struct timeval oldtv;
- struct count64 timer0current;
- int ticks;
-
- s = splstatclock();
-
- gettimer0count(&timer0current);
-
- tm = time.tv_usec;
-
- /* unsigned arithmetic should take care of overflow */
- /* with a >= 32 Hz clock, ticks will always be < 0x7FFF */
- ticks = (int)((unsigned)
- (timer0current.lo - timer0_at_last_clockintr.lo));
-
-#ifdef DIAGNOSTIC
- if ((ticks < 0) || (ticks > 0xffff))
- printf("microtime bug: ticks = %x\n", ticks);
-#endif
-
- while (ticks > 0) {
-
- if (ticks < 0xffff) {
- msb = (ticks >> 8) & 0xFF;
- lsb = ticks & 0xFF;
- } else {
- msb = 0xff;
- lsb = 0xff;
- }
-
- /* see comments above */
- tm += isa_timer_msb_table[msb] + isa_timer_lsb_table[lsb];
-
- /* for a 64 Hz RTC, ticks will never overflow table */
- /* microtime will be less accurate if the RTC is < 36 Hz */
- ticks -= 0xffff;
- }
-
- tvp->tv_sec = time.tv_sec;
- if (tm >= 1000000) {
- tvp->tv_sec += 1;
- tm -= 1000000;
- }
-
- tvp->tv_usec = tm;
-
- /* Make sure the time has advanced. */
+ static struct timecounter i8253_tc = {
+ .tc_get_timecount = i8253_get_timecount,
+ .tc_counter_mask = TIMER0_ROLLOVER,
+ .tc_frequency = TIMER_FREQ,
+ .tc_name = "i8253",
+ .tc_quality = 100
+ };
- if (tvp->tv_sec == oldtv.tv_sec &&
- tvp->tv_usec <= oldtv.tv_usec) {
- tvp->tv_usec = oldtv.tv_usec + 1;
- if (tvp->tv_usec >= 1000000) {
- tvp->tv_usec -= 1000000;
- ++tvp->tv_sec;
- }
- }
-
- oldtv = *tvp;
- (void)splx(s);
+ tc_init(&i8253_tc);
}
/* End of clock.c */
--------------010602090705070208040709--