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