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