-/* $NetBSD: clock.c,v 1.17 1996/01/29 04:10:00 briggs Exp $ */
+/* $NetBSD: clock.c,v 1.19 1996/02/03 22:49:58 briggs Exp $ */
/*
* Copyright (c) 1988 University of Utah.
*/
#if !defined(STANDALONE)
-#include "param.h"
-#include "kernel.h"
+#include <sys/param.h>
+#include <sys/kernel.h>
-#include "machine/psl.h"
-#include "machine/cpu.h"
+#include <machine/psl.h>
+#include <machine/cpu.h>
#if defined(GPROF) && defined(PROFTIMER)
-#include "sys/gprof.h"
+#include <sys/gprof.h>
#endif
#else /* STANDALONE */
*/
#define CLK_RATE 12766
+#define DELAY_CALIBRATE (0xffffff << 7) /* Large value for calibration */
+#define LARGE_DELAY 0x40000 /* About 335 msec */
+
+int delay_factor = DELAY_CALIBRATE;
+volatile int delay_flag = 1;
+
/*
* delay(usec)
- * Delay usec microseconds. This is inaccurate because it
- * assumes that it takes no time to actually execute. We should
- * try to compensate for this sometime because access to the via
- * is hardly cheap.
+ * Delay usec microseconds.
*
- * It would probably be worthwhile to invent a version of this that
- * didn't depend on the VIA.
+ * 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(int usec)
{
- register int ticks, t;
+ register unsigned int cycles;
+
+ if (usec > LARGE_DELAY)
+ cycles = (usec >> 7) * delay_factor;
+ else
+ cycles = ((usec > 0 ? usec : 1) * delay_factor) >> 7;
- if (usec <= 0)
- usec = 1;
+ while ((cycles-- > 0) && delay_flag)
+ ;
+}
+
+/*
+ * Dummy delay calibration. Functionally identical to delay(), but
+ * returns the number of times through the loop.
+ */
+static int
+dummy_delay(usec)
+ int usec;
+{
+ register unsigned int cycles;
- if (usec < 200000)
- ticks = (usec * 10000) / CLK_RATE;
+ if (usec > LARGE_DELAY)
+ cycles = (usec >> 7) * delay_factor;
else
- ticks = (usec / CLK_RATE) * 10000;
+ cycles = ((usec > 0 ? usec : 1) * delay_factor) >> 7;
- while (ticks) {
- t = min(ticks, 65535);
+ while ((cycles-- > 0) && delay_flag)
+ ;
+
+ return ((delay_factor >> 7) - cycles);
+}
+
+static void
+delay_timer1_irq()
+{
+ delay_flag = 0;
+}
- via_reg(VIA1, vT2C) = (t & 0xff);
- via_reg(VIA1, vT2CH) = ((t >> 8) & 0xff);
+/*
+ * Calibrate delay_factor with VIA1 timer T1.
+ */
+void
+mac68k_calibrate_delay()
+{
+ int n;
+ int sum;
- while (!(via_reg(VIA1, vIFR) & V1IF_T2))
- ;
+ mac68k_register_via1_t1_irq(delay_timer1_irq);
+ via_reg(VIA1, vIER) = 0x80 | V1IF_T1;
- ticks -= t;
+ for (sum = 0, n = 8; n > 0; n--) {
+ delay_flag = 1;
+ via_reg(VIA1, vT1C) = 0; /* 1024 clock ticks */
+ via_reg(VIA1, vT1CH) = 4; /* (approx 1.3 msec) */
+ sum += dummy_delay(1);
}
+
+ via_reg(VIA1, vIER) = V1IF_T1;
+ via_reg(VIA1, vT1C) = 0;
+ via_reg(VIA1, vT1CH) = 0;
+ mac68k_register_via1_t1_irq(NULL);
+
+ /*
+ * If this weren't integer math, the following would look
+ * a lot prettier. It should really be something like
+ * this:
+ * delay_factor = ((sum / 8) / (1024 * 1.2766)) * 128;
+ * That is, average the sum, divide by the number of usec,
+ * and multiply by a scale factor of 128.
+ *
+ * We can accomplish the same thing by simplifying and using
+ * shifts, being careful to avoid as much loss of precision
+ * as possible. (If the sum exceeds (2^31-1)/10000, we need
+ * to rearrange the calculation slightly to do this.)
+ */
+ if (sum > 214748) /* This is a _fast_ machine! */
+ delay_factor = (((sum >> 3) * 10000) / CLK_RATE) >> 3;
+ else
+ delay_factor = (((sum * 10000) >> 3) / CLK_RATE) >> 3;
+
+ /* Reset the delay_flag for normal use */
+ delay_flag = 1;
+
+#ifdef DEBUG
+ printf("delay calibrated, factor = %d\n", delay_factor);
+#endif
}
.globl _initenv, _getenvvars | in machdep.c
.globl _setmachdep | in machdep.c
+ .globl _VIA_initialize | in via.c
/* Initialize source/destination control registers for movs */
moveq #FC_USERD,d0 | user space
jbsr _getenvvars | Parse the environment buffer
jbsr _setmachdep | Set some machine-dep stuff
+ jbsr _VIA_initialize | Initialize the VIAs
jbsr _vm_set_page_size | Set the vm system page size, now.
jbsr _consinit | XXX Should only be if graybar on
.word 0, 0, 0, 0, 0, 0
_mac68k_buserr_addr:
.long 0
+ .globl _SONICSPACE, _SONICSPACE_size
+_SONICSPACE:
+ .space 108123
+/* size is figured out in if_sn.c.
+ This should be dynamically allocated at some point. */
+_SONICSPACE_size:
+ .long 108123
-/* $NetBSD: via.c,v 1.34 1995/09/28 04:11:18 briggs Exp $ */
+/* $NetBSD: via.c,v 1.36 1996/02/03 22:50:19 briggs Exp $ */
/*-
* Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
void
VIA_initialize()
{
- /* Sanity. */
- if(via_inited){printf("WARNING: Initializing VIA's again.\n");return;}
-
/* Initialize VIA1 */
/* set all timers to 0 */
via_reg(VIA1, vT1L) = 0;
/* turn off timer latch */
via_reg(VIA1, vACR) &= 0x3f;
- Via2Base = Via1Base + VIA2 * 0x2000;
if (VIA2 == VIA2OFF) {
/* Initialize VIA2 */
via2_reg(vT1L) = 0;
via2iarg[3] = (void *) 3;
}
}
+
+extern void
+mac68k_register_via1_t1_irq(irq_func)
+ void (*irq_func)(void *);
+{
+ if (irq_func)
+ via1itab[6] = irq_func;
+ else
+ via1itab[6] = rtclock_intr;
+}