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