xref: /openbsd-src/sys/arch/macppc/dev/openpic.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: openpic.c,v 1.52 2008/11/21 17:35:52 deraadt Exp $	*/
2 
3 /*-
4  * Copyright (c) 1995 Per Fogelstrom
5  * Copyright (c) 1993, 1994 Charles M. Hannum.
6  * Copyright (c) 1990 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * William Jolitz and Don Ahn.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	@(#)isa.c	7.2 (Berkeley) 5/12/91
37  */
38 
39 #include <sys/param.h>
40 #include <sys/device.h>
41 #include <sys/ioctl.h>
42 #include <sys/mbuf.h>
43 #include <sys/socket.h>
44 #include <sys/systm.h>
45 
46 #include <uvm/uvm.h>
47 #include <ddb/db_var.h>
48 
49 #include <machine/atomic.h>
50 #include <machine/autoconf.h>
51 #include <machine/intr.h>
52 #include <machine/psl.h>
53 #include <machine/pio.h>
54 #include <machine/powerpc.h>
55 #include <macppc/dev/openpicreg.h>
56 #include <dev/ofw/openfirm.h>
57 
58 #define ICU_LEN 128
59 #define LEGAL_IRQ(x) ((x >= 0) && (x < ICU_LEN))
60 
61 int o_intrtype[ICU_LEN], o_intrmaxlvl[ICU_LEN];
62 struct intrhand *o_intrhand[ICU_LEN] = { 0 };
63 int o_hwirq[ICU_LEN], o_virq[ICU_LEN];
64 int o_virq_max;
65 
66 static int fakeintr(void *);
67 static char *intr_typename(int type);
68 void openpic_calc_mask(void);
69 static __inline int cntlzw(int x);
70 static int mapirq(int irq);
71 int openpic_prog_button(void *arg);
72 void openpic_enable_irq_mask(int irq_mask);
73 
74 #define HWIRQ_MAX 27
75 #define HWIRQ_MASK 0x0fffffff
76 
77 /* IRQ vector used for inter-processor interrupts. */
78 #define IPI_VECTOR_NOP	64
79 #define IPI_VECTOR_DDB	65
80 #ifdef MULTIPROCESSOR
81 static struct evcount ipi_ddb[PPC_MAXPROCS];
82 static struct evcount ipi_nop[PPC_MAXPROCS];
83 static int ipi_nopirq = IPI_VECTOR_NOP;
84 static int ipi_ddbirq = IPI_VECTOR_DDB;
85 #endif
86 
87 static __inline u_int openpic_read(int);
88 static __inline void openpic_write(int, u_int);
89 void openpic_set_enable_irq(int, int);
90 void openpic_enable_irq(int);
91 void openpic_disable_irq(int);
92 void openpic_init(void);
93 void openpic_set_priority(int, int);
94 void openpic_ipi_ddb(void);
95 static __inline int openpic_read_irq(int);
96 static __inline void openpic_eoi(int);
97 
98 struct openpic_softc {
99 	struct device sc_dev;
100 };
101 
102 int	openpic_match(struct device *parent, void *cf, void *aux);
103 void	openpic_attach(struct device *, struct device *, void *);
104 void	openpic_do_pending_int(void);
105 void	openpic_collect_preconf_intr(void);
106 void	ext_intr_openpic(void);
107 
108 struct cfattach openpic_ca = {
109 	sizeof(struct openpic_softc),
110 	openpic_match,
111 	openpic_attach
112 };
113 
114 struct cfdriver openpic_cd = {
115 	NULL, "openpic", DV_DULL
116 };
117 
118 int
119 openpic_match(struct device *parent, void *cf, void *aux)
120 {
121 	char type[40];
122 	int pirq;
123 	struct confargs *ca = aux;
124 
125 	bzero (type, sizeof(type));
126 
127 	if (OF_getprop(ca->ca_node, "interrupt-parent", &pirq, sizeof(pirq))
128 	    == sizeof(pirq))
129 		return 0; /* XXX */
130 
131 	if (strcmp(ca->ca_name, "interrupt-controller") != 0 &&
132 	    strcmp(ca->ca_name, "mpic") != 0)
133 		return 0;
134 
135 	OF_getprop(ca->ca_node, "device_type", type, sizeof(type));
136 	if (strcmp(type, "open-pic") != 0)
137 		return 0;
138 
139 	if (ca->ca_nreg < 8)
140 		return 0;
141 
142 	return 1;
143 }
144 
145 typedef void  (void_f) (void);
146 extern void_f *pending_int_f;
147 
148 vaddr_t openpic_base;
149 void * openpic_intr_establish( void * lcv, int irq, int type, int level,
150 	int (*ih_fun)(void *), void *ih_arg, char *name);
151 void openpic_intr_disestablish( void *lcp, void *arg);
152 #ifdef MULTIPROCESSOR
153 intr_send_ipi_t openpic_send_ipi;
154 #endif
155 void openpic_collect_preconf_intr(void);
156 int openpic_big_endian;
157 
158 void
159 openpic_attach(struct device *parent, struct device  *self, void *aux)
160 {
161 	struct confargs *ca = aux;
162 	u_int32_t reg;
163 
164 	reg = 0;
165 	if (OF_getprop(ca->ca_node, "big-endian", &reg, sizeof reg) == 0)
166 		openpic_big_endian = 1;
167 
168 	openpic_base = (vaddr_t) mapiodev (ca->ca_baseaddr +
169 			ca->ca_reg[0], 0x40000);
170 
171 	printf(": version 0x%x %s endian", openpic_read(OPENPIC_VENDOR_ID),
172 		openpic_big_endian ? "big" : "little" );
173 
174 	openpic_init();
175 
176 	pending_int_f = openpic_do_pending_int;
177 	intr_establish_func  = openpic_intr_establish;
178 	intr_disestablish_func  = openpic_intr_disestablish;
179 	mac_intr_establish_func  = openpic_intr_establish;
180 	mac_intr_disestablish_func  = openpic_intr_disestablish;
181 #ifdef MULTIPROCESSOR
182 	intr_send_ipi_func = openpic_send_ipi;
183 #endif
184 	install_extint(ext_intr_openpic);
185 
186 #if 1
187 	openpic_collect_preconf_intr();
188 #endif
189 
190 #if 1
191 	mac_intr_establish(parent, 0x37, IST_LEVEL,
192 		IPL_HIGH, openpic_prog_button, (void *)0x37, "progbutton");
193 #endif
194 
195 	ppc_intr_enable(1);
196 
197 	printf("\n");
198 }
199 
200 void
201 openpic_collect_preconf_intr()
202 {
203 	int i;
204 	for (i = 0; i < ppc_configed_intr_cnt; i++) {
205 #ifdef DEBUG
206 		printf("\n\t%s irq %d level %d fun %x arg %x",
207 		    ppc_configed_intr[i].ih_what, ppc_configed_intr[i].ih_irq,
208 		    ppc_configed_intr[i].ih_level, ppc_configed_intr[i].ih_fun,
209 		    ppc_configed_intr[i].ih_arg);
210 #endif
211 		openpic_intr_establish(NULL, ppc_configed_intr[i].ih_irq,
212 		    IST_LEVEL, ppc_configed_intr[i].ih_level,
213 		    ppc_configed_intr[i].ih_fun, ppc_configed_intr[i].ih_arg,
214 		    ppc_configed_intr[i].ih_what);
215 	}
216 }
217 
218 static int
219 fakeintr(void *arg)
220 {
221 
222 	return 0;
223 }
224 
225 /*
226  * Register an interrupt handler.
227  */
228 void *
229 openpic_intr_establish(void *lcv, int irq, int type, int level,
230     int (*ih_fun)(void *), void *ih_arg, char *name)
231 {
232 	struct intrhand **p, *q, *ih;
233 	static struct intrhand fakehand;
234 
235 	fakehand.ih_next = NULL;
236 	fakehand.ih_fun  = fakeintr;
237 
238 #if 0
239 printf("mac_intr_establish, hI %d L %d ", irq, type);
240 #endif
241 
242 	irq = mapirq(irq);
243 #if 0
244 printf("vI %d ", irq);
245 #endif
246 
247 	/* no point in sleeping unless someone can free memory. */
248 	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
249 	if (ih == NULL)
250 		panic("intr_establish: can't malloc handler info");
251 
252 	if (!LEGAL_IRQ(irq) || type == IST_NONE)
253 		panic("intr_establish: bogus irq or type");
254 
255 	switch (o_intrtype[irq]) {
256 	case IST_NONE:
257 		o_intrtype[irq] = type;
258 		break;
259 	case IST_EDGE:
260 	case IST_LEVEL:
261 		if (type == o_intrtype[irq])
262 			break;
263 	case IST_PULSE:
264 		if (type != IST_NONE)
265 			panic("intr_establish: can't share %s with %s",
266 			    intr_typename(o_intrtype[irq]),
267 			    intr_typename(type));
268 		break;
269 	}
270 
271 	/*
272 	 * Figure out where to put the handler.
273 	 * This is O(N^2), but we want to preserve the order, and N is
274 	 * generally small.
275 	 */
276 	for (p = &o_intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
277 		;
278 
279 	/*
280 	 * Actually install a fake handler momentarily, since we might be doing
281 	 * this with interrupts enabled and DON'T WANt the real routine called
282 	 * until masking is set up.
283 	 */
284 	fakehand.ih_level = level;
285 	*p = &fakehand;
286 
287 	openpic_calc_mask();
288 
289 	/*
290 	 * Poke the real handler in now.
291 	 */
292 	ih->ih_fun = ih_fun;
293 	ih->ih_arg = ih_arg;
294 	ih->ih_next = NULL;
295 	ih->ih_level = level;
296 	ih->ih_irq = irq;
297 	evcount_attach(&ih->ih_count, name, (void *)&o_hwirq[irq],
298 	    &evcount_intr);
299 	*p = ih;
300 
301 	return (ih);
302 }
303 
304 /*
305  * Deregister an interrupt handler.
306  */
307 void
308 openpic_intr_disestablish(void *lcp, void *arg)
309 {
310 	struct intrhand *ih = arg;
311 	int irq = ih->ih_irq;
312 	struct intrhand **p, *q;
313 
314 	if (!LEGAL_IRQ(irq))
315 		panic("intr_disestablish: bogus irq");
316 
317 	/*
318 	 * Remove the handler from the chain.
319 	 * This is O(n^2), too.
320 	 */
321 	for (p = &o_intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next)
322 		;
323 	if (q)
324 		*p = q->ih_next;
325 	else
326 		panic("intr_disestablish: handler not registered");
327 
328 	evcount_detach(&ih->ih_count);
329 	free((void *)ih, M_DEVBUF);
330 
331 	openpic_calc_mask();
332 
333 	if (o_intrhand[irq] == NULL)
334 		o_intrtype[irq] = IST_NONE;
335 }
336 
337 
338 static char *
339 intr_typename(int type)
340 {
341 
342 	switch (type) {
343 	case IST_NONE:
344 		return ("none");
345 	case IST_PULSE:
346 		return ("pulsed");
347 	case IST_EDGE:
348 		return ("edge-triggered");
349 	case IST_LEVEL:
350 		return ("level-triggered");
351 	default:
352 		panic("intr_typename: invalid type %d", type);
353 #if 1 /* XXX */
354 		return ("unknown");
355 #endif
356 	}
357 }
358 
359 /*
360  * Recalculate the interrupt masks from scratch.
361  * We could code special registry and deregistry versions of this function that
362  * would be faster, but the code would be nastier, and we don't expect this to
363  * happen very much anyway.
364  */
365 
366 void
367 openpic_calc_mask()
368 {
369 	int irq;
370 	struct intrhand *ih;
371 	int i;
372 
373 	/* disable all openpic interrupts */
374 	openpic_set_priority(0, 15);
375 
376 	for (irq = 0; irq < ICU_LEN; irq++) {
377 		int max = IPL_NONE;
378 		int min = IPL_HIGH;
379 		int reg;
380 		if (o_virq[irq] != 0) {
381 			for (ih = o_intrhand[o_virq[irq]]; ih;
382 			    ih = ih->ih_next) {
383 				if (ih->ih_level > max)
384 					max = ih->ih_level;
385 				if (ih->ih_level < min)
386 					min = ih->ih_level;
387 			}
388 		}
389 
390 		o_intrmaxlvl[irq] = max;
391 
392 		/* adjust priority if it changes */
393 		reg = openpic_read(OPENPIC_SRC_VECTOR(irq));
394 		if (max != ((reg >> OPENPIC_PRIORITY_SHIFT) & 0xf)) {
395 			openpic_write(OPENPIC_SRC_VECTOR(irq),
396 				(reg & ~(0xf << OPENPIC_PRIORITY_SHIFT)) |
397 				(max << OPENPIC_PRIORITY_SHIFT) );
398 		}
399 
400 		if (max == IPL_NONE)
401 			min = IPL_NONE; /* Interrupt not enabled */
402 
403 		if (o_virq[irq] != 0) {
404 			/* Enable (dont mask) interrupts at lower levels */
405 			for (i = IPL_NONE; i < min; i++)
406 				imask[i] &= ~(1 << o_virq[irq]);
407 			for (; i <= IPL_HIGH; i++)
408 				imask[i] |= (1 << o_virq[irq]);
409 		}
410 	}
411 
412 	/* restore interrupts */
413 	openpic_set_priority(0, 0);
414 
415 	for (i = IPL_NONE; i <= IPL_HIGH; i++) {
416 		if (i > IPL_NONE)
417 			imask[i] |= SINT_MASK;
418 	}
419 	imask[IPL_HIGH] = 0xffffffff;
420 }
421 
422 /*
423  * Map 64 irqs into 32 (bits).
424  */
425 static int
426 mapirq(int irq)
427 {
428 	int v;
429 
430 	/* irq in table already? */
431 	if (o_virq[irq] != 0)
432 		return o_virq[irq];
433 
434 	if (irq < 0 || irq >= ICU_LEN)
435 		panic("invalid irq %d", irq);
436 
437 	o_virq_max++;
438 	v = o_virq_max;
439 	if (v > HWIRQ_MAX)
440 		panic("virq overflow");
441 
442 	o_hwirq[v] = irq;
443 	o_virq[irq] = v;
444 #if 0
445 printf("\nmapirq %x to %x\n", irq, v);
446 #endif
447 
448 	return v;
449 }
450 
451 /*
452  * Count leading zeros.
453  */
454 static __inline int
455 cntlzw(int x)
456 {
457 	int a;
458 
459 	__asm __volatile ("cntlzw %0,%1" : "=r"(a) : "r"(x));
460 
461 	return a;
462 }
463 
464 void openpic_do_pending_softint(int pcpl);
465 
466 void
467 openpic_do_pending_int()
468 {
469 	struct cpu_info *ci = curcpu();
470 	struct intrhand *ih;
471 	int irq;
472 	int pcpl;
473 	int hwpend;
474 	int pri, pripending;
475 	int s;
476 
477 	if (ci->ci_iactive & CI_IACTIVE_PROCESSING_HARD)
478 		return;
479 
480 	atomic_setbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_HARD);
481 	s = ppc_intr_disable();
482 	pcpl = ci->ci_cpl;
483 
484 	hwpend = ci->ci_ipending & ~pcpl;	/* Do now unmasked pendings */
485 	hwpend &= HWIRQ_MASK;
486 	while (hwpend) {
487 		/* this still doesn't handle the interrupts in priority order */
488 		for (pri = IPL_HIGH; pri >= IPL_NONE; pri--) {
489 			pripending = hwpend & ~imask[pri];
490 			irq = 31 - cntlzw(pripending);
491 			ci->ci_ipending &= ~(1L << irq);
492 			ci->ci_cpl = imask[o_intrmaxlvl[o_hwirq[irq]]];
493 			openpic_enable_irq_mask(~ci->ci_cpl);
494 			ih = o_intrhand[irq];
495 			while(ih) {
496 				ppc_intr_enable(1);
497 
498 				KERNEL_LOCK();
499 				if ((*ih->ih_fun)(ih->ih_arg))
500 					ih->ih_count.ec_count++;
501 				KERNEL_UNLOCK();
502 
503 				(void)ppc_intr_disable();
504 
505 				ih = ih->ih_next;
506 			}
507 		}
508 		hwpend = ci->ci_ipending & ~pcpl;/* Catch new pendings */
509 		hwpend &= HWIRQ_MASK;
510 	}
511 	ci->ci_cpl = pcpl | SINT_MASK;
512 	openpic_enable_irq_mask(~ci->ci_cpl);
513 	atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_HARD);
514 
515 	openpic_do_pending_softint(pcpl);
516 
517 	ppc_intr_enable(s);
518 }
519 
520 void
521 openpic_do_pending_softint(int pcpl)
522 {
523 	struct cpu_info *ci = curcpu();
524 
525 	if (ci->ci_iactive & CI_IACTIVE_PROCESSING_SOFT)
526 		return;
527 
528 	atomic_setbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT);
529 
530 	do {
531 		if((ci->ci_ipending & SINT_CLOCK) & ~pcpl) {
532 			ci->ci_ipending &= ~SINT_CLOCK;
533 			ci->ci_cpl = SINT_CLOCK|SINT_NET|SINT_TTY;
534 			ppc_intr_enable(1);
535 			KERNEL_LOCK();
536 			softclock();
537 			KERNEL_UNLOCK();
538 			ppc_intr_disable();
539 			continue;
540 		}
541 		if((ci->ci_ipending & SINT_NET) & ~pcpl) {
542 			extern int netisr;
543 			int pisr;
544 
545 			ci->ci_ipending &= ~SINT_NET;
546 			ci->ci_cpl = SINT_NET|SINT_TTY;
547 			while ((pisr = netisr) != 0) {
548 				atomic_clearbits_int(&netisr, pisr);
549 				ppc_intr_enable(1);
550 				KERNEL_LOCK();
551 				softnet(pisr);
552 				KERNEL_UNLOCK();
553 				ppc_intr_disable();
554 			}
555 			continue;
556 		}
557 		if((ci->ci_ipending & SINT_TTY) & ~pcpl) {
558 			ci->ci_ipending &= ~SINT_TTY;
559 			ci->ci_cpl = SINT_TTY;
560 			ppc_intr_enable(1);
561 			KERNEL_LOCK();
562 			softtty();
563 			KERNEL_UNLOCK();
564 			ppc_intr_disable();
565 			continue;
566 		}
567 	} while ((ci->ci_ipending & SINT_MASK) & ~pcpl);
568 	ci->ci_cpl = pcpl;	/* Don't use splx... we are here already! */
569 
570 	atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT);
571 }
572 
573 u_int
574 openpic_read(int reg)
575 {
576 	char *addr = (void *)(openpic_base + reg);
577 
578 	if (openpic_big_endian)
579 		return in32(addr);
580 	else
581 		return in32rb(addr);
582 }
583 
584 void
585 openpic_write(int reg, u_int val)
586 {
587 	char *addr = (void *)(openpic_base + reg);
588 
589 	if (openpic_big_endian)
590 		out32(addr, val);
591 	else
592 		out32rb(addr, val);
593 }
594 
595 void
596 openpic_enable_irq_mask(int irq_mask)
597 {
598 	int irq;
599 	for ( irq = 0; irq <= o_virq_max; irq++) {
600 		if (irq_mask & (1 << irq))
601 			openpic_enable_irq(o_hwirq[irq]);
602 		else
603 			openpic_disable_irq(o_hwirq[irq]);
604 	}
605 }
606 
607 void
608 openpic_set_enable_irq(int irq, int type)
609 {
610 	u_int x;
611 
612 	x = openpic_read(OPENPIC_SRC_VECTOR(irq));
613 	x &= ~(OPENPIC_IMASK|OPENPIC_SENSE_LEVEL|OPENPIC_SENSE_EDGE);
614 	if (type == IST_LEVEL)
615 		x |= OPENPIC_SENSE_LEVEL;
616 	else
617 		x |= OPENPIC_SENSE_EDGE;
618 	openpic_write(OPENPIC_SRC_VECTOR(irq), x);
619 }
620 void
621 openpic_enable_irq(int irq)
622 {
623 	u_int x;
624 
625 	x = openpic_read(OPENPIC_SRC_VECTOR(irq));
626 	x &= ~(OPENPIC_IMASK|OPENPIC_SENSE_LEVEL|OPENPIC_SENSE_EDGE);
627 	if (o_intrtype[o_virq[irq]] == IST_LEVEL)
628 		x |= OPENPIC_SENSE_LEVEL;
629 	else
630 		x |= OPENPIC_SENSE_EDGE;
631 	openpic_write(OPENPIC_SRC_VECTOR(irq), x);
632 }
633 
634 void
635 openpic_disable_irq(int irq)
636 {
637 	u_int x;
638 
639 	x = openpic_read(OPENPIC_SRC_VECTOR(irq));
640 	x |= OPENPIC_IMASK;
641 	openpic_write(OPENPIC_SRC_VECTOR(irq), x);
642 }
643 
644 void
645 openpic_set_priority(int cpu, int pri)
646 {
647 	u_int x;
648 
649 	x = openpic_read(OPENPIC_CPU_PRIORITY(cpu));
650 	x &= ~OPENPIC_CPU_PRIORITY_MASK;
651 	x |= pri;
652 	openpic_write(OPENPIC_CPU_PRIORITY(cpu), x);
653 }
654 
655 int
656 openpic_read_irq(int cpu)
657 {
658 	return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
659 }
660 
661 void
662 openpic_eoi(int cpu)
663 {
664 	openpic_write(OPENPIC_EOI(cpu), 0);
665 	openpic_read(OPENPIC_EOI(cpu));
666 }
667 
668 #ifdef MULTIPROCESSOR
669 
670 void
671 openpic_send_ipi(struct cpu_info *ci, int id)
672 {
673 	switch (id) {
674 	case PPC_IPI_NOP:
675 		id = 0;
676 		break;
677 	case PPC_IPI_DDB:
678 		id = 1;
679 		break;
680 	default:
681 		panic("invalid ipi send to cpu %d %d\n", ci->ci_cpuid, id);
682 	}
683 
684 
685 	openpic_write(OPENPIC_IPI(curcpu()->ci_cpuid, id), 1 << ci->ci_cpuid);
686 }
687 
688 #endif
689 
690 void
691 ext_intr_openpic()
692 {
693 	struct cpu_info *ci = curcpu();
694 	int irq, realirq;
695 	int r_imen;
696 	int pcpl, ocpl;
697 	struct intrhand *ih;
698 
699 	pcpl = ci->ci_cpl;
700 
701 	realirq = openpic_read_irq(ci->ci_cpuid);
702 
703 	while (realirq != 255) {
704 #ifdef MULTIPROCESSOR
705 		if (realirq == IPI_VECTOR_NOP) {
706 			ipi_nop[ci->ci_cpuid].ec_count++;
707 			openpic_eoi(ci->ci_cpuid);
708 			realirq = openpic_read_irq(ci->ci_cpuid);
709 			continue;
710 		}
711 		if (realirq == IPI_VECTOR_DDB) {
712 			ipi_ddb[ci->ci_cpuid].ec_count++;
713 			openpic_eoi(ci->ci_cpuid);
714 			openpic_ipi_ddb();
715 			realirq = openpic_read_irq(ci->ci_cpuid);
716 			continue;
717 		}
718 #endif
719 
720 		irq = o_virq[realirq];
721 
722 		/* XXX check range */
723 
724 		r_imen = 1 << irq;
725 
726 		if ((pcpl & r_imen) != 0) {
727 			/* Masked! Mark this as pending. */
728 			ci->ci_ipending |= r_imen;
729 			openpic_enable_irq_mask(~imask[o_intrmaxlvl[realirq]]);
730 			openpic_eoi(ci->ci_cpuid);
731 		} else {
732 			openpic_enable_irq_mask(~imask[o_intrmaxlvl[realirq]]);
733 			openpic_eoi(ci->ci_cpuid);
734 			ocpl = splraise(imask[o_intrmaxlvl[realirq]]);
735 
736 			ih = o_intrhand[irq];
737 			while (ih) {
738 				ppc_intr_enable(1);
739 
740 				KERNEL_LOCK();
741 				if ((*ih->ih_fun)(ih->ih_arg))
742 					ih->ih_count.ec_count++;
743 				KERNEL_UNLOCK();
744 
745 				(void)ppc_intr_disable();
746 				ih = ih->ih_next;
747 			}
748 
749 			uvmexp.intrs++;
750 			__asm__ volatile("":::"memory"); /* don't reorder.... */
751 			ci->ci_cpl = ocpl;
752 			__asm__ volatile("":::"memory"); /* don't reorder.... */
753 			openpic_enable_irq_mask(~pcpl);
754 		}
755 
756 		realirq = openpic_read_irq(ci->ci_cpuid);
757 	}
758 	ppc_intr_enable(1);
759 
760 	splx(pcpl);	/* Process pendings. */
761 }
762 
763 void
764 openpic_init()
765 {
766 	int irq;
767 	u_int x;
768 
769 	/* disable all interrupts */
770 	for (irq = 0; irq < 255; irq++)
771 		openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
772 	openpic_set_priority(0, 15);
773 
774 	/* we don't need 8259 pass through mode */
775 	x = openpic_read(OPENPIC_CONFIG);
776 	x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
777 	openpic_write(OPENPIC_CONFIG, x);
778 
779 	/* send all interrupts to cpu 0 */
780 	for (irq = 0; irq < ICU_LEN; irq++)
781 		openpic_write(OPENPIC_IDEST(irq), 1 << 0);
782 	for (irq = 0; irq < ICU_LEN; irq++) {
783 		x = irq;
784 		x |= OPENPIC_IMASK;
785 		x |= OPENPIC_POLARITY_POSITIVE;
786 		x |= OPENPIC_SENSE_LEVEL;
787 		x |= 8 << OPENPIC_PRIORITY_SHIFT;
788 		openpic_write(OPENPIC_SRC_VECTOR(irq), x);
789 	}
790 
791 #ifdef MULTIPROCESSOR
792 	/* Set up inter-processor interrupts. */
793 	/* IPI0 - NOP */
794 	x = openpic_read(OPENPIC_IPI_VECTOR(0));
795 	x &= ~(OPENPIC_IMASK | OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK);
796 	x |= (15 << OPENPIC_PRIORITY_SHIFT) | IPI_VECTOR_NOP;
797 	openpic_write(OPENPIC_IPI_VECTOR(0), x);
798 	/* IPI1 - DDB */
799 	x = openpic_read(OPENPIC_IPI_VECTOR(1));
800 	x &= ~(OPENPIC_IMASK | OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK);
801 	x |= (15 << OPENPIC_PRIORITY_SHIFT) | IPI_VECTOR_DDB;
802 	openpic_write(OPENPIC_IPI_VECTOR(1), x);
803 
804 	evcount_attach(&ipi_nop[0], "ipi_nop0", (void *)&ipi_nopirq,
805 	    &evcount_intr);
806 	evcount_attach(&ipi_nop[1], "ipi_nop1", (void *)&ipi_nopirq,
807 	    &evcount_intr);
808 	evcount_attach(&ipi_ddb[0], "ipi_ddb0", (void *)&ipi_ddbirq,
809 	    &evcount_intr);
810 	evcount_attach(&ipi_ddb[1], "ipi_ddb1", (void *)&ipi_ddbirq,
811 	    &evcount_intr);
812 #endif
813 
814 	/* XXX set spurious intr vector */
815 
816 	openpic_set_priority(0, 0);
817 
818 	/* clear all pending interrunts */
819 	for (irq = 0; irq < ICU_LEN; irq++) {
820 		openpic_read_irq(0);
821 		openpic_eoi(0);
822 	}
823 
824 	for (irq = 0; irq < ICU_LEN; irq++)
825 		openpic_disable_irq(irq);
826 
827 	install_extint(ext_intr_openpic);
828 }
829 /*
830  * programmer_button function to fix args to Debugger.
831  * deal with any enables/disables, if necessary.
832  */
833 int
834 openpic_prog_button (void *arg)
835 {
836 #ifdef DDB
837 	if (db_console)
838 		Debugger();
839 #else
840 	printf("programmer button pressed, debugger not available\n");
841 #endif
842 	return 1;
843 }
844 
845 
846 void
847 openpic_ipi_ddb(void)
848 {
849 	Debugger();
850 }
851 
852