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