summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/amd64/amd64/microtime.S3
-rw-r--r--sys/arch/amd64/isa/clock.c71
2 files changed, 72 insertions, 2 deletions
diff --git a/sys/arch/amd64/amd64/microtime.S b/sys/arch/amd64/amd64/microtime.S
index 6475d6baba5..ce3c24f01e6 100644
--- a/sys/arch/amd64/amd64/microtime.S
+++ b/sys/arch/amd64/amd64/microtime.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: microtime.S,v 1.2 2004/03/09 23:05:13 deraadt Exp $ */
+/* $OpenBSD: microtime.S,v 1.3 2004/03/22 19:43:29 nordin Exp $ */
/* $NetBSD: microtime.S,v 1.1 2003/04/26 18:39:30 fvdl Exp $ */
/*-
@@ -95,6 +95,7 @@ ENTRY(microtime)
# 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
diff --git a/sys/arch/amd64/isa/clock.c b/sys/arch/amd64/isa/clock.c
index 8c2fc2dab1f..fcf6db666e5 100644
--- a/sys/arch/amd64/isa/clock.c
+++ b/sys/arch/amd64/isa/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.2 2004/03/09 23:05:13 deraadt Exp $ */
+/* $OpenBSD: clock.c,v 1.3 2004/03/22 19:43:29 nordin Exp $ */
/* $NetBSD: clock.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */
/*-
@@ -230,6 +230,8 @@ 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 */
@@ -238,6 +240,73 @@ startrtclock()
/* 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