1 /* $NetBSD: isr.c,v 1.6 2002/09/27 15:36:12 provos Exp $ */ 2 /* $NetBSD: isr.c,v 1.6 2002/09/27 15:36:12 provos Exp $ */ 3 4 /*- 5 * Copyright (c) 1996 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 41 42 __KERNEL_RCSID(0, "$NetBSD: isr.c,v 1.6 2002/09/27 15:36:12 provos Exp $"); 43 44 /* 45 * Link and dispatch interrupts. 46 */ 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/malloc.h> 51 #include <sys/vmmeter.h> 52 53 #include <uvm/uvm_extern.h> 54 55 #include <net/netisr.h> 56 57 #include <machine/cpu.h> 58 59 #include <luna68k/luna68k/isr.h> 60 61 isr_autovec_list_t isr_autovec[NISRAUTOVEC]; 62 struct isr_vectored isr_vectored[NISRVECTORED]; 63 64 extern int intrcnt[]; /* from locore.s */ 65 extern void (*vectab[]) __P((void)); 66 extern void badtrap __P((void)); 67 extern void intrhand_vectored __P((void)); 68 69 extern int getsr __P((void)); /* in locore.s */ 70 71 void 72 isrinit() 73 { 74 int i; 75 76 /* Initialize the autovector lists. */ 77 for (i = 0; i < NISRAUTOVEC; ++i) { 78 LIST_INIT(&isr_autovec[i]); 79 } 80 } 81 82 /* 83 * Establish an autovectored interrupt handler. 84 * Called by driver attach functions. 85 */ 86 void 87 isrlink_autovec(func, arg, ipl, priority) 88 int (*func) __P((void *)); 89 void *arg; 90 int ipl; 91 int priority; 92 { 93 struct isr_autovec *newisr, *curisr; 94 isr_autovec_list_t *list; 95 96 if ((ipl < 0) || (ipl >= NISRAUTOVEC)) 97 panic("isrlink_autovec: bad ipl %d", ipl); 98 99 newisr = (struct isr_autovec *)malloc(sizeof(struct isr_autovec), 100 M_DEVBUF, M_NOWAIT); 101 if (newisr == NULL) 102 panic("isrlink_autovec: can't allocate space for isr"); 103 104 /* Fill in the new entry. */ 105 newisr->isr_func = func; 106 newisr->isr_arg = arg; 107 newisr->isr_ipl = ipl; 108 newisr->isr_priority = priority; 109 110 /* 111 * Some devices are particularly sensitive to interrupt 112 * handling latency. The SCC, for example, can lose many 113 * characters if its interrupt isn't handled with reasonable 114 * speed. 115 * 116 * To work around this problem, each device can give itself a 117 * "priority". An unbuffered SCC would give itself a higher 118 * priority than a SCSI device, for example. 119 * 120 * This solution was originally developed for the hp300, which 121 * has a flat spl scheme (by necessity). Thankfully, the 122 * MVME systems don't have this problem, though this may serve 123 * a useful purpose in any case. 124 */ 125 126 /* 127 * Get the appropriate ISR list. If the list is empty, no 128 * additional work is necessary; we simply insert ourselves 129 * at the head of the list. 130 */ 131 list = &isr_autovec[ipl]; 132 if (list->lh_first == NULL) { 133 LIST_INSERT_HEAD(list, newisr, isr_link); 134 return; 135 } 136 137 /* 138 * A little extra work is required. We traverse the list 139 * and place ourselves after any ISRs with our current (or 140 * higher) priority. 141 */ 142 for (curisr = list->lh_first; curisr->isr_link.le_next != NULL; 143 curisr = curisr->isr_link.le_next) { 144 if (newisr->isr_priority > curisr->isr_priority) { 145 LIST_INSERT_BEFORE(curisr, newisr, isr_link); 146 return; 147 } 148 } 149 150 /* 151 * We're the least important entry, it seems. We just go 152 * on the end. 153 */ 154 LIST_INSERT_AFTER(curisr, newisr, isr_link); 155 } 156 157 /* 158 * Establish a vectored interrupt handler. 159 * Called by bus interrupt establish functions. 160 */ 161 void 162 isrlink_vectored(func, arg, ipl, vec) 163 int (*func) __P((void *)); 164 void *arg; 165 int ipl, vec; 166 { 167 struct isr_vectored *isr; 168 169 if ((ipl < 0) || (ipl >= NISRAUTOVEC)) 170 panic("isrlink_vectored: bad ipl %d", ipl); 171 if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) 172 panic("isrlink_vectored: bad vec 0x%x", vec); 173 174 isr = &isr_vectored[vec - ISRVECTORED]; 175 176 if ((vectab[vec] != badtrap) || (isr->isr_func != NULL)) 177 panic("isrlink_vectored: vec 0x%x not available", vec); 178 179 /* Fill in the new entry. */ 180 isr->isr_func = func; 181 isr->isr_arg = arg; 182 isr->isr_ipl = ipl; 183 184 /* Hook into the vector table. */ 185 vectab[vec] = intrhand_vectored; 186 } 187 188 /* 189 * Unhook a vectored interrupt. 190 */ 191 void 192 isrunlink_vectored(vec) 193 int vec; 194 { 195 196 if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) 197 panic("isrunlink_vectored: bad vec 0x%x", vec); 198 199 if (vectab[vec] != intrhand_vectored) 200 panic("isrunlink_vectored: not vectored interrupt"); 201 202 vectab[vec] = badtrap; 203 bzero(&isr_vectored[vec - ISRVECTORED], sizeof(struct isr_vectored)); 204 } 205 206 /* 207 * This is the dispatcher called by the low-level 208 * assembly language autovectored interrupt routine. 209 */ 210 void 211 isrdispatch_autovec(evec) 212 int evec; /* format | vector offset */ 213 { 214 struct isr_autovec *isr; 215 isr_autovec_list_t *list; 216 int handled = 0, ipl, vec; 217 static int straycount, unexpected; 218 219 vec = (evec & 0xfff) >> 2; 220 if ((vec < ISRAUTOVEC) || (vec >= (ISRAUTOVEC + NISRAUTOVEC))) 221 panic("isrdispatch_autovec: bad vec 0x%x", vec); 222 ipl = vec - ISRAUTOVEC; 223 224 intrcnt[ipl]++; 225 uvmexp.intrs++; 226 227 list = &isr_autovec[ipl]; 228 if (list->lh_first == NULL) { 229 printf("isrdispatch_autovec: ipl %d unexpected\n", ipl); 230 if (++unexpected > 10) 231 panic("too many unexpected interrupts"); 232 return; 233 } 234 235 /* Give all the handlers a chance. */ 236 for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next) 237 handled |= (*isr->isr_func)(isr->isr_arg); 238 239 if (handled) 240 straycount = 0; 241 else if (++straycount > 50) 242 panic("isr_dispatch_autovec: too many stray interrupts"); 243 else 244 printf("isrdispatch_autovec: stray level %d interrupt\n", ipl); 245 } 246 247 /* 248 * This is the dispatcher called by the low-level 249 * assembly language vectored interrupt routine. 250 */ 251 void 252 isrdispatch_vectored(pc, evec, frame) 253 int pc, evec; 254 void *frame; 255 { 256 struct isr_vectored *isr; 257 int ipl, vec; 258 259 vec = (evec & 0xfff) >> 2; 260 ipl = (getsr() >> 8) & 7; 261 262 intrcnt[ipl]++; 263 uvmexp.intrs++; 264 265 if ((vec < ISRVECTORED) || (vec >= (ISRVECTORED + NISRVECTORED))) 266 panic("isrdispatch_vectored: bad vec 0x%x", vec); 267 isr = &isr_vectored[vec - ISRVECTORED]; 268 269 if (isr->isr_func == NULL) { 270 printf("isrdispatch_vectored: no handler for vec 0x%x\n", vec); 271 vectab[vec] = badtrap; 272 return; 273 } 274 275 /* 276 * Handler gets exception frame if argument is NULL. 277 */ 278 if ((*isr->isr_func)(isr->isr_arg ? isr->isr_arg : frame) == 0) 279 printf("isrdispatch_vectored: vec 0x%x not claimed\n", vec); 280 } 281 282 void netintr __P((void)); 283 284 void 285 netintr() 286 { 287 #define DONETISR(bit, fn) do { \ 288 if (netisr & (1 << bit)) { \ 289 netisr &= ~(1 << bit); \ 290 fn(); \ 291 } \ 292 } while (0) 293 294 #include <net/netisr_dispatch.h> 295 296 #undef DONETISR 297 298 } 299