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