1 /* $NetBSD: intr.c,v 1.10 2002/10/19 12:22:33 bsh 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 "opt_irqstats.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/syslog.h> 43 #include <sys/malloc.h> 44 #include <sys/conf.h> 45 46 #include <uvm/uvm_extern.h> 47 48 #include <machine/atomic.h> 49 #include <machine/intr.h> 50 #include <machine/cpu.h> 51 52 #include <net/netisr.h> 53 54 #include <arm/arm32/machdep.h> 55 56 #ifndef NPLCOM 57 #define NPLCOM 0 58 #endif 59 60 /* Prototypes */ 61 static void clearsoftintr __P((u_int)); 62 63 u_int soft_interrupts = 0; 64 65 extern int current_spl_level; 66 67 extern unsigned spl_mask; 68 69 /* Generate soft interrupt counts if IRQSTATS is defined */ 70 #ifdef IRQSTATS 71 extern u_int sintrcnt[]; 72 #define INC_SINTRCNT(x) ++sintrcnt[x] 73 #else 74 #define INC_SINTRCNT(x) 75 #endif /* IRQSTATS */ 76 77 #define COUNT uvmexp.softs; 78 79 /* Prototypes */ 80 81 #include "com.h" 82 #if NCOM > 0 83 extern void comsoft __P((void)); 84 #endif /* NCOM > 0 */ 85 86 #if NPLCOM > 0 87 extern void plcomsoft __P((void)); 88 #endif /* NPLCOM > 0 */ 89 90 /* Eventually these will become macros */ 91 92 void 93 setsoftintr(intrmask) 94 u_int intrmask; 95 { 96 atomic_set_bit(&soft_interrupts, intrmask); 97 } 98 99 static void 100 clearsoftintr(intrmask) 101 u_int intrmask; 102 { 103 atomic_clear_bit(&soft_interrupts, intrmask); 104 } 105 106 void 107 setsoftclock() 108 { 109 atomic_set_bit(&soft_interrupts, SOFTIRQ_BIT(SOFTIRQ_CLOCK)); 110 } 111 112 void 113 setsoftnet() 114 { 115 atomic_set_bit(&soft_interrupts, SOFTIRQ_BIT(SOFTIRQ_NET)); 116 } 117 118 void 119 setsoftserial() 120 { 121 atomic_set_bit(&soft_interrupts, SOFTIRQ_BIT(SOFTIRQ_SERIAL)); 122 } 123 124 /* Handle software interrupts */ 125 126 void 127 dosoftints() 128 { 129 u_int softints; 130 int s; 131 132 softints = soft_interrupts & spl_smasks[current_spl_level]; 133 if (softints == 0) return; 134 135 /* 136 * Software clock interrupts 137 */ 138 139 if (softints & SOFTIRQ_BIT(SOFTIRQ_CLOCK)) { 140 s = splsoftclock(); 141 ++COUNT; 142 INC_SINTRCNT(SOFTIRQ_CLOCK); 143 clearsoftintr(SOFTIRQ_BIT(SOFTIRQ_CLOCK)); 144 softclock(NULL); 145 (void)splx(s); 146 } 147 148 /* 149 * Network software interrupts 150 */ 151 152 if (softints & SOFTIRQ_BIT(SOFTIRQ_NET)) { 153 s = splsoftnet(); 154 ++COUNT; 155 INC_SINTRCNT(SOFTIRQ_NET); 156 clearsoftintr(SOFTIRQ_BIT(SOFTIRQ_NET)); 157 158 #define DONETISR(bit, fn) do { \ 159 if (netisr & (1 << bit)) { \ 160 atomic_clear_bit(&netisr, (1 << bit)); \ 161 fn(); \ 162 } \ 163 } while (0) 164 165 #include <net/netisr_dispatch.h> 166 167 #undef DONETISR 168 169 (void)splx(s); 170 } 171 /* 172 * Serial software interrupts 173 */ 174 175 if (softints & SOFTIRQ_BIT(SOFTIRQ_SERIAL)) { 176 s = splsoftserial(); 177 ++COUNT; 178 INC_SINTRCNT(SOFTIRQ_SERIAL); 179 clearsoftintr(SOFTIRQ_BIT(SOFTIRQ_SERIAL)); 180 #if NCOM > 0 181 comsoft(); 182 #endif /* NCOM > 0 */ 183 #if NPLCOM > 0 184 plcomsoft(); 185 #endif /* NPLCOM > 0 */ 186 (void)splx(s); 187 } 188 } 189 190 int current_spl_level = _SPL_SERIAL; 191 u_int spl_masks[_SPL_LEVELS + 1]; 192 u_int spl_smasks[_SPL_LEVELS]; 193 int safepri = _SPL_0; 194 195 extern u_int irqmasks[]; 196 197 void 198 set_spl_masks() 199 { 200 int loop; 201 202 for (loop = 0; loop < _SPL_LEVELS; ++loop) { 203 spl_masks[loop] = 0xffffffff; 204 spl_smasks[loop] = 0; 205 } 206 207 spl_masks[_SPL_BIO] = irqmasks[IPL_BIO]; 208 spl_masks[_SPL_NET] = irqmasks[IPL_NET]; 209 spl_masks[_SPL_SOFTSERIAL] = irqmasks[IPL_TTY]; 210 spl_masks[_SPL_TTY] = irqmasks[IPL_TTY]; 211 spl_masks[_SPL_IMP] = irqmasks[IPL_IMP]; 212 spl_masks[_SPL_AUDIO] = irqmasks[IPL_AUDIO]; 213 spl_masks[_SPL_CLOCK] = irqmasks[IPL_CLOCK]; 214 #ifdef IPL_STATCLOCK 215 spl_masks[_SPL_STATCLOCK] = irqmasks[IPL_STATCLOCK]; 216 #else 217 spl_masks[_SPL_STATCLOCK] = irqmasks[IPL_CLOCK]; 218 #endif 219 spl_masks[_SPL_HIGH] = irqmasks[IPL_HIGH]; 220 spl_masks[_SPL_SERIAL] = irqmasks[IPL_SERIAL]; 221 spl_masks[_SPL_LEVELS] = 0; 222 223 spl_smasks[_SPL_0] = 0xffffffff; 224 for (loop = 0; loop < _SPL_SOFTSERIAL; ++loop) 225 spl_smasks[loop] |= SOFTIRQ_BIT(SOFTIRQ_SERIAL); 226 for (loop = 0; loop < _SPL_SOFTNET; ++loop) 227 spl_smasks[loop] |= SOFTIRQ_BIT(SOFTIRQ_NET); 228 for (loop = 0; loop < _SPL_SOFTCLOCK; ++loop) 229 spl_smasks[loop] |= SOFTIRQ_BIT(SOFTIRQ_CLOCK); 230 } 231 232 #ifdef DIAGNOSTIC 233 void 234 dump_spl_masks() 235 { 236 int loop; 237 238 for (loop = 0; loop < _SPL_LEVELS; ++loop) { 239 printf("spl_mask[%d]=%08x splsmask[%d]=%08x\n", loop, 240 spl_masks[loop], loop, spl_smasks[loop]); 241 } 242 } 243 #endif 244 245 /* End of intr.c */ 246