Annotation of sys/arch/alpha/dev/shared_intr.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: shared_intr.c,v 1.15 2006/06/15 20:08:29 brad Exp $ */
! 2: /* $NetBSD: shared_intr.c,v 1.13 2000/03/19 01:46:18 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1996 Carnegie-Mellon University.
! 6: * All rights reserved.
! 7: *
! 8: * Authors: Chris G. Demetriou
! 9: *
! 10: * Permission to use, copy, modify and distribute this software and
! 11: * its documentation is hereby granted, provided that both the copyright
! 12: * notice and this permission notice appear in all copies of the
! 13: * software, derivative works or modified versions, and any portions
! 14: * thereof, and that both notices appear in supporting documentation.
! 15: *
! 16: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 17: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
! 18: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 19: *
! 20: * Carnegie Mellon requests users of this software to return to
! 21: *
! 22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 23: * School of Computer Science
! 24: * Carnegie Mellon University
! 25: * Pittsburgh PA 15213-3890
! 26: *
! 27: * any improvements or extensions that they make and grant Carnegie the
! 28: * rights to redistribute these changes.
! 29: */
! 30:
! 31: /*
! 32: * Common shared-interrupt-line functionality.
! 33: */
! 34:
! 35: #include <sys/param.h>
! 36: #include <sys/kernel.h>
! 37: #include <sys/systm.h>
! 38: #include <sys/malloc.h>
! 39: #include <sys/syslog.h>
! 40: #include <sys/queue.h>
! 41:
! 42: #include <machine/intr.h>
! 43:
! 44: static const char *intr_typename(int);
! 45:
! 46: static const char *
! 47: intr_typename(type)
! 48: int type;
! 49: {
! 50:
! 51: switch (type) {
! 52: case IST_UNUSABLE:
! 53: return ("disabled");
! 54: case IST_NONE:
! 55: return ("none");
! 56: case IST_PULSE:
! 57: return ("pulsed");
! 58: case IST_EDGE:
! 59: return ("edge-triggered");
! 60: case IST_LEVEL:
! 61: return ("level-triggered");
! 62: }
! 63: panic("intr_typename: unknown type %d", type);
! 64: }
! 65:
! 66: struct alpha_shared_intr *
! 67: alpha_shared_intr_alloc(n)
! 68: unsigned int n;
! 69: {
! 70: struct alpha_shared_intr *intr;
! 71: unsigned int i;
! 72:
! 73: intr = malloc(n * sizeof (struct alpha_shared_intr), M_DEVBUF,
! 74: cold ? M_NOWAIT : M_WAITOK);
! 75: if (intr == NULL)
! 76: panic("alpha_shared_intr_alloc: couldn't malloc intr");
! 77:
! 78: for (i = 0; i < n; i++) {
! 79: TAILQ_INIT(&intr[i].intr_q);
! 80: intr[i].intr_sharetype = IST_NONE;
! 81: intr[i].intr_dfltsharetype = IST_NONE;
! 82: intr[i].intr_nstrays = 0;
! 83: intr[i].intr_maxstrays = 5;
! 84: intr[i].intr_private = NULL;
! 85: }
! 86:
! 87: return (intr);
! 88: }
! 89:
! 90: int
! 91: alpha_shared_intr_dispatch(intr, num)
! 92: struct alpha_shared_intr *intr;
! 93: unsigned int num;
! 94: {
! 95: struct alpha_shared_intrhand *ih;
! 96: int rv, handled;
! 97:
! 98: handled = 0;
! 99: TAILQ_FOREACH(ih, &intr[num].intr_q, ih_q) {
! 100: /*
! 101: * The handler returns one of three values:
! 102: * 0: This interrupt wasn't for me.
! 103: * 1: This interrupt was for me.
! 104: * -1: This interrupt might have been for me, but I can't say
! 105: * for sure.
! 106: */
! 107: if ((rv = (*ih->ih_fn)(ih->ih_arg)))
! 108: ih->ih_count.ec_count++;
! 109:
! 110: handled = handled || (rv != 0);
! 111: }
! 112:
! 113: return (handled);
! 114: }
! 115:
! 116: void *
! 117: alpha_shared_intr_establish(intr, num, type, level, fn, arg, basename)
! 118: struct alpha_shared_intr *intr;
! 119: unsigned int num;
! 120: int type, level;
! 121: int (*fn)(void *);
! 122: void *arg;
! 123: const char *basename;
! 124: {
! 125: struct alpha_shared_intrhand *ih;
! 126:
! 127: if (intr[num].intr_sharetype == IST_UNUSABLE) {
! 128: printf("alpha_shared_intr_establish: %s %d: unusable\n",
! 129: basename, num);
! 130: return NULL;
! 131: }
! 132:
! 133: /* no point in sleeping unless someone can free memory. */
! 134: ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
! 135: if (ih == NULL)
! 136: panic("alpha_shared_intr_establish: can't malloc intrhand");
! 137:
! 138: #ifdef DIAGNOSTIC
! 139: if (type == IST_NONE)
! 140: panic("alpha_shared_intr_establish: bogus type");
! 141: #endif
! 142:
! 143: switch (intr[num].intr_sharetype) {
! 144: case IST_EDGE:
! 145: case IST_LEVEL:
! 146: if (type == intr[num].intr_sharetype)
! 147: break;
! 148: case IST_PULSE:
! 149: if (type != IST_NONE) {
! 150: if (TAILQ_EMPTY(&intr[num].intr_q)) {
! 151: printf("alpha_shared_intr_establish: %s %d: warning: using %s on %s\n",
! 152: basename, num, intr_typename(type),
! 153: intr_typename(intr[num].intr_sharetype));
! 154: type = intr[num].intr_sharetype;
! 155: } else {
! 156: panic("alpha_shared_intr_establish: %s %d: can't share %s with %s",
! 157: basename, num, intr_typename(type),
! 158: intr_typename(intr[num].intr_sharetype));
! 159: }
! 160: }
! 161: break;
! 162:
! 163: case IST_NONE:
! 164: /* not currently used; safe */
! 165: break;
! 166: }
! 167:
! 168: ih->ih_intrhead = intr;
! 169: ih->ih_fn = fn;
! 170: ih->ih_arg = arg;
! 171: ih->ih_level = level;
! 172: ih->ih_num = num;
! 173: evcount_attach(&ih->ih_count, basename, (void *)&ih->ih_num,
! 174: &evcount_intr);
! 175:
! 176: intr[num].intr_sharetype = type;
! 177: TAILQ_INSERT_TAIL(&intr[num].intr_q, ih, ih_q);
! 178:
! 179: return (ih);
! 180: }
! 181:
! 182: void
! 183: alpha_shared_intr_disestablish(intr, cookie, basename)
! 184: struct alpha_shared_intr *intr;
! 185: void *cookie;
! 186: const char *basename;
! 187: {
! 188: struct alpha_shared_intrhand *ih = cookie;
! 189: unsigned int num = ih->ih_num;
! 190:
! 191: /*
! 192: * Just remove it from the list and free the entry. We let
! 193: * the caller deal with resetting the share type, if appropriate.
! 194: */
! 195: evcount_detach(&ih->ih_count);
! 196: TAILQ_REMOVE(&intr[num].intr_q, ih, ih_q);
! 197: free(ih, M_DEVBUF);
! 198: }
! 199:
! 200: int
! 201: alpha_shared_intr_get_sharetype(intr, num)
! 202: struct alpha_shared_intr *intr;
! 203: unsigned int num;
! 204: {
! 205:
! 206: return (intr[num].intr_sharetype);
! 207: }
! 208:
! 209: int
! 210: alpha_shared_intr_isactive(intr, num)
! 211: struct alpha_shared_intr *intr;
! 212: unsigned int num;
! 213: {
! 214:
! 215: return (!TAILQ_EMPTY(&intr[num].intr_q));
! 216: }
! 217:
! 218: int
! 219: alpha_shared_intr_firstactive(struct alpha_shared_intr *intr, unsigned int num)
! 220: {
! 221:
! 222: return (!TAILQ_EMPTY(&intr[num].intr_q) &&
! 223: TAILQ_NEXT(intr[num].intr_q.tqh_first, ih_q) == NULL);
! 224: }
! 225:
! 226: void
! 227: alpha_shared_intr_set_dfltsharetype(intr, num, newdfltsharetype)
! 228: struct alpha_shared_intr *intr;
! 229: unsigned int num;
! 230: int newdfltsharetype;
! 231: {
! 232:
! 233: #ifdef DIAGNOSTIC
! 234: if (alpha_shared_intr_isactive(intr, num))
! 235: panic("alpha_shared_intr_set_dfltsharetype on active intr");
! 236: #endif
! 237:
! 238: intr[num].intr_dfltsharetype = newdfltsharetype;
! 239: intr[num].intr_sharetype = intr[num].intr_dfltsharetype;
! 240: }
! 241:
! 242: void
! 243: alpha_shared_intr_set_maxstrays(intr, num, newmaxstrays)
! 244: struct alpha_shared_intr *intr;
! 245: unsigned int num;
! 246: int newmaxstrays;
! 247: {
! 248: int s = splhigh();
! 249: intr[num].intr_maxstrays = newmaxstrays;
! 250: intr[num].intr_nstrays = 0;
! 251: splx(s);
! 252: }
! 253:
! 254: void
! 255: alpha_shared_intr_reset_strays(intr, num)
! 256: struct alpha_shared_intr *intr;
! 257: unsigned int num;
! 258: {
! 259:
! 260: /*
! 261: * Don't bother blocking interrupts; this doesn't have to be
! 262: * precise, but it does need to be fast.
! 263: */
! 264: intr[num].intr_nstrays = 0;
! 265: }
! 266:
! 267: void
! 268: alpha_shared_intr_stray(intr, num, basename)
! 269: struct alpha_shared_intr *intr;
! 270: unsigned int num;
! 271: const char *basename;
! 272: {
! 273:
! 274: intr[num].intr_nstrays++;
! 275:
! 276: if (intr[num].intr_maxstrays == 0)
! 277: return;
! 278:
! 279: if (intr[num].intr_nstrays <= intr[num].intr_maxstrays)
! 280: log(LOG_ERR, "stray %s %d%s\n", basename, num,
! 281: intr[num].intr_nstrays >= intr[num].intr_maxstrays ?
! 282: "; stopped logging" : "");
! 283: }
! 284:
! 285: void
! 286: alpha_shared_intr_set_private(intr, num, v)
! 287: struct alpha_shared_intr *intr;
! 288: unsigned int num;
! 289: void *v;
! 290: {
! 291:
! 292: intr[num].intr_private = v;
! 293: }
! 294:
! 295: void *
! 296: alpha_shared_intr_get_private(intr, num)
! 297: struct alpha_shared_intr *intr;
! 298: unsigned int num;
! 299: {
! 300:
! 301: return (intr[num].intr_private);
! 302: }
CVSweb