1 /* $NetBSD: intr.c,v 1.27 2008/02/24 20:51:52 matt 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.27 2008/02/24 20:51:52 matt Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/syslog.h> 44 #include <sys/malloc.h> 45 #include <sys/conf.h> 46 47 #include <uvm/uvm_extern.h> 48 49 #include <machine/atomic.h> 50 #include <machine/intr.h> 51 #include <machine/cpu.h> 52 53 #include <net/netisr.h> 54 55 #include <arm/arm32/machdep.h> 56 57 extern int current_spl_level; 58 59 static u_int spl_smasks[_SPL_LEVELS]; 60 61 /* Eventually these will become macros */ 62 63 #ifdef __HAVE_FAST_SOFTINTS 64 /* Generate soft interrupt counts if IRQSTATS is defined */ 65 /* Prototypes */ 66 static void clearsoftintr(u_int); 67 68 static u_int soft_interrupts = 0; 69 #define SI_SOFTMASK(si) (1U << (si)) 70 71 static inline void 72 clearsoftintr(u_int intrmask) 73 { 74 atomic_clear_bit(&soft_interrupts, intrmask); 75 } 76 77 void 78 _setsoftintr(int si) 79 { 80 atomic_set_bit(&soft_interrupts, SI_SOFTMASK(si)); 81 } 82 83 /* Handle software interrupts */ 84 85 void 86 dosoftints(void) 87 { 88 u_int softints; 89 int s; 90 91 softints = soft_interrupts & spl_smasks[current_spl_level]; 92 if (softints == 0) return; 93 94 /* 95 * Serial software interrupts 96 */ 97 if (softints & SI_SOFTMASK(SI_SOFTSERIAL)) { 98 s = splsoftserial(); 99 clearsoftintr(SI_SOFTMASK(SI_SOFTSERIAL)); 100 softintr_dispatch(SI_SOFTSERIAL); 101 (void)splx(s); 102 } 103 104 /* 105 * Network software interrupts 106 */ 107 if (softints & SI_SOFTMASK(SI_SOFTNET)) { 108 s = splsoftnet(); 109 clearsoftintr(SI_SOFTMASK(SI_SOFTNET)); 110 softintr_dispatch(SI_SOFTNET); 111 (void)splx(s); 112 } 113 114 /* 115 * Block software interrupts 116 */ 117 if (softints & SI_SOFTMASK(SI_SOFTBIO)) { 118 s = splsoftbio(); 119 clearsoftintr(SI_SOFTMASK(SI_SOFTBIO)); 120 softintr_dispatch(SI_SOFTBIO); 121 (void)splx(s); 122 } 123 124 /* 125 * Software clock interrupts 126 */ 127 if (softints & SI_SOFTMASK(SI_SOFTCLOCK)) { 128 s = splsoftclock(); 129 clearsoftintr(SI_SOFTMASK(SI_SOFTCLOCK)); 130 softintr_dispatch(SI_SOFTCLOCK); 131 (void)splx(s); 132 } 133 } 134 #endif 135 136 int current_spl_level = _SPL_HIGH; 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_VM] = irqmasks[IPL_VM]; 153 spl_masks[_SPL_SCHED] = irqmasks[IPL_SCHED]; 154 spl_masks[_SPL_HIGH] = irqmasks[IPL_HIGH]; 155 spl_masks[_SPL_LEVELS] = 0; 156 157 spl_smasks[_SPL_0] = 0xffffffff; 158 #ifdef __HAVE_FAST_SOFTINTS 159 for (loop = 0; loop < _SPL_SOFTSERIAL; ++loop) 160 spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTSERIAL); 161 for (loop = 0; loop < _SPL_SOFTNET; ++loop) 162 spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTNET); 163 for (loop = 0; loop < _SPL_SOFTCLOCK; ++loop) 164 spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTCLOCK); 165 for (loop = 0; loop < _SPL_SOFTBIO; ++loop) 166 spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTBIO); 167 #endif 168 } 169 170 static const int ipl_to_spl_map[] = { 171 [IPL_NONE] = 1 + _SPL_0, 172 [IPL_SOFTCLOCK] = 1 + _SPL_SOFTCLOCK, 173 [IPL_SOFTBIO] = 1 + _SPL_SOFTBIO, 174 [IPL_SOFTNET] = 1 + _SPL_SOFTNET, 175 [IPL_SOFTSERIAL] = 1 + _SPL_SOFTSERIAL, 176 [IPL_VM] = 1 + _SPL_VM, 177 [IPL_SCHED] = 1 + _SPL_SCHED, 178 [IPL_HIGH] = 1 + _SPL_HIGH, 179 }; 180 181 int 182 ipl_to_spl(ipl_t ipl) 183 { 184 int spl; 185 186 KASSERT(ipl < __arraycount(ipl_to_spl_map)); 187 KASSERT(ipl_to_spl_map[ipl]); 188 189 spl = ipl_to_spl_map[ipl] - 1; 190 KASSERT(spl < 0x100); 191 192 return spl; 193 } 194 195 #ifdef DIAGNOSTIC 196 void 197 dump_spl_masks(void) 198 { 199 int loop; 200 201 for (loop = 0; loop < _SPL_LEVELS; ++loop) { 202 printf("spl_masks[%d]=%08x splsmask[%d]=%08x\n", loop, 203 spl_masks[loop], loop, spl_smasks[loop]); 204 } 205 } 206 #endif 207 208 /* End of intr.c */ 209