xref: /netbsd-src/sys/arch/arm/arm32/intr.c (revision 7fa608457b817eca6e0977b37f758ae064f3c99c)
1 /*	$NetBSD: intr.c,v 1.24 2007/10/17 19:53:31 garbled Exp $	*/
2 
3 /*
4  * Copyright (c) 1994-1998 Mark Brinicombe.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by Mark Brinicombe
18  *	for the NetBSD Project.
19  * 4. The name of the company nor the name of the author may be used to
20  *    endorse or promote products derived from this software without specific
21  *    prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * Soft interrupt and other generic interrupt functions.
36  */
37 
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.24 2007/10/17 19:53:31 garbled Exp $");
40 
41 #include "opt_irqstats.h"
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/syslog.h>
46 #include <sys/malloc.h>
47 #include <sys/conf.h>
48 
49 #include <uvm/uvm_extern.h>
50 
51 #include <machine/atomic.h>
52 #include <machine/intr.h>
53 #include <machine/cpu.h>
54 
55 #include <net/netisr.h>
56 
57 #include <arm/arm32/machdep.h>
58 
59 extern int current_spl_level;
60 
61 /* Generate soft interrupt counts if IRQSTATS is defined */
62 /* Prototypes */
63 static void clearsoftintr(u_int);
64 
65 static u_int soft_interrupts = 0;
66 static u_int spl_smasks[_SPL_LEVELS];
67 
68 /* Eventually these will become macros */
69 
70 #define	SI_SOFTMASK(si)	(1U << (si))
71 
72 static inline void
73 clearsoftintr(u_int intrmask)
74 {
75 	atomic_clear_bit(&soft_interrupts, intrmask);
76 }
77 
78 void
79 _setsoftintr(int si)
80 {
81 	atomic_set_bit(&soft_interrupts, SI_SOFTMASK(si));
82 }
83 
84 /* Handle software interrupts */
85 
86 void
87 dosoftints(void)
88 {
89 	u_int softints;
90 	int s;
91 
92 	softints = soft_interrupts & spl_smasks[current_spl_level];
93 	if (softints == 0) return;
94 
95 	/*
96 	 * Serial software interrupts
97 	 */
98 	if (softints & SI_SOFTMASK(SI_SOFTSERIAL)) {
99 		s = splsoftserial();
100 		clearsoftintr(SI_SOFTMASK(SI_SOFTSERIAL));
101 		softintr_dispatch(SI_SOFTSERIAL);
102 		(void)splx(s);
103 	}
104 
105 	/*
106 	 * Network software interrupts
107 	 */
108 	if (softints & SI_SOFTMASK(SI_SOFTNET)) {
109 		s = splsoftnet();
110 		clearsoftintr(SI_SOFTMASK(SI_SOFTNET));
111 		softintr_dispatch(SI_SOFTNET);
112 		(void)splx(s);
113 	}
114 
115 	/*
116 	 * Software clock interrupts
117 	 */
118 	if (softints & SI_SOFTMASK(SI_SOFTCLOCK)) {
119 		s = splsoftclock();
120 		clearsoftintr(SI_SOFTMASK(SI_SOFTCLOCK));
121 		softintr_dispatch(SI_SOFTCLOCK);
122 		(void)splx(s);
123 	}
124 
125 	/*
126 	 * Misc software interrupts
127 	 */
128 	if (softints & SI_SOFTMASK(SI_SOFT)) {
129 		s = splsoft();
130 		clearsoftintr(SI_SOFTMASK(SI_SOFT));
131 		softintr_dispatch(SI_SOFT);
132 		(void)splx(s);
133 	}
134 }
135 
136 int current_spl_level = _SPL_SERIAL;
137 u_int spl_masks[_SPL_LEVELS + 1];
138 int safepri = _SPL_0;
139 
140 extern u_int irqmasks[];
141 
142 void
143 set_spl_masks(void)
144 {
145 	int loop;
146 
147 	for (loop = 0; loop < _SPL_LEVELS; ++loop) {
148 		spl_masks[loop] = 0xffffffff;
149 		spl_smasks[loop] = 0;
150 	}
151 
152 	spl_masks[_SPL_BIO]        = irqmasks[IPL_BIO];
153 	spl_masks[_SPL_NET]        = irqmasks[IPL_NET];
154 	spl_masks[_SPL_SOFTSERIAL] = irqmasks[IPL_TTY];
155 	spl_masks[_SPL_TTY]        = irqmasks[IPL_TTY];
156 	spl_masks[_SPL_VM]         = irqmasks[IPL_VM];
157 	spl_masks[_SPL_AUDIO]      = irqmasks[IPL_AUDIO];
158 	spl_masks[_SPL_CLOCK]      = irqmasks[IPL_CLOCK];
159 #ifdef IPL_STATCLOCK
160 	spl_masks[_SPL_STATCLOCK]  = irqmasks[IPL_STATCLOCK];
161 #else
162 	spl_masks[_SPL_STATCLOCK]  = irqmasks[IPL_CLOCK];
163 #endif
164 	spl_masks[_SPL_HIGH]       = irqmasks[IPL_HIGH];
165 	spl_masks[_SPL_SERIAL]     = irqmasks[IPL_SERIAL];
166 	spl_masks[_SPL_LEVELS]     = 0;
167 
168 	spl_smasks[_SPL_0] = 0xffffffff;
169 	for (loop = 0; loop < _SPL_SOFTSERIAL; ++loop)
170 		spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTSERIAL);
171 	for (loop = 0; loop < _SPL_SOFTNET; ++loop)
172 		spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTNET);
173 	for (loop = 0; loop < _SPL_SOFTCLOCK; ++loop)
174 		spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTCLOCK);
175 	for (loop = 0; loop < _SPL_SOFT; ++loop)
176 		spl_smasks[loop] |= SI_SOFTMASK(SI_SOFT);
177 }
178 
179 static const int ipl_to_spl_map[] = {
180 	[IPL_NONE] = 1 + _SPL_0,
181 #ifdef IPL_SOFT
182 	[IPL_SOFT] = 1 + _SPL_SOFT,
183 #endif /* IPL_SOFTCLOCK */
184 #if defined(IPL_SOFTCLOCK)
185 	[IPL_SOFTCLOCK] = 1 + _SPL_SOFTCLOCK,
186 #endif /* defined(IPL_SOFTCLOCK) */
187 #if defined(IPL_SOFTNET)
188 	[IPL_SOFTNET] = 1 + _SPL_SOFTNET,
189 #endif /* defined(IPL_SOFTNET) */
190 	[IPL_BIO] = 1 + _SPL_BIO,
191 	[IPL_NET] = 1 + _SPL_NET,
192 #if defined(IPL_SOFTSERIAL)
193 	[IPL_SOFTSERIAL] = 1 + _SPL_SOFTSERIAL,
194 #endif /* defined(IPL_SOFTSERIAL) */
195 	[IPL_TTY] = 1 + _SPL_TTY,
196 	[IPL_VM] = 1 + _SPL_VM,
197 	[IPL_AUDIO] = 1 + _SPL_AUDIO,
198 	[IPL_CLOCK] = 1 + _SPL_CLOCK,
199 	[IPL_STATCLOCK] = 1 + _SPL_STATCLOCK,
200 	[IPL_HIGH] = 1 + _SPL_HIGH,
201 	[IPL_SERIAL] = 1 + _SPL_SERIAL,
202 };
203 
204 int
205 ipl_to_spl(ipl_t ipl)
206 {
207 	int spl;
208 
209 	KASSERT(ipl < __arraycount(ipl_to_spl_map));
210 	KASSERT(ipl_to_spl_map[ipl]);
211 
212 	spl = ipl_to_spl_map[ipl] - 1;
213 	KASSERT(spl < 0x100);
214 
215 	return spl;
216 }
217 
218 #ifdef DIAGNOSTIC
219 void
220 dump_spl_masks(void)
221 {
222 	int loop;
223 
224 	for (loop = 0; loop < _SPL_LEVELS; ++loop) {
225 		printf("spl_masks[%d]=%08x splsmask[%d]=%08x\n", loop,
226 		    spl_masks[loop], loop, spl_smasks[loop]);
227 	}
228 }
229 #endif
230 
231 /* End of intr.c */
232