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