xref: /netbsd-src/sys/arch/sgimips/dev/int.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: int.c,v 1.21 2009/12/14 00:46:13 matt 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.21 2009/12/14 00:46:13 matt Exp $");
37 
38 #include "opt_cputype.h"
39 
40 #include <sys/param.h>
41 #include <sys/proc.h>
42 #include <sys/systm.h>
43 #include <sys/timetc.h>
44 #include <sys/kernel.h>
45 #include <sys/device.h>
46 #include <sys/malloc.h>
47 
48 #include <dev/ic/i8253reg.h>
49 #include <machine/sysconf.h>
50 #include <machine/machtype.h>
51 #include <machine/bus.h>
52 #include <mips/locore.h>
53 
54 #include <mips/cache.h>
55 
56 #include <sgimips/dev/int1reg.h>
57 #include <sgimips/dev/int2reg.h>
58 #include <sgimips/dev/int2var.h>
59 
60 static bus_space_handle_t ioh;
61 static bus_space_tag_t iot;
62 
63 struct int_softc {
64 	struct device sc_dev;
65 };
66 
67 
68 static int	int_match(struct device *, struct cfdata *, void *);
69 static void	int_attach(struct device *, struct device *, void *);
70 static void	int1_local_intr(uint32_t, uint32_t, uint32_t, uint32_t);
71 static void    *int1_intr_establish(int, int, int (*)(void *), void *);
72 static void    *int2_intr_establish(int, int, int (*)(void *), void *);
73 static void 	int2_local0_intr(uint32_t, uint32_t, uint32_t, uint32_t);
74 static void	int2_local1_intr(uint32_t, uint32_t, uint32_t, uint32_t);
75 static int 	int2_mappable_intr(void *);
76 static void    *int2_intr_establish(int, int, int (*)(void *), void *);
77 static void	int_8254_cal(void);
78 static u_int	int_8254_get_timecount(struct timecounter *);
79 static void	int_8254_intr0(uint32_t, uint32_t, uint32_t, uint32_t);
80 static void	int_8254_intr1(uint32_t, uint32_t, uint32_t, uint32_t);
81 
82 #ifdef MIPS3
83 static u_long	int2_cpu_freq(struct device *);
84 static u_long	int2_cal_timer(void);
85 #endif
86 
87 static 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 
98 static u_long int_8254_tc_count;
99 
100 CFATTACH_DECL(int, sizeof(struct int_softc),
101     int_match, int_attach, NULL, NULL);
102 
103 static int
104 int_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 
118 static void
119 int_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 
230 int
231 int2_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 
264 static void
265 int1_local_intr(uint32_t status, uint32_t cause, uint32_t pc, 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; i < 16; i++) {
279 		if (stat & (1 << i)) {
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 
291 void
292 int2_local0_intr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipend)
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 
317 void
318 int2_local1_intr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipend)
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 
343 void *
344 int1_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 
387 void *
388 int2_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
452 static u_long
453 int2_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 
481 static u_long
482 int2_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  */
541 void
542 int_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 
601 static u_int
602 int_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 
635 static void
636 int_8254_intr0(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipend)
637 {
638 	struct clockframe cf;
639 
640 	cf.pc = pc;
641 	cf.sr = status;
642 
643 	hardclock(&cf);
644 
645 	switch (mach_type) {
646 	case MACH_SGI_IP6 | MACH_SGI_IP10:
647 		bus_space_read_1(iot, ioh, INT1_TIMER_0_ACK);
648 		break;
649 
650 	case MACH_SGI_IP12:
651 		bus_space_write_1(iot, ioh, INT2_TIMER_CLEAR, 0x01);
652 		break;
653 
654 	default:
655 		panic("int_8254_intr0");
656 	}
657 }
658 
659 static void
660 int_8254_intr1(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipend)
661 {
662 	int s;
663 
664 	s = splhigh();
665 
666 	int_8254_tc_count += 0xffff;
667 	switch (mach_type) {
668 	case MACH_SGI_IP6 | MACH_SGI_IP10:
669 		bus_space_read_1(iot, ioh, INT1_TIMER_1_ACK);
670 		break;
671 
672 	case MACH_SGI_IP12:
673 		bus_space_write_1(iot, ioh, INT2_TIMER_CLEAR, 0x02);
674 		break;
675 
676 	default:
677 		panic("int_8254_intr1");
678 	}
679 
680 	splx(s);
681 }
682 
683 void
684 int2_wait_fifo(uint32_t flag)
685 {
686 
687 	if (ioh == 0)
688 		delay(5000);
689 	else
690 		while (bus_space_read_1(iot, ioh, INT2_LOCAL0_STATUS) & flag)
691 			;
692 }
693