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