intr.c revision 166901
1129198Scognet/*	$NetBSD: intr.c,v 1.12 2003/07/15 00:24:41 lukem Exp $	*/
2129198Scognet
3139735Simp/*-
4129198Scognet * Copyright (c) 2004 Olivier Houchard.
5129198Scognet * Copyright (c) 1994-1998 Mark Brinicombe.
6129198Scognet * All rights reserved.
7129198Scognet *
8129198Scognet * Redistribution and use in source and binary forms, with or without
9129198Scognet * modification, are permitted provided that the following conditions
10129198Scognet * are met:
11129198Scognet * 1. Redistributions of source code must retain the above copyright
12129198Scognet *    notice, this list of conditions and the following disclaimer.
13129198Scognet * 2. Redistributions in binary form must reproduce the above copyright
14129198Scognet *    notice, this list of conditions and the following disclaimer in the
15129198Scognet *    documentation and/or other materials provided with the distribution.
16129198Scognet * 3. All advertising materials mentioning features or use of this software
17129198Scognet *    must display the following acknowledgement:
18129198Scognet *	This product includes software developed by Mark Brinicombe
19129198Scognet *	for the NetBSD Project.
20129198Scognet * 4. The name of the company nor the name of the author may be used to
21129198Scognet *    endorse or promote products derived from this software without specific
22129198Scognet *    prior written permission.
23129198Scognet *
24129198Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25129198Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26129198Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27129198Scognet * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34129198Scognet * SUCH DAMAGE.
35129198Scognet *
36129198Scognet * Soft interrupt and other generic interrupt functions.
37129198Scognet */
38129198Scognet
39129198Scognet#include <sys/cdefs.h>
40129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/intr.c 166901 2007-02-23 12:19:07Z piso $");
41129198Scognet#include <sys/param.h>
42129198Scognet#include <sys/systm.h>
43129198Scognet#include <sys/syslog.h>
44129198Scognet#include <sys/malloc.h>
45135650Scognet#include <sys/proc.h>
46129198Scognet#include <sys/bus.h>
47129198Scognet#include <sys/interrupt.h>
48129198Scognet#include <sys/conf.h>
49129198Scognet#include <machine/atomic.h>
50129198Scognet#include <machine/intr.h>
51129198Scognet#include <machine/cpu.h>
52129198Scognet
53151658Sjhbstatic struct intr_event *intr_events[NIRQ];
54137629Scognetstatic int intrcnt_tab[NIRQ];
55137629Scognetstatic int intrcnt_index = 0;
56137629Scognetstatic int last_printed = 0;
57129198Scognet
58153666Sjhbvoid	arm_handler_execute(struct trapframe *, int);
59135650Scognet
60137629Scognetvoid
61166901Spisoarm_setup_irqhandler(const char *name, driver_filter_t *filt,
62166901Spiso    void (*hand)(void*), void *arg, int irq, int flags, void **cookiep)
63129198Scognet{
64151658Sjhb	struct intr_event *event;
65129198Scognet	int error;
66129198Scognet
67129198Scognet	if (irq < 0 || irq >= NIRQ)
68129198Scognet		return;
69151658Sjhb	event = intr_events[irq];
70151658Sjhb	if (event == NULL) {
71151658Sjhb		error = intr_event_create(&event, (void *)irq, 0,
72151658Sjhb		    (void (*)(void *))arm_unmask_irq, "intr%d:", irq);
73129198Scognet		if (error)
74129198Scognet			return;
75151658Sjhb		intr_events[irq] = event;
76137629Scognet		last_printed +=
77137629Scognet		    snprintf(intrnames + last_printed,
78137629Scognet		    MAXCOMLEN + 1,
79137629Scognet		    "irq%d: %s", irq, name);
80137629Scognet		last_printed++;
81137629Scognet		intrcnt_tab[irq] = intrcnt_index;
82137629Scognet		intrcnt_index++;
83137629Scognet
84129198Scognet	}
85166901Spiso	intr_event_add_handler(event, name, filt, hand, arg,
86151658Sjhb	    intr_priority(flags), flags, cookiep);
87129198Scognet}
88129198Scognet
89147166Scognetint
90147166Scognetarm_remove_irqhandler(void *cookie)
91147166Scognet{
92151658Sjhb	return (intr_event_remove_handler(cookie));
93147166Scognet}
94147166Scognet
95129198Scognetvoid dosoftints(void);
96129198Scognetvoid
97129198Scognetdosoftints(void)
98129198Scognet{
99129198Scognet}
100129198Scognet
101129198Scognetvoid
102153666Sjhbarm_handler_execute(struct trapframe *frame, int irqnb)
103129198Scognet{
104151658Sjhb	struct intr_event *event;
105151658Sjhb	struct intr_handler *ih;
106135650Scognet	struct thread *td = curthread;
107151658Sjhb	int i, thread;
108129198Scognet
109164087Scognet	PCPU_LAZY_INC(cnt.v_intr);
110135650Scognet	td->td_intr_nesting_level++;
111147166Scognet	while ((i = arm_get_next_irq()) != -1) {
112150869Scognet		arm_mask_irq(i);
113137629Scognet		intrcnt[intrcnt_tab[i]]++;
114151658Sjhb		event = intr_events[i];
115151658Sjhb		if (!event || TAILQ_EMPTY(&event->ie_handlers))
116135650Scognet			continue;
117151658Sjhb
118151658Sjhb		/* Execute fast handlers. */
119151658Sjhb		thread = 0;
120151658Sjhb		TAILQ_FOREACH(ih, &event->ie_handlers, ih_next) {
121166901Spiso			if (ih->ih_filter == NULL)
122151658Sjhb				thread = 1;
123151658Sjhb			else
124166901Spiso				ih->ih_filter(ih->ih_argument ?
125135650Scognet				    ih->ih_argument : frame);
126151658Sjhb		}
127151658Sjhb
128151658Sjhb		/* Schedule thread if needed. */
129151658Sjhb		if (thread)
130151658Sjhb			intr_event_schedule_thread(event);
131151658Sjhb		else
132150869Scognet			arm_unmask_irq(i);
133135650Scognet	}
134135650Scognet	td->td_intr_nesting_level--;
135129198Scognet}
136