Home | History | Annotate | Line # | Download | only in dev
int.c revision 1.28
      1 /*	$NetBSD: int.c,v 1.28 2015/02/18 16:47:58 macallan Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2009 Stephen M. Rumble
      5  * Copyright (c) 2004 Christopher SEKIYA
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 /*
     32  * INT1/INT2/INT3 interrupt controllers (IP6, IP10, IP12, IP20, IP22, IP24...)
     33  */
     34 
     35 #include <sys/cdefs.h>
     36 __KERNEL_RCSID(0, "$NetBSD: int.c,v 1.28 2015/02/18 16:47:58 macallan Exp $");
     37 
     38 #define __INTR_PRIVATE
     39 #include "opt_cputype.h"
     40 
     41 #include <sys/param.h>
     42 #include <sys/proc.h>
     43 #include <sys/systm.h>
     44 #include <sys/timetc.h>
     45 #include <sys/kernel.h>
     46 #include <sys/device.h>
     47 #include <sys/malloc.h>
     48 
     49 #include <dev/ic/i8253reg.h>
     50 #include <machine/sysconf.h>
     51 #include <machine/machtype.h>
     52 #include <sys/bus.h>
     53 #include <mips/locore.h>
     54 
     55 #include <mips/cache.h>
     56 
     57 #include <sgimips/dev/int1reg.h>
     58 #include <sgimips/dev/int2reg.h>
     59 #include <sgimips/dev/int2var.h>
     60 
     61 static bus_space_handle_t ioh;
     62 static bus_space_tag_t iot;
     63 
     64 static int	int_match(device_t, cfdata_t, void *);
     65 static void	int_attach(device_t, device_t, void *);
     66 static void    *int1_intr_establish(int, int, int (*)(void *), void *);
     67 static void    *int2_intr_establish(int, int, int (*)(void *), void *);
     68 static void 	int1_local_intr(vaddr_t, uint32_t, uint32_t);
     69 static void 	int2_local0_intr(vaddr_t, uint32_t, uint32_t);
     70 static void	int2_local1_intr(vaddr_t, uint32_t, uint32_t);
     71 static int 	int2_mappable_intr(void *);
     72 static void	int_8254_cal(void);
     73 static u_int	int_8254_get_timecount(struct timecounter *);
     74 static void	int_8254_intr0(vaddr_t, uint32_t, uint32_t);
     75 static void	int_8254_intr1(vaddr_t, uint32_t, uint32_t);
     76 
     77 #ifdef MIPS3
     78 static u_long	int2_cpu_freq(device_t);
     79 static u_long	int2_cal_timer(void);
     80 #endif
     81 
     82 static struct timecounter int_8254_timecounter = {
     83 	int_8254_get_timecount,	/* get_timecount */
     84 	0,			/* no poll_pps */
     85 	~0u,			/* counter_mask */
     86 	0,			/* frequency; set in int_8254_cal */
     87 	"int i8254",		/* name */
     88 	100,			/* quality */
     89 	NULL,			/* prev */
     90 	NULL,			/* next */
     91 };
     92 
     93 static u_long int_8254_tc_count;
     94 
     95 CFATTACH_DECL_NEW(int, 0,
     96     int_match, int_attach, NULL, NULL);
     97 
     98 static int
     99 int_match(device_t parent, cfdata_t match, void *aux)
    100 {
    101 
    102 	switch (mach_type) {
    103 	case MACH_SGI_IP6 | MACH_SGI_IP10:
    104 	case MACH_SGI_IP12:
    105 	case MACH_SGI_IP20:
    106 	case MACH_SGI_IP22:
    107 		return 1;
    108 	}
    109 
    110 	return 0;
    111 }
    112 
    113 static void
    114 int_attach(device_t parent, device_t self, void *aux)
    115 {
    116 	uint32_t address;
    117 
    118 	switch (mach_type) {
    119 	case MACH_SGI_IP6 | MACH_SGI_IP10:
    120 		address = INT1_IP6_IP10;
    121 		break;
    122 
    123 	case MACH_SGI_IP12:
    124 		address = INT2_IP12;
    125 		break;
    126 
    127 	case MACH_SGI_IP20:
    128 		address = INT2_IP20;
    129 		break;
    130 
    131 	case MACH_SGI_IP22:
    132 		if (mach_subtype == MACH_SGI_IP22_FULLHOUSE)
    133 			address = INT2_IP22;
    134 		else
    135 			address = INT2_IP24;
    136 		break;
    137 
    138 	default:
    139 		panic("\nint0: passed match, but failed attach?");
    140 	}
    141 
    142 	printf(" addr 0x%x\n", address);
    143 
    144 	iot = normal_memt;
    145 	/*
    146 	 * XXX INT1 registers are spread *way* out, but for now this should
    147 	 * work
    148 	 */
    149 	bus_space_map(iot, address, 0x100, 0, &ioh);
    150 
    151 	switch (mach_type) {
    152 	case MACH_SGI_IP6 | MACH_SGI_IP10:
    153 		/* Clean out interrupt masks */
    154 		bus_space_write_1(iot, ioh, INT1_LOCAL_MASK, 0);
    155 
    156 		/* Turn off timers and clear interrupts */
    157 		bus_space_write_1(iot, ioh, INT1_TIMER_CONTROL,
    158 		    (TIMER_SEL0 | TIMER_16BIT | TIMER_SWSTROBE));
    159 		bus_space_write_1(iot, ioh, INT1_TIMER_CONTROL,
    160 		    (TIMER_SEL1 | TIMER_16BIT | TIMER_SWSTROBE));
    161 		bus_space_write_1(iot, ioh, INT1_TIMER_CONTROL,
    162 		    (TIMER_SEL2 | TIMER_16BIT | TIMER_SWSTROBE));
    163 		wbflush();
    164 		delay(4);
    165 		bus_space_read_1(iot, ioh, INT1_TIMER_0_ACK);
    166 		bus_space_read_1(iot, ioh, INT1_TIMER_1_ACK);
    167 
    168 		platform.intr_establish = int1_intr_establish;
    169 		platform.intr1 = int1_local_intr;
    170 		platform.intr2 = int_8254_intr0;
    171 		platform.intr4 = int_8254_intr1;
    172 		int_8254_cal();
    173 		break;
    174 
    175 	case MACH_SGI_IP12:
    176 	case MACH_SGI_IP20:
    177 	case MACH_SGI_IP22:
    178 		/* Clean out interrupt masks */
    179 		bus_space_write_1(iot, ioh, INT2_LOCAL0_MASK, 0);
    180 		bus_space_write_1(iot, ioh, INT2_LOCAL1_MASK, 0);
    181 		bus_space_write_1(iot, ioh, INT2_MAP_MASK0, 0);
    182 		bus_space_write_1(iot, ioh, INT2_MAP_MASK1, 0);
    183 
    184 		/* Reset timer interrupts */
    185 		bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL,
    186 		    (TIMER_SEL0 | TIMER_16BIT | TIMER_SWSTROBE));
    187 		bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL,
    188 		    (TIMER_SEL1 | TIMER_16BIT | TIMER_SWSTROBE));
    189 		bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL,
    190 		    (TIMER_SEL2 | TIMER_16BIT | TIMER_SWSTROBE));
    191 		wbflush();
    192 		delay(4);
    193 		bus_space_write_1(iot, ioh, INT2_TIMER_CLEAR, 0x03);
    194 
    195 		if (mach_type == MACH_SGI_IP12) {
    196 			platform.intr_establish = int2_intr_establish;
    197 			platform.intr1 = int2_local0_intr;
    198 			platform.intr2 = int2_local1_intr;
    199 			platform.intr3 = int_8254_intr0;
    200 			platform.intr4 = int_8254_intr1;
    201 			int_8254_cal();
    202 		} else {
    203 			platform.intr_establish = int2_intr_establish;
    204 			platform.intr0 = int2_local0_intr;
    205 			platform.intr1 = int2_local1_intr;
    206 #ifdef MIPS3
    207 			curcpu()->ci_cpu_freq = int2_cpu_freq(self);
    208 #endif
    209 		}
    210 		break;
    211 
    212 	default:
    213 		panic("int0: unsupported machine type %i\n", mach_type);
    214 	}
    215 
    216 	curcpu()->ci_cycles_per_hz = curcpu()->ci_cpu_freq / (2 * hz);
    217 	curcpu()->ci_divisor_delay = curcpu()->ci_cpu_freq / (2 * 1000000);
    218 
    219 	if (mach_type == MACH_SGI_IP22) {
    220 		/* Wire interrupts 7, 11 to mappable interrupt 0,1 handlers */
    221 		intrtab[7].ih_fun = int2_mappable_intr;
    222 		intrtab[7].ih_arg = (void*) 0;
    223 
    224 		intrtab[11].ih_fun = int2_mappable_intr;
    225 		intrtab[11].ih_arg = (void*) 1;
    226 	}
    227 }
    228 
    229 int
    230 int2_mappable_intr(void *arg)
    231 {
    232 	int i;
    233 	int ret;
    234 	int intnum;
    235 	uint32_t mstat;
    236 	uint32_t mmask;
    237 	int which = (intptr_t)arg;
    238 	struct sgimips_intrhand *ih;
    239 
    240 	ret = 0;
    241 	mstat = bus_space_read_1(iot, ioh, INT2_MAP_STATUS);
    242 	mmask = bus_space_read_1(iot, ioh, INT2_MAP_MASK0 + (which << 2));
    243 
    244 	mstat &= mmask;
    245 
    246 	for (i = 0; i < 8; i++) {
    247 		intnum = i + 16 + (which << 3);
    248 		if (mstat & (1 << i)) {
    249 			for (ih = &intrtab[intnum]; ih != NULL;
    250 			    ih = ih->ih_next) {
    251 				if (ih->ih_fun != NULL)
    252 					ret |= (ih->ih_fun)(ih->ih_arg);
    253 				else
    254 					printf("int0: unexpected mapped "
    255 					       "interrupt %d\n", intnum);
    256 			}
    257 		}
    258 	}
    259 
    260 	return ret;
    261 }
    262 
    263 static void
    264 int1_local_intr(vaddr_t pc, uint32_t status, uint32_t ipend)
    265 {
    266 	int i;
    267 	uint16_t stat;
    268 	uint8_t  mask;
    269 	struct sgimips_intrhand *ih;
    270 
    271 	stat = bus_space_read_2(iot, ioh, INT1_LOCAL_STATUS);
    272 	mask = bus_space_read_1(iot, ioh, INT1_LOCAL_MASK);
    273 
    274 	/* for STATUS, a 0 bit means interrupt is pending */
    275 	stat = ~stat & mask;
    276 
    277 	for (i = 0; stat != 0; i++, stat >>= 1) {
    278 		if (stat & 1) {
    279 			for (ih = &intrtab[i]; ih != NULL; ih = ih->ih_next) {
    280 				if (ih->ih_fun != NULL)
    281 					(ih->ih_fun)(ih->ih_arg);
    282 				else
    283 					printf("int0: unexpected local "
    284 					       "interrupt %d\n", i);
    285 			}
    286 		}
    287 	}
    288 }
    289 
    290 void
    291 int2_local0_intr(vaddr_t pc, uint32_t status, uint32_t ipending)
    292 {
    293 	int i;
    294 	uint32_t l0stat;
    295 	uint32_t l0mask;
    296 	struct sgimips_intrhand *ih;
    297 
    298 	l0stat = bus_space_read_1(iot, ioh, INT2_LOCAL0_STATUS);
    299 	l0mask = bus_space_read_1(iot, ioh, INT2_LOCAL0_MASK);
    300 
    301 	l0stat &= l0mask;
    302 
    303 	for (i = 0; i < 8; i++) {
    304 		if (l0stat & (1 << i)) {
    305 			for (ih = &intrtab[i]; ih != NULL; ih = ih->ih_next) {
    306 				if (ih->ih_fun != NULL)
    307 					(ih->ih_fun)(ih->ih_arg);
    308 				else
    309 					printf("int0: unexpected local0 "
    310 					       "interrupt %d\n", i);
    311 			}
    312 		}
    313 	}
    314 }
    315 
    316 void
    317 int2_local1_intr(vaddr_t pc, uint32_t status, uint32_t ipending)
    318 {
    319 	int i;
    320 	uint32_t l1stat;
    321 	uint32_t l1mask;
    322 	struct sgimips_intrhand *ih;
    323 
    324 	l1stat = bus_space_read_1(iot, ioh, INT2_LOCAL1_STATUS);
    325 	l1mask = bus_space_read_1(iot, ioh, INT2_LOCAL1_MASK);
    326 
    327 	l1stat &= l1mask;
    328 
    329 	for (i = 0; i < 8; i++) {
    330 		if (l1stat & (1 << i)) {
    331 			for (ih = &intrtab[8+i]; ih != NULL; ih = ih->ih_next) {
    332 				if (ih->ih_fun != NULL)
    333 					(ih->ih_fun)(ih->ih_arg);
    334 				else
    335 					printf("int0: unexpected local1 "
    336 					       " interrupt %x\n", 8 + i);
    337 			}
    338 		}
    339 	}
    340 }
    341 
    342 void *
    343 int1_intr_establish(int level, int ipl, int (*handler) (void *), void *arg)
    344 {
    345 	uint8_t mask;
    346 
    347 	if (level < 0 || level >= NINTR)
    348 		panic("invalid interrupt level");
    349 
    350 	if (intrtab[level].ih_fun == NULL) {
    351 		intrtab[level].ih_fun = handler;
    352 		intrtab[level].ih_arg = arg;
    353 		intrtab[level].ih_next = NULL;
    354 	} else {
    355 		struct sgimips_intrhand *n, *ih;
    356 
    357 		ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT);
    358 		if (ih == NULL) {
    359 			printf("int0: can't allocate handler\n");
    360 			return (void *)NULL;
    361 		}
    362 
    363 		ih->ih_fun = handler;
    364 		ih->ih_arg = arg;
    365 		ih->ih_next = NULL;
    366 
    367 		for (n = &intrtab[level]; n->ih_next != NULL; n = n->ih_next)
    368 			;
    369 
    370 		n->ih_next = ih;
    371 
    372 		return NULL;	/* vector already set */
    373 	}
    374 
    375 	if (level < 8) {
    376 		mask = bus_space_read_1(iot, ioh, INT1_LOCAL_MASK);
    377 		mask |= (1 << level);
    378 		bus_space_write_1(iot, ioh, INT1_LOCAL_MASK, mask);
    379 	} else {
    380 		printf("int0: level >= 16 (%d)\n", level);
    381 	}
    382 
    383 	return NULL;
    384 }
    385 
    386 void *
    387 int2_intr_establish(int level, int ipl, int (*handler) (void *), void *arg)
    388 {
    389 	uint32_t mask;
    390 
    391 	if (level < 0 || level >= NINTR)
    392 		panic("invalid interrupt level");
    393 
    394 	if (intrtab[level].ih_fun == NULL) {
    395 		intrtab[level].ih_fun = handler;
    396 		intrtab[level].ih_arg = arg;
    397 		intrtab[level].ih_next = NULL;
    398 	} else {
    399 		struct sgimips_intrhand *n, *ih;
    400 
    401 		ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT);
    402 		if (ih == NULL) {
    403 			printf("int0: can't allocate handler\n");
    404 			return NULL;
    405 		}
    406 
    407 		ih->ih_fun = handler;
    408 		ih->ih_arg = arg;
    409 		ih->ih_next = NULL;
    410 
    411 		for (n = &intrtab[level]; n->ih_next != NULL; n = n->ih_next)
    412 			;
    413 
    414 		n->ih_next = ih;
    415 
    416 		return NULL;	/* vector already set */
    417 	}
    418 
    419 	if (level < 8) {
    420 		mask = bus_space_read_1(iot, ioh, INT2_LOCAL0_MASK);
    421 		mask |= (1 << level);
    422 		bus_space_write_1(iot, ioh, INT2_LOCAL0_MASK, mask);
    423 	} else if (level < 16) {
    424 		mask = bus_space_read_1(iot, ioh, INT2_LOCAL1_MASK);
    425 		mask |= (1 << (level - 8));
    426 		bus_space_write_1(iot, ioh, INT2_LOCAL1_MASK, mask);
    427 	} else if (level < 24) {
    428 		/* Map0 interrupt maps to l0 bit 7, so turn that on too */
    429 		mask = bus_space_read_1(iot, ioh, INT2_LOCAL0_MASK);
    430 		mask |= (1 << 7);
    431 		bus_space_write_1(iot, ioh, INT2_LOCAL0_MASK, mask);
    432 
    433 		mask = bus_space_read_1(iot, ioh, INT2_MAP_MASK0);
    434 		mask |= (1 << (level - 16));
    435 		bus_space_write_1(iot, ioh, INT2_MAP_MASK0, mask);
    436 	} else {
    437 		/* Map1 interrupt maps to l1 bit 3, so turn that on too */
    438 		mask = bus_space_read_1(iot, ioh, INT2_LOCAL1_MASK);
    439 		mask |= (1 << 3);
    440 		bus_space_write_1(iot, ioh, INT2_LOCAL1_MASK, mask);
    441 
    442 		mask = bus_space_read_1(iot, ioh, INT2_MAP_MASK1);
    443 		mask |= (1 << (level - 24));
    444 		bus_space_write_1(iot, ioh, INT2_MAP_MASK1, mask);
    445 	}
    446 
    447 	return NULL;
    448 }
    449 
    450 #ifdef MIPS3
    451 static u_long
    452 int2_cpu_freq(device_t self)
    453 {
    454 	int i;
    455 	unsigned long cps;
    456 	unsigned long ctrdiff[3];
    457 
    458 	/* calibrate timer */
    459 	int2_cal_timer();
    460 
    461 	cps = 0;
    462 	for (i = 0;
    463 	    i < sizeof(ctrdiff) / sizeof(ctrdiff[0]); i++) {
    464 		do {
    465 			ctrdiff[i] = int2_cal_timer();
    466 		} while (ctrdiff[i] == 0);
    467 
    468 		cps += ctrdiff[i];
    469 	}
    470 
    471 	cps = cps / (sizeof(ctrdiff) / sizeof(ctrdiff[0]));
    472 
    473 	printf("%s: bus %luMHz, CPU %luMHz\n",
    474 	    device_xname(self), cps / 10000, cps / 5000);
    475 
    476 	/* R4k/R4400/R4600/R5k count at half CPU frequency */
    477 	return (2 * cps * hz);
    478 }
    479 
    480 static u_long
    481 int2_cal_timer(void)
    482 {
    483 	int s;
    484 	int roundtime;
    485 	int sampletime;
    486 	int msb;
    487 	unsigned long startctr, endctr;
    488 
    489 	/*
    490 	 * NOTE: HZ must be greater than 15 for this to work, as otherwise
    491 	 * we'll overflow the counter.  We round the answer to nearest 1
    492 	 * MHz of the master (2x) clock.
    493 	 */
    494 	roundtime = (1000000 / hz) / 2;
    495 	sampletime = (1000000 / hz) + 0xff;
    496 
    497 	s = splhigh();
    498 
    499 	bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL,
    500 	    (TIMER_SEL2 | TIMER_16BIT | TIMER_RATEGEN));
    501 	bus_space_write_1(iot, ioh, INT2_TIMER_2, (sampletime & 0xff));
    502 	bus_space_write_1(iot, ioh, INT2_TIMER_2, (sampletime >> 8));
    503 
    504 	startctr = mips3_cp0_count_read();
    505 
    506 	/* Wait for the MSB to count down to zero */
    507 	do {
    508 		bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL, TIMER_SEL2);
    509 		(void)bus_space_read_1(iot, ioh, INT2_TIMER_2);
    510 		msb = bus_space_read_1(iot, ioh, INT2_TIMER_2) & 0xff;
    511 
    512 		endctr = mips3_cp0_count_read();
    513 	} while (msb);
    514 
    515 	/* Turn off timer */
    516 	bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL,
    517 	    (TIMER_SEL2 | TIMER_16BIT | TIMER_SWSTROBE));
    518 
    519 	splx(s);
    520 
    521 	return (endctr - startctr) / roundtime * roundtime;
    522 }
    523 #endif /* MIPS3 */
    524 
    525 /*
    526  * A master clock is wired to TIMER_2, which in turn clocks the two other
    527  * timers. The master frequencies are as follows:
    528  *     IP6,  IP10:		3.6864MHz
    529  *     IP12, IP20, IP22:	1MHz
    530  *     IP17:			10MHz
    531  *
    532  * TIMER_0 and TIMER_1 interrupts are tied to MIPS interrupts as follows:
    533  *     IP6,  IP10:		TIMER_0: INT2, TIMER_1: INT4
    534  *     IP12:			TIMER_0: INT3, TIMER_1: INT4
    535  *     IP17, IP20, IP22:	TIMER_0: INT2, TIMER_1: INT3
    536  *
    537  * NB: Apparently int2 doesn't like counting down from one, but two works.
    538  */
    539 void
    540 int_8254_cal(void)
    541 {
    542 	bus_size_t timer_control, timer_0, timer_1, timer_2;
    543 	int s;
    544 
    545 	switch (mach_type) {
    546 	case MACH_SGI_IP6 | MACH_SGI_IP10:
    547 		int_8254_timecounter.tc_frequency = 3686400 / 8;
    548 		timer_control	= INT1_TIMER_CONTROL;
    549 		timer_0		= INT1_TIMER_0;
    550 		timer_1		= INT1_TIMER_1;
    551 		timer_2		= INT1_TIMER_2;
    552 		break;
    553 
    554 	case MACH_SGI_IP12:
    555 		int_8254_timecounter.tc_frequency = 1000000 / 8;
    556 		timer_control	= INT2_TIMER_CONTROL;
    557 		timer_0		= INT2_TIMER_0;
    558 		timer_1		= INT2_TIMER_1;
    559 		timer_2		= INT2_TIMER_2;
    560 		break;
    561 
    562 	default:
    563 		panic("int_8254_cal");
    564 	}
    565 
    566 	s = splhigh();
    567 
    568 	/* Timer0 is our hz. */
    569 	bus_space_write_1(iot, ioh, timer_control,
    570 	    TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
    571 	bus_space_write_1(iot, ioh, timer_0,
    572 	    (int_8254_timecounter.tc_frequency / hz) % 256);
    573 	wbflush();
    574 	delay(4);
    575 	bus_space_write_1(iot, ioh, timer_0,
    576 	    (int_8254_timecounter.tc_frequency / hz) / 256);
    577 
    578 	/* Timer1 is for timecounting. */
    579 	bus_space_write_1(iot, ioh, timer_control,
    580 	    TIMER_SEL1 | TIMER_RATEGEN | TIMER_16BIT);
    581 	bus_space_write_1(iot, ioh, timer_1, 0xff);
    582 	wbflush();
    583 	delay(4);
    584 	bus_space_write_1(iot, ioh, timer_1, 0xff);
    585 
    586 	/* Timer2 clocks timer0 and timer1. */
    587 	bus_space_write_1(iot, ioh, timer_control,
    588 	    TIMER_SEL2 | TIMER_RATEGEN | TIMER_16BIT);
    589 	bus_space_write_1(iot, ioh, timer_2, 8);
    590 	wbflush();
    591 	delay(4);
    592 	bus_space_write_1(iot, ioh, timer_2, 0);
    593 
    594 	splx(s);
    595 
    596 	tc_init(&int_8254_timecounter);
    597 }
    598 
    599 static u_int
    600 int_8254_get_timecount(struct timecounter *tc)
    601 {
    602 	int s;
    603 	u_int count;
    604 	u_char lo, hi;
    605 
    606 	s = splhigh();
    607 
    608 	switch (mach_type) {
    609 	case MACH_SGI_IP6 | MACH_SGI_IP10:
    610 		bus_space_write_1(iot, ioh, INT1_TIMER_CONTROL,
    611 		    TIMER_SEL1 | TIMER_LATCH);
    612 		lo = bus_space_read_1(iot, ioh, INT1_TIMER_1);
    613 		hi = bus_space_read_1(iot, ioh, INT1_TIMER_1);
    614 		break;
    615 
    616 	case MACH_SGI_IP12:
    617 		bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL,
    618 		    TIMER_SEL1 | TIMER_LATCH);
    619 		lo = bus_space_read_1(iot, ioh, INT2_TIMER_1);
    620 		hi = bus_space_read_1(iot, ioh, INT2_TIMER_1);
    621 		break;
    622 
    623 	default:
    624 		panic("int_8254_get_timecount");
    625 	}
    626 
    627 	count = 0xffff - ((hi << 8) | lo);
    628 	splx(s);
    629 
    630 	return (int_8254_tc_count + count);
    631 }
    632 
    633 static void
    634 int_8254_intr0(vaddr_t pc, uint32_t status, uint32_t ipending)
    635 {
    636 	struct clockframe cf;
    637 
    638 	cf.pc = pc;
    639 	cf.sr = status;
    640 	cf.intr = (curcpu()->ci_idepth > 1);
    641 
    642 	hardclock(&cf);
    643 
    644 	switch (mach_type) {
    645 	case MACH_SGI_IP6 | MACH_SGI_IP10:
    646 		bus_space_read_1(iot, ioh, INT1_TIMER_0_ACK);
    647 		break;
    648 
    649 	case MACH_SGI_IP12:
    650 		bus_space_write_1(iot, ioh, INT2_TIMER_CLEAR, 0x01);
    651 		break;
    652 
    653 	default:
    654 		panic("int_8254_intr0");
    655 	}
    656 }
    657 
    658 static void
    659 int_8254_intr1(vaddr_t pc, uint32_t status, uint32_t ipending)
    660 {
    661 	int s;
    662 
    663 	s = splhigh();
    664 
    665 	int_8254_tc_count += 0xffff;
    666 	switch (mach_type) {
    667 	case MACH_SGI_IP6 | MACH_SGI_IP10:
    668 		bus_space_read_1(iot, ioh, INT1_TIMER_1_ACK);
    669 		break;
    670 
    671 	case MACH_SGI_IP12:
    672 		bus_space_write_1(iot, ioh, INT2_TIMER_CLEAR, 0x02);
    673 		break;
    674 
    675 	default:
    676 		panic("int_8254_intr1");
    677 	}
    678 
    679 	splx(s);
    680 }
    681 
    682 void
    683 int2_wait_fifo(uint32_t flag)
    684 {
    685 
    686 	if (ioh == 0)
    687 		delay(5000);
    688 	else
    689 		while (bus_space_read_1(iot, ioh, INT2_LOCAL0_STATUS) & flag)
    690 			;
    691 }
    692