1 1.36 thorpej /* $NetBSD: iq80310_intr.c,v 1.36 2020/11/21 15:30:07 thorpej Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /* 4 1.8 thorpej * Copyright (c) 2001, 2002 Wasabi Systems, Inc. 5 1.1 thorpej * All rights reserved. 6 1.1 thorpej * 7 1.1 thorpej * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 1.1 thorpej * 9 1.1 thorpej * Redistribution and use in source and binary forms, with or without 10 1.1 thorpej * modification, are permitted provided that the following conditions 11 1.1 thorpej * are met: 12 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 13 1.1 thorpej * notice, this list of conditions and the following disclaimer. 14 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 16 1.1 thorpej * documentation and/or other materials provided with the distribution. 17 1.1 thorpej * 3. All advertising materials mentioning features or use of this software 18 1.1 thorpej * must display the following acknowledgement: 19 1.1 thorpej * This product includes software developed for the NetBSD Project by 20 1.1 thorpej * Wasabi Systems, Inc. 21 1.1 thorpej * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 1.1 thorpej * or promote products derived from this software without specific prior 23 1.1 thorpej * written permission. 24 1.1 thorpej * 25 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 1.1 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 1.1 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 1.1 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 1.1 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 1.1 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 1.1 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 1.1 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 1.1 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 1.1 thorpej * POSSIBILITY OF SUCH DAMAGE. 36 1.1 thorpej */ 37 1.20 lukem 38 1.20 lukem #include <sys/cdefs.h> 39 1.36 thorpej __KERNEL_RCSID(0, "$NetBSD: iq80310_intr.c,v 1.36 2020/11/21 15:30:07 thorpej Exp $"); 40 1.1 thorpej 41 1.18 thorpej #ifndef EVBARM_SPL_NOINLINE 42 1.18 thorpej #define EVBARM_SPL_NOINLINE 43 1.18 thorpej #endif 44 1.18 thorpej 45 1.1 thorpej /* 46 1.1 thorpej * Interrupt support for the Intel IQ80310. 47 1.1 thorpej */ 48 1.1 thorpej 49 1.1 thorpej #include <sys/param.h> 50 1.1 thorpej #include <sys/systm.h> 51 1.36 thorpej #include <sys/kmem.h> 52 1.1 thorpej 53 1.29 dyoung #include <sys/bus.h> 54 1.1 thorpej #include <machine/intr.h> 55 1.8 thorpej 56 1.5 thorpej #include <arm/cpufunc.h> 57 1.1 thorpej 58 1.6 thorpej #include <arm/xscale/i80200reg.h> 59 1.8 thorpej #include <arm/xscale/i80200var.h> 60 1.6 thorpej 61 1.1 thorpej #include <evbarm/iq80310/iq80310reg.h> 62 1.1 thorpej #include <evbarm/iq80310/iq80310var.h> 63 1.1 thorpej #include <evbarm/iq80310/obiovar.h> 64 1.1 thorpej 65 1.8 thorpej /* Interrupt handler queues. */ 66 1.8 thorpej struct intrq intrq[NIRQ]; 67 1.1 thorpej 68 1.8 thorpej /* Interrupts to mask at each level. */ 69 1.17 briggs int iq80310_imask[NIPL]; 70 1.1 thorpej 71 1.8 thorpej /* Interrupts pending. */ 72 1.23 perry volatile int iq80310_ipending; 73 1.1 thorpej 74 1.8 thorpej /* Software copy of the IRQs we have enabled. */ 75 1.8 thorpej uint32_t intr_enabled; 76 1.1 thorpej 77 1.28 jakllsch #ifdef __HAVE_FAST_SOFTINTS 78 1.8 thorpej /* 79 1.8 thorpej * Map a software interrupt queue index (at the top of the word, and 80 1.8 thorpej * highest priority softintr is encountered first in an ffs()). 81 1.8 thorpej */ 82 1.8 thorpej #define SI_TO_IRQBIT(si) (1U << (31 - (si))) 83 1.6 thorpej 84 1.8 thorpej /* 85 1.8 thorpej * Map a software interrupt queue to an interrupt priority level. 86 1.8 thorpej */ 87 1.8 thorpej static const int si_to_ipl[SI_NQUEUES] = { 88 1.8 thorpej IPL_SOFT, /* SI_SOFT */ 89 1.8 thorpej IPL_SOFTCLOCK, /* SI_SOFTCLOCK */ 90 1.8 thorpej IPL_SOFTNET, /* SI_SOFTNET */ 91 1.8 thorpej IPL_SOFTSERIAL, /* SI_SOFTSERIAL */ 92 1.8 thorpej }; 93 1.25 matt #endif 94 1.6 thorpej 95 1.30 skrll void iq80310_intr_dispatch(struct trapframe *frame); 96 1.1 thorpej 97 1.23 perry static inline uint32_t 98 1.1 thorpej iq80310_intstat_read(void) 99 1.1 thorpej { 100 1.1 thorpej uint32_t intstat; 101 1.1 thorpej 102 1.3 thorpej intstat = CPLD_READ(IQ80310_XINT3_STATUS) & 0x1f; 103 1.9 thorpej #if defined(IRQ_READ_XINT0) 104 1.9 thorpej if (IRQ_READ_XINT0) 105 1.3 thorpej intstat |= (CPLD_READ(IQ80310_XINT0_STATUS) & 0x7) << 5; 106 1.9 thorpej #endif 107 1.1 thorpej 108 1.8 thorpej /* XXX Why do we have to mask off? */ 109 1.8 thorpej return (intstat & intr_enabled); 110 1.8 thorpej } 111 1.8 thorpej 112 1.23 perry static inline void 113 1.8 thorpej iq80310_set_intrmask(void) 114 1.8 thorpej { 115 1.8 thorpej uint32_t disabled; 116 1.8 thorpej 117 1.8 thorpej intr_enabled |= IRQ_BITS_ALWAYS_ON; 118 1.8 thorpej 119 1.8 thorpej /* The XINT_MASK register sets a bit to *disable*. */ 120 1.8 thorpej disabled = (~intr_enabled) & IRQ_BITS; 121 1.8 thorpej 122 1.8 thorpej CPLD_WRITE(IQ80310_XINT_MASK, disabled & 0x1f); 123 1.8 thorpej } 124 1.8 thorpej 125 1.23 perry static inline void 126 1.8 thorpej iq80310_enable_irq(int irq) 127 1.8 thorpej { 128 1.8 thorpej 129 1.8 thorpej intr_enabled |= (1U << irq); 130 1.8 thorpej iq80310_set_intrmask(); 131 1.8 thorpej } 132 1.8 thorpej 133 1.23 perry static inline void 134 1.8 thorpej iq80310_disable_irq(int irq) 135 1.8 thorpej { 136 1.8 thorpej 137 1.8 thorpej intr_enabled &= ~(1U << irq); 138 1.8 thorpej iq80310_set_intrmask(); 139 1.8 thorpej } 140 1.8 thorpej 141 1.8 thorpej /* 142 1.8 thorpej * NOTE: This routine must be called with interrupts disabled in the CPSR. 143 1.8 thorpej */ 144 1.8 thorpej static void 145 1.8 thorpej iq80310_intr_calculate_masks(void) 146 1.8 thorpej { 147 1.8 thorpej struct intrq *iq; 148 1.8 thorpej struct intrhand *ih; 149 1.8 thorpej int irq, ipl; 150 1.8 thorpej 151 1.8 thorpej /* First, figure out which IPLs each IRQ has. */ 152 1.8 thorpej for (irq = 0; irq < NIRQ; irq++) { 153 1.8 thorpej int levels = 0; 154 1.8 thorpej iq = &intrq[irq]; 155 1.8 thorpej iq80310_disable_irq(irq); 156 1.8 thorpej for (ih = TAILQ_FIRST(&iq->iq_list); ih != NULL; 157 1.8 thorpej ih = TAILQ_NEXT(ih, ih_list)) 158 1.8 thorpej levels |= (1U << ih->ih_ipl); 159 1.8 thorpej iq->iq_levels = levels; 160 1.8 thorpej } 161 1.8 thorpej 162 1.8 thorpej /* Next, figure out which IRQs are used by each IPL. */ 163 1.8 thorpej for (ipl = 0; ipl < NIPL; ipl++) { 164 1.8 thorpej int irqs = 0; 165 1.8 thorpej for (irq = 0; irq < NIRQ; irq++) { 166 1.8 thorpej if (intrq[irq].iq_levels & (1U << ipl)) 167 1.8 thorpej irqs |= (1U << irq); 168 1.8 thorpej } 169 1.17 briggs iq80310_imask[ipl] = irqs; 170 1.8 thorpej } 171 1.8 thorpej 172 1.17 briggs iq80310_imask[IPL_NONE] = 0; 173 1.25 matt iq80310_imask[IPL_SOFTCLOCK] = 0; 174 1.25 matt iq80310_imask[IPL_SOFTNET] = 0; 175 1.25 matt iq80310_imask[IPL_SOFTSERIAL] = 0; 176 1.8 thorpej 177 1.8 thorpej /* 178 1.8 thorpej * splsoftnet() must also block splsoftclock(), since we don't 179 1.8 thorpej * want timer-driven network events to occur while we're 180 1.8 thorpej * processing incoming packets. 181 1.8 thorpej */ 182 1.17 briggs iq80310_imask[IPL_SOFTNET] |= iq80310_imask[IPL_SOFTCLOCK]; 183 1.8 thorpej 184 1.6 thorpej /* 185 1.24 wiz * Enforce a hierarchy that gives "slow" device (or devices with 186 1.8 thorpej * limited input buffer space/"real-time" requirements) a better 187 1.8 thorpej * chance at not dropping data. 188 1.6 thorpej */ 189 1.17 briggs iq80310_imask[IPL_BIO] |= iq80310_imask[IPL_SOFTNET]; 190 1.17 briggs iq80310_imask[IPL_NET] |= iq80310_imask[IPL_BIO]; 191 1.17 briggs iq80310_imask[IPL_SOFTSERIAL] |= iq80310_imask[IPL_NET]; 192 1.17 briggs iq80310_imask[IPL_TTY] |= iq80310_imask[IPL_SOFTSERIAL]; 193 1.7 thorpej 194 1.8 thorpej /* 195 1.8 thorpej * splvm() blocks all interrupts that use the kernel memory 196 1.8 thorpej * allocation facilities. 197 1.8 thorpej */ 198 1.19 thorpej iq80310_imask[IPL_VM] |= iq80310_imask[IPL_TTY]; 199 1.1 thorpej 200 1.8 thorpej /* 201 1.8 thorpej * Audio devices are not allowed to perform memory allocation 202 1.8 thorpej * in their interrupt routines, and they have fairly "real-time" 203 1.8 thorpej * requirements, so give them a high interrupt priority. 204 1.8 thorpej */ 205 1.19 thorpej iq80310_imask[IPL_AUDIO] |= iq80310_imask[IPL_VM]; 206 1.8 thorpej 207 1.8 thorpej /* 208 1.8 thorpej * splclock() must block anything that uses the scheduler. 209 1.8 thorpej */ 210 1.17 briggs iq80310_imask[IPL_CLOCK] |= iq80310_imask[IPL_AUDIO]; 211 1.1 thorpej 212 1.8 thorpej /* 213 1.8 thorpej * No separate statclock on the IQ80310. 214 1.8 thorpej */ 215 1.25 matt #ifdef IPL_STATCLOCK 216 1.17 briggs iq80310_imask[IPL_STATCLOCK] |= iq80310_imask[IPL_CLOCK]; 217 1.25 matt #endif 218 1.6 thorpej 219 1.1 thorpej /* 220 1.8 thorpej * splhigh() must block "everything". 221 1.1 thorpej */ 222 1.25 matt #ifdef IPL_STATCLOCK 223 1.17 briggs iq80310_imask[IPL_HIGH] |= iq80310_imask[IPL_STATCLOCK]; 224 1.25 matt #else 225 1.25 matt iq80310_imask[IPL_HIGH] |= iq80310_imask[IPL_CLOCK]; 226 1.25 matt #endif 227 1.1 thorpej 228 1.1 thorpej /* 229 1.8 thorpej * XXX We need serial drivers to run at the absolute highest priority 230 1.8 thorpej * in order to avoid overruns, so serial > high. 231 1.1 thorpej */ 232 1.17 briggs iq80310_imask[IPL_SERIAL] |= iq80310_imask[IPL_HIGH]; 233 1.1 thorpej 234 1.8 thorpej /* 235 1.8 thorpej * Now compute which IRQs must be blocked when servicing any 236 1.8 thorpej * given IRQ. 237 1.8 thorpej */ 238 1.8 thorpej for (irq = 0; irq < NIRQ; irq++) { 239 1.8 thorpej int irqs = (1U << irq); 240 1.8 thorpej iq = &intrq[irq]; 241 1.8 thorpej if (TAILQ_FIRST(&iq->iq_list) != NULL) 242 1.8 thorpej iq80310_enable_irq(irq); 243 1.8 thorpej for (ih = TAILQ_FIRST(&iq->iq_list); ih != NULL; 244 1.8 thorpej ih = TAILQ_NEXT(ih, ih_list)) 245 1.17 briggs irqs |= iq80310_imask[ih->ih_ipl]; 246 1.8 thorpej iq->iq_mask = irqs; 247 1.8 thorpej } 248 1.8 thorpej } 249 1.8 thorpej 250 1.28 jakllsch #ifdef __HAVE_FAST_SOFTINTS 251 1.17 briggs void 252 1.12 thorpej iq80310_do_soft(void) 253 1.8 thorpej { 254 1.8 thorpej static __cpu_simple_lock_t processing = __SIMPLELOCK_UNLOCKED; 255 1.26 matt struct cpu_info * const ci = curcpu(); 256 1.8 thorpej int new, oldirqstate; 257 1.8 thorpej 258 1.8 thorpej if (__cpu_simple_lock_try(&processing) == 0) 259 1.8 thorpej return; 260 1.8 thorpej 261 1.26 matt new = ci->ci_cpl; 262 1.8 thorpej 263 1.8 thorpej oldirqstate = disable_interrupts(I32_bit); 264 1.8 thorpej 265 1.8 thorpej #define DO_SOFTINT(si) \ 266 1.17 briggs if ((iq80310_ipending & ~new) & SI_TO_IRQBIT(si)) { \ 267 1.17 briggs iq80310_ipending &= ~SI_TO_IRQBIT(si); \ 268 1.26 matt ci->ci_cpl |= iq80310_imask[si_to_ipl[(si)]]; \ 269 1.8 thorpej restore_interrupts(oldirqstate); \ 270 1.8 thorpej softintr_dispatch(si); \ 271 1.8 thorpej oldirqstate = disable_interrupts(I32_bit); \ 272 1.26 matt ci->ci_cpl = new; \ 273 1.8 thorpej } 274 1.8 thorpej 275 1.8 thorpej DO_SOFTINT(SI_SOFTSERIAL); 276 1.8 thorpej DO_SOFTINT(SI_SOFTNET); 277 1.8 thorpej DO_SOFTINT(SI_SOFTCLOCK); 278 1.8 thorpej DO_SOFTINT(SI_SOFT); 279 1.8 thorpej 280 1.8 thorpej __cpu_simple_unlock(&processing); 281 1.8 thorpej 282 1.8 thorpej restore_interrupts(oldirqstate); 283 1.1 thorpej } 284 1.28 jakllsch #endif /* __HAVE_SOFT_FASTINTS */ 285 1.1 thorpej 286 1.8 thorpej int 287 1.8 thorpej _splraise(int ipl) 288 1.1 thorpej { 289 1.8 thorpej 290 1.18 thorpej return (iq80310_splraise(ipl)); 291 1.1 thorpej } 292 1.1 thorpej 293 1.23 perry inline void 294 1.8 thorpej splx(int new) 295 1.8 thorpej { 296 1.8 thorpej 297 1.18 thorpej return (iq80310_splx(new)); 298 1.8 thorpej } 299 1.8 thorpej 300 1.8 thorpej int 301 1.8 thorpej _spllower(int ipl) 302 1.1 thorpej { 303 1.17 briggs 304 1.18 thorpej return (iq80310_spllower(ipl)); 305 1.17 briggs } 306 1.17 briggs 307 1.28 jakllsch #ifdef __HAVE_FAST_SOFTINTS 308 1.1 thorpej void 309 1.8 thorpej _setsoftintr(int si) 310 1.1 thorpej { 311 1.8 thorpej int oldirqstate; 312 1.8 thorpej 313 1.8 thorpej oldirqstate = disable_interrupts(I32_bit); 314 1.17 briggs iq80310_ipending |= SI_TO_IRQBIT(si); 315 1.8 thorpej restore_interrupts(oldirqstate); 316 1.1 thorpej 317 1.8 thorpej /* Process unmasked pending soft interrupts. */ 318 1.26 matt if ((iq80310_ipending & ~IRQ_BITS) & ~curcpl()) 319 1.12 thorpej iq80310_do_soft(); 320 1.1 thorpej } 321 1.25 matt #endif 322 1.1 thorpej 323 1.1 thorpej void 324 1.8 thorpej iq80310_intr_init(void) 325 1.1 thorpej { 326 1.8 thorpej struct intrq *iq; 327 1.8 thorpej int i; 328 1.1 thorpej 329 1.8 thorpej /* 330 1.8 thorpej * The Secondary PCI interrupts INTA, INTB, and INTC 331 1.8 thorpej * area always enabled, since they cannot be masked 332 1.8 thorpej * in the CPLD. 333 1.8 thorpej */ 334 1.8 thorpej intr_enabled |= IRQ_BITS_ALWAYS_ON; 335 1.8 thorpej 336 1.8 thorpej for (i = 0; i < NIRQ; i++) { 337 1.8 thorpej iq = &intrq[i]; 338 1.8 thorpej TAILQ_INIT(&iq->iq_list); 339 1.8 thorpej 340 1.34 christos snprintf(iq->iq_name, sizeof(iq->iq_name), "irq %d", i); 341 1.8 thorpej } 342 1.8 thorpej 343 1.8 thorpej iq80310_intr_calculate_masks(); 344 1.8 thorpej 345 1.8 thorpej /* Enable external interrupts on the i80200. */ 346 1.8 thorpej i80200_extirq_dispatch = iq80310_intr_dispatch; 347 1.15 briggs i80200_intr_enable(INTCTL_IM | INTCTL_PM); 348 1.8 thorpej 349 1.8 thorpej /* Enable IRQs (don't yet use FIQs). */ 350 1.8 thorpej enable_interrupts(I32_bit); 351 1.1 thorpej } 352 1.1 thorpej 353 1.32 chs void 354 1.32 chs iq80310_intr_evcnt_attach(void) 355 1.32 chs { 356 1.32 chs struct intrq *iq; 357 1.32 chs int i; 358 1.32 chs 359 1.32 chs for (i = 0; i < NIRQ; i++) { 360 1.32 chs iq = &intrq[i]; 361 1.32 chs evcnt_attach_dynamic(&iq->iq_ev, EVCNT_TYPE_INTR, 362 1.32 chs NULL, "iq80310", iq->iq_name); 363 1.32 chs } 364 1.32 chs } 365 1.32 chs 366 1.1 thorpej void * 367 1.1 thorpej iq80310_intr_establish(int irq, int ipl, int (*func)(void *), void *arg) 368 1.1 thorpej { 369 1.8 thorpej struct intrq *iq; 370 1.8 thorpej struct intrhand *ih; 371 1.1 thorpej u_int oldirqstate; 372 1.8 thorpej 373 1.8 thorpej if (irq < 0 || irq > NIRQ) 374 1.8 thorpej panic("iq80310_intr_establish: IRQ %d out of range", irq); 375 1.1 thorpej 376 1.36 thorpej ih = kmem_alloc(sizeof(*ih), KM_SLEEP); 377 1.1 thorpej ih->ih_func = func; 378 1.1 thorpej ih->ih_arg = arg; 379 1.8 thorpej ih->ih_ipl = ipl; 380 1.8 thorpej ih->ih_irq = irq; 381 1.1 thorpej 382 1.8 thorpej iq = &intrq[irq]; 383 1.1 thorpej 384 1.8 thorpej /* All IQ80310 interrupts are level-triggered. */ 385 1.8 thorpej iq->iq_ist = IST_LEVEL; 386 1.1 thorpej 387 1.8 thorpej oldirqstate = disable_interrupts(I32_bit); 388 1.1 thorpej 389 1.8 thorpej TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list); 390 1.1 thorpej 391 1.8 thorpej iq80310_intr_calculate_masks(); 392 1.1 thorpej 393 1.1 thorpej restore_interrupts(oldirqstate); 394 1.1 thorpej 395 1.1 thorpej return (ih); 396 1.1 thorpej } 397 1.1 thorpej 398 1.1 thorpej void 399 1.1 thorpej iq80310_intr_disestablish(void *cookie) 400 1.1 thorpej { 401 1.8 thorpej struct intrhand *ih = cookie; 402 1.8 thorpej struct intrq *iq = &intrq[ih->ih_irq]; 403 1.8 thorpej int oldirqstate; 404 1.8 thorpej 405 1.8 thorpej oldirqstate = disable_interrupts(I32_bit); 406 1.8 thorpej 407 1.8 thorpej TAILQ_REMOVE(&iq->iq_list, ih, ih_list); 408 1.8 thorpej 409 1.8 thorpej iq80310_intr_calculate_masks(); 410 1.1 thorpej 411 1.8 thorpej restore_interrupts(oldirqstate); 412 1.8 thorpej } 413 1.8 thorpej 414 1.8 thorpej void 415 1.30 skrll iq80310_intr_dispatch(struct trapframe *frame) 416 1.8 thorpej { 417 1.8 thorpej struct intrq *iq; 418 1.8 thorpej struct intrhand *ih; 419 1.33 martin int oldirqstate, pcpl, irq, ibit, hwpend, rv; 420 1.26 matt struct cpu_info * const ci = curcpu(); 421 1.33 martin #if 0 422 1.33 martin int stray; 423 1.13 thorpej 424 1.13 thorpej stray = 1; 425 1.33 martin #endif 426 1.8 thorpej 427 1.8 thorpej /* First, disable external IRQs. */ 428 1.15 briggs i80200_intr_disable(INTCTL_IM | INTCTL_PM); 429 1.8 thorpej 430 1.26 matt pcpl = ci->ci_cpl; 431 1.8 thorpej 432 1.8 thorpej for (hwpend = iq80310_intstat_read(); hwpend != 0;) { 433 1.8 thorpej irq = ffs(hwpend) - 1; 434 1.8 thorpej ibit = (1U << irq); 435 1.8 thorpej 436 1.33 martin #if 0 437 1.13 thorpej stray = 0; 438 1.33 martin #endif 439 1.13 thorpej 440 1.8 thorpej hwpend &= ~ibit; 441 1.8 thorpej 442 1.8 thorpej if (pcpl & ibit) { 443 1.8 thorpej /* 444 1.8 thorpej * IRQ is masked; mark it as pending and check 445 1.8 thorpej * the next one. Note: external IRQs are already 446 1.8 thorpej * disabled. 447 1.8 thorpej */ 448 1.17 briggs iq80310_ipending |= ibit; 449 1.8 thorpej continue; 450 1.8 thorpej } 451 1.8 thorpej 452 1.17 briggs iq80310_ipending &= ~ibit; 453 1.13 thorpej rv = 0; 454 1.8 thorpej 455 1.8 thorpej iq = &intrq[irq]; 456 1.8 thorpej iq->iq_ev.ev_count++; 457 1.27 matt ci->ci_data.cpu_nintr++; 458 1.26 matt ci->ci_cpl |= iq->iq_mask; 459 1.8 thorpej oldirqstate = enable_interrupts(I32_bit); 460 1.8 thorpej for (ih = TAILQ_FIRST(&iq->iq_list); ih != NULL; 461 1.8 thorpej ih = TAILQ_NEXT(ih, ih_list)) { 462 1.13 thorpej rv |= (*ih->ih_func)(ih->ih_arg ? ih->ih_arg : frame); 463 1.8 thorpej } 464 1.8 thorpej restore_interrupts(oldirqstate); 465 1.8 thorpej 466 1.26 matt ci->ci_cpl = pcpl; 467 1.13 thorpej 468 1.14 thorpej #if 0 /* XXX */ 469 1.13 thorpej if (rv == 0) 470 1.13 thorpej printf("Stray interrupt: IRQ %d\n", irq); 471 1.14 thorpej #endif 472 1.8 thorpej } 473 1.13 thorpej 474 1.14 thorpej #if 0 /* XXX */ 475 1.13 thorpej if (stray) 476 1.13 thorpej printf("Stray external interrupt\n"); 477 1.14 thorpej #endif 478 1.8 thorpej 479 1.26 matt #ifdef __HAVE_FAST_SOFTINTS 480 1.8 thorpej /* Check for pendings soft intrs. */ 481 1.26 matt if ((iq80310_ipending & ~IRQ_BITS) & ~ci->ci_cpl) { 482 1.8 thorpej oldirqstate = enable_interrupts(I32_bit); 483 1.12 thorpej iq80310_do_soft(); 484 1.8 thorpej restore_interrupts(oldirqstate); 485 1.8 thorpej } 486 1.25 matt #endif 487 1.8 thorpej 488 1.8 thorpej /* 489 1.8 thorpej * If no hardware interrupts are masked, re-enable external 490 1.8 thorpej * interrupts. 491 1.8 thorpej */ 492 1.17 briggs if ((iq80310_ipending & IRQ_BITS) == 0) 493 1.15 briggs i80200_intr_enable(INTCTL_IM | INTCTL_PM); 494 1.1 thorpej } 495