I wrote: > - we should ask Steve (scw@) first. > - IIRC some sources for old microtime(9) are shared with mvmeppc port > and in sys/dev/mvme so we should handle it too. > > Anyway I'll take a look after I'm back to my home. I'm still in my hometown, but I played with the sources via ssh: --- Index: arch/mvme68k/dev/clock_pcc.c =================================================================== RCS file: /cvsroot/src/sys/arch/mvme68k/dev/clock_pcc.c,v retrieving revision 1.16 diff -u -r1.16 clock_pcc.c --- arch/mvme68k/dev/clock_pcc.c 11 Dec 2005 12:18:17 -0000 1.16 +++ arch/mvme68k/dev/clock_pcc.c 4 Jan 2008 13:46:42 -0000 @@ -48,6 +48,7 @@ #include <sys/kernel.h> #include <sys/systm.h> #include <sys/device.h> +#include <sys/timetc.h> #include <machine/psl.h> #include <machine/bus.h> @@ -64,6 +65,7 @@ struct device sc_dev; struct clock_attach_args sc_clock_args; u_char sc_clock_lvl; + struct timecounter sc_tc; }; CFATTACH_DECL(clock_pcc, sizeof(struct clock_pcc_softc), @@ -75,10 +77,12 @@ static int clock_pcc_profintr __P((void *)); static int clock_pcc_statintr __P((void *)); static void clock_pcc_initclocks __P((void *, int, int)); -static long clock_pcc_microtime __P((void *)); static void clock_pcc_shutdown __P((void *)); +static uint32_t clock_pcc_getcount(struct timecounter *); static struct clock_pcc_softc *clock_pcc_sc; +static uint32_t clock_pcc_count; +static uint16_t clock_pcc_reload; /* ARGSUSED */ int @@ -122,7 +126,6 @@ clock_pcc_sc = sc; sc->sc_clock_args.ca_arg = sc; sc->sc_clock_args.ca_initfunc = clock_pcc_initclocks; - sc->sc_clock_args.ca_microtime = clock_pcc_microtime; /* Do common portions of clock config. */ clock_config(self, &sc->sc_clock_args, pccintr_evcnt(pa->pa_ipl)); @@ -148,6 +151,7 @@ pcc_reg_write16(sys_pcc, PCCREG_TMR1_PRELOAD, pcc_timer_us2lim(prof_us)); + clock_pcc_reload = pcc_timer_us2lim(prof_us); pcc_reg_write(sys_pcc, PCCREG_TMR1_CONTROL, PCC_TIMERCLEAR); pcc_reg_write(sys_pcc, PCCREG_TMR1_CONTROL, PCC_TIMERSTART); pcc_reg_write(sys_pcc, PCCREG_TMR1_INTR_CTRL, sc->sc_clock_lvl); @@ -157,20 +161,25 @@ pcc_reg_write(sys_pcc, PCCREG_TMR2_CONTROL, PCC_TIMERCLEAR); pcc_reg_write(sys_pcc, PCCREG_TMR2_CONTROL, PCC_TIMERSTART); pcc_reg_write(sys_pcc, PCCREG_TMR2_INTR_CTRL, sc->sc_clock_lvl); + + sc->sc_tc.tc_get_timecount = clock_pcc_getcount; + sc->sc_tc.tc_name = "pcc_count"; + sc->sc_tc.tc_frequency = PCC_TIMERFREQ; + sc->sc_tc.tc_quality = 100; + sc->sc_tc.tc_counter_mask = ~0; + tc_init(&sc->sc_tc); } /* ARGSUSED */ -long -clock_pcc_microtime(arg) - void *arg; +uint32_t +clock_pcc_getcount(struct timecounter *tc) { - static int ovfl_adj[] = { - 0, 10000, 20000, 30000, - 40000, 50000, 60000, 70000, - 80000, 90000, 100000, 110000, - 120000, 130000, 140000, 150000}; - u_int8_t cr; - u_int16_t tc, tc2; + uint32_t cnt; + uint16_t tc1, tc2; + uint8_t cr; + int s; + + s = splhigh(); /* * There's no way to latch the counter and overflow registers @@ -178,16 +187,22 @@ * race by checking for counter wrap-around and re-reading the * overflow counter if necessary. * - * Note: This only works because we're called at splhigh(). + * Note: This only works because we're at splhigh(). */ - tc = pcc_reg_read16(sys_pcc, PCCREG_TMR1_COUNT); + tc1 = pcc_reg_read16(sys_pcc, PCCREG_TMR1_COUNT); cr = pcc_reg_read(sys_pcc, PCCREG_TMR1_CONTROL); - if (tc > (tc2 = pcc_reg_read16(sys_pcc, PCCREG_TMR1_COUNT))) { + tc2 = pcc_reg_read16(sys_pcc, PCCREG_TMR1_COUNT); + if (tc1 > tc2) { cr = pcc_reg_read(sys_pcc, PCCREG_TMR1_CONTROL); - tc = tc2; + tc1 = tc2; } + cnt = clock_pcc_count; + splx(s); + /* XXX assume HZ = 100 */ + cnt += (tc1 - clock_pcc_reload) + + (PCC_TIMERFREQ / 100) * (cr >> PCC_TIMEROVFLSHIFT); - return ((long) pcc_timer_cnt2us(tc) + ovfl_adj[cr>>PCC_TIMEROVFLSHIFT]); + return cnt; } int @@ -208,8 +223,11 @@ clock_pcc_sc->sc_clock_lvl); splx(s); - for (cr >>= PCC_TIMEROVFLSHIFT; cr; cr--) + for (cr >>= PCC_TIMEROVFLSHIFT; cr; cr--) { + /* XXX assume HZ = 100 */ + clock_pcc_count += PCC_TIMERFREQ / 100; hardclock(frame); + } return (1); } Index: arch/mvme68k/dev/pccreg.h =================================================================== RCS file: /cvsroot/src/sys/arch/mvme68k/dev/pccreg.h,v retrieving revision 1.9 diff -u -r1.9 pccreg.h --- arch/mvme68k/dev/pccreg.h 12 Aug 2001 18:33:13 -0000 1.9 +++ arch/mvme68k/dev/pccreg.h 4 Jan 2008 13:46:42 -0000 @@ -154,16 +154,15 @@ */ #define PCC_TIMERACK 0x80 /* ack intr */ -#define PCC_TIMER100HZ 63936 /* load value for 100Hz */ #define PCC_TIMERCLEAR 0x0 /* reset and clear timer */ #define PCC_TIMERENABLE 0x1 /* Enable clock */ #define PCC_TIMERSTOP 0x3 /* stop clock, but don't clear it */ #define PCC_TIMERSTART 0x7 /* start timer */ #define PCC_TIMEROVFLSHIFT 4 -#define pcc_timer_hz2lim(hz) (65536 - (160000/(hz))) -#define pcc_timer_us2lim(us) (65536 - (160000/(1000000/(us)))) -#define pcc_timer_cnt2us(cnt) ((((cnt) - PCC_TIMER100HZ) * 25) / 4) +#define PCC_TIMERFREQ 160000 +#define pcc_timer_hz2lim(hz) (0x10000 - (PCC_TIMERFREQ/(hz))) +#define pcc_timer_us2lim(us) (0x10000 - (PCC_TIMERFREQ/(1000000/(us)))) /* * serial control Index: arch/mvme68k/include/types.h =================================================================== RCS file: /cvsroot/src/sys/arch/mvme68k/include/types.h,v retrieving revision 1.12 diff -u -r1.12 types.h --- arch/mvme68k/include/types.h 17 Oct 2007 19:55:47 -0000 1.12 +++ arch/mvme68k/include/types.h 4 Jan 2008 13:46:42 -0000 @@ -7,5 +7,6 @@ #define __HAVE_DEVICE_REGISTER #define __HAVE_GENERIC_TODR +#define __HAVE_TIMECOUNTER #endif Index: arch/mvme68k/mvme68k/clock.c =================================================================== RCS file: /cvsroot/src/sys/arch/mvme68k/mvme68k/clock.c,v retrieving revision 1.24 diff -u -r1.24 clock.c --- arch/mvme68k/mvme68k/clock.c 9 Sep 2006 22:28:27 -0000 1.24 +++ arch/mvme68k/mvme68k/clock.c 4 Jan 2008 13:46:42 -0000 @@ -139,39 +139,3 @@ /* XXX should we do something here? XXX */ } - -/* - * Return the best possible estimate of the time in the timeval - * to which tvp points. We do this by returning the current time - * plus the amount of time, in uSec, since the last clock interrupt - * (clock_args->ca_microtime()) was handled. - * - * Check that this time is no less than any previously-reported time, - * which could happen around the time of a clock adjustment. Just for fun, - * we guarantee that the time will be greater than the value obtained by a - * previous call. - */ - -void -microtime(tvp) - struct timeval *tvp; -{ - int s = splhigh(); - static struct timeval lasttime; - - *tvp = time; - tvp->tv_usec += (*clock_args->ca_microtime)(clock_args->ca_arg); - while (tvp->tv_usec >= 1000000) { - tvp->tv_sec++; - tvp->tv_usec -= 1000000; - } - if (tvp->tv_sec == lasttime.tv_sec && - tvp->tv_usec <= lasttime.tv_usec && - (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { - tvp->tv_sec++; - tvp->tv_usec -= 1000000; - } - lasttime = *tvp; - splx(s); -} - Index: dev/mvme/clock_pcctwo.c =================================================================== RCS file: /cvsroot/src/sys/dev/mvme/clock_pcctwo.c,v retrieving revision 1.11 diff -u -r1.11 clock_pcctwo.c --- dev/mvme/clock_pcctwo.c 19 Oct 2007 12:00:36 -0000 1.11 +++ dev/mvme/clock_pcctwo.c 4 Jan 2008 13:46:43 -0000 @@ -49,6 +49,7 @@ #include <sys/kernel.h> #include <sys/systm.h> #include <sys/device.h> +#include <sys/timetc.h> #include <machine/psl.h> #include <sys/bus.h> @@ -65,6 +66,7 @@ struct device sc_dev; struct clock_attach_args sc_clock_args; u_char sc_clock_lvl; + struct timecounter sc_tc; }; CFATTACH_DECL(clock_pcctwo, sizeof(struct clock_pcctwo_softc), @@ -75,10 +77,11 @@ static int clock_pcctwo_profintr(void *); static int clock_pcctwo_statintr(void *); static void clock_pcctwo_initclocks(void *, int, int); -static long clock_pcctwo_microtime(void *); static void clock_pcctwo_shutdown(void *); +static uint32_t clock_pcctwo_getcount(struct timecounter *); static struct clock_pcctwo_softc *clock_pcctwo_sc; +static uint32_t clock_pcctwo_count; /* ARGSUSED */ int @@ -119,7 +122,6 @@ sc->sc_clock_args.ca_arg = sc; sc->sc_clock_args.ca_initfunc = clock_pcctwo_initclocks; - sc->sc_clock_args.ca_microtime = clock_pcctwo_microtime; /* Do common portions of clock config. */ clock_config(self, &sc->sc_clock_args, pcctwointr_evcnt(pa->pa_ipl)); @@ -162,20 +164,25 @@ pcc2_reg_write(sys_pcctwo, PCC2REG_TIMER2_CONTROL, PCCTWO_TT_CTRL_CEN | PCCTWO_TT_CTRL_COC | PCCTWO_TT_CTRL_COVF); pcc2_reg_write(sys_pcctwo, PCC2REG_TIMER2_ICSR, sc->sc_clock_lvl); + + sc->sc_tc.tc_get_timecount = clock_pcctwo_getcount; + sc->sc_tc.tc_name = "pcctwo_count"; + sc->sc_tc.tc_frequency = PCCTWO_TIMERFREQ; + sc->sc_tc.tc_quality = 100; + sc->sc_tc.tc_counter_mask = ~0; + tc_init(&sc->sc_tc); } /* ARGSUSED */ -long -clock_pcctwo_microtime(arg) - void *arg; +uint32_t +clock_pcctwo_getcount(struct timecounter *tc) { - static int ovfl_adj[] = { - 0, 10000, 20000, 30000, - 40000, 50000, 60000, 70000, - 80000, 90000, 100000, 110000, - 120000, 130000, 140000, 150000}; - u_int8_t cr; - u_int32_t tc, tc2; + uint32_t cnt; + uint32_t tc1, tc2; + uint8_t cr; + int s; + + s = splhigh(); /* * There's no way to latch the counter and overflow registers @@ -183,16 +190,21 @@ * race by checking for counter wrap-around and re-reading the * overflow counter if necessary. * - * Note: This only works because we're called at splhigh(). + * Note: This only works because we're at splhigh(). */ - tc = pcc2_reg_read32(sys_pcctwo, PCC2REG_TIMER1_COUNTER); + tc1 = pcc2_reg_read32(sys_pcctwo, PCC2REG_TIMER1_COUNTER); cr = pcc2_reg_read(sys_pcctwo, PCC2REG_TIMER1_CONTROL); - if (tc > (tc2 = pcc2_reg_read32(sys_pcctwo, PCC2REG_TIMER1_COUNTER))) { + tc2 = pcc2_reg_read32(sys_pcctwo, PCC2REG_TIMER1_COUNTER); + if (tc1 > tc2) { cr = pcc2_reg_read(sys_pcctwo, PCC2REG_TIMER1_CONTROL); - tc = tc2; + tc1 = tc2; } + cnt = clock_pcctwo_count; + splx(s); + /* XXX assume HZ = 100 */ + cnt += tc1 + (PCCTWO_TIMERFREQ / 100) * PCCTWO_TT_CTRL_OVF(cr); - return ((long) PCCTWO_LIM2US(tc) + ovfl_adj[PCCTWO_TT_CTRL_OVF(cr)]); + return cnt; } int @@ -214,8 +226,11 @@ clock_pcctwo_sc->sc_clock_lvl); splx(s); - for (cr = PCCTWO_TT_CTRL_OVF(cr); cr; cr--) + for (cr = PCCTWO_TT_CTRL_OVF(cr); cr; cr--) { + /* XXX assume HZ = 100 */ + clock_pcctwo_count += PCCTWO_TIMERFREQ / 100; hardclock(frame); + } return (1); } Index: dev/mvme/clockvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/mvme/clockvar.h,v retrieving revision 1.6 diff -u -r1.6 clockvar.h --- dev/mvme/clockvar.h 11 Dec 2005 12:22:47 -0000 1.6 +++ dev/mvme/clockvar.h 4 Jan 2008 13:46:43 -0000 @@ -53,7 +53,6 @@ struct clock_attach_args { void (*ca_initfunc)(void *, int, int); - long (*ca_microtime)(void *); void *ca_arg; }; Index: dev/mvme/pcctworeg.h =================================================================== RCS file: /cvsroot/src/sys/dev/mvme/pcctworeg.h,v retrieving revision 1.1 diff -u -r1.1 pcctworeg.h --- dev/mvme/pcctworeg.h 12 Feb 2002 20:38:49 -0000 1.1 +++ dev/mvme/pcctworeg.h 4 Jan 2008 13:46:43 -0000 @@ -239,6 +239,7 @@ * this is simple since the Tick Counters already have * a 1uS period. (PCC2REG_TIMER[12]_COMPARE) */ +#define PCCTWO_TIMERFREQ 1000000 #define PCCTWO_US2LIM(us) (us) #define PCCTWO_LIM2US(lim) (lim) --- Note in Garrett's patch tc1 value which was read from TMR1_COUNT was not used for timecounter, but it looks he just forgot to add it. --- Izumi Tsutsui