summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Reindl <martin@cvs.openbsd.org>2004-11-30 01:44:23 +0000
committerMartin Reindl <martin@cvs.openbsd.org>2004-11-30 01:44:23 +0000
commit9fb0a99025af567ab4c0b08fae9d1dea2ba98a44 (patch)
tree4de7d893c72a1615b483393ddb1aabb6323889e2
parent3fca817cbc05076038d7e138301275202aed2fc1 (diff)
provide a more accurate assembly delay() routine
ok miod@ >From: NetBSD
-rw-r--r--sys/arch/mac68k/mac68k/clock.c61
-rw-r--r--sys/arch/mac68k/mac68k/locore.s47
2 files changed, 57 insertions, 51 deletions
diff --git a/sys/arch/mac68k/mac68k/clock.c b/sys/arch/mac68k/mac68k/clock.c
index b8e7eeefeb8..9971328f047 100644
--- a/sys/arch/mac68k/mac68k/clock.c
+++ b/sys/arch/mac68k/mac68k/clock.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: clock.c,v 1.17 2004/11/26 21:21:28 miod Exp $ */
-/* $NetBSD: clock.c,v 1.36 1997/10/07 03:04:55 scottr Exp $ */
+/* $OpenBSD: clock.c,v 1.18 2004/11/30 01:44:22 martin Exp $ */
+/* $NetBSD: clock.c,v 1.39 1999/11/05 19:14:56 scottr Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -408,6 +408,8 @@ resettodr()
"to the PRAM on this system.\n");
#endif
}
+
+
/*
* The Macintosh timers decrement once every 1.2766 microseconds.
* MGFH2, p. 180
@@ -415,55 +417,11 @@ resettodr()
#define CLK_RATE 12766
#define DELAY_CALIBRATE (0xffffff << 7) /* Large value for calibration */
-#define LARGE_DELAY 0x40000 /* About 335 msec */
u_int delay_factor = DELAY_CALIBRATE;
volatile int delay_flag = 1;
-/*
- * delay(usec)
- * Delay usec microseconds.
- *
- * The delay_factor is scaled up by a factor of 128 to avoid loss
- * of precision for small delays. As a result of this, note that
- * delays larger that LARGE_DELAY will be up to 128 usec too short,
- * due to adjustments for calculations involving 32 bit values.
- */
-void
-delay(usec)
- unsigned usec;
-{
- volatile unsigned int cycles;
-
- if (usec > LARGE_DELAY)
- cycles = (usec >> 7) * delay_factor;
- else
- cycles = ((usec > 0 ? usec : 1) * delay_factor) >> 7;
-
- while ((cycles-- > 0) && delay_flag);
-}
-
-static unsigned dummy_delay(unsigned);
-/*
- * Dummy delay calibration. Functionally identical to delay(), but
- * returns the number of times through the loop.
- */
-static unsigned
-dummy_delay(usec)
- unsigned usec;
-{
- volatile unsigned int cycles;
-
- if (usec > LARGE_DELAY)
- cycles = (usec >> 7) * delay_factor;
- else
- cycles = ((usec > 0 ? usec : 1) * delay_factor) >> 7;
-
- while ((cycles-- > 0) && delay_flag);
-
- return ((delay_factor >> 7) - cycles);
-}
-
+int _delay(u_int);
static int delay_timer1_irq(void *);
static int
@@ -480,8 +438,9 @@ delay_timer1_irq(dummy)
void
mac68k_calibrate_delay()
{
- int n;
- unsigned sum;
+ u_int sum, n;
+
+ (void)spl0();
/* Disable VIA1 timer 1 interrupts and set up service routine */
via_reg(VIA1, vIER) = V1IF_T1;
@@ -501,7 +460,7 @@ mac68k_calibrate_delay()
delay_flag = 1;
via_reg(VIA1, vT1C) = 0; /* 1024 clock ticks */
via_reg(VIA1, vT1CH) = 4; /* (approx 1.3 msec) */
- sum += dummy_delay(1);
+ sum += ((delay_factor >> 7) - _delay(1));
}
/* Disable timer interrupts and reset service routine */
@@ -533,4 +492,6 @@ mac68k_calibrate_delay()
if (clock_debug)
printf("mac68k_calibrate_delay(): delay_factor calibrated\n");
#endif
+
+ (void)splhigh();
}
diff --git a/sys/arch/mac68k/mac68k/locore.s b/sys/arch/mac68k/mac68k/locore.s
index b49530ff836..762c40d819c 100644
--- a/sys/arch/mac68k/mac68k/locore.s
+++ b/sys/arch/mac68k/mac68k/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.38 2004/11/27 14:26:32 miod Exp $ */
+/* $OpenBSD: locore.s,v 1.39 2004/11/30 01:44:22 martin Exp $ */
/* $NetBSD: locore.s,v 1.103 1998/07/09 06:02:50 scottr Exp $ */
/*
@@ -1506,6 +1506,51 @@ Lm68881rdone:
rts
/*
+ * delay() - delay for a specified number of microseconds
+ * _delay() - calibrator helper for delay()
+ *
+ * Notice that delay_factor is scaled up by a factor of 128 to avoid loss
+ * of precision for small delays. As a result of this we need to avoid
+ * overflow.
+ *
+ * The branch target for the loops must be aligned on a half-line (8-byte)
+ * boundary to minimize cache effects. This guarantees both that there
+ * will be no prefetch stalls due to cache line burst operations and that
+ * the loops will run from a single cache half-line.
+ */
+ .align 8 | align to half-line boundary
+
+ALTENTRY(_delay, _delay)
+ENTRY(delay)
+ movl sp@(4),d0 | get microseconds to delay
+ cmpl #0x40000,d0 | is it a "large" delay?
+ bls Ldelayshort | no, normal calculation
+ movql #0x7f,d1 | adjust for scaled multipler (to
+ addl d1,d0 | avoid overflow)
+ lsrl #7,d0
+ mulul _C_LABEL(delay_factor),d0 | calculate number of loop iterations
+ bra Ldelaysetup | go do it!
+Ldelayshort:
+ mulul _C_LABEL(delay_factor),d0 | calculate number of loop iterations
+ lsrl #7,d0 | adjust for scaled multiplier
+Ldelaysetup:
+ jeq Ldelayexit | bail out if nothing to do
+ movql #0,d1 | put bits 15-0 in d1 for the
+ movw d0,d1 | inner loop, and move bits
+ movw #0,d0 | 31-16 to the low-order word
+ subql #1,d1 | of d0 for the outer loop
+ swap d0
+Ldelay:
+ tstl _C_LABEL(delay_flag) | this never changes for delay()!
+ dbeq d1,Ldelay | (used only for timing purposes)
+ dbeq d0,Ldelay
+ addqw #1,d1 | adjust end count and
+ swap d0 | return the longword result
+ orl d1,d0
+Ldelayexit:
+ rts
+
+/*
* Handle the nitty-gritty of rebooting the machine.
* Basically we just turn off the MMU and jump to the appropriate ROM routine.
* Note that we must be running in an address range that is mapped one-to-one