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