Home | History | Annotate | Line # | Download | only in dev
int.c revision 1.9.2.2
      1  1.9.2.2  skrll /*	$NetBSD: int.c,v 1.9.2.2 2004/08/03 10:40:00 skrll Exp $	*/
      2  1.9.2.2  skrll 
      3  1.9.2.2  skrll /*
      4  1.9.2.2  skrll  * Copyright (c) 2004 Christopher SEKIYA
      5  1.9.2.2  skrll  * All rights reserved.
      6  1.9.2.2  skrll  *
      7  1.9.2.2  skrll  * Redistribution and use in source and binary forms, with or without
      8  1.9.2.2  skrll  * modification, are permitted provided that the following conditions
      9  1.9.2.2  skrll  * are met:
     10  1.9.2.2  skrll  * 1. Redistributions of source code must retain the above copyright
     11  1.9.2.2  skrll  *    notice, this list of conditions and the following disclaimer.
     12  1.9.2.2  skrll  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.9.2.2  skrll  *    notice, this list of conditions and the following disclaimer in the
     14  1.9.2.2  skrll  *    documentation and/or other materials provided with the distribution.
     15  1.9.2.2  skrll  * 3. The name of the author may not be used to endorse or promote products
     16  1.9.2.2  skrll  *    derived from this software without specific prior written permission.
     17  1.9.2.2  skrll  *
     18  1.9.2.2  skrll  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  1.9.2.2  skrll  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  1.9.2.2  skrll  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  1.9.2.2  skrll  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  1.9.2.2  skrll  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     23  1.9.2.2  skrll  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24  1.9.2.2  skrll  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25  1.9.2.2  skrll  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  1.9.2.2  skrll  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  1.9.2.2  skrll  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  1.9.2.2  skrll  */
     29  1.9.2.2  skrll 
     30  1.9.2.2  skrll /*
     31  1.9.2.2  skrll  * INT/INT2/INT3 interrupt controller (used in Indy's, Indigo's, etc..)
     32  1.9.2.2  skrll  */
     33  1.9.2.2  skrll 
     34  1.9.2.2  skrll #include <sys/cdefs.h>
     35  1.9.2.2  skrll __KERNEL_RCSID(0, "$NetBSD: int.c,v 1.9.2.2 2004/08/03 10:40:00 skrll Exp $");
     36  1.9.2.2  skrll 
     37  1.9.2.2  skrll #include "opt_cputype.h"
     38  1.9.2.2  skrll 
     39  1.9.2.2  skrll #include <sys/param.h>
     40  1.9.2.2  skrll #include <sys/proc.h>
     41  1.9.2.2  skrll #include <sys/systm.h>
     42  1.9.2.2  skrll #include <sys/kernel.h>
     43  1.9.2.2  skrll #include <sys/device.h>
     44  1.9.2.2  skrll #include <sys/malloc.h>
     45  1.9.2.2  skrll 
     46  1.9.2.2  skrll #include <dev/ic/i8253reg.h>
     47  1.9.2.2  skrll #include <machine/sysconf.h>
     48  1.9.2.2  skrll #include <machine/machtype.h>
     49  1.9.2.2  skrll #include <machine/bus.h>
     50  1.9.2.2  skrll #include <mips/locore.h>
     51  1.9.2.2  skrll 
     52  1.9.2.2  skrll #include <mips/cache.h>
     53  1.9.2.2  skrll 
     54  1.9.2.2  skrll #include <sgimips/dev/int2reg.h>
     55  1.9.2.2  skrll #include <sgimips/dev/int2var.h>
     56  1.9.2.2  skrll 
     57  1.9.2.2  skrll static bus_space_handle_t ioh;
     58  1.9.2.2  skrll static bus_space_tag_t iot;
     59  1.9.2.2  skrll 
     60  1.9.2.2  skrll struct int_softc {
     61  1.9.2.2  skrll 	struct device sc_dev;
     62  1.9.2.2  skrll };
     63  1.9.2.2  skrll 
     64  1.9.2.2  skrll 
     65  1.9.2.2  skrll static int	int_match(struct device *, struct cfdata *, void *);
     66  1.9.2.2  skrll static void	int_attach(struct device *, struct device *, void *);
     67  1.9.2.2  skrll void 		int_local0_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
     68  1.9.2.2  skrll void		int_local1_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
     69  1.9.2.2  skrll int 		int_mappable_intr(void *);
     70  1.9.2.2  skrll void		*int_intr_establish(int, int, int (*)(void *), void *);
     71  1.9.2.2  skrll unsigned long	int_cal_timer(void);
     72  1.9.2.2  skrll void		int_8254_cal(void);
     73  1.9.2.2  skrll 
     74  1.9.2.2  skrll CFATTACH_DECL(int, sizeof(struct int_softc),
     75  1.9.2.2  skrll 	int_match, int_attach, NULL, NULL);
     76  1.9.2.2  skrll 
     77  1.9.2.2  skrll static int
     78  1.9.2.2  skrll int_match(struct device *parent, struct cfdata *match, void *aux)
     79  1.9.2.2  skrll {
     80  1.9.2.2  skrll 
     81  1.9.2.2  skrll 	if ((mach_type == MACH_SGI_IP12) || (mach_type == MACH_SGI_IP20) ||
     82  1.9.2.2  skrll 	    (mach_type == MACH_SGI_IP22) )
     83  1.9.2.2  skrll 		return 1;
     84  1.9.2.2  skrll 
     85  1.9.2.2  skrll 	return 0;
     86  1.9.2.2  skrll }
     87  1.9.2.2  skrll 
     88  1.9.2.2  skrll static void
     89  1.9.2.2  skrll int_attach(struct device *parent, struct device *self, void *aux)
     90  1.9.2.2  skrll {
     91  1.9.2.2  skrll 	u_int32_t address;
     92  1.9.2.2  skrll 
     93  1.9.2.2  skrll 	if (mach_type == MACH_SGI_IP12)
     94  1.9.2.2  skrll 		address = INT_IP12;
     95  1.9.2.2  skrll 	else if (mach_type == MACH_SGI_IP20)
     96  1.9.2.2  skrll 		address = INT_IP20;
     97  1.9.2.2  skrll 	else if (mach_type == MACH_SGI_IP22) {
     98  1.9.2.2  skrll 		if (mach_subtype == MACH_SGI_IP22_FULLHOUSE)
     99  1.9.2.2  skrll 			address = INT_IP22;
    100  1.9.2.2  skrll 		else
    101  1.9.2.2  skrll 			address = INT_IP24;
    102  1.9.2.2  skrll 	} else
    103  1.9.2.2  skrll 		panic("\nint0: passed match, but failed attach?");
    104  1.9.2.2  skrll 
    105  1.9.2.2  skrll 	printf(" addr 0x%x", address);
    106  1.9.2.2  skrll 
    107  1.9.2.2  skrll 	bus_space_map(iot, address, 0, 0, &ioh);
    108  1.9.2.2  skrll 	iot = SGIMIPS_BUS_SPACE_NORMAL;
    109  1.9.2.2  skrll 
    110  1.9.2.2  skrll 	/* Clean out interrupt masks */
    111  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, 0);
    112  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_LOCAL1_MASK, 0);
    113  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_MAP_MASK0, 0);
    114  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_MAP_MASK1, 0);
    115  1.9.2.2  skrll 
    116  1.9.2.2  skrll 	/* Reset timer interrupts */
    117  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_TIMER_CLEAR, 0x03);
    118  1.9.2.2  skrll 
    119  1.9.2.2  skrll 	switch (mach_type) {
    120  1.9.2.2  skrll 		case MACH_SGI_IP12:
    121  1.9.2.2  skrll 			platform.intr1 = int_local0_intr;
    122  1.9.2.2  skrll 			platform.intr2 = int_local1_intr;
    123  1.9.2.2  skrll 			int_8254_cal();
    124  1.9.2.2  skrll 			break;
    125  1.9.2.2  skrll #ifdef MIPS3
    126  1.9.2.2  skrll 		case MACH_SGI_IP20:
    127  1.9.2.2  skrll 		case MACH_SGI_IP22:
    128  1.9.2.2  skrll 		{
    129  1.9.2.2  skrll 			int i;
    130  1.9.2.2  skrll 			unsigned long cps;
    131  1.9.2.2  skrll 			unsigned long ctrdiff[3];
    132  1.9.2.2  skrll 
    133  1.9.2.2  skrll 			platform.intr0 = int_local0_intr;
    134  1.9.2.2  skrll 			platform.intr1 = int_local1_intr;
    135  1.9.2.2  skrll 
    136  1.9.2.2  skrll 			/* calibrate timer */
    137  1.9.2.2  skrll 			int_cal_timer();
    138  1.9.2.2  skrll 
    139  1.9.2.2  skrll 			cps = 0;
    140  1.9.2.2  skrll 			for (i = 0;
    141  1.9.2.2  skrll 			    i < sizeof(ctrdiff) / sizeof(ctrdiff[0]); i++) {
    142  1.9.2.2  skrll 				do {
    143  1.9.2.2  skrll 					ctrdiff[i] = int_cal_timer();
    144  1.9.2.2  skrll 				} while (ctrdiff[i] == 0);
    145  1.9.2.2  skrll 
    146  1.9.2.2  skrll 				cps += ctrdiff[i];
    147  1.9.2.2  skrll 			}
    148  1.9.2.2  skrll 
    149  1.9.2.2  skrll 			cps = cps / (sizeof(ctrdiff) / sizeof(ctrdiff[0]));
    150  1.9.2.2  skrll 
    151  1.9.2.2  skrll 			printf(": bus %luMHz, CPU %luMHz",
    152  1.9.2.2  skrll 			    cps / 10000, cps / 5000);
    153  1.9.2.2  skrll 
    154  1.9.2.2  skrll 			/* R4k/R4400/R4600/R5k count at half CPU frequency */
    155  1.9.2.2  skrll 			curcpu()->ci_cpu_freq = 2 * cps * hz;
    156  1.9.2.2  skrll 		}
    157  1.9.2.2  skrll #endif /* MIPS3 */
    158  1.9.2.2  skrll 
    159  1.9.2.2  skrll 			break;
    160  1.9.2.2  skrll 		default:
    161  1.9.2.2  skrll 			panic("int0: unsupported machine type %i\n", mach_type);
    162  1.9.2.2  skrll 			break;
    163  1.9.2.2  skrll 	}
    164  1.9.2.2  skrll 
    165  1.9.2.2  skrll 	printf("\n");
    166  1.9.2.2  skrll 
    167  1.9.2.2  skrll 	curcpu()->ci_cycles_per_hz = curcpu()->ci_cpu_freq / (2 * hz);
    168  1.9.2.2  skrll 	curcpu()->ci_divisor_delay = curcpu()->ci_cpu_freq / (2 * 1000000);
    169  1.9.2.2  skrll 	MIPS_SET_CI_RECIPRICAL(curcpu());
    170  1.9.2.2  skrll 
    171  1.9.2.2  skrll 	if (mach_type == MACH_SGI_IP22) {
    172  1.9.2.2  skrll 		/* Wire interrupts 7, 11 to mappable interrupt 0,1 handlers */
    173  1.9.2.2  skrll 		intrtab[7].ih_fun = int_mappable_intr;
    174  1.9.2.2  skrll 		intrtab[7].ih_arg = (void*) 0;
    175  1.9.2.2  skrll 
    176  1.9.2.2  skrll 		intrtab[11].ih_fun = int_mappable_intr;
    177  1.9.2.2  skrll 		intrtab[11].ih_arg = (void*) 1;
    178  1.9.2.2  skrll 	}
    179  1.9.2.2  skrll 
    180  1.9.2.2  skrll 	platform.intr_establish = int_intr_establish;
    181  1.9.2.2  skrll }
    182  1.9.2.2  skrll 
    183  1.9.2.2  skrll int
    184  1.9.2.2  skrll int_mappable_intr(void *arg)
    185  1.9.2.2  skrll {
    186  1.9.2.2  skrll 	int i;
    187  1.9.2.2  skrll 	int ret;
    188  1.9.2.2  skrll 	int intnum;
    189  1.9.2.2  skrll 	u_int32_t mstat;
    190  1.9.2.2  skrll 	u_int32_t mmask;
    191  1.9.2.2  skrll 	int which = (int)arg;
    192  1.9.2.2  skrll 	struct sgimips_intrhand *ih;
    193  1.9.2.2  skrll 
    194  1.9.2.2  skrll 	ret = 0;
    195  1.9.2.2  skrll 	mstat = bus_space_read_4(iot, ioh, INT2_MAP_STATUS);
    196  1.9.2.2  skrll 	mmask = bus_space_read_4(iot, ioh, INT2_MAP_MASK0 + (which << 2));
    197  1.9.2.2  skrll 
    198  1.9.2.2  skrll 	mstat &= mmask;
    199  1.9.2.2  skrll 
    200  1.9.2.2  skrll 	for (i = 0; i < 8; i++) {
    201  1.9.2.2  skrll 		intnum = i + 16 + (which << 3);
    202  1.9.2.2  skrll 		if (mstat & (1 << i)) {
    203  1.9.2.2  skrll 			for (ih = &intrtab[intnum]; ih != NULL;
    204  1.9.2.2  skrll 							ih = ih->ih_next) {
    205  1.9.2.2  skrll 				if (ih->ih_fun != NULL)
    206  1.9.2.2  skrll 					ret |= (ih->ih_fun)(ih->ih_arg);
    207  1.9.2.2  skrll 				else
    208  1.9.2.2  skrll 					printf("int0: unexpected mapped "
    209  1.9.2.2  skrll 					       "interrupt %d\n", intnum);
    210  1.9.2.2  skrll 			}
    211  1.9.2.2  skrll 		}
    212  1.9.2.2  skrll 	}
    213  1.9.2.2  skrll 
    214  1.9.2.2  skrll 	return ret;
    215  1.9.2.2  skrll }
    216  1.9.2.2  skrll 
    217  1.9.2.2  skrll void
    218  1.9.2.2  skrll int_local0_intr(u_int32_t status, u_int32_t cause, u_int32_t pc,
    219  1.9.2.2  skrll 		u_int32_t ipending)
    220  1.9.2.2  skrll {
    221  1.9.2.2  skrll 	int i;
    222  1.9.2.2  skrll 	u_int32_t l0stat;
    223  1.9.2.2  skrll 	u_int32_t l0mask;
    224  1.9.2.2  skrll 	struct sgimips_intrhand *ih;
    225  1.9.2.2  skrll 
    226  1.9.2.2  skrll 	l0stat = bus_space_read_4(iot, ioh, INT2_LOCAL0_STATUS);
    227  1.9.2.2  skrll 	l0mask = bus_space_read_4(iot, ioh, INT2_LOCAL0_MASK);
    228  1.9.2.2  skrll 
    229  1.9.2.2  skrll 	/* The "FIFO full" bit is apparently not latched in the ISR, which
    230  1.9.2.2  skrll 	   means that it won't be present in l0stat unless we're very lucky.
    231  1.9.2.2  skrll 	   If no interrupts are pending, assume that it was caused by a full
    232  1.9.2.2  skrll 	   FIFO and dispatch.
    233  1.9.2.2  skrll 	 */
    234  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, l0mask & (0xfe));
    235  1.9.2.2  skrll 	if ( (l0mask & 0x01) && ((l0stat & l0mask) == 0) )
    236  1.9.2.2  skrll 	  l0stat = 0x01;
    237  1.9.2.2  skrll 
    238  1.9.2.2  skrll 	for (i = 0; i < 8; i++) {
    239  1.9.2.2  skrll 		if ( (l0stat & l0mask) & (1 << i)) {
    240  1.9.2.2  skrll 			for (ih = &intrtab[i]; ih != NULL; ih = ih->ih_next) {
    241  1.9.2.2  skrll 				if (ih->ih_fun != NULL)
    242  1.9.2.2  skrll 					(ih->ih_fun)(ih->ih_arg);
    243  1.9.2.2  skrll 				else
    244  1.9.2.2  skrll 					printf("int0: unexpected local0 "
    245  1.9.2.2  skrll 					       "interrupt %d\n", i);
    246  1.9.2.2  skrll 			}
    247  1.9.2.2  skrll 		}
    248  1.9.2.2  skrll 	}
    249  1.9.2.2  skrll 
    250  1.9.2.2  skrll 	/* Unmask FIFO */
    251  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, l0mask | 0x01);
    252  1.9.2.2  skrll }
    253  1.9.2.2  skrll 
    254  1.9.2.2  skrll void
    255  1.9.2.2  skrll int_local1_intr(u_int32_t status, u_int32_t cause, u_int32_t pc,
    256  1.9.2.2  skrll 		u_int32_t ipending)
    257  1.9.2.2  skrll {
    258  1.9.2.2  skrll 	int i;
    259  1.9.2.2  skrll 	u_int32_t l1stat;
    260  1.9.2.2  skrll 	u_int32_t l1mask;
    261  1.9.2.2  skrll 	struct sgimips_intrhand *ih;
    262  1.9.2.2  skrll 
    263  1.9.2.2  skrll 	l1stat = bus_space_read_4(iot, ioh, INT2_LOCAL1_STATUS);
    264  1.9.2.2  skrll 	l1mask = bus_space_read_4(iot, ioh, INT2_LOCAL1_MASK);
    265  1.9.2.2  skrll 
    266  1.9.2.2  skrll 	l1stat &= l1mask;
    267  1.9.2.2  skrll 
    268  1.9.2.2  skrll 	for (i = 0; i < 8; i++) {
    269  1.9.2.2  skrll 		if (l1stat & (1 << i)) {
    270  1.9.2.2  skrll 			for (ih = &intrtab[8+i]; ih != NULL; ih = ih->ih_next) {
    271  1.9.2.2  skrll 				if (ih->ih_fun != NULL)
    272  1.9.2.2  skrll 					(ih->ih_fun)(ih->ih_arg);
    273  1.9.2.2  skrll 				else
    274  1.9.2.2  skrll 					printf("int0: unexpected local1 "
    275  1.9.2.2  skrll 					       " interrupt %x\n", 8 + i);
    276  1.9.2.2  skrll 			}
    277  1.9.2.2  skrll 		}
    278  1.9.2.2  skrll 	}
    279  1.9.2.2  skrll }
    280  1.9.2.2  skrll 
    281  1.9.2.2  skrll void *
    282  1.9.2.2  skrll int_intr_establish(int level, int ipl, int (*handler) (void *), void *arg)
    283  1.9.2.2  skrll {
    284  1.9.2.2  skrll 	u_int32_t mask;
    285  1.9.2.2  skrll 
    286  1.9.2.2  skrll 	if (level < 0 || level >= NINTR)
    287  1.9.2.2  skrll 		panic("invalid interrupt level");
    288  1.9.2.2  skrll 
    289  1.9.2.2  skrll 	if (intrtab[level].ih_fun == NULL) {
    290  1.9.2.2  skrll 		intrtab[level].ih_fun = handler;
    291  1.9.2.2  skrll 		intrtab[level].ih_arg = arg;
    292  1.9.2.2  skrll 		intrtab[level].ih_next = NULL;
    293  1.9.2.2  skrll 	} else {
    294  1.9.2.2  skrll 		struct sgimips_intrhand *n, *ih = malloc(sizeof *ih,
    295  1.9.2.2  skrll 							 M_DEVBUF, M_NOWAIT);
    296  1.9.2.2  skrll 
    297  1.9.2.2  skrll 		if (ih == NULL) {
    298  1.9.2.2  skrll 			printf("int_intr_establish: can't allocate handler\n");
    299  1.9.2.2  skrll 			return (void *)NULL;
    300  1.9.2.2  skrll 		}
    301  1.9.2.2  skrll 
    302  1.9.2.2  skrll 		ih->ih_fun = handler;
    303  1.9.2.2  skrll 		ih->ih_arg = arg;
    304  1.9.2.2  skrll 		ih->ih_next = NULL;
    305  1.9.2.2  skrll 
    306  1.9.2.2  skrll 		for (n = &intrtab[level]; n->ih_next != NULL; n = n->ih_next)
    307  1.9.2.2  skrll 			;
    308  1.9.2.2  skrll 
    309  1.9.2.2  skrll 		n->ih_next = ih;
    310  1.9.2.2  skrll 
    311  1.9.2.2  skrll 		return (void *)NULL;	/* vector already set */
    312  1.9.2.2  skrll 	}
    313  1.9.2.2  skrll 
    314  1.9.2.2  skrll 
    315  1.9.2.2  skrll 	if (level < 8) {
    316  1.9.2.2  skrll 		mask = bus_space_read_4(iot, ioh, INT2_LOCAL0_MASK);
    317  1.9.2.2  skrll 		mask |= (1 << level);
    318  1.9.2.2  skrll 		bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, mask);
    319  1.9.2.2  skrll 	} else if (level < 16) {
    320  1.9.2.2  skrll 		mask = bus_space_read_4(iot, ioh, INT2_LOCAL1_MASK);
    321  1.9.2.2  skrll 		mask |= (1 << (level - 8));
    322  1.9.2.2  skrll 		bus_space_write_4(iot, ioh, INT2_LOCAL1_MASK, mask);
    323  1.9.2.2  skrll 	} else if (level < 24) {
    324  1.9.2.2  skrll 		/* Map0 interrupt maps to l0 bit 7, so turn that on too */
    325  1.9.2.2  skrll 		mask = bus_space_read_4(iot, ioh, INT2_LOCAL0_MASK);
    326  1.9.2.2  skrll 		mask |= (1 << 7);
    327  1.9.2.2  skrll 		bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, mask);
    328  1.9.2.2  skrll 
    329  1.9.2.2  skrll 		mask = bus_space_read_4(iot, ioh, INT2_MAP_MASK0);
    330  1.9.2.2  skrll 		mask |= (1 << (level - 16));
    331  1.9.2.2  skrll 		bus_space_write_4(iot, ioh, INT2_MAP_MASK0, mask);
    332  1.9.2.2  skrll 	} else {
    333  1.9.2.2  skrll 		/* Map1 interrupt maps to l1 bit 3, so turn that on too */
    334  1.9.2.2  skrll 		mask = bus_space_read_4(iot, ioh, INT2_LOCAL1_MASK);
    335  1.9.2.2  skrll 		mask |= (1 << 3);
    336  1.9.2.2  skrll 		bus_space_write_4(iot, ioh, INT2_LOCAL1_MASK, mask);
    337  1.9.2.2  skrll 
    338  1.9.2.2  skrll 		mask = bus_space_read_4(iot, ioh, INT2_MAP_MASK1);
    339  1.9.2.2  skrll 		mask |= (1 << (level - 24));
    340  1.9.2.2  skrll 		bus_space_write_4(iot, ioh, INT2_MAP_MASK1, mask);
    341  1.9.2.2  skrll 	}
    342  1.9.2.2  skrll 
    343  1.9.2.2  skrll 	return (void *)NULL;
    344  1.9.2.2  skrll }
    345  1.9.2.2  skrll 
    346  1.9.2.2  skrll #ifdef MIPS3
    347  1.9.2.2  skrll unsigned long
    348  1.9.2.2  skrll int_cal_timer(void)
    349  1.9.2.2  skrll {
    350  1.9.2.2  skrll 	int s;
    351  1.9.2.2  skrll 	int roundtime;
    352  1.9.2.2  skrll 	int sampletime;
    353  1.9.2.2  skrll 	int startmsb, lsb, msb;
    354  1.9.2.2  skrll 	unsigned long startctr, endctr;
    355  1.9.2.2  skrll 
    356  1.9.2.2  skrll 	/*
    357  1.9.2.2  skrll 	 * NOTE: HZ must be greater than 15 for this to work, as otherwise
    358  1.9.2.2  skrll 	 * we'll overflow the counter.  We round the answer to hearest 1
    359  1.9.2.2  skrll 	 * MHz of the master (2x) clock.
    360  1.9.2.2  skrll 	 */
    361  1.9.2.2  skrll 	roundtime = (1000000 / hz) / 2;
    362  1.9.2.2  skrll 	sampletime = (1000000 / hz) + 0xff;
    363  1.9.2.2  skrll 	startmsb = (sampletime >> 8);
    364  1.9.2.2  skrll 
    365  1.9.2.2  skrll 	s = splhigh();
    366  1.9.2.2  skrll 
    367  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_TIMER_CONTROL,
    368  1.9.2.2  skrll 		( TIMER_SEL2 | TIMER_16BIT | TIMER_RATEGEN) );
    369  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_TIMER_2, (sampletime & 0xff));
    370  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_TIMER_2, (sampletime >> 8));
    371  1.9.2.2  skrll 
    372  1.9.2.2  skrll 	startctr = mips3_cp0_count_read();
    373  1.9.2.2  skrll 
    374  1.9.2.2  skrll 	/* Wait for the MSB to count down to zero */
    375  1.9.2.2  skrll 	do {
    376  1.9.2.2  skrll 		bus_space_write_4(iot, ioh, INT2_TIMER_CONTROL, TIMER_SEL2 );
    377  1.9.2.2  skrll 		lsb = bus_space_read_4(iot, ioh, INT2_TIMER_2) & 0xff;
    378  1.9.2.2  skrll 		msb = bus_space_read_4(iot, ioh, INT2_TIMER_2) & 0xff;
    379  1.9.2.2  skrll 
    380  1.9.2.2  skrll 		endctr = mips3_cp0_count_read();
    381  1.9.2.2  skrll 	} while (msb);
    382  1.9.2.2  skrll 
    383  1.9.2.2  skrll 	/* Turn off timer */
    384  1.9.2.2  skrll 	bus_space_write_4(iot, ioh, INT2_TIMER_CONTROL,
    385  1.9.2.2  skrll 		( TIMER_SEL2 | TIMER_16BIT | TIMER_SWSTROBE) );
    386  1.9.2.2  skrll 
    387  1.9.2.2  skrll 	splx(s);
    388  1.9.2.2  skrll 
    389  1.9.2.2  skrll 	return (endctr - startctr) / roundtime * roundtime;
    390  1.9.2.2  skrll }
    391  1.9.2.2  skrll #endif /* MIPS3 */
    392  1.9.2.2  skrll 
    393  1.9.2.2  skrll void
    394  1.9.2.2  skrll int_8254_cal(void)
    395  1.9.2.2  skrll {
    396  1.9.2.2  skrll 	int s;
    397  1.9.2.2  skrll 
    398  1.9.2.2  skrll 	s = splhigh();
    399  1.9.2.2  skrll 
    400  1.9.2.2  skrll 	bus_space_write_1(iot, ioh, INT2_TIMER_0 + 15,
    401  1.9.2.2  skrll                                 TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
    402  1.9.2.2  skrll 	bus_space_write_1(iot, ioh, INT2_TIMER_0 + 3, (20000 / hz) % 256);
    403  1.9.2.2  skrll 	wbflush();
    404  1.9.2.2  skrll 	delay(4);
    405  1.9.2.2  skrll 	bus_space_write_1(iot, ioh, INT2_TIMER_0 + 3, (20000 / hz) / 256);
    406  1.9.2.2  skrll 
    407  1.9.2.2  skrll 	bus_space_write_1(iot, ioh, INT2_TIMER_0 + 15,
    408  1.9.2.2  skrll                                 TIMER_SEL2|TIMER_RATEGEN|TIMER_16BIT);
    409  1.9.2.2  skrll 	bus_space_write_1(iot, ioh, INT2_TIMER_0 + 11, 50);
    410  1.9.2.2  skrll 	wbflush();
    411  1.9.2.2  skrll 	delay(4);
    412  1.9.2.2  skrll 	bus_space_write_1(iot, ioh, INT2_TIMER_0 + 11, 0);
    413  1.9.2.2  skrll 	splx(s);
    414  1.9.2.2  skrll }
    415  1.9.2.2  skrll 
    416  1.9.2.2  skrll void
    417  1.9.2.2  skrll int2_wait_fifo(u_int32_t flag)
    418  1.9.2.2  skrll {
    419  1.9.2.2  skrll 	if (ioh == 0)
    420  1.9.2.2  skrll 		delay(5000);
    421  1.9.2.2  skrll 	else
    422  1.9.2.2  skrll 		while (bus_space_read_4(iot, ioh, INT2_LOCAL0_STATUS) & flag)
    423  1.9.2.2  skrll 			;
    424  1.9.2.2  skrll }
    425