1 /* $NetBSD: shared_intr.c,v 1.3 1997/04/07 23:40:11 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Authors: Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 /* 31 * Common shared-interrupt-line functionality. 32 */ 33 34 #include <machine/options.h> /* Config options headers */ 35 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 36 37 __KERNEL_RCSID(0, "$NetBSD: shared_intr.c,v 1.3 1997/04/07 23:40:11 cgd Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/malloc.h> 42 #include <sys/syslog.h> 43 #include <sys/queue.h> 44 45 #include <machine/intr.h> 46 47 extern int cold; 48 49 static const char *intr_typename __P((int)); 50 51 static const char * 52 intr_typename(type) 53 int type; 54 { 55 56 switch (type) { 57 case IST_UNUSABLE: 58 return ("disabled"); 59 case IST_NONE: 60 return ("none"); 61 case IST_PULSE: 62 return ("pulsed"); 63 case IST_EDGE: 64 return ("edge-triggered"); 65 case IST_LEVEL: 66 return ("level-triggered"); 67 } 68 panic("intr_typename: unknown type %d", type); 69 } 70 71 struct alpha_shared_intr * 72 alpha_shared_intr_alloc(n) 73 unsigned int n; 74 { 75 struct alpha_shared_intr *intr; 76 unsigned int i; 77 78 intr = malloc(n * sizeof (struct alpha_shared_intr), M_DEVBUF, 79 cold ? M_NOWAIT : M_WAITOK); 80 if (intr == NULL) 81 panic("alpha_shared_intr_alloc: couldn't malloc intr"); 82 83 for (i = 0; i < n; i++) { 84 TAILQ_INIT(&intr[i].intr_q); 85 intr[i].intr_sharetype = IST_NONE; 86 intr[i].intr_dfltsharetype = IST_NONE; 87 intr[i].intr_nstrays = 0; 88 intr[i].intr_maxstrays = 5; 89 } 90 91 return (intr); 92 } 93 94 int 95 alpha_shared_intr_dispatch(intr, num) 96 struct alpha_shared_intr *intr; 97 unsigned int num; 98 { 99 struct alpha_shared_intrhand *ih; 100 int rv, handled; 101 102 ih = intr[num].intr_q.tqh_first; 103 handled = 0; 104 while (ih != NULL) { 105 106 /* 107 * The handler returns one of three values: 108 * 0: This interrupt wasn't for me. 109 * 1: This interrupt was for me. 110 * -1: This interrupt might have been for me, but I can't say 111 * for sure. 112 */ 113 rv = (*ih->ih_fn)(ih->ih_arg); 114 115 handled = handled || (rv != 0); 116 ih = ih->ih_q.tqe_next; 117 } 118 119 return (handled); 120 } 121 122 void * 123 alpha_shared_intr_establish(intr, num, type, level, fn, arg, basename) 124 struct alpha_shared_intr *intr; 125 unsigned int num; 126 int type, level; 127 int (*fn) __P((void *)); 128 void *arg; 129 const char *basename; 130 { 131 struct alpha_shared_intrhand *ih; 132 133 if (intr[num].intr_sharetype == IST_UNUSABLE) { 134 printf("alpha_shared_intr_establish: %s %d: unusable\n", 135 basename, num); 136 return NULL; 137 } 138 139 /* no point in sleeping unless someone can free memory. */ 140 ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); 141 if (ih == NULL) 142 panic("alpha_shared_intr_establish: can't malloc intrhand"); 143 144 #ifdef DIAGNOSTIC 145 if (type == IST_NONE) 146 panic("alpha_shared_intr_establish: bogus type"); 147 #endif 148 149 switch (intr[num].intr_sharetype) { 150 case IST_EDGE: 151 case IST_LEVEL: 152 if (type == intr[num].intr_sharetype) 153 break; 154 case IST_PULSE: 155 if (type != IST_NONE) { 156 if (intr[num].intr_q.tqh_first == NULL) { 157 printf("alpha_shared_intr_establish: %s %d: warning: using %s on %s\n", 158 basename, num, intr_typename(type), 159 intr_typename(intr[num].intr_sharetype)); 160 type = intr[num].intr_sharetype; 161 } else { 162 panic("alpha_shared_intr_establish: %s %d: can't share %s with %s", 163 basename, num, intr_typename(type), 164 intr_typename(intr[num].intr_sharetype)); 165 } 166 } 167 break; 168 169 case IST_NONE: 170 /* not currently used; safe */ 171 break; 172 } 173 174 ih->ih_fn = fn; 175 ih->ih_arg = arg; 176 ih->ih_level = level; 177 178 intr[num].intr_sharetype = type; 179 TAILQ_INSERT_TAIL(&intr[num].intr_q, ih, ih_q); 180 181 return (ih); 182 } 183 184 int 185 alpha_shared_intr_get_sharetype(intr, num) 186 struct alpha_shared_intr *intr; 187 unsigned int num; 188 { 189 190 return (intr[num].intr_sharetype); 191 } 192 193 int 194 alpha_shared_intr_isactive(intr, num) 195 struct alpha_shared_intr *intr; 196 unsigned int num; 197 { 198 199 return (intr[num].intr_q.tqh_first != NULL); 200 } 201 202 void 203 alpha_shared_intr_set_dfltsharetype(intr, num, newdfltsharetype) 204 struct alpha_shared_intr *intr; 205 unsigned int num; 206 int newdfltsharetype; 207 { 208 209 #ifdef DIAGNOSTIC 210 if (alpha_shared_intr_isactive(intr, num)) 211 panic("alpha_shared_intr_set_dfltsharetype on active intr"); 212 #endif 213 214 intr[num].intr_dfltsharetype = newdfltsharetype; 215 intr[num].intr_sharetype = intr[num].intr_dfltsharetype; 216 } 217 218 void 219 alpha_shared_intr_set_maxstrays(intr, num, newmaxstrays) 220 struct alpha_shared_intr *intr; 221 unsigned int num; 222 int newmaxstrays; 223 { 224 225 #ifdef DIAGNOSTIC 226 if (alpha_shared_intr_isactive(intr, num)) 227 panic("alpha_shared_intr_set_maxstrays on active intr"); 228 #endif 229 230 intr[num].intr_maxstrays = newmaxstrays; 231 intr[num].intr_nstrays = 0; 232 } 233 234 void 235 alpha_shared_intr_stray(intr, num, basename) 236 struct alpha_shared_intr *intr; 237 unsigned int num; 238 const char *basename; 239 { 240 241 intr[num].intr_nstrays++; 242 if (intr[num].intr_nstrays <= intr[num].intr_maxstrays) 243 log(LOG_ERR, "stray %s %d%s\n", basename, num, 244 intr[num].intr_nstrays >= intr[num].intr_maxstrays ? 245 "; stopped logging" : ""); 246 } 247