xref: /openbsd-src/sys/arch/macppc/dev/openpic.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: openpic.c,v 1.65 2011/08/29 20:21:44 drahn Exp $	*/
2 
3 /*-
4  * Copyright (c) 2008 Dale Rahn <drahn@openbsd.org>
5  * Copyright (c) 1995 Per Fogelstrom
6  * Copyright (c) 1993, 1994 Charles M. Hannum.
7  * Copyright (c) 1990 The Regents of the University of California.
8  * All rights reserved.
9  *
10  * This code is derived from software contributed to Berkeley by
11  * William Jolitz and Don Ahn.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	@(#)isa.c	7.2 (Berkeley) 5/12/91
38  */
39 
40 #include <sys/param.h>
41 #include <sys/device.h>
42 #include <sys/ioctl.h>
43 #include <sys/mbuf.h>
44 #include <sys/socket.h>
45 #include <sys/systm.h>
46 
47 #include <uvm/uvm.h>
48 #include <ddb/db_var.h>
49 
50 #include <machine/atomic.h>
51 #include <machine/autoconf.h>
52 #include <machine/intr.h>
53 #include <machine/psl.h>
54 #include <machine/pio.h>
55 #include <machine/powerpc.h>
56 #include <macppc/dev/openpicreg.h>
57 #include <dev/ofw/openfirm.h>
58 
59 #define ICU_LEN 128
60 int openpic_numirq = ICU_LEN;
61 #define LEGAL_IRQ(x) ((x >= 0) && (x < ICU_LEN))
62 
63 int openpic_pri_share[IPL_NUM];
64 
65 struct intrq openpic_handler[ICU_LEN];
66 
67 void openpic_calc_mask(void);
68 
69 ppc_splraise_t openpic_splraise;
70 ppc_spllower_t openpic_spllower;
71 ppc_splx_t openpic_splx;
72 
73 /* IRQ vector used for inter-processor interrupts. */
74 #define IPI_VECTOR_NOP	64
75 #define IPI_VECTOR_DDB	65
76 #ifdef MULTIPROCESSOR
77 static struct evcount ipi_ddb[PPC_MAXPROCS];
78 static struct evcount ipi_nop[PPC_MAXPROCS];
79 static int ipi_nopirq = IPI_VECTOR_NOP;
80 static int ipi_ddbirq = IPI_VECTOR_DDB;
81 #endif
82 struct evcount openpic_spurious;
83 int openpic_spurious_irq = 255;
84 
85 void	openpic_enable_irq(int, int);
86 void	openpic_disable_irq(int);
87 void	openpic_init(void);
88 void	openpic_set_priority(int, int);
89 void	openpic_ipi_ddb(void);
90 void	*openpic_intr_establish(void *, int, int, int, int (*)(void *),
91     void *, const char *);
92 
93 typedef void  (void_f) (void);
94 extern void_f *pending_int_f;
95 
96 vaddr_t openpic_base;
97 void	openpic_intr_disestablish( void *lcp, void *arg);
98 void	openpic_collect_preconf_intr(void);
99 int	openpic_big_endian;
100 #ifdef MULTIPROCESSOR
101 intr_send_ipi_t openpic_send_ipi;
102 #endif
103 
104 u_int openpic_read(int reg);
105 void openpic_write(int reg, u_int val);
106 
107 struct openpic_softc {
108 	struct device sc_dev;
109 };
110 
111 int	openpic_match(struct device *parent, void *cf, void *aux);
112 void	openpic_attach(struct device *, struct device *, void *);
113 void	openpic_do_pending_int(int pcpl);
114 void	openpic_do_pending_int_dis(int pcpl, int s);
115 void	openpic_collect_preconf_intr(void);
116 void	openpic_ext_intr(void);
117 
118 struct cfattach openpic_ca = {
119 	sizeof(struct openpic_softc),
120 	openpic_match,
121 	openpic_attach
122 };
123 
124 struct cfdriver openpic_cd = {
125 	NULL, "openpic", DV_DULL
126 };
127 
128 u_int
129 openpic_read(int reg)
130 {
131 	char *addr = (void *)(openpic_base + reg);
132 
133 	asm volatile("eieio"::: "memory");
134 	if (openpic_big_endian)
135 		return in32(addr);
136 	else
137 		return in32rb(addr);
138 }
139 
140 void
141 openpic_write(int reg, u_int val)
142 {
143 	char *addr = (void *)(openpic_base + reg);
144 
145 	if (openpic_big_endian)
146 		out32(addr, val);
147 	else
148 		out32rb(addr, val);
149 	asm volatile("eieio"::: "memory");
150 }
151 
152 static inline int
153 openpic_read_irq(int cpu)
154 {
155 	return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
156 }
157 
158 static inline void
159 openpic_eoi(int cpu)
160 {
161 	openpic_write(OPENPIC_EOI(cpu), 0);
162 }
163 
164 int
165 openpic_match(struct device *parent, void *cf, void *aux)
166 {
167 	char type[40];
168 	int pirq;
169 	struct confargs *ca = aux;
170 
171 	bzero (type, sizeof(type));
172 
173 	if (OF_getprop(ca->ca_node, "interrupt-parent", &pirq, sizeof(pirq))
174 	    == sizeof(pirq))
175 		return 0; /* XXX */
176 
177 	if (strcmp(ca->ca_name, "interrupt-controller") != 0 &&
178 	    strcmp(ca->ca_name, "mpic") != 0)
179 		return 0;
180 
181 	OF_getprop(ca->ca_node, "device_type", type, sizeof(type));
182 	if (strcmp(type, "open-pic") != 0)
183 		return 0;
184 
185 	if (ca->ca_nreg < 8)
186 		return 0;
187 
188 	return 1;
189 }
190 
191 void
192 openpic_attach(struct device *parent, struct device  *self, void *aux)
193 {
194 	struct cpu_info *ci = curcpu();
195 	struct confargs *ca = aux;
196 	u_int32_t reg;
197 
198 	reg = 0;
199 	if (OF_getprop(ca->ca_node, "big-endian", &reg, sizeof reg) == 0)
200 		openpic_big_endian = 1;
201 
202 	openpic_base = (vaddr_t) mapiodev (ca->ca_baseaddr +
203 			ca->ca_reg[0], 0x40000);
204 
205 	/* openpic may support more than 128 interupts but driver doesn't */
206 	openpic_numirq = ((openpic_read(OPENPIC_FEATURE) >> 16) & 0x7f)+1;
207 
208 	printf(": version 0x%x feature %x %s",
209 	    openpic_read(OPENPIC_VENDOR_ID),
210 	    openpic_read(OPENPIC_FEATURE),
211 		openpic_big_endian ? "BE" : "LE" );
212 
213 	openpic_init();
214 
215 	intr_establish_func  = openpic_intr_establish;
216 	intr_disestablish_func  = openpic_intr_disestablish;
217 	mac_intr_establish_func  = openpic_intr_establish;
218 	mac_intr_disestablish_func  = openpic_intr_disestablish;
219 #ifdef MULTIPROCESSOR
220 	intr_send_ipi_func = openpic_send_ipi;
221 #endif
222 
223 	ppc_smask_init();
224 
225 	openpic_collect_preconf_intr();
226 
227 	evcount_attach(&openpic_spurious, "spurious", &openpic_spurious_irq);
228 
229 	ppc_intr_func.raise = openpic_splraise;
230 	ppc_intr_func.lower = openpic_spllower;
231 	ppc_intr_func.x = openpic_splx;
232 
233 	openpic_set_priority(0, ci->ci_cpl);
234 
235 	ppc_intr_enable(1);
236 
237 	printf("\n");
238 }
239 
240 static inline void
241 openpic_setipl(int newcpl)
242 {
243 	struct cpu_info *ci = curcpu();
244 	int s;
245 	/* XXX - try do to this without the disable */
246 	s = ppc_intr_disable();
247 	ci->ci_cpl = newcpl;
248 	openpic_set_priority(ci->ci_cpuid, newcpl);
249 	ppc_intr_enable(s);
250 }
251 
252 int
253 openpic_splraise(int newcpl)
254 {
255 	struct cpu_info *ci = curcpu();
256 	newcpl = openpic_pri_share[newcpl];
257 	int ocpl = ci->ci_cpl;
258 	if (ocpl > newcpl)
259 		newcpl = ocpl;
260 
261 	openpic_setipl(newcpl);
262 
263 	return ocpl;
264 }
265 
266 int
267 openpic_spllower(int newcpl)
268 {
269 	struct cpu_info *ci = curcpu();
270 	int ocpl = ci->ci_cpl;
271 
272 	openpic_splx(newcpl);
273 
274 	return ocpl;
275 }
276 
277 void
278 openpic_splx(int newcpl)
279 {
280 	openpic_do_pending_int(newcpl);
281 }
282 
283 void
284 openpic_collect_preconf_intr()
285 {
286 	int i;
287 	for (i = 0; i < ppc_configed_intr_cnt; i++) {
288 #ifdef DEBUG
289 		printf("\n\t%s irq %d level %d fun %x arg %x",
290 		    ppc_configed_intr[i].ih_what, ppc_configed_intr[i].ih_irq,
291 		    ppc_configed_intr[i].ih_level, ppc_configed_intr[i].ih_fun,
292 		    ppc_configed_intr[i].ih_arg);
293 #endif
294 		openpic_intr_establish(NULL, ppc_configed_intr[i].ih_irq,
295 		    IST_LEVEL, ppc_configed_intr[i].ih_level,
296 		    ppc_configed_intr[i].ih_fun, ppc_configed_intr[i].ih_arg,
297 		    ppc_configed_intr[i].ih_what);
298 	}
299 }
300 
301 /*
302  * Register an interrupt handler.
303  */
304 void *
305 openpic_intr_establish(void *lcv, int irq, int type, int level,
306     int (*ih_fun)(void *), void *ih_arg, const char *name)
307 {
308 	struct intrhand *ih;
309 	struct intrq *iq;
310 	int s;
311 
312 	/* no point in sleeping unless someone can free memory. */
313 	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
314 	if (ih == NULL)
315 		panic("intr_establish: can't malloc handler info");
316 	iq = &openpic_handler[irq];
317 
318 	if (!LEGAL_IRQ(irq) || type == IST_NONE)
319 		panic("intr_establish: bogus irq or type");
320 
321 	switch (iq->iq_ist) {
322 	case IST_NONE:
323 		iq->iq_ist = type;
324 		break;
325 	case IST_EDGE:
326 		intr_shared_edge = 1;
327 		/* FALLTHROUGH */
328 	case IST_LEVEL:
329 		if (type == iq->iq_ist)
330 			break;
331 	case IST_PULSE:
332 		if (type != IST_NONE)
333 			panic("intr_establish: can't share %s with %s",
334 			    ppc_intr_typename(iq->iq_ist),
335 			    ppc_intr_typename(type));
336 		break;
337 	}
338 
339 	ih->ih_fun = ih_fun;
340 	ih->ih_arg = ih_arg;
341 	ih->ih_level = level;
342 	ih->ih_irq = irq;
343 
344 	evcount_attach(&ih->ih_count, name, &ih->ih_irq);
345 
346 	/*
347 	 * Append handler to end of list
348 	 */
349 	s = ppc_intr_disable();
350 
351 	TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list);
352 	openpic_calc_mask();
353 
354 	ppc_intr_enable(s);
355 
356 	return (ih);
357 }
358 
359 /*
360  * Deregister an interrupt handler.
361  */
362 void
363 openpic_intr_disestablish(void *lcp, void *arg)
364 {
365 	struct intrhand *ih = arg;
366 	int irq = ih->ih_irq;
367 	struct intrq *iq = &openpic_handler[irq];
368 	int s;
369 
370 	if (!LEGAL_IRQ(irq))
371 		panic("intr_disestablish: bogus irq");
372 
373 	/*
374 	 * Remove the handler from the chain.
375 	 */
376 	s = ppc_intr_disable();
377 
378 	TAILQ_REMOVE(&iq->iq_list, ih, ih_list);
379 	openpic_calc_mask();
380 
381 	ppc_intr_enable(s);
382 
383 	evcount_detach(&ih->ih_count);
384 	free((void *)ih, M_DEVBUF);
385 
386 	if (TAILQ_EMPTY(&iq->iq_list))
387 		iq->iq_ist = IST_NONE;
388 }
389 
390 /*
391  * Recalculate the interrupt masks from scratch.
392  * We could code special registry and deregistry versions of this function that
393  * would be faster, but the code would be nastier, and we don't expect this to
394  * happen very much anyway.
395  */
396 
397 void
398 openpic_calc_mask()
399 {
400 	struct cpu_info *ci = curcpu();
401 	int irq;
402 	struct intrhand *ih;
403 	int i;
404 
405 	/* disable all openpic interrupts */
406 	openpic_set_priority(ci->ci_cpuid, 15);
407 
408 	for (i = IPL_NONE; i < IPL_NUM; i++) {
409 		openpic_pri_share[i] = i;
410 	}
411 
412 	for (irq = 0; irq < openpic_numirq; irq++) {
413 		int maxipl = IPL_NONE;
414 		int minipl = IPL_HIGH;
415 		struct intrq *iq = &openpic_handler[irq];
416 
417 		TAILQ_FOREACH(ih, &iq->iq_list, ih_list) {
418 			if (ih->ih_level > maxipl)
419 				maxipl = ih->ih_level;
420 			if (ih->ih_level < minipl)
421 				minipl = ih->ih_level;
422 		}
423 
424 		if (maxipl == IPL_NONE) {
425 			minipl = IPL_NONE; /* Interrupt not enabled */
426 
427 			openpic_disable_irq(irq);
428 		} else {
429 			for (i = minipl; i <= maxipl; i++) {
430 				openpic_pri_share[i] = maxipl;
431 			}
432 			openpic_enable_irq(irq, maxipl);
433 		}
434 
435 		iq->iq_ipl = maxipl;
436 	}
437 
438 	/* restore interrupts */
439 	openpic_set_priority(ci->ci_cpuid, ci->ci_cpl);
440 }
441 
442 void
443 openpic_do_pending_int(int pcpl)
444 {
445 	int s;
446 	s = ppc_intr_disable();
447 	openpic_do_pending_int_dis(pcpl, s);
448 	ppc_intr_enable(s);
449 
450 }
451 
452 /*
453  * This function expect interrupts disabled on entry and exit,
454  * the s argument indicates if interrupts may be enabled during
455  * the processing of off level interrupts, s 'should' always be 1.
456  */
457 void
458 openpic_do_pending_int_dis(int pcpl, int s)
459 {
460 	struct cpu_info *ci = curcpu();
461 
462 	if (ci->ci_iactive & CI_IACTIVE_PROCESSING_SOFT) {
463 		/* soft interrupts are being processed, just set ipl/return */
464 		openpic_setipl(pcpl);
465 		return;
466 	}
467 
468 	atomic_setbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT);
469 
470 	do {
471 		if((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTCLOCK)) &&
472 		    (pcpl < IPL_SOFTCLOCK)) {
473  			ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTCLOCK);
474 			softintr_dispatch(SI_SOFTCLOCK);
475  		}
476 		if((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTNET)) &&
477 		    (pcpl < IPL_SOFTNET)) {
478 			ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTNET);
479 			softintr_dispatch(SI_SOFTNET);
480 		}
481 		if((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTTTY)) &&
482 		    (pcpl < IPL_SOFTTTY)) {
483 			ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTTTY);
484 			softintr_dispatch(SI_SOFTTTY);
485 		}
486 	} while (ci->ci_ipending & ppc_smask[pcpl]);
487 	openpic_setipl(pcpl);	/* Don't use splx... we are here already! */
488 
489 	atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT);
490 }
491 
492 void
493 openpic_enable_irq(int irq, int pri)
494 {
495 	u_int x;
496 	struct intrq *iq = &openpic_handler[irq];
497 
498 	x = irq;
499 	if (iq->iq_ist == IST_LEVEL)
500 		x |= OPENPIC_SENSE_LEVEL;
501 	else
502 		x |= OPENPIC_SENSE_EDGE;
503 	x |= OPENPIC_POLARITY_NEGATIVE;
504 	x |= pri << OPENPIC_PRIORITY_SHIFT;
505 	openpic_write(OPENPIC_SRC_VECTOR(irq), x);
506 }
507 
508 void
509 openpic_disable_irq(int irq)
510 {
511 	u_int x;
512 
513 	x = openpic_read(OPENPIC_SRC_VECTOR(irq));
514 	x |= OPENPIC_IMASK;
515 	openpic_write(OPENPIC_SRC_VECTOR(irq), x);
516 }
517 
518 void
519 openpic_set_priority(int cpu, int pri)
520 {
521 	openpic_write(OPENPIC_CPU_PRIORITY(cpu), pri);
522 }
523 
524 #ifdef MULTIPROCESSOR
525 void
526 openpic_send_ipi(struct cpu_info *ci, int id)
527 {
528 	switch (id) {
529 	case PPC_IPI_NOP:
530 		id = 0;
531 		break;
532 	case PPC_IPI_DDB:
533 		id = 1;
534 		break;
535 	default:
536 		panic("invalid ipi send to cpu %d %d", ci->ci_cpuid, id);
537 	}
538 
539 	openpic_write(OPENPIC_IPI(curcpu()->ci_cpuid, id), 1 << ci->ci_cpuid);
540 }
541 
542 #endif
543 
544 int openpic_irqnest[PPC_MAXPROCS];
545 int openpic_irqloop[PPC_MAXPROCS];
546 void
547 openpic_ext_intr()
548 {
549 	struct cpu_info *ci = curcpu();
550 	int irq, pcpl, ret;
551 	int maxipl = IPL_NONE;
552 	struct intrhand *ih;
553 	struct intrq *iq;
554 	int spurious;
555 
556 	pcpl = ci->ci_cpl;
557 
558 	openpic_irqloop[ci->ci_cpuid] = 0;
559 	irq = openpic_read_irq(ci->ci_cpuid);
560 	openpic_irqnest[ci->ci_cpuid]++;
561 
562 	while (irq != 255) {
563 		openpic_irqloop[ci->ci_cpuid]++;
564 		if (openpic_irqloop[ci->ci_cpuid] > 20 ||
565 		    openpic_irqnest[ci->ci_cpuid] > 3) {
566 			printf("irqloop %d irqnest %d\n",
567 			    openpic_irqloop[ci->ci_cpuid],
568 			    openpic_irqnest[ci->ci_cpuid]);
569 		}
570 #ifdef MULTIPROCESSOR
571 		if (irq == IPI_VECTOR_NOP) {
572 			ipi_nop[ci->ci_cpuid].ec_count++;
573 			openpic_eoi(ci->ci_cpuid);
574 			irq = openpic_read_irq(ci->ci_cpuid);
575 			continue;
576 		}
577 		if (irq == IPI_VECTOR_DDB) {
578 			ipi_ddb[ci->ci_cpuid].ec_count++;
579 			openpic_eoi(ci->ci_cpuid);
580 			openpic_ipi_ddb();
581 			irq = openpic_read_irq(ci->ci_cpuid);
582 			continue;
583 		}
584 #endif
585 		iq = &openpic_handler[irq];
586 
587 		if (iq->iq_ipl <= ci->ci_cpl)
588 			printf("invalid interrupt %d lvl %d at %d hw %d\n",
589 			    irq, iq->iq_ipl, ci->ci_cpl,
590 			    openpic_read(OPENPIC_CPU_PRIORITY(ci->ci_cpuid)));
591 		if (iq->iq_ipl > maxipl)
592 			maxipl = iq->iq_ipl;
593 		splraise(iq->iq_ipl);
594 		openpic_eoi(ci->ci_cpuid);
595 
596 		spurious = 1;
597 		TAILQ_FOREACH(ih, &iq->iq_list, ih_list) {
598 			ppc_intr_enable(1);
599 			KERNEL_LOCK();
600 			ret = (*ih->ih_fun)(ih->ih_arg);
601 			if (ret) {
602 				ih->ih_count.ec_count++;
603 				spurious = 0;
604  			}
605 			KERNEL_UNLOCK();
606 
607 			(void)ppc_intr_disable();
608 			if (intr_shared_edge == 00 && ret == 1)
609 				break;
610  		}
611 		if (spurious) {
612 			openpic_spurious.ec_count++;
613 #ifdef OPENPIC_NOISY
614 			printf("spurious intr %d\n", irq);
615 #endif
616 		}
617 
618 		uvmexp.intrs++;
619 		openpic_setipl(pcpl);
620 
621 		irq = openpic_read_irq(ci->ci_cpuid);
622 	}
623 
624 	if (openpic_irqnest[ci->ci_cpuid] == 1) {
625 		openpic_irqloop[ci->ci_cpuid] = 0;
626 		/* raise IPL back to max until do_pending will lower it back */
627 		openpic_setipl(maxipl);
628 		/*
629 		 * we must not process pending soft interrupts when nested, can
630 		 * cause excessive recursion.
631 		 *
632 		 * The loop here is because an interrupt could case a pending
633 		 * soft interrupt between the finishing of the
634 		 * openpic_do_pending_int, but before ppc_intr_disable
635 		 */
636 		do {
637 			openpic_irqloop[ci->ci_cpuid]++;
638 			if (openpic_irqloop[ci->ci_cpuid] > 5) {
639 				printf("ext_intr: do_pending loop %d\n",
640 				    openpic_irqloop[ci->ci_cpuid]);
641 			}
642 			if (ci->ci_iactive & CI_IACTIVE_PROCESSING_SOFT) {
643 				openpic_setipl(pcpl);
644 				/*
645 				 * some may be pending but someone else is
646 				 * processing them
647 				 */
648 				break;
649 			} else {
650 				openpic_do_pending_int_dis(pcpl, 1);
651 			}
652 		} while (ci->ci_ipending & ppc_smask[pcpl]);
653 	}
654 	openpic_irqnest[ci->ci_cpuid]--;
655 }
656 
657 void
658 openpic_init()
659 {
660 	struct cpu_info *ci = curcpu();
661 	struct intrq *iq;
662 	int irq;
663 	u_int x;
664 	int i;
665 
666 	openpic_set_priority(ci->ci_cpuid, 15);
667 
668 	/* disable all interrupts */
669 	for (irq = 0; irq < openpic_numirq; irq++)
670 		openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
671 
672 	for (i = 0; i < openpic_numirq; i++) {
673 		iq = &openpic_handler[i];
674 		TAILQ_INIT(&iq->iq_list);
675 	}
676 
677 	/* we don't need 8259 pass through mode */
678 	x = openpic_read(OPENPIC_CONFIG);
679 	x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
680 	openpic_write(OPENPIC_CONFIG, x);
681 
682 	/* initialize all vectors to something sane */
683 	for (irq = 0; irq < ICU_LEN; irq++) {
684 		x = irq;
685 		x |= OPENPIC_IMASK;
686 		x |= OPENPIC_POLARITY_NEGATIVE;
687 		x |= OPENPIC_SENSE_LEVEL;
688 		x |= 8 << OPENPIC_PRIORITY_SHIFT;
689 		openpic_write(OPENPIC_SRC_VECTOR(irq), x);
690 	}
691 
692 	/* send all interrupts to cpu 0 */
693 	for (irq = 0; irq < openpic_numirq; irq++)
694 		openpic_write(OPENPIC_IDEST(irq), 1 << 0);
695 
696 	/* clear all pending interrunts */
697 	for (irq = 0; irq < ICU_LEN; irq++) {
698 		openpic_read_irq(ci->ci_cpuid);
699 		openpic_eoi(ci->ci_cpuid);
700 	}
701 
702 #ifdef MULTIPROCESSOR
703 	/* Set up inter-processor interrupts. */
704 	/* IPI0 - NOP */
705 	x = IPI_VECTOR_NOP;
706 	x |= 15 << OPENPIC_PRIORITY_SHIFT;
707 	openpic_write(OPENPIC_IPI_VECTOR(0), x);
708 	/* IPI1 - DDB */
709 	x = IPI_VECTOR_DDB;
710 	x |= 15 << OPENPIC_PRIORITY_SHIFT;
711 	openpic_write(OPENPIC_IPI_VECTOR(1), x);
712 
713 	/* XXX - ncpus */
714 	evcount_attach(&ipi_nop[0], "ipi_nop0", &ipi_nopirq);
715 	evcount_attach(&ipi_nop[1], "ipi_nop1", &ipi_nopirq);
716 	evcount_attach(&ipi_ddb[0], "ipi_ddb0", &ipi_ddbirq);
717 	evcount_attach(&ipi_ddb[1], "ipi_ddb1", &ipi_ddbirq);
718 #endif
719 
720 	/* clear all pending interrunts */
721 	for (irq = 0; irq < ICU_LEN; irq++) {
722 		openpic_read_irq(0);
723 		openpic_eoi(0);
724 	}
725 
726 #if 0
727 	openpic_write(OPENPIC_SPURIOUS_VECTOR, 255);
728 #endif
729 
730 	install_extint(openpic_ext_intr);
731 
732 	openpic_set_priority(ci->ci_cpuid, 0);
733 }
734 
735 void
736 openpic_ipi_ddb()
737 {
738 #ifdef OPENPIC_NOISY
739 	printf("ipi_ddb() called\n");
740 #endif
741 	Debugger();
742 }
743