summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/amd64/amd64/machdep.c8
-rw-r--r--sys/arch/amd64/amd64/microtime.S108
-rw-r--r--sys/arch/amd64/conf/Makefile.amd649
-rw-r--r--sys/arch/amd64/include/_types.h3
-rw-r--r--sys/arch/amd64/include/cpu.h14
-rw-r--r--sys/arch/amd64/isa/clock.c255
6 files changed, 128 insertions, 269 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index efed8f9ec69..740c4e70317 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.51 2006/10/01 10:52:10 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.52 2006/11/07 09:09:42 otto Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -204,7 +204,6 @@ pid_t sigpid = 0;
extern paddr_t avail_start, avail_end;
void (*delay_func)(int) = i8254_delay;
-void (*microtime_func)(struct timeval *) = i8254_microtime;
void (*initclock_func)(void) = i8254_initclocks;
struct mtrr_funcs *mtrr_funcs;
@@ -1808,6 +1807,11 @@ void
cpu_initclocks(void)
{
(*initclock_func)();
+
+ if (initclock_func == i8254_initclocks)
+ i8254_inittimecounter();
+ else
+ i8254_inittimecounter_simple();
}
void
diff --git a/sys/arch/amd64/amd64/microtime.S b/sys/arch/amd64/amd64/microtime.S
deleted file mode 100644
index d2cdb9534dd..00000000000
--- a/sys/arch/amd64/amd64/microtime.S
+++ /dev/null
@@ -1,108 +0,0 @@
-/* $OpenBSD: microtime.S,v 1.5 2005/12/13 00:18:19 jsg Exp $ */
-/* $NetBSD: microtime.S,v 1.1 2003/04/26 18:39:30 fvdl Exp $ */
-
-/*-
- * Copyright (c) 1993 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <machine/asm.h>
-#include <dev/isa/isareg.h>
-#include <dev/ic/i8253reg.h>
-
-#include "assym.h"
-
-#define IRQ_BIT(irq_num) (1 << ((irq_num) & 7))
-#define IRQ_BYTE(irq_num) ((irq_num) >> 3)
-
-ENTRY(i8254_microtime)
- # clear registers and do whatever we can up front
- xorl %edx,%edx
- movl $(TIMER_SEL0|TIMER_LATCH),%eax
-
- cli # disable interrupts
-
- # select timer 0 and latch its counter
- outb %al,$IO_TIMER1+TIMER_MODE
- inb $IO_ICU1,%al # as close to timer latch as possible
- movb %al,%ch # %ch is current ICU mask
-
- # Read counter value into [%al %dl], LSB first
- inb $IO_TIMER1+TIMER_CNTR0,%al
- movb %al,%dl # %dl has LSB
- inb $IO_TIMER1+TIMER_CNTR0,%al # %al has MSB
-
- # save state of IIR in ICU, and of ipending, for later perusal
- movb CPUVAR(IPENDING) + IRQ_BYTE(0),%cl
-
- # save the current value of _time
- movq _C_LABEL(time)(%rip),%r8 # get time.tv_sec
- movq (_C_LABEL(time)+8)(%rip),%r9 # and time.tv_usec
-
- sti # enable interrupts, we're done
-
- # At this point we've collected all the state we need to
- # compute the time. First figure out if we've got a pending
- # interrupt. If the IRQ0 bit is set in ipending we've taken
- # a clock interrupt without incrementing time, so we bump
- # time.tv_usec by a tick. Otherwise if the ICU shows a pending
- # interrupt for IRQ0 we (or the caller) may have blocked an interrupt
- # with the cli. If the counter is not a very small value (3 as
- # a heuristic), i.e. in pre-interrupt state, we add a tick to
- # time.tv_usec
-
- testb $IRQ_BIT(0),%cl # pending interrupt?
- jnz 1f # yes, increment count
-
- testb $IRQ_BIT(0),%ch # hardware interrupt pending?
- jz 2f # no, continue
- testb %al,%al # MSB zero?
- jnz 1f # no, add a tick
- cmpb $3,%dl # is this small number?
- jbe 2f # yes, continue
-1: addq _C_LABEL(isa_timer_tick)(%rip),%r9 # add a tick
-
- # We've corrected for pending interrupts. Now do a table lookup
- # based on each of the high and low order counter bytes to increment
- # time.tv_usec
-2: leaq _C_LABEL(isa_timer_msb_table)(%rip),%rsi
- movw (%rsi,%rax,2),%ax
- leaq _C_LABEL(isa_timer_lsb_table)(%rip),%rsi
- subw (%rsi,%rdx,2),%ax
- addq %rax,%r9 # add msb increment
-
- # Normalize the struct timeval. We know the previous increments
- # will be less than a second, so we'll only need to adjust accordingly
- cmpq $1000000,%r9 # carry in timeval?
- jb 3f
- subq $1000000,%r9 # adjust usec
- incq %r8 # bump sec
-
-3: movq %r8,(%rdi) # tvp->tv_sec = sec
- movq %r9,8(%rdi) # tvp->tv_usec = usec
-
- ret
diff --git a/sys/arch/amd64/conf/Makefile.amd64 b/sys/arch/amd64/conf/Makefile.amd64
index 06b4987d3c8..268ff5d4311 100644
--- a/sys/arch/amd64/conf/Makefile.amd64
+++ b/sys/arch/amd64/conf/Makefile.amd64
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.amd64,v 1.9 2006/07/27 05:58:11 miod Exp $
+# $OpenBSD: Makefile.amd64,v 1.10 2006/11/07 09:09:42 otto Exp $
# Makefile for OpenBSD
#
@@ -99,7 +99,7 @@ HOSTED_C= ${HOSTCC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $<
# ${SYSTEM_LD_HEAD}
# ${SYSTEM_LD} swapxxx.o
# ${SYSTEM_LD_TAIL}
-SYSTEM_OBJ= locore.o vector.o copy.o microtime.o spl.o \
+SYSTEM_OBJ= locore.o vector.o copy.o spl.o \
param.o ioconf.o ${OBJS} ${LIBKERN} ${LIBCOMPAT}
SYSTEM_DEP= Makefile ${SYSTEM_OBJ}
SYSTEM_LD_HEAD= rm -f $@
@@ -161,7 +161,7 @@ links:
sh makelinks && rm -f dontlink makelinks
AFILES= ${AMD64}/amd64/locore.S ${AMD64}/amd64/vector.S ${AMD64}/amd64/copy.S \
- ${AMD64}/amd64/microtime.S ${AMD64}/amd64/spl.S
+ ${AMD64}/amd64/spl.S
SRCS= param.c ioconf.c ${AFILES} ${CFILES} ${SFILES}
depend:: .depend
.depend: ${SRCS} assym.h param.c ${APMINC}
@@ -196,9 +196,6 @@ vector.o: ${AMD64}/amd64/vector.S assym.h
copy.o: ${AMD64}/amd64/copy.S assym.h
${NORMAL_S}
-microtime.o: ${AMD64}/amd64/microtime.S assym.h
- ${NORMAL_S}
-
spl.o: ${AMD64}/amd64/spl.S assym.h
${NORMAL_S}
diff --git a/sys/arch/amd64/include/_types.h b/sys/arch/amd64/include/_types.h
index 259b7405e94..b399e2d6f61 100644
--- a/sys/arch/amd64/include/_types.h
+++ b/sys/arch/amd64/include/_types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: _types.h,v 1.1 2006/01/06 18:50:08 millert Exp $ */
+/* $OpenBSD: _types.h,v 1.2 2006/11/07 09:09:42 otto Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -118,5 +118,6 @@ typedef void * __wctype_t;
#define __HAVE_GENERIC_SOFT_INTERRUPTS
#define __HAVE_CPUINFO
#define __HAVE_MUTEX
+#define __HAVE_TIMECOUNTER
#endif /* _AMD64__TYPES_H_ */
diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h
index 372a26d080c..5d587c39f1f 100644
--- a/sys/arch/amd64/include/cpu.h
+++ b/sys/arch/amd64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.18 2006/03/08 03:33:21 uwe Exp $ */
+/* $OpenBSD: cpu.h,v 1.19 2006/11/07 09:09:42 otto Exp $ */
/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
/*-
@@ -230,11 +230,9 @@ extern u_int32_t cpus_attached;
*/
extern void (*delay_func)(int);
struct timeval;
-extern void (*microtime_func)(struct timeval *);
#define DELAY(x) (*delay_func)(x)
#define delay(x) (*delay_func)(x)
-#define microtime(tv) (*microtime_func)(tv)
/*
@@ -251,12 +249,6 @@ extern int cpu_id;
extern char cpu_vendor[];
extern int cpuid_level;
-/* kern_microtime.c */
-
-extern struct timeval cc_microset_time;
-void cc_microtime(struct timeval *);
-void cc_microset(struct cpu_info *);
-
/* identcpu.c */
void identifycpu(struct cpu_info *);
@@ -286,8 +278,10 @@ void child_trampoline(void);
void initrtclock(void);
void startrtclock(void);
void i8254_delay(int);
-void i8254_microtime(struct timeval *);
void i8254_initclocks(void);
+void i8254_inittimecounter(void);
+void i8254_inittimecounter_simple(void);
+
void cpu_init_msrs(struct cpu_info *);
diff --git a/sys/arch/amd64/isa/clock.c b/sys/arch/amd64/isa/clock.c
index 92bcb8b40c5..62abb2c199c 100644
--- a/sys/arch/amd64/isa/clock.c
+++ b/sys/arch/amd64/isa/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.9 2006/02/12 19:55:38 miod Exp $ */
+/* $OpenBSD: clock.c,v 1.10 2006/11/07 09:09:43 otto Exp $ */
/* $NetBSD: clock.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */
/*-
@@ -95,6 +95,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/timeout.h>
+#include <sys/timetc.h>
#include <machine/cpu.h>
#include <machine/intr.h>
@@ -109,7 +110,18 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <dev/clock_subr.h>
#include <machine/specialreg.h>
-void spinwait(int);
+/* Timecounter on the i8254 */
+u_int32_t i8254_lastcount;
+u_int32_t i8254_offset;
+int i8254_ticked;
+u_int i8254_get_timecount(struct timecounter *tc);
+
+u_int i8254_simple_get_timecount(struct timecounter *tc);
+
+static struct timecounter i8254_timecounter = {
+ i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
+};
+
int clockintr(void *);
int rtcintr(void *);
int gettick(void);
@@ -118,7 +130,6 @@ int rtcget(mc_todregs *);
void rtcput(mc_todregs *);
int bcdtobin(int);
int bintobcd(int);
-void findcpuspeed(void);
__inline u_int mc146818_read(void *, u_int);
__inline void mc146818_write(void *, u_int, u_int);
@@ -146,11 +157,14 @@ mc146818_write(sc, reg, datum)
DELAY(1);
}
+struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH);
+
u_long rtclock_tval;
+int rtclock_init;
/* minimal initialization, enough for delay() */
void
-initrtclock()
+initrtclock(void)
{
u_long tval;
@@ -162,6 +176,7 @@ initrtclock()
tval = (TIMER_FREQ * 2) / (u_long) hz;
tval = (tval / 2) + (tval & 0x1);
+ mtx_enter(&timer_mutex);
/* initialize 8253 clock */
outb(IO_TIMER1+TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
@@ -170,105 +185,21 @@ initrtclock()
outb(IO_TIMER1+TIMER_CNTR0, tval / 256);
rtclock_tval = tval;
+ rtclock_init = 1;
+ mtx_leave(&timer_mutex);
}
-/*
- * microtime() makes use of the following globals. Note that isa_timer_tick
- * may be redundant to the `tick' variable, but is kept here for stability.
- * isa_timer_count is the countdown count for the timer. timer_msb_table[]
- * and timer_lsb_table[] are used to compute the microsecond increment
- * for time.tv_usec in the follow fashion:
- *
- * time.tv_usec += isa_timer_msb_table[cnt_msb] - isa_timer_lsb_table[cnt_lsb];
- */
-#define ISA_TIMER_MSB_TABLE_SIZE 128
-
-u_long isa_timer_tick; /* the number of microseconds in a tick */
-u_short isa_timer_count; /* the countdown count for the timer */
-u_short isa_timer_msb_table[ISA_TIMER_MSB_TABLE_SIZE]; /* timer->usec MSB */
-u_short isa_timer_lsb_table[256]; /* timer->usec conversion for LSB */
-
void
startrtclock()
{
int s;
- u_long tval;
- u_long t, msb, lsb, quotient, remainder;
- findcpuspeed(); /* use the clock (while it's free)
- to find the cpu speed */
- initrtclock();
+ if (!rtclock_init)
+ initrtclock();
/* Check diagnostic status */
if ((s = mc146818_read(NULL, NVRAM_DIAG)) != 0) /* XXX softc */
printf("RTC BIOS diagnostic error %b\n", s, NVRAM_DIAG_BITS);
-
- /*
- * Compute timer_tick from hz. We truncate this value (i.e.
- * round down) to minimize the possibility of a backward clock
- * step if hz is not a nice number.
- */
- isa_timer_tick = 1000000 / (u_long) hz;
-
- /*
- * We can't stand any number with an MSB larger than
- * TIMER_MSB_TABLE_SIZE will accomodate.
- */
- tval = rtclock_tval;
- if ((tval / 256) >= ISA_TIMER_MSB_TABLE_SIZE
- || TIMER_FREQ > (8*1024*1024)) {
- panic("startrtclock: TIMER_FREQ/HZ unsupportable");
- }
- isa_timer_count = (u_short) tval;
-
- /*
- * Now compute the translation tables from timer ticks to
- * microseconds. We go to some length to ensure all values
- * are rounded-to-nearest (i.e. +-0.5 of the exact values)
- * as this will ensure the computation
- *
- * isa_timer_msb_table[msb] - isa_timer_lsb_table[lsb]
- *
- * will produce a result which is +-1 usec away from the
- * correctly rounded conversion (in fact, it'll be exact about
- * 75% of the time, 1 too large 12.5% of the time, and 1 too
- * small 12.5% of the time).
- */
- 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));
-
- /* MSB table is zero unless the MSB is <= isa_timer_count */
- if (s < ISA_TIMER_MSB_TABLE_SIZE) {
- msb = ((u_long) s) * 256;
- if (msb > tval) {
- isa_timer_msb_table[s] = 0;
- } else {
- /*
- * Harder computation here, since multiplying
- * the value by 1000000 can overflow a long.
- * To avoid 64-bit computations we divide
- * the high order byte and the low order
- * byte of the numerator separately, adding
- * the remainder of the first computation
- * into the second. The constraint on
- * TIMER_FREQ above should prevent overflow
- * here.
- */
- msb = tval - msb;
- lsb = msb % 256;
- msb = (msb / 256) * 1000000;
- quotient = msb / TIMER_FREQ;
- remainder = msb % TIMER_FREQ;
- t = ((remainder * 256 * 2)
- + (lsb * 1000000 * 2)) / TIMER_FREQ;
- isa_timer_msb_table[s] = (u_short)((t / 2)
- + (t & 0x1) + (quotient * 256));
- }
- }
- }
-
}
int
@@ -276,6 +207,15 @@ clockintr(void *arg)
{
struct clockframe *frame = arg;
+ if (timecounter->tc_get_timecount == i8254_get_timecount) {
+ if (i8254_ticked) {
+ i8254_ticked = 0;
+ } else {
+ i8254_offset += rtclock_tval;
+ i8254_lastcount = 0;
+ }
+ }
+
hardclock(frame);
return 1;
@@ -306,6 +246,7 @@ gettick()
u_char lo, hi;
/* Don't want someone screwing with the counter while we're here. */
+ mtx_enter(&timer_mutex);
ef = read_rflags();
disable_intr();
/* Select counter 0 and latch it. */
@@ -313,6 +254,7 @@ gettick()
lo = inb(IO_TIMER1+TIMER_CNTR0);
hi = inb(IO_TIMER1+TIMER_CNTR0);
write_rflags(ef);
+ mtx_leave(&timer_mutex);
return ((hi << 8) | lo);
}
@@ -334,7 +276,7 @@ i8254_delay(int n)
};
/* allow DELAY() to be used before startrtclock() */
- if (!rtclock_tval)
+ if (!rtclock_init)
initrtclock();
/*
@@ -385,31 +327,6 @@ i8254_delay(int n)
}
}
-unsigned int delaycount; /* calibrated loop variable (1 millisecond) */
-
-#define FIRST_GUESS 0x2000
-
-void
-findcpuspeed()
-{
- int i;
- int remainder;
-
- /* Put counter in count down mode */
- outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
- outb(TIMER_CNTR0, 0xff);
- outb(TIMER_CNTR0, 0xff);
- for (i = FIRST_GUESS; i; i--)
- ;
- /* Read the value left in the counter */
- remainder = gettick();
- /*
- * Formula for delaycount is:
- * (loopcount * timer clock speed) / (counter ticks * 1000)
- */
- delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff-remainder);
-}
-
void
rtcdrain(void *v)
{
@@ -434,10 +351,6 @@ i8254_initclocks()
stathz = 128;
profhz = 1024;
- /*
- * XXX If you're doing strange things with multiple clocks, you might
- * want to keep track of clock handlers.
- */
isa_intr_establish(NULL, 0, IST_PULSE, IPL_CLOCK, clockintr,
0, "clock");
isa_intr_establish(NULL, 8, IST_PULSE, IPL_CLOCK, rtcintr, 0, "rtc");
@@ -606,15 +519,15 @@ clock_expandyear(clockyear)
* from a filesystem.
*/
void
-inittodr(base)
- time_t base;
+inittodr(time_t base)
{
+ struct timespec ts;
mc_todregs rtclk;
struct clock_ymdhms dt;
int s;
-#if defined(I586_CPU) || defined(I686_CPU)
- struct cpu_info *ci = curcpu();
-#endif
+
+ ts.tv_nsec = 0;
+
/*
* We mostly ignore the suggested time (which comes from the
* file system) and go for the RTC clock time stored in the
@@ -673,33 +586,26 @@ inittodr(base)
}
}
- time.tv_sec = clock_ymdhms_to_secs(&dt) + tz.tz_minuteswest * 60;
+ ts.tv_sec = clock_ymdhms_to_secs(&dt) + tz.tz_minuteswest * 60;
if (tz.tz_dsttime)
- time.tv_sec -= 3600;
-#ifdef DEBUG_CLOCK
- printf("readclock: %ld (%ld)\n", time.tv_sec, base);
-#endif
-#if defined(I586_CPU) || defined(I686_CPU)
- if (ci->ci_feature_flags & CPUID_TSC) {
- cc_microset_time = time;
- cc_microset(ci);
- }
-#endif
+ ts.tv_sec -= 3600;
- if (base != 0 && base < time.tv_sec - 5*SECYR)
+ if (base != 0 && base < ts.tv_sec - 5*SECYR)
printf("WARNING: file system time much less than clock time\n");
- else if (base > time.tv_sec + 5*SECYR) {
+ else if (base > ts.tv_sec + 5*SECYR) {
printf("WARNING: clock time much less than file system time\n");
printf("WARNING: using file system time\n");
goto fstime;
}
+ tc_setclock(&ts);
timeset = 1;
return;
fstime:
+ ts.tv_sec = base;
+ tc_setclock(&ts);
timeset = 1;
- time.tv_sec = base;
printf("WARNING: CHECK AND RESET THE DATE!\n");
}
@@ -728,7 +634,7 @@ resettodr()
diff = tz.tz_minuteswest * 60;
if (tz.tz_dsttime)
diff -= 3600;
- clock_secs_to_ymdhms(time.tv_sec - diff, &dt);
+ clock_secs_to_ymdhms(time_second - diff, &dt);
rtclk[MC_SEC] = bintobcd(dt.dt_sec);
rtclk[MC_MIN] = bintobcd(dt.dt_min);
@@ -760,3 +666,68 @@ setstatclockrate(arg)
else
mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | MC_RATE_1024_Hz);
}
+
+void
+i8254_inittimecounter(void)
+{
+ tc_init(&i8254_timecounter);
+}
+
+/*
+ * If we're using lapic to drive hardclock, we can use a simpler
+ * algorithm for the i8254 timecounters.
+ */
+void
+i8254_inittimecounter_simple(void)
+{
+ u_long tval = 0x8000;
+
+ i8254_timecounter.tc_get_timecount = i8254_simple_get_timecount;
+ i8254_timecounter.tc_counter_mask = 0x7fff;
+
+ i8254_timecounter.tc_frequency = TIMER_FREQ;
+
+ mtx_enter(&timer_mutex);
+ outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
+ outb(IO_TIMER1 + TIMER_CNTR0, tval & 0xff);
+ outb(IO_TIMER1 + TIMER_CNTR0, tval >> 8);
+
+ rtclock_tval = tval;
+ rtclock_init = 1;
+ mtx_leave(&timer_mutex);
+
+ tc_init(&i8254_timecounter);
+}
+
+u_int
+i8254_simple_get_timecount(struct timecounter *tc)
+{
+ return (rtclock_tval - gettick());
+}
+
+u_int
+i8254_get_timecount(struct timecounter *tc)
+{
+ u_char hi, lo;
+ u_int count;
+ u_long ef;
+
+ ef = read_rflags();
+ disable_intr();
+
+ outb(IO_TIMER1+TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
+ lo = inb(IO_TIMER1+TIMER_CNTR0);
+ hi = inb(IO_TIMER1+TIMER_CNTR0);
+
+ count = rtclock_tval - ((hi << 8) | lo);
+
+ if (count < i8254_lastcount) {
+ i8254_ticked = 1;
+ i8254_offset += rtclock_tval;
+ }
+ i8254_lastcount = count;
+ count += i8254_offset;
+ write_rflags(ef);
+
+ return (count);
+}