| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: m68k_intr.c,v 1.3 2024/01/15 00:37:08 thorpej Exp $ */ | | 1 | /* $NetBSD: m68k_intr.c,v 1.4 2024/01/15 02:13:16 thorpej Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1996, 2023, 2024 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1996, 2023, 2024 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | | 8 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -24,27 +24,27 @@ | | | @@ -24,27 +24,27 @@ |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * Common interrupt handling for m68k platforms. | | 33 | * Common interrupt handling for m68k platforms. |
34 | */ | | 34 | */ |
35 | | | 35 | |
36 | #include <sys/cdefs.h> | | 36 | #include <sys/cdefs.h> |
37 | __KERNEL_RCSID(0, "$NetBSD: m68k_intr.c,v 1.3 2024/01/15 00:37:08 thorpej Exp $"); | | 37 | __KERNEL_RCSID(0, "$NetBSD: m68k_intr.c,v 1.4 2024/01/15 02:13:16 thorpej Exp $"); |
38 | | | 38 | |
39 | #define _M68K_INTR_PRIVATE | | 39 | #define _M68K_INTR_PRIVATE |
40 | | | 40 | |
41 | #include <sys/param.h> | | 41 | #include <sys/param.h> |
42 | #include <sys/systm.h> | | 42 | #include <sys/systm.h> |
43 | #include <sys/kmem.h> | | 43 | #include <sys/kmem.h> |
44 | #include <sys/vmmeter.h> | | 44 | #include <sys/vmmeter.h> |
45 | #include <sys/device.h> | | 45 | #include <sys/device.h> |
46 | #include <sys/cpu.h> | | 46 | #include <sys/cpu.h> |
47 | #include <sys/bus.h> | | 47 | #include <sys/bus.h> |
48 | #include <sys/once.h> | | 48 | #include <sys/once.h> |
49 | #include <sys/intr.h> | | 49 | #include <sys/intr.h> |
50 | | | 50 | |
| @@ -198,27 +198,27 @@ m68k_intr_init(const struct m68k_ih_allo | | | @@ -198,27 +198,27 @@ m68k_intr_init(const struct m68k_ih_allo |
198 | for (i = 0; i < NAUTOVECTORS; i++) { | | 198 | for (i = 0; i < NAUTOVECTORS; i++) { |
199 | LIST_INIT(&m68k_intrhands_autovec[i]); | | 199 | LIST_INIT(&m68k_intrhands_autovec[i]); |
200 | } | | 200 | } |
201 | } | | 201 | } |
202 | | | 202 | |
203 | /* | | 203 | /* |
204 | * m68k_intr_establish -- | | 204 | * m68k_intr_establish -- |
205 | * Establish an interrupt handler at the specified vector. | | 205 | * Establish an interrupt handler at the specified vector. |
206 | * XXX We don't do anything with isrpri yet. | | 206 | * XXX We don't do anything with isrpri yet. |
207 | * XXX We don't do anything with the flags yet. | | 207 | * XXX We don't do anything with the flags yet. |
208 | */ | | 208 | */ |
209 | void * | | 209 | void * |
210 | m68k_intr_establish(int (*func)(void *), void *arg, struct evcnt *ev, | | 210 | m68k_intr_establish(int (*func)(void *), void *arg, struct evcnt *ev, |
211 | int vec, int ipl, int isrpri __unused, int flags __unused) | | 211 | int vec, int ipl, int isrpri, int flags __unused) |
212 | { | | 212 | { |
213 | struct m68k_intrhand *ih; | | 213 | struct m68k_intrhand *ih; |
214 | int s; | | 214 | int s; |
215 | | | 215 | |
216 | /* | | 216 | /* |
217 | * If a platform doesn't want special behavior, we don't | | 217 | * If a platform doesn't want special behavior, we don't |
218 | * require them to call m68k_intr_init(); we just handle | | 218 | * require them to call m68k_intr_init(); we just handle |
219 | * it here. | | 219 | * it here. |
220 | * | | 220 | * |
221 | * XXX m68k_intr_init() might be called really early, so | | 221 | * XXX m68k_intr_init() might be called really early, so |
222 | * XXX can't use a once control. | | 222 | * XXX can't use a once control. |
223 | */ | | 223 | */ |
224 | if (__predict_false(ih_allocfuncs == NULL)) { | | 224 | if (__predict_false(ih_allocfuncs == NULL)) { |
| @@ -232,46 +232,71 @@ m68k_intr_establish(int (*func)(void *), | | | @@ -232,46 +232,71 @@ m68k_intr_establish(int (*func)(void *), |
232 | | | 232 | |
233 | #ifdef __HAVE_M68K_INTR_VECTORED | | 233 | #ifdef __HAVE_M68K_INTR_VECTORED |
234 | KASSERT(vec >= 0); | | 234 | KASSERT(vec >= 0); |
235 | KASSERT(vec < NVECTORS); | | 235 | KASSERT(vec < NVECTORS); |
236 | #else | | 236 | #else |
237 | KASSERT(vec == 0); | | 237 | KASSERT(vec == 0); |
238 | #endif /* __HAVE_M68K_INTR_VECTORED */ | | 238 | #endif /* __HAVE_M68K_INTR_VECTORED */ |
239 | | | 239 | |
240 | ih = m68k_ih_alloc(); | | 240 | ih = m68k_ih_alloc(); |
241 | ih->ih_func = func; | | 241 | ih->ih_func = func; |
242 | ih->ih_arg = arg; | | 242 | ih->ih_arg = arg; |
243 | ih->ih_vec = vec; | | 243 | ih->ih_vec = vec; |
244 | ih->ih_ipl = ipl; | | 244 | ih->ih_ipl = ipl; |
| | | 245 | ih->ih_isrpri = isrpri; |
245 | if ((ih->ih_evcnt = ev) == NULL) { | | 246 | if ((ih->ih_evcnt = ev) == NULL) { |
246 | ih->ih_evcnt = &bitbucket; | | 247 | ih->ih_evcnt = &bitbucket; |
247 | } | | 248 | } |
248 | | | 249 | |
249 | #ifdef __HAVE_M68K_INTR_VECTORED | | 250 | #ifdef __HAVE_M68K_INTR_VECTORED |
250 | if (vec != 0) { | | 251 | if (vec != 0) { |
251 | if (vec_get_entry(vec) != INTR_FREEVEC) { | | 252 | if (vec_get_entry(vec) != INTR_FREEVEC) { |
252 | m68k_ih_free(ih); | | 253 | m68k_ih_free(ih); |
253 | return NULL; | | 254 | return NULL; |
254 | } | | 255 | } |
255 | if (! m68k_intrvec_add(ih)) { | | 256 | if (! m68k_intrvec_add(ih)) { |
256 | m68k_ih_free(ih); | | 257 | m68k_ih_free(ih); |
257 | return NULL; | | 258 | return NULL; |
258 | } | | 259 | } |
259 | return ih; | | 260 | return ih; |
260 | } | | 261 | } |
261 | #endif | | 262 | #endif |
262 | | | 263 | |
| | | 264 | /* |
| | | 265 | * Some devices are particularly sensitive to interrupt |
| | | 266 | * handling latency. Unbuffered serial ports, for example, |
| | | 267 | * can lose data if their interrupts aren't handled with |
| | | 268 | * reasonable speed. For this reason, we sort interrupt |
| | | 269 | * handlers by an abstract "ISR" priority, inserting higher- |
| | | 270 | * priority interrupts before lower-priority interrupts. |
| | | 271 | */ |
| | | 272 | struct m68k_intrhand_list * const list = &m68k_intrhands_autovec[ipl]; |
| | | 273 | struct m68k_intrhand *curih; |
| | | 274 | |
263 | s = splhigh(); | | 275 | s = splhigh(); |
264 | LIST_INSERT_HEAD(&m68k_intrhands_autovec[ipl], ih, ih_link); | | 276 | if (LIST_EMPTY(list)) { |
| | | 277 | LIST_INSERT_HEAD(list, ih, ih_link); |
| | | 278 | goto done; |
| | | 279 | } |
| | | 280 | for (curih = LIST_FIRST(list); |
| | | 281 | LIST_NEXT(curih, ih_link) != NULL; |
| | | 282 | curih = LIST_NEXT(curih, ih_link)) { |
| | | 283 | if (ih->ih_isrpri > curih->ih_isrpri) { |
| | | 284 | LIST_INSERT_BEFORE(curih, ih, ih_link); |
| | | 285 | goto done; |
| | | 286 | } |
| | | 287 | } |
| | | 288 | LIST_INSERT_AFTER(curih, ih, ih_link); |
| | | 289 | done: |
265 | splx(s); | | 290 | splx(s); |
266 | | | 291 | |
267 | return ih; | | 292 | return ih; |
268 | } | | 293 | } |
269 | | | 294 | |
270 | /* | | 295 | /* |
271 | * m68k_intr_disestablish -- | | 296 | * m68k_intr_disestablish -- |
272 | * Remove an interrupt handler. Returns true if the handler | | 297 | * Remove an interrupt handler. Returns true if the handler |
273 | * list for this vector is now empty. | | 298 | * list for this vector is now empty. |
274 | */ | | 299 | */ |
275 | bool | | 300 | bool |
276 | m68k_intr_disestablish(void *v) | | 301 | m68k_intr_disestablish(void *v) |
277 | { | | 302 | { |