From: briggs Date: Sun, 4 Feb 1996 16:40:12 +0000 (+0000) Subject: New self-calibrating spin-wait delay() from Scott Reynolds . X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=0f10f041713eb8b783388a745284b0131ea5e976;p=openbsd New self-calibrating spin-wait delay() from Scott Reynolds . --- diff --git a/sys/arch/mac68k/mac68k/clock.c b/sys/arch/mac68k/mac68k/clock.c index a24b3555408..154306f9b68 100644 --- a/sys/arch/mac68k/mac68k/clock.c +++ b/sys/arch/mac68k/mac68k/clock.c @@ -1,4 +1,4 @@ -/* $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. @@ -78,14 +78,14 @@ */ #if !defined(STANDALONE) -#include "param.h" -#include "kernel.h" +#include +#include -#include "machine/psl.h" -#include "machine/cpu.h" +#include +#include #if defined(GPROF) && defined(PROFTIMER) -#include "sys/gprof.h" +#include #endif #else /* STANDALONE */ @@ -407,38 +407,108 @@ resettodr(void) */ #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 } diff --git a/sys/arch/mac68k/mac68k/locore.s b/sys/arch/mac68k/mac68k/locore.s index fab0ace21ce..c147b4dac3b 100644 --- a/sys/arch/mac68k/mac68k/locore.s +++ b/sys/arch/mac68k/mac68k/locore.s @@ -820,6 +820,7 @@ start: .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 @@ -834,6 +835,7 @@ start: 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 @@ -2106,3 +2108,10 @@ _mac68k_vrsrc_vec: .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 diff --git a/sys/arch/mac68k/mac68k/machdep.c b/sys/arch/mac68k/mac68k/machdep.c index 18a799c1cd6..22245d30d89 100644 --- a/sys/arch/mac68k/mac68k/machdep.c +++ b/sys/arch/mac68k/mac68k/machdep.c @@ -221,6 +221,8 @@ consinit(void) ddb_init(); #endif init = 1; + } else { + mac68k_calibrate_delay(); } } diff --git a/sys/arch/mac68k/mac68k/via.c b/sys/arch/mac68k/mac68k/via.c index 81810f779d3..35abdf1e070 100644 --- a/sys/arch/mac68k/mac68k/via.c +++ b/sys/arch/mac68k/mac68k/via.c @@ -1,4 +1,4 @@ -/* $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, @@ -102,9 +102,6 @@ void *slotptab[6]; 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; @@ -117,7 +114,6 @@ VIA_initialize() /* turn off timer latch */ via_reg(VIA1, vACR) &= 0x3f; - Via2Base = Via1Base + VIA2 * 0x2000; if (VIA2 == VIA2OFF) { /* Initialize VIA2 */ via2_reg(vT1L) = 0; @@ -383,3 +379,13 @@ mac68k_register_scsi_irq(irq_func, client_data) 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; +} diff --git a/sys/arch/mac68k/mac68k/via.h b/sys/arch/mac68k/mac68k/via.h index 923eaeddedb..b6b63aa9add 100644 --- a/sys/arch/mac68k/mac68k/via.h +++ b/sys/arch/mac68k/mac68k/via.h @@ -1,4 +1,4 @@ -/* $NetBSD: via.h,v 1.14 1995/09/04 05:06:00 briggs Exp $ */ +/* $NetBSD: via.h,v 1.15 1996/02/03 22:50:22 briggs Exp $ */ /*- * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo, @@ -177,6 +177,7 @@ int rbv_vidstatus (void); int add_nubus_intr (int addr, void (*func)(), void *client_data); void mac68k_register_scsi_irq(void (*irq_func)(void *), void *clnt); void mac68k_register_scsi_drq(void (*drq_func)(void *), void *clnt); +void mac68k_register_via1_t1_irq(void (*irq_func)(void *)); extern void (*via1itab[7])(); extern void (*via2itab[7])();