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