199651Sbenno/*-
299651Sbenno * Copyright (c) 1991 The Regents of the University of California.
399651Sbenno * All rights reserved.
499651Sbenno *
599651Sbenno * This code is derived from software contributed to Berkeley by
699651Sbenno * William Jolitz.
799651Sbenno *
899651Sbenno * Redistribution and use in source and binary forms, with or without
999651Sbenno * modification, are permitted provided that the following conditions
1099651Sbenno * are met:
1199651Sbenno * 1. Redistributions of source code must retain the above copyright
1299651Sbenno *    notice, this list of conditions and the following disclaimer.
1399651Sbenno * 2. Redistributions in binary form must reproduce the above copyright
1499651Sbenno *    notice, this list of conditions and the following disclaimer in the
1599651Sbenno *    documentation and/or other materials provided with the distribution.
1699651Sbenno * 4. Neither the name of the University nor the names of its contributors
1799651Sbenno *    may be used to endorse or promote products derived from this software
1899651Sbenno *    without specific prior written permission.
1999651Sbenno *
2099651Sbenno * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2199651Sbenno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2299651Sbenno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2399651Sbenno * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2499651Sbenno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2599651Sbenno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2699651Sbenno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2799651Sbenno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2899651Sbenno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2999651Sbenno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3099651Sbenno * SUCH DAMAGE.
3199651Sbenno */
3299651Sbenno/*-
3399651Sbenno * Copyright (c) 2002 Benno Rice.
3499651Sbenno * All rights reserved.
3599651Sbenno *
3699651Sbenno * Redistribution and use in source and binary forms, with or without
3799651Sbenno * modification, are permitted provided that the following conditions
3899651Sbenno * are met:
3999651Sbenno * 1. Redistributions of source code must retain the above copyright
4099651Sbenno *    notice, this list of conditions and the following disclaimer.
4199651Sbenno * 2. Redistributions in binary form must reproduce the above copyright
4299651Sbenno *    notice, this list of conditions and the following disclaimer in the
4399651Sbenno *    documentation and/or other materials provided with the distribution.
4499651Sbenno *
4599651Sbenno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4699651Sbenno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4799651Sbenno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4899651Sbenno * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4999651Sbenno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5099651Sbenno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5199651Sbenno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5299651Sbenno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5399651Sbenno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5499651Sbenno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5599651Sbenno * SUCH DAMAGE.
5699651Sbenno *
5799651Sbenno *	from: @(#)isa.c	7.2 (Berkeley) 5/13/91
5899651Sbenno *	form: src/sys/i386/isa/intr_machdep.c,v 1.57 2001/07/20
5999651Sbenno *
6099651Sbenno * $FreeBSD$
6199651Sbenno */
6299651Sbenno
63218075Smarcel#include "opt_isa.h"
64218075Smarcel
6599651Sbenno#include <sys/param.h>
6699651Sbenno#include <sys/systm.h>
6799651Sbenno#include <sys/kernel.h>
6899651Sbenno#include <sys/queue.h>
6999651Sbenno#include <sys/bus.h>
70222813Sattilio#include <sys/cpuset.h>
7199651Sbenno#include <sys/interrupt.h>
72164987Smarcel#include <sys/ktr.h>
7399651Sbenno#include <sys/lock.h>
7499651Sbenno#include <sys/malloc.h>
7599651Sbenno#include <sys/mutex.h>
7699651Sbenno#include <sys/pcpu.h>
77209486Snwhitehorn#include <sys/smp.h>
78171805Smarcel#include <sys/syslog.h>
7999651Sbenno#include <sys/vmmeter.h>
80125708Sgrehan#include <sys/proc.h>
8199651Sbenno
8299651Sbenno#include <machine/frame.h>
8399651Sbenno#include <machine/intr_machdep.h>
84171805Smarcel#include <machine/md_var.h>
85178628Smarcel#include <machine/smp.h>
8699651Sbenno#include <machine/trap.h>
8799651Sbenno
88171805Smarcel#include "pic_if.h"
89171805Smarcel
9099651Sbenno#define	MAX_STRAY_LOG	5
9199651Sbenno
92249132Smavstatic MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
9399651Sbenno
94171805Smarcelstruct powerpc_intr {
95164987Smarcel	struct intr_event *event;
96164987Smarcel	long	*cntp;
97191450Smarcel	u_int	irq;
98191450Smarcel	device_t pic;
99191450Smarcel	u_int	intline;
100191450Smarcel	u_int	vector;
101212453Smav	u_int	cntindex;
102222813Sattilio	cpuset_t cpu;
103176918Smarcel	enum intr_trigger trig;
104176918Smarcel	enum intr_polarity pol;
105164987Smarcel};
10699651Sbenno
107209298Snwhitehornstruct pic {
108218075Smarcel	device_t dev;
109218075Smarcel	uint32_t node;
110218075Smarcel	u_int	irqs;
111218075Smarcel	u_int	ipis;
112218075Smarcel	int	base;
113209298Snwhitehorn};
114209298Snwhitehorn
115212453Smavstatic u_int intrcnt_index = 0;
116191307Srajstatic struct mtx intr_table_lock;
117171805Smarcelstatic struct powerpc_intr *powerpc_intrs[INTR_VECTORS];
118209298Snwhitehornstatic struct pic piclist[MAX_PICS];
119171805Smarcelstatic u_int nvectors;		/* Allocated vectors */
120209298Snwhitehornstatic u_int npics;		/* PICs registered */
121218075Smarcel#ifdef DEV_ISA
122218075Smarcelstatic u_int nirqs = 16;	/* Allocated IRQS (ISA pre-allocated). */
123218075Smarcel#else
124218075Smarcelstatic u_int nirqs = 0;		/* Allocated IRQs. */
125218075Smarcel#endif
126171805Smarcelstatic u_int stray_count;
12799651Sbenno
128209298Snwhitehorndevice_t root_pic;
129209298Snwhitehorn
130178628Smarcel#ifdef SMP
131178628Smarcelstatic void *ipi_cookie;
132178628Smarcel#endif
133178628Smarcel
134177068Smarcelstatic void
135191307Srajintr_init(void *dummy __unused)
136191307Sraj{
137191307Sraj
138191307Sraj	mtx_init(&intr_table_lock, "intr sources lock", NULL, MTX_DEF);
139191307Sraj}
140191307SrajSYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
141191307Sraj
142209486Snwhitehorn#ifdef SMP
143191307Srajstatic void
144209486Snwhitehornsmp_intr_init(void *dummy __unused)
145209486Snwhitehorn{
146209486Snwhitehorn	struct powerpc_intr *i;
147209486Snwhitehorn	int vector;
148209486Snwhitehorn
149209486Snwhitehorn	for (vector = 0; vector < nvectors; vector++) {
150209486Snwhitehorn		i = powerpc_intrs[vector];
151209486Snwhitehorn		if (i != NULL && i->pic == root_pic)
152209486Snwhitehorn			PIC_BIND(i->pic, i->intline, i->cpu);
153209486Snwhitehorn	}
154209486Snwhitehorn}
155209486SnwhitehornSYSINIT(smp_intr_init, SI_SUB_SMP, SI_ORDER_ANY, smp_intr_init, NULL);
156209486Snwhitehorn#endif
157209486Snwhitehorn
158209486Snwhitehornstatic void
159177068Smarcelintrcnt_setname(const char *name, int index)
160177068Smarcel{
161191307Sraj
162177068Smarcel	snprintf(intrnames + (MAXCOMLEN + 1) * index, MAXCOMLEN + 1, "%-*s",
163177068Smarcel	    MAXCOMLEN, name);
164177068Smarcel}
165177068Smarcel
166212453Smavvoid
167212453Smavintrcnt_add(const char *name, u_long **countp)
168212453Smav{
169212453Smav	int idx;
170212453Smav
171212453Smav	idx = atomic_fetchadd_int(&intrcnt_index, 1);
172212453Smav	*countp = &intrcnt[idx];
173212453Smav	intrcnt_setname(name, idx);
174212453Smav}
175212453Smav
176176918Smarcelstatic struct powerpc_intr *
177176918Smarcelintr_lookup(u_int irq)
178176918Smarcel{
179177068Smarcel	char intrname[8];
180176918Smarcel	struct powerpc_intr *i, *iscan;
181176918Smarcel	int vector;
182176918Smarcel
183191307Sraj	mtx_lock(&intr_table_lock);
184176918Smarcel	for (vector = 0; vector < nvectors; vector++) {
185176918Smarcel		i = powerpc_intrs[vector];
186191307Sraj		if (i != NULL && i->irq == irq) {
187191307Sraj			mtx_unlock(&intr_table_lock);
188176918Smarcel			return (i);
189191307Sraj		}
190176918Smarcel	}
191176918Smarcel
192176918Smarcel	i = malloc(sizeof(*i), M_INTR, M_NOWAIT);
193209486Snwhitehorn	if (i == NULL) {
194209486Snwhitehorn		mtx_unlock(&intr_table_lock);
195176918Smarcel		return (NULL);
196209486Snwhitehorn	}
197176918Smarcel
198176918Smarcel	i->event = NULL;
199176918Smarcel	i->cntp = NULL;
200176918Smarcel	i->trig = INTR_TRIGGER_CONFORM;
201176918Smarcel	i->pol = INTR_POLARITY_CONFORM;
202176918Smarcel	i->irq = irq;
203208835Snwhitehorn	i->pic = NULL;
204176918Smarcel	i->vector = -1;
205176918Smarcel
206209486Snwhitehorn#ifdef SMP
207209486Snwhitehorn	i->cpu = all_cpus;
208209486Snwhitehorn#else
209222813Sattilio	CPU_SETOF(0, &i->cpu);
210209486Snwhitehorn#endif
211209486Snwhitehorn
212176918Smarcel	for (vector = 0; vector < INTR_VECTORS && vector <= nvectors;
213176918Smarcel	    vector++) {
214176918Smarcel		iscan = powerpc_intrs[vector];
215176918Smarcel		if (iscan != NULL && iscan->irq == irq)
216176918Smarcel			break;
217176918Smarcel		if (iscan == NULL && i->vector == -1)
218176918Smarcel			i->vector = vector;
219176918Smarcel		iscan = NULL;
220176918Smarcel	}
221176918Smarcel
222176918Smarcel	if (iscan == NULL && i->vector != -1) {
223176918Smarcel		powerpc_intrs[i->vector] = i;
224212453Smav		i->cntindex = atomic_fetchadd_int(&intrcnt_index, 1);
225212453Smav		i->cntp = &intrcnt[i->cntindex];
226177068Smarcel		sprintf(intrname, "irq%u:", i->irq);
227212453Smav		intrcnt_setname(intrname, i->cntindex);
228176918Smarcel		nvectors++;
229176918Smarcel	}
230191307Sraj	mtx_unlock(&intr_table_lock);
231176918Smarcel
232176918Smarcel	if (iscan != NULL || i->vector == -1) {
233176918Smarcel		free(i, M_INTR);
234176918Smarcel		i = iscan;
235176918Smarcel	}
236176918Smarcel
237176918Smarcel	return (i);
238176918Smarcel}
239176918Smarcel
240191450Smarcelstatic int
241191450Smarcelpowerpc_map_irq(struct powerpc_intr *i)
242191450Smarcel{
243218075Smarcel	struct pic *p;
244218075Smarcel	u_int cnt;
245218075Smarcel	int idx;
246191450Smarcel
247218075Smarcel	for (idx = 0; idx < npics; idx++) {
248218075Smarcel		p = &piclist[idx];
249218075Smarcel		cnt = p->irqs + p->ipis;
250218075Smarcel		if (i->irq >= p->base && i->irq < p->base + cnt)
251218075Smarcel			break;
252218075Smarcel	}
253218075Smarcel	if (idx == npics)
254218075Smarcel		return (EINVAL);
255191450Smarcel
256218075Smarcel	i->intline = i->irq - p->base;
257218075Smarcel	i->pic = p->dev;
258218075Smarcel
259209298Snwhitehorn	/* Try a best guess if that failed */
260209298Snwhitehorn	if (i->pic == NULL)
261209298Snwhitehorn		i->pic = root_pic;
262209298Snwhitehorn
263191450Smarcel	return (0);
264191450Smarcel}
265191450Smarcel
266171805Smarcelstatic void
267171805Smarcelpowerpc_intr_eoi(void *arg)
26899651Sbenno{
269191450Smarcel	struct powerpc_intr *i = arg;
27099651Sbenno
271191450Smarcel	PIC_EOI(i->pic, i->intline);
272171805Smarcel}
27399651Sbenno
274171805Smarcelstatic void
275209724Snwhitehornpowerpc_intr_pre_ithread(void *arg)
276171805Smarcel{
277191450Smarcel	struct powerpc_intr *i = arg;
27899651Sbenno
279191450Smarcel	PIC_MASK(i->pic, i->intline);
280209724Snwhitehorn	PIC_EOI(i->pic, i->intline);
281171805Smarcel}
28299651Sbenno
283171805Smarcelstatic void
284209724Snwhitehornpowerpc_intr_post_ithread(void *arg)
285171805Smarcel{
286191450Smarcel	struct powerpc_intr *i = arg;
287164987Smarcel
288191450Smarcel	PIC_UNMASK(i->pic, i->intline);
289171805Smarcel}
290125708Sgrehan
291209724Snwhitehornstatic int
292209724Snwhitehornpowerpc_assign_intr_cpu(void *arg, u_char cpu)
293209724Snwhitehorn{
294209724Snwhitehorn#ifdef SMP
295209724Snwhitehorn	struct powerpc_intr *i = arg;
296209724Snwhitehorn
297209724Snwhitehorn	if (cpu == NOCPU)
298209724Snwhitehorn		i->cpu = all_cpus;
299209724Snwhitehorn	else
300222813Sattilio		CPU_SETOF(cpu, &i->cpu);
301209724Snwhitehorn
302209724Snwhitehorn	if (!cold && i->pic != NULL && i->pic == root_pic)
303209724Snwhitehorn		PIC_BIND(i->pic, i->intline, i->cpu);
304209724Snwhitehorn
305209724Snwhitehorn	return (0);
306209724Snwhitehorn#else
307209724Snwhitehorn	return (EOPNOTSUPP);
308209724Snwhitehorn#endif
309209724Snwhitehorn}
310209724Snwhitehorn
311171805Smarcelvoid
312218075Smarcelpowerpc_register_pic(device_t dev, uint32_t node, u_int irqs, u_int ipis,
313218075Smarcel    u_int atpic)
314171805Smarcel{
315218075Smarcel	struct pic *p;
316218075Smarcel	u_int irq;
317218075Smarcel	int idx;
318171805Smarcel
319209298Snwhitehorn	mtx_lock(&intr_table_lock);
320209298Snwhitehorn
321218075Smarcel	/* XXX see powerpc_get_irq(). */
322218075Smarcel	for (idx = 0; idx < npics; idx++) {
323218075Smarcel		p = &piclist[idx];
324218075Smarcel		if (p->node != node)
325218075Smarcel			continue;
326218075Smarcel		if (node != 0 || p->dev == dev)
327209298Snwhitehorn			break;
328209298Snwhitehorn	}
329218075Smarcel	p = &piclist[idx];
330218075Smarcel
331218075Smarcel	p->dev = dev;
332218075Smarcel	p->node = node;
333218075Smarcel	p->irqs = irqs;
334218075Smarcel	p->ipis = ipis;
335218075Smarcel	if (idx == npics) {
336218075Smarcel#ifdef DEV_ISA
337218075Smarcel		p->base = (atpic) ? 0 : nirqs;
338218075Smarcel#else
339218075Smarcel		p->base = nirqs;
340218075Smarcel#endif
341218075Smarcel		irq = p->base + irqs + ipis;
342218075Smarcel		nirqs = MAX(nirqs, irq);
343209298Snwhitehorn		npics++;
344218075Smarcel	}
345209298Snwhitehorn
346209298Snwhitehorn	mtx_unlock(&intr_table_lock);
34799651Sbenno}
34899651Sbenno
349218075Smarcelu_int
350218075Smarcelpowerpc_get_irq(uint32_t node, u_int pin)
351191450Smarcel{
352218075Smarcel	int idx;
353191450Smarcel
354218075Smarcel	if (node == 0)
355218075Smarcel		return (pin);
356218075Smarcel
357209298Snwhitehorn	mtx_lock(&intr_table_lock);
358218075Smarcel	for (idx = 0; idx < npics; idx++) {
359218075Smarcel		if (piclist[idx].node == node) {
360209298Snwhitehorn			mtx_unlock(&intr_table_lock);
361218075Smarcel			return (piclist[idx].base + pin);
362209298Snwhitehorn		}
363209298Snwhitehorn	}
364218075Smarcel
365218075Smarcel	/*
366218075Smarcel	 * XXX we should never encounter an unregistered PIC, but that
367218075Smarcel	 * can only be done when we properly support bus enumeration
368218075Smarcel	 * using multiple passes. Until then, fake an entry and give it
369218075Smarcel	 * some adhoc maximum number of IRQs and IPIs.
370218075Smarcel	 */
371218075Smarcel	piclist[idx].dev = NULL;
372218075Smarcel	piclist[idx].node = node;
373218075Smarcel	piclist[idx].irqs = 124;
374218075Smarcel	piclist[idx].ipis = 4;
375218075Smarcel	piclist[idx].base = nirqs;
376218075Smarcel	nirqs += 128;
377209298Snwhitehorn	npics++;
378209298Snwhitehorn
379209298Snwhitehorn	mtx_unlock(&intr_table_lock);
380209298Snwhitehorn
381218075Smarcel	return (piclist[idx].base + pin);
382191450Smarcel}
383191450Smarcel
38499651Sbennoint
385171805Smarcelpowerpc_enable_intr(void)
38699651Sbenno{
387171805Smarcel	struct powerpc_intr *i;
388191450Smarcel	int error, vector;
389209298Snwhitehorn#ifdef SMP
390209298Snwhitehorn	int n;
391209298Snwhitehorn#endif
392171805Smarcel
393209298Snwhitehorn	if (npics == 0)
394178628Smarcel		panic("no PIC detected\n");
395178628Smarcel
396218075Smarcel	if (root_pic == NULL)
397218075Smarcel		root_pic = piclist[0].dev;
398218075Smarcel
399178628Smarcel#ifdef SMP
400178628Smarcel	/* Install an IPI handler. */
401221738Snwhitehorn	if (mp_ncpus > 1) {
402221738Snwhitehorn		for (n = 0; n < npics; n++) {
403221738Snwhitehorn			if (piclist[n].dev != root_pic)
404221738Snwhitehorn				continue;
405209298Snwhitehorn
406221738Snwhitehorn			KASSERT(piclist[n].ipis != 0,
407221738Snwhitehorn			    ("%s: SMP root PIC does not supply any IPIs",
408221738Snwhitehorn			    __func__));
409221738Snwhitehorn			error = powerpc_setup_intr("IPI",
410221738Snwhitehorn			    MAP_IRQ(piclist[n].node, piclist[n].irqs),
411221738Snwhitehorn			    powerpc_ipi_handler, NULL, NULL,
412221738Snwhitehorn			    INTR_TYPE_MISC | INTR_EXCL, &ipi_cookie);
413221738Snwhitehorn			if (error) {
414221738Snwhitehorn				printf("unable to setup IPI handler\n");
415221738Snwhitehorn				return (error);
416221738Snwhitehorn			}
417209298Snwhitehorn		}
418178628Smarcel	}
419178628Smarcel#endif
420178628Smarcel
421171805Smarcel	for (vector = 0; vector < nvectors; vector++) {
422171805Smarcel		i = powerpc_intrs[vector];
423171805Smarcel		if (i == NULL)
424171805Smarcel			continue;
425171805Smarcel
426191450Smarcel		error = powerpc_map_irq(i);
427191450Smarcel		if (error)
428191450Smarcel			continue;
429191450Smarcel
430176918Smarcel		if (i->trig != INTR_TRIGGER_CONFORM ||
431176918Smarcel		    i->pol != INTR_POLARITY_CONFORM)
432191450Smarcel			PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
433176918Smarcel
434176918Smarcel		if (i->event != NULL)
435191450Smarcel			PIC_ENABLE(i->pic, i->intline, vector);
436171805Smarcel	}
437171805Smarcel
438171805Smarcel	return (0);
439171805Smarcel}
440171805Smarcel
441171805Smarcelint
442209298Snwhitehornpowerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter,
443171805Smarcel    driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep)
444171805Smarcel{
445171805Smarcel	struct powerpc_intr *i;
446187691Snwhitehorn	int error, enable = 0;
44799651Sbenno
448176918Smarcel	i = intr_lookup(irq);
449176918Smarcel	if (i == NULL)
450176918Smarcel		return (ENOMEM);
451164987Smarcel
452176918Smarcel	if (i->event == NULL) {
453191450Smarcel		error = intr_event_create(&i->event, (void *)i, 0, irq,
454209724Snwhitehorn		    powerpc_intr_pre_ithread, powerpc_intr_post_ithread,
455209724Snwhitehorn		    powerpc_intr_eoi, powerpc_assign_intr_cpu, "irq%u:", irq);
456176918Smarcel		if (error)
45799651Sbenno			return (error);
45899651Sbenno
459187691Snwhitehorn		enable = 1;
46099651Sbenno	}
46199651Sbenno
462166901Spiso	error = intr_event_add_handler(i->event, name, filter, handler, arg,
463151658Sjhb	    intr_priority(flags), flags, cookiep);
464191307Sraj
465191307Sraj	mtx_lock(&intr_table_lock);
466212453Smav	intrcnt_setname(i->event->ie_fullname, i->cntindex);
467191307Sraj	mtx_unlock(&intr_table_lock);
468187691Snwhitehorn
469191450Smarcel	if (!cold) {
470191450Smarcel		error = powerpc_map_irq(i);
471208835Snwhitehorn
472208835Snwhitehorn		if (!error && (i->trig != INTR_TRIGGER_CONFORM ||
473208835Snwhitehorn		    i->pol != INTR_POLARITY_CONFORM))
474208835Snwhitehorn			PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
475208835Snwhitehorn
476209486Snwhitehorn		if (!error && i->pic == root_pic)
477209486Snwhitehorn			PIC_BIND(i->pic, i->intline, i->cpu);
478209486Snwhitehorn
479191450Smarcel		if (!error && enable)
480191450Smarcel			PIC_ENABLE(i->pic, i->intline, i->vector);
481191450Smarcel	}
482164987Smarcel	return (error);
48399651Sbenno}
48499651Sbenno
48599651Sbennoint
486171805Smarcelpowerpc_teardown_intr(void *cookie)
48799651Sbenno{
48899651Sbenno
489164987Smarcel	return (intr_event_remove_handler(cookie));
49099651Sbenno}
49199651Sbenno
492209486Snwhitehorn#ifdef SMP
493176918Smarcelint
494209486Snwhitehornpowerpc_bind_intr(u_int irq, u_char cpu)
495209486Snwhitehorn{
496209486Snwhitehorn	struct powerpc_intr *i;
497209486Snwhitehorn
498209486Snwhitehorn	i = intr_lookup(irq);
499209486Snwhitehorn	if (i == NULL)
500209486Snwhitehorn		return (ENOMEM);
501209486Snwhitehorn
502209486Snwhitehorn	return (intr_event_bind(i->event, cpu));
503209486Snwhitehorn}
504209486Snwhitehorn#endif
505209486Snwhitehorn
506209486Snwhitehornint
507176918Smarcelpowerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol)
508176918Smarcel{
509176918Smarcel	struct powerpc_intr *i;
510176918Smarcel
511176918Smarcel	i = intr_lookup(irq);
512176918Smarcel	if (i == NULL)
513176918Smarcel		return (ENOMEM);
514176918Smarcel
515176918Smarcel	i->trig = trig;
516176918Smarcel	i->pol = pol;
517176918Smarcel
518208835Snwhitehorn	if (!cold && i->pic != NULL)
519191450Smarcel		PIC_CONFIG(i->pic, i->intline, trig, pol);
520176918Smarcel
521176918Smarcel	return (0);
522176918Smarcel}
523176918Smarcel
52499651Sbennovoid
525171805Smarcelpowerpc_dispatch_intr(u_int vector, struct trapframe *tf)
52699651Sbenno{
527171805Smarcel	struct powerpc_intr *i;
528164987Smarcel	struct intr_event *ie;
52999651Sbenno
530171805Smarcel	i = powerpc_intrs[vector];
531164987Smarcel	if (i == NULL)
532164987Smarcel		goto stray;
53399651Sbenno
534171805Smarcel	(*i->cntp)++;
53599651Sbenno
536164987Smarcel	ie = i->event;
537164987Smarcel	KASSERT(ie != NULL, ("%s: interrupt without an event", __func__));
53899651Sbenno
539171805Smarcel	if (intr_event_handle(ie, tf) != 0) {
540164987Smarcel		goto stray;
54199651Sbenno	}
542164987Smarcel	return;
54399651Sbenno
544164987Smarcelstray:
545171805Smarcel	stray_count++;
546171805Smarcel	if (stray_count <= MAX_STRAY_LOG) {
547177940Sjhb		printf("stray irq %d\n", i ? i->irq : -1);
548171805Smarcel		if (stray_count >= MAX_STRAY_LOG) {
549164987Smarcel			printf("got %d stray interrupts, not logging anymore\n",
550171805Smarcel			    MAX_STRAY_LOG);
551164987Smarcel		}
552164987Smarcel	}
553171805Smarcel	if (i != NULL)
554191450Smarcel		PIC_MASK(i->pic, i->intline);
55599651Sbenno}
556