1 /*-
2 * Copyright (c) 1995 Per Fogelstrom
3 * Copyright (c) 1993, 1994 Charles M. Hannum.
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * William Jolitz and Don Ahn.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * $NetBSD: extintr.c,v 1.12 2000/02/14 12:45:52 tsubai Exp $
39 * @(#)isa.c 7.2 (Berkeley) 5/12/91
40 */
41
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD: releng/6.0/sys/powerpc/powerpc/extintr.c 113038 2003-04-03 21:36:33Z obrien $");
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/bus.h>
48 #include <sys/lock.h>
49 #include <sys/mutex.h>
50 #include <sys/interrupt.h>
51 #include <sys/malloc.h>
52 #include <sys/kernel.h>
53
54 #include <vm/vm.h>
55 #include <vm/vm_kern.h>
56
57 #if 0 /* XXX: Not used yet and may never be. */
58 #include <machine/autoconf.h>
59 #endif
60
61 #include <machine/intr.h>
62 #include <machine/psl.h>
63 #include <machine/pio.h>
64
65 #include <machine/openpicreg.h>
66
67 #include <dev/ofw/openfirm.h>
68
69 #define NIRQ 32
70 #define HWIRQ_MAX (NIRQ - 4 - 1)
71 #define HWIRQ_MASK 0x0fffffff
72
73 void intr_calculatemasks(void);
74 char *intr_typename(int);
75 int fakeintr(void *);
76
77 static __inline int cntlzw(int);
78 static __inline int read_irq(void);
79 static __inline int mapirq(int);
80 static void enable_irq(int);
81
82 static __inline u_int openpic_read(int);
83 static __inline void openpic_write(int, u_int);
84 void openpic_enable_irq(int);
85 void openpic_disable_irq(int);
86 void openpic_set_priority(int, int);
87 static __inline int openpic_read_irq(int);
88 static __inline void openpic_eoi(int);
89
90 unsigned int imen = 0xffffffff;
91 u_int cpl, ipending, tickspending;
92 int imask[NIPL];
93
94 int intrtype[NIRQ], intrmask[NIRQ], intrlevel[NIRQ];
95 struct intrhand *intrhand[NIRQ];
96
97 static u_char hwirq[NIRQ], virq[ICU_LEN];
98 static int virq_max = 0;
99
100 static u_char *obio_base, *openpic_base;
101
102 #if 0 /* XXX */
103 extern u_int *heathrow_FCR;
104 #endif
105
106 extern void install_extint(void (*)(void));
107
108 #define interrupt_reg (obio_base + 0x10)
109
110 #define INT_STATE_REG_H (interrupt_reg + 0x00)
111 #define INT_ENABLE_REG_H (interrupt_reg + 0x04)
112 #define INT_CLEAR_REG_H (interrupt_reg + 0x08)
113 #define INT_LEVEL_REG_H (interrupt_reg + 0x0c)
114 #define INT_STATE_REG_L (interrupt_reg + 0x10)
115 #define INT_ENABLE_REG_L (interrupt_reg + 0x14)
116 #define INT_CLEAR_REG_L (interrupt_reg + 0x18)
117 #define INT_LEVEL_REG_L (interrupt_reg + 0x1c)
118
119 #define have_openpic (openpic_base != NULL)
120
121 /*
122 * Map 64 irqs into 32 (bits).
123 */
124 int
125 mapirq(irq)
126 int irq;
127 {
128 int v;
129
130 if (irq < 0 || irq >= ICU_LEN)
131 panic("invalid irq");
132 if (virq[irq])
133 return virq[irq];
134
135 virq_max++;
136 v = virq_max;
137 if (v > HWIRQ_MAX)
138 panic("virq overflow");
139
140 hwirq[v] = irq;
141 virq[irq] = v;
142
143 return v;
144 }
145
146 /*
147 * Count leading zeros.
148 */
149 static __inline int
150 cntlzw(x)
151 int x;
152 {
153 int a;
154
155 __asm __volatile ("cntlzw %0,%1" : "=r"(a) : "r"(x));
156
157 return a;
158 }
159
160 int
161 read_irq()
162 {
163 int rv, lo, hi, p;
164
165 rv = 0;
166 lo = in32rb(INT_STATE_REG_L);
167 if (lo)
168 out32rb(INT_CLEAR_REG_L, lo);
169 while (lo) {
170 p = 31 - cntlzw(lo);
171 rv |= 1 << virq[p];
172 lo &= ~(1 << p);
173 }
174
175 #if 0 /* XXX */
176 if (heathrow_FCR) /* has heathrow? */
177 hi = in32rb(INT_STATE_REG_H);
178 else
179 #endif
180 hi = 0;
181
182 if (hi)
183 out32rb(INT_CLEAR_REG_H, hi);
184 while (hi) {
185 p = 31 - cntlzw(hi);
186 rv |= 1 << virq[p + 32];
187 hi &= ~(1 << p);
188 }
189
190 /* 1 << 0 is invalid. */
191 return rv & ~1;
192 }
193
194 void
195 enable_irq(x)
196 int x;
197 {
198 int lo, hi, v, irq;
199
200 x &= HWIRQ_MASK; /* XXX Higher bits are software interrupts. */
201
202 lo = hi = 0;
203 while (x) {
204 v = 31 - cntlzw(x);
205 irq = hwirq[v];
206 if (irq < 32)
207 lo |= 1 << irq;
208 else
209 hi |= 1 << (irq - 32);
210 x &= ~(1 << v);
211 }
212
213 out32rb(INT_ENABLE_REG_L, lo);
214 #if 0 /* XXX */
215 if (heathrow_FCR)
216 out32rb(INT_ENABLE_REG_H, hi);
217 #endif
218 }
219
220 u_int
221 openpic_read(reg)
222 int reg;
223 {
224 char *addr;
225
226 addr = openpic_base + reg;
227
228 return in32rb(addr);
229 }
230
231 void
232 openpic_write(reg, val)
233 int reg;
234 u_int val;
235 {
236 char *addr;
237
238 addr = openpic_base + reg;
239
240 out32rb(addr, val);
241 }
242
243 void
244 openpic_enable_irq(irq)
245 int irq;
246 {
247 u_int x;
248
249 x = openpic_read(OPENPIC_SRC_VECTOR(irq));
250 x &= ~OPENPIC_IMASK;
251 openpic_write(OPENPIC_SRC_VECTOR(irq), x);
252 }
253
254 void
255 openpic_disable_irq(irq)
256 int irq;
257 {
258 u_int x;
259
260 x = openpic_read(OPENPIC_SRC_VECTOR(irq));
261 x |= OPENPIC_IMASK;
262 openpic_write(OPENPIC_SRC_VECTOR(irq), x);
263 }
264
265 void
266 openpic_set_priority(cpu, pri)
267 int cpu, pri;
268 {
269 u_int x;
270
271 x = openpic_read(OPENPIC_CPU_PRIORITY(cpu));
272 x &= ~OPENPIC_CPU_PRIORITY_MASK;
273 x |= pri;
274 openpic_write(OPENPIC_CPU_PRIORITY(cpu), x);
275 }
276
277 int
278 openpic_read_irq(cpu)
279 int cpu;
280 {
281 return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
282 }
283
284 void
285 openpic_eoi(cpu)
286 int cpu;
287 {
288 openpic_write(OPENPIC_EOI(cpu), 0);
289 openpic_read(OPENPIC_EOI(cpu));
290 }
291
292 /*
293 * Recalculate the interrupt masks from scratch.
294 * We could code special registry and deregistry versions of this function that
295 * would be faster, but the code would be nastier, and we don't expect this to
296 * happen very much anyway.
297 */
298 void
299 intr_calculatemasks()
300 {
301 int irq, level, irqs;
302 struct intrhand *q;
303
304 irqs = 0;
305
306 /* First, figure out which levels each IRQ uses. */
307 #if 0 /* XXX */
308 for (irq = 0; irq < NIRQ; irq++) {
309 register int levels = 0;
310 for (q = intrhand[irq]; q; q = q->ih_next)
311 levels |= 1 << q->ih_level;
312 intrlevel[irq] = levels;
313 }
314 #endif
315
316 /* Then figure out which IRQs use each level. */
317 for (level = 0; level < NIPL; level++) {
318 register int irqs = 0;
319 for (irq = 0; irq < NIRQ; irq++)
320 if (intrlevel[irq] & (1 << level))
321 irqs |= 1 << irq;
322 imask[level] = irqs;
323 }
324
325 /*
326 * IPL_CLOCK should mask clock interrupt even if interrupt handler
327 * is not registered.
328 */
329 imask[IPL_CLOCK] |= 1 << SPL_CLOCK;
330
331 /*
332 * Initialize soft interrupt masks to block themselves.
333 */
334 imask[IPL_SOFTCLOCK] = 1 << SIR_CLOCK;
335 imask[IPL_SOFTNET] = 1 << SIR_NET;
336 imask[IPL_SOFTSERIAL] = 1 << SIR_SERIAL;
337
338 /*
339 * IPL_NONE is used for hardware interrupts that are never blocked,
340 * and do not block anything else.
341 */
342 imask[IPL_NONE] = 0;
343
344 /*
345 * Enforce a hierarchy that gives slow devices a better chance at not
346 * dropping data.
347 */
348 imask[IPL_SOFTCLOCK] |= imask[IPL_NONE];
349 imask[IPL_SOFTNET] |= imask[IPL_SOFTCLOCK];
350 imask[IPL_BIO] |= imask[IPL_SOFTNET];
351 imask[IPL_NET] |= imask[IPL_BIO];
352 imask[IPL_SOFTSERIAL] |= imask[IPL_NET];
353 imask[IPL_TTY] |= imask[IPL_SOFTSERIAL];
354
355 /*
356 * There are tty, network and disk drivers that use free() at interrupt
357 * time, so imp > (tty | net | bio).
358 */
359 imask[IPL_IMP] |= imask[IPL_TTY];
360
361 imask[IPL_AUDIO] |= imask[IPL_IMP];
362
363 /*
364 * Since run queues may be manipulated by both the statclock and tty,
365 * network, and disk drivers, clock > imp.
366 */
367 imask[IPL_CLOCK] |= imask[IPL_AUDIO];
368
369 /*
370 * IPL_HIGH must block everything that can manipulate a run queue.
371 */
372 imask[IPL_HIGH] |= imask[IPL_CLOCK];
373
374 /*
375 * We need serial drivers to run at the absolute highest priority to
376 * avoid overruns, so serial > high.
377 */
378 imask[IPL_SERIAL] |= imask[IPL_HIGH];
379
380 /* And eventually calculate the complete masks. */
381 #if 0 /* XXX */
382 for (irq = 0; irq < NIRQ; irq++) {
383 register int irqs = 1 << irq;
384 for (q = intrhand[irq]; q; q = q->ih_next)
385 irqs |= imask[q->ih_level];
386 intrmask[irq] = irqs;
387 }
388 #endif
389
390 /* Lastly, determine which IRQs are actually in use. */
391 for (irq = 0; irq < NIRQ; irq++)
392 if (intrhand[irq])
393 irqs |= 1 << irq;
394
395 if (have_openpic) {
396 for (irq = 0; irq < NIRQ; irq++) {
397 if (irqs & (1 << irq))
398 openpic_enable_irq(hwirq[irq]);
399 else
400 openpic_disable_irq(hwirq[irq]);
401 }
402 } else {
403 imen = ~irqs;
404 enable_irq(~imen);
405 }
406 }
407
408 int
409 fakeintr(arg)
410 void *arg;
411 {
412
413 return 0;
414 }
415
416 #define LEGAL_IRQ(x) ((x) >= 0 && (x) < NIRQ)
417
418 char *
419 intr_typename(type)
420 int type;
421 {
422
423 switch (type) {
424 case IST_NONE :
425 return ("none");
426 case IST_PULSE:
427 return ("pulsed");
428 case IST_EDGE:
429 return ("edge-triggered");
430 case IST_LEVEL:
431 return ("level-triggered");
432 default:
433 panic("intr_typename: invalid type %d", type);
434 #if 1 /* XXX */
435 return ("unknown");
436 #endif
437 }
438 }
439
440 /*
441 * Register an interrupt handler.
442 */
443 void *
444 intr_establish(int irq, int type, int level, int (*ih_fun)(void *),
445 void *ih_arg)
446 {
447 struct intrhand **p, *q, *ih;
448 static struct intrhand fakehand = {fakeintr};
449
450 irq = mapirq(irq);
451
452 /* no point in sleeping unless someone can free memory. */
453 ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
454 if (ih == NULL)
455 panic("intr_establish: can't malloc handler info");
456
457 if (!LEGAL_IRQ(irq) || type == IST_NONE)
458 panic("intr_establish: bogus irq or type");
459
460 switch (intrtype[irq]) {
461 case IST_NONE:
462 intrtype[irq] = type;
463 break;
464 case IST_EDGE:
465 case IST_LEVEL:
466 if (type == intrtype[irq])
467 break;
468 case IST_PULSE:
469 if (type != IST_NONE)
470 panic("intr_establish: can't share %s with %s",
471 intr_typename(intrtype[irq]),
472 intr_typename(type));
473 break;
474 }
475
476 /*
477 * Figure out where to put the handler.
478 * This is O(N^2), but we want to preserve the order, and N is
479 * generally small.
480 */
481 #if 0 /* XXX */
482 for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
483 ;
484 #endif
485
486 /*
487 * Actually install a fake handler momentarily, since we might be doing
488 * this with interrupts enabled and don't want the real routine called
489 * until masking is set up.
490 */
491 #if 0 /* XXX */
492 fakehand.ih_level = level;
493 #endif
494 *p = &fakehand;
495
496 intr_calculatemasks();
497
498 /*
499 * Poke the real handler in now.
500 */
501 #if 0
502 ih->ih_fun = ih_fun;
503 ih->ih_arg = ih_arg;
504 ih->ih_count = 0;
505 ih->ih_next = NULL;
506 ih->ih_level = level;
507 ih->ih_irq = irq;
508 #endif
509 *p = ih;
510
511 return (ih);
512 }
513
514 /*
515 * Deregister an interrupt handler.
516 */
517 void
518 intr_disestablish(void *arg)
519 {
520 struct intrhand *ih, **p, *q;
521 int irq;
522
523 #if 0 /* XXX */
524 irq = ih->ih_irq;
525 #endif
526
527 ih = arg;
528
529 if (!LEGAL_IRQ(irq))
530 panic("intr_disestablish: bogus irq");
531
532 /*
533 * Remove the handler from the chain.
534 * This is O(n^2), too.
535 */
536 for (p = &intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next)
537 ;
538 if (q)
539 #if 0 /* XXX */
540 *p = q->ih_next;
541 #else
542 p = p;
543 #endif
544 else
545 panic("intr_disestablish: handler not registered");
546 free((void *)ih, M_DEVBUF);
547
548 intr_calculatemasks();
549
550 if (intrhand[irq] == NULL)
551 intrtype[irq] = IST_NONE;
552 }
553
554 /*
555 * external interrupt handler
556 */
557 void
558 ext_intr(void)
559 {
560 int irq;
561 int o_imen, r_imen;
562 int pcpl;
563 struct intrhand *ih;
564 volatile unsigned long int_state;
565
566 pcpl = splhigh(); /* Turn off all */
567
568 int_state = read_irq();
569 if (int_state == 0)
570 goto out;
571
572 start:
573 irq = 31 - cntlzw(int_state);
574
575 o_imen = imen;
576 r_imen = 1 << irq;
577
578 if ((pcpl & r_imen) != 0) {
579 ipending |= r_imen; /* Masked! Mark this as pending */
580 imen |= r_imen;
581 enable_irq(~imen);
582 } else {
583 ih = intrhand[irq];
584 while (ih) {
585 #if 0 /* XXX */
586 (*ih->ih_fun)(ih->ih_arg);
587 ih = ih->ih_next;
588 #endif
589 }
590
591 intrcnt[hwirq[irq]]++;
592 }
593
594 int_state &= ~r_imen;
595 if (int_state)
596 goto start;
597
598 out:
599 splx(pcpl); /* Process pendings. */
600 }
601
602 void
603 ext_intr_openpic()
604 {
605 int irq, realirq;
606 int r_imen;
607 int pcpl;
608 struct intrhand *ih;
609
610 pcpl = splhigh(); /* Turn off all */
611
612 realirq = openpic_read_irq(0);
613 if (realirq == 255) {
614 printf("sprious interrupt\n");
615 goto out;
616 }
617
618 start:
619 irq = virq[realirq];
620
621 /* XXX check range */
622
623 r_imen = 1 << irq;
624
625 if ((pcpl & r_imen) != 0) {
626 ipending |= r_imen; /* Masked! Mark this as pending */
627 openpic_disable_irq(realirq);
628 } else {
629 ih = intrhand[irq];
630 while (ih) {
631 #if 0 /* XXX */
632 (*ih->ih_fun)(ih->ih_arg);
633 ih = ih->ih_next;
634 #endif
635 }
636
637 intrcnt[hwirq[irq]]++;
638 }
639
640 openpic_eoi(0);
641
642 realirq = openpic_read_irq(0);
643 if (realirq != 255)
644 goto start;
645
646 out:
647 splx(pcpl); /* Process pendings. */
648 }
649
650 void
651 do_pending_int()
652 {
653 struct intrhand *ih;
654 int irq;
655 int pcpl;
656 int hwpend;
657 int emsr, dmsr;
658 static int processing;
659
660 return; /* XXX */
661
662 if (processing)
663 return;
664
665 processing = 1;
666 emsr = mfmsr();
667 dmsr = emsr & ~PSL_EE;
668 mtmsr(dmsr);
669
670 pcpl = splhigh(); /* Turn off all */
671 hwpend = ipending & ~pcpl; /* Do now unmasked pendings */
672 if (!have_openpic) {
673 imen &= ~hwpend;
674 enable_irq(~imen);
675 }
676 hwpend &= HWIRQ_MASK;
677 while (hwpend) {
678 irq = 31 - cntlzw(hwpend);
679 hwpend &= ~(1L << irq);
680 ih = intrhand[irq];
681 while(ih) {
682 #if 0 /* XXX */
683 (*ih->ih_fun)(ih->ih_arg);
684 ih = ih->ih_next;
685 #endif
686 }
687
688 intrcnt[hwirq[irq]]++;
689 if (have_openpic)
690 openpic_enable_irq(hwirq[irq]);
691 }
692
693 /*out32rb(INT_ENABLE_REG, ~imen);*/
694
695 if ((ipending & ~pcpl) & (1 << SIR_CLOCK)) {
696 ipending &= ~(1 << SIR_CLOCK);
697 softclock(NULL);
698 intrcnt[CNT_SOFTCLOCK]++;
699 }
700 #if 0 /* XXX */
701 if ((ipending & ~pcpl) & (1 << SIR_NET)) {
702 ipending &= ~(1 << SIR_NET);
703 softnet();
704 intrcnt[CNT_SOFTNET]++;
705 }
706 if ((ipending & ~pcpl) & (1 << SIR_SERIAL)) {
707 ipending &= ~(1 << SIR_SERIAL);
708 softserial();
709 intrcnt[CNT_SOFTSERIAL]++;
710 }
711 #endif
712 ipending &= pcpl;
713 cpl = pcpl; /* Don't use splx... we are here already! */
714 mtmsr(emsr);
715 processing = 0;
716 }
717
718 void
719 openpic_init(void)
720 {
721 int irq;
722 u_int x;
723
724 /* disable all interrupts */
725 for (irq = 0; irq < 256; irq++)
726 openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
727
728 openpic_set_priority(0, 15);
729
730 /* we don't need 8259 pass through mode */
731 x = openpic_read(OPENPIC_CONFIG);
732 x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
733 openpic_write(OPENPIC_CONFIG, x);
734
735 /* send all interrupts to cpu 0 */
736 for (irq = 0; irq < ICU_LEN; irq++)
737 openpic_write(OPENPIC_IDEST(irq), 1 << 0);
738
739 for (irq = 0; irq < ICU_LEN; irq++) {
740 x = irq;
741 x |= OPENPIC_IMASK;
742 x |= OPENPIC_POLARITY_POSITIVE;
743 x |= OPENPIC_SENSE_LEVEL;
744 x |= 8 << OPENPIC_PRIORITY_SHIFT;
745 openpic_write(OPENPIC_SRC_VECTOR(irq), x);
746 }
747
748 /* XXX set spurious intr vector */
749
750 openpic_set_priority(0, 0);
751
752 /* clear all pending interrunts */
753 for (irq = 0; irq < 256; irq++) {
754 openpic_read_irq(0);
755 openpic_eoi(0);
756 }
757
758 for (irq = 0; irq < ICU_LEN; irq++)
759 openpic_disable_irq(irq);
760
761 install_extint(ext_intr_openpic);
762 }
763
764 void
765 legacy_int_init(void)
766 {
767 out32rb(INT_ENABLE_REG_L, 0); /* disable all intr. */
768 out32rb(INT_CLEAR_REG_L, 0xffffffff); /* clear pending intr. */
769
770 install_extint(ext_intr);
771 }
772
773 #define HEATHROW_FCR_OFFSET 0x38 /* XXX should not here */
774 #define GC_OBIO_BASE 0xf3000000
775
776 void
777 init_interrupt(void)
778 {
779 int chosen;
780 int mac_io, reg[5];
781 int32_t ictlr;
782 char type[32];
783
784 openpic_base = NULL;
785
786 mac_io = OF_finddevice("mac-io");
787 if (mac_io == -1)
788 mac_io = OF_finddevice("/pci/mac-io");
789
790 if (mac_io == -1) {
791 /*
792 * No mac-io. Assume Grand-Central or OHare.
793 */
794 obio_base = (void *)GC_OBIO_BASE;
795 legacy_int_init();
796 return;
797 }
798
799 if (OF_getprop(mac_io, "assigned-addresses", reg, sizeof(reg)) < 20)
800 goto failed;
801
802 obio_base = (void *)reg[2];
803 #if 0 /* XXX */
804 heathrow_FCR = (void *)(obio_base + HEATHROW_FCR_OFFSET);
805 #endif
806
807 bzero(type, sizeof(type));
808 chosen = OF_finddevice("/chosen");
809 if (OF_getprop(chosen, "interrupt-controller", &ictlr, 4) == 4)
810 OF_getprop(ictlr, "device_type", type, sizeof(type));
811
812 if (strcmp(type, "open-pic") != 0) {
813 /*
814 * Not an open-pic. Must be a Heathrow (compatible).
815 */
816 legacy_int_init();
817 return;
818 } else {
819 /*
820 * We have an Open PIC.
821 */
822 if (OF_getprop(ictlr, "reg", reg, sizeof(reg)) < 8)
823 goto failed;
824
825 openpic_base = (void *)(obio_base + reg[0]);
826 openpic_init();
827 return;
828 }
829
830 printf("unknown interrupt controller\n");
831 failed:
832 panic("init_interrupt: failed to initialize interrupt controller");
833 }
Cache object: aae573a2e32bb2cb6fb732f6b7941466
|