Home | History | Annotate | Line # | Download | only in isa
      1  1.20    andvar /*	$NetBSD: clock.c,v 1.20 2023/12/09 00:02:10 andvar Exp $	*/
      2   1.1   thorpej 
      3   1.1   thorpej /*
      4   1.1   thorpej  * Copyright 1997
      5   1.1   thorpej  * Digital Equipment Corporation. All rights reserved.
      6   1.1   thorpej  *
      7   1.1   thorpej  * This software is furnished under license and may be used and
      8   1.1   thorpej  * copied only in accordance with the following terms and conditions.
      9   1.1   thorpej  * Subject to these conditions, you may download, copy, install,
     10   1.1   thorpej  * use, modify and distribute this software in source and/or binary
     11   1.1   thorpej  * form. No title or ownership is transferred hereby.
     12   1.1   thorpej  *
     13   1.1   thorpej  * 1) Any source code used, modified or distributed must reproduce
     14   1.1   thorpej  *    and retain this copyright notice and list of conditions as
     15   1.1   thorpej  *    they appear in the source file.
     16   1.1   thorpej  *
     17   1.1   thorpej  * 2) No right is granted to use any trade name, trademark, or logo of
     18   1.1   thorpej  *    Digital Equipment Corporation. Neither the "Digital Equipment
     19   1.1   thorpej  *    Corporation" name nor any trademark or logo of Digital Equipment
     20   1.1   thorpej  *    Corporation may be used to endorse or promote products derived
     21   1.1   thorpej  *    from this software without the prior written permission of
     22   1.1   thorpej  *    Digital Equipment Corporation.
     23   1.1   thorpej  *
     24   1.1   thorpej  * 3) This software is provided "AS-IS" and any express or implied
     25   1.1   thorpej  *    warranties, including but not limited to, any implied warranties
     26   1.1   thorpej  *    of merchantability, fitness for a particular purpose, or
     27   1.1   thorpej  *    non-infringement are disclaimed. In no event shall DIGITAL be
     28   1.1   thorpej  *    liable for any damages whatsoever, and in particular, DIGITAL
     29   1.1   thorpej  *    shall not be liable for special, indirect, consequential, or
     30   1.1   thorpej  *    incidental damages or damages for lost profits, loss of
     31   1.1   thorpej  *    revenue or loss of use, whether such damages arise in contract,
     32   1.1   thorpej  *    negligence, tort, under statute, in equity, at law or otherwise,
     33   1.1   thorpej  *    even if advised of the possibility of such damage.
     34   1.1   thorpej  */
     35   1.1   thorpej 
     36   1.1   thorpej /*-
     37   1.1   thorpej  * Copyright (c) 1990 The Regents of the University of California.
     38   1.1   thorpej  * All rights reserved.
     39   1.1   thorpej  *
     40   1.1   thorpej  * This code is derived from software contributed to Berkeley by
     41   1.1   thorpej  * William Jolitz and Don Ahn.
     42   1.1   thorpej  *
     43   1.1   thorpej  * Redistribution and use in source and binary forms, with or without
     44   1.1   thorpej  * modification, are permitted provided that the following conditions
     45   1.1   thorpej  * are met:
     46   1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     47   1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     48   1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     49   1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     50   1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     51   1.6       agc  * 3. Neither the name of the University nor the names of its contributors
     52   1.6       agc  *    may be used to endorse or promote products derived from this software
     53   1.6       agc  *    without specific prior written permission.
     54   1.6       agc  *
     55   1.6       agc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     56   1.6       agc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     57   1.6       agc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     58   1.6       agc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     59   1.6       agc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     60   1.6       agc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     61   1.6       agc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     62   1.6       agc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     63   1.6       agc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     64   1.6       agc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     65   1.6       agc  * SUCH DAMAGE.
     66   1.6       agc  *
     67   1.6       agc  *	@(#)clock.c	7.2 (Berkeley) 5/12/91
     68   1.6       agc  */
     69   1.6       agc /*-
     70   1.6       agc  * Copyright (c) 1993, 1994 Charles M. Hannum.
     71   1.6       agc  *
     72   1.6       agc  * This code is derived from software contributed to Berkeley by
     73   1.6       agc  * William Jolitz and Don Ahn.
     74   1.6       agc  *
     75   1.6       agc  * Redistribution and use in source and binary forms, with or without
     76   1.6       agc  * modification, are permitted provided that the following conditions
     77   1.6       agc  * are met:
     78   1.6       agc  * 1. Redistributions of source code must retain the above copyright
     79   1.6       agc  *    notice, this list of conditions and the following disclaimer.
     80   1.6       agc  * 2. Redistributions in binary form must reproduce the above copyright
     81   1.6       agc  *    notice, this list of conditions and the following disclaimer in the
     82   1.6       agc  *    documentation and/or other materials provided with the distribution.
     83   1.1   thorpej  * 3. All advertising materials mentioning features or use of this software
     84   1.1   thorpej  *    must display the following acknowledgement:
     85   1.1   thorpej  *	This product includes software developed by the University of
     86   1.1   thorpej  *	California, Berkeley and its contributors.
     87   1.1   thorpej  * 4. Neither the name of the University nor the names of its contributors
     88   1.1   thorpej  *    may be used to endorse or promote products derived from this software
     89   1.1   thorpej  *    without specific prior written permission.
     90   1.1   thorpej  *
     91   1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     92   1.1   thorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     93   1.1   thorpej  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     94   1.1   thorpej  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     95   1.1   thorpej  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     96   1.1   thorpej  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     97   1.1   thorpej  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     98   1.1   thorpej  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     99   1.1   thorpej  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    100   1.1   thorpej  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    101   1.1   thorpej  * SUCH DAMAGE.
    102   1.1   thorpej  *
    103   1.1   thorpej  *	@(#)clock.c	7.2 (Berkeley) 5/12/91
    104   1.1   thorpej  */
    105   1.1   thorpej /*
    106   1.1   thorpej  * Mach Operating System
    107   1.1   thorpej  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
    108   1.1   thorpej  * All Rights Reserved.
    109   1.1   thorpej  *
    110   1.1   thorpej  * Permission to use, copy, modify and distribute this software and its
    111   1.1   thorpej  * documentation is hereby granted, provided that both the copyright
    112   1.1   thorpej  * notice and this permission notice appear in all copies of the
    113   1.1   thorpej  * software, derivative works or modified versions, and any portions
    114   1.1   thorpej  * thereof, and that both notices appear in supporting documentation.
    115   1.1   thorpej  *
    116   1.1   thorpej  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
    117   1.1   thorpej  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
    118   1.1   thorpej  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
    119   1.1   thorpej  *
    120   1.1   thorpej  * Carnegie Mellon requests users of this software to return to
    121   1.1   thorpej  *
    122   1.1   thorpej  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
    123   1.1   thorpej  *  School of Computer Science
    124   1.1   thorpej  *  Carnegie Mellon University
    125   1.1   thorpej  *  Pittsburgh PA 15213-3890
    126   1.1   thorpej  *
    127   1.1   thorpej  * any improvements or extensions that they make and grant Carnegie Mellon
    128   1.1   thorpej  * the rights to redistribute these changes.
    129   1.1   thorpej  */
    130   1.1   thorpej /*
    131   1.1   thorpej   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
    132   1.1   thorpej 
    133   1.1   thorpej 		All Rights Reserved
    134   1.1   thorpej 
    135   1.1   thorpej Permission to use, copy, modify, and distribute this software and
    136   1.1   thorpej its documentation for any purpose and without fee is hereby
    137   1.1   thorpej granted, provided that the above copyright notice appears in all
    138   1.1   thorpej copies and that both the copyright notice and this permission notice
    139   1.1   thorpej appear in supporting documentation, and that the name of Intel
    140   1.1   thorpej not be used in advertising or publicity pertaining to distribution
    141   1.1   thorpej of the software without specific, written prior permission.
    142   1.1   thorpej 
    143   1.1   thorpej INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
    144   1.1   thorpej INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
    145   1.1   thorpej IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
    146   1.1   thorpej CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    147   1.1   thorpej LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
    148   1.1   thorpej NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
    149   1.1   thorpej WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    150   1.1   thorpej */
    151   1.1   thorpej 
    152   1.1   thorpej /*
    153   1.1   thorpej  * Primitive clock interrupt routines.
    154   1.1   thorpej  */
    155   1.5     lukem 
    156   1.5     lukem #include <sys/cdefs.h>
    157  1.20    andvar __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.20 2023/12/09 00:02:10 andvar Exp $");
    158   1.5     lukem 
    159   1.1   thorpej #include <sys/param.h>
    160   1.1   thorpej #include <sys/systm.h>
    161   1.1   thorpej #include <sys/time.h>
    162  1.13   gdamore #include <sys/timetc.h>
    163   1.1   thorpej #include <sys/kernel.h>
    164   1.1   thorpej #include <sys/device.h>
    165   1.1   thorpej 
    166   1.1   thorpej #include <machine/cpu.h>
    167   1.1   thorpej #include <machine/intr.h>
    168  1.14      matt #include <machine/irqhandler.h>
    169   1.1   thorpej #include <machine/pio.h>
    170   1.1   thorpej #include <arm/cpufunc.h>
    171   1.1   thorpej 
    172   1.1   thorpej #include <dev/isa/isareg.h>
    173   1.1   thorpej #include <dev/isa/isavar.h>
    174   1.1   thorpej #include <dev/ic/mc146818reg.h>
    175   1.1   thorpej #include <dev/ic/i8253reg.h>
    176   1.1   thorpej #include <shark/isa/nvram.h>
    177   1.1   thorpej #include <shark/isa/spkrreg.h>
    178   1.1   thorpej #include <shark/shark/hat.h>
    179   1.1   thorpej 
    180   1.3       chs void	sysbeepstop(void *);
    181   1.3       chs void	sysbeep(int, int);
    182   1.3       chs void	rtcinit(void);
    183   1.1   thorpej int     timer_hz_to_count(int);
    184   1.1   thorpej 
    185   1.3       chs static void findcpuspeed(void);
    186   1.1   thorpej static void delayloop(int);
    187   1.3       chs static int  clockintr(void *);
    188   1.3       chs static int  gettick(void);
    189  1.13   gdamore static void tc_init_i8253(void);
    190   1.3       chs 
    191   1.3       chs void startrtclock(void);
    192   1.1   thorpej 
    193  1.12   gdamore inline unsigned mc146818_read(void *, unsigned);
    194  1.12   gdamore inline void mc146818_write(void *, unsigned, unsigned);
    195   1.1   thorpej 
    196  1.12   gdamore inline unsigned
    197  1.12   gdamore mc146818_read(void *sc, unsigned reg)
    198   1.1   thorpej {
    199   1.1   thorpej 
    200   1.1   thorpej 	outb(IO_RTC, reg);
    201   1.1   thorpej 	return (inb(IO_RTC+1));
    202   1.1   thorpej }
    203   1.1   thorpej 
    204  1.10     perry inline void
    205  1.12   gdamore mc146818_write(void *sc, unsigned reg, unsigned datum)
    206   1.1   thorpej {
    207   1.1   thorpej 
    208   1.1   thorpej 	outb(IO_RTC, reg);
    209   1.1   thorpej 	outb(IO_RTC+1, datum);
    210   1.1   thorpej }
    211   1.1   thorpej 
    212   1.1   thorpej unsigned int count1024usec; /* calibrated loop variable (1024 microseconds) */
    213   1.1   thorpej 
    214   1.1   thorpej /* number of timer ticks in a Musec = 2^20 usecs */
    215   1.1   thorpej #define TIMER_MUSECFREQ\
    216   1.1   thorpej     (((((((TIMER_FREQ) * 1024) + 999) / 1000) * 1024) + 999) / 1000)
    217   1.1   thorpej #define TIMER_MUSECDIV(x) ((TIMER_MUSECFREQ+(x)/2)/(x))
    218   1.1   thorpej 
    219   1.1   thorpej /*
    220   1.1   thorpej  * microtime() makes use of the following globals.
    221   1.1   thorpej  * timer_msb_table[] and timer_lsb_table[] are used to compute the
    222   1.1   thorpej  * microsecond increment.
    223   1.1   thorpej  *
    224   1.1   thorpej  * time.tv_usec += isa_timer_msb_table[cnt_msb] + isa_timer_lsb_table[cnt_lsb];
    225   1.1   thorpej  */
    226   1.1   thorpej 
    227   1.1   thorpej u_short	isa_timer_lsb_table[256];	/* timer->usec conversion for LSB */
    228   1.1   thorpej 
    229   1.1   thorpej /* 64 bit counts from timer 0 */
    230   1.1   thorpej struct count64 {
    231  1.12   gdamore 	unsigned lo;   /* low 32 bits */
    232  1.12   gdamore 	unsigned hi;   /* high 32 bits */
    233   1.1   thorpej };
    234   1.1   thorpej 
    235   1.1   thorpej #define TIMER0_ROLLOVER  0xFFFF  /* maximum rollover for 8254 counter */
    236   1.1   thorpej 
    237   1.1   thorpej struct count64 timer0count;
    238   1.1   thorpej struct count64 timer0_at_last_clockintr;
    239   1.1   thorpej unsigned       timer0last;
    240   1.1   thorpej 
    241   1.1   thorpej /*#define TESTHAT*/
    242   1.1   thorpej #ifdef TESTHAT
    243   1.1   thorpej #define HATSTACKSIZE 1024
    244   1.1   thorpej #define HATHZ  50000
    245   1.1   thorpej #define HATHZ2 10000
    246   1.1   thorpej unsigned char hatStack[HATSTACKSIZE];
    247   1.1   thorpej 
    248   1.1   thorpej unsigned testHatOn = 0;
    249   1.1   thorpej unsigned nHats = 0;
    250   1.1   thorpej unsigned nHatWedges = 0;
    251   1.1   thorpej unsigned fiqReason = 0;
    252   1.1   thorpej unsigned hatCount = 0;
    253   1.1   thorpej unsigned hatCount2 = 0;
    254   1.1   thorpej 
    255  1.20    andvar static void hatTest(int testReason)
    256   1.1   thorpej {
    257   1.1   thorpej 
    258  1.12   gdamore 	fiqReason |= testReason;
    259  1.12   gdamore 	nHats++;
    260   1.1   thorpej }
    261   1.1   thorpej 
    262  1.20    andvar static void hatWedge(int nFIQs)
    263   1.1   thorpej {
    264  1.12   gdamore 
    265  1.12   gdamore 	printf("Unwedging the HAT.  fiqs_happened = %d\n", nFIQs);
    266  1.12   gdamore 	nHatWedges++;
    267   1.1   thorpej }
    268   1.1   thorpej #endif
    269   1.1   thorpej 
    270   1.1   thorpej void
    271  1.12   gdamore startrtclock(void)
    272   1.1   thorpej {
    273  1.12   gdamore 
    274  1.12   gdamore 	findcpuspeed();		/* use the clock (while it's free) to
    275  1.12   gdamore 				   find the CPU speed */
    276   1.1   thorpej 
    277   1.1   thorpej 	timer0count.lo = 0;
    278   1.1   thorpej 	timer0count.hi = 0;
    279   1.1   thorpej 	timer0_at_last_clockintr.lo = 0;
    280   1.1   thorpej 	timer0_at_last_clockintr.hi = 0;
    281   1.1   thorpej 	timer0last     = 0;
    282   1.1   thorpej 
    283   1.1   thorpej 	/* initialize 8253 clock */
    284   1.1   thorpej 	outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
    285   1.1   thorpej 	outb(IO_TIMER1 + TIMER_CNTR0, TIMER0_ROLLOVER % 256);
    286   1.1   thorpej 	outb(IO_TIMER1 + TIMER_CNTR0, TIMER0_ROLLOVER / 256);
    287   1.1   thorpej 
    288   1.1   thorpej #ifdef TESTHAT
    289   1.1   thorpej 	hatCount = timer_hz_to_count(HATHZ);
    290   1.1   thorpej 	hatCount2 = timer_hz_to_count(HATHZ2);
    291   1.1   thorpej 	printf("HAT test on @ %d Hz = %d ticks\n", HATHZ, hatCount);
    292   1.1   thorpej #endif
    293   1.1   thorpej }
    294   1.1   thorpej 
    295   1.1   thorpej int
    296  1.12   gdamore timer_hz_to_count(int timer_hz)
    297   1.1   thorpej {
    298   1.1   thorpej 	u_long tval;
    299   1.1   thorpej 
    300   1.1   thorpej 	tval = (TIMER_FREQ * 2) / (u_long) timer_hz;
    301   1.1   thorpej 	tval = (tval / 2) + (tval & 0x1);
    302   1.1   thorpej 
    303   1.1   thorpej 	return (int)tval;
    304   1.1   thorpej }
    305   1.1   thorpej 
    306   1.3       chs void gettimer0count(struct count64 *);
    307   1.3       chs 
    308   1.1   thorpej /* must be called at SPL_CLOCK or higher */
    309  1.12   gdamore void gettimer0count(struct count64 *pcount)
    310   1.1   thorpej {
    311   1.1   thorpej 	unsigned current, ticks, oldlo;
    312   1.1   thorpej 
    313   1.1   thorpej 	/*
    314   1.1   thorpej 	 * Latch the current value of the timer and then read it.
    315   1.4       wiz 	 * This guarantees an atomic reading of the time.
    316   1.1   thorpej 	 */
    317   1.1   thorpej 
    318   1.1   thorpej 	current = gettick();
    319   1.1   thorpej 
    320   1.1   thorpej 	if (timer0last >= current)
    321  1.12   gdamore 		ticks = timer0last - current;
    322   1.1   thorpej 	else
    323  1.12   gdamore 		ticks = timer0last + (TIMER0_ROLLOVER - current);
    324   1.1   thorpej 
    325   1.1   thorpej 	timer0last = current;
    326   1.1   thorpej 
    327   1.1   thorpej 	oldlo = timer0count.lo;
    328   1.1   thorpej 
    329   1.1   thorpej 	if (oldlo > (timer0count.lo = oldlo + ticks)) /* carry? */
    330  1.12   gdamore 		timer0count.hi++;
    331   1.1   thorpej 
    332   1.1   thorpej 	*pcount = timer0count;
    333   1.1   thorpej }
    334   1.1   thorpej 
    335   1.1   thorpej static int
    336  1.12   gdamore clockintr(void *arg)
    337   1.1   thorpej {
    338   1.1   thorpej 	struct clockframe *frame = arg;		/* not strictly necessary */
    339   1.1   thorpej 	extern void isa_specific_eoi(int irq);
    340   1.1   thorpej #ifdef TESTHAT
    341   1.1   thorpej 	static int ticks = 0;
    342   1.1   thorpej #endif
    343   1.1   thorpej 	static int hatUnwedgeCtr = 0;
    344   1.1   thorpej 
    345   1.1   thorpej 	gettimer0count(&timer0_at_last_clockintr);
    346   1.1   thorpej 
    347   1.1   thorpej 	mc146818_read(NULL, MC_REGC); /* clear the clock interrupt */
    348   1.1   thorpej 
    349   1.1   thorpej 	/* check to see if the high-availability timer needs to be unwedged */
    350   1.1   thorpej 	if (++hatUnwedgeCtr >= (hz / HAT_MIN_FREQ)) {
    351  1.12   gdamore 		hatUnwedgeCtr = 0;
    352  1.17   msaitoh 		hatUnwedge();
    353   1.1   thorpej 	}
    354   1.1   thorpej 
    355   1.1   thorpej #ifdef TESTHAT
    356   1.1   thorpej 	++ticks;
    357   1.1   thorpej 
    358   1.1   thorpej 	if (testHatOn && ((ticks & 0x3f) == 0)) {
    359  1.12   gdamore 		if (testHatOn == 1) {
    360  1.12   gdamore 			hatClkAdjust(hatCount2);
    361  1.12   gdamore 			testHatOn = 2;
    362  1.12   gdamore 		} else {
    363  1.12   gdamore 			testHatOn = 0;
    364  1.12   gdamore 			hatClkOff();
    365  1.12   gdamore 			printf("hat off status: %d %d %x\n", nHats,
    366  1.12   gdamore 			    nHatWedges, fiqReason);
    367  1.12   gdamore 		}
    368   1.1   thorpej 	} else if (!testHatOn && (ticks & 0x1ff) == 0) {
    369  1.12   gdamore 		printf("hat on status: %d %d %x\n",
    370  1.12   gdamore 		    nHats, nHatWedges, fiqReason);
    371  1.12   gdamore 		testHatOn = 1;
    372  1.12   gdamore 		nHats = 0;
    373  1.12   gdamore 		fiqReason = 0;
    374  1.12   gdamore 		hatClkOn(hatCount, hatTest, 0xfeedface,
    375  1.12   gdamore 		    hatStack + HATSTACKSIZE - sizeof(unsigned),
    376  1.12   gdamore 		    hatWedge);
    377   1.1   thorpej 	}
    378   1.1   thorpej #endif
    379   1.1   thorpej 	hardclock(frame);
    380  1.15   tsutsui 	return(1);
    381   1.1   thorpej }
    382   1.1   thorpej 
    383   1.1   thorpej static int
    384  1.12   gdamore gettick(void)
    385   1.1   thorpej {
    386   1.1   thorpej 	u_char lo, hi;
    387   1.1   thorpej 	u_int savedints;
    388   1.1   thorpej 
    389   1.1   thorpej 	/* Don't want someone screwing with the counter while we're here. */
    390   1.1   thorpej 	savedints = disable_interrupts(I32_bit);
    391   1.1   thorpej 	/* Select counter 0 and latch it. */
    392   1.1   thorpej 	outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
    393   1.1   thorpej 	lo = inb(IO_TIMER1 + TIMER_CNTR0);
    394   1.1   thorpej 	hi = inb(IO_TIMER1 + TIMER_CNTR0);
    395   1.1   thorpej 	restore_interrupts(savedints);
    396   1.1   thorpej 	return ((hi << 8) | lo);
    397   1.1   thorpej }
    398   1.1   thorpej 
    399   1.1   thorpej /* modifications from i386 to shark isa version:
    400   1.1   thorpej    - removed hardcoded "n -=" values that approximated the time to
    401   1.1   thorpej      calculate delay ticks
    402  1.19    andvar    - made the time to calculate delay ticks almost negligible. 4 multiplies
    403   1.1   thorpej      = maximum of 12 cycles = 75ns on a slow SA-110, plus a bunch of shifts;
    404   1.1   thorpej      as opposed to 4 multiplies plus a bunch of divides.
    405   1.1   thorpej    - removed i386 assembly language hack
    406   1.1   thorpej    - put code in findcpuspeed that works even if FIRST_GUESS is orders
    407   1.1   thorpej      of magnitude low
    408   1.1   thorpej    - put code in delay() to use delayloop() for short delays
    409   1.1   thorpej    - microtime no longer in assembly language
    410   1.1   thorpej */
    411   1.1   thorpej 
    412   1.1   thorpej /*
    413   1.1   thorpej  * Wait "n" microseconds.
    414   1.1   thorpej  * Relies on timer 1 counting down from (TIMER_FREQ / hz) at TIMER_FREQ Hz.
    415   1.1   thorpej  * Note: timer had better have been programmed before this is first used!
    416   1.1   thorpej  * (Note that we use `rate generator' mode, which counts at 1:1; `square
    417   1.1   thorpej  * wave' mode counts at 2:1).
    418   1.1   thorpej  */
    419   1.1   thorpej void
    420  1.12   gdamore delay(unsigned n)
    421   1.1   thorpej {
    422   1.8       scw 	int ticks, otick;
    423   1.1   thorpej 	int nticks;
    424   1.1   thorpej 
    425   1.1   thorpej 	if (n < 100) {
    426  1.12   gdamore 		/* it can take a long time (1 usec or longer) just for
    427  1.12   gdamore 		   1 ISA read, so it's best not to use the timer for
    428  1.12   gdamore 		   short delays */
    429  1.12   gdamore 		delayloop((n * count1024usec) >> 10);
    430  1.12   gdamore 		return;
    431   1.1   thorpej 	}
    432   1.1   thorpej 
    433   1.1   thorpej 	/*
    434   1.1   thorpej 	 * Read the counter first, so that the rest of the setup overhead is
    435   1.1   thorpej 	 * counted.
    436   1.1   thorpej 	 */
    437   1.1   thorpej 	otick = gettick();
    438   1.1   thorpej 
    439   1.1   thorpej 	/*
    440   1.1   thorpej 	 * Calculate ((n * TIMER_FREQ) / 1e6) without using floating point and
    441   1.1   thorpej 	 * without any avoidable overflows.
    442   1.1   thorpej 	 */
    443   1.1   thorpej 	{
    444   1.1   thorpej 	        /* a Musec = 2^20 usec */
    445   1.1   thorpej 		int Musec = n >> 20,
    446   1.1   thorpej 		    usec = n & ((1 << 20) - 1);
    447   1.1   thorpej 		nticks
    448   1.1   thorpej 		  = (Musec * TIMER_MUSECFREQ) +
    449   1.1   thorpej 		    (usec * (TIMER_MUSECFREQ >> 20)) +
    450   1.1   thorpej 		    ((usec * ((TIMER_MUSECFREQ & ((1 <<20) - 1)) >>10)) >>10) +
    451   1.1   thorpej 		    ((usec * (TIMER_MUSECFREQ & ((1 << 10) - 1))) >> 20);
    452   1.1   thorpej 	}
    453   1.1   thorpej 
    454   1.1   thorpej 	while (nticks > 0) {
    455   1.8       scw 		ticks = gettick();
    456   1.8       scw 		if (ticks > otick)
    457   1.8       scw 			nticks -= TIMER0_ROLLOVER - (ticks - otick);
    458   1.1   thorpej 		else
    459   1.8       scw 			nticks -= otick - ticks;
    460   1.8       scw 		otick = ticks;
    461   1.1   thorpej 	}
    462   1.1   thorpej 
    463   1.1   thorpej }
    464   1.1   thorpej 
    465   1.1   thorpej void
    466  1.12   gdamore sysbeepstop(void *arg)
    467   1.1   thorpej {
    468   1.1   thorpej }
    469   1.1   thorpej 
    470   1.1   thorpej void
    471  1.12   gdamore sysbeep(int pitch, int period)
    472   1.1   thorpej {
    473   1.1   thorpej }
    474   1.1   thorpej 
    475   1.1   thorpej #define FIRST_GUESS   0x2000
    476   1.1   thorpej 
    477   1.1   thorpej static void
    478  1.12   gdamore findcpuspeed(void)
    479   1.1   thorpej {
    480   1.1   thorpej 	int ticks;
    481   1.1   thorpej 	unsigned int guess = FIRST_GUESS;
    482   1.1   thorpej 
    483   1.1   thorpej 	while (1) { /* loop until accurate enough */
    484  1.12   gdamore 		/* Put counter in count down mode */
    485  1.12   gdamore 		outb(IO_TIMER1 + TIMER_MODE,
    486  1.12   gdamore 		    TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
    487  1.12   gdamore 		outb(IO_TIMER1 + TIMER_CNTR0, 0xff);
    488  1.12   gdamore 		outb(IO_TIMER1 + TIMER_CNTR0, 0xff);
    489  1.12   gdamore 		delayloop(guess);
    490  1.12   gdamore 
    491  1.12   gdamore 		/* Read the value left in the counter */
    492  1.12   gdamore 		/*
    493  1.12   gdamore 		 * Formula for delaycount is:
    494  1.12   gdamore 		 *  (loopcount * timer clock speed) / (counter ticks * 1000)
    495  1.12   gdamore 		 */
    496  1.12   gdamore 		ticks = 0xFFFF - gettick();
    497  1.12   gdamore 		if (ticks == 0) ticks = 1; /* just in case */
    498  1.12   gdamore 		if (ticks < (TIMER_MUSECDIV(1024))) { /* not accurate enough */
    499  1.18  riastrad 			guess *= uimax(2, (TIMER_MUSECDIV(1024) / ticks));
    500  1.12   gdamore 			continue;
    501  1.12   gdamore 		}
    502  1.12   gdamore 		count1024usec = (guess * (TIMER_MUSECDIV(1024))) / ticks;
    503  1.12   gdamore 		return;
    504   1.1   thorpej 	}
    505   1.1   thorpej }
    506   1.1   thorpej 
    507   1.1   thorpej static void
    508  1.12   gdamore delayloop(int counts)
    509   1.1   thorpej {
    510  1.12   gdamore 	while (counts--)
    511  1.12   gdamore 		__insn_barrier();
    512   1.1   thorpej }
    513   1.1   thorpej 
    514   1.1   thorpej void
    515  1.12   gdamore cpu_initclocks(void)
    516   1.1   thorpej {
    517   1.1   thorpej         unsigned hzval;
    518   1.1   thorpej 
    519   1.1   thorpej 	printf("clock: hz=%d stathz = %d profhz = %d\n", hz, stathz, profhz);
    520   1.1   thorpej 
    521   1.1   thorpej 	/* install RTC interrupt handler */
    522   1.1   thorpej 	(void)isa_intr_establish(NULL, IRQ_RTC, IST_LEVEL, IPL_CLOCK,
    523   1.1   thorpej 				 clockintr, 0);
    524   1.1   thorpej 
    525   1.1   thorpej 	/* set  up periodic interrupt @ hz
    526   1.1   thorpej 	   this is the subset of hz values in kern_clock.c that are
    527   1.1   thorpej 	   supported by the ISA RTC */
    528   1.1   thorpej 	switch (hz) {
    529   1.1   thorpej 	case 64:
    530   1.1   thorpej 		hzval = MC_RATE_64_Hz;
    531   1.1   thorpej 		break;
    532   1.1   thorpej 	case 128:
    533   1.1   thorpej 		hzval = MC_RATE_128_Hz;
    534   1.1   thorpej 		break;
    535   1.1   thorpej 	case 256:
    536   1.1   thorpej 		hzval = MC_RATE_256_Hz;
    537   1.1   thorpej 		break;
    538   1.1   thorpej 	case 1024:
    539   1.1   thorpej 		hzval = MC_RATE_1024_Hz;
    540   1.1   thorpej 		break;
    541   1.1   thorpej 	default:
    542   1.2    provos 		panic("cannot configure hz = %d", hz);
    543   1.1   thorpej         }
    544   1.1   thorpej 
    545   1.1   thorpej 	rtcinit(); /* make sure basics are done by now */
    546   1.1   thorpej 
    547   1.1   thorpej 	/* blast values to set up clock interrupt */
    548   1.1   thorpej 	mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | hzval);
    549   1.1   thorpej 	/* enable periodic interrupt */
    550   1.1   thorpej 	mc146818_write(NULL, MC_REGB,
    551   1.1   thorpej 		       mc146818_read(NULL, MC_REGB) | MC_REGB_PIE);
    552  1.13   gdamore 
    553  1.13   gdamore 	tc_init_i8253();
    554   1.1   thorpej }
    555   1.1   thorpej 
    556   1.1   thorpej void
    557  1.12   gdamore rtcinit(void)
    558   1.1   thorpej {
    559   1.1   thorpej 	static int first_rtcopen_ever = 1;
    560   1.1   thorpej 
    561   1.1   thorpej 	if (!first_rtcopen_ever)
    562   1.1   thorpej 		return;
    563   1.1   thorpej 	first_rtcopen_ever = 0;
    564   1.1   thorpej 
    565   1.1   thorpej 	mc146818_write(NULL, MC_REGA,			/* XXX softc */
    566   1.1   thorpej 	    MC_BASE_32_KHz | MC_RATE_1024_Hz);
    567   1.1   thorpej 	mc146818_write(NULL, MC_REGB, MC_REGB_24HR);	/* XXX softc */
    568   1.1   thorpej }
    569   1.1   thorpej 
    570   1.1   thorpej void
    571  1.12   gdamore setstatclockrate(int arg)
    572   1.1   thorpej {
    573   1.1   thorpej }
    574   1.1   thorpej 
    575  1.13   gdamore static uint32_t
    576  1.13   gdamore i8253_get_timecount(struct timecounter *tc)
    577  1.13   gdamore {
    578  1.13   gdamore 	return (TIMER0_ROLLOVER - gettick());
    579  1.13   gdamore }
    580   1.1   thorpej 
    581   1.1   thorpej void
    582  1.13   gdamore tc_init_i8253(void)
    583   1.1   thorpej {
    584  1.13   gdamore 	static struct timecounter i8253_tc = {
    585  1.13   gdamore 		.tc_get_timecount = i8253_get_timecount,
    586  1.13   gdamore 		.tc_counter_mask = TIMER0_ROLLOVER,
    587  1.13   gdamore 		.tc_frequency = TIMER_FREQ,
    588  1.13   gdamore 		.tc_name = "i8253",
    589  1.13   gdamore 		.tc_quality = 100
    590  1.13   gdamore 	};
    591   1.1   thorpej 
    592  1.13   gdamore 	tc_init(&i8253_tc);
    593   1.1   thorpej }
    594   1.1   thorpej 
    595   1.1   thorpej /* End of clock.c */
    596